@fangxinyan/lumina 0.7.0 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (236) hide show
  1. package/dist/Alert.cjs +5 -5
  2. package/dist/Alert.js +4 -4
  3. package/dist/AppShell.cjs +8 -8
  4. package/dist/AppShell.js +4 -4
  5. package/dist/AutoComplete.cjs +7 -7
  6. package/dist/AutoComplete.js +6 -6
  7. package/dist/Avatar.cjs +4 -4
  8. package/dist/Avatar.js +3 -3
  9. package/dist/Badge.cjs +4 -4
  10. package/dist/Badge.js +3 -3
  11. package/dist/Button.cjs +6 -6
  12. package/dist/Button.js +4 -4
  13. package/dist/Calendar.cjs +5 -5
  14. package/dist/Calendar.js +4 -4
  15. package/dist/Card.cjs +7 -7
  16. package/dist/Card.js +6 -6
  17. package/dist/Cascader.cjs +7 -7
  18. package/dist/Cascader.js +6 -6
  19. package/dist/{Checkbox-IHFML4FV.css → Checkbox-YQ43GFUI.css} +7 -0
  20. package/dist/Checkbox.cjs +5 -5
  21. package/dist/Checkbox.d.cts +2 -0
  22. package/dist/Checkbox.d.ts +2 -0
  23. package/dist/Checkbox.js +4 -4
  24. package/dist/Collapse.cjs +5 -5
  25. package/dist/Collapse.js +4 -4
  26. package/dist/ColorPicker.cjs +7 -7
  27. package/dist/ColorPicker.js +6 -6
  28. package/dist/CommandPalette.cjs +7 -7
  29. package/dist/CommandPalette.js +6 -6
  30. package/dist/ContextMenu.cjs +4 -4
  31. package/dist/ContextMenu.js +3 -3
  32. package/dist/DatePicker.cjs +9 -9
  33. package/dist/DatePicker.js +8 -8
  34. package/dist/DateTimePicker.cjs +9 -9
  35. package/dist/DateTimePicker.js +8 -8
  36. package/dist/Divider.cjs +4 -4
  37. package/dist/Divider.js +3 -3
  38. package/dist/Drawer.cjs +5 -5
  39. package/dist/Drawer.js +4 -4
  40. package/dist/Empty.cjs +4 -4
  41. package/dist/Empty.js +3 -3
  42. package/dist/Form.cjs +6 -6
  43. package/dist/Form.js +3 -3
  44. package/dist/Icon.cjs +51 -51
  45. package/dist/Icon.js +3 -3
  46. package/dist/Image.cjs +9 -9
  47. package/dist/Image.js +5 -5
  48. package/dist/Input.cjs +7 -7
  49. package/dist/Input.js +5 -5
  50. package/dist/InputNumber.cjs +7 -7
  51. package/dist/InputNumber.js +6 -6
  52. package/dist/List.cjs +4 -4
  53. package/dist/List.js +3 -3
  54. package/dist/Message.cjs +8 -8
  55. package/dist/Message.js +4 -4
  56. package/dist/Modal.cjs +6 -6
  57. package/dist/Modal.js +5 -5
  58. package/dist/Pagination.cjs +9 -9
  59. package/dist/Pagination.js +8 -8
  60. package/dist/Popover.cjs +4 -4
  61. package/dist/Popover.js +3 -3
  62. package/dist/Progress.cjs +4 -4
  63. package/dist/Progress.js +3 -3
  64. package/dist/Radio.cjs +5 -5
  65. package/dist/Radio.js +3 -3
  66. package/dist/{Select-TU37MAHZ.css → Select-QPBB73KA.css} +34 -5
  67. package/dist/Select.cjs +8 -8
  68. package/dist/Select.d.cts +16 -1
  69. package/dist/Select.d.ts +16 -1
  70. package/dist/Select.js +7 -7
  71. package/dist/Skeleton.cjs +4 -4
  72. package/dist/Skeleton.js +3 -3
  73. package/dist/Slider.cjs +4 -4
  74. package/dist/Slider.js +3 -3
  75. package/dist/Spin.cjs +4 -4
  76. package/dist/Spin.js +3 -3
  77. package/dist/Splitter.cjs +4 -4
  78. package/dist/Splitter.d.cts +10 -0
  79. package/dist/Splitter.d.ts +10 -0
  80. package/dist/Splitter.js +3 -3
  81. package/dist/StatusBar.cjs +5 -5
  82. package/dist/StatusBar.js +3 -3
  83. package/dist/Surface.cjs +5 -5
  84. package/dist/Surface.js +3 -3
  85. package/dist/{Switch-TATU3LPB.css → Switch-3JV3LCPX.css} +3 -0
  86. package/dist/Switch.cjs +4 -4
  87. package/dist/Switch.d.cts +2 -0
  88. package/dist/Switch.d.ts +2 -0
  89. package/dist/Switch.js +3 -3
  90. package/dist/{Table-W4HPZ7MZ.css → Table-KB6EEBDJ.css} +28 -1
  91. package/dist/Table.cjs +12 -12
  92. package/dist/Table.d.cts +7 -1
  93. package/dist/Table.d.ts +7 -1
  94. package/dist/Table.js +11 -11
  95. package/dist/TablePro.cjs +13 -13
  96. package/dist/TablePro.js +12 -12
  97. package/dist/{Tabs-A3IG6UZ6.css → Tabs-FB2AMBWL.css} +14 -0
  98. package/dist/Tabs.cjs +4 -4
  99. package/dist/Tabs.d.cts +6 -0
  100. package/dist/Tabs.d.ts +6 -0
  101. package/dist/Tabs.js +3 -3
  102. package/dist/Tag.cjs +5 -5
  103. package/dist/Tag.js +4 -4
  104. package/dist/Textarea.cjs +6 -6
  105. package/dist/Textarea.js +4 -4
  106. package/dist/Theme.cjs +19 -19
  107. package/dist/Theme.js +1 -1
  108. package/dist/ThemePanel.cjs +14 -14
  109. package/dist/ThemePanel.js +11 -11
  110. package/dist/TimePicker.cjs +8 -8
  111. package/dist/TimePicker.js +7 -7
  112. package/dist/Timeline.cjs +5 -5
  113. package/dist/Timeline.js +4 -4
  114. package/dist/Tooltip.cjs +4 -4
  115. package/dist/Tooltip.js +3 -3
  116. package/dist/Typography.cjs +9 -9
  117. package/dist/Typography.js +4 -4
  118. package/dist/{chunk-LQMOYVQF.js → chunk-2BM65ITV.js} +2 -2
  119. package/dist/{chunk-UQI4R32R.js → chunk-2COQYOVG.js} +4 -4
  120. package/dist/{chunk-WMZV7PNO.js → chunk-2NECDEAJ.js} +7 -3
  121. package/dist/{chunk-I4YPBAQ5.js → chunk-2NXLVPF4.js} +3 -3
  122. package/dist/{chunk-7QAVPVMW.js → chunk-2V6RQQRI.js} +4 -4
  123. package/dist/{chunk-ZEYK37VW.cjs → chunk-2XDLXAZT.cjs} +6 -6
  124. package/dist/{chunk-TYZ6L7E6.cjs → chunk-33YRXHVK.cjs} +6 -6
  125. package/dist/{chunk-3EMWDDWK.cjs → chunk-3D5RJA7R.cjs} +16 -16
  126. package/dist/{chunk-VX6MZO4K.cjs → chunk-3J7HOTD6.cjs} +6 -6
  127. package/dist/{chunk-ARUN2DMD.js → chunk-427CDZDU.js} +2 -2
  128. package/dist/chunk-4JANYBXO.js +100 -0
  129. package/dist/{chunk-ZHVR4YPB.cjs → chunk-4LYJRFD2.cjs} +3 -3
  130. package/dist/{chunk-LG62MPMU.cjs → chunk-4MZW2KBN.cjs} +11 -11
  131. package/dist/{chunk-F7WUCOBP.cjs → chunk-4ZSFMWLF.cjs} +24 -24
  132. package/dist/{chunk-FMUHLIHB.cjs → chunk-53I3PWRH.cjs} +3 -3
  133. package/dist/{chunk-JHM7MN3G.js → chunk-563SQXH7.js} +3 -3
  134. package/dist/{chunk-DRDDQCDD.js → chunk-5HLNFDV4.js} +1 -1
  135. package/dist/{chunk-2HIN5NFM.js → chunk-5VLANZAJ.js} +3 -3
  136. package/dist/{chunk-ALAG4ZUH.js → chunk-6OVWY63D.js} +2 -2
  137. package/dist/{chunk-434Y2JVW.cjs → chunk-6WEXRX7K.cjs} +7 -7
  138. package/dist/{chunk-MCDW3VKZ.cjs → chunk-76CTKBXD.cjs} +3 -3
  139. package/dist/{chunk-VA3JWOAB.cjs → chunk-7IWUBBYX.cjs} +15 -15
  140. package/dist/{chunk-ENFLP7SN.cjs → chunk-7KA5D37Z.cjs} +40 -30
  141. package/dist/{chunk-Y2MT6PI6.js → chunk-7NKNQRK6.js} +4 -4
  142. package/dist/{chunk-EAUB6FEN.js → chunk-7PUYEPLK.js} +4 -4
  143. package/dist/{chunk-7VLAHOA7.cjs → chunk-7ZMUCSCJ.cjs} +8 -8
  144. package/dist/{chunk-RPO7657K.js → chunk-A34P5CU7.js} +3 -3
  145. package/dist/{chunk-FKCPSVC4.cjs → chunk-ADPXWCTK.cjs} +9 -9
  146. package/dist/{chunk-QDCPVI3S.cjs → chunk-AE5XWZ24.cjs} +14 -14
  147. package/dist/{chunk-XZXY3XCL.cjs → chunk-AEY76EAH.cjs} +55 -38
  148. package/dist/{chunk-3EHJ5QI3.js → chunk-AL2PYVVP.js} +99 -49
  149. package/dist/{chunk-PIJV2FHO.cjs → chunk-AQN3PD24.cjs} +30 -30
  150. package/dist/{chunk-RMGFRAZ2.cjs → chunk-AR3MT2ZT.cjs} +10 -10
  151. package/dist/{chunk-3F424R5P.js → chunk-AXZNZ2IH.js} +3 -3
  152. package/dist/{chunk-HVPUGYBY.js → chunk-BDPJ2BPN.js} +4 -4
  153. package/dist/{chunk-HQFKXTX6.js → chunk-BOBT7JUB.js} +2 -2
  154. package/dist/{chunk-O6G3F5L4.js → chunk-CFKAKB2B.js} +5 -5
  155. package/dist/{chunk-U5YYOOLC.cjs → chunk-CLJLBFNU.cjs} +4 -4
  156. package/dist/{chunk-HYHBCHFM.cjs → chunk-CNV7R2OZ.cjs} +7 -7
  157. package/dist/{chunk-ULTDRMGN.js → chunk-CPVUDSIY.js} +6 -6
  158. package/dist/{chunk-QDY56GGO.js → chunk-D2N7OXMK.js} +2 -2
  159. package/dist/{chunk-LJVQQEME.js → chunk-DQMG4XPX.js} +6 -6
  160. package/dist/{chunk-STQDKMS5.cjs → chunk-GFGMGJ5A.cjs} +13 -13
  161. package/dist/{chunk-BKW5PXEO.js → chunk-GMFOY7RD.js} +5 -5
  162. package/dist/{chunk-GTFP7HA3.cjs → chunk-GW77XQEF.cjs} +15 -15
  163. package/dist/{chunk-DU2DSERH.js → chunk-HAIWLYLR.js} +3 -3
  164. package/dist/{chunk-VVRXNGYL.cjs → chunk-HJGPUE67.cjs} +9 -9
  165. package/dist/{chunk-JINKQT6H.cjs → chunk-HMN65CDW.cjs} +10 -6
  166. package/dist/{chunk-MUZQWIMR.cjs → chunk-I2YL5XE4.cjs} +18 -18
  167. package/dist/{chunk-EE5KXDRK.cjs → chunk-I4GJZLJU.cjs} +6 -6
  168. package/dist/{chunk-QDMFXRPI.js → chunk-INCTDROH.js} +2 -2
  169. package/dist/{chunk-2BIOTRQC.js → chunk-ISK2RW7F.js} +2 -2
  170. package/dist/{chunk-OLYSSZHP.js → chunk-IU6PLLEL.js} +10 -10
  171. package/dist/{chunk-LOWTSOWT.js → chunk-J7D5CQDK.js} +34 -7
  172. package/dist/{chunk-EA3NZBCZ.js → chunk-JMYUO7V7.js} +20 -10
  173. package/dist/{chunk-D7YSY5RZ.cjs → chunk-K3KHQ77L.cjs} +111 -61
  174. package/dist/{chunk-AURYNA6G.js → chunk-KFCWDFBW.js} +2 -2
  175. package/dist/{chunk-KCDOC3HS.cjs → chunk-KPBZKHCS.cjs} +8 -6
  176. package/dist/{chunk-PQOBBASY.js → chunk-L2NEYHYG.js} +2 -2
  177. package/dist/{chunk-VQEMMJHC.js → chunk-LACXN5CI.js} +2 -2
  178. package/dist/{chunk-T4RR6NVU.cjs → chunk-M3JYP3V4.cjs} +7 -7
  179. package/dist/{chunk-FY73C7JK.js → chunk-MEBAE7DB.js} +4 -4
  180. package/dist/{chunk-5AXNUX3J.js → chunk-MFJHI472.js} +2 -2
  181. package/dist/{chunk-4SKHRPDH.js → chunk-MKVONDTB.js} +6 -6
  182. package/dist/{chunk-U7VEPMCX.cjs → chunk-MV56FOAD.cjs} +35 -8
  183. package/dist/{chunk-LEDESWNL.js → chunk-O6PRE6MZ.js} +5 -3
  184. package/dist/{chunk-EUTK2ZRJ.cjs → chunk-OBNGHJ3N.cjs} +3 -3
  185. package/dist/{chunk-62VV5COT.js → chunk-OGMI3TO5.js} +3 -3
  186. package/dist/{chunk-YAYSXZZZ.cjs → chunk-PYCAGTO7.cjs} +3 -3
  187. package/dist/{chunk-6DKPJ5LV.cjs → chunk-QI6BJJXM.cjs} +6 -6
  188. package/dist/{chunk-Y22PTPA7.js → chunk-QK3E6FAQ.js} +5 -5
  189. package/dist/{chunk-KATJAJUU.js → chunk-QSLXUNLM.js} +6 -4
  190. package/dist/{chunk-E66PSVBU.cjs → chunk-QTMI4ZA4.cjs} +5 -5
  191. package/dist/{chunk-LDX6Q6RK.cjs → chunk-RA5BULQ3.cjs} +3 -3
  192. package/dist/{chunk-BIPOXOHP.cjs → chunk-RWM44VCZ.cjs} +9 -9
  193. package/dist/{chunk-JKUXA3U6.cjs → chunk-RXITGNPX.cjs} +5 -5
  194. package/dist/{chunk-YPMQC5HX.js → chunk-RYF5ADJW.js} +3 -3
  195. package/dist/{chunk-SXLRWYQQ.js → chunk-SXT672KF.js} +5 -5
  196. package/dist/{chunk-U3SG2YT2.js → chunk-TALNKJQ2.js} +3 -3
  197. package/dist/{chunk-3IZZBM56.js → chunk-TNQJA5JF.js} +3 -3
  198. package/dist/{chunk-Q565GDVK.cjs → chunk-TPFY5SKB.cjs} +9 -9
  199. package/dist/{chunk-RERMZNF3.cjs → chunk-TTRU4TLQ.cjs} +3 -3
  200. package/dist/{chunk-UE4HFGJ6.js → chunk-TUXF2G2O.js} +4 -4
  201. package/dist/{chunk-3DKFS44V.js → chunk-TY5LOU3A.js} +3 -3
  202. package/dist/{chunk-6RQJXSWN.js → chunk-U7V2FOIM.js} +3 -3
  203. package/dist/{chunk-BJDQVVCG.js → chunk-UCE53RYR.js} +5 -5
  204. package/dist/{chunk-WROF2PVG.cjs → chunk-UQF7E32V.cjs} +6 -4
  205. package/dist/{chunk-NRJXZPZR.cjs → chunk-V6BLBIY6.cjs} +17 -17
  206. package/dist/{chunk-2AUXUZ3Z.cjs → chunk-VDVKY2IX.cjs} +4 -4
  207. package/dist/{chunk-YKHIIC7M.js → chunk-VLQ6XIAL.js} +2 -2
  208. package/dist/{chunk-GFKWSDD6.cjs → chunk-VNP5WB6M.cjs} +6 -6
  209. package/dist/{chunk-56I6ZKGU.cjs → chunk-VTN6YLRJ.cjs} +11 -11
  210. package/dist/{chunk-YBGMTQ2V.js → chunk-XFJTJVWD.js} +3 -3
  211. package/dist/{chunk-77HU7JWK.cjs → chunk-XHKSUKKL.cjs} +6 -6
  212. package/dist/{chunk-K5HGHOG7.js → chunk-Y3WFWA52.js} +2 -2
  213. package/dist/{chunk-QNQSNVCU.cjs → chunk-YU4LBDBD.cjs} +6 -6
  214. package/dist/{chunk-QYPA77OI.cjs → chunk-Z6AG7O4B.cjs} +3 -3
  215. package/dist/{chunk-AUO2YYHB.js → chunk-Z7GKR4LL.js} +4 -4
  216. package/dist/{chunk-ZYIE3BH7.cjs → chunk-ZBRFGD3I.cjs} +3 -3
  217. package/dist/{chunk-5CZA33BK.cjs → chunk-ZCAYS4KR.cjs} +8 -8
  218. package/dist/{chunk-Q5HLC56A.cjs → chunk-ZGZLEJKA.cjs} +4 -4
  219. package/dist/{chunk-YUJ7Z6N2.cjs → chunk-ZT7ZWAF2.cjs} +13 -13
  220. package/dist/index.cjs +189 -189
  221. package/dist/index.d.cts +3 -3
  222. package/dist/index.d.ts +3 -3
  223. package/dist/index.js +52 -52
  224. package/dist/styles.css +100 -20
  225. package/dist/{tokens-CEJVVA3G.css → tokens-223RYVVS.css} +14 -14
  226. package/dist/tokens.css +14 -14
  227. package/docs/llms/checkbox.md +22 -5
  228. package/docs/llms/drawer.md +8 -1
  229. package/docs/llms/select.md +50 -0
  230. package/docs/llms/splitter.md +12 -1
  231. package/docs/llms/switch.md +22 -5
  232. package/docs/llms/tablepro.md +23 -1
  233. package/docs/llms/tabs.md +21 -0
  234. package/docs/llms.md +1 -1
  235. package/package.json +1 -1
  236. package/dist/chunk-RAK6CENJ.js +0 -83
@@ -27,6 +27,23 @@ multiple + Tag 形式呈现已选项。
27
27
  <Select multiple clearable value={tags} onChange={setTags} options={...} />
28
28
  ```
29
29
 
30
+ ### 数量上限 / 分类限选
31
+
32
+ maxCount 限制总数;getOptionDisabled 可读取当前选择,实现“一类最多选一个”。
33
+
34
+ ```tsx
35
+ <Select
36
+ multiple
37
+ maxCount={2}
38
+ value={values}
39
+ onChange={setValues}
40
+ getOptionDisabled={(option, selectedValues) =>
41
+ hasOtherSelectionInCategory(option, selectedValues)
42
+ }
43
+ options={groupedOptions}
44
+ />
45
+ ```
46
+
30
47
  ### 搜索过滤
31
48
 
32
49
  searchable + clearable + 选项 icon/description。icon 支持 IconName 或 ReactNode。
@@ -70,6 +87,26 @@ optionRender 承载多行菜单内容;selectedRender 提供适合固定高度
70
87
  />
71
88
  ```
72
89
 
90
+ ### 置顶分组与额外操作
91
+
92
+ 分组设置 pinned 后会稳定提升到菜单顶部;optionExtraRender 提供不会触发选中的独立尾部区域。收藏仅是业务侧示例。
93
+
94
+ ```tsx
95
+ const groups = [
96
+ { label: "其他服务", options: otherOptions },
97
+ { label: "已收藏", pinned: true, options: favoriteOptions },
98
+ ];
99
+
100
+ <Select
101
+ value={service}
102
+ onChange={setService}
103
+ options={groups}
104
+ optionExtraRender={(option) => (
105
+ <IconButton icon={isFavorite(option) ? "starFilled" : "star"} />
106
+ )}
107
+ />
108
+ ```
109
+
73
110
  ### 分组
74
111
 
75
112
  options 接受 { label, options } 表示分组。
@@ -108,6 +145,8 @@ loading 时显示 spinner,emptyContent 自定义空态。
108
145
  | placeholder | `string` | `"请选择…"` | 空选择时的提示文本 |
109
146
  | multiple | `boolean` | `false` | 多选 |
110
147
  | maxTagCount | `number` | — | 多选时显示的标签数(超出折叠 +N) |
148
+ | maxCount | `number` | — | 多选允许的最大选择数;达到上限后禁用未选项 |
149
+ | getOptionDisabled | `(option, selectedValues) => boolean` | — | 基于候选项和当前选择动态判断禁用状态 |
111
150
  | searchable | `boolean` | `false` | 可搜索 |
112
151
  | showSearch | `boolean` | `false` | searchable 的等价别名 |
113
152
  | filterOption | `(input, option) => boolean` | — | 自定义过滤 |
@@ -121,6 +160,7 @@ loading 时显示 spinner,emptyContent 自定义空态。
121
160
  | loading | `boolean` | `false` | 加载态 |
122
161
  | emptyContent | `ReactNode` | — | 空态文案 |
123
162
  | optionRender | `(option, info) => ReactNode` | — | 自定义菜单内完整选项内容,并获得 selected / active / index 状态 |
163
+ | optionExtraRender | `(option, info) => ReactNode` | — | 自定义选项尾部的独立内容或操作,不触发选中;info 含 disabled / groupPinned |
124
164
  | selectedRender | `(option, info) => ReactNode` | — | 自定义触发器中的紧凑已选内容;单选和多选标签均支持 |
125
165
  | listHeight | `number` | `260` | 菜单选项滚动区域最大高度 |
126
166
  | popupStyle | `CSSProperties` | — | Portal 菜单内联样式,可覆盖宽度或高度 |
@@ -139,8 +179,18 @@ loading 时显示 spinner,emptyContent 自定义空态。
139
179
  | ariaLabel | `string` | — | 复杂选项或 optionRender 的独立可访问名称 |
140
180
  | icon | `IconName | ReactNode` | — | 前置图标,可传内置图标名或自定义节点 |
141
181
  | description | `ReactNode` | — | 次要描述 |
182
+ | extra | `ReactNode` | — | 选项尾部的静态独立内容或操作;optionExtraRender 存在时由其覆盖 |
142
183
  | disabled | `boolean` | `false` | 禁用项 |
143
184
 
144
185
 
186
+ **SelectOptionGroup**
187
+
188
+ | Prop | 类型 | 默认 | 说明 |
189
+ | --- | --- | --- | --- |
190
+ | label \* | `ReactNode` | — | 分组标题 |
191
+ | options \* | `SelectOption<T>[]` | — | 分组内选项 |
192
+ | pinned | `boolean` | `false` | 稳定提升到菜单顶部,其他项目保持原始顺序 |
193
+
194
+
145
195
  ---
146
196
  [← 回到索引](../llms.md)
@@ -13,7 +13,15 @@ import { Splitter } from "@fangxinyan/lumina";
13
13
  ### 水平分栏
14
14
 
15
15
  ```tsx
16
- <Splitter defaultSize={200} min={120} max={360}>
16
+ <Splitter
17
+ defaultSize={200}
18
+ min={120}
19
+ max={360}
20
+ firstPaneClassName="workspace-sidebar-pane"
21
+ firstPaneStyle={{ overflow: "hidden" }}
22
+ secondPaneClassName="workspace-main-pane"
23
+ handle={<span aria-hidden>⋮</span>}
24
+ >
17
25
  <SidePanel />
18
26
  <MainPanel />
19
27
  </Splitter>
@@ -64,6 +72,9 @@ const [w, setW] = useState(220);
64
72
  | step | `number` | `16` | 方向键步长 (px) |
65
73
  | secondMin | `number` | `24` | 第二面板保留的最小尺寸 |
66
74
  | storageKey | `string` | — | 持久化尺寸的本地存储键 |
75
+ | firstPaneClassName / firstPaneStyle | `string / CSSProperties` | — | 第一个面板的 class 与内联样式 |
76
+ | secondPaneClassName / secondPaneStyle | `string / CSSProperties` | — | 第二个面板的 class 与内联样式 |
77
+ | handle | `ReactNode` | — | 正式的分隔手柄内容槽;null 隐藏默认握柄 |
67
78
  | handleProps | `HTMLAttributes<HTMLDivElement>` | — | 分隔手柄原生属性与 aria-label |
68
79
  | children \* | `[ReactNode, ReactNode]` | — | 必须恰好两个子节点 |
69
80
 
@@ -16,15 +16,31 @@ import { Switch } from "@fangxinyan/lumina";
16
16
  <Switch checked={v} onChange={setV} label="开启通知" />
17
17
  ```
18
18
 
19
- ### 原生表单
19
+ ### Lumina 表单校验
20
20
 
21
- 开启后按 name / value 参与原生表单提交,required 可交给浏览器校验。
21
+ 通过 Form.Item 与 message 提供一致的组件反馈,不再触发浏览器原生 required 气泡。name / value 仍会透传到真实 checkbox。
22
22
 
23
23
  ```tsx
24
- <form onSubmit={(event) => event.preventDefault()}>
25
- <Switch name="notifications" value="enabled" required label="开启通知" />
24
+ <Form
25
+ layout="inline"
26
+ onFinish={() => message.success({ key: "switch-validation", content: "通知已开启" })}
27
+ onFinishFailed={() => message.warning({ key: "switch-validation", content: "请先开启通知" })}
28
+ >
29
+ <Form.Item
30
+ name="notifications"
31
+ valuePropName="checked"
32
+ rules={[{
33
+ required: true,
34
+ message: "请开启通知",
35
+ validator: (_rule, checked) => checked
36
+ ? Promise.resolve()
37
+ : Promise.reject(new Error("请开启通知")),
38
+ }]}
39
+ >
40
+ <Switch name="notifications" value="enabled" label="开启通知" />
41
+ </Form.Item>
26
42
  <Button type="submit">验证提交</Button>
27
- </form>
43
+ </Form>
28
44
  ```
29
45
 
30
46
  ### 尺寸
@@ -66,6 +82,7 @@ checkedChildren / unCheckedChildren 在轨道内显示简短文字(如 ON/OFF)
66
82
  | size | `"sm" | "md"` | `"md"` | 尺寸 |
67
83
  | name / value | `string` | — | 原生表单字段名与开启时提交的值 |
68
84
  | required / form | `boolean / string` | — | 原生必填约束与关联 form id |
85
+ | invalid | `boolean` | `false` | 错误态,可由 Form.Item 自动注入 |
69
86
  | disabled | `boolean` | `false` | 禁用 |
70
87
 
71
88
 
@@ -25,6 +25,27 @@ import { TablePro } from "@fangxinyan/lumina";
25
25
  />
26
26
  ```
27
27
 
28
+ ### 当前行高亮 / 横向空态
29
+
30
+ activeRowKey 只表达当前上下文,不会勾选行;横向滚动表格的 empty 会始终居中在可视区域。
31
+
32
+ ```tsx
33
+ <TablePro
34
+ rowKey="id"
35
+ activeRowKey={activeRowKey}
36
+ rowClassName={(row) => row.status === "离线" ? "offline-row" : undefined}
37
+ onRowClick={(row) => setActiveRowKey(row.id)}
38
+ data={rows}
39
+ columns={columns}
40
+ />
41
+
42
+ <TablePro
43
+ data={[]}
44
+ scroll={{ x: 1200 }}
45
+ empty={<Tag>当前筛选没有结果</Tag>}
46
+ />
47
+ ```
48
+
28
49
  ### 卡片行分页
29
50
 
30
51
  variant='cards' 与内置 pagination 共用 TablePro 容器背景,分页区不会单独变成另一块底色。
@@ -59,7 +80,8 @@ TablePro 直接透传 expandable 到 Table。
59
80
 
60
81
  | Prop | 类型 | 默认 | 说明 |
61
82
  | --- | --- | --- | --- |
62
- | ... | `TableProps` | — | 继承自 Table 全部 props (包括新的 pagination / scroll / rowSelection / expandable / filters) |
83
+ | ... | `TableProps` | — | 继承自 Table 全部 props (包括 pagination / scroll / rowSelection / expandable / filters) |
84
+ | activeRowKey / rowClassName | `RowKey / string | (row, index) => string` | — | 纯高亮当前行,并支持固定或按行计算的业务类名 |
63
85
  | toolbar | `ReactNode` | — | 工具栏内容 |
64
86
  | actions | `ReactNode` | — | 工具栏右侧操作 |
65
87
  | footer | `ReactNode` | — | 底部 (可选,传了会渲染在分页下方) |
package/docs/llms/tabs.md CHANGED
@@ -25,6 +25,24 @@ import { Tabs } from "@fangxinyan/lumina";
25
25
  <Tabs variant="line" items={[...]} />
26
26
  ```
27
27
 
28
+ ### 满高布局 / 正文独立滚动
29
+
30
+ fill 让 Tabs 占满父容器,标签条保持固定,只有 tabs-content 滚动;两个 className 可定向接入业务布局。
31
+
32
+ ```tsx
33
+ <div style={{ height: 260 }}>
34
+ <Tabs
35
+ fill
36
+ tabBarClassName="workspace-tabs-bar"
37
+ contentClassName="workspace-tabs-content"
38
+ items={[
39
+ { key: "general", label: "通用", content: <LongSettings /> },
40
+ { key: "advanced", label: "高级", content: <LongSettings /> },
41
+ ]}
42
+ />
43
+ </div>
44
+ ```
45
+
28
46
  ### 居中对齐
29
47
 
30
48
  centered 让标签条在容器中水平居中。
@@ -44,6 +62,9 @@ centered 让标签条在容器中水平居中。
44
62
  | onChange | `(key: string) => void` | — | 切换 |
45
63
  | variant | `"line" | "pill" | "segmented"` | `"line"` | 样式 |
46
64
  | centered | `boolean` | `false` | 标签条居中对齐 |
65
+ | tabBarClassName | `string` | — | 标签条容器的附加类名 |
66
+ | contentClassName | `string` | — | 正文容器的附加类名 |
67
+ | fill | `boolean` | `false` | 占满父容器,并让正文区域独立滚动 |
47
68
 
48
69
 
49
70
  ---
package/docs/llms.md CHANGED
@@ -3,7 +3,7 @@
3
3
  > 拟态风格的 React 18 组件库,目标是 Electron 桌面应用。**写给 AI 编程助手**的按需文档 —— 每个组件单独一个 `.md`,避免一次性读取全部。示例源自 playground 的 demo,可直接复制运行。
4
4
 
5
5
  - **包名**: `@fangxinyan/lumina`
6
- - **版本**: `0.7.0`
6
+ - **版本**: `0.9.0`
7
7
  - **React 最低版本**: 18
8
8
  - **环境**: 带打包器的 React 工程(Vite / Next.js / Webpack / Remix / Electron + Vite 等)
9
9
  - **零运行时依赖**: 只依赖 `react` / `react-dom` (peer deps)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fangxinyan/lumina",
3
- "version": "0.7.0",
3
+ "version": "0.9.0",
4
4
  "description": "Lumina — Neumorphic component library for Electron & React apps",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -1,83 +0,0 @@
1
- import { withComponentTheme } from './chunk-DRDDQCDD.js';
2
- import './tokens-CEJVVA3G.css';
3
- import './shared-NJHRNLRH.css';
4
- import './Tabs-A3IG6UZ6.css';
5
- import * as React from 'react';
6
- import { jsxs, jsx } from 'react/jsx-runtime';
7
-
8
- var getFirstEnabledKey = (items) => items.find((item) => !item.disabled)?.key;
9
- var TabsBase = React.forwardRef(({
10
- items,
11
- activeKey,
12
- defaultActiveKey,
13
- onChange,
14
- variant = "line",
15
- centered,
16
- className = "",
17
- ...rest
18
- }, ref) => {
19
- const baseId = React.useId();
20
- const tabRefs = React.useRef(/* @__PURE__ */ new Map());
21
- const [inner, setInner] = React.useState(defaultActiveKey ?? getFirstEnabledKey(items));
22
- const isControlled = activeKey !== void 0;
23
- const requested = isControlled ? activeKey : inner;
24
- const current = items.some((item) => item.key === requested && !item.disabled) ? requested : getFirstEnabledKey(items);
25
- const select = (k) => {
26
- if (items.find((item) => item.key === k)?.disabled) return;
27
- if (!isControlled) setInner(k);
28
- onChange?.(k);
29
- };
30
- const handleTabKeyDown = (event) => {
31
- const enabled = items.filter((item) => !item.disabled);
32
- const index = enabled.findIndex((item) => item.key === current);
33
- let target;
34
- if (event.key === "ArrowRight") target = enabled[(index + 1) % enabled.length];
35
- if (event.key === "ArrowLeft") target = enabled[(index - 1 + enabled.length) % enabled.length];
36
- if (event.key === "Home") target = enabled[0];
37
- if (event.key === "End") target = enabled[enabled.length - 1];
38
- if (!target) return;
39
- event.preventDefault();
40
- tabRefs.current.get(target.key)?.focus();
41
- select(target.key);
42
- };
43
- const active = items.find((i) => i.key === current);
44
- const activeIndex = items.findIndex((item) => item.key === current);
45
- return /* @__PURE__ */ jsxs("div", { ref, className: `tabs ${variant} ${centered ? "centered" : ""} ${className}`, ...rest, children: [
46
- /* @__PURE__ */ jsx("div", { className: "tabs-nav", role: "tablist", children: items.map((it, index) => /* @__PURE__ */ jsx(
47
- "button",
48
- {
49
- ref: (node) => {
50
- if (node) tabRefs.current.set(it.key, node);
51
- else tabRefs.current.delete(it.key);
52
- },
53
- type: "button",
54
- role: "tab",
55
- id: `${baseId}-tab-${index}`,
56
- "aria-selected": current === it.key,
57
- "aria-controls": it.content !== void 0 ? `${baseId}-panel-${index}` : void 0,
58
- tabIndex: current === it.key ? 0 : -1,
59
- disabled: it.disabled,
60
- className: `tab ${current === it.key ? "active" : ""}`,
61
- onClick: () => select(it.key),
62
- onKeyDown: handleTabKeyDown,
63
- children: it.label
64
- },
65
- it.key
66
- )) }),
67
- active?.content !== void 0 && /* @__PURE__ */ jsx(
68
- "div",
69
- {
70
- id: `${baseId}-panel-${activeIndex}`,
71
- className: "tabs-content",
72
- role: "tabpanel",
73
- "aria-labelledby": `${baseId}-tab-${activeIndex}`,
74
- tabIndex: 0,
75
- children: active.content
76
- }
77
- )
78
- ] });
79
- });
80
- TabsBase.displayName = "Tabs";
81
- var Tabs = withComponentTheme(TabsBase, "Tabs", "tabs");
82
-
83
- export { Tabs };