hd-garden 0.12.1 → 0.13.1

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.
@@ -8,10 +8,11 @@ import {
8
8
  groupHandbookDocs,
9
9
  HANDBOOK_SECTIONS,
10
10
  HANDBOOK_UI,
11
- NAV_SHORT_TITLE,
12
11
  REFERENCE_SECTION,
12
+ handbookNavLabel,
13
13
  isReferencePath,
14
14
  handbookPath,
15
+ referenceBadgeSuffix,
15
16
  sectionTitle,
16
17
  type GardenDocNavItem,
17
18
  type HandbookLang,
@@ -103,7 +104,7 @@ export function GardenDocsNav({
103
104
  <div className="gdoc-mobile-crumb" aria-hidden="true">
104
105
  <span>{sectionTitle(currentSection, lang) ?? t.name}</span>
105
106
  <CaretRight size={12} />
106
- <strong>{currentDoc ? (lang === "en" ? currentDoc.navTitle ?? currentDoc.title : NAV_SHORT_TITLE[currentDoc.path] ?? currentDoc.title) : t.overviewHint}</strong>
107
+ <strong>{currentDoc ? handbookNavLabel(currentDoc, lang) : t.overviewHint}</strong>
107
108
  </div>
108
109
  </div>
109
110
 
@@ -161,7 +162,10 @@ export function GardenDocsNav({
161
162
  {group.items.map((item) => {
162
163
  const active = item.path === currentPath;
163
164
  const badge = COMPONENT_BADGE[item.path];
164
- const label = lang === "en" ? item.navTitle ?? item.title : NAV_SHORT_TITLE[item.path] ?? item.title;
165
+ const label = handbookNavLabel(item, lang);
166
+ const referenceSuffix = group.id === REFERENCE_SECTION && badge
167
+ ? referenceBadgeSuffix(badge, label)
168
+ : null;
165
169
  return (
166
170
  <li key={item.path} className={active ? "is-active" : undefined}>
167
171
  <Link
@@ -172,7 +176,11 @@ export function GardenDocsNav({
172
176
  {badge ? (
173
177
  <>
174
178
  <code className="gdoc-comp-pill">{badge}</code>
175
- {group.id === REFERENCE_SECTION ? null : <span className="gdoc-comp-label">{label}</span>}
179
+ {group.id === REFERENCE_SECTION ? (
180
+ referenceSuffix ? <span className="gdoc-comp-label">{referenceSuffix}</span> : null
181
+ ) : (
182
+ <span className="gdoc-comp-label">{label}</span>
183
+ )}
176
184
  </>
177
185
  ) : (
178
186
  <span>{label}</span>
@@ -133,6 +133,31 @@ export const NAV_SHORT_TITLE: Record<string, string> = {
133
133
  reference: "总览",
134
134
  };
135
135
 
136
+
137
+ /**
138
+ * Reference sidebar shows COMPONENT_BADGE inside <code>. When two pages share a
139
+ * badge (compose + compose-icons), keep the code pill and append the remainder
140
+ * of navTitle / short label after a separator (space / · / dash).
141
+ * Returns the suffix including its leading separator, or null.
142
+ */
143
+ export function referenceBadgeSuffix(badge: string, label: string): string | null {
144
+ if (!badge || !label || label === badge) return null;
145
+ if (!label.startsWith(badge)) return null;
146
+ const rest = label.slice(badge.length);
147
+ if (!rest || !/^[\s·\-—]/.test(rest)) return null;
148
+ return rest;
149
+ }
150
+
151
+ /** Sidebar text label: prefer authored navTitle; ZH may fall back to NAV_SHORT_TITLE. */
152
+ export function handbookNavLabel(item: GardenDocNavItem, lang: HandbookLang): string {
153
+ if (item.navTitle) return item.navTitle;
154
+ if (lang !== "en") {
155
+ const short = NAV_SHORT_TITLE[item.path];
156
+ if (short) return short;
157
+ }
158
+ return item.title;
159
+ }
160
+
136
161
  export function groupHandbookDocs<T extends GardenDocNavItem>(docs: T[]) {
137
162
  const bySection = new Map<string, T[]>();
138
163
  for (const section of HANDBOOK_SECTIONS) {
@@ -132,3 +132,73 @@ intent: |
132
132
  <slider min={1} max={12} value={seats} onChange={setSeats} label="席位" />
133
133
  <stat label="月费" value={total} unit="USD" />
134
134
  ```
135
+
136
+ Play 图表:`palette`(series|categorical)、`yStep`、`overflow`(expand|clip);块头可选 `frame: none`。布局头栏用 `<stack direction="row" justify="between">`。
137
+
138
+ 图例:`legend`(auto|show|hide)、`legendPosition`(top|bottom)。
139
+
140
+ ## 图表示例(play)
141
+
142
+ 下面两例是官方 compose 图表样板:静态八柱(系列蓝 + `yStep`)与可调权重五类柱(`palette="categorical"` + 底图例)。示意数据。
143
+
144
+ ### 静态:活跃时段分布
145
+
146
+ ```garden compose #compose-chart-active-hours
147
+ caption: 示意:最近 30 天活跃记录归一化后的分布。峰在 20:00。
148
+ frame: none
149
+ intent: |
150
+ 静态分布:系列蓝柱、显式 8% 刻度、stack 头栏左标题右徽章。
151
+ ---
152
+ {@body const rows = [
153
+ { h: "08:00", p: 0.05 },
154
+ { h: "10:00", p: 0.07 },
155
+ { h: "12:00", p: 0.15 },
156
+ { h: "14:00", p: 0.06 },
157
+ { h: "16:00", p: 0.09 },
158
+ { h: "18:00", p: 0.14 },
159
+ { h: "20:00", p: 0.28 },
160
+ { h: "22:00", p: 0.16 }
161
+ ]}
162
+
163
+ <stack direction="row" justify="between" align="center" gap={2}>
164
+ <stack gap={1}>
165
+ <caption>用户活跃时间分布(示例)</caption>
166
+ <caption>假设用户最近 30 天的活跃记录经过归一化后的分布</caption>
167
+ </stack>
168
+ <badge tone="new">推荐 20:00</badge>
169
+ </stack>
170
+
171
+ <chart data={rows} x={h} yLabel="活跃概率" yFormat="percent" yMin={0} yMax={0.32} yStep={0.08} overflow="expand" height={280}>
172
+ <bar y={p} label="活跃概率" tone="accent" />
173
+ </chart>
174
+ ```
175
+
176
+ ### 交互:个人与整体融合权重
177
+
178
+ 默认权重 **45%**。拧滑杆或快切 0 / 45 / 100,五根分类色柱与「预测最佳时间」跟着变。
179
+
180
+ ```garden compose #compose-chart-fusion-weights
181
+ caption: 交互示例:拧个人权重,融合柱按公式重算。示意数据。
182
+ frame: none
183
+ intent: |
184
+ 融合滑杆:categorical 逐柱色、legend 底栏单系列、overflow expand。
185
+ ---
186
+ {@body const [w, setW] = DIL.useState(45)}
187
+ {@body const a = w / 100}
188
+ {@body const p08 = a * 0.05 + (1 - a) * 0.12}
189
+ {@body const p12 = a * 0.12 + (1 - a) * 0.22}
190
+ {@body const p18 = a * 0.20 + (1 - a) * 0.26}
191
+ {@body const p20 = a * 0.45 + (1 - a) * 0.28}
192
+ {@body const p22 = a * 0.18 + (1 - a) * 0.12}
193
+ {@body const rows = [{ h: "08:00", p: p08 }, { h: "12:00", p: p12 }, { h: "18:00", p: p18 }, { h: "20:00", p: p20 }, { h: "22:00", p: p22 }]}
194
+ {@body const peak = max(p08, p12, p18, p20, p22)}
195
+ {@body const best = p20 == peak ? "20:00" : (p18 == peak ? "18:00" : (p12 == peak ? "12:00" : (p22 == peak ? "22:00" : "08:00")))}
196
+
197
+ <choice value={w} onChange={setW} label="权重快切" options={[{value:0,label:"0%"},{value:45,label:"45%"},{value:100,label:"100%"}]} />
198
+ <slider min={0} max={100} value={w} onChange={setW} label="个人活跃数据权重" unit="%" />
199
+ <chart legend="show" legendPosition="bottom" data={rows} x={h} palette="categorical" yLabel="融合后活跃概率" yFormat="percent" yMin={0} yMax={0.4} overflow="expand" height={280}>
200
+ <bar y={p} label="融合后活跃概率" tone="accent" />
201
+ </chart>
202
+ <stat label="预测最佳时间" value={best} />
203
+ ```
204
+
@@ -42,3 +42,7 @@ caption: 示例:按字数、阅读速度和配图数估算一篇文章的阅
42
42
  ## 字段说明
43
43
 
44
44
  全部字段、默认值、取值限制和报错代码见 [组件参考 · interactive](/garden/reference/interactive)。
45
+
46
+ Play 图表:`palette`(series|categorical)、`yStep`、`overflow`(expand|clip);块头可选 `frame: none`。布局头栏用 `<stack direction="row" justify="between">`。
47
+
48
+ 图例:`legend`(auto|show|hide)、`legendPosition`(top|bottom)。
@@ -121,3 +121,71 @@ intent: |
121
121
  <slider min={1} max={12} value={seats} onChange={setSeats} label="Seats" />
122
122
  <stat label="Monthly" value={total} unit="USD" />
123
123
  ```
124
+
125
+ Play charts: `palette` (`series`|`categorical`), `yStep`, `overflow` (`expand`|`clip`); block header may set `frame: none`. Title/badge rows use `<stack direction="row" justify="between">`. Legend: `legend` (`auto`|`show`|`hide`), `legendPosition` (`top`|`bottom`).
126
+
127
+ ## Chart examples (play)
128
+
129
+ Two official compose chart samples: eight static series bars with `yStep`, and a five-category weighted fusion chart (`palette="categorical"` + bottom legend). Illustrative data.
130
+
131
+ ### Static: active hours
132
+
133
+ ```garden compose #compose-chart-active-hours
134
+ caption: "Illustrative: normalized activity over 30 days. Peak at 20:00."
135
+ frame: none
136
+ intent: |
137
+ Static distribution: series blue bars, explicit 8% ticks, stack header.
138
+ ---
139
+ {@body const rows = [
140
+ { h: "08:00", p: 0.05 },
141
+ { h: "10:00", p: 0.07 },
142
+ { h: "12:00", p: 0.15 },
143
+ { h: "14:00", p: 0.06 },
144
+ { h: "16:00", p: 0.09 },
145
+ { h: "18:00", p: 0.14 },
146
+ { h: "20:00", p: 0.28 },
147
+ { h: "22:00", p: 0.16 }
148
+ ]}
149
+
150
+ <stack direction="row" justify="between" align="center" gap={2}>
151
+ <stack gap={1}>
152
+ <caption>User activity by hour (sample)</caption>
153
+ <caption>Normalized activity over the last 30 days (illustrative)</caption>
154
+ </stack>
155
+ <badge tone="new">Peak 20:00</badge>
156
+ </stack>
157
+
158
+ <chart data={rows} x={h} yLabel="Activity" yFormat="percent" yMin={0} yMax={0.32} yStep={0.08} overflow="expand" height={280}>
159
+ <bar y={p} label="Activity" tone="accent" />
160
+ </chart>
161
+ ```
162
+
163
+ ### Interactive: personal vs global fusion weight
164
+
165
+ Default weight **45%**. Twist the slider or jump 0 / 45 / 100 — five categorical bars and “best time” update together.
166
+
167
+ ```garden compose #compose-chart-fusion-weights
168
+ caption: Twist personal weight; fused bars recompute. Illustrative priors.
169
+ frame: none
170
+ intent: |
171
+ Fusion slider: categorical bars, bottom one-entry legend, overflow expand.
172
+ ---
173
+ {@body const [w, setW] = DIL.useState(45)}
174
+ {@body const a = w / 100}
175
+ {@body const p08 = a * 0.05 + (1 - a) * 0.12}
176
+ {@body const p12 = a * 0.12 + (1 - a) * 0.22}
177
+ {@body const p18 = a * 0.20 + (1 - a) * 0.26}
178
+ {@body const p20 = a * 0.45 + (1 - a) * 0.28}
179
+ {@body const p22 = a * 0.18 + (1 - a) * 0.12}
180
+ {@body const rows = [{ h: "08:00", p: p08 }, { h: "12:00", p: p12 }, { h: "18:00", p: p18 }, { h: "20:00", p: p20 }, { h: "22:00", p: p22 }]}
181
+ {@body const peak = max(p08, p12, p18, p20, p22)}
182
+ {@body const best = p20 == peak ? "20:00" : (p18 == peak ? "18:00" : (p12 == peak ? "12:00" : (p22 == peak ? "22:00" : "08:00")))}
183
+
184
+ <choice value={w} onChange={setW} label="Weight presets" options={[{value:0,label:"0%"},{value:45,label:"45%"},{value:100,label:"100%"}]} />
185
+ <slider min={0} max={100} value={w} onChange={setW} label="Personal activity weight" unit="%" />
186
+ <chart legend="show" legendPosition="bottom" data={rows} x={h} palette="categorical" yLabel="Fused activity" yFormat="percent" yMin={0} yMax={0.4} overflow="expand" height={280}>
187
+ <bar y={p} label="Fused activity" tone="accent" />
188
+ </chart>
189
+ <stat label="Predicted best time" value={best} />
190
+ ```
191
+
@@ -170,6 +170,11 @@ One mini sample per group, then a one-line table for every tag. No per-tag essay
170
170
  | `code` | Code snapshot |
171
171
  | `pre` | Preformatted text |
172
172
 
173
+
174
+ ## Chart examples
175
+
176
+ Play-level chart samples (static eight bars, fusion weight slider) live on [Diagrams · compose](/garden/en/components/compose#ui-compose-chart-active-hours).
177
+
173
178
  ## Limits
174
179
 
175
180
  - Nesting ~10 levels / ~220 nodes.
@@ -170,6 +170,11 @@ badge: compose
170
170
  | `code` | 代码快照 |
171
171
  | `pre` | 预格式文本 |
172
172
 
173
+
174
+ ## 图表示例
175
+
176
+ 玩法级图表示例(静态八柱、融合权重滑杆)见 [说明图 · compose](/garden/components/compose#ui-compose-chart-active-hours)。
177
+
173
178
  ## 限制
174
179
 
175
180
  - 嵌套约 10 层 / 约 220 节点。