@keyfunc/keybricks-ds 2.4.8 → 2.4.11
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/DEPLOY.md +10 -7
- package/INTEGRATION.md +17 -1
- package/assets/fonts/inter/InterVariable-Italic.woff2 +0 -0
- package/assets/fonts/inter/InterVariable.woff2 +0 -0
- package/assets/fonts/inter/LICENSE.txt +92 -0
- package/assets/fonts/inter/README.md +13 -0
- package/changelog.js +95 -0
- package/components/_cards/smart-table.card.html +3 -1
- package/components/_shared/src-data.js +1 -1
- package/components/data/SmartTable.d.ts +5 -0
- package/components/data/SmartTable.jsx +5 -2
- package/components/data/SmartTable.vue +4 -4
- package/covers.js +104 -0
- package/gallery.html +133 -0
- package/guidelines/_color-lab.js +46 -0
- package/guidelines/brand-logo.html +9 -0
- package/guidelines/colors-list.html +86 -0
- package/guidelines/colors-palette.html +85 -0
- package/guidelines/colors-schemes.html +68 -0
- package/guidelines/colors-transparency.html +59 -0
- package/guidelines/foundations-borders.html +10 -0
- package/guidelines/foundations-chrome.html +17 -0
- package/guidelines/foundations-motion.html +17 -0
- package/guidelines/foundations-radii.html +14 -0
- package/guidelines/foundations-size-tiers.html +88 -0
- package/guidelines/foundations-spacing.html +19 -0
- package/guidelines/interaction-states.html +25 -0
- package/guidelines/type-extended.html +11 -0
- package/guidelines/type-mono.html +10 -0
- package/guidelines/type-scale.html +15 -0
- package/guidelines/type-weights.html +12 -0
- package/index.html +597 -0
- package/package.json +8 -2
- package/readme.md +1 -1
- package/readme.zh-CN.md +1 -1
- package/site-nav.js +1 -0
- package/tokens/fonts.css +19 -4
- package/tokens/hover.css +2 -0
package/index.html
ADDED
|
@@ -0,0 +1,597 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en" data-theme="light" data-lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>Keybricks Design System</title>
|
|
7
|
+
<script>(function(){var d=window.matchMedia&&window.matchMedia('(prefers-color-scheme: dark)').matches;var t=d?'dark':'light';document.documentElement.setAttribute('data-theme',t);document.documentElement.style.colorScheme=t;})();</script>
|
|
8
|
+
<link rel="stylesheet" href="styles.css"><link rel="stylesheet" href="tokens/hover.css">
|
|
9
|
+
<style>
|
|
10
|
+
*{box-sizing:border-box}
|
|
11
|
+
html{scroll-behavior:smooth}
|
|
12
|
+
html,body{margin:0;height:100%}
|
|
13
|
+
body{background:var(--bg-app);color:var(--text-body);font-family:var(--font-sans);font-size:var(--text-base);letter-spacing:var(--tracking-base)}
|
|
14
|
+
a{color:var(--link)}a:hover{color:var(--link-hover)}
|
|
15
|
+
.shell{display:flex;min-height:100vh}
|
|
16
|
+
|
|
17
|
+
/* sidebar */
|
|
18
|
+
.sidebar{width:264px;flex-shrink:0;position:sticky;top:0;height:100vh;overflow-y:auto;border-right:1px solid var(--border-card);background:var(--bg-surface);padding:16px 12px 48px}
|
|
19
|
+
.brand{display:flex;align-items:center;gap:9px;padding:4px 8px 2px}
|
|
20
|
+
.brand img{width:22px;height:22px;display:block;flex-shrink:0}
|
|
21
|
+
.brand b{font-size:var(--text-md);line-height:var(--leading-md);letter-spacing:var(--tracking-md);font-weight:var(--weight-semibold);color:var(--text-heading)}
|
|
22
|
+
.brand-sub{font-size:var(--text-xs);color:var(--text-muted);padding:2px 8px 14px;letter-spacing:var(--tracking-xs)}
|
|
23
|
+
.nav-search{position:relative;margin:0 4px 10px}
|
|
24
|
+
.nav-search input{width:100%;height:var(--control-h);box-sizing:border-box;border:1px solid var(--border-control);border-radius:var(--radius-md);background:var(--bg-inset);color:var(--text-heading);font-family:var(--font-sans);font-size:var(--control-text);line-height:var(--control-leading);padding:0 10px 0 30px;letter-spacing:var(--control-tracking)}
|
|
25
|
+
.nav-search input:focus{outline:none;border-color:var(--focus-border);box-shadow:0 0 0 2px var(--focus-ring);background:var(--bg-surface)}
|
|
26
|
+
.nav-search svg{position:absolute;left:9px;top:50%;transform:translateY(-50%);color:var(--text-muted);pointer-events:none}
|
|
27
|
+
.nav-label{padding:14px 8px 4px;font-size:var(--text-xs);line-height:var(--leading-xs);font-weight:var(--weight-semibold);color:var(--text-secondary);letter-spacing:var(--tracking-xs)}
|
|
28
|
+
.nav-item{display:flex;flex-direction:column;justify-content:center;gap:1px;min-height:var(--h-subnav-item);box-sizing:border-box;padding:6px 10px;border-radius:var(--radius-md);cursor:pointer;color:var(--text-body);font-size:var(--text-base);line-height:18px;letter-spacing:var(--tracking-base);font-weight:var(--weight-medium);transition:var(--t-hover);text-decoration:none}.nav-item+.nav-item{margin-top:2px}.nav-item,.nav-item>*{min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.nav-item>*{display:block}
|
|
29
|
+
.nav-item:hover{background:var(--bg-hover);color:var(--text-body)}
|
|
30
|
+
.nav-item.active{background:var(--bg-active);color:var(--text-heading)}
|
|
31
|
+
.nav-count{font-family:var(--font-sans);font-variant-numeric:tabular-nums;font-size:var(--text-2xs);color:var(--text-muted);font-weight:var(--weight-regular);letter-spacing:0}
|
|
32
|
+
|
|
33
|
+
/* topbar */
|
|
34
|
+
.main{flex:1;min-width:0}
|
|
35
|
+
.topbar{position:sticky;top:0;z-index:20;height:var(--topbar-h);box-sizing:border-box;display:flex;align-items:center;justify-content:space-between;gap:12px;padding:0 28px;border-bottom:1px solid var(--border-card);background:color-mix(in srgb,var(--bg-app) 88%,transparent);backdrop-filter:blur(8px)}
|
|
36
|
+
.doclinks{display:flex;align-items:center;gap:4px;min-width:0;overflow-x:auto;scrollbar-width:none}
|
|
37
|
+
.doclinks::-webkit-scrollbar{display:none}
|
|
38
|
+
.doclink{display:inline-flex;align-items:center;gap:6px;height:28px;box-sizing:border-box;padding:0 8px;border-radius:var(--radius-md);color:var(--text-secondary);font-size:var(--text-xs);line-height:var(--leading-xs);text-decoration:none;white-space:nowrap;flex-shrink:0;transition:var(--t-hover);letter-spacing:var(--tracking-xs)}
|
|
39
|
+
.doclink:hover{background:var(--bg-hover);color:var(--text-heading)}
|
|
40
|
+
.doclink svg{flex-shrink:0;opacity:.8}
|
|
41
|
+
.topbar-right{display:flex;align-items:center;gap:10px;flex-shrink:0}
|
|
42
|
+
.lang-switch{display:flex;align-items:center;height:28px;box-sizing:border-box;gap:2px;padding:2px;border-radius:var(--radius-md);background:var(--bg-inset);border:1px solid var(--border-control)}
|
|
43
|
+
.lang-btn{display:inline-flex;align-items:center;height:22px;padding:0 6px;font-size:var(--text-xs);line-height:var(--leading-xs);border-radius:var(--radius-sm);border:none;background:transparent;color:var(--text-secondary);cursor:pointer;font-family:var(--font-sans);font-weight:var(--weight-medium);white-space:nowrap;transition:var(--t-hover);letter-spacing:var(--tracking-xs)}
|
|
44
|
+
.lang-btn.active{background:var(--bg-surface);color:var(--text-heading);box-shadow:0 1px 2px rgba(0,0,0,.08)}
|
|
45
|
+
.lang-btn:not(.active):hover{color:var(--text-heading)}
|
|
46
|
+
.tbtn{display:inline-flex;align-items:center;gap:6px;height:28px;box-sizing:border-box;padding:0 8px;border-radius:var(--radius-md);border:1px solid var(--border-control);background:var(--bg-surface);color:var(--text-body);font-size:var(--text-xs);line-height:var(--leading-xs);font-family:var(--font-sans);cursor:pointer;transition:var(--t-hover);letter-spacing:var(--tracking-xs)}
|
|
47
|
+
.tbtn:hover{background:var(--bg-hover);color:var(--text-heading)}
|
|
48
|
+
|
|
49
|
+
/* content */
|
|
50
|
+
.content{padding:34px 40px 160px;max-width:1240px}
|
|
51
|
+
section{margin-bottom:52px;scroll-margin-top:78px}
|
|
52
|
+
.eyebrow{font-size:var(--text-xs);line-height:var(--leading-xs);font-weight:var(--weight-semibold);color:var(--text-secondary);margin-bottom:6px;letter-spacing:var(--tracking-xs)}
|
|
53
|
+
.sec-head{margin-bottom:14px}
|
|
54
|
+
.sec-head h2{margin:0;font-size:var(--text-2xl);line-height:var(--leading-2xl);letter-spacing:var(--tracking-2xl);font-weight:var(--weight-semibold);color:var(--text-heading)}
|
|
55
|
+
.sec-head .desc{margin:4px 0 0;font-size:var(--text-base);line-height:var(--leading-base);color:var(--text-secondary);max-width:70ch}
|
|
56
|
+
.sec-meta{display:flex;align-items:center;gap:10px;margin-top:9px;font-size:var(--text-xs);color:var(--text-muted);font-family:var(--font-sans);font-variant-numeric:tabular-nums;letter-spacing:var(--tracking-xs)}
|
|
57
|
+
.sec-meta a{color:var(--text-muted);text-decoration:none}
|
|
58
|
+
.sec-meta a:hover{color:var(--action-primary)}
|
|
59
|
+
.frame-wrap{position:relative;border:1px solid var(--border-card);border-radius:var(--radius-lg);background:var(--bg-surface);overflow:hidden}
|
|
60
|
+
.frame-wrap iframe{border:0;display:block;transform-origin:top left;background:var(--bg-surface)}
|
|
61
|
+
.frame-ph{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;font-family:var(--font-sans);font-variant-numeric:tabular-nums;font-size:var(--text-xs);color:var(--text-muted);background:var(--bg-inset);letter-spacing:var(--tracking-xs)}
|
|
62
|
+
.code-area{margin-top:14px}
|
|
63
|
+
.code-btn{display:inline-flex;align-items:center;gap:6px;height:28px;box-sizing:border-box;padding:0 8px;line-height:var(--leading-xs);border-radius:var(--radius-md);border:1px solid var(--border-control);background:var(--bg-surface);color:var(--text-secondary);font-size:var(--text-xs);font-family:var(--font-sans);cursor:pointer;transition:var(--t-hover);letter-spacing:var(--tracking-xs)}
|
|
64
|
+
.code-btn:hover{background:var(--bg-hover);color:var(--text-heading)}
|
|
65
|
+
.code-panel{display:none;margin-top:10px;border:1px solid var(--border-card);border-radius:var(--radius-lg);overflow:hidden;background:var(--bg-inset)}
|
|
66
|
+
.code-panel.open{display:block}
|
|
67
|
+
.code-head{display:flex;align-items:center;justify-content:space-between;background:var(--bg-surface);border-bottom:1px solid var(--border-subtle)}
|
|
68
|
+
.code-tabs{display:flex;flex:1;overflow-x:auto;scrollbar-width:none}
|
|
69
|
+
.code-tabs::-webkit-scrollbar{display:none}
|
|
70
|
+
.code-tab{padding:8px 12px;border:none;background:transparent;font-size:var(--text-xs);font-family:var(--font-sans);color:var(--text-secondary);cursor:pointer;white-space:nowrap;border-bottom:2px solid transparent;margin-bottom:-1px;letter-spacing:var(--tracking-xs)}
|
|
71
|
+
.code-tab.on{color:var(--text-heading);border-bottom-color:var(--action-primary)}
|
|
72
|
+
.code-fw{display:flex;gap:3px;padding:6px 8px;flex-shrink:0}
|
|
73
|
+
.code-fw{display:flex;align-items:center;flex-shrink:0;height:28px;box-sizing:border-box;gap:2px;padding:2px;margin:0 8px;border-radius:var(--radius-md);background:var(--bg-inset);border:1px solid var(--border-control)}.fw-btn{display:inline-flex;align-items:center;height:22px;padding:0 6px;font-size:var(--text-xs);line-height:var(--leading-xs);border-radius:var(--radius-sm);border:none;background:transparent;color:var(--text-secondary);font-family:var(--font-sans);font-weight:var(--weight-medium);white-space:nowrap;cursor:pointer;transition:var(--t-hover);letter-spacing:var(--tracking-xs)}.fw-btn:not(.on):hover{color:var(--text-heading)}
|
|
74
|
+
.fw-btn.on{background:var(--bg-surface);color:var(--text-heading);box-shadow:0 1px 2px rgba(0,0,0,.08)}
|
|
75
|
+
.code-body{position:relative}
|
|
76
|
+
.code-body pre{margin:0;padding:14px 70px 14px 16px;overflow:auto;max-height:420px;font-family:var(--font-mono);font-size:var(--text-code);line-height:var(--leading-code);color:var(--text-body);white-space:pre}
|
|
77
|
+
.copy-btn{position:absolute;top:8px;right:10px;display:inline-flex;align-items:center;height:28px;box-sizing:border-box;padding:0 8px;border-radius:var(--radius-md);border:1px solid var(--border-control);background:var(--bg-surface);color:var(--text-secondary);font-size:var(--text-xs);line-height:var(--leading-xs);font-family:var(--font-sans);cursor:pointer;letter-spacing:var(--tracking-xs)}
|
|
78
|
+
|
|
79
|
+
/* overview */
|
|
80
|
+
#overview{margin-bottom:64px}
|
|
81
|
+
.hero h1{margin:0;font-size:var(--text-3xl);line-height:var(--leading-3xl);letter-spacing:var(--tracking-3xl);font-weight:var(--weight-semibold);color:var(--text-heading)}
|
|
82
|
+
.hero .lede{margin:10px 0 0;font-size:var(--text-md);line-height:var(--leading-md);color:var(--text-secondary);max-width:74ch;letter-spacing:var(--tracking-md)}
|
|
83
|
+
.stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:12px;margin:26px 0 0}
|
|
84
|
+
.stat{border:1px solid var(--border-card);border-radius:var(--radius-lg);background:var(--bg-surface);padding:14px 16px}
|
|
85
|
+
.stat .n{font-size:var(--text-num);line-height:var(--leading-num);letter-spacing:var(--tracking-num);font-weight:var(--weight-light);color:var(--text-heading)}
|
|
86
|
+
.stat .k{font-size:var(--text-xs);color:var(--text-secondary);padding-top:2px;letter-spacing:var(--tracking-xs)}
|
|
87
|
+
.doccards{display:grid;grid-template-columns:repeat(auto-fit,minmax(230px,1fr));gap:12px;margin-top:12px}
|
|
88
|
+
.doccard{display:block;color:var(--text-body);border:1px solid var(--border-card);border-radius:var(--radius-lg);background:var(--bg-surface);padding:14px 16px;text-decoration:none;transition:var(--t-hover)}
|
|
89
|
+
.doccard:hover{background:var(--bg-hover);border-color:var(--border-strong);color:var(--text-body)}
|
|
90
|
+
.doccard .t{display:flex;align-items:center;gap:7px;font-size:var(--text-base);font-weight:var(--weight-medium);color:var(--text-heading)}
|
|
91
|
+
.doccard .t svg{color:var(--text-secondary)}
|
|
92
|
+
.doccard .d{font-size:var(--text-xs);line-height:16.5px;color:var(--text-secondary);padding-top:4px;letter-spacing:var(--tracking-xs)}
|
|
93
|
+
.sub-h{margin:32px 0 8px;font-size:var(--text-xs);line-height:var(--leading-xs);font-weight:var(--weight-semibold);color:var(--text-secondary);letter-spacing:var(--tracking-xs)}
|
|
94
|
+
|
|
95
|
+
/* home thumbnail index */
|
|
96
|
+
.th{margin-bottom:48px}
|
|
97
|
+
.th-head{display:flex;align-items:baseline;gap:8px}
|
|
98
|
+
.th-title{margin:0;font-size:var(--text-xl);line-height:var(--leading-xl);letter-spacing:var(--tracking-xl);font-weight:var(--weight-semibold);color:var(--text-heading)}
|
|
99
|
+
.th-count{font-size:var(--text-base);color:var(--text-muted);font-variant-numeric:tabular-nums}
|
|
100
|
+
.th-lede{margin:6px 0 16px;font-size:var(--text-base);line-height:var(--leading-base);color:var(--text-secondary);max-width:74ch}
|
|
101
|
+
.tiles{display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:16px}
|
|
102
|
+
.tile{display:flex;flex-direction:column;gap:8px;text-decoration:none;color:inherit;border-radius:var(--radius-lg)}.tile:hover{color:inherit}
|
|
103
|
+
.tile-stage{position:relative;height:140px;border:1px solid var(--border-card);border-radius:var(--radius-lg);background:var(--bg-surface);overflow:hidden;display:flex;align-items:center;justify-content:center;transform:translateZ(0);contain:paint;transition:var(--t-hover)}
|
|
104
|
+
.tile:hover .tile-stage{border-color:var(--border-strong);box-shadow:var(--shadow-node)}
|
|
105
|
+
.tile:focus-visible{outline:2px solid var(--focus-border);outline-offset:2px}
|
|
106
|
+
.tile-cover{pointer-events:none;user-select:none;transform-origin:center;display:flex;align-items:center;justify-content:center}
|
|
107
|
+
.tile-fallback{font-size:var(--text-base);color:var(--text-muted)}
|
|
108
|
+
.tile-name{font-size:var(--text-base);line-height:var(--leading-base);font-weight:var(--weight-medium);color:var(--text-heading)}
|
|
109
|
+
[hidden]{display:none!important}
|
|
110
|
+
.grp-off{display:none!important}
|
|
111
|
+
.lib-title{display:flex;align-items:baseline;gap:8px;margin-bottom:28px}
|
|
112
|
+
.lib-title h1{margin:0;font-size:var(--text-3xl);line-height:var(--leading-3xl);letter-spacing:var(--tracking-3xl);font-weight:var(--weight-semibold);color:var(--text-heading)}
|
|
113
|
+
|
|
114
|
+
/* changelog */
|
|
115
|
+
#changelog{margin-bottom:64px}
|
|
116
|
+
.cl-title{margin:0;font-size:var(--text-xl);line-height:var(--leading-xl);letter-spacing:var(--tracking-xl);font-weight:var(--weight-semibold);color:var(--text-heading)}
|
|
117
|
+
.cl-lede{margin:6px 0 20px;font-size:var(--text-base);line-height:var(--leading-base);color:var(--text-secondary);max-width:74ch}
|
|
118
|
+
.cl-lede a{color:var(--link)}.cl-lede a:hover{color:var(--link-hover,var(--action-primary-hover))}
|
|
119
|
+
.cl-rel{display:grid;grid-template-columns:140px minmax(0,1fr);gap:24px;padding:20px 0;border-top:1px solid var(--border-subtle)}
|
|
120
|
+
.cl-head{display:flex;flex-direction:column;align-items:flex-start;gap:6px}
|
|
121
|
+
.cl-v{font-size:var(--text-md);line-height:var(--leading-md);font-weight:var(--weight-semibold);color:var(--text-heading);font-variant-numeric:tabular-nums;letter-spacing:var(--tracking-md)}
|
|
122
|
+
.cl-date{font-size:var(--text-xs);line-height:var(--leading-xs);color:var(--text-secondary);font-variant-numeric:tabular-nums;letter-spacing:var(--tracking-xs)}
|
|
123
|
+
.cl-status{display:inline-flex;align-items:center;height:20px;padding:0 6px;border-radius:var(--radius-sm);background:var(--warning-bg);color:var(--warning-text);font-size:var(--text-xs);font-weight:var(--weight-medium);letter-spacing:var(--tracking-xs)}
|
|
124
|
+
.cl-items{margin:0;padding:0;list-style:none;display:flex;flex-direction:column;gap:10px}
|
|
125
|
+
.cl-items li{display:grid;grid-template-columns:auto minmax(0,1fr);gap:10px;align-items:baseline}
|
|
126
|
+
.cl-t{font-size:var(--text-base);line-height:var(--leading-base);color:var(--text-body);text-wrap:pretty}
|
|
127
|
+
.cl-t code{font-family:var(--font-mono);font-size:var(--text-code);padding:1px 4px;border-radius:var(--radius-sm);background:var(--bg-hover);border:1px solid var(--border-control);color:var(--text-heading)}
|
|
128
|
+
.cl-tag{display:inline-flex;align-items:center;height:20px;padding:0 6px;border-radius:var(--radius-sm);font-size:var(--text-xs);font-weight:var(--weight-medium);white-space:nowrap;min-width:var(--cl-tag-w,64px);justify-content:center;box-sizing:border-box;letter-spacing:var(--tracking-xs)}
|
|
129
|
+
.cl-new{background:var(--info-bg);color:var(--info-fg)}
|
|
130
|
+
.cl-improved{background:var(--bg-hover);color:var(--text-body)}
|
|
131
|
+
.cl-fixed{background:var(--success-bg);color:var(--success-text)}
|
|
132
|
+
.cl-breaking{background:var(--danger-bg);color:var(--danger-text)}
|
|
133
|
+
.cl-removed{background:var(--bg-hover);color:var(--text-secondary)}
|
|
134
|
+
@media (max-width:720px){.cl-rel{grid-template-columns:minmax(0,1fr);gap:10px}.cl-head{flex-direction:row;align-items:baseline;gap:10px}}
|
|
135
|
+
|
|
136
|
+
/* bilingual pairing */
|
|
137
|
+
.bi{display:flex}
|
|
138
|
+
.bi-col{flex-direction:column;gap:1px}
|
|
139
|
+
.bi-row{flex-direction:row;align-items:baseline;gap:8px;flex-wrap:wrap}
|
|
140
|
+
.ln-sub{font-size:.82em;font-weight:var(--weight-regular);color:var(--text-muted);letter-spacing:0}
|
|
141
|
+
.nav-item .ln-sub{font-size:var(--text-2xs);line-height:var(--leading-2xs);letter-spacing:var(--tracking-2xs)}
|
|
142
|
+
.cl-tag.bi-row,.cl-status.bi-row{flex-wrap:nowrap;align-items:center;gap:4px}
|
|
143
|
+
.cl-tag .ln-sub,.cl-status .ln-sub{font-size:inherit;color:inherit;opacity:.8}
|
|
144
|
+
.tile-cover{letter-spacing:0}</style>
|
|
145
|
+
</head>
|
|
146
|
+
<body>
|
|
147
|
+
<div class="shell">
|
|
148
|
+
<nav class="sidebar">
|
|
149
|
+
<div class="brand"><img src="assets/keybricks-logo.png" alt=""><b>Keybricks</b></div>
|
|
150
|
+
<div class="brand-sub" data-i="brandsub"></div>
|
|
151
|
+
<div class="nav-search">
|
|
152
|
+
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"/><path d="m21 21-4.3-4.3"/></svg>
|
|
153
|
+
<input type="search" id="filter" autocomplete="off">
|
|
154
|
+
</div>
|
|
155
|
+
<div id="nav"></div>
|
|
156
|
+
</nav>
|
|
157
|
+
<div class="main">
|
|
158
|
+
<div class="topbar">
|
|
159
|
+
<div class="doclinks">
|
|
160
|
+
<a class="doclink" href="readme.md" data-readme="1">
|
|
161
|
+
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20"/><path d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z"/></svg>
|
|
162
|
+
<span data-i="doc_readme"></span></a>
|
|
163
|
+
<a class="doclink" href="DESIGN.md" download="Keybricks-DESIGN.md">
|
|
164
|
+
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg>
|
|
165
|
+
<span data-i="doc_design"></span></a>
|
|
166
|
+
<a class="doclink" href="INTEGRATION.md"><span data-i="doc_integration"></span></a>
|
|
167
|
+
<a class="doclink" href="gallery.html"><span data-i="doc_gallery"></span></a>
|
|
168
|
+
</div>
|
|
169
|
+
<div class="topbar-right">
|
|
170
|
+
<div class="lang-switch" id="langSwitch">
|
|
171
|
+
<button class="lang-btn active" data-lang="en">EN</button>
|
|
172
|
+
<button class="lang-btn" data-lang="zh">中文</button>
|
|
173
|
+
<button class="lang-btn" data-lang="both">EN+中文</button>
|
|
174
|
+
<button class="lang-btn" data-lang="ja">日本語</button>
|
|
175
|
+
</div>
|
|
176
|
+
<button class="tbtn" id="themeToggle"><span id="themeIcon">☽</span><span id="themeLabel">Dark</span></button>
|
|
177
|
+
</div>
|
|
178
|
+
</div>
|
|
179
|
+
<div class="content" id="content"></div>
|
|
180
|
+
</div>
|
|
181
|
+
</div>
|
|
182
|
+
|
|
183
|
+
<script src="https://unpkg.com/react@18.3.1/umd/react.production.min.js" crossorigin="anonymous"></script>
|
|
184
|
+
<script src="https://unpkg.com/react-dom@18.3.1/umd/react-dom.production.min.js" crossorigin="anonymous"></script>
|
|
185
|
+
<script src="https://unpkg.com/d3@7.9.0/dist/d3.min.js" integrity="sha384-CjloA8y00+1SDAUkjs099PVfnY2KmDC2BZnws9kh8D/lX1s46w6EPhpXdqMfjK6i" crossorigin="anonymous"></script>
|
|
186
|
+
<script src="https://unpkg.com/topojson-client@3.1.0/dist/topojson-client.min.js" integrity="sha384-Ukv1p/xTma6P4/2bY5KzWBw+ydSpXmhCMtyciIQVDJ1RmOxtCYNMF1uXT9T63H67" crossorigin="anonymous"></script>
|
|
187
|
+
<script src="_ds_bundle.js"></script>
|
|
188
|
+
<script src="site-nav.js"></script>
|
|
189
|
+
<script src="changelog.js"></script>
|
|
190
|
+
<script src="covers.js"></script>
|
|
191
|
+
<script>
|
|
192
|
+
const GROUPS=[["Brand","品牌","ブランド"],["Colors","颜色","カラー"],["Type","字体排印","タイポグラフィ"],["Foundations","基础规范","基盤仕様"],["Components","组件","コンポーネント"],["Charts","图表","チャート"],["Icons","图标库","アイコン"]];
|
|
193
|
+
|
|
194
|
+
const S={
|
|
195
|
+
brandsub:["Design System · v2.4.11","设计系统 · v2.4.11","デザインシステム · v2.4.11"],
|
|
196
|
+
doc_readme:["Readme","说明文档","ドキュメント"],
|
|
197
|
+
doc_design:["DESIGN.md","下载 DESIGN.md","DESIGN.md"],
|
|
198
|
+
doc_integration:["Integration","接入指南","導入ガイド"],
|
|
199
|
+
doc_gallery:["Gallery","组件画廊","ギャラリー"],
|
|
200
|
+
nav_overview:["Overview","总览","概要"],
|
|
201
|
+
nav_changelog:["Changelog","更新日志","変更履歴"],
|
|
202
|
+
nav_library:["All pages","全部页面","すべてのページ"],
|
|
203
|
+
th_components:["Components","组件","コンポーネント"],
|
|
204
|
+
th_charts:["Charts","图表","チャート"],
|
|
205
|
+
th_components_x:["Every component, at its simplest. Open one to see all its cases — the page holds every component, so you can keep scrolling.","每个组件最简单的样子。点开可查看它的全部用例——组件页包含全部组件,可以一直往下浏览。","各コンポーネントの最もシンプルな形。開くとすべてのケースを確認でき、ページには全コンポーネントが並ぶので、そのままスクロールできます。"],
|
|
206
|
+
th_charts_x:["Every chart type, drawn with real data.","每种图表类型,用真实数据绘制。","すべてのグラフタイプを実データで描画。"],
|
|
207
|
+
th_icons:["Icons","图标","アイコン"],
|
|
208
|
+
th_icons_x:["The icon libraries: the core set the product draws with, and the larger sets to reach for when it has no match.","图标库:产品使用的核心图标,以及核心库没有合适图标时可用的扩展库。","アイコンライブラリ:製品が使うコアセットと、該当がないときに使う拡張セット。"],
|
|
209
|
+
cl_lede:["What changed in each release, newest first. Upgrade notes and migration details are in <a href=\"INTEGRATION.md\">INTEGRATION.md</a>.","每个版本的改动,最新的在前。升级与迁移细节见 <a href=\"INTEGRATION.md\">INTEGRATION.md</a>。","リリースごとの変更点(新しい順)。アップグレードと移行の詳細は <a href=\"INTEGRATION.md\">INTEGRATION.md</a> を参照。"],
|
|
210
|
+
cl_unreleased:["Unreleased","未发布","未リリース"],
|
|
211
|
+
filter_ph:["Filter…","筛选…","絞り込み…"],
|
|
212
|
+
ov_eyebrow:["Overview","总览","概要"],
|
|
213
|
+
ov_title:["Keybricks Design System","Keybricks 设计系统","Keybricks デザインシステム"],
|
|
214
|
+
ov_lede:[
|
|
215
|
+
"The design language of the Keybricks EPM platform: a near-monochrome, high-density enterprise UI built on one token layer, one action blue, and 121 components shipped for React and Vue 3. Every card on this page is the live component, rendered from the same source the product imports.",
|
|
216
|
+
"Keybricks 企业绩效管理平台的设计语言:近乎单色、高密度的企业级界面,构建在同一套 token 之上,只有一个强调蓝,121 个组件同时提供 React 与 Vue 3 版本。本页每张卡片都是实时渲染的真实组件,与产品引用的是同一份源码。",
|
|
217
|
+
"Keybricks EPM プラットフォームのデザイン言語:ほぼモノクロで高密度なエンタープライズ UI を、単一のトークン層と 1 色のアクションブルーで構築。121 個のコンポーネントを React と Vue 3 で提供します。本ページのカードはすべて、製品と同じソースから描画された実物のコンポーネントです。"],
|
|
218
|
+
st_components:["Components","组件","コンポーネント"],
|
|
219
|
+
st_icons:["Icons","图标","アイコン"],
|
|
220
|
+
st_charts:["Chart types","图表类型","チャート種類"],
|
|
221
|
+
st_tokens:["Token files","Token 文件","トークンファイル"],
|
|
222
|
+
st_themes:["Themes","主题","テーマ"],st_fw:["Frameworks","框架","フレームワーク"],
|
|
223
|
+
d_readme:["readme.md","readme.md","readme.md"],
|
|
224
|
+
d_readme_x:["What the system is, in full — content voice, visual foundations, iconography, the component index.","体系全貌 — 文案语气、视觉基础、图标系统、组件清单。","システムの全体像 — 文言のトーン、視覚基盤、アイコン、コンポーネント一覧。"],
|
|
225
|
+
d_design:["DESIGN.md","DESIGN.md","DESIGN.md"],
|
|
226
|
+
d_design_x:["The rules file for AI coding agents: absolute values, interaction states, an explicit do-not list.","给 AI 编程代理读的规则文件:绝对数值、交互状态、明确的禁止事项。","AI コーディングエージェント向けのルールファイル:絶対値、インタラクション状態、禁止事項。"],
|
|
227
|
+
d_integration:["INTEGRATION.md","INTEGRATION.md","INTEGRATION.md"],
|
|
228
|
+
d_integration_x:["Three steps to first paint, size tiers, import paths for all 121 components, token reference, versioning.","三步跑通首屏,尺寸层级,121 个组件的引入路径、token 速查、版本策略。","初回描画までの 3 ステップ、サイズ階層、全 121 コンポーネントの import パス、トークン早見表、バージョン方針。"],
|
|
229
|
+
d_gallery:["gallery.html","gallery.html","gallery.html"],
|
|
230
|
+
d_gallery_x:["Every card as a filterable thumbnail grid — the fastest way to find a component.","全部卡片的可筛选缩略图网格 — 找组件最快的入口。","全カードをフィルター可能なサムネイル一覧で — コンポーネントを最速で探せます。"],
|
|
231
|
+
open_full:["open full size","查看原尺寸","原寸で開く"],
|
|
232
|
+
loading:["loading…","加载中…","読み込み中…"]
|
|
233
|
+
};
|
|
234
|
+
|
|
235
|
+
const html=document.documentElement;
|
|
236
|
+
let lang="en";
|
|
237
|
+
const i18nEls=[];
|
|
238
|
+
|
|
239
|
+
function pick(v){return lang==="zh"?(v[1]||v[0]):lang==="ja"?(v[2]||v[0]):v[0];}
|
|
240
|
+
function paint(el){
|
|
241
|
+
const v=el.__l;if(!v)return;
|
|
242
|
+
if(lang==="both"){
|
|
243
|
+
el.classList.add("bi",el.dataset.row?"bi-row":"bi-col");
|
|
244
|
+
el.innerHTML='<span class="ln-en"></span><span class="ln-sub"></span>';
|
|
245
|
+
el.firstChild[el.__html?"innerHTML":"textContent"]=v[0];
|
|
246
|
+
el.lastChild[el.__html?"innerHTML":"textContent"]=v[1]||"";
|
|
247
|
+
} else {
|
|
248
|
+
el.classList.remove("bi","bi-row","bi-col");
|
|
249
|
+
el[el.__html?"innerHTML":"textContent"]=pick(v);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
function bind(el,v,opt){el.__l=v;if(opt&&opt.html)el.__html=1;if(opt&&opt.row)el.dataset.row="1";i18nEls.push(el);paint(el);return el;}
|
|
253
|
+
function make(tag,cls,v,opt){const el=document.createElement(tag);if(cls)el.className=cls;if(v)bind(el,v,opt);return el;}
|
|
254
|
+
function setLang(l){
|
|
255
|
+
lang=l;html.setAttribute("data-lang",l);
|
|
256
|
+
html.setAttribute("lang",l==="ja"?"ja":l==="zh"?"zh":"en");
|
|
257
|
+
i18nEls.forEach(paint);
|
|
258
|
+
document.getElementById("filter").placeholder=pick(S.filter_ph);
|
|
259
|
+
document.querySelectorAll('a[data-readme]').forEach(a=>{a.href=(l==="zh"||l==="both")?"readme.zh-CN.md":"readme.md";});
|
|
260
|
+
if(typeof fitChangelogTags==="function")fitChangelogTags();
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/* ---------- overview ---------- */
|
|
264
|
+
function renderOverview(){
|
|
265
|
+
const s=document.createElement("section");s.id="overview";
|
|
266
|
+
const hero=document.createElement("div");hero.className="hero";
|
|
267
|
+
hero.appendChild(make("div","eyebrow",S.ov_eyebrow));
|
|
268
|
+
hero.appendChild(make("h1",null,S.ov_title,{row:1}));
|
|
269
|
+
hero.appendChild(make("p","lede",S.ov_lede));
|
|
270
|
+
s.appendChild(hero);
|
|
271
|
+
const stats=document.createElement("div");stats.className="stats";
|
|
272
|
+
[["121",S.st_components],["1,610",S.st_icons],["27",S.st_charts],["10",S.st_tokens],["React · Vue 3",S.st_fw]].forEach(([n,k])=>{
|
|
273
|
+
const d=document.createElement("div");d.className="stat";
|
|
274
|
+
const nn=document.createElement("div");nn.className="n";nn.textContent=n;
|
|
275
|
+
if(/[A-Za-z]/.test(n))nn.style.fontSize="var(--text-md)",nn.style.lineHeight="var(--leading-num)",nn.style.fontWeight="var(--weight-medium)";
|
|
276
|
+
d.appendChild(nn);d.appendChild(make("div","k",k));stats.appendChild(d);
|
|
277
|
+
});
|
|
278
|
+
s.appendChild(stats);
|
|
279
|
+
const bookIcon='<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20"/><path d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z"/></svg>';
|
|
280
|
+
const cards=[["readme.md",S.d_readme,S.d_readme_x,null],["DESIGN.md",S.d_design,S.d_design_x,"Keybricks-DESIGN.md"],["INTEGRATION.md",S.d_integration,S.d_integration_x,null],["gallery.html",S.d_gallery,S.d_gallery_x,null]];
|
|
281
|
+
const wrap=document.createElement("div");wrap.className="doccards";
|
|
282
|
+
cards.forEach(([href,t,d,dl])=>{
|
|
283
|
+
const a=document.createElement("a");a.className="doccard";a.href=href;if(dl)a.setAttribute("download",dl);if(href==="readme.md")a.dataset.readme="1";
|
|
284
|
+
const tt=document.createElement("div");tt.className="t";tt.innerHTML=bookIcon;
|
|
285
|
+
const label=make("span",null,t);tt.appendChild(label);
|
|
286
|
+
a.appendChild(tt);a.appendChild(make("div","d",d));wrap.appendChild(a);
|
|
287
|
+
});
|
|
288
|
+
s.appendChild(make("div","sub-h",["Documentation","文档","ドキュメント"]));
|
|
289
|
+
s.appendChild(wrap);
|
|
290
|
+
document.getElementById("content").appendChild(s);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
/* ---------- home: thumbnail index (covers: covers.js) ---------- */
|
|
294
|
+
const stem=p=>p.replace(/^.*\//,"").replace(/\.card\.html$|\.html$/,"");
|
|
295
|
+
class CoverBoundary extends React.Component{constructor(p){super(p);this.state={err:false};}static getDerivedStateFromError(){return {err:true};}componentDidCatch(e){console.warn("cover failed:",this.props.name,e&&e.message);}render(){return this.state.err?React.createElement("div",{className:"tile-fallback"},this.props.name):this.props.children;}}
|
|
296
|
+
function renderTiles(host,group,titleS,ledeS){
|
|
297
|
+
const items=KB_CARDS.filter(c=>c.group===group);if(!items.length)return;
|
|
298
|
+
const head=document.createElement("div");head.className="th-head";
|
|
299
|
+
const h=make("h2","th-title",titleS);const n=document.createElement("span");n.className="th-count";n.textContent=items.length;
|
|
300
|
+
head.appendChild(h);head.appendChild(n);host.appendChild(head);
|
|
301
|
+
host.appendChild(make("p","th-lede",ledeS));
|
|
302
|
+
const grid=document.createElement("div");grid.className="tiles";
|
|
303
|
+
const K=window.KeybricksDesignSystem_71231a,C=window.KB_COVERS||{};
|
|
304
|
+
items.forEach(c=>{
|
|
305
|
+
const a=document.createElement("a");a.className="tile";a.href="#/c/"+slug(c.path);
|
|
306
|
+
const stage=document.createElement("div");stage.className="tile-stage";stage.setAttribute("inert","");stage.setAttribute("aria-hidden","true");
|
|
307
|
+
const inner=document.createElement("div");inner.className="tile-cover";stage.appendChild(inner);
|
|
308
|
+
a.appendChild(stage);a.appendChild(make("div","tile-name",[c.name,c.zh,c.ja]));grid.appendChild(a);
|
|
309
|
+
const cov=C[stem(c.path)];
|
|
310
|
+
if(cov&&K&&window.ReactDOM){inner.style.transform="scale("+cov[0]+")";
|
|
311
|
+
try{ReactDOM.createRoot(inner).render(React.createElement(CoverBoundary,{name:c.name},cov[1](React.createElement,K)));}catch(e){inner.textContent=c.name;}}
|
|
312
|
+
else{inner.className="tile-fallback";inner.textContent=c.name;}
|
|
313
|
+
});
|
|
314
|
+
host.appendChild(grid);
|
|
315
|
+
}
|
|
316
|
+
function renderHome(){
|
|
317
|
+
const home=document.getElementById("view-home");
|
|
318
|
+
const comp=document.createElement("section");comp.id="th-components";comp.className="th";renderTiles(comp,"Components",S.th_components,S.th_components_x);home.appendChild(comp);
|
|
319
|
+
const ch=document.createElement("section");ch.id="th-charts";ch.className="th";renderTiles(ch,"Charts",S.th_charts,S.th_charts_x);home.appendChild(ch);
|
|
320
|
+
const ic=document.createElement("section");ic.id="th-icons";ic.className="th";renderTiles(ic,"Icons",S.th_icons,S.th_icons_x);home.appendChild(ic);
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
/* ---------- routes: #/ home · #/changelog · #/c/<card> the one page with every card ---------- */
|
|
324
|
+
function route(){
|
|
325
|
+
let hsh=location.hash||"#/";
|
|
326
|
+
if(/^#[^/]/.test(hsh)&&hsh!=="#overview"&&hsh!=="#changelog"){history.replaceState(null,"","#/c/"+hsh.slice(1));hsh=location.hash;}
|
|
327
|
+
if(hsh==="#overview")hsh="#/";if(hsh==="#changelog")hsh="#/changelog";
|
|
328
|
+
const view=hsh.startsWith("#/c/")?"library":hsh==="#/changelog"?"changelog":"home";
|
|
329
|
+
["home","changelog","library"].forEach(v=>{document.getElementById("view-"+v).hidden=v!==view;});
|
|
330
|
+
document.querySelectorAll(".nav-item").forEach(n=>n.classList.toggle("active",(view==="home"&&n.dataset.jump==="overview")||(view==="changelog"&&n.dataset.jump==="changelog")));
|
|
331
|
+
const target=view==="library"?document.getElementById(hsh.slice(4)):null;
|
|
332
|
+
const sc=document.scrollingElement||document.documentElement;
|
|
333
|
+
// one page per group: show only the target card's group (a search shows every group)
|
|
334
|
+
const grp=target?target.dataset.group:null;libGroup=grp;applyGroup();
|
|
335
|
+
const lt=document.getElementById("lib-title");if(lt&&grp){const g=GROUPS.find(x=>x[0]===grp);lt.innerHTML="";lt.appendChild(make("h1",null,g||[grp],{row:1}));const n=document.createElement("span");n.className="th-count";n.textContent=KB_CARDS.filter(c=>c.group===grp).length;lt.appendChild(n);}
|
|
336
|
+
// frames sized while the library was hidden measured a zero width — size them again before measuring
|
|
337
|
+
if(view==="library")document.querySelectorAll("iframe").forEach(f=>{if(f.__wrap)fit(f);});
|
|
338
|
+
if(target)settleOn(target);else{if(settleOff)settleOff();window.scrollTo({top:0,behavior:"instant"});}
|
|
339
|
+
if(view==="changelog")fitChangelogTags();
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
let libGroup=null;
|
|
343
|
+
function applyGroup(){
|
|
344
|
+
const q=document.getElementById("filter").value.trim();
|
|
345
|
+
document.querySelectorAll("#view-library section[data-group]").forEach(sec=>sec.classList.toggle("grp-off",!q&&!!libGroup&&sec.dataset.group!==libGroup));
|
|
346
|
+
const lt=document.getElementById("lib-title");if(lt)lt.hidden=!!q;
|
|
347
|
+
}
|
|
348
|
+
/* Scroll a section to the top and keep it pinned while the cards above it load and resize (they load lazily and grow
|
|
349
|
+
to their real height seconds later). A ResizeObserver re-pins on every layout change; any user input, or 10s, releases it. */
|
|
350
|
+
let settleOff=null;
|
|
351
|
+
function settleOn(target){
|
|
352
|
+
if(settleOff)settleOff();
|
|
353
|
+
const sc=document.scrollingElement||document.documentElement,lib=document.getElementById("view-library");
|
|
354
|
+
const markNav=()=>document.querySelectorAll(".nav-item").forEach(n=>n.classList.toggle("active",n.dataset.jump===target.id));
|
|
355
|
+
const pin=()=>{const d=target.getBoundingClientRect().top-72;if(Math.abs(d)>1)window.scrollTo({top:sc.scrollTop+d,behavior:"instant"});markNav();};
|
|
356
|
+
const ro=new ResizeObserver(pin);ro.observe(lib);document.querySelectorAll("#view-library .frame-wrap").forEach(w=>ro.observe(w));
|
|
357
|
+
const evs=["wheel","touchmove","keydown","mousedown"];
|
|
358
|
+
const off=()=>{ro.disconnect();markNav();clearTimeout(t);evs.forEach(e=>window.removeEventListener(e,off,true));if(settleOff===off)settleOff=null;};
|
|
359
|
+
evs.forEach(e=>window.addEventListener(e,off,{capture:true,passive:true}));
|
|
360
|
+
const t=setTimeout(off,10000);settleOff=off;
|
|
361
|
+
pin();requestAnimationFrame(pin);
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
/* ---------- changelog (data: changelog.js) ---------- */
|
|
365
|
+
const CL_TAGS={new:["New","新增","新規"],improved:["Improved","改进","改善"],fixed:["Fixed","修复","修正"],breaking:["Breaking","不兼容变更","互換性のない変更"],removed:["Removed","移除","削除"]};
|
|
366
|
+
function renderChangelog(){
|
|
367
|
+
const s=document.createElement("section");s.id="changelog";
|
|
368
|
+
s.appendChild(make("h2","cl-title",S.nav_changelog));
|
|
369
|
+
s.appendChild(make("p","cl-lede",S.cl_lede,{html:1}));
|
|
370
|
+
(window.KB_CHANGELOG||[]).forEach(rel=>{
|
|
371
|
+
const r=document.createElement("article");r.className="cl-rel";r.id="v"+rel.v.replace(/\./g,"-");
|
|
372
|
+
const head=document.createElement("div");head.className="cl-head";
|
|
373
|
+
const v=document.createElement("div");v.className="cl-v";v.textContent=rel.v;head.appendChild(v);
|
|
374
|
+
if(rel.status==="unreleased")head.appendChild(make("span","cl-status",S.cl_unreleased,{row:1}));
|
|
375
|
+
else if(rel.date){const d=document.createElement("time");d.className="cl-date";d.dateTime=rel.date;d.textContent=rel.date;head.appendChild(d);}
|
|
376
|
+
r.appendChild(head);
|
|
377
|
+
const ul=document.createElement("ul");ul.className="cl-items";
|
|
378
|
+
rel.items.forEach(it=>{
|
|
379
|
+
const li=document.createElement("li");
|
|
380
|
+
li.appendChild(make("span","cl-tag cl-"+it.tag,CL_TAGS[it.tag]||[it.tag],{row:1}));
|
|
381
|
+
li.appendChild(make("span","cl-t",it.t,{html:1}));
|
|
382
|
+
ul.appendChild(li);
|
|
383
|
+
});
|
|
384
|
+
r.appendChild(ul);s.appendChild(r);
|
|
385
|
+
});
|
|
386
|
+
document.getElementById("content").appendChild(s);
|
|
387
|
+
fitChangelogTags();
|
|
388
|
+
}
|
|
389
|
+
/* One tag width for the whole changelog — the widest label in the current language — so every description starts at the same left edge. */
|
|
390
|
+
function fitChangelogTags(){
|
|
391
|
+
const root=document.getElementById("changelog");if(!root)return;
|
|
392
|
+
root.style.removeProperty("--cl-tag-w");
|
|
393
|
+
let w=64;root.querySelectorAll(".cl-tag").forEach(t=>{w=Math.max(w,Math.ceil(t.getBoundingClientRect().width));});
|
|
394
|
+
root.style.setProperty("--cl-tag-w",w+"px");
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
/* ---------- sections ---------- */
|
|
398
|
+
const slug=p=>p.replace(/[^a-zA-Z0-9]+/g,"-");
|
|
399
|
+
function renderSections(){
|
|
400
|
+
const content=document.getElementById("content");
|
|
401
|
+
GROUPS.forEach(([g])=>{
|
|
402
|
+
KB_CARDS.filter(c=>c.group===g).forEach(c=>{
|
|
403
|
+
const s=document.createElement("section");s.id=slug(c.path);s.dataset.group=g;
|
|
404
|
+
s.dataset.find=(c.name+" "+c.zh+" "+c.ja+" "+c.subtitle+" "+c.subtitleZh+" "+g).toLowerCase();
|
|
405
|
+
const head=document.createElement("div");head.className="sec-head";
|
|
406
|
+
head.appendChild(make("div","eyebrow",GROUPS.find(x=>x[0]===g)));
|
|
407
|
+
head.appendChild(make("h2",null,[c.name,c.zh,c.ja],{row:1}));
|
|
408
|
+
head.appendChild(make("p","desc",[c.subtitle,c.subtitleZh,c.subtitleJa]));
|
|
409
|
+
const meta=document.createElement("div");meta.className="sec-meta";
|
|
410
|
+
const a=document.createElement("a");a.href=c.path;a.target="_blank";
|
|
411
|
+
a.appendChild(make("span",null,S.open_full,{row:1}));a.appendChild(document.createTextNode(" ↗"));
|
|
412
|
+
const path=document.createElement("span");path.textContent=c.path;
|
|
413
|
+
meta.appendChild(path);meta.appendChild(a);
|
|
414
|
+
head.appendChild(meta);s.appendChild(head);
|
|
415
|
+
const [w,h]=(c.viewport||"700x400").split("x").map(Number);
|
|
416
|
+
const wrap=document.createElement("div");wrap.className="frame-wrap";wrap.style.height=h+"px";
|
|
417
|
+
const ph=document.createElement("div");ph.className="frame-ph";bind(ph,S.loading);
|
|
418
|
+
const f=document.createElement("iframe");f.loading="lazy";f.dataset.src=c.path;f.width=w;f.height=h;
|
|
419
|
+
if(c.alwaysDark)f.dataset.alwaysdark="1";
|
|
420
|
+
if(c.selfManaged)f.dataset.selfmanaged="1";
|
|
421
|
+
f.__w=w;f.__h=h;f.__wrap=wrap;f.__ph=ph;f.__section=s;
|
|
422
|
+
wrap.appendChild(f);wrap.appendChild(ph);s.appendChild(wrap);
|
|
423
|
+
content.appendChild(s);
|
|
424
|
+
});
|
|
425
|
+
});
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
/* ---------- sidebar ---------- */
|
|
429
|
+
function renderNav(){
|
|
430
|
+
const nav=document.getElementById("nav");
|
|
431
|
+
const top=document.createElement("a");top.className="nav-item";top.href="#/";top.dataset.jump="overview";
|
|
432
|
+
bind(top,S.nav_overview);nav.appendChild(top);
|
|
433
|
+
const cl=document.createElement("a");cl.className="nav-item";cl.href="#/changelog";cl.dataset.jump="changelog";
|
|
434
|
+
bind(cl,S.nav_changelog);nav.appendChild(cl);
|
|
435
|
+
GROUPS.forEach(gr=>{
|
|
436
|
+
const items=KB_CARDS.filter(c=>c.group===gr[0]);
|
|
437
|
+
if(!items.length)return;
|
|
438
|
+
const lab=document.createElement("div");lab.className="nav-label";
|
|
439
|
+
const ls=make("span",null,gr);lab.appendChild(ls);
|
|
440
|
+
const cnt=document.createElement("span");cnt.className="nav-count";cnt.textContent=" "+items.length;lab.appendChild(cnt);
|
|
441
|
+
lab.dataset.groupLabel=gr[0];lab.style.cursor="pointer";lab.title=gr[0];lab.onclick=()=>{location.hash="#/c/"+slug(items[0].path);};nav.appendChild(lab);
|
|
442
|
+
items.forEach(c=>{
|
|
443
|
+
const a=document.createElement("a");a.className="nav-item";a.href="#/c/"+slug(c.path);a.dataset.jump=slug(c.path);
|
|
444
|
+
a.dataset.find=(c.name+" "+c.zh+" "+c.ja+" "+c.subtitle+" "+c.subtitleZh+" "+gr[0]).toLowerCase();
|
|
445
|
+
bind(a,[c.name,c.zh,c.ja]);nav.appendChild(a);
|
|
446
|
+
});
|
|
447
|
+
});
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
/* ---------- theme ---------- */
|
|
451
|
+
let followSystem=true;
|
|
452
|
+
const themeOf=()=>html.getAttribute("data-theme")||"light";
|
|
453
|
+
function pushTheme(f){
|
|
454
|
+
if(f.dataset.alwaysdark==="1"||f.dataset.selfmanaged==="1")return;
|
|
455
|
+
const t=themeOf();
|
|
456
|
+
try{f.contentWindow&&f.contentWindow.postMessage({kb:"theme",theme:t},"*");}catch(e){}
|
|
457
|
+
try{
|
|
458
|
+
const d=f.contentDocument;
|
|
459
|
+
if(d&&d.documentElement){d.documentElement.setAttribute("data-theme",t);d.documentElement.style.colorScheme=t;}
|
|
460
|
+
}catch(e){}
|
|
461
|
+
}
|
|
462
|
+
function syncFrames(){document.querySelectorAll("iframe").forEach(pushTheme);}
|
|
463
|
+
function setTheme(t,fromUser){
|
|
464
|
+
if(fromUser)followSystem=false;
|
|
465
|
+
html.setAttribute("data-theme",t);html.style.colorScheme=t;
|
|
466
|
+
document.getElementById("themeLabel").textContent=t==="dark"?"Light":"Dark";
|
|
467
|
+
document.getElementById("themeIcon").textContent=t==="dark"?"\u2600":"\u263D";
|
|
468
|
+
syncFrames();[80,300,900].forEach(d=>setTimeout(syncFrames,d));
|
|
469
|
+
}
|
|
470
|
+
const mq=window.matchMedia?window.matchMedia("(prefers-color-scheme: dark)"):null;
|
|
471
|
+
setTheme(mq&&mq.matches?"dark":"light");
|
|
472
|
+
if(mq&&mq.addEventListener)mq.addEventListener("change",e=>{if(followSystem)setTheme(e.matches?"dark":"light");});
|
|
473
|
+
document.getElementById("themeToggle").addEventListener("click",()=>setTheme(themeOf()==="dark"?"light":"dark",true));
|
|
474
|
+
|
|
475
|
+
/* ---------- frames: lazy load, fit to width, grow with content ---------- */
|
|
476
|
+
/* Cards serve their source over postMessage (works from file:// too, where the host
|
|
477
|
+
cannot read the frame's DOM); the View Code UI is rendered here, below the box. */
|
|
478
|
+
const CODE_ICON='<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m18 16 4-4-4-4"/><path d="m6 8-4 4 4 4"/><path d="m14.5 4-5 16"/></svg>';
|
|
479
|
+
function buildCode(f,files){
|
|
480
|
+
if(f.__code||!files||!files.length)return;
|
|
481
|
+
const area=document.createElement("div");area.className="code-area";
|
|
482
|
+
const btn=document.createElement("button");btn.className="code-btn";
|
|
483
|
+
btn.innerHTML=CODE_ICON+'<span>View Code</span>';
|
|
484
|
+
const panel=document.createElement("div");panel.className="code-panel";
|
|
485
|
+
const head=document.createElement("div");head.className="code-head";
|
|
486
|
+
const tabs=document.createElement("div");tabs.className="code-tabs";
|
|
487
|
+
const fwb=document.createElement("div");fwb.className="code-fw";
|
|
488
|
+
head.appendChild(tabs);head.appendChild(fwb);
|
|
489
|
+
const body=document.createElement("div");body.className="code-body";
|
|
490
|
+
const pre=document.createElement("pre");
|
|
491
|
+
const copy=document.createElement("button");copy.className="copy-btn";copy.textContent="Copy";
|
|
492
|
+
body.appendChild(pre);body.appendChild(copy);
|
|
493
|
+
panel.appendChild(head);panel.appendChild(body);
|
|
494
|
+
area.appendChild(btn);area.appendChild(panel);
|
|
495
|
+
f.__section.appendChild(area);
|
|
496
|
+
let framework="react",active=0,open=false;const cache={};
|
|
497
|
+
files.forEach((t,i)=>{const b=document.createElement("button");b.className="code-tab";b.textContent=t.name;b.onclick=()=>{active=i;render();};tabs.appendChild(b);});
|
|
498
|
+
[["react","React"],["vue","Vue 3"]].forEach(([k,lab])=>{const b=document.createElement("button");b.className="fw-btn";b.textContent=lab;b.onclick=()=>{framework=k;render();};fwb.appendChild(b);});
|
|
499
|
+
const hidden=(t)=>(framework==="vue"&&t.reactOnly)||(framework==="react"&&t.vueOnly);
|
|
500
|
+
function render(){
|
|
501
|
+
if(hidden(files[active])){const k=files.findIndex(t=>!hidden(t));if(k>=0)active=k;}
|
|
502
|
+
[...tabs.children].forEach((el,i)=>{el.classList.toggle("on",i===active);el.style.display=hidden(files[i])?"none":"";el.textContent=framework==="vue"?(files[i].vueName||files[i].name.replace(/\.jsx$/,".vue")):files[i].name;});
|
|
503
|
+
[...fwb.children].forEach((el,i)=>el.classList.toggle("on",i===(framework==="react"?0:1)));
|
|
504
|
+
const key=framework+"|"+files[active].path;
|
|
505
|
+
if(cache[key]!=null)pre.textContent=cache[key];
|
|
506
|
+
else{pre.textContent="Loading…";try{f.contentWindow.postMessage({kb:"src-get",path:files[active].path,framework},"*");}catch(e){}}
|
|
507
|
+
}
|
|
508
|
+
copy.onclick=()=>{const t=pre.textContent;try{navigator.clipboard.writeText(t);}catch(e){}copy.textContent="Copied";setTimeout(()=>{copy.textContent="Copy";},1200);};
|
|
509
|
+
btn.onclick=()=>{open=!open;panel.classList.toggle("open",open);btn.querySelector("span").textContent=open?"Hide Code":"View Code";if(open)render();};
|
|
510
|
+
f.__code={receive(m){cache[m.framework+"|"+m.path]=m.text;if(open&&files[active].path===m.path&&framework===m.framework)pre.textContent=m.text;}};
|
|
511
|
+
}
|
|
512
|
+
addEventListener("message",e=>{
|
|
513
|
+
const m=e.data;if(!m||!m.kb)return;
|
|
514
|
+
const f=[...document.querySelectorAll("iframe")].find(x=>{try{return x.contentWindow===e.source;}catch(err){return false;}});
|
|
515
|
+
if(!f)return;
|
|
516
|
+
if(m.kb==="src-manifest")buildCode(f,m.files);
|
|
517
|
+
else if(m.kb==="src-text"&&f.__code)f.__code.receive(m);
|
|
518
|
+
else if(m.kb==="theme-ask")pushTheme(f);
|
|
519
|
+
});
|
|
520
|
+
function fit(f){
|
|
521
|
+
const wrap=f.__wrap,avail=wrap.clientWidth;
|
|
522
|
+
const scale=avail<f.__w?avail/f.__w:1;
|
|
523
|
+
const w=scale<1?f.__w:avail;
|
|
524
|
+
let h=f.__h;
|
|
525
|
+
try{const d=f.contentDocument;if(d&&d.documentElement)h=Math.max(h,d.documentElement.scrollHeight);}catch(e){}
|
|
526
|
+
f.style.width=w+"px";f.style.height=h+"px";
|
|
527
|
+
f.style.transform=scale<1?"scale("+scale+")":"none";
|
|
528
|
+
wrap.style.height=Math.round(h*scale)+"px";
|
|
529
|
+
}
|
|
530
|
+
function watchFrames(){
|
|
531
|
+
const frames=[...document.querySelectorAll("iframe[data-src]")];
|
|
532
|
+
const io=new IntersectionObserver(es=>{
|
|
533
|
+
if(settleOff)return;
|
|
534
|
+
es.forEach(e=>{
|
|
535
|
+
if(!e.isIntersecting)return;
|
|
536
|
+
const f=e.target;io.unobserve(f);
|
|
537
|
+
f.addEventListener("load",()=>{
|
|
538
|
+
if(f.__ph)f.__ph.remove();
|
|
539
|
+
pushTheme(f);fit(f);
|
|
540
|
+
[120,400,1000,2000].forEach(d=>setTimeout(()=>{pushTheme(f);fit(f);},d));
|
|
541
|
+
try{new f.contentWindow.ResizeObserver(()=>fit(f)).observe(f.contentDocument.documentElement);}catch(err){}
|
|
542
|
+
});
|
|
543
|
+
f.src=f.dataset.src;f.removeAttribute("data-src");
|
|
544
|
+
});
|
|
545
|
+
},{rootMargin:"500px 0px"});
|
|
546
|
+
frames.forEach(f=>io.observe(f));
|
|
547
|
+
addEventListener("resize",()=>document.querySelectorAll("iframe").forEach(f=>{if(f.__wrap&&!f.dataset.src)fit(f);}));
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
/* ---------- scroll spy + filter ---------- */
|
|
551
|
+
function scrollSpy(){
|
|
552
|
+
const map={};document.querySelectorAll("[data-jump]").forEach(el=>map[el.dataset.jump]=el);
|
|
553
|
+
const spy=new IntersectionObserver(es=>{
|
|
554
|
+
if(settleOff)return;
|
|
555
|
+
es.forEach(e=>{
|
|
556
|
+
if(!e.isIntersecting)return;
|
|
557
|
+
document.querySelectorAll(".nav-item").forEach(n=>n.classList.remove("active"));
|
|
558
|
+
const el=map[e.target.id];if(el){el.classList.add("active");
|
|
559
|
+
const r=el.getBoundingClientRect();if(r.top<70||r.bottom>innerHeight-20)el.parentElement.scrollTop+=r.top-160;}
|
|
560
|
+
});
|
|
561
|
+
},{rootMargin:"-12% 0px -78% 0px"});
|
|
562
|
+
document.querySelectorAll("section[id]").forEach(s=>spy.observe(s));
|
|
563
|
+
}
|
|
564
|
+
function setupFilter(){
|
|
565
|
+
const input=document.getElementById("filter");
|
|
566
|
+
input.addEventListener("input",()=>{
|
|
567
|
+
const t=input.value.trim().toLowerCase();
|
|
568
|
+
applyGroup();
|
|
569
|
+
if(t&&!location.hash.startsWith("#/c/")){const first=document.querySelector("#view-library section[data-find]");if(first)history.replaceState(null,"","#/c/"+first.id);route();}
|
|
570
|
+
document.querySelectorAll(".nav-item[data-find]").forEach(el=>{el.style.display=!t||el.dataset.find.includes(t)?"":"none";});
|
|
571
|
+
document.querySelectorAll("section[data-find]").forEach(el=>{el.style.display=!t||el.dataset.find.includes(t)?"":"none";});
|
|
572
|
+
document.querySelectorAll(".nav-label").forEach(lab=>{
|
|
573
|
+
let n=lab.nextElementSibling,any=false;
|
|
574
|
+
while(n&&n.classList.contains("nav-item")){if(n.style.display!=="none")any=true;n=n.nextElementSibling;}
|
|
575
|
+
lab.style.display=any?"":"none";
|
|
576
|
+
});
|
|
577
|
+
});
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
document.querySelectorAll("[data-i]").forEach(el=>{if(S[el.dataset.i])bind(el,S[el.dataset.i]);});
|
|
581
|
+
(()=>{const c=document.getElementById("content");["home","changelog","library"].forEach(v=>{const d=document.createElement("div");d.id="view-"+v;c.appendChild(d);});})();
|
|
582
|
+
renderOverview();renderChangelog();renderSections();renderNav();
|
|
583
|
+
(()=>{const g=id=>document.getElementById(id);g("view-home").appendChild(g("overview"));g("view-changelog").appendChild(g("changelog"));
|
|
584
|
+
const lt=document.createElement("div");lt.id="lib-title";lt.className="lib-title";g("view-library").appendChild(lt);
|
|
585
|
+
document.querySelectorAll("#content > section[data-group]").forEach(sec=>g("view-library").appendChild(sec));})();
|
|
586
|
+
renderHome();
|
|
587
|
+
if(document.fonts&&document.fonts.ready)document.fonts.ready.then(fitChangelogTags);
|
|
588
|
+
document.getElementById("langSwitch").addEventListener("click",e=>{
|
|
589
|
+
const b=e.target.closest(".lang-btn");if(!b)return;
|
|
590
|
+
document.querySelectorAll(".lang-btn").forEach(x=>x.classList.toggle("active",x===b));
|
|
591
|
+
setLang(b.dataset.lang);
|
|
592
|
+
});
|
|
593
|
+
setLang("en");watchFrames();scrollSpy();setupFilter();
|
|
594
|
+
window.addEventListener("hashchange",route);route();
|
|
595
|
+
</script>
|
|
596
|
+
</body>
|
|
597
|
+
</html>
|