@fangxinyan/lumina 0.5.0 → 0.5.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.
Files changed (184) hide show
  1. package/dist/Accordion.cjs +3 -3
  2. package/dist/Accordion.js +2 -2
  3. package/dist/Alert.cjs +3 -3
  4. package/dist/Alert.js +2 -2
  5. package/dist/AutoComplete.cjs +5 -5
  6. package/dist/AutoComplete.js +4 -4
  7. package/dist/Button.cjs +4 -4
  8. package/dist/Button.js +2 -2
  9. package/dist/Calendar.cjs +3 -3
  10. package/dist/Calendar.js +2 -2
  11. package/dist/Cascader.cjs +4 -4
  12. package/dist/Cascader.js +3 -3
  13. package/dist/Checkbox.cjs +4 -4
  14. package/dist/Checkbox.js +2 -2
  15. package/dist/ColorPicker.cjs +3 -3
  16. package/dist/ColorPicker.js +2 -2
  17. package/dist/CommandPalette.cjs +4 -4
  18. package/dist/CommandPalette.js +3 -3
  19. package/dist/Drawer.cjs +3 -3
  20. package/dist/Drawer.js +2 -2
  21. package/dist/Icon.cjs +3 -3
  22. package/dist/Icon.d.cts +1 -1
  23. package/dist/Icon.d.ts +1 -1
  24. package/dist/Icon.js +1 -1
  25. package/dist/Image.cjs +4 -4
  26. package/dist/Image.js +2 -2
  27. package/dist/Input.cjs +4 -4
  28. package/dist/Input.js +2 -2
  29. package/dist/InputNumber.cjs +4 -4
  30. package/dist/InputNumber.js +3 -3
  31. package/dist/Modal.cjs +4 -4
  32. package/dist/Modal.js +3 -3
  33. package/dist/Pagination.cjs +6 -6
  34. package/dist/Pagination.js +5 -5
  35. package/dist/Popover-DVGQGWX6.css +103 -0
  36. package/dist/Popover.cjs +3 -3
  37. package/dist/Popover.d.cts +23 -1
  38. package/dist/Popover.d.ts +23 -1
  39. package/dist/Popover.js +2 -2
  40. package/dist/Select.cjs +5 -5
  41. package/dist/Select.js +4 -4
  42. package/dist/Table.cjs +9 -9
  43. package/dist/Table.js +7 -7
  44. package/dist/Tag.cjs +4 -4
  45. package/dist/Tag.js +2 -2
  46. package/dist/Timeline-RHZAZKZ7.css +136 -0
  47. package/dist/Timeline.cjs +13 -0
  48. package/dist/Timeline.cjs.map +1 -0
  49. package/dist/Timeline.d.cts +38 -0
  50. package/dist/Timeline.d.ts +38 -0
  51. package/dist/Timeline.js +4 -0
  52. package/dist/Timeline.js.map +1 -0
  53. package/dist/{Toast-6PVSAXQ5.css → Toast-YSACW3EM.css} +2 -2
  54. package/dist/Toast.cjs +4 -4
  55. package/dist/Toast.js +2 -2
  56. package/dist/{Tooltip-ST24GY4S.css → Tooltip-DMKUPC24.css} +1 -0
  57. package/dist/Tooltip.cjs +3 -3
  58. package/dist/Tooltip.js +2 -2
  59. package/dist/Typography.cjs +7 -7
  60. package/dist/Typography.js +2 -2
  61. package/dist/{chunk-BCPAY65C.cjs → chunk-2D5VCIJZ.cjs} +7 -7
  62. package/dist/{chunk-BCPAY65C.cjs.map → chunk-2D5VCIJZ.cjs.map} +1 -1
  63. package/dist/{chunk-LLNEDEST.cjs → chunk-2OBQOEFD.cjs} +4 -4
  64. package/dist/{chunk-LLNEDEST.cjs.map → chunk-2OBQOEFD.cjs.map} +1 -1
  65. package/dist/{chunk-N73JGXYZ.cjs → chunk-3ES5QPAF.cjs} +4 -4
  66. package/dist/{chunk-N73JGXYZ.cjs.map → chunk-3ES5QPAF.cjs.map} +1 -1
  67. package/dist/{chunk-YCHUHMNP.cjs → chunk-3KQKEE5O.cjs} +5 -4
  68. package/dist/chunk-3KQKEE5O.cjs.map +1 -0
  69. package/dist/{chunk-RZ2E3XEU.cjs → chunk-3XIDJEYR.cjs} +21 -6
  70. package/dist/chunk-3XIDJEYR.cjs.map +1 -0
  71. package/dist/{chunk-IOWREUEP.js → chunk-3YYOYDKI.js} +4 -4
  72. package/dist/{chunk-IOWREUEP.js.map → chunk-3YYOYDKI.js.map} +1 -1
  73. package/dist/{chunk-PKXXR76Q.js → chunk-4ADDAZK3.js} +3 -3
  74. package/dist/{chunk-PKXXR76Q.js.map → chunk-4ADDAZK3.js.map} +1 -1
  75. package/dist/{chunk-TZLM5GF4.js → chunk-5SJJI3HL.js} +4 -4
  76. package/dist/{chunk-TZLM5GF4.js.map → chunk-5SJJI3HL.js.map} +1 -1
  77. package/dist/{chunk-2ENTRT7R.cjs → chunk-AJEF2ZB7.cjs} +16 -6
  78. package/dist/chunk-AJEF2ZB7.cjs.map +1 -0
  79. package/dist/{chunk-V2DIQ3RH.js → chunk-ANAQER3T.js} +21 -6
  80. package/dist/chunk-ANAQER3T.js.map +1 -0
  81. package/dist/{chunk-FXQGPHK2.js → chunk-AZRJZM7W.js} +3 -3
  82. package/dist/{chunk-FXQGPHK2.js.map → chunk-AZRJZM7W.js.map} +1 -1
  83. package/dist/{chunk-3BZ47QNV.cjs → chunk-BIXW4ZYW.cjs} +7 -7
  84. package/dist/{chunk-3BZ47QNV.cjs.map → chunk-BIXW4ZYW.cjs.map} +1 -1
  85. package/dist/{chunk-IJA26LRY.cjs → chunk-BPDWBY6Y.cjs} +4 -4
  86. package/dist/{chunk-IJA26LRY.cjs.map → chunk-BPDWBY6Y.cjs.map} +1 -1
  87. package/dist/{chunk-77TZHI76.cjs → chunk-D26YHP2Y.cjs} +7 -7
  88. package/dist/{chunk-77TZHI76.cjs.map → chunk-D26YHP2Y.cjs.map} +1 -1
  89. package/dist/{chunk-T4PI2ZX7.cjs → chunk-D3GZSL2B.cjs} +16 -17
  90. package/dist/chunk-D3GZSL2B.cjs.map +1 -0
  91. package/dist/{chunk-VQBZKRIB.cjs → chunk-DF5K2BZ2.cjs} +6 -6
  92. package/dist/{chunk-VQBZKRIB.cjs.map → chunk-DF5K2BZ2.cjs.map} +1 -1
  93. package/dist/{chunk-7M7NAMR5.js → chunk-DLGFIRVW.js} +14 -4
  94. package/dist/chunk-DLGFIRVW.js.map +1 -0
  95. package/dist/{chunk-6Z24VO3K.js → chunk-E7UQSFKF.js} +3 -3
  96. package/dist/{chunk-6Z24VO3K.js.map → chunk-E7UQSFKF.js.map} +1 -1
  97. package/dist/{chunk-KW7Z4IQC.js → chunk-FLPHVK45.js} +3 -3
  98. package/dist/{chunk-KW7Z4IQC.js.map → chunk-FLPHVK45.js.map} +1 -1
  99. package/dist/{chunk-WUOFJPZ4.js → chunk-GB5NAXBP.js} +3 -3
  100. package/dist/{chunk-WUOFJPZ4.js.map → chunk-GB5NAXBP.js.map} +1 -1
  101. package/dist/{chunk-SMHXSEBD.cjs → chunk-GT45MQAK.cjs} +7 -7
  102. package/dist/{chunk-SMHXSEBD.cjs.map → chunk-GT45MQAK.cjs.map} +1 -1
  103. package/dist/{chunk-TZXEZFCI.cjs → chunk-H2QTLV5T.cjs} +5 -5
  104. package/dist/{chunk-TZXEZFCI.cjs.map → chunk-H2QTLV5T.cjs.map} +1 -1
  105. package/dist/{chunk-FFZLSY2N.js → chunk-HHPYY4LH.js} +4 -4
  106. package/dist/{chunk-FFZLSY2N.js.map → chunk-HHPYY4LH.js.map} +1 -1
  107. package/dist/{chunk-XYVJ3FBQ.cjs → chunk-I7UJA6RM.cjs} +5 -5
  108. package/dist/{chunk-XYVJ3FBQ.cjs.map → chunk-I7UJA6RM.cjs.map} +1 -1
  109. package/dist/{chunk-YFBHVTKN.cjs → chunk-IJIQ4H6C.cjs} +7 -7
  110. package/dist/{chunk-YFBHVTKN.cjs.map → chunk-IJIQ4H6C.cjs.map} +1 -1
  111. package/dist/{chunk-LXNR6TQK.js → chunk-ILVNMES2.js} +3 -3
  112. package/dist/{chunk-LXNR6TQK.js.map → chunk-ILVNMES2.js.map} +1 -1
  113. package/dist/{chunk-JXHMJUVI.js → chunk-JELHUUM5.js} +3 -3
  114. package/dist/{chunk-JXHMJUVI.js.map → chunk-JELHUUM5.js.map} +1 -1
  115. package/dist/{chunk-CTYW42GG.js → chunk-JQZFOIX6.js} +6 -6
  116. package/dist/{chunk-CTYW42GG.js.map → chunk-JQZFOIX6.js.map} +1 -1
  117. package/dist/{chunk-I7WLFADD.js → chunk-LWN2PXW7.js} +3 -3
  118. package/dist/{chunk-I7WLFADD.js.map → chunk-LWN2PXW7.js.map} +1 -1
  119. package/dist/{chunk-I2HHC6QW.js → chunk-N5W6XJI2.js} +3 -3
  120. package/dist/{chunk-I2HHC6QW.js.map → chunk-N5W6XJI2.js.map} +1 -1
  121. package/dist/chunk-P2AV5BD7.cjs +137 -0
  122. package/dist/chunk-P2AV5BD7.cjs.map +1 -0
  123. package/dist/{chunk-ZFJHUOFU.js → chunk-P4XPESR2.js} +4 -4
  124. package/dist/{chunk-ZFJHUOFU.js.map → chunk-P4XPESR2.js.map} +1 -1
  125. package/dist/{chunk-AESLEYST.js → chunk-RJNGXR5Y.js} +4 -4
  126. package/dist/{chunk-AESLEYST.js.map → chunk-RJNGXR5Y.js.map} +1 -1
  127. package/dist/chunk-S3NIRNWM.js +86 -0
  128. package/dist/chunk-S3NIRNWM.js.map +1 -0
  129. package/dist/{chunk-HJIKU6MF.cjs → chunk-S7RFIMA3.cjs} +4 -4
  130. package/dist/{chunk-HJIKU6MF.cjs.map → chunk-S7RFIMA3.cjs.map} +1 -1
  131. package/dist/chunk-TAYFI4RG.cjs +108 -0
  132. package/dist/chunk-TAYFI4RG.cjs.map +1 -0
  133. package/dist/{chunk-OZVPJWXO.cjs → chunk-TCPTBLDV.cjs} +5 -5
  134. package/dist/{chunk-OZVPJWXO.cjs.map → chunk-TCPTBLDV.cjs.map} +1 -1
  135. package/dist/{chunk-E62JFAHW.js → chunk-TGUDT3GK.js} +4 -4
  136. package/dist/{chunk-E62JFAHW.js.map → chunk-TGUDT3GK.js.map} +1 -1
  137. package/dist/{chunk-XCYE4OQV.js → chunk-TMRSI543.js} +3 -3
  138. package/dist/{chunk-XCYE4OQV.js.map → chunk-TMRSI543.js.map} +1 -1
  139. package/dist/{chunk-RWHWEQQX.cjs → chunk-U7TAQLPN.cjs} +6 -6
  140. package/dist/{chunk-RWHWEQQX.cjs.map → chunk-U7TAQLPN.cjs.map} +1 -1
  141. package/dist/chunk-UEHONGPZ.js +115 -0
  142. package/dist/chunk-UEHONGPZ.js.map +1 -0
  143. package/dist/{chunk-NN7WMXY4.cjs → chunk-UUY7EDVJ.cjs} +4 -4
  144. package/dist/{chunk-NN7WMXY4.cjs.map → chunk-UUY7EDVJ.cjs.map} +1 -1
  145. package/dist/{chunk-OM76QWUN.js → chunk-UXABXEWT.js} +3 -3
  146. package/dist/{chunk-OM76QWUN.js.map → chunk-UXABXEWT.js.map} +1 -1
  147. package/dist/{chunk-MDQNUKCP.cjs → chunk-V6466VMN.cjs} +14 -14
  148. package/dist/{chunk-MDQNUKCP.cjs.map → chunk-V6466VMN.cjs.map} +1 -1
  149. package/dist/{chunk-O7C6S644.js → chunk-WBL7LOIH.js} +3 -3
  150. package/dist/{chunk-O7C6S644.js.map → chunk-WBL7LOIH.js.map} +1 -1
  151. package/dist/{chunk-RQV7SMIZ.cjs → chunk-WKNVNN2K.cjs} +5 -5
  152. package/dist/{chunk-RQV7SMIZ.cjs.map → chunk-WKNVNN2K.cjs.map} +1 -1
  153. package/dist/{chunk-HXSAH4Y6.cjs → chunk-WR3FML2W.cjs} +7 -7
  154. package/dist/{chunk-HXSAH4Y6.cjs.map → chunk-WR3FML2W.cjs.map} +1 -1
  155. package/dist/{chunk-QOGROEVD.js → chunk-X3JG3IR6.js} +6 -5
  156. package/dist/chunk-X3JG3IR6.js.map +1 -0
  157. package/dist/{chunk-6XZ362VL.js → chunk-XT7RXXOE.js} +6 -7
  158. package/dist/chunk-XT7RXXOE.js.map +1 -0
  159. package/dist/{chunk-WVBFQB26.cjs → chunk-ZSR5JSYZ.cjs} +8 -8
  160. package/dist/{chunk-WVBFQB26.cjs.map → chunk-ZSR5JSYZ.cjs.map} +1 -1
  161. package/dist/index.cjs +65 -60
  162. package/dist/index.cjs.map +1 -1
  163. package/dist/index.d.cts +2 -1
  164. package/dist/index.d.ts +2 -1
  165. package/dist/index.js +26 -25
  166. package/dist/index.js.map +1 -1
  167. package/dist/styles.css +86 -4
  168. package/docs/llms/popover.md +138 -6
  169. package/docs/llms/timeline.md +140 -0
  170. package/docs/llms.md +3 -2
  171. package/package.json +5 -1
  172. package/dist/Popover-NYEKT5CQ.css +0 -10
  173. package/dist/chunk-2ENTRT7R.cjs.map +0 -1
  174. package/dist/chunk-3UU2PUK4.js +0 -66
  175. package/dist/chunk-3UU2PUK4.js.map +0 -1
  176. package/dist/chunk-6XZ362VL.js.map +0 -1
  177. package/dist/chunk-7M7NAMR5.js.map +0 -1
  178. package/dist/chunk-O2HMH5BI.cjs +0 -88
  179. package/dist/chunk-O2HMH5BI.cjs.map +0 -1
  180. package/dist/chunk-QOGROEVD.js.map +0 -1
  181. package/dist/chunk-RZ2E3XEU.cjs.map +0 -1
  182. package/dist/chunk-T4PI2ZX7.cjs.map +0 -1
  183. package/dist/chunk-V2DIQ3RH.js.map +0 -1
  184. package/dist/chunk-YCHUHMNP.cjs.map +0 -1
package/dist/styles.css CHANGED
@@ -1542,6 +1542,7 @@ input, textarea, select { font-family: inherit; color: inherit; }
1542
1542
  .tip-anchor {
1543
1543
  position: relative;
1544
1544
  display: inline-flex;
1545
+ align-self: flex-start;
1545
1546
  }
1546
1547
  .tip {
1547
1548
  background: var(--bg-sunken);
@@ -1576,7 +1577,7 @@ input, textarea, select { font-family: inherit; color: inherit; }
1576
1577
  box-shadow: var(--neu-float);
1577
1578
  padding: 12px 16px;
1578
1579
  min-width: 240px;
1579
- display: flex; align-items: flex-start; gap: 10px;
1580
+ display: flex; align-items: center; gap: 10px;
1580
1581
  font-size: 13px;
1581
1582
  pointer-events: auto;
1582
1583
  animation: toastIn var(--dur-slow) var(--ease);
@@ -1585,7 +1586,7 @@ input, textarea, select { font-family: inherit; color: inherit; }
1585
1586
  .toast.success { border-color: var(--success); }
1586
1587
  .toast.warning { border-color: var(--warning); }
1587
1588
  .toast.danger { border-color: var(--danger); }
1588
- .toast .toast-icon { color: var(--accent); margin-top: 2px; }
1589
+ .toast .toast-icon { color: var(--accent); flex-shrink: 0; }
1589
1590
  .toast.success .toast-icon { color: var(--success); }
1590
1591
  .toast.warning .toast-icon { color: var(--warning); }
1591
1592
  .toast.danger .toast-icon { color: var(--danger); }
@@ -1606,10 +1607,91 @@ input, textarea, select { font-family: inherit; color: inherit; }
1606
1607
  z-index: 1000;
1607
1608
  background: var(--bg);
1608
1609
  border-radius: var(--r-md);
1609
- padding: var(--gap-3);
1610
1610
  min-width: 220px;
1611
1611
  box-shadow: var(--neu-float);
1612
- animation: menuIn var(--dur) var(--ease);
1612
+ position: relative;
1613
+ }
1614
+ /*
1615
+ * Direction-aware entrance.
1616
+ * We animate `opacity` + `translate` (the standalone property, NOT `transform`)
1617
+ * so we don't clobber the inline `transform: translateX(-50%)` that useFloating
1618
+ * applies for cross-axis centering.
1619
+ */
1620
+ .popover-bottom { animation: popoverInDown var(--dur) var(--ease); }
1621
+ .popover-top { animation: popoverInUp var(--dur) var(--ease); }
1622
+ .popover-left { animation: popoverInLeft var(--dur) var(--ease); }
1623
+ .popover-right { animation: popoverInRight var(--dur) var(--ease); }
1624
+ @keyframes popoverInDown { from { opacity: 0; translate: 0 -6px; } }
1625
+ @keyframes popoverInUp { from { opacity: 0; translate: 0 6px; } }
1626
+ @keyframes popoverInLeft { from { opacity: 0; translate: 6px 0; } }
1627
+ @keyframes popoverInRight { from { opacity: 0; translate: -6px 0; } }
1628
+ /* ---- Header ---- */
1629
+ .popover-header {
1630
+ display: flex;
1631
+ align-items: center;
1632
+ justify-content: space-between;
1633
+ padding: var(--gap-3) var(--gap-3) 0;
1634
+ gap: var(--gap-2);
1635
+ }
1636
+ .popover-title {
1637
+ font-weight: 600;
1638
+ font-size: 14px;
1639
+ color: var(--fg);
1640
+ }
1641
+ .popover-close {
1642
+ all: unset;
1643
+ cursor: pointer;
1644
+ font-size: 16px;
1645
+ color: var(--fg-muted);
1646
+ line-height: 1;
1647
+ padding: 2px 4px;
1648
+ border-radius: var(--r-xs);
1649
+ transition: color var(--dur-fast) var(--ease);
1650
+ margin-left: auto;
1651
+ }
1652
+ .popover-close:hover {
1653
+ color: var(--fg);
1654
+ }
1655
+ /* ---- Body ---- */
1656
+ .popover-body {
1657
+ padding: var(--gap-3);
1658
+ }
1659
+ .popover-header + .popover-body {
1660
+ padding-top: var(--gap-2);
1661
+ }
1662
+ /* ---- Arrow ---- */
1663
+ .popover-arrow {
1664
+ position: absolute;
1665
+ width: 10px;
1666
+ height: 10px;
1667
+ background: var(--bg);
1668
+ box-shadow: 2px 2px 4px rgba(163, 177, 198, 0.2);
1669
+ transform: rotate(45deg);
1670
+ pointer-events: none;
1671
+ }
1672
+ .popover-arrow-bottom {
1673
+ top: -5px;
1674
+ left: 50%;
1675
+ margin-left: -5px;
1676
+ box-shadow: -2px -2px 4px rgba(163, 177, 198, 0.2);
1677
+ }
1678
+ .popover-arrow-top {
1679
+ bottom: -5px;
1680
+ left: 50%;
1681
+ margin-left: -5px;
1682
+ box-shadow: 2px 2px 4px rgba(163, 177, 198, 0.2);
1683
+ }
1684
+ .popover-arrow-left {
1685
+ right: -5px;
1686
+ top: 50%;
1687
+ margin-top: -5px;
1688
+ box-shadow: 2px -2px 4px rgba(163, 177, 198, 0.2);
1689
+ }
1690
+ .popover-arrow-right {
1691
+ left: -5px;
1692
+ top: 50%;
1693
+ margin-top: -5px;
1694
+ box-shadow: -2px 2px 4px rgba(163, 177, 198, 0.2);
1613
1695
  }
1614
1696
  /* ============ Alert ============ */
1615
1697
  .alert {
@@ -1,6 +1,6 @@
1
1
  # Popover 气泡卡片
2
2
 
3
- > 比 Tooltip 更丰富,可承载交互内容。
3
+ > 比 Tooltip 更丰富,可承载交互内容。
4
4
 
5
5
  ## 导入
6
6
 
@@ -10,11 +10,137 @@ import { Popover } from "@fangxinyan/lumina";
10
10
 
11
11
  ## 示例
12
12
 
13
- ### 基础
13
+ ### 基础用法
14
+
15
+ 点击触发,弹出气泡卡片
16
+
17
+ ```tsx
18
+ <Row gap={24}>
19
+ <Popover
20
+ title="确认删除?"
21
+ content={
22
+ <div>
23
+ <div style={{ color: "var(--fg-muted)", fontSize: 13, marginBottom: 12 }}>
24
+ 删除后无法恢复。
25
+ </div>
26
+ <Row gap={6}>
27
+ <Button size="sm" variant="ghost">取消</Button>
28
+ <Button size="sm" variant="danger">删除</Button>
29
+ </Row>
30
+ </div>
31
+ }
32
+ >
33
+ <Button variant="danger" icon="trash">删除项目</Button>
34
+ </Popover>
35
+
36
+ <Popover
37
+ placement="right"
38
+ content={
39
+ <div style={{ display: "flex", alignItems: "center", gap: 10, minWidth: 160 }}>
40
+ <Avatar alt="金" size="sm" />
41
+ <div>
42
+ <div style={{ fontSize: 13, fontWeight: 600 }}>金伟</div>
43
+ <div style={{ fontSize: 11, color: "var(--fg-muted)" }}>设计总监</div>
44
+ </div>
45
+ </div>
46
+ }
47
+ >
48
+ <Avatar alt="金" />
49
+ </Popover>
50
+ </Row>
51
+ ```
52
+
53
+ ### 四方向
54
+
55
+ 支持 top / bottom / left / right 四个方向
56
+
57
+ ```tsx
58
+ <div style={{ display: "flex", flexWrap: "wrap", justifyContent: "center", gap: 12 }}>
59
+ <Popover placement="top" arrow content={<div>上方弹出内容</div>}>
60
+ <Button variant="ghost">上方</Button>
61
+ </Popover>
62
+ <Popover placement="bottom" arrow content={<div>下方弹出内容</div>}>
63
+ <Button variant="ghost">下方</Button>
64
+ </Popover>
65
+ <Popover placement="left" arrow content={<div>左侧弹出内容</div>}>
66
+ <Button variant="ghost">左侧</Button>
67
+ </Popover>
68
+ <Popover placement="right" arrow content={<div>右侧弹出内容</div>}>
69
+ <Button variant="ghost">右侧</Button>
70
+ </Popover>
71
+ </div>
72
+ ```
73
+
74
+ ### 箭头
75
+
76
+ arrow 属性添加指向触发元素的小箭头
77
+
78
+ ```tsx
79
+ <Popover
80
+ arrow
81
+ title="系统通知"
82
+ content={<div style={{ color: "var(--fg-muted)", fontSize: 13 }}>你有 3 条未读消息。</div>}
83
+ >
84
+ <Button icon="bell">消息</Button>
85
+ </Popover>
86
+ ```
87
+
88
+ ### 可关闭
89
+
90
+ closable 显示关闭按钮,适合信息提示场景
91
+
92
+ ```tsx
93
+ <Popover
94
+ closable
95
+ arrow
96
+ title="注意事项"
97
+ content={<div style={{ color: "var(--fg-muted)", fontSize: 13 }}>此操作需要管理员权限才能执行。</div>}
98
+ >
99
+ <Button icon="alert">权限</Button>
100
+ </Popover>
101
+ ```
102
+
103
+ ### Hover 触发
104
+
105
+ trigger="hover" 鼠标悬停触发
106
+
107
+ ```tsx
108
+ <Popover
109
+ trigger="hover"
110
+ arrow
111
+ content={
112
+ <div style={{ display: "flex", alignItems: "center", gap: 10, minWidth: 160 }}>
113
+ <Avatar alt="云" size="sm" />
114
+ <div>
115
+ <div style={{ fontSize: 13, fontWeight: 600 }}>云曦</div>
116
+ <div style={{ fontSize: 11, color: "var(--fg-muted)" }}>前端工程师</div>
117
+ </div>
118
+ </div>
119
+ }
120
+ >
121
+ <Avatar alt="云" />
122
+ </Popover>
123
+ ```
124
+
125
+ ### 表单内容
126
+
127
+ 气泡内可放置表单等复杂交互
14
128
 
15
129
  ```tsx
16
- <Popover content={<>...</>}>
17
- <Button>触发</Button>
130
+ <Popover
131
+ title="快速备注"
132
+ closable
133
+ arrow
134
+ content={
135
+ <div style={{ display: "flex", flexDirection: "column", gap: 10 }}>
136
+ <Input placeholder="输入备注..." />
137
+ <div style={{ display: "flex", justifyContent: "flex-end", gap: 6 }}>
138
+ <Button size="sm">保存</Button>
139
+ </div>
140
+ </div>
141
+ }
142
+ >
143
+ <Button icon="edit">备注</Button>
18
144
  </Popover>
19
145
  ```
20
146
 
@@ -25,9 +151,15 @@ import { Popover } from "@fangxinyan/lumina";
25
151
  | Prop | 类型 | 默认 | 说明 |
26
152
  | --- | --- | --- | --- |
27
153
  | content \* | `ReactNode` | — | 浮层内容 |
28
- | placement | `"top" | "bottom" | "left" | "right"` | `"bottom"` | 位置 |
154
+ | title | `ReactNode` | — | 标题 |
155
+ | placement | `"top" | "bottom" | "left" | "right"` | `"bottom"` | 弹出位置 |
29
156
  | trigger | `"click" | "hover"` | `"click"` | 触发方式 |
30
- | open / defaultOpen / onOpenChange | `—` | — | 受控显示 |
157
+ | arrow | `boolean` | `false` | 显示箭头 |
158
+ | closable | `boolean` | `false` | 显示关闭按钮 |
159
+ | width | `number | "auto"` | — | 面板宽度,"auto" 自适应 |
160
+ | open | `boolean` | — | 受控显示状态 |
161
+ | defaultOpen | `boolean` | `false` | 非受控初始状态 |
162
+ | onOpenChange | `(open: boolean) => void` | — | 显示状态变化回调 |
31
163
 
32
164
 
33
165
  ---
@@ -0,0 +1,140 @@
1
+ # Timeline 时间线
2
+
3
+ > 垂直时间线,支持等待状态、自定义圆点、交替布局
4
+
5
+ ## 示例
6
+
7
+ ### 基础用法
8
+
9
+ 最简单的时间线
10
+
11
+ ```tsx
12
+ <Timeline
13
+ items={[
14
+ { children: "创建项目 2024-01-01" },
15
+ { children: "初始化仓库 2024-01-05" },
16
+ { children: "发布 v0.1.0 2024-02-01" },
17
+ { children: "里程碑达成 2024-03-15" },
18
+ ]}
19
+ />
20
+ ```
21
+
22
+ ### 彩色节点
23
+
24
+ 通过 color 区分不同状态
25
+
26
+ ```tsx
27
+ <Timeline
28
+ items={[
29
+ { children: "成功部署", color: "success" },
30
+ { children: "告警通知", color: "warning" },
31
+ { children: "构建失败", color: "danger" },
32
+ { children: "信息更新", color: "info" },
33
+ ]}
34
+ />
35
+ ```
36
+
37
+ ### 等待状态
38
+
39
+ pending 属性展示加载中的末尾节点,适合表示流程尚未结束
40
+
41
+ ```tsx
42
+ <Timeline
43
+ pending
44
+ pendingContent="部署中..."
45
+ items={[
46
+ { children: "提交代码 10:21", color: "success" },
47
+ { children: "代码审查通过 10:45", color: "success" },
48
+ { children: "CI 构建完成 11:02", color: "success" },
49
+ ]}
50
+ />
51
+ ```
52
+
53
+ ### 自定义等待图标
54
+
55
+ pending 传入 ReactNode 自定义等待指示器
56
+
57
+ ```tsx
58
+ <Timeline
59
+ pending={<Icon name="clock" size={14} />}
60
+ pendingContent="等待审批..."
61
+ items={[
62
+ { children: "提交申请" },
63
+ { children: "部门审核通过" },
64
+ ]}
65
+ />
66
+ ```
67
+
68
+ ### 自定义圆点
69
+
70
+ 通过 dot 字段自定义每个节点的图标
71
+
72
+ ```tsx
73
+ <Timeline
74
+ items={[
75
+ { children: "项目创建", dot: <Icon name="folder" size={14} /> },
76
+ { children: "代码提交", dot: <Icon name="code" size={14} /> },
77
+ { children: "发布上线", dot: <Icon name="zap" size={14} /> },
78
+ ]}
79
+ />
80
+ ```
81
+
82
+ ### 交替模式
83
+
84
+ mode="alternate" 让内容交替出现在两侧
85
+
86
+ ```tsx
87
+ <Timeline
88
+ mode="alternate"
89
+ items={[
90
+ { children: "创建项目", label: "2024-01" },
91
+ { children: "完成设计稿", label: "2024-02" },
92
+ { children: "开发完成", label: "2024-03" },
93
+ { children: "发布上线", label: "2024-04" },
94
+ ]}
95
+ />
96
+ ```
97
+
98
+ ### 倒序
99
+
100
+ reverse 属性将时间线反转,最新的事件在最上面
101
+
102
+ ```tsx
103
+ <Timeline
104
+ reverse
105
+ pending
106
+ pendingContent="进行中..."
107
+ items={[
108
+ { children: "第一步:需求确认", color: "success" },
109
+ { children: "第二步:开发中", color: "success" },
110
+ { children: "第三步:测试", color: "warning" },
111
+ ]}
112
+ />
113
+ ```
114
+
115
+ ## API
116
+
117
+ **Timeline**
118
+
119
+ | Prop | 类型 | 默认 | 说明 |
120
+ | --- | --- | --- | --- |
121
+ | items \* | `TimelineItemConfig[]` | — | 时间线节点数组 |
122
+ | pending | `boolean | ReactNode` | `false` | 显示末尾等待节点;true 显示默认 spinner,传 ReactNode 自定义 |
123
+ | pendingContent | `ReactNode` | `"加载中..."` | 等待节点的文字内容 |
124
+ | mode | `"left" | "right" | "alternate"` | `"left"` | 布局模式 |
125
+ | reverse | `boolean` | `false` | 反转节点顺序 |
126
+
127
+
128
+ **TimelineItemConfig**
129
+
130
+ | Prop | 类型 | 默认 | 说明 |
131
+ | --- | --- | --- | --- |
132
+ | key | `string` | — | 唯一标识 |
133
+ | children | `ReactNode` | — | 节点内容 |
134
+ | label | `ReactNode` | — | 对侧标签(alternate 模式下使用) |
135
+ | color | `"accent" | "success" | "warning" | "danger" | "info" | "muted"` | `"accent"` | 圆点颜色 |
136
+ | dot | `ReactNode` | — | 自定义圆点内容 |
137
+
138
+
139
+ ---
140
+ [← 回到索引](../llms.md)
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.5.0`
6
+ - **版本**: `0.5.1`
7
7
  - **React 最低版本**: 18
8
8
  - **环境**: 带打包器的 React 工程(Vite / Next.js / Webpack / Remix / Electron + Vite 等)
9
9
  - **零运行时依赖**: 只依赖 `react` / `react-dom` (peer deps)
@@ -72,6 +72,7 @@
72
72
  - [Image 图片](./llms/image.md) — 凹陷外框包裹的图片容器,带预览、错误占位。
73
73
  - [Divider 分隔符](./llms/divider.md) — 对内容进行分割。
74
74
  - [Progress 进度](./llms/progress.md) — 条形进度 Progress 与环形进度 Ring。
75
+ - [Timeline 时间线](./llms/timeline.md) — 垂直时间线,支持等待状态、自定义圆点、交替布局
75
76
  - [List 列表](./llms/list.md) — 承载一组结构化的同质化数据。
76
77
  - [Table 表格](./llms/table.md) — 结构化数据展示。
77
78
  - [Table Pro](./llms/tablepro.md) — 带工具栏 / 搜索 / 筛选 / 排序 / 多选 / 分页的全功能表格。
@@ -86,7 +87,7 @@
86
87
  - [Drawer 抽屉](./llms/drawer.md) — 从屏幕边缘滑出的浮层。
87
88
  - [Toast 通知](./llms/toast.md) — 全局轻量提示,4 种语义。
88
89
  - [Tooltip 文字提示](./llms/tooltip.md) — 鼠标悬浮触发的简短说明。
89
- - [Popover 气泡卡片](./llms/popover.md) — 比 Tooltip 更丰富,可承载交互内容。
90
+ - [Popover 气泡卡片](./llms/popover.md) — 比 Tooltip 更丰富,可承载交互内容。
90
91
  - [Alert 警告提示](./llms/alert.md) — 页面中嵌入的警告/提示。
91
92
  - [Empty 空状态](./llms/empty.md) — 列表、页面或容器无数据时的占位。
92
93
  - [Spinner 加载](./llms/spinner.md) — 表示任务正在进行,提示用户等待。
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fangxinyan/lumina",
3
- "version": "0.5.0",
3
+ "version": "0.5.1",
4
4
  "description": "Lumina — Neumorphic component library for Electron & React apps",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -47,11 +47,15 @@
47
47
  "react-dom": ">=18"
48
48
  },
49
49
  "devDependencies": {
50
+ "@babel/standalone": "^7.29.2",
51
+ "@types/node": "^25.6.0",
52
+ "@types/prismjs": "^1.26.6",
50
53
  "@types/react": "^18.3.3",
51
54
  "@types/react-dom": "^18.3.0",
52
55
  "@vitejs/plugin-react": "^4.3.1",
53
56
  "postcss": "^8.5.10",
54
57
  "postcss-import": "^16.1.1",
58
+ "prismjs": "^1.30.0",
55
59
  "react": "^18.3.1",
56
60
  "react-dom": "^18.3.1",
57
61
  "tsup": "^8.2.4",
@@ -1,10 +0,0 @@
1
- /* ============ Popover ============ */
2
- .popover {
3
- z-index: 1000;
4
- background: var(--bg);
5
- border-radius: var(--r-md);
6
- padding: var(--gap-3);
7
- min-width: 220px;
8
- box-shadow: var(--neu-float);
9
- animation: menuIn var(--dur) var(--ease);
10
- }
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/Toast/Toast.tsx"],"names":["React","ReactDOM","jsx","jsxs","Icon"],"mappings":"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","file":"chunk-2ENTRT7R.cjs","sourcesContent":["import \"../../styles/tokens.css\";\nimport \"../../styles/shared.css\";\nimport \"./Toast.css\";\nimport * as React from \"react\";\nimport ReactDOM from \"react-dom\";\nimport { Icon } from \"../Icon\";\n\nexport type ToastType = \"info\" | \"success\" | \"warning\" | \"danger\";\n\nexport interface ToastItem {\n id: number;\n type: ToastType;\n title?: React.ReactNode;\n message?: React.ReactNode;\n duration?: number;\n}\n\ntype ListenerState = ToastItem[];\nconst listeners = new Set<(s: ListenerState) => void>();\nlet items: ListenerState = [];\nlet uid = 0;\n\nfunction emit() {\n listeners.forEach((l) => l(items));\n}\n\nexport const toast = {\n show(t: Omit<ToastItem, \"id\">) {\n const id = ++uid;\n items = [...items, { ...t, id, duration: t.duration ?? 3200 }];\n emit();\n if (items[items.length - 1].duration! > 0) {\n setTimeout(() => toast.dismiss(id), items[items.length - 1].duration);\n }\n return id;\n },\n info: (message: React.ReactNode, title?: React.ReactNode) => toast.show({ type: \"info\", message, title }),\n success: (message: React.ReactNode, title?: React.ReactNode) => toast.show({ type: \"success\", message, title }),\n warn: (message: React.ReactNode, title?: React.ReactNode) => toast.show({ type: \"warning\", message, title }),\n error: (message: React.ReactNode, title?: React.ReactNode) => toast.show({ type: \"danger\", message, title }),\n dismiss(id: number) {\n items = items.filter((i) => i.id !== id);\n emit();\n },\n clear() {\n items = [];\n emit();\n },\n};\n\nexport interface ToastContainerProps {\n placement?: \"top-right\" | \"top-left\" | \"bottom-right\" | \"bottom-left\" | \"top-center\";\n}\n\n/** `ToastContainer` — mount once at your app root; subscribes to `toast.*` calls. */\nexport const ToastContainer: React.FC<ToastContainerProps> = ({ placement = \"top-right\" }) => {\n const [list, setList] = React.useState<ListenerState>(items);\n React.useEffect(() => {\n listeners.add(setList);\n return () => {\n listeners.delete(setList);\n };\n }, []);\n if (typeof document === \"undefined\") return null;\n return ReactDOM.createPortal(\n <div className={`toast-container ${placement}`}>\n {list.map((t) => {\n const iconName =\n t.type === \"success\" ? \"check2\" : t.type === \"warning\" ? \"alert\" : t.type === \"danger\" ? \"alert\" : \"info\";\n return (\n <div key={t.id} className={`toast ${t.type}`} role=\"status\">\n <Icon name={iconName} size={18} className=\"toast-icon\" />\n <div className=\"toast-body\">\n {t.title && <div className=\"toast-title\">{t.title}</div>}\n {t.message && <div className=\"toast-msg\">{t.message}</div>}\n </div>\n <button type=\"button\" className=\"toast-close\" onClick={() => toast.dismiss(t.id)} aria-label=\"Dismiss\">\n <Icon name=\"x\" size={14} />\n </button>\n </div>\n );\n })}\n </div>,\n document.body\n );\n};\n"]}
@@ -1,66 +0,0 @@
1
- import { useFloating } from './chunk-V2DIQ3RH.js';
2
- import './tokens-BIIUTPKN.css';
3
- import './shared-NJHRNLRH.css';
4
- import './Popover-NYEKT5CQ.css';
5
- import * as React from 'react';
6
- import { createPortal } from 'react-dom';
7
- import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
8
-
9
- var Popover = ({
10
- content,
11
- placement = "bottom",
12
- trigger = "click",
13
- defaultOpen = false,
14
- open,
15
- onOpenChange,
16
- children,
17
- className = ""
18
- }) => {
19
- const [inner, setInner] = React.useState(defaultOpen);
20
- const isControlled = open !== void 0;
21
- const show = isControlled ? open : inner;
22
- const panelRef = React.useRef(null);
23
- const { triggerRef, floatingStyle, placement: resolved } = useFloating({
24
- open: show,
25
- placement,
26
- panelWidth: 240,
27
- panelHeight: 160,
28
- alignCross: "center"
29
- });
30
- const set = (v) => {
31
- if (!isControlled) setInner(v);
32
- onOpenChange?.(v);
33
- };
34
- React.useEffect(() => {
35
- if (trigger !== "click" || !show) return;
36
- const h = (e) => {
37
- const t = e.target;
38
- if (triggerRef.current?.contains(t)) return;
39
- if (panelRef.current?.contains(t)) return;
40
- set(false);
41
- };
42
- document.addEventListener("mousedown", h);
43
- return () => document.removeEventListener("mousedown", h);
44
- }, [show, trigger]);
45
- const interact = trigger === "hover" ? { onMouseEnter: () => set(true), onMouseLeave: () => set(false) } : { onClick: () => set(!show) };
46
- return /* @__PURE__ */ jsxs(Fragment, { children: [
47
- /* @__PURE__ */ jsx(
48
- "span",
49
- {
50
- ref: triggerRef,
51
- className: `popover-anchor ${className}`,
52
- style: { display: "inline-flex" },
53
- ...interact,
54
- children
55
- }
56
- ),
57
- show && typeof document !== "undefined" && createPortal(
58
- /* @__PURE__ */ jsx("span", { ref: panelRef, className: `popover ${resolved}`, style: floatingStyle, children: content }),
59
- document.body
60
- )
61
- ] });
62
- };
63
-
64
- export { Popover };
65
- //# sourceMappingURL=chunk-3UU2PUK4.js.map
66
- //# sourceMappingURL=chunk-3UU2PUK4.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/Popover/Popover.tsx"],"names":[],"mappings":";;;;;;;;AAmBO,IAAM,UAAkC,CAAC;AAAA,EAC9C,OAAA;AAAA,EACA,SAAA,GAAY,QAAA;AAAA,EACZ,OAAA,GAAU,OAAA;AAAA,EACV,WAAA,GAAc,KAAA;AAAA,EACd,IAAA;AAAA,EACA,YAAA;AAAA,EACA,QAAA;AAAA,EACA,SAAA,GAAY;AACd,CAAA,KAAM;AACJ,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAU,eAAS,WAAW,CAAA;AACpD,EAAA,MAAM,eAAe,IAAA,KAAS,MAAA;AAC9B,EAAA,MAAM,IAAA,GAAO,eAAe,IAAA,GAAQ,KAAA;AACpC,EAAA,MAAM,QAAA,GAAiB,aAAwB,IAAI,CAAA;AAEnD,EAAA,MAAM,EAAE,UAAA,EAAY,aAAA,EAAe,SAAA,EAAW,QAAA,KAAa,WAAA,CAA6B;AAAA,IACtF,IAAA,EAAM,IAAA;AAAA,IACN,SAAA;AAAA,IACA,UAAA,EAAY,GAAA;AAAA,IACZ,WAAA,EAAa,GAAA;AAAA,IACb,UAAA,EAAY;AAAA,GACb,CAAA;AAED,EAAA,MAAM,GAAA,GAAM,CAAC,CAAA,KAAe;AAC1B,IAAA,IAAI,CAAC,YAAA,EAAc,QAAA,CAAS,CAAC,CAAA;AAC7B,IAAA,YAAA,GAAe,CAAC,CAAA;AAAA,EAClB,CAAA;AAEA,EAAM,gBAAU,MAAM;AACpB,IAAA,IAAI,OAAA,KAAY,OAAA,IAAW,CAAC,IAAA,EAAM;AAClC,IAAA,MAAM,CAAA,GAAI,CAAC,CAAA,KAAkB;AAC3B,MAAA,MAAM,IAAI,CAAA,CAAE,MAAA;AACZ,MAAA,IAAI,UAAA,CAAW,OAAA,EAAS,QAAA,CAAS,CAAC,CAAA,EAAG;AACrC,MAAA,IAAI,QAAA,CAAS,OAAA,EAAS,QAAA,CAAS,CAAC,CAAA,EAAG;AACnC,MAAA,GAAA,CAAI,KAAK,CAAA;AAAA,IACX,CAAA;AACA,IAAA,QAAA,CAAS,gBAAA,CAAiB,aAAa,CAAC,CAAA;AACxC,IAAA,OAAO,MAAM,QAAA,CAAS,mBAAA,CAAoB,WAAA,EAAa,CAAC,CAAA;AAAA,EAE1D,CAAA,EAAG,CAAC,IAAA,EAAM,OAAO,CAAC,CAAA;AAElB,EAAA,MAAM,QAAA,GACJ,YAAY,OAAA,GACR,EAAE,cAAc,MAAM,GAAA,CAAI,IAAI,CAAA,EAAG,YAAA,EAAc,MAAM,GAAA,CAAI,KAAK,GAAE,GAChE,EAAE,SAAS,MAAM,GAAA,CAAI,CAAC,IAAI,CAAA,EAAE;AAElC,EAAA,uBACE,IAAA,CAAA,QAAA,EAAA,EACE,QAAA,EAAA;AAAA,oBAAA,GAAA;AAAA,MAAC,MAAA;AAAA,MAAA;AAAA,QACC,GAAA,EAAK,UAAA;AAAA,QACL,SAAA,EAAW,kBAAkB,SAAS,CAAA,CAAA;AAAA,QACtC,KAAA,EAAO,EAAE,OAAA,EAAS,aAAA,EAAc;AAAA,QAC/B,GAAG,QAAA;AAAA,QAEH;AAAA;AAAA,KACH;AAAA,IACC,IAAA,IAAQ,OAAO,QAAA,KAAa,WAAA,IAC3B,YAAA;AAAA,sBACE,GAAA,CAAC,MAAA,EAAA,EAAK,GAAA,EAAK,QAAA,EAAU,SAAA,EAAW,WAAW,QAAQ,CAAA,CAAA,EAAI,KAAA,EAAO,aAAA,EAC3D,QAAA,EAAA,OAAA,EACH,CAAA;AAAA,MACA,QAAA,CAAS;AAAA;AACX,GAAA,EACJ,CAAA;AAEJ","file":"chunk-3UU2PUK4.js","sourcesContent":["import \"../../styles/tokens.css\";\nimport \"../../styles/shared.css\";\nimport \"./Popover.css\";\nimport * as React from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { useFloating } from \"../../utils/useFloating\";\n\nexport interface PopoverProps {\n content: React.ReactNode;\n placement?: \"top\" | \"bottom\" | \"left\" | \"right\";\n trigger?: \"click\" | \"hover\";\n defaultOpen?: boolean;\n open?: boolean;\n onOpenChange?: (open: boolean) => void;\n children: React.ReactElement;\n className?: string;\n}\n\n/** `Popover` — rich content bubble. */\nexport const Popover: React.FC<PopoverProps> = ({\n content,\n placement = \"bottom\",\n trigger = \"click\",\n defaultOpen = false,\n open,\n onOpenChange,\n children,\n className = \"\",\n}) => {\n const [inner, setInner] = React.useState(defaultOpen);\n const isControlled = open !== undefined;\n const show = isControlled ? open! : inner;\n const panelRef = React.useRef<HTMLSpanElement>(null);\n\n const { triggerRef, floatingStyle, placement: resolved } = useFloating<HTMLSpanElement>({\n open: show,\n placement,\n panelWidth: 240,\n panelHeight: 160,\n alignCross: \"center\",\n });\n\n const set = (v: boolean) => {\n if (!isControlled) setInner(v);\n onOpenChange?.(v);\n };\n\n React.useEffect(() => {\n if (trigger !== \"click\" || !show) return;\n const h = (e: MouseEvent) => {\n const t = e.target as Node;\n if (triggerRef.current?.contains(t)) return;\n if (panelRef.current?.contains(t)) return;\n set(false);\n };\n document.addEventListener(\"mousedown\", h);\n return () => document.removeEventListener(\"mousedown\", h);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [show, trigger]);\n\n const interact =\n trigger === \"hover\"\n ? { onMouseEnter: () => set(true), onMouseLeave: () => set(false) }\n : { onClick: () => set(!show) };\n\n return (\n <>\n <span\n ref={triggerRef}\n className={`popover-anchor ${className}`}\n style={{ display: \"inline-flex\" }}\n {...interact}\n >\n {children}\n </span>\n {show && typeof document !== \"undefined\" &&\n createPortal(\n <span ref={panelRef} className={`popover ${resolved}`} style={floatingStyle}>\n {content}\n </span>,\n document.body\n )}\n </>\n );\n};\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/Select/Select.tsx"],"names":[],"mappings":"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","file":"chunk-6XZ362VL.js","sourcesContent":["import \"../../styles/tokens.css\";\nimport \"../../styles/shared.css\";\nimport \"./Select.css\";\nimport * as React from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { Icon, type IconName } from \"../Icon\";\nimport { Tag } from \"../Tag\";\nimport { useFloating } from \"../../utils/useFloating\";\n\nexport interface SelectOption<T extends string | number = string> {\n value: T;\n label: React.ReactNode;\n /** Searchable text — used by default filter when `label` isn't a string. */\n text?: string;\n /** Secondary line shown beneath the label. */\n description?: React.ReactNode;\n /** Leading icon. */\n icon?: IconName;\n disabled?: boolean;\n}\n\nexport interface SelectOptionGroup<T extends string | number = string> {\n /** Group heading. */\n label: React.ReactNode;\n options: SelectOption<T>[];\n}\n\nexport type SelectItem<T extends string | number = string> =\n | SelectOption<T>\n | SelectOptionGroup<T>;\n\nconst isGroup = <T extends string | number>(\n it: SelectItem<T>\n): it is SelectOptionGroup<T> => Array.isArray((it as SelectOptionGroup<T>).options);\n\ninterface BaseSelectProps<T extends string | number = string> {\n /** Flat or mixed (groups + options) item list. */\n options: SelectItem<T>[];\n placeholder?: string;\n disabled?: boolean;\n size?: \"sm\" | \"md\" | \"lg\";\n /** Show invalid (red) ring. */\n invalid?: boolean;\n /** Show a small × to clear the selection (single mode) or all selections (multi). */\n clearable?: boolean;\n /** Add a search input at the top of the menu. */\n searchable?: boolean;\n /** Custom filter — defaults to label/text/value substring match. */\n filterOption?: (input: string, option: SelectOption<T>) => boolean;\n /** Show spinner instead of options. */\n loading?: boolean;\n /** Custom empty content when no options match. */\n emptyContent?: React.ReactNode;\n /** Controlled open state. */\n open?: boolean;\n defaultOpen?: boolean;\n onOpenChange?: (open: boolean) => void;\n className?: string;\n /** Class for the popped-out menu. */\n menuClassName?: string;\n}\n\nexport interface SingleSelectProps<T extends string | number = string> extends BaseSelectProps<T> {\n multiple?: false;\n value?: T;\n defaultValue?: T;\n onChange?: (value: T) => void;\n /** Fired when user clears the selection via the × button. */\n onClear?: () => void;\n}\n\nexport interface MultiSelectProps<T extends string | number = string> extends BaseSelectProps<T> {\n multiple: true;\n value?: T[];\n defaultValue?: T[];\n onChange?: (value: T[]) => void;\n /** Max selected items shown as tags before collapsing to \"+N\". */\n maxTagCount?: number;\n}\n\nexport type SelectProps<T extends string | number = string> =\n | SingleSelectProps<T>\n | MultiSelectProps<T>;\n\nconst flatten = <T extends string | number>(items: SelectItem<T>[]): SelectOption<T>[] =>\n items.flatMap((it) => (isGroup(it) ? it.options : [it]));\n\nconst defaultFilter = <T extends string | number>(input: string, opt: SelectOption<T>): boolean => {\n const q = input.toLowerCase();\n const txt =\n opt.text ?? (typeof opt.label === \"string\" ? opt.label : String(opt.value));\n return txt.toLowerCase().includes(q);\n};\n\n/** `Select` — neumorphic dropdown. Set `multiple` for tag-style multi-select. */\nexport function Select<T extends string | number = string>(props: SingleSelectProps<T>): React.ReactElement;\nexport function Select<T extends string | number = string>(props: MultiSelectProps<T>): React.ReactElement;\nexport function Select<T extends string | number = string>(props: SelectProps<T>): React.ReactElement {\n const {\n options,\n placeholder = \"请选择…\",\n disabled,\n size = \"md\",\n invalid,\n clearable,\n searchable,\n filterOption,\n loading,\n emptyContent,\n open: openProp,\n defaultOpen,\n onOpenChange,\n className = \"\",\n menuClassName = \"\",\n } = props;\n const isMulti = props.multiple === true;\n\n const [innerSingle, setInnerSingle] = React.useState<T | undefined>(\n !isMulti ? (props as SingleSelectProps<T>).defaultValue : undefined\n );\n const [innerMulti, setInnerMulti] = React.useState<T[]>(\n isMulti ? (props as MultiSelectProps<T>).defaultValue ?? [] : []\n );\n const [innerOpen, setInnerOpen] = React.useState(defaultOpen ?? false);\n const [query, setQuery] = React.useState(\"\");\n const [activeIdx, setActiveIdx] = React.useState(-1);\n\n const searchRef = React.useRef<HTMLInputElement>(null);\n const menuRef = React.useRef<HTMLDivElement>(null);\n\n const openControlled = openProp !== undefined;\n const open = openControlled ? openProp! : innerOpen;\n const setOpen = (v: boolean) => {\n if (!openControlled) setInnerOpen(v);\n onOpenChange?.(v);\n if (!v) setQuery(\"\");\n };\n\n const { triggerRef: ref, floatingStyle } = useFloating<HTMLDivElement>({\n open,\n placement: \"bottom\",\n matchTriggerWidth: true,\n panelHeight: 320,\n });\n\n const singleControlled = !isMulti && (props as SingleSelectProps<T>).value !== undefined;\n const multiControlled = isMulti && (props as MultiSelectProps<T>).value !== undefined;\n\n const singleValue = singleControlled ? (props as SingleSelectProps<T>).value : innerSingle;\n const multiValue = multiControlled ? (props as MultiSelectProps<T>).value! : innerMulti;\n\n React.useEffect(() => {\n if (!open) return;\n const h = (e: MouseEvent) => {\n const t = e.target as Node;\n if (ref.current?.contains(t)) return;\n if (menuRef.current?.contains(t)) return;\n setOpen(false);\n };\n document.addEventListener(\"mousedown\", h);\n return () => document.removeEventListener(\"mousedown\", h);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [open]);\n\n // Auto-focus search input when opened\n React.useEffect(() => {\n if (open && searchable) {\n requestAnimationFrame(() => searchRef.current?.focus());\n }\n if (!open) setActiveIdx(-1);\n }, [open, searchable]);\n\n // Filter options\n const allFlat = React.useMemo(() => flatten(options), [options]);\n const filteredFlat = React.useMemo(() => {\n if (!query.trim()) return allFlat;\n const f = filterOption ?? defaultFilter;\n return allFlat.filter((o) => f(query, o));\n }, [allFlat, query, filterOption]);\n\n // Re-bucket into groups respecting filter (for menu rendering)\n const filteredItems = React.useMemo<SelectItem<T>[]>(() => {\n if (!query.trim()) return options;\n return options\n .map((it) => {\n if (!isGroup(it)) {\n return filteredFlat.includes(it) ? it : null;\n }\n const kept = it.options.filter((o) => filteredFlat.includes(o));\n return kept.length ? { label: it.label, options: kept } : null;\n })\n .filter((x): x is SelectItem<T> => x !== null);\n }, [options, filteredFlat, query]);\n\n React.useEffect(() => {\n setActiveIdx(filteredFlat.length ? 0 : -1);\n }, [filteredFlat.length]);\n\n const pickSingle = (opt: SelectOption<T>) => {\n if (opt.disabled) return;\n if (!singleControlled) setInnerSingle(opt.value);\n (props as SingleSelectProps<T>).onChange?.(opt.value);\n setOpen(false);\n };\n\n const toggleMulti = (opt: SelectOption<T>) => {\n if (opt.disabled) return;\n const cur = multiValue ?? [];\n const next = cur.includes(opt.value) ? cur.filter((v) => v !== opt.value) : [...cur, opt.value];\n if (!multiControlled) setInnerMulti(next);\n (props as MultiSelectProps<T>).onChange?.(next);\n };\n\n const clearAll = (e: React.MouseEvent) => {\n e.stopPropagation();\n if (isMulti) {\n if (!multiControlled) setInnerMulti([]);\n (props as MultiSelectProps<T>).onChange?.([]);\n } else {\n if (!singleControlled) setInnerSingle(undefined);\n (props as SingleSelectProps<T>).onClear?.();\n }\n };\n\n const isSelected = (val: T) =>\n isMulti ? (multiValue ?? []).includes(val) : singleValue === val;\n\n const onKeyDown = (e: React.KeyboardEvent) => {\n if (!open) {\n if (e.key === \"Enter\" || e.key === \" \" || e.key === \"ArrowDown\") {\n e.preventDefault();\n setOpen(true);\n }\n return;\n }\n if (e.key === \"Escape\") {\n e.preventDefault();\n setOpen(false);\n return;\n }\n if (e.key === \"ArrowDown\") {\n e.preventDefault();\n setActiveIdx((i) => Math.min(filteredFlat.length - 1, i + 1));\n return;\n }\n if (e.key === \"ArrowUp\") {\n e.preventDefault();\n setActiveIdx((i) => Math.max(0, i - 1));\n return;\n }\n if (e.key === \"Enter\") {\n e.preventDefault();\n const opt = filteredFlat[activeIdx];\n if (opt && !opt.disabled) {\n if (isMulti) toggleMulti(opt);\n else pickSingle(opt);\n }\n return;\n }\n };\n\n const renderTrigger = () => {\n if (isMulti) {\n const selected = (multiValue ?? [])\n .map((v) => allFlat.find((o) => o.value === v))\n .filter((o): o is SelectOption<T> => !!o);\n const max = (props as MultiSelectProps<T>).maxTagCount;\n const shown = max != null ? selected.slice(0, max) : selected;\n const overflow = selected.length - shown.length;\n if (selected.length === 0) {\n return <span className=\"placeholder\">{placeholder}</span>;\n }\n return (\n <span className=\"select-tags\">\n {shown.map((o) => (\n <Tag\n key={String(o.value)}\n tone=\"accent\"\n removable={!disabled}\n onRemove={() => {\n const cur = multiValue ?? [];\n const next = cur.filter((v) => v !== o.value);\n if (!multiControlled) setInnerMulti(next);\n (props as MultiSelectProps<T>).onChange?.(next);\n }}\n onClick={(e) => e.stopPropagation()}\n >\n {o.label}\n </Tag>\n ))}\n {overflow > 0 && <Tag tone=\"neutral\">+{overflow}</Tag>}\n </span>\n );\n }\n const current = allFlat.find((o) => o.value === singleValue);\n if (!current) return <span className=\"placeholder\">{placeholder}</span>;\n return (\n <span className=\"select-value\">\n {current.icon && <Icon name={current.icon} size={14} />}\n <span>{current.label}</span>\n </span>\n );\n };\n\n const hasSelection = isMulti ? (multiValue?.length ?? 0) > 0 : singleValue !== undefined;\n const showClear = clearable && hasSelection && !disabled;\n\n // Render an option button\n let renderIdx = -1;\n const renderOption = (o: SelectOption<T>) => {\n renderIdx += 1;\n const idx = renderIdx;\n const sel = isSelected(o.value);\n const active = idx === activeIdx;\n return (\n <button\n key={String(o.value)}\n type=\"button\"\n role=\"option\"\n aria-selected={sel}\n disabled={o.disabled}\n className={`menu-item ${sel ? \"active\" : \"\"} ${active ? \"highlight\" : \"\"}`}\n onMouseEnter={() => setActiveIdx(idx)}\n onClick={() => (isMulti ? toggleMulti(o) : pickSingle(o))}\n >\n {isMulti && (\n <span className={`menu-check ${sel ? \"on\" : \"\"}`} aria-hidden>\n {sel && <Icon name=\"check\" size={11} stroke={3} />}\n </span>\n )}\n {o.icon && <Icon name={o.icon} size={14} />}\n <span className=\"menu-item-body\">\n <span className=\"menu-item-label\">{o.label}</span>\n {o.description && <span className=\"menu-item-desc\">{o.description}</span>}\n </span>\n {!isMulti && (\n <span className=\"tick\">\n <Icon name=\"check\" size={12} stroke={3} />\n </span>\n )}\n </button>\n );\n };\n\n return (\n <div\n ref={ref}\n className={`select ${size} ${isMulti ? \"multi\" : \"\"} ${open ? \"open\" : \"\"} ${disabled ? \"disabled\" : \"\"} ${invalid ? \"invalid\" : \"\"} ${className}`}\n onKeyDown={onKeyDown}\n tabIndex={disabled ? -1 : 0}\n >\n <button\n type=\"button\"\n className=\"select-trigger\"\n disabled={disabled}\n onClick={() => !disabled && setOpen(!open)}\n >\n {renderTrigger()}\n {showClear && (\n <span className=\"select-clear\" role=\"button\" aria-label=\"Clear\" onClick={clearAll}>\n <Icon name=\"x\" size={12} />\n </span>\n )}\n <Icon name=\"chevDown\" size={14} className=\"select-caret\" />\n </button>\n {open && typeof document !== \"undefined\" &&\n createPortal(\n <div\n ref={menuRef}\n className={`menu ${menuClassName}`}\n role=\"listbox\"\n aria-multiselectable={isMulti || undefined}\n style={floatingStyle}\n >\n {searchable && (\n <div className=\"menu-search\">\n <Icon name=\"search\" size={13} />\n <input\n ref={searchRef}\n type=\"text\"\n value={query}\n placeholder=\"搜索...\"\n onChange={(e) => setQuery(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === \"Escape\" || e.key === \"ArrowDown\" || e.key === \"ArrowUp\" || e.key === \"Enter\") {\n e.preventDefault();\n onKeyDown(e);\n }\n }}\n />\n </div>\n )}\n {loading ? (\n <div className=\"menu-state\">\n <span className=\"menu-state-ico\">\n <span className=\"spinner\" />\n </span>\n <span>加载中...</span>\n </div>\n ) : filteredItems.length === 0 ? (\n <div className=\"menu-state\">\n <span className=\"menu-state-ico\">\n <Icon name=\"search\" size={16} />\n </span>\n <span>{emptyContent ?? \"暂无匹配项\"}</span>\n </div>\n ) : (\n filteredItems.map((it, gi) =>\n isGroup(it) ? (\n <React.Fragment key={`g-${gi}`}>\n <div className=\"menu-group-label\">{it.label}</div>\n {it.options.map(renderOption)}\n </React.Fragment>\n ) : (\n renderOption(it)\n )\n )\n )}\n </div>,\n document.body\n )}\n </div>\n );\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/Toast/Toast.tsx"],"names":[],"mappings":"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","file":"chunk-7M7NAMR5.js","sourcesContent":["import \"../../styles/tokens.css\";\nimport \"../../styles/shared.css\";\nimport \"./Toast.css\";\nimport * as React from \"react\";\nimport ReactDOM from \"react-dom\";\nimport { Icon } from \"../Icon\";\n\nexport type ToastType = \"info\" | \"success\" | \"warning\" | \"danger\";\n\nexport interface ToastItem {\n id: number;\n type: ToastType;\n title?: React.ReactNode;\n message?: React.ReactNode;\n duration?: number;\n}\n\ntype ListenerState = ToastItem[];\nconst listeners = new Set<(s: ListenerState) => void>();\nlet items: ListenerState = [];\nlet uid = 0;\n\nfunction emit() {\n listeners.forEach((l) => l(items));\n}\n\nexport const toast = {\n show(t: Omit<ToastItem, \"id\">) {\n const id = ++uid;\n items = [...items, { ...t, id, duration: t.duration ?? 3200 }];\n emit();\n if (items[items.length - 1].duration! > 0) {\n setTimeout(() => toast.dismiss(id), items[items.length - 1].duration);\n }\n return id;\n },\n info: (message: React.ReactNode, title?: React.ReactNode) => toast.show({ type: \"info\", message, title }),\n success: (message: React.ReactNode, title?: React.ReactNode) => toast.show({ type: \"success\", message, title }),\n warn: (message: React.ReactNode, title?: React.ReactNode) => toast.show({ type: \"warning\", message, title }),\n error: (message: React.ReactNode, title?: React.ReactNode) => toast.show({ type: \"danger\", message, title }),\n dismiss(id: number) {\n items = items.filter((i) => i.id !== id);\n emit();\n },\n clear() {\n items = [];\n emit();\n },\n};\n\nexport interface ToastContainerProps {\n placement?: \"top-right\" | \"top-left\" | \"bottom-right\" | \"bottom-left\" | \"top-center\";\n}\n\n/** `ToastContainer` — mount once at your app root; subscribes to `toast.*` calls. */\nexport const ToastContainer: React.FC<ToastContainerProps> = ({ placement = \"top-right\" }) => {\n const [list, setList] = React.useState<ListenerState>(items);\n React.useEffect(() => {\n listeners.add(setList);\n return () => {\n listeners.delete(setList);\n };\n }, []);\n if (typeof document === \"undefined\") return null;\n return ReactDOM.createPortal(\n <div className={`toast-container ${placement}`}>\n {list.map((t) => {\n const iconName =\n t.type === \"success\" ? \"check2\" : t.type === \"warning\" ? \"alert\" : t.type === \"danger\" ? \"alert\" : \"info\";\n return (\n <div key={t.id} className={`toast ${t.type}`} role=\"status\">\n <Icon name={iconName} size={18} className=\"toast-icon\" />\n <div className=\"toast-body\">\n {t.title && <div className=\"toast-title\">{t.title}</div>}\n {t.message && <div className=\"toast-msg\">{t.message}</div>}\n </div>\n <button type=\"button\" className=\"toast-close\" onClick={() => toast.dismiss(t.id)} aria-label=\"Dismiss\">\n <Icon name=\"x\" size={14} />\n </button>\n </div>\n );\n })}\n </div>,\n document.body\n );\n};\n"]}