@fangxinyan/lumina 0.6.3 → 0.6.5

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 (255) hide show
  1. package/dist/{Alert-QBKIDY5H.css → Alert-HVPI6L4V.css} +2 -2
  2. package/dist/Alert.cjs +3 -3
  3. package/dist/Alert.js +2 -2
  4. package/dist/{AppShell-RCALXUCZ.css → AppShell-FZCD4C56.css} +4 -4
  5. package/dist/AppShell.cjs +5 -5
  6. package/dist/AppShell.js +1 -1
  7. package/dist/{AutoComplete-P5KZMZO5.css → AutoComplete-4YZBMW4E.css} +2 -2
  8. package/dist/AutoComplete.cjs +5 -5
  9. package/dist/AutoComplete.js +4 -4
  10. package/dist/{Avatar-R5A4AFKZ.css → Avatar-TNPOHVY5.css} +1 -1
  11. package/dist/Avatar.cjs +2 -2
  12. package/dist/Avatar.js +1 -1
  13. package/dist/Badge.cjs +2 -2
  14. package/dist/Badge.js +1 -1
  15. package/dist/{Button-4Z3Q6KII.css → Button-TUMZUQLI.css} +11 -11
  16. package/dist/Button.cjs +3 -3
  17. package/dist/Button.js +2 -2
  18. package/dist/{Calendar-LHZELUDL.css → Calendar-RUTPKREW.css} +4 -4
  19. package/dist/Calendar.cjs +3 -3
  20. package/dist/Calendar.js +2 -2
  21. package/dist/{Card-6RMVIHWX.css → Card-MA6SV7D5.css} +6 -6
  22. package/dist/Card.cjs +2 -2
  23. package/dist/Card.js +1 -1
  24. package/dist/{Cascader-3BLLA7EN.css → Cascader-ANEQUPMI.css} +8 -8
  25. package/dist/Cascader.cjs +5 -5
  26. package/dist/Cascader.js +4 -4
  27. package/dist/{Checkbox-U5EUDSYS.css → Checkbox-EDNPZRIP.css} +3 -3
  28. package/dist/Checkbox.cjs +3 -3
  29. package/dist/Checkbox.js +2 -2
  30. package/dist/{Collapse-66U5YJFY.css → Collapse-UNBHEPYP.css} +2 -2
  31. package/dist/Collapse.cjs +3 -3
  32. package/dist/Collapse.js +2 -2
  33. package/dist/{ColorPicker-SDDQGHCM.css → ColorPicker-LPG6QPYF.css} +7 -7
  34. package/dist/ColorPicker.cjs +2 -2
  35. package/dist/ColorPicker.js +1 -1
  36. package/dist/{CommandPalette-T45DBMPY.css → CommandPalette-RTKWNH2D.css} +3 -3
  37. package/dist/CommandPalette.cjs +5 -5
  38. package/dist/CommandPalette.js +4 -4
  39. package/dist/{ContextMenu-FKW6CQW4.css → ContextMenu-WRR2SSWL.css} +3 -3
  40. package/dist/ContextMenu.cjs +2 -2
  41. package/dist/ContextMenu.js +1 -1
  42. package/dist/{Divider-OEE4Q2KS.css → Divider-RPQCVH3J.css} +2 -2
  43. package/dist/Divider.cjs +2 -2
  44. package/dist/Divider.js +1 -1
  45. package/dist/{Drawer-IPGB4CXH.css → Drawer-7N3URAJ6.css} +8 -5
  46. package/dist/Drawer.cjs +3 -3
  47. package/dist/Drawer.js +2 -2
  48. package/dist/{Empty-DC2LPORC.css → Empty-CZTRZMZQ.css} +1 -1
  49. package/dist/Empty.cjs +2 -2
  50. package/dist/Empty.js +1 -1
  51. package/dist/{Form-5GRVZNDO.css → Form-NGCQWTMZ.css} +1 -1
  52. package/dist/Form.cjs +4 -4
  53. package/dist/Form.js +1 -1
  54. package/dist/Icon.cjs +49 -49
  55. package/dist/Icon.js +1 -1
  56. package/dist/{Image-MRYQCRQ5.css → Image-SGSRTHQX.css} +5 -5
  57. package/dist/Image.cjs +6 -6
  58. package/dist/Image.js +2 -2
  59. package/dist/{Input-HUBJ55OH.css → Input-7GDPGP3E.css} +12 -12
  60. package/dist/Input.cjs +5 -5
  61. package/dist/Input.js +3 -3
  62. package/dist/InputNumber.cjs +5 -5
  63. package/dist/InputNumber.js +4 -4
  64. package/dist/{List-W5BW4D2P.css → List-LSMU5QAC.css} +3 -3
  65. package/dist/List.cjs +2 -2
  66. package/dist/List.js +1 -1
  67. package/dist/{Message-2MZ3LFPU.css → Message-H222YGR6.css} +1 -1
  68. package/dist/Message.cjs +6 -6
  69. package/dist/Message.js +2 -2
  70. package/dist/{Modal-2QNDW4SO.css → Modal-MCFDYVUQ.css} +3 -3
  71. package/dist/Modal.cjs +4 -4
  72. package/dist/Modal.js +3 -3
  73. package/dist/{Pagination-YIRYJUXP.css → Pagination-YSZSNFHG.css} +5 -5
  74. package/dist/Pagination.cjs +7 -7
  75. package/dist/Pagination.js +6 -6
  76. package/dist/{Popover-DVGQGWX6.css → Popover-Y3LDCJPW.css} +1 -1
  77. package/dist/Popover.cjs +2 -2
  78. package/dist/Popover.js +1 -1
  79. package/dist/{Progress-CHV7DN6Y.css → Progress-CZNXCYGW.css} +1 -1
  80. package/dist/Progress.cjs +2 -2
  81. package/dist/Progress.js +1 -1
  82. package/dist/{Radio-GVFDPAZM.css → Radio-IQKASYDF.css} +4 -4
  83. package/dist/Radio.cjs +3 -3
  84. package/dist/Radio.js +1 -1
  85. package/dist/{Select-Z5VYPEEY.css → Select-YZ2NUJSX.css} +18 -18
  86. package/dist/Select.cjs +6 -6
  87. package/dist/Select.js +5 -5
  88. package/dist/Skeleton.cjs +2 -2
  89. package/dist/Skeleton.js +1 -1
  90. package/dist/{Slider-3JKA5EW6.css → Slider-UM2IZZBH.css} +7 -7
  91. package/dist/Slider.cjs +2 -2
  92. package/dist/Slider.js +1 -1
  93. package/dist/{Spin-3GJNMSIH.css → Spin-GONGPV4Q.css} +1 -1
  94. package/dist/Spin.cjs +2 -2
  95. package/dist/Spin.js +1 -1
  96. package/dist/Splitter.cjs +2 -2
  97. package/dist/Splitter.js +1 -1
  98. package/dist/{StatusBar-CDS2GPSI.css → StatusBar-FJKEEPXU.css} +3 -7
  99. package/dist/StatusBar.cjs +3 -3
  100. package/dist/StatusBar.js +1 -1
  101. package/dist/Surface-UDDN3DGL.css +42 -0
  102. package/dist/Surface.cjs +16 -0
  103. package/dist/Surface.d.cts +60 -0
  104. package/dist/Surface.d.ts +60 -0
  105. package/dist/Surface.js +3 -0
  106. package/dist/{Switch-36KJNDXM.css → Switch-COAQIOMH.css} +8 -5
  107. package/dist/Switch.cjs +2 -2
  108. package/dist/Switch.js +1 -1
  109. package/dist/{Table-ATJJQLKU.css → Table-IYJTPY6J.css} +16 -16
  110. package/dist/Table.cjs +9 -9
  111. package/dist/Table.js +8 -8
  112. package/dist/{TablePro-3XVHYLSL.css → TablePro-JRSBPXB5.css} +1 -1
  113. package/dist/TablePro.cjs +10 -10
  114. package/dist/TablePro.js +9 -9
  115. package/dist/{Tabs-BLSNI2T5.css → Tabs-X5U5PCPV.css} +2 -2
  116. package/dist/Tabs.cjs +2 -2
  117. package/dist/Tabs.js +1 -1
  118. package/dist/{Tag-HDYCDPFS.css → Tag-G2XWAL7A.css} +1 -1
  119. package/dist/Tag.cjs +3 -3
  120. package/dist/Tag.js +2 -2
  121. package/dist/{Textarea-YNET7IBH.css → Textarea-YHWKHIFE.css} +3 -3
  122. package/dist/Textarea.cjs +4 -4
  123. package/dist/Textarea.js +2 -2
  124. package/dist/Theme.cjs +11 -11
  125. package/dist/Theme.d.cts +5 -1
  126. package/dist/Theme.d.ts +5 -1
  127. package/dist/Theme.js +1 -1
  128. package/dist/ThemePanel-76LB3YA5.css +509 -0
  129. package/dist/ThemePanel.cjs +29 -0
  130. package/dist/ThemePanel.d.cts +80 -0
  131. package/dist/ThemePanel.d.ts +80 -0
  132. package/dist/ThemePanel.js +12 -0
  133. package/dist/{Timeline-3ZHOHPXT.css → Timeline-ZIM7QFQC.css} +1 -1
  134. package/dist/Timeline.cjs +3 -3
  135. package/dist/Timeline.js +2 -2
  136. package/dist/{Tooltip-DMKUPC24.css → Tooltip-5FSPJWLX.css} +4 -2
  137. package/dist/Tooltip.cjs +2 -2
  138. package/dist/Tooltip.d.cts +2 -0
  139. package/dist/Tooltip.d.ts +2 -0
  140. package/dist/Tooltip.js +1 -1
  141. package/dist/{Typography-NKPWTJCV.css → Typography-32QQLD4F.css} +41 -11
  142. package/dist/Typography.cjs +8 -7
  143. package/dist/Typography.d.cts +1 -1
  144. package/dist/Typography.d.ts +1 -1
  145. package/dist/Typography.js +3 -2
  146. package/dist/{chunk-DWAN57G4.js → chunk-2NT5QKEX.js} +3 -3
  147. package/dist/{chunk-6BWELOCT.js → chunk-2SCXQ7QS.js} +2 -2
  148. package/dist/{chunk-TP567B3L.cjs → chunk-2ZADGBUN.cjs} +5 -5
  149. package/dist/{chunk-CETNCRZ4.js → chunk-2ZFJTMEF.js} +4 -4
  150. package/dist/{chunk-I5WTQ5Y3.js → chunk-3YP7CBJT.js} +3 -3
  151. package/dist/{chunk-UUHFKIWP.cjs → chunk-4UKM4KAC.cjs} +2 -2
  152. package/dist/{chunk-HLFH5HWR.js → chunk-56PHETWO.js} +3 -3
  153. package/dist/{chunk-ET6DYQVZ.js → chunk-5JNDDWFZ.js} +132 -14
  154. package/dist/{chunk-MPVCYU2K.cjs → chunk-5NFSDFBB.cjs} +4 -4
  155. package/dist/{chunk-P6P4DGLF.cjs → chunk-66GXZQKL.cjs} +4 -4
  156. package/dist/{chunk-QP3VCSRY.cjs → chunk-66T76GII.cjs} +6 -6
  157. package/dist/chunk-6EOSMK34.cjs +194 -0
  158. package/dist/{chunk-WNM5RVXR.cjs → chunk-6GQPF3EI.cjs} +2 -2
  159. package/dist/{chunk-V272XR3F.cjs → chunk-6LARTGLP.cjs} +1 -1
  160. package/dist/chunk-6SPMHY54.js +191 -0
  161. package/dist/{chunk-YLIQ37KY.cjs → chunk-6XVLERA3.cjs} +2 -2
  162. package/dist/{chunk-FBYUZOZP.js → chunk-7D76MI37.js} +5 -5
  163. package/dist/{chunk-J5ZGYQZK.js → chunk-7NZ2A4MA.js} +155 -29
  164. package/dist/{chunk-KLEKKZ73.js → chunk-7ZNGHWVS.js} +1 -1
  165. package/dist/{chunk-7AG524YZ.cjs → chunk-ACQSRMLF.cjs} +5 -5
  166. package/dist/{chunk-JVUVOR6S.js → chunk-AJH2O4WC.js} +3 -3
  167. package/dist/{chunk-NTS5L4NQ.cjs → chunk-BJ6WUVEG.cjs} +4 -4
  168. package/dist/{chunk-S3VXH5L4.cjs → chunk-C24W6PTJ.cjs} +2 -2
  169. package/dist/{chunk-GMN74OEY.cjs → chunk-CBKJXKVI.cjs} +2 -2
  170. package/dist/{chunk-FWPBORRB.js → chunk-CEZ2DR4R.js} +3 -3
  171. package/dist/{chunk-SQGPSMSK.js → chunk-CNGKJYGZ.js} +3 -3
  172. package/dist/{chunk-PULGVK2I.cjs → chunk-D5PCIVID.cjs} +4 -4
  173. package/dist/{chunk-DG5VQ6BO.cjs → chunk-D64IPDUE.cjs} +4 -4
  174. package/dist/{chunk-VFFIE2VO.cjs → chunk-DYHNOYRC.cjs} +7 -7
  175. package/dist/{chunk-P6EZG2R7.cjs → chunk-DYSGXQUK.cjs} +7 -7
  176. package/dist/{chunk-H4LGWZMH.cjs → chunk-GBKUGKIY.cjs} +11 -11
  177. package/dist/{chunk-J2HZTJO6.js → chunk-GUZ2DNDC.js} +3 -3
  178. package/dist/{chunk-K6F25JXT.js → chunk-GZCU6HXD.js} +2 -2
  179. package/dist/{chunk-USQ43DJ5.js → chunk-HFUHQUPQ.js} +2 -2
  180. package/dist/{chunk-7JN6FJ55.js → chunk-HU7T64Y3.js} +2 -2
  181. package/dist/{chunk-X5GCOMC3.cjs → chunk-IDJCFYPP.cjs} +15 -15
  182. package/dist/{chunk-KD4YYIIO.cjs → chunk-IHK2FRTS.cjs} +2 -2
  183. package/dist/{chunk-Q5SZIU7Z.cjs → chunk-JFQ53MO4.cjs} +1 -1
  184. package/dist/{chunk-7PQJCLIR.js → chunk-KMG7OMOS.js} +2 -2
  185. package/dist/{chunk-2HQCUBA7.cjs → chunk-L27C5O4W.cjs} +4 -4
  186. package/dist/chunk-LFTCK2VM.cjs +1194 -0
  187. package/dist/{chunk-BVQ77VRY.js → chunk-LI4XJTEA.js} +3 -3
  188. package/dist/{chunk-45VJGBGN.js → chunk-LQLOOUS3.js} +2 -2
  189. package/dist/{chunk-PL6DRFUO.cjs → chunk-MOMLQP7B.cjs} +2 -2
  190. package/dist/{chunk-OF7JIYBY.cjs → chunk-MYHBC3HA.cjs} +2 -2
  191. package/dist/{chunk-LKK2AA7W.js → chunk-MYRLCN6V.js} +2 -2
  192. package/dist/{chunk-ZKE73UQF.cjs → chunk-N2BTMKF2.cjs} +5 -5
  193. package/dist/{chunk-6ZXQJRAT.cjs → chunk-N2COYOXE.cjs} +155 -29
  194. package/dist/{chunk-2TL37AP5.cjs → chunk-N3OLFKV5.cjs} +1 -1
  195. package/dist/{chunk-5JSDQ6QQ.cjs → chunk-NDO22RER.cjs} +2 -2
  196. package/dist/{chunk-ME5BZ2WA.js → chunk-NE7IUGMK.js} +3 -3
  197. package/dist/{chunk-F6RYCBQG.js → chunk-NFXHIO3G.js} +1 -1
  198. package/dist/chunk-NJCHFXGC.js +1170 -0
  199. package/dist/chunk-NT6CJYI3.cjs +129 -0
  200. package/dist/chunk-O43DOE7V.js +106 -0
  201. package/dist/{chunk-GNEZD7KE.cjs → chunk-O4BOBOYV.cjs} +2 -2
  202. package/dist/{chunk-XSN4TLN5.cjs → chunk-OGPDCBPD.cjs} +12 -12
  203. package/dist/{chunk-6YQTMI55.js → chunk-OHFZ7L4T.js} +2 -2
  204. package/dist/{chunk-7IYKKLV3.js → chunk-OHIFKN4E.js} +4 -4
  205. package/dist/{chunk-46VXFTEC.js → chunk-OQU3TJCF.js} +3 -3
  206. package/dist/{chunk-5TKC6IEN.js → chunk-PEJLXJQD.js} +1 -1
  207. package/dist/{chunk-HWFM4MAT.js → chunk-PKHITACT.js} +2 -2
  208. package/dist/{chunk-JCEHZ336.js → chunk-PNZJFLMY.js} +3 -3
  209. package/dist/{chunk-XRR3CYQL.js → chunk-QP7RXZES.js} +2 -2
  210. package/dist/{chunk-5MN3PMF4.cjs → chunk-QY76WTO5.cjs} +9 -9
  211. package/dist/{chunk-FGW5GJ22.cjs → chunk-R74TZKJS.cjs} +4 -4
  212. package/dist/{chunk-TGL5BGMR.js → chunk-REMJWNAT.js} +4 -4
  213. package/dist/{chunk-3YJU3D5S.cjs → chunk-RIUDYPRB.cjs} +62 -13
  214. package/dist/{chunk-SWBWZIL4.cjs → chunk-S6OKX4H7.cjs} +2 -2
  215. package/dist/{chunk-EC4WGEAJ.js → chunk-SABWUELE.js} +2 -2
  216. package/dist/{chunk-TEEFR2FD.js → chunk-SFAGHPBT.js} +62 -13
  217. package/dist/{chunk-QKQHZIF3.cjs → chunk-SG42F5VB.cjs} +2 -2
  218. package/dist/{chunk-5C2AI2SD.js → chunk-SQIWPU6V.js} +2 -2
  219. package/dist/{chunk-5DKRY67M.cjs → chunk-SYWTT5TY.cjs} +5 -5
  220. package/dist/{chunk-OBEKX4VR.js → chunk-TVUBGXWA.js} +2 -2
  221. package/dist/{chunk-7PNJI5UE.cjs → chunk-U2H4DRMV.cjs} +2 -2
  222. package/dist/{chunk-HKF2V5MM.cjs → chunk-VAXWWJJP.cjs} +9 -9
  223. package/dist/{chunk-5H5YP2TB.js → chunk-VNNQYJLT.js} +3 -3
  224. package/dist/{chunk-KGSADAOD.cjs → chunk-VSUMJX6Z.cjs} +2 -2
  225. package/dist/{chunk-K5IGFBDR.js → chunk-W5CJC7S7.js} +3 -3
  226. package/dist/{chunk-AXZ7ELMA.js → chunk-WEJKY3DF.js} +2 -2
  227. package/dist/{chunk-GIZU3H6H.js → chunk-WXWFMWWF.js} +3 -3
  228. package/dist/{chunk-UKS23N3L.js → chunk-XVP7IKLZ.js} +4 -4
  229. package/dist/{chunk-ELNT3CFO.js → chunk-Y5F7ZTBH.js} +2 -2
  230. package/dist/{chunk-QCILPZWP.js → chunk-YJEXAO2I.js} +2 -2
  231. package/dist/{chunk-7ABFUIOB.cjs → chunk-YNCDTKAE.cjs} +2 -2
  232. package/dist/{chunk-K7FV7W6U.cjs → chunk-YSCIMHOI.cjs} +5 -5
  233. package/dist/{chunk-BPOOVO5T.js → chunk-YSXD344H.js} +5 -5
  234. package/dist/{chunk-47VG2P34.js → chunk-YT5NLCRC.js} +1 -1
  235. package/dist/{chunk-R2TEDH2F.cjs → chunk-YU5JK247.cjs} +135 -17
  236. package/dist/{chunk-HZSIUOCN.cjs → chunk-YUKXNWVE.cjs} +1 -1
  237. package/dist/{chunk-65FIH5A3.js → chunk-YVTLHTG6.js} +2 -2
  238. package/dist/{chunk-GENABQYA.cjs → chunk-Z4PZ2ZHI.cjs} +2 -2
  239. package/dist/{chunk-6HMTV6P4.cjs → chunk-ZPKHGKVL.cjs} +4 -4
  240. package/dist/{chunk-AAGF7K3L.js → chunk-ZPP7LTHP.js} +3 -3
  241. package/dist/{chunk-IZOHYJUQ.cjs → chunk-ZWCDB5PP.cjs} +2 -2
  242. package/dist/index.cjs +214 -191
  243. package/dist/index.d.cts +3 -1
  244. package/dist/index.d.ts +3 -1
  245. package/dist/index.js +49 -46
  246. package/dist/styles.css +715 -175
  247. package/dist/{tokens-BIIUTPKN.css → tokens-EF34LSWI.css} +42 -17
  248. package/dist/tokens.css +42 -17
  249. package/docs/llms/surface.md +90 -0
  250. package/docs/llms/theme.md +24 -2
  251. package/docs/llms/themepanel.md +128 -0
  252. package/docs/llms/tooltip.md +1 -0
  253. package/docs/llms/typography.md +12 -2
  254. package/docs/llms.md +3 -1
  255. package/package.json +1 -1
@@ -0,0 +1,1170 @@
1
+ import { Slider } from './chunk-HU7T64Y3.js';
2
+ import { pickLuminaThemePresets } from './chunk-6SPMHY54.js';
3
+ import { useTheme, ACCENT_PRESETS, FONT_STACKS } from './chunk-7NZ2A4MA.js';
4
+ import { Switch } from './chunk-YJEXAO2I.js';
5
+ import { RadioGroup } from './chunk-HFUHQUPQ.js';
6
+ import { ColorPicker } from './chunk-GZCU6HXD.js';
7
+ import { Input } from './chunk-XVP7IKLZ.js';
8
+ import { Button } from './chunk-CNGKJYGZ.js';
9
+ import { Icon } from './chunk-YT5NLCRC.js';
10
+ import './tokens-EF34LSWI.css';
11
+ import './shared-NJHRNLRH.css';
12
+ import './ThemePanel-76LB3YA5.css';
13
+ import * as React from 'react';
14
+ import { jsxs, jsx } from 'react/jsx-runtime';
15
+
16
+ var THEME_PANEL_DEFAULT_THEME_PRESETS = pickLuminaThemePresets(["light", "dark", "porcelain", "assistant", "assistantDark"]);
17
+ var THEME_PANEL_DEFAULT_PRESET_OPTIONS = [
18
+ { key: "light", label: "\u6D45\u8272", description: "\u9ED8\u8BA4", preset: THEME_PANEL_DEFAULT_THEME_PRESETS.light },
19
+ { key: "dark", label: "\u6DF1\u8272", description: "\u9ED8\u8BA4", preset: THEME_PANEL_DEFAULT_THEME_PRESETS.dark },
20
+ { key: "porcelain", label: "\u74F7\u767D", description: "\u6E05\u4EAE", preset: THEME_PANEL_DEFAULT_THEME_PRESETS.porcelain },
21
+ { key: "assistant", label: "\u52A9\u624B", description: "Soft", preset: THEME_PANEL_DEFAULT_THEME_PRESETS.assistant },
22
+ { key: "assistantDark", label: "\u52A9\u624B\u6697", description: "Soft", preset: THEME_PANEL_DEFAULT_THEME_PRESETS.assistantDark }
23
+ ];
24
+ var DRAFT_THEME_MODE = "__theme_panel_draft__";
25
+ var DEFAULT_SURFACE_BY_BASE = {
26
+ light: THEME_PANEL_DEFAULT_THEME_PRESETS.light.tokens.bg,
27
+ dark: THEME_PANEL_DEFAULT_THEME_PRESETS.dark.tokens.bg
28
+ };
29
+ var SURFACE_TOKEN_KEYS = [
30
+ "bg",
31
+ "bg-raised",
32
+ "bg-sunken",
33
+ "fg",
34
+ "fg-muted",
35
+ "fg-subtle",
36
+ "border",
37
+ "divider"
38
+ ];
39
+ var SHADOW_TOKEN_KEYS = [
40
+ "shadow-dark",
41
+ "shadow-light",
42
+ "shadow-scale",
43
+ "shadow-float-scale"
44
+ ];
45
+ var THEME_TOKEN_KEYS = [...SURFACE_TOKEN_KEYS, ...SHADOW_TOKEN_KEYS];
46
+ var DEFAULT_SECTIONS = [
47
+ "mode",
48
+ "presets",
49
+ "accent",
50
+ "shadow",
51
+ "radius",
52
+ "font",
53
+ "density"
54
+ ];
55
+ var DEFAULT_MODE_OPTIONS = [
56
+ { key: "light", label: "\u6D45\u8272" },
57
+ { key: "dark", label: "\u6DF1\u8272" },
58
+ { key: "system", label: "\u7CFB\u7EDF" }
59
+ ];
60
+ var DENSITY_OPTIONS = [
61
+ { value: "compact", label: "\u7D27\u51D1" },
62
+ { value: "comfortable", label: "\u8212\u9002" },
63
+ { value: "spacious", label: "\u5BBD\u677E" }
64
+ ];
65
+ var FONT_OPTIONS = [
66
+ { value: "system", label: "\u7CFB\u7EDF" },
67
+ { value: "sf", label: "SF Pro" },
68
+ { value: "serif", label: "\u886C\u7EBF" },
69
+ { value: "mono", label: "\u7B49\u5BBD" }
70
+ ];
71
+ var THEME_CREATE_MODE_OPTIONS = [
72
+ { value: "simple", label: "\u7B80\u6D01" },
73
+ { value: "advanced", label: "\u6DF1\u5EA6" }
74
+ ];
75
+ var ADVANCED_FONT_MODE_OPTIONS = [
76
+ { value: "preset", label: "\u9884\u8BBE\u5B57\u4F53" },
77
+ { value: "custom", label: "\u81EA\u5B9A\u4E49\u6808" }
78
+ ];
79
+ var SURFACE_TOKEN_FIELDS = [
80
+ { key: "bg", label: "\u80CC\u666F" },
81
+ { key: "bg-raised", label: "\u51F8\u8D77\u9762" },
82
+ { key: "bg-sunken", label: "\u51F9\u9677\u9762" },
83
+ { key: "fg", label: "\u6B63\u6587" },
84
+ { key: "fg-muted", label: "\u6B21\u7EA7\u6587\u5B57" },
85
+ { key: "fg-subtle", label: "\u5F31\u6587\u5B57" },
86
+ { key: "border", label: "\u63CF\u8FB9" },
87
+ { key: "divider", label: "\u5206\u5272\u7EBF" }
88
+ ];
89
+ var SHADOW_TOKEN_FIELDS = [
90
+ { key: "shadow-dark", label: "\u6697\u9634\u5F71", kind: "color" },
91
+ { key: "shadow-light", label: "\u4EAE\u9634\u5F71", kind: "color" },
92
+ { key: "shadow-scale", label: "\u9634\u5F71\u6269\u6563", kind: "scale" },
93
+ { key: "shadow-float-scale", label: "\u6D6E\u5C42\u6DF1\u5EA6", kind: "scale" }
94
+ ];
95
+ var ACCENT_PALETTE_FIELDS = [
96
+ { key: "accent", label: "\u4E3B\u8272" },
97
+ { key: "ink", label: "\u6587\u5B57\u8272" },
98
+ { key: "soft", label: "\u67D4\u548C\u5E95" },
99
+ { key: "glow", label: "\u5149\u6655" }
100
+ ];
101
+ function accentFromPreset(preset) {
102
+ const accent = preset?.accent ?? "sky";
103
+ if (typeof accent === "string") {
104
+ return ACCENT_PRESETS[accent]?.accent ?? accent;
105
+ }
106
+ return accent.accent;
107
+ }
108
+ function fallbackPresetLabel(key) {
109
+ return key.replace(/^user-/, "").replace(/[-_]+/g, " ").replace(/\b\w/g, (letter) => letter.toUpperCase());
110
+ }
111
+ function nodeToText(node, fallback) {
112
+ if (typeof node === "string") return node;
113
+ if (typeof node === "number") return String(node);
114
+ return fallback;
115
+ }
116
+ function createThemeKey(label, themes, prefix) {
117
+ const normalizedPrefix = prefix.trim().replace(/[^a-z0-9-]+/gi, "-").replace(/^-+|-+$/g, "") || "user";
118
+ const slug = label.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
119
+ const base = `${normalizedPrefix}-${slug || "custom-theme"}`;
120
+ let key = base;
121
+ let i = 2;
122
+ while (key in themes || key in THEME_PANEL_DEFAULT_THEME_PRESETS || key === DRAFT_THEME_MODE) {
123
+ key = `${base}-${i}`;
124
+ i += 1;
125
+ }
126
+ return key;
127
+ }
128
+ var clampColor = (value) => Math.min(1, Math.max(0, value));
129
+ function normalizeHexColor(input) {
130
+ const value = input.trim().replace(/^#/, "");
131
+ if (!/^([\da-f]{3}|[\da-f]{6})$/i.test(value)) return null;
132
+ const hex = value.length === 3 ? value.split("").map((part) => part + part).join("") : value;
133
+ return `#${hex.toLowerCase()}`;
134
+ }
135
+ function hexToRgbColor(hex) {
136
+ const normalized = normalizeHexColor(hex);
137
+ if (!normalized) return null;
138
+ const value = Number.parseInt(normalized.slice(1), 16);
139
+ return [value >> 16 & 255, value >> 8 & 255, value & 255];
140
+ }
141
+ function rgbToHexColor(red, green, blue) {
142
+ const toHex = (value) => Math.round(Math.min(255, Math.max(0, value))).toString(16).padStart(2, "0");
143
+ return `#${toHex(red)}${toHex(green)}${toHex(blue)}`;
144
+ }
145
+ function parseRgbColor(value) {
146
+ const match = value.trim().match(/^rgba?\((.+)\)$/i);
147
+ if (!match) return null;
148
+ const parts = match[1].replace(/\s*\/\s*[\d.]+%?$/, "").split(/[\s,]+/).filter(Boolean).slice(0, 3);
149
+ if (parts.length < 3) return null;
150
+ const channels = parts.map((part) => {
151
+ const numeric = Number.parseFloat(part);
152
+ return part.endsWith("%") ? numeric / 100 * 255 : numeric;
153
+ });
154
+ return channels.every(Number.isFinite) ? rgbToHexColor(channels[0], channels[1], channels[2]) : null;
155
+ }
156
+ function parseOklchColor(value) {
157
+ const match = value.trim().match(/^oklch\(\s*([+-]?\d*\.?\d+)(%)?\s+([+-]?\d*\.?\d+)\s+([+-]?\d*\.?\d+)(deg|rad|turn)?(?:\s*\/\s*[^)]+)?\s*\)$/i);
158
+ if (!match) return null;
159
+ const lightness = Number.parseFloat(match[1]);
160
+ const chroma = Number.parseFloat(match[3]);
161
+ const hueValue = Number.parseFloat(match[4]);
162
+ if (![lightness, chroma, hueValue].every(Number.isFinite)) return null;
163
+ const hue = match[5] === "rad" ? hueValue * 180 / Math.PI : match[5] === "turn" ? hueValue * 360 : hueValue;
164
+ const l = match[2] ? lightness / 100 : lightness;
165
+ const a = chroma * Math.cos(hue * Math.PI / 180);
166
+ const b = chroma * Math.sin(hue * Math.PI / 180);
167
+ const lmsL = (l + 0.3963377774 * a + 0.2158037573 * b) ** 3;
168
+ const lmsM = (l - 0.1055613458 * a - 0.0638541728 * b) ** 3;
169
+ const lmsS = (l - 0.0894841775 * a - 1.291485548 * b) ** 3;
170
+ const linearR = 4.0767416621 * lmsL - 3.3077115913 * lmsM + 0.2309699292 * lmsS;
171
+ const linearG = -1.2684380046 * lmsL + 2.6097574011 * lmsM - 0.3413193965 * lmsS;
172
+ const linearB = -0.0041960863 * lmsL - 0.7034186147 * lmsM + 1.707614701 * lmsS;
173
+ const encode = (channel) => {
174
+ const c = clampColor(channel);
175
+ return c <= 31308e-7 ? c * 12.92 : 1.055 * c ** (1 / 2.4) - 0.055;
176
+ };
177
+ return rgbToHexColor(encode(linearR) * 255, encode(linearG) * 255, encode(linearB) * 255);
178
+ }
179
+ function cssColorToHex(value, fallback) {
180
+ return normalizeHexColor(value) ?? parseRgbColor(value) ?? parseOklchColor(value) ?? fallback;
181
+ }
182
+ function sameHexColor(a, b) {
183
+ const left = normalizeHexColor(a);
184
+ const right = normalizeHexColor(b);
185
+ return !!left && left === right;
186
+ }
187
+ function shiftHexColor(value, delta) {
188
+ if (!value) return void 0;
189
+ const rgb = hexToRgbColor(value);
190
+ if (!rgb) return value;
191
+ return rgbToHexColor(rgb[0] + delta[0], rgb[1] + delta[1], rgb[2] + delta[2]);
192
+ }
193
+ function createAccentPalette(accent, base) {
194
+ return {
195
+ accent,
196
+ ink: base === "dark" ? `color-mix(in oklch, ${accent} 68%, white)` : `color-mix(in oklch, ${accent} 65%, black)`,
197
+ soft: base === "dark" ? `color-mix(in oklch, ${accent} 28%, black)` : `color-mix(in oklch, ${accent} 15%, white)`,
198
+ glow: base === "dark" ? `color-mix(in oklch, ${accent} 18%, transparent)` : `color-mix(in oklch, ${accent} 35%, transparent)`
199
+ };
200
+ }
201
+ function createSurfaceTokens(surface, base) {
202
+ return base === "dark" ? {
203
+ bg: surface,
204
+ "bg-raised": `color-mix(in oklch, ${surface} 88%, white)`,
205
+ "bg-sunken": `color-mix(in oklch, ${surface} 84%, black)`,
206
+ fg: `color-mix(in oklch, ${surface} 18%, white)`,
207
+ "fg-muted": `color-mix(in oklch, ${surface} 48%, white)`,
208
+ "fg-subtle": `color-mix(in oklch, ${surface} 66%, white)`,
209
+ border: "rgba(255, 255, 255, 0.08)",
210
+ divider: "rgba(255, 255, 255, 0.08)",
211
+ "shadow-dark": "rgba(0, 0, 0, 0.56)",
212
+ "shadow-light": "rgba(130, 145, 180, 0.06)",
213
+ "shadow-scale": "1",
214
+ "shadow-float-scale": "1"
215
+ } : {
216
+ bg: surface,
217
+ "bg-raised": `color-mix(in oklch, ${surface} 82%, white)`,
218
+ "bg-sunken": `color-mix(in oklch, ${surface} 88%, black)`,
219
+ fg: `color-mix(in oklch, ${surface} 24%, black)`,
220
+ "fg-muted": `color-mix(in oklch, ${surface} 48%, black)`,
221
+ "fg-subtle": `color-mix(in oklch, ${surface} 66%, black)`,
222
+ border: "rgba(110, 130, 150, 0.14)",
223
+ divider: "rgba(110, 130, 150, 0.18)",
224
+ "shadow-dark": `color-mix(in oklch, ${surface} 68%, black)`,
225
+ "shadow-light": "rgba(255, 255, 255, 0.96)",
226
+ "shadow-scale": "1",
227
+ "shadow-float-scale": "1"
228
+ };
229
+ }
230
+ function defaultBaseTokens(base) {
231
+ const tokens = THEME_PANEL_DEFAULT_THEME_PRESETS[base].tokens;
232
+ return { ...tokens };
233
+ }
234
+ function createDraftSurfaceTokens(surface, base, sourceSurface, sourceTokens) {
235
+ if (sameHexColor(surface, sourceSurface)) return { ...sourceTokens };
236
+ const current = hexToRgbColor(surface);
237
+ const source = hexToRgbColor(sourceSurface);
238
+ if (!current || !source) return createSurfaceTokens(surface, base);
239
+ const delta = [
240
+ current[0] - source[0],
241
+ current[1] - source[1],
242
+ current[2] - source[2]
243
+ ];
244
+ return {
245
+ ...sourceTokens,
246
+ bg: normalizeHexColor(surface) ?? surface,
247
+ "bg-raised": shiftHexColor(sourceTokens["bg-raised"], delta) ?? sourceTokens["bg-raised"],
248
+ "bg-sunken": shiftHexColor(sourceTokens["bg-sunken"], delta) ?? sourceTokens["bg-sunken"]
249
+ };
250
+ }
251
+ function createDraftAccentPalette(accent, base, sourceAccent, sourcePalette) {
252
+ return sameHexColor(accent, sourceAccent) ? { ...sourcePalette } : createAccentPalette(accent, base);
253
+ }
254
+ function readCssVar(element, name, fallback) {
255
+ if (!element || typeof window === "undefined") return fallback;
256
+ return getComputedStyle(element).getPropertyValue(name).trim() || fallback;
257
+ }
258
+ function readCurrentThemeTokens(element, base) {
259
+ const fallbackTokens = defaultBaseTokens(base);
260
+ return Object.fromEntries(
261
+ THEME_TOKEN_KEYS.map((key) => [
262
+ key,
263
+ readCssVar(element, `--${key}`, fallbackTokens[key] ?? DEFAULT_SURFACE_BY_BASE[base])
264
+ ])
265
+ );
266
+ }
267
+ function readCurrentAccentPalette(element, fallback) {
268
+ return {
269
+ accent: readCssVar(element, "--accent", fallback.accent),
270
+ ink: readCssVar(element, "--accent-ink", fallback.ink),
271
+ soft: readCssVar(element, "--accent-soft", fallback.soft),
272
+ glow: readCssVar(element, "--accent-glow", fallback.glow)
273
+ };
274
+ }
275
+ function toFontKey(font) {
276
+ return typeof font === "string" && FONT_OPTIONS.some((option) => option.value === font) ? font : "system";
277
+ }
278
+ function fontConfigToText(font) {
279
+ return typeof font === "string" ? font : JSON.stringify(font);
280
+ }
281
+ function fontToStack(font) {
282
+ if (typeof font === "string") return FONT_STACKS[font] ?? font;
283
+ return font.sans ?? font.display ?? FONT_STACKS.system;
284
+ }
285
+ function tokenPickerValue(value, fallback) {
286
+ return cssColorToHex(value ?? fallback, fallback);
287
+ }
288
+ function parseScaleToken(value, fallback = 1) {
289
+ const parsed = Number.parseFloat(value ?? "");
290
+ return Number.isFinite(parsed) ? Math.min(2, Math.max(0.2, parsed)) : fallback;
291
+ }
292
+ function formatScaleToken(value) {
293
+ return value.toFixed(2).replace(/\.?0+$/, "");
294
+ }
295
+ var ThemePanel = React.forwardRef(
296
+ ({
297
+ title = "\u4E3B\u9898",
298
+ description = "\u5FEB\u901F\u8C03\u6574\u5F53\u524D Lumina \u4E3B\u9898",
299
+ sections = DEFAULT_SECTIONS,
300
+ modeOptions = DEFAULT_MODE_OPTIONS,
301
+ presetOptions,
302
+ defaultCustomAccent = "#845ef7",
303
+ allowCreateTheme = true,
304
+ defaultCreateThemeName = "\u6211\u7684\u4E3B\u9898",
305
+ createThemeKeyPrefix = "user",
306
+ onCreateTheme,
307
+ allowDeleteTheme = true,
308
+ onDeleteTheme,
309
+ showReset = true,
310
+ compact,
311
+ className = "",
312
+ ...rest
313
+ }, ref) => {
314
+ const theme = useTheme();
315
+ const rootRef = React.useRef(null);
316
+ const previewSnapshotRef = React.useRef(null);
317
+ const updateThemeRef = React.useRef(theme.update);
318
+ updateThemeRef.current = theme.update;
319
+ const [customAccent, setCustomAccent] = React.useState(defaultCustomAccent);
320
+ const [createdThemeMeta, setCreatedThemeMeta] = React.useState({});
321
+ const [isCreatingTheme, setIsCreatingTheme] = React.useState(false);
322
+ const [previewDraft, setPreviewDraft] = React.useState(true);
323
+ const [draftName, setDraftName] = React.useState(defaultCreateThemeName);
324
+ const [draftBase, setDraftBase] = React.useState("light");
325
+ const [draftSurface, setDraftSurface] = React.useState(DEFAULT_SURFACE_BY_BASE.light);
326
+ const [draftAccent, setDraftAccent] = React.useState(defaultCustomAccent);
327
+ const [draftTokens, setDraftTokens] = React.useState(
328
+ () => defaultBaseTokens("light")
329
+ );
330
+ const [draftSourceSurface, setDraftSourceSurface] = React.useState(DEFAULT_SURFACE_BY_BASE.light);
331
+ const [draftSourceTokens, setDraftSourceTokens] = React.useState(
332
+ () => defaultBaseTokens("light")
333
+ );
334
+ const [draftAccentPalette, setDraftAccentPalette] = React.useState(
335
+ () => createAccentPalette(defaultCustomAccent, "light")
336
+ );
337
+ const [draftSourceAccent, setDraftSourceAccent] = React.useState(defaultCustomAccent);
338
+ const [draftSourceAccentPalette, setDraftSourceAccentPalette] = React.useState(
339
+ () => createAccentPalette(defaultCustomAccent, "light")
340
+ );
341
+ const [draftDensity, setDraftDensity] = React.useState("comfortable");
342
+ const [draftIntensity, setDraftIntensity] = React.useState(5);
343
+ const [draftRadius, setDraftRadius] = React.useState(20);
344
+ const [draftFont, setDraftFont] = React.useState("sf");
345
+ const [createMode, setCreateMode] = React.useState("simple");
346
+ const [advancedFontMode, setAdvancedFontMode] = React.useState("preset");
347
+ const [draftBasePresets, setDraftBasePresets] = React.useState(() => ({
348
+ light: THEME_PANEL_DEFAULT_THEME_PRESETS.light,
349
+ dark: THEME_PANEL_DEFAULT_THEME_PRESETS.dark
350
+ }));
351
+ const modeValue = String(theme.mode);
352
+ const protectedPresetKeys = React.useMemo(
353
+ () => /* @__PURE__ */ new Set(["system", ...THEME_PANEL_DEFAULT_PRESET_OPTIONS.map((option) => String(option.key))]),
354
+ []
355
+ );
356
+ const setRootRef = React.useCallback(
357
+ (node) => {
358
+ rootRef.current = node;
359
+ if (typeof ref === "function") ref(node);
360
+ else if (ref) ref.current = node;
361
+ },
362
+ [ref]
363
+ );
364
+ const draftPreset = React.useMemo(
365
+ () => ({
366
+ base: draftBase,
367
+ accent: draftAccentPalette,
368
+ density: draftDensity,
369
+ intensity: draftIntensity,
370
+ radius: draftRadius,
371
+ font: draftFont,
372
+ tokens: draftTokens
373
+ }),
374
+ [draftAccentPalette, draftBase, draftDensity, draftFont, draftIntensity, draftRadius, draftTokens]
375
+ );
376
+ const resolvedPresetOptions = React.useMemo(() => {
377
+ if (presetOptions) return presetOptions;
378
+ const defaultKeys = new Set(THEME_PANEL_DEFAULT_PRESET_OPTIONS.map((option) => String(option.key)));
379
+ const builtIns = THEME_PANEL_DEFAULT_PRESET_OPTIONS.map((option) => {
380
+ const key = String(option.key);
381
+ return {
382
+ ...option,
383
+ preset: theme.themes[key] ?? option.preset
384
+ };
385
+ });
386
+ const customOptions = Object.entries(theme.themes).filter(([key]) => !defaultKeys.has(key)).map(([key, preset]) => ({
387
+ key,
388
+ label: createdThemeMeta[key]?.label ?? preset.label ?? fallbackPresetLabel(key),
389
+ description: createdThemeMeta[key]?.description ?? preset.description ?? (preset.base === "dark" ? "\u6DF1\u8272" : "\u6D45\u8272"),
390
+ preset
391
+ }));
392
+ return [...builtIns, ...customOptions];
393
+ }, [createdThemeMeta, presetOptions, theme.themes]);
394
+ React.useEffect(() => {
395
+ if (!isCreatingTheme || !previewDraft) return;
396
+ updateThemeRef.current({
397
+ mode: DRAFT_THEME_MODE,
398
+ colorScheme: draftPreset.base,
399
+ accent: draftPreset.accent,
400
+ density: draftPreset.density,
401
+ intensity: draftPreset.intensity,
402
+ radius: draftPreset.radius,
403
+ font: draftPreset.font,
404
+ tokens: draftPreset.tokens
405
+ });
406
+ }, [draftPreset, isCreatingTheme, previewDraft]);
407
+ const clearCreateState = () => {
408
+ previewSnapshotRef.current = null;
409
+ setIsCreatingTheme(false);
410
+ setPreviewDraft(true);
411
+ };
412
+ const restorePreviewSnapshot = () => {
413
+ const snapshot = previewSnapshotRef.current;
414
+ if (!snapshot) return;
415
+ updateThemeRef.current({
416
+ ...snapshot,
417
+ mode: snapshot.mode === DRAFT_THEME_MODE ? snapshot.colorScheme ?? "light" : snapshot.mode
418
+ });
419
+ };
420
+ React.useEffect(() => {
421
+ return () => {
422
+ restorePreviewSnapshot();
423
+ };
424
+ }, []);
425
+ const applyMode = (mode) => {
426
+ clearCreateState();
427
+ if (mode === "light" || mode === "dark" || mode === "system") {
428
+ theme.update({ mode, colorScheme: mode === "system" ? theme.colorScheme : mode, tokens: {} });
429
+ return;
430
+ }
431
+ theme.setMode(mode);
432
+ };
433
+ const applyPreset = (option) => {
434
+ clearCreateState();
435
+ const key = String(option.key);
436
+ const preset = option.preset ?? theme.themes[key];
437
+ if (!preset) {
438
+ theme.setMode(option.key);
439
+ return;
440
+ }
441
+ const isBuiltInMode = key === "light" || key === "dark" || key === "system";
442
+ const fallbackAccent = theme.accent === "custom" ? theme.accentPalette : theme.accent;
443
+ theme.update({
444
+ ...!isBuiltInMode ? { themes: { ...theme.themes, [key]: preset } } : null,
445
+ mode: option.key,
446
+ colorScheme: preset.base ?? theme.colorScheme,
447
+ accent: preset.accent ?? fallbackAccent,
448
+ density: preset.density ?? theme.density,
449
+ intensity: preset.intensity ?? theme.intensity,
450
+ radius: preset.radius ?? theme.radius,
451
+ font: preset.font ?? theme.font,
452
+ tokens: preset.tokens ?? {}
453
+ });
454
+ };
455
+ const deletePreset = (option) => {
456
+ clearCreateState();
457
+ const key = String(option.key);
458
+ if (protectedPresetKeys.has(key) || !(key in theme.themes)) return;
459
+ const preset = option.preset ?? theme.themes[key];
460
+ const { [key]: _removed, ...nextThemes } = theme.themes;
461
+ const active = modeValue === key;
462
+ const nextBase = theme.colorScheme === "dark" ? "dark" : "light";
463
+ const fallbackPreset = THEME_PANEL_DEFAULT_THEME_PRESETS[nextBase];
464
+ const nextConfig = active ? {
465
+ mode: nextBase,
466
+ colorScheme: fallbackPreset.base,
467
+ accent: fallbackPreset.accent,
468
+ density: fallbackPreset.density,
469
+ intensity: fallbackPreset.intensity,
470
+ radius: fallbackPreset.radius,
471
+ font: fallbackPreset.font,
472
+ tokens: fallbackPreset.tokens
473
+ } : {};
474
+ theme.update({
475
+ ...nextConfig,
476
+ themes: nextThemes
477
+ });
478
+ setCreatedThemeMeta((current) => {
479
+ if (!(key in current)) return current;
480
+ const { [key]: _meta, ...next } = current;
481
+ return next;
482
+ });
483
+ onDeleteTheme?.({
484
+ key,
485
+ label: nodeToText(option.label, preset?.label ?? fallbackPresetLabel(key)),
486
+ description: nodeToText(
487
+ option.description,
488
+ preset?.description ?? (preset?.base === "dark" ? "\u6DF1\u8272" : "\u6D45\u8272")
489
+ ),
490
+ preset
491
+ });
492
+ };
493
+ const beginCreateTheme = () => {
494
+ const root = rootRef.current;
495
+ const base = theme.colorScheme;
496
+ const surface = cssColorToHex(
497
+ readCssVar(root, "--bg", DEFAULT_SURFACE_BY_BASE[base]),
498
+ DEFAULT_SURFACE_BY_BASE[base]
499
+ );
500
+ const accentPalette = readCurrentAccentPalette(root, theme.accentPalette);
501
+ const accent = cssColorToHex(accentPalette.accent, defaultCustomAccent);
502
+ const currentTokens = readCurrentThemeTokens(root, base);
503
+ const currentPreset = {
504
+ base,
505
+ accent: accentPalette,
506
+ density: theme.density,
507
+ intensity: theme.intensity,
508
+ radius: theme.radius,
509
+ font: theme.font,
510
+ tokens: currentTokens
511
+ };
512
+ const basePresets = {
513
+ light: base === "light" ? currentPreset : THEME_PANEL_DEFAULT_THEME_PRESETS.light,
514
+ dark: base === "dark" ? currentPreset : THEME_PANEL_DEFAULT_THEME_PRESETS.dark
515
+ };
516
+ previewSnapshotRef.current = {
517
+ mode: theme.mode,
518
+ colorScheme: theme.colorScheme,
519
+ accent: theme.accent === "custom" ? theme.accentPalette : theme.accent,
520
+ density: theme.density,
521
+ intensity: theme.intensity,
522
+ radius: theme.radius,
523
+ font: theme.font,
524
+ tokens: theme.tokens,
525
+ themes: theme.themes
526
+ };
527
+ setDraftBasePresets(basePresets);
528
+ setDraftName(defaultCreateThemeName);
529
+ setDraftBase(base);
530
+ setDraftSurface(cssColorToHex(currentTokens.bg ?? surface, surface));
531
+ setDraftTokens(currentTokens);
532
+ setDraftSourceSurface(cssColorToHex(currentTokens.bg ?? surface, surface));
533
+ setDraftSourceTokens(currentTokens);
534
+ setDraftAccent(accent);
535
+ setDraftAccentPalette(accentPalette);
536
+ setDraftSourceAccent(accent);
537
+ setDraftSourceAccentPalette(accentPalette);
538
+ setDraftDensity(theme.density);
539
+ setDraftIntensity(theme.intensity);
540
+ setDraftRadius(theme.radius);
541
+ setDraftFont(theme.font ?? "sf");
542
+ setAdvancedFontMode(toFontKey(theme.font) === theme.font ? "preset" : "custom");
543
+ setCreateMode("simple");
544
+ setCustomAccent(accent);
545
+ setPreviewDraft(true);
546
+ setIsCreatingTheme(true);
547
+ };
548
+ const cancelCreateTheme = () => {
549
+ restorePreviewSnapshot();
550
+ clearCreateState();
551
+ };
552
+ const toggleDraftPreview = (checked) => {
553
+ setPreviewDraft(checked);
554
+ if (!checked) restorePreviewSnapshot();
555
+ };
556
+ const updateDraftBase = (base) => {
557
+ const preset = draftBasePresets[base] ?? THEME_PANEL_DEFAULT_THEME_PRESETS[base];
558
+ const tokens = { ...preset.tokens ?? defaultBaseTokens(base) };
559
+ const surface = cssColorToHex(tokens.bg ?? DEFAULT_SURFACE_BY_BASE[base], DEFAULT_SURFACE_BY_BASE[base]);
560
+ setDraftBase(base);
561
+ setDraftSurface(surface);
562
+ setDraftTokens(tokens);
563
+ setDraftSourceSurface(surface);
564
+ setDraftSourceTokens(tokens);
565
+ const nextAccent = cssColorToHex(draftAccent, defaultCustomAccent);
566
+ const accentPalette = createAccentPalette(nextAccent, base);
567
+ setDraftAccent(nextAccent);
568
+ setDraftAccentPalette(accentPalette);
569
+ setDraftSourceAccent(nextAccent);
570
+ setDraftSourceAccentPalette(accentPalette);
571
+ };
572
+ const updateDraftSurface = (surface) => {
573
+ setDraftSurface(surface);
574
+ setDraftTokens(createDraftSurfaceTokens(surface, draftBase, draftSourceSurface, draftSourceTokens));
575
+ };
576
+ const updateDraftToken = (key, value) => {
577
+ setDraftTokens((current) => ({ ...current, [key]: value }));
578
+ if (key === "bg") setDraftSurface(cssColorToHex(value, draftSurface));
579
+ };
580
+ const updateDraftAccent = (accent) => {
581
+ setDraftAccent(accent);
582
+ setDraftAccentPalette(createDraftAccentPalette(accent, draftBase, draftSourceAccent, draftSourceAccentPalette));
583
+ if (previewDraft) setCustomAccent(accent);
584
+ };
585
+ const updateDraftAccentSlot = (key, value) => {
586
+ setDraftAccentPalette((current) => ({ ...current, [key]: value }));
587
+ if (key === "accent") {
588
+ const accent = cssColorToHex(value, draftAccent);
589
+ setDraftAccent(accent);
590
+ if (previewDraft) setCustomAccent(accent);
591
+ }
592
+ };
593
+ const saveCustomTheme = () => {
594
+ const label = draftName.trim() || defaultCreateThemeName || "\u81EA\u5B9A\u4E49\u4E3B\u9898";
595
+ const key = createThemeKey(label, theme.themes, createThemeKeyPrefix);
596
+ const description2 = draftBase === "dark" ? "\u81EA\u5EFA\u6697" : "\u81EA\u5EFA\u4EAE";
597
+ const preset = { ...draftPreset, label, description: description2 };
598
+ const presetOption = { key, label, description: description2, preset };
599
+ const nextThemes = { ...theme.themes, [String(key)]: preset };
600
+ const meta = { key, label, description: description2 };
601
+ setCreatedThemeMeta((current) => ({ ...current, [String(key)]: meta }));
602
+ theme.update({
603
+ themes: nextThemes,
604
+ mode: key,
605
+ colorScheme: preset.base,
606
+ accent: preset.accent,
607
+ density: preset.density,
608
+ intensity: preset.intensity,
609
+ radius: preset.radius,
610
+ font: preset.font,
611
+ tokens: preset.tokens
612
+ });
613
+ setCustomAccent(draftAccent);
614
+ onCreateTheme?.({ ...meta, preset, presetOption });
615
+ clearCreateState();
616
+ };
617
+ const resetTheme = () => {
618
+ clearCreateState();
619
+ theme.reset();
620
+ };
621
+ const rootClass = ["theme-panel", compact && "compact", className].filter(Boolean).join(" ");
622
+ const shadowScale = parseScaleToken(
623
+ theme.tokens["shadow-scale"] ?? readCssVar(rootRef.current, "--shadow-scale", "1")
624
+ );
625
+ const shadowFloatScale = parseScaleToken(
626
+ theme.tokens["shadow-float-scale"] ?? readCssVar(rootRef.current, "--shadow-float-scale", "1")
627
+ );
628
+ const updateThemeToken = (key, value) => {
629
+ theme.setTokens({ ...theme.tokens, [key]: value });
630
+ };
631
+ return /* @__PURE__ */ jsxs("div", { ref: setRootRef, className: rootClass, ...rest, children: [
632
+ (title || description) && /* @__PURE__ */ jsxs("div", { className: "theme-panel-head", children: [
633
+ /* @__PURE__ */ jsxs("div", { className: "theme-panel-title", children: [
634
+ /* @__PURE__ */ jsx(Icon, { name: "sliders", size: 14 }),
635
+ title && /* @__PURE__ */ jsx("span", { children: title })
636
+ ] }),
637
+ description && /* @__PURE__ */ jsx("div", { className: "theme-panel-desc", children: description })
638
+ ] }),
639
+ sections.includes("mode") && /* @__PURE__ */ jsxs("div", { className: "theme-panel-row", children: [
640
+ /* @__PURE__ */ jsxs("div", { className: "theme-panel-label", children: [
641
+ /* @__PURE__ */ jsx("span", { children: "\u6A21\u5F0F" }),
642
+ /* @__PURE__ */ jsx("span", { children: theme.colorScheme })
643
+ ] }),
644
+ /* @__PURE__ */ jsx(
645
+ RadioGroup,
646
+ {
647
+ variant: "segmented",
648
+ size: "sm",
649
+ value: modeValue,
650
+ options: modeOptions.map((option) => ({
651
+ value: String(option.key),
652
+ label: option.label
653
+ })),
654
+ onChange: applyMode
655
+ }
656
+ )
657
+ ] }),
658
+ sections.includes("presets") && (resolvedPresetOptions.length > 0 || allowCreateTheme) && /* @__PURE__ */ jsxs("div", { className: "theme-panel-row", children: [
659
+ /* @__PURE__ */ jsxs("div", { className: "theme-panel-label", children: [
660
+ /* @__PURE__ */ jsx("span", { children: "\u4E3B\u9898\u9884\u8BBE" }),
661
+ /* @__PURE__ */ jsx("span", { children: modeValue })
662
+ ] }),
663
+ resolvedPresetOptions.length > 0 && /* @__PURE__ */ jsx("div", { className: "theme-panel-presets", children: resolvedPresetOptions.map((option) => {
664
+ const key = String(option.key);
665
+ const preset = option.preset ?? theme.themes[key];
666
+ const active = modeValue === key;
667
+ const deletable = allowDeleteTheme && !protectedPresetKeys.has(key) && key in theme.themes;
668
+ return /* @__PURE__ */ jsxs("div", { className: `theme-panel-preset-shell ${deletable ? "deletable" : ""}`, children: [
669
+ /* @__PURE__ */ jsxs(
670
+ Button,
671
+ {
672
+ type: "button",
673
+ variant: "ghost",
674
+ size: "sm",
675
+ className: `theme-panel-preset ${active ? "active" : ""}`,
676
+ onClick: () => applyPreset(option),
677
+ children: [
678
+ /* @__PURE__ */ jsxs("span", { className: "theme-panel-preset-ink", "aria-hidden": true, children: [
679
+ /* @__PURE__ */ jsx("span", { style: { background: preset?.tokens?.bg ?? "var(--bg)" } }),
680
+ /* @__PURE__ */ jsx("span", { style: { background: preset?.tokens?.["bg-raised"] ?? "var(--bg-raised)" } }),
681
+ /* @__PURE__ */ jsx("span", { style: { background: accentFromPreset(preset) } })
682
+ ] }),
683
+ /* @__PURE__ */ jsxs("span", { className: "theme-panel-preset-copy", children: [
684
+ /* @__PURE__ */ jsx("span", { children: option.label }),
685
+ option.description && /* @__PURE__ */ jsx("small", { children: option.description })
686
+ ] })
687
+ ]
688
+ }
689
+ ),
690
+ deletable && /* @__PURE__ */ jsx(
691
+ Button,
692
+ {
693
+ type: "button",
694
+ variant: "danger",
695
+ size: "sm",
696
+ icon: "trash",
697
+ iconOnly: true,
698
+ tip: `\u5220\u9664 ${nodeToText(option.label, fallbackPresetLabel(key))}`,
699
+ className: "theme-panel-preset-delete",
700
+ onClick: () => deletePreset(option)
701
+ }
702
+ )
703
+ ] }, key);
704
+ }) }),
705
+ allowCreateTheme && !isCreatingTheme && /* @__PURE__ */ jsx(Button, { type: "button", variant: "primary", size: "sm", icon: "plus", block: true, onClick: beginCreateTheme, children: "\u65B0\u5EFA\u4E3B\u9898" }),
706
+ allowCreateTheme && isCreatingTheme && /* @__PURE__ */ jsxs("div", { className: "theme-panel-create", children: [
707
+ /* @__PURE__ */ jsxs("div", { className: "theme-panel-create-head", children: [
708
+ /* @__PURE__ */ jsxs("div", { children: [
709
+ /* @__PURE__ */ jsx("span", { children: "\u65B0\u5EFA\u4E3B\u9898" }),
710
+ /* @__PURE__ */ jsx("small", { children: previewDraft ? "\u5B9E\u65F6\u9884\u89C8\u4E2D" : "\u9884\u89C8\u5DF2\u6682\u505C" })
711
+ ] }),
712
+ /* @__PURE__ */ jsx(
713
+ Switch,
714
+ {
715
+ size: "sm",
716
+ checked: previewDraft,
717
+ onChange: toggleDraftPreview,
718
+ checkedChildren: "\u9884\u89C8",
719
+ unCheckedChildren: "\u505C"
720
+ }
721
+ )
722
+ ] }),
723
+ /* @__PURE__ */ jsx(
724
+ Input,
725
+ {
726
+ size: "sm",
727
+ value: draftName,
728
+ onValueChange: setDraftName,
729
+ placeholder: "\u8F93\u5165\u4E3B\u9898\u540D\u79F0",
730
+ leadingIcon: "palette",
731
+ allowClear: true
732
+ }
733
+ ),
734
+ /* @__PURE__ */ jsx(
735
+ RadioGroup,
736
+ {
737
+ className: "theme-panel-create-mode",
738
+ variant: "segmented",
739
+ size: "sm",
740
+ value: createMode,
741
+ options: THEME_CREATE_MODE_OPTIONS.map((option) => ({
742
+ value: option.value,
743
+ label: option.label
744
+ })),
745
+ onChange: setCreateMode
746
+ }
747
+ ),
748
+ /* @__PURE__ */ jsxs("div", { className: "theme-panel-create-field", children: [
749
+ /* @__PURE__ */ jsx("span", { children: "\u57FA\u5E95" }),
750
+ /* @__PURE__ */ jsx(
751
+ RadioGroup,
752
+ {
753
+ variant: "segmented",
754
+ size: "sm",
755
+ value: draftBase,
756
+ options: [
757
+ { value: "light", label: "\u6D45" },
758
+ { value: "dark", label: "\u6DF1" }
759
+ ],
760
+ onChange: updateDraftBase
761
+ }
762
+ )
763
+ ] }),
764
+ createMode === "simple" && /* @__PURE__ */ jsxs("div", { className: "theme-panel-create-grid", children: [
765
+ /* @__PURE__ */ jsxs("div", { className: "theme-panel-create-field", children: [
766
+ /* @__PURE__ */ jsx("span", { children: "\u8868\u9762" }),
767
+ /* @__PURE__ */ jsx(ColorPicker, { size: "sm", value: draftSurface, onChange: updateDraftSurface })
768
+ ] }),
769
+ /* @__PURE__ */ jsxs("div", { className: "theme-panel-create-field", children: [
770
+ /* @__PURE__ */ jsx("span", { children: "\u5F3A\u8C03" }),
771
+ /* @__PURE__ */ jsx(ColorPicker, { size: "sm", value: draftAccent, onChange: updateDraftAccent })
772
+ ] })
773
+ ] }),
774
+ /* @__PURE__ */ jsxs("div", { className: "theme-panel-create-sliders", children: [
775
+ /* @__PURE__ */ jsxs("div", { className: "theme-panel-label", children: [
776
+ /* @__PURE__ */ jsx("span", { children: "\u9634\u5F71\u5F3A\u5EA6" }),
777
+ /* @__PURE__ */ jsx("span", { children: draftIntensity })
778
+ ] }),
779
+ /* @__PURE__ */ jsx(Slider, { value: draftIntensity, onChange: setDraftIntensity, min: 1, max: 10, step: 1 }),
780
+ /* @__PURE__ */ jsxs("div", { className: "theme-panel-label", children: [
781
+ /* @__PURE__ */ jsx("span", { children: "\u5706\u89D2" }),
782
+ /* @__PURE__ */ jsxs("span", { children: [
783
+ draftRadius,
784
+ "px"
785
+ ] })
786
+ ] }),
787
+ /* @__PURE__ */ jsx(Slider, { value: draftRadius, onChange: setDraftRadius, min: 8, max: 36, step: 2 })
788
+ ] }),
789
+ /* @__PURE__ */ jsxs("div", { className: "theme-panel-create-field", children: [
790
+ /* @__PURE__ */ jsx("span", { children: "\u5BC6\u5EA6" }),
791
+ /* @__PURE__ */ jsx(
792
+ RadioGroup,
793
+ {
794
+ variant: "segmented",
795
+ size: "sm",
796
+ value: draftDensity,
797
+ options: DENSITY_OPTIONS.map((option) => ({ value: option.value, label: option.label })),
798
+ onChange: setDraftDensity
799
+ }
800
+ )
801
+ ] }),
802
+ /* @__PURE__ */ jsxs("div", { className: "theme-panel-create-field", children: [
803
+ /* @__PURE__ */ jsx("span", { children: "\u5B57\u4F53" }),
804
+ /* @__PURE__ */ jsx(
805
+ RadioGroup,
806
+ {
807
+ variant: "segmented",
808
+ size: "sm",
809
+ value: toFontKey(draftFont),
810
+ options: FONT_OPTIONS.map((option) => ({ value: option.value, label: option.label })),
811
+ onChange: (value) => setDraftFont(value)
812
+ }
813
+ )
814
+ ] }),
815
+ createMode === "advanced" && /* @__PURE__ */ jsxs("div", { className: "theme-panel-advanced", children: [
816
+ /* @__PURE__ */ jsxs("div", { className: "theme-panel-advanced-section compact", children: [
817
+ /* @__PURE__ */ jsxs("div", { className: "theme-panel-advanced-title", children: [
818
+ /* @__PURE__ */ jsx("span", { children: "\u5B57\u4F53" }),
819
+ /* @__PURE__ */ jsx("small", { children: advancedFontMode === "preset" ? "\u9009\u62E9\u5185\u7F6E\u5B57\u4F53" : "\u586B\u5199 CSS font-family" })
820
+ ] }),
821
+ /* @__PURE__ */ jsx(
822
+ RadioGroup,
823
+ {
824
+ className: "theme-panel-create-mode",
825
+ variant: "segmented",
826
+ size: "sm",
827
+ value: advancedFontMode,
828
+ options: ADVANCED_FONT_MODE_OPTIONS.map((option) => ({
829
+ value: option.value,
830
+ label: option.label
831
+ })),
832
+ onChange: (value) => {
833
+ setAdvancedFontMode(value);
834
+ if (value === "preset") setDraftFont(toFontKey(draftFont));
835
+ }
836
+ }
837
+ ),
838
+ advancedFontMode === "custom" && /* @__PURE__ */ jsxs("div", { className: "theme-panel-create-field", children: [
839
+ /* @__PURE__ */ jsx("span", { children: "\u5B57\u4F53\u6808" }),
840
+ /* @__PURE__ */ jsx(
841
+ Input,
842
+ {
843
+ size: "sm",
844
+ value: fontConfigToText(draftFont),
845
+ onValueChange: (value) => setDraftFont(value || "system"),
846
+ placeholder: "CSS font-family"
847
+ }
848
+ )
849
+ ] })
850
+ ] }),
851
+ /* @__PURE__ */ jsxs("div", { className: "theme-panel-advanced-section", children: [
852
+ /* @__PURE__ */ jsxs("div", { className: "theme-panel-advanced-title", children: [
853
+ /* @__PURE__ */ jsx("span", { children: "\u8868\u9762 tokens" }),
854
+ /* @__PURE__ */ jsx("small", { children: "\u5B8C\u6574\u8986\u5199 --bg / --fg" })
855
+ ] }),
856
+ /* @__PURE__ */ jsx("div", { className: "theme-panel-token-grid", children: SURFACE_TOKEN_FIELDS.map((field) => /* @__PURE__ */ jsxs("div", { className: "theme-panel-token-field", children: [
857
+ /* @__PURE__ */ jsxs("span", { className: "theme-panel-token-label", children: [
858
+ /* @__PURE__ */ jsx("span", { children: field.label }),
859
+ /* @__PURE__ */ jsxs("code", { children: [
860
+ "--",
861
+ field.key
862
+ ] })
863
+ ] }),
864
+ /* @__PURE__ */ jsxs("span", { className: "theme-panel-token-input", children: [
865
+ /* @__PURE__ */ jsx(
866
+ ColorPicker,
867
+ {
868
+ className: "theme-panel-token-picker",
869
+ value: tokenPickerValue(draftTokens[field.key], draftSurface),
870
+ onChange: (value) => updateDraftToken(field.key, value),
871
+ placement: "left",
872
+ "aria-label": `\u9009\u62E9 ${field.label}`,
873
+ children: /* @__PURE__ */ jsx(
874
+ "span",
875
+ {
876
+ className: "theme-panel-token-swatch",
877
+ style: { background: draftTokens[field.key] }
878
+ }
879
+ )
880
+ }
881
+ ),
882
+ /* @__PURE__ */ jsx(
883
+ Input,
884
+ {
885
+ size: "sm",
886
+ value: draftTokens[field.key] ?? "",
887
+ onValueChange: (value) => updateDraftToken(field.key, value)
888
+ }
889
+ )
890
+ ] })
891
+ ] }, field.key)) })
892
+ ] }),
893
+ /* @__PURE__ */ jsxs("div", { className: "theme-panel-advanced-section", children: [
894
+ /* @__PURE__ */ jsxs("div", { className: "theme-panel-advanced-title", children: [
895
+ /* @__PURE__ */ jsx("span", { children: "\u9634\u5F71\u7CFB\u7EDF" }),
896
+ /* @__PURE__ */ jsx("small", { children: "\u6697/\u4EAE\u9634\u5F71\u4E0E\u5C42\u7EA7\u7F29\u653E" })
897
+ ] }),
898
+ /* @__PURE__ */ jsx("div", { className: "theme-panel-token-grid", children: SHADOW_TOKEN_FIELDS.map(
899
+ (field) => field.kind === "color" ? /* @__PURE__ */ jsxs("div", { className: "theme-panel-token-field", children: [
900
+ /* @__PURE__ */ jsxs("span", { className: "theme-panel-token-label", children: [
901
+ /* @__PURE__ */ jsx("span", { children: field.label }),
902
+ /* @__PURE__ */ jsxs("code", { children: [
903
+ "--",
904
+ field.key
905
+ ] })
906
+ ] }),
907
+ /* @__PURE__ */ jsxs("span", { className: "theme-panel-token-input", children: [
908
+ /* @__PURE__ */ jsx(
909
+ ColorPicker,
910
+ {
911
+ className: "theme-panel-token-picker",
912
+ value: tokenPickerValue(draftTokens[field.key], draftSurface),
913
+ onChange: (value) => updateDraftToken(field.key, value),
914
+ placement: "left",
915
+ "aria-label": `\u9009\u62E9 ${field.label}`,
916
+ children: /* @__PURE__ */ jsx(
917
+ "span",
918
+ {
919
+ className: "theme-panel-token-swatch",
920
+ style: { background: draftTokens[field.key] }
921
+ }
922
+ )
923
+ }
924
+ ),
925
+ /* @__PURE__ */ jsx(
926
+ Input,
927
+ {
928
+ size: "sm",
929
+ value: draftTokens[field.key] ?? "",
930
+ onValueChange: (value) => updateDraftToken(field.key, value)
931
+ }
932
+ )
933
+ ] })
934
+ ] }, field.key) : /* @__PURE__ */ jsxs("div", { className: "theme-panel-token-field scale", children: [
935
+ /* @__PURE__ */ jsxs("span", { className: "theme-panel-token-label", children: [
936
+ /* @__PURE__ */ jsx("span", { children: field.label }),
937
+ /* @__PURE__ */ jsxs("code", { children: [
938
+ "--",
939
+ field.key
940
+ ] })
941
+ ] }),
942
+ /* @__PURE__ */ jsxs("span", { className: "theme-panel-token-scale", children: [
943
+ /* @__PURE__ */ jsx(
944
+ Input,
945
+ {
946
+ size: "sm",
947
+ value: draftTokens[field.key] ?? "1",
948
+ onValueChange: (value) => updateDraftToken(field.key, value || "1")
949
+ }
950
+ ),
951
+ /* @__PURE__ */ jsx(
952
+ Slider,
953
+ {
954
+ value: parseScaleToken(draftTokens[field.key]),
955
+ onChange: (value) => updateDraftToken(field.key, formatScaleToken(value)),
956
+ min: 0.6,
957
+ max: field.key === "shadow-float-scale" ? 1.8 : 1.6,
958
+ step: 0.05
959
+ }
960
+ )
961
+ ] })
962
+ ] }, field.key)
963
+ ) })
964
+ ] }),
965
+ /* @__PURE__ */ jsxs("div", { className: "theme-panel-advanced-section", children: [
966
+ /* @__PURE__ */ jsxs("div", { className: "theme-panel-advanced-title", children: [
967
+ /* @__PURE__ */ jsx("span", { children: "\u5F3A\u8C03 palette" }),
968
+ /* @__PURE__ */ jsx("small", { children: "\u5B8C\u6574\u8986\u5199 accent / ink / soft / glow" })
969
+ ] }),
970
+ /* @__PURE__ */ jsx("div", { className: "theme-panel-token-grid", children: ACCENT_PALETTE_FIELDS.map((field) => /* @__PURE__ */ jsxs("div", { className: "theme-panel-token-field", children: [
971
+ /* @__PURE__ */ jsxs("span", { className: "theme-panel-token-label", children: [
972
+ /* @__PURE__ */ jsx("span", { children: field.label }),
973
+ /* @__PURE__ */ jsxs("code", { children: [
974
+ "accent.",
975
+ field.key
976
+ ] })
977
+ ] }),
978
+ /* @__PURE__ */ jsxs("span", { className: "theme-panel-token-input", children: [
979
+ /* @__PURE__ */ jsx(
980
+ ColorPicker,
981
+ {
982
+ className: "theme-panel-token-picker",
983
+ value: tokenPickerValue(draftAccentPalette[field.key], draftAccent),
984
+ onChange: (value) => updateDraftAccentSlot(field.key, value),
985
+ placement: "left",
986
+ "aria-label": `\u9009\u62E9 ${field.label}`,
987
+ children: /* @__PURE__ */ jsx(
988
+ "span",
989
+ {
990
+ className: "theme-panel-token-swatch",
991
+ style: { background: draftAccentPalette[field.key] }
992
+ }
993
+ )
994
+ }
995
+ ),
996
+ /* @__PURE__ */ jsx(
997
+ Input,
998
+ {
999
+ size: "sm",
1000
+ value: draftAccentPalette[field.key],
1001
+ onValueChange: (value) => updateDraftAccentSlot(field.key, value)
1002
+ }
1003
+ )
1004
+ ] })
1005
+ ] }, field.key)) })
1006
+ ] })
1007
+ ] }),
1008
+ /* @__PURE__ */ jsxs(
1009
+ "div",
1010
+ {
1011
+ className: "theme-panel-create-preview",
1012
+ style: {
1013
+ "--preview-bg": draftTokens.bg,
1014
+ "--preview-fg": draftTokens.fg,
1015
+ "--preview-accent": draftAccentPalette.accent,
1016
+ "--preview-radius": `${draftRadius}px`,
1017
+ "--preview-shadow-dark": draftTokens["shadow-dark"],
1018
+ "--preview-shadow-light": draftTokens["shadow-light"],
1019
+ "--preview-shadow-scale": draftTokens["shadow-scale"] ?? "1",
1020
+ "--preview-accent-glow": draftAccentPalette.glow,
1021
+ "--preview-font": fontToStack(draftFont)
1022
+ },
1023
+ children: [
1024
+ /* @__PURE__ */ jsxs("span", { className: "theme-panel-create-preview-label", children: [
1025
+ /* @__PURE__ */ jsx(Icon, { name: "palette", size: 13 }),
1026
+ /* @__PURE__ */ jsx("span", { children: draftName.trim() || "\u81EA\u5B9A\u4E49\u4E3B\u9898" })
1027
+ ] }),
1028
+ /* @__PURE__ */ jsx("i", { "aria-hidden": true })
1029
+ ]
1030
+ }
1031
+ ),
1032
+ /* @__PURE__ */ jsxs("div", { className: "theme-panel-create-actions", children: [
1033
+ /* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", size: "sm", icon: "x", onClick: cancelCreateTheme, children: "\u53D6\u6D88" }),
1034
+ /* @__PURE__ */ jsx(
1035
+ Button,
1036
+ {
1037
+ type: "button",
1038
+ variant: "primary",
1039
+ size: "sm",
1040
+ icon: "check",
1041
+ onClick: saveCustomTheme,
1042
+ disabled: !draftName.trim(),
1043
+ children: "\u4FDD\u5B58\u4E3B\u9898"
1044
+ }
1045
+ )
1046
+ ] })
1047
+ ] })
1048
+ ] }),
1049
+ sections.includes("accent") && /* @__PURE__ */ jsxs("div", { className: "theme-panel-row", children: [
1050
+ /* @__PURE__ */ jsxs("div", { className: "theme-panel-label", children: [
1051
+ /* @__PURE__ */ jsx("span", { children: "\u5F3A\u8C03\u8272" }),
1052
+ /* @__PURE__ */ jsx("span", { children: theme.accent === "custom" ? customAccent : theme.accent })
1053
+ ] }),
1054
+ /* @__PURE__ */ jsxs("div", { className: "theme-panel-swatches", children: [
1055
+ Object.keys(ACCENT_PRESETS).map((key) => /* @__PURE__ */ jsx(
1056
+ Button,
1057
+ {
1058
+ type: "button",
1059
+ size: "sm",
1060
+ "aria-label": key,
1061
+ className: `theme-panel-swatch ${theme.accent === key ? "active" : ""}`,
1062
+ style: { background: ACCENT_PRESETS[key].accent },
1063
+ onClick: () => theme.setAccent(key)
1064
+ },
1065
+ key
1066
+ )),
1067
+ /* @__PURE__ */ jsx(
1068
+ ColorPicker,
1069
+ {
1070
+ size: "sm",
1071
+ value: customAccent,
1072
+ onChange: (value) => {
1073
+ setCustomAccent(value);
1074
+ theme.setAccent(value);
1075
+ }
1076
+ }
1077
+ )
1078
+ ] })
1079
+ ] }),
1080
+ sections.includes("shadow") && /* @__PURE__ */ jsxs("div", { className: "theme-panel-row theme-panel-shadow", children: [
1081
+ /* @__PURE__ */ jsxs("div", { className: "theme-panel-label", children: [
1082
+ /* @__PURE__ */ jsx("span", { children: "\u9634\u5F71\u5F3A\u5EA6" }),
1083
+ /* @__PURE__ */ jsx("span", { children: theme.intensity })
1084
+ ] }),
1085
+ /* @__PURE__ */ jsx(Slider, { value: theme.intensity, onChange: theme.setIntensity, min: 1, max: 10, step: 1 }),
1086
+ /* @__PURE__ */ jsxs("div", { className: "theme-panel-label", children: [
1087
+ /* @__PURE__ */ jsx("span", { children: "\u9634\u5F71\u6269\u6563" }),
1088
+ /* @__PURE__ */ jsxs("span", { children: [
1089
+ formatScaleToken(shadowScale),
1090
+ "x"
1091
+ ] })
1092
+ ] }),
1093
+ /* @__PURE__ */ jsx(
1094
+ Slider,
1095
+ {
1096
+ value: shadowScale,
1097
+ onChange: (value) => updateThemeToken("shadow-scale", formatScaleToken(value)),
1098
+ min: 0.6,
1099
+ max: 1.6,
1100
+ step: 0.05
1101
+ }
1102
+ ),
1103
+ /* @__PURE__ */ jsxs("div", { className: "theme-panel-label", children: [
1104
+ /* @__PURE__ */ jsx("span", { children: "\u6D6E\u5C42\u6DF1\u5EA6" }),
1105
+ /* @__PURE__ */ jsxs("span", { children: [
1106
+ formatScaleToken(shadowFloatScale),
1107
+ "x"
1108
+ ] })
1109
+ ] }),
1110
+ /* @__PURE__ */ jsx(
1111
+ Slider,
1112
+ {
1113
+ value: shadowFloatScale,
1114
+ onChange: (value) => updateThemeToken("shadow-float-scale", formatScaleToken(value)),
1115
+ min: 0.6,
1116
+ max: 1.8,
1117
+ step: 0.05
1118
+ }
1119
+ )
1120
+ ] }),
1121
+ sections.includes("intensity") && !sections.includes("shadow") && /* @__PURE__ */ jsxs("div", { className: "theme-panel-row", children: [
1122
+ /* @__PURE__ */ jsxs("div", { className: "theme-panel-label", children: [
1123
+ /* @__PURE__ */ jsx("span", { children: "\u9634\u5F71" }),
1124
+ /* @__PURE__ */ jsx("span", { children: theme.intensity })
1125
+ ] }),
1126
+ /* @__PURE__ */ jsx(Slider, { value: theme.intensity, onChange: theme.setIntensity, min: 1, max: 10, step: 1 })
1127
+ ] }),
1128
+ sections.includes("radius") && /* @__PURE__ */ jsxs("div", { className: "theme-panel-row", children: [
1129
+ /* @__PURE__ */ jsxs("div", { className: "theme-panel-label", children: [
1130
+ /* @__PURE__ */ jsx("span", { children: "\u5706\u89D2" }),
1131
+ /* @__PURE__ */ jsxs("span", { children: [
1132
+ theme.radius,
1133
+ "px"
1134
+ ] })
1135
+ ] }),
1136
+ /* @__PURE__ */ jsx(Slider, { value: theme.radius, onChange: theme.setRadius, min: 8, max: 36, step: 2 })
1137
+ ] }),
1138
+ sections.includes("font") && /* @__PURE__ */ jsxs("div", { className: "theme-panel-row", children: [
1139
+ /* @__PURE__ */ jsx("div", { className: "theme-panel-label", children: /* @__PURE__ */ jsx("span", { children: "\u5B57\u4F53" }) }),
1140
+ /* @__PURE__ */ jsx(
1141
+ RadioGroup,
1142
+ {
1143
+ variant: "segmented",
1144
+ size: "sm",
1145
+ value: typeof theme.font === "string" ? theme.font : "system",
1146
+ options: FONT_OPTIONS.map((option) => ({ value: option.value, label: option.label })),
1147
+ onChange: (value) => theme.setFont(value)
1148
+ }
1149
+ )
1150
+ ] }),
1151
+ sections.includes("density") && /* @__PURE__ */ jsxs("div", { className: "theme-panel-row", children: [
1152
+ /* @__PURE__ */ jsx("div", { className: "theme-panel-label", children: /* @__PURE__ */ jsx("span", { children: "\u5BC6\u5EA6" }) }),
1153
+ /* @__PURE__ */ jsx(
1154
+ RadioGroup,
1155
+ {
1156
+ variant: "segmented",
1157
+ size: "sm",
1158
+ value: theme.density,
1159
+ options: DENSITY_OPTIONS.map((option) => ({ value: option.value, label: option.label })),
1160
+ onChange: theme.setDensity
1161
+ }
1162
+ )
1163
+ ] }),
1164
+ showReset && /* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", size: "sm", icon: "reload", block: true, onClick: resetTheme, children: "\u91CD\u7F6E\u4E3B\u9898" })
1165
+ ] });
1166
+ }
1167
+ );
1168
+ ThemePanel.displayName = "ThemePanel";
1169
+
1170
+ export { THEME_PANEL_DEFAULT_PRESET_OPTIONS, THEME_PANEL_DEFAULT_THEME_PRESETS, ThemePanel };