@rainbow-oh/yee-c 0.4.3 → 0.4.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 (254) hide show
  1. package/dist/cjs/Button/button.d.ts +1 -1
  2. package/dist/cjs/CSV/download.d.ts +1 -1
  3. package/dist/cjs/Carousel/carousel.d.ts +2 -2
  4. package/dist/cjs/Carousel/carousel.js +9 -2
  5. package/dist/cjs/Carousel/interface.d.ts +5 -0
  6. package/dist/cjs/Cascader/cascader.js +53 -62
  7. package/dist/cjs/Cascader/interface.d.ts +19 -2
  8. package/dist/cjs/Cascader/node.js +11 -6
  9. package/dist/cjs/Cascader/search-list.js +2 -1
  10. package/dist/cjs/Cascader/utils/index.d.ts +58 -14
  11. package/dist/cjs/Cascader/utils/index.js +57 -73
  12. package/dist/cjs/Drawer/style/index.less +4 -0
  13. package/dist/cjs/FloatButton/float-button.d.ts +1 -1
  14. package/dist/cjs/Form/demo/basic.js +2 -2
  15. package/dist/cjs/Form/style/index.less +15 -0
  16. package/dist/cjs/Input/style/index.less +19 -17
  17. package/dist/cjs/InputNumber/style/index.less +0 -29
  18. package/dist/cjs/PickerPanel/interface.d.ts +44 -2
  19. package/dist/cjs/PickerPanel/panels/DatePanel/DateBody.d.ts +2 -1
  20. package/dist/cjs/PickerPanel/panels/DatePanel/DateHeader.d.ts +2 -1
  21. package/dist/cjs/PickerPanel/panels/DatePanel/DateHeader.js +1 -1
  22. package/dist/cjs/PickerPanel/panels/DatePanel/index.d.ts +2 -1
  23. package/dist/cjs/PickerPanel/panels/DateTimePanel/index.d.ts +7 -1
  24. package/dist/cjs/PickerPanel/panels/DateTimePanel/index.js +18 -4
  25. package/dist/cjs/PickerPanel/panels/DecadePanel/DecadeBody.d.ts +2 -1
  26. package/dist/cjs/PickerPanel/panels/DecadePanel/DecadeBody.js +1 -1
  27. package/dist/cjs/PickerPanel/panels/DecadePanel/DecadeHeader.d.ts +2 -1
  28. package/dist/cjs/PickerPanel/panels/DecadePanel/DecadeHeader.js +1 -1
  29. package/dist/cjs/PickerPanel/panels/DecadePanel/index.d.ts +2 -1
  30. package/dist/cjs/PickerPanel/panels/DecadePanel/index.js +1 -1
  31. package/dist/cjs/PickerPanel/panels/Header.d.ts +13 -1
  32. package/dist/cjs/PickerPanel/panels/MonthPanel/MonthBody.d.ts +2 -1
  33. package/dist/cjs/PickerPanel/panels/MonthPanel/MonthHeader.d.ts +2 -1
  34. package/dist/cjs/PickerPanel/panels/MonthPanel/MonthHeader.js +1 -1
  35. package/dist/cjs/PickerPanel/panels/MonthPanel/index.d.ts +2 -1
  36. package/dist/cjs/PickerPanel/panels/MonthPanel/index.js +1 -1
  37. package/dist/cjs/PickerPanel/panels/PanelBody.d.ts +21 -1
  38. package/dist/cjs/PickerPanel/panels/PanelBody.js +3 -3
  39. package/dist/cjs/PickerPanel/panels/QuarterPanel/QuarterBody.d.ts +2 -1
  40. package/dist/cjs/PickerPanel/panels/QuarterPanel/QuarterHeader.d.ts +2 -1
  41. package/dist/cjs/PickerPanel/panels/QuarterPanel/index.d.ts +2 -1
  42. package/dist/cjs/PickerPanel/panels/RangePanel/index.d.ts +2 -1
  43. package/dist/cjs/PickerPanel/panels/RangePanel/index.js +2 -2
  44. package/dist/cjs/PickerPanel/panels/RangePanel/interface.d.ts +5 -5
  45. package/dist/cjs/PickerPanel/panels/TimePanel/TimeBody.d.ts +17 -1
  46. package/dist/cjs/PickerPanel/panels/TimePanel/TimeCell.d.ts +7 -1
  47. package/dist/cjs/PickerPanel/panels/TimePanel/TimeCell.js +1 -1
  48. package/dist/cjs/PickerPanel/panels/TimePanel/TimeColumn.d.ts +14 -1
  49. package/dist/cjs/PickerPanel/panels/TimePanel/TimeColumn.js +1 -1
  50. package/dist/cjs/PickerPanel/panels/TimePanel/TimeHeader.d.ts +4 -1
  51. package/dist/cjs/PickerPanel/panels/TimePanel/index.d.ts +9 -1
  52. package/dist/cjs/PickerPanel/panels/WeekPanel/WeekBody.d.ts +2 -1
  53. package/dist/cjs/PickerPanel/panels/WeekPanel/WeekHeader.d.ts +2 -1
  54. package/dist/cjs/PickerPanel/panels/WeekPanel/index.d.ts +2 -1
  55. package/dist/cjs/PickerPanel/panels/YearPanel/YearBody.d.ts +2 -1
  56. package/dist/cjs/PickerPanel/panels/YearPanel/YearBody.js +2 -2
  57. package/dist/cjs/PickerPanel/panels/YearPanel/YearHeader.d.ts +2 -1
  58. package/dist/cjs/PickerPanel/panels/YearPanel/YearHeader.js +7 -1
  59. package/dist/cjs/PickerPanel/panels/YearPanel/index.d.ts +2 -1
  60. package/dist/cjs/PickerPanel/panels/YearPanel/index.js +1 -1
  61. package/dist/cjs/PickerPanel/utils/pickerUtils.d.ts +7 -7
  62. package/dist/cjs/PickerPanel/utils/pickerUtils.js +2 -2
  63. package/dist/cjs/Popover/style/index.less +1 -0
  64. package/dist/cjs/Select/interface.d.ts +77 -0
  65. package/dist/cjs/Select/option.d.ts +2 -1
  66. package/dist/cjs/Select/option.js +6 -3
  67. package/dist/cjs/Select/options.d.ts +3 -2
  68. package/dist/cjs/Select/options.js +53 -47
  69. package/dist/cjs/Select/select.js +1 -1
  70. package/dist/cjs/Select/style/index.less +8 -13
  71. package/dist/cjs/Selector/interface.d.ts +4 -0
  72. package/dist/cjs/Selector/selector.js +3 -0
  73. package/dist/cjs/Selector/style/index.less +21 -137
  74. package/dist/cjs/Table/hooks/useFilter.js +1 -1
  75. package/dist/cjs/Table/interface.d.ts +4 -0
  76. package/dist/cjs/Table/style/index.less +2 -0
  77. package/dist/cjs/Table/theader/filter.js +2 -1
  78. package/dist/cjs/Tabs/demo/basic.js +8 -1
  79. package/dist/cjs/Tabs/tabs.js +3 -1
  80. package/dist/cjs/Tag/demo/checkable.js +1 -0
  81. package/dist/cjs/Tag/tag.js +1 -1
  82. package/dist/cjs/TextArea/style/index.less +0 -17
  83. package/dist/cjs/Trigger/trigger.js +1 -1
  84. package/dist/cjs/hooks/useEvent.js +4 -1
  85. package/dist/cjs/style/color.css +1 -1
  86. package/dist/cjs/style/size.css +11 -2
  87. package/dist/cjs/style/themes.css +1 -1
  88. package/dist/cjs/style/variables.css +13 -4
  89. package/dist/cjs/version.d.ts +1 -1
  90. package/dist/cjs/version.js +1 -1
  91. package/dist/esm/Button/button.d.ts +1 -1
  92. package/dist/esm/CSV/download.d.ts +1 -1
  93. package/dist/esm/Carousel/carousel.d.ts +2 -2
  94. package/dist/esm/Carousel/carousel.js +5 -1
  95. package/dist/esm/Carousel/interface.d.ts +5 -0
  96. package/dist/esm/Cascader/cascader.js +49 -56
  97. package/dist/esm/Cascader/interface.d.ts +19 -2
  98. package/dist/esm/Cascader/node.js +8 -11
  99. package/dist/esm/Cascader/search-list.js +2 -1
  100. package/dist/esm/Cascader/utils/index.d.ts +58 -14
  101. package/dist/esm/Cascader/utils/index.js +124 -75
  102. package/dist/esm/Drawer/style/index.less +4 -0
  103. package/dist/esm/FloatButton/float-button.d.ts +1 -1
  104. package/dist/esm/Form/demo/basic.js +4 -2
  105. package/dist/esm/Form/style/index.less +15 -0
  106. package/dist/esm/Input/style/index.less +19 -17
  107. package/dist/esm/InputNumber/style/index.less +0 -29
  108. package/dist/esm/PickerPanel/interface.d.ts +44 -2
  109. package/dist/esm/PickerPanel/panels/DatePanel/DateBody.d.ts +2 -1
  110. package/dist/esm/PickerPanel/panels/DatePanel/DateHeader.d.ts +2 -1
  111. package/dist/esm/PickerPanel/panels/DatePanel/DateHeader.js +1 -1
  112. package/dist/esm/PickerPanel/panels/DatePanel/index.d.ts +2 -1
  113. package/dist/esm/PickerPanel/panels/DateTimePanel/index.d.ts +7 -1
  114. package/dist/esm/PickerPanel/panels/DateTimePanel/index.js +11 -7
  115. package/dist/esm/PickerPanel/panels/DecadePanel/DecadeBody.d.ts +2 -1
  116. package/dist/esm/PickerPanel/panels/DecadePanel/DecadeBody.js +2 -1
  117. package/dist/esm/PickerPanel/panels/DecadePanel/DecadeHeader.d.ts +2 -1
  118. package/dist/esm/PickerPanel/panels/DecadePanel/DecadeHeader.js +2 -1
  119. package/dist/esm/PickerPanel/panels/DecadePanel/index.d.ts +2 -1
  120. package/dist/esm/PickerPanel/panels/DecadePanel/index.js +1 -1
  121. package/dist/esm/PickerPanel/panels/Header.d.ts +13 -1
  122. package/dist/esm/PickerPanel/panels/MonthPanel/MonthBody.d.ts +2 -1
  123. package/dist/esm/PickerPanel/panels/MonthPanel/MonthHeader.d.ts +2 -1
  124. package/dist/esm/PickerPanel/panels/MonthPanel/MonthHeader.js +2 -1
  125. package/dist/esm/PickerPanel/panels/MonthPanel/index.d.ts +2 -1
  126. package/dist/esm/PickerPanel/panels/MonthPanel/index.js +1 -1
  127. package/dist/esm/PickerPanel/panels/PanelBody.d.ts +21 -1
  128. package/dist/esm/PickerPanel/panels/PanelBody.js +2 -4
  129. package/dist/esm/PickerPanel/panels/QuarterPanel/QuarterBody.d.ts +2 -1
  130. package/dist/esm/PickerPanel/panels/QuarterPanel/QuarterHeader.d.ts +2 -1
  131. package/dist/esm/PickerPanel/panels/QuarterPanel/index.d.ts +2 -1
  132. package/dist/esm/PickerPanel/panels/RangePanel/index.d.ts +2 -1
  133. package/dist/esm/PickerPanel/panels/RangePanel/index.js +2 -2
  134. package/dist/esm/PickerPanel/panels/RangePanel/interface.d.ts +5 -5
  135. package/dist/esm/PickerPanel/panels/TimePanel/TimeBody.d.ts +17 -1
  136. package/dist/esm/PickerPanel/panels/TimePanel/TimeCell.d.ts +7 -1
  137. package/dist/esm/PickerPanel/panels/TimePanel/TimeCell.js +1 -1
  138. package/dist/esm/PickerPanel/panels/TimePanel/TimeColumn.d.ts +14 -1
  139. package/dist/esm/PickerPanel/panels/TimePanel/TimeColumn.js +1 -1
  140. package/dist/esm/PickerPanel/panels/TimePanel/TimeHeader.d.ts +4 -1
  141. package/dist/esm/PickerPanel/panels/TimePanel/index.d.ts +9 -1
  142. package/dist/esm/PickerPanel/panels/WeekPanel/WeekBody.d.ts +2 -1
  143. package/dist/esm/PickerPanel/panels/WeekPanel/WeekHeader.d.ts +2 -1
  144. package/dist/esm/PickerPanel/panels/WeekPanel/index.d.ts +2 -1
  145. package/dist/esm/PickerPanel/panels/YearPanel/YearBody.d.ts +2 -1
  146. package/dist/esm/PickerPanel/panels/YearPanel/YearBody.js +3 -2
  147. package/dist/esm/PickerPanel/panels/YearPanel/YearHeader.d.ts +2 -1
  148. package/dist/esm/PickerPanel/panels/YearPanel/YearHeader.js +2 -1
  149. package/dist/esm/PickerPanel/panels/YearPanel/index.d.ts +2 -1
  150. package/dist/esm/PickerPanel/panels/YearPanel/index.js +1 -1
  151. package/dist/esm/PickerPanel/picker-panel.js +3 -0
  152. package/dist/esm/PickerPanel/utils/pickerUtils.d.ts +7 -7
  153. package/dist/esm/PickerPanel/utils/pickerUtils.js +4 -10
  154. package/dist/esm/Popover/style/index.less +1 -0
  155. package/dist/esm/Select/interface.d.ts +77 -0
  156. package/dist/esm/Select/option.d.ts +2 -1
  157. package/dist/esm/Select/option.js +11 -2
  158. package/dist/esm/Select/options.d.ts +3 -2
  159. package/dist/esm/Select/options.js +3 -1
  160. package/dist/esm/Select/select.js +1 -3
  161. package/dist/esm/Select/style/index.less +8 -13
  162. package/dist/esm/Selector/interface.d.ts +4 -0
  163. package/dist/esm/Selector/selector.js +4 -2
  164. package/dist/esm/Selector/style/index.less +21 -137
  165. package/dist/esm/Table/hooks/useFilter.js +1 -1
  166. package/dist/esm/Table/interface.d.ts +4 -0
  167. package/dist/esm/Table/style/index.less +2 -0
  168. package/dist/esm/Table/theader/filter.js +3 -4
  169. package/dist/esm/Tabs/demo/basic.js +4 -1
  170. package/dist/esm/Tabs/tabs.js +3 -1
  171. package/dist/esm/Tag/demo/checkable.js +1 -0
  172. package/dist/esm/Tag/tag.js +1 -1
  173. package/dist/esm/TextArea/style/index.less +0 -17
  174. package/dist/esm/Trigger/trigger.js +1 -1
  175. package/dist/esm/style/color.css +1 -1
  176. package/dist/esm/style/size.css +11 -2
  177. package/dist/esm/style/themes.css +1 -1
  178. package/dist/esm/style/variables.css +13 -4
  179. package/dist/esm/version.d.ts +1 -1
  180. package/dist/esm/version.js +1 -1
  181. package/dist/umd/yee-c.min.css +2 -2
  182. package/dist/umd/yee-c.min.js +1 -1
  183. package/package.json +1 -1
  184. package/src/Carousel/carousel.tsx +14 -3
  185. package/src/Carousel/interface.ts +6 -0
  186. package/src/Cascader/cascader.tsx +68 -63
  187. package/src/Cascader/column.tsx +1 -1
  188. package/src/Cascader/interface.ts +19 -2
  189. package/src/Cascader/node.tsx +12 -7
  190. package/src/Cascader/search-list.tsx +1 -1
  191. package/src/Cascader/utils/index.ts +130 -68
  192. package/src/Drawer/style/index.less +4 -0
  193. package/src/Dropdown/dropdown.tsx +1 -1
  194. package/src/FloatButton/float-button.tsx +5 -3
  195. package/src/Form/demo/basic.tsx +2 -2
  196. package/src/Form/style/index.less +15 -0
  197. package/src/Input/style/index.less +19 -17
  198. package/src/InputNumber/style/index.less +0 -29
  199. package/src/PickerPanel/interface.ts +43 -2
  200. package/src/PickerPanel/panels/DatePanel/DateBody.tsx +2 -1
  201. package/src/PickerPanel/panels/DatePanel/DateHeader.tsx +3 -2
  202. package/src/PickerPanel/panels/DatePanel/index.tsx +2 -1
  203. package/src/PickerPanel/panels/DateTimePanel/index.tsx +12 -5
  204. package/src/PickerPanel/panels/DecadePanel/DecadeBody.tsx +3 -2
  205. package/src/PickerPanel/panels/DecadePanel/DecadeHeader.tsx +3 -2
  206. package/src/PickerPanel/panels/DecadePanel/index.tsx +3 -2
  207. package/src/PickerPanel/panels/Header.tsx +14 -1
  208. package/src/PickerPanel/panels/MonthPanel/MonthBody.tsx +2 -1
  209. package/src/PickerPanel/panels/MonthPanel/MonthHeader.tsx +3 -2
  210. package/src/PickerPanel/panels/MonthPanel/index.tsx +3 -2
  211. package/src/PickerPanel/panels/PanelBody.tsx +27 -5
  212. package/src/PickerPanel/panels/QuarterPanel/QuarterBody.tsx +2 -1
  213. package/src/PickerPanel/panels/QuarterPanel/QuarterHeader.tsx +2 -1
  214. package/src/PickerPanel/panels/QuarterPanel/index.tsx +2 -1
  215. package/src/PickerPanel/panels/RangePanel/index.tsx +11 -9
  216. package/src/PickerPanel/panels/RangePanel/interface.ts +5 -5
  217. package/src/PickerPanel/panels/TimePanel/TimeBody.tsx +21 -5
  218. package/src/PickerPanel/panels/TimePanel/TimeCell.tsx +9 -2
  219. package/src/PickerPanel/panels/TimePanel/TimeColumn.tsx +15 -2
  220. package/src/PickerPanel/panels/TimePanel/TimeHeader.tsx +5 -1
  221. package/src/PickerPanel/panels/TimePanel/index.tsx +10 -1
  222. package/src/PickerPanel/panels/WeekPanel/WeekBody.tsx +2 -1
  223. package/src/PickerPanel/panels/WeekPanel/WeekHeader.tsx +2 -1
  224. package/src/PickerPanel/panels/WeekPanel/index.tsx +2 -1
  225. package/src/PickerPanel/panels/YearPanel/YearBody.tsx +4 -3
  226. package/src/PickerPanel/panels/YearPanel/YearHeader.tsx +9 -3
  227. package/src/PickerPanel/panels/YearPanel/index.tsx +3 -2
  228. package/src/PickerPanel/picker-panel.tsx +5 -3
  229. package/src/PickerPanel/utils/pickerUtils.ts +17 -8
  230. package/src/Popover/style/index.less +1 -0
  231. package/src/Select/interface.ts +87 -0
  232. package/src/Select/option.tsx +13 -4
  233. package/src/Select/options.tsx +49 -43
  234. package/src/Select/select.tsx +5 -2
  235. package/src/Select/style/index.less +8 -13
  236. package/src/Selector/interface.ts +4 -0
  237. package/src/Selector/selector.tsx +2 -0
  238. package/src/Selector/style/index.less +21 -137
  239. package/src/Splitter/hooks/useMove.ts +2 -2
  240. package/src/Table/hooks/useFilter.ts +1 -1
  241. package/src/Table/interface.ts +4 -0
  242. package/src/Table/style/index.less +2 -0
  243. package/src/Table/theader/filter.tsx +2 -2
  244. package/src/Tabs/demo/basic.tsx +7 -1
  245. package/src/Tabs/tabs.tsx +3 -2
  246. package/src/Tag/demo/checkable.tsx +1 -0
  247. package/src/Tag/tag.tsx +1 -1
  248. package/src/TextArea/style/index.less +0 -17
  249. package/src/Trigger/trigger.tsx +1 -1
  250. package/src/hooks/useEvent.ts +7 -4
  251. package/src/hooks/useMergedState.ts +6 -4
  252. package/src/style/color.css +1 -1
  253. package/src/style/size.css +11 -2
  254. package/src/version.ts +1 -1
@@ -16,70 +16,104 @@ export function hasChild(
16
16
  }
17
17
 
18
18
  /**
19
- * Get the next queue element for navigation
19
+ * Separator used to build a node's `uid` from its value path. A control
20
+ * character is used on purpose so it can never appear inside a user value —
21
+ * this prevents collisions like value `"a-1"` vs path `["a", "1"]` that a plain
22
+ * `'-'` separator would produce.
23
+ */
24
+ export const UID_SEP = '';
25
+
26
+ /**
27
+ * Build the canonical uid for a value path. Use this everywhere a path needs
28
+ * to be turned into a key (nodeMap lookups, selected keys, comparisons) so the
29
+ * format stays consistent with the `uid`/`pid` produced by `flattenOptions`.
30
+ * @param path - The value path
31
+ */
32
+ export const pathToUid = (path: Array<string | number>): string =>
33
+ path.map(String).join(UID_SEP);
34
+
35
+ /**
36
+ * Get the direct flattened children of the node identified by `uid`.
37
+ *
38
+ * Flattened nodes intentionally do not carry a `children` reference (it used to
39
+ * point at the raw, un-flattened subtree and caused type lies). Derive children
40
+ * from the flat list via `pid` instead — single source of truth.
41
+ * @param data - The flattened options data
42
+ * @param uid - The parent node's uid
43
+ */
44
+ export const getChildren = (
45
+ data: Array<FlattenOption>,
46
+ uid: string,
47
+ ): FlattenOption[] => data.filter((item) => item.pid === uid);
48
+
49
+ /**
50
+ * Find the node in `data` whose parent is `pid` and whose value is `value`.
20
51
  * @internal
21
52
  */
22
- const getNextQueueElement = (
53
+ const findInColumn = (
23
54
  data: Array<FlattenOption>,
55
+ pid: string,
24
56
  value: string | number,
25
- ): [FlattenOption[], { id: string | number; text: string }] | [] => {
26
- if (!Array.isArray(data)) {
27
- return [];
28
- }
29
-
30
- for (let i = 0; i < data.length; i++) {
31
- const item = data[i];
32
- if (item.uid === value) {
33
- const nexts = hasChild(item)
34
- ? (item.children as Array<FlattenOption>).filter((c) => c.pid === value)
35
- : [];
36
- return [
37
- nexts,
38
- { id: item.value as string | number, text: item.label as string },
39
- ];
40
- }
41
- }
42
- return [];
43
- };
57
+ ): FlattenOption | undefined =>
58
+ data.find((item) => item.pid === pid && item.value === value);
44
59
 
45
60
  /**
46
- * Populate data into input fields and dropdown lists from a value array
47
- * @param arr - The value array representing the selected path
61
+ * Reconstruct cascade columns and the highlight path from a value path.
62
+ *
63
+ * Walks the flattened options level by level, matching each value segment
64
+ * against the correct parent column via `pid` + `value`. Returns:
65
+ * - `queue`: the columns to render (column 0 = root, then each matched
66
+ * node's children column).
67
+ * - `path`: the highlight breadcrumb shaped as `{ key: uid, label }`, so it
68
+ * aligns with `expandedPath[level].key === uid` in the node view.
69
+ *
70
+ * Stops safely at the last valid segment if the value path does not exist in
71
+ * the data source.
72
+ *
73
+ * @param arr - The selected path. In `multiple` mode the value is an array of
74
+ * paths; the first path is used to drive which columns get expanded.
48
75
  * @param data - The flattened options data
49
76
  * @param options - Optional configuration
50
- * @returns A tuple of [queue, path] where queue is the column data and path is the selected path info
77
+ * @returns A tuple of `[queue, path]`
51
78
  */
52
79
  export const changeToView = (
53
- arr: Array<string | number>,
80
+ arr: Array<string | number> | Array<Array<string | number>>,
54
81
  data: Array<FlattenOption>,
55
82
  options?: {
56
- needNext?: boolean;
57
83
  multiple?: boolean;
58
84
  },
59
- ) => {
60
- const { needNext, multiple } = options || {};
61
- const _queue: FlattenOption[][] = [];
62
- const _path: Array<{ id: string | number; text: string }> = [];
85
+ ): [FlattenOption[][], Array<{ key: string; label: string }>] => {
86
+ const { multiple } = options || {};
87
+ const queue: FlattenOption[][] = [];
88
+ const path: Array<{ key: string; label: string }> = [];
89
+
90
+ // Column 0 (root level) is always present so the popup can open even with
91
+ // no selection.
92
+ queue.push(data.filter((item) => item.level === 0));
93
+
94
+ if (!Array.isArray(arr) || arr.length === 0) {
95
+ return [queue, path];
96
+ }
97
+
98
+ // In multiple mode the value is an array of paths; use the first one to
99
+ // drive column expansion.
100
+ const segments: Array<string | number> =
101
+ multiple && Array.isArray(arr[0])
102
+ ? (arr[0] as Array<string | number>)
103
+ : (arr as Array<string | number>);
63
104
 
64
- if (Array.isArray(arr)) {
65
- let i = 0;
66
- let _arr = arr;
67
- if (multiple) {
68
- _arr = Array.isArray(arr[0]) ? arr[0] : arr;
105
+ let currentPid = '';
106
+ for (let i = 0; i < segments.length; i++) {
107
+ const matched = findInColumn(data, currentPid, segments[i]);
108
+ if (!matched) break; // value path doesn't exist in the data source
109
+ path.push({ key: matched.uid, label: matched.label as string });
110
+ if (!matched.isLeaf) {
111
+ queue.push(getChildren(data, matched.uid));
69
112
  }
70
- let _data = data.filter((item) => item.level === 0);
71
- do {
72
- _queue.push(_data);
73
- const result = getNextQueueElement(_data, _arr[i]);
74
- if (result.length) {
75
- const [_dataNext, _pathItem] = result;
76
- _data = _dataNext;
77
- _path.push(_pathItem);
78
- }
79
- i++;
80
- } while (needNext ? i <= _arr.length : i < _arr.length);
113
+ currentPid = matched.uid;
81
114
  }
82
- return [_queue, _path];
115
+
116
+ return [queue, path];
83
117
  };
84
118
 
85
119
  // Assemble Tags Options
@@ -302,11 +336,11 @@ export const changeToView = (
302
336
  // }
303
337
 
304
338
  /**
305
- * Format a path array into a key string
339
+ * Format a value path into a key string. Alias of `pathToUid` so all path→key
340
+ * conversions share one collision-safe format.
306
341
  * @param val - The path array
307
- * @returns A string key joined by '-'
308
342
  */
309
- export const formatKey = (val: Array<string | number>) => val.join('-');
343
+ export const formatKey = (val: Array<string | number>): string => pathToUid(val);
310
344
 
311
345
  /**
312
346
  * Check if a path has the same prefix as another path
@@ -330,14 +364,16 @@ export const isSamePrefixPath = (
330
364
  * Determine if a node is fully selected or half selected (indeterminate)
331
365
  * @param value - The selected value paths
332
366
  * @param item - The flatten option node to check
367
+ * @param children - The node's direct flattened children (derive via `getChildren`)
333
368
  * @returns A tuple [checkedAll, indeterminate]
334
369
  */
335
370
  export function isHalfChecked(
336
371
  value: Array<Array<string | number>>,
337
372
  item: FlattenOption,
373
+ children: FlattenOption[],
338
374
  ) {
339
- if (!hasChild(item)) return [false, false];
340
- const total = item.children!.length;
375
+ if (!children.length) return [false, false];
376
+ const total = children.length;
341
377
  const prefixPath = item.path;
342
378
 
343
379
  const filtered = value.filter((path) => isSamePrefixPath(prefixPath, path));
@@ -348,14 +384,29 @@ export function isHalfChecked(
348
384
  }
349
385
 
350
386
  /**
351
- * Flatten a tree structure into an array for easier searching and traversal
387
+ * Default maximum tree depth accepted by `flattenOptions`. Guards against
388
+ * stack overflow on pathological/deeply-nested input.
389
+ */
390
+ const DEFAULT_MAX_DEPTH = 100;
391
+
392
+ /**
393
+ * Flatten a tree structure into an array for easier searching and traversal.
394
+ *
395
+ * The flattened nodes intentionally do NOT carry a `children` field — use
396
+ * `getChildren(data, uid)` to read a node's children. `uid`/`pid` are built
397
+ * via `pathToUid` (collision-safe). Includes a depth cap and a cycle guard so
398
+ * malformed input (very deep or self-referencing trees) cannot overflow the
399
+ * stack.
400
+ *
352
401
  * @param tree - The tree data to flatten
353
402
  * @param fieldNames - Custom field names for label, value, and children
403
+ * @param maxDepth - Maximum nesting depth (default 100)
354
404
  * @returns An array of flattened options with additional metadata
355
405
  */
356
406
  export const flattenOptions = (
357
407
  tree: Array<Record<string, unknown>>,
358
- fieldNames: FieldNames,
408
+ fieldNames?: FieldNames,
409
+ maxDepth: number = DEFAULT_MAX_DEPTH,
359
410
  ): FlattenOption[] => {
360
411
  const res: FlattenOption[] = [];
361
412
  const {
@@ -363,29 +414,40 @@ export const flattenOptions = (
363
414
  value = 'value',
364
415
  children = 'children',
365
416
  } = fieldNames || {};
417
+ // Object-identity set of nodes on the current DFS path, for cycle detection.
418
+ const seen = new Set<Record<string, unknown>>();
366
419
  const dfs = (
367
420
  nodes: Array<Record<string, unknown>>,
368
421
  parents: Array<string | number> = [],
422
+ labelParents: string[] = [],
369
423
  ) => {
370
424
  nodes.forEach((node: Record<string, unknown>) => {
371
- const wrappered = {
372
- $source: node,
373
- label: node[label],
374
- value: node[value],
375
- children: node[children],
376
- } as Option;
377
- const path = [...parents, wrappered['value']] as Array<string | number>;
378
- const uid = path.join('-');
379
- const pid = parents.join('-');
425
+ if (parents.length >= maxDepth) return; // depth guard
426
+ if (seen.has(node)) return; // cycle guard (back-edge to an ancestor)
427
+ const nodeLabel = node[label] as string;
428
+ const path = [...parents, node[value]] as Array<string | number>;
429
+ const labelPath = [...labelParents, nodeLabel];
430
+ const uid = pathToUid(path);
380
431
  res.push({
381
- ...wrappered,
382
- pid,
432
+ $source: node as Option,
433
+ label: nodeLabel,
434
+ value: node[value] as string | number,
435
+ pid: pathToUid(parents),
383
436
  uid,
384
437
  path,
438
+ labelPath,
385
439
  level: parents.length,
386
- isLeaf: !hasChild(wrappered),
387
- } as FlattenOption);
388
- if (wrappered['children']) dfs(wrappered['children'] as Option[], path);
440
+ isLeaf: !hasChild(node, children),
441
+ });
442
+ if (hasChild(node, children)) {
443
+ seen.add(node);
444
+ dfs(
445
+ node[children] as Array<Record<string, unknown>>,
446
+ path,
447
+ labelPath,
448
+ );
449
+ seen.delete(node);
450
+ }
389
451
  });
390
452
  };
391
453
  dfs(tree);
@@ -37,6 +37,10 @@
37
37
  padding: var(--yee-drawer-header-padding);
38
38
  }
39
39
 
40
+ &-title {
41
+ font-weight: var(--yee-drawer-title-font-weight);
42
+ }
43
+
40
44
  &-body {
41
45
  flex: 1;
42
46
  padding: var(--yee-drawer-body-padding);
@@ -56,7 +56,7 @@ const Dropdown: FC<DropdownProps> = (baseprops) => {
56
56
  <Trigger
57
57
  {...rest}
58
58
  arrow={arrow}
59
- popup={renderPopup() as any}
59
+ popup={renderPopup() as React.ReactElement}
60
60
  placement={placement}
61
61
  popupClassName={`${prefixCls}-popup`}
62
62
  open={mergedOpen}
@@ -8,8 +8,8 @@ import { FloatButtonGroupCtx } from './float-button-group';
8
8
  import type { FloatButtonProps } from './interface';
9
9
  import './style/index.less';
10
10
 
11
- const FloatButton = React.forwardRef(
12
- (baseprops: FloatButtonProps, ref: any) => {
11
+ const FloatButton = React.forwardRef<HTMLButtonElement, FloatButtonProps>(
12
+ (baseprops, ref) => {
13
13
  const { floatbutton } = useContext(GlobalContext);
14
14
  const props = mergeContextToProps(baseprops, floatbutton);
15
15
  const {
@@ -26,7 +26,9 @@ const FloatButton = React.forwardRef(
26
26
  ...rest
27
27
  } = props;
28
28
 
29
- const componentRef = ref || React.createRef();
29
+ const componentRef =
30
+ (ref as React.RefObject<HTMLButtonElement | null>) ||
31
+ React.createRef<HTMLButtonElement>();
30
32
 
31
33
  const onMove = (pos: { x: number; y: number }) => {
32
34
  // Check if element exists before operating
@@ -64,7 +64,7 @@ export default () => {
64
64
  </Form.Field>
65
65
  </Grid.Item>
66
66
  <Grid.Item>
67
- <Form.Field name="gender" label="Gender" initialValue="male">
67
+ <Form.Field name="gender" label="Gender" initialValue="male" required>
68
68
  <Select
69
69
  options={[
70
70
  { label: 'male', value: 'male' },
@@ -76,7 +76,7 @@ export default () => {
76
76
  </Grid.Item>
77
77
 
78
78
  <Grid.Item>
79
- <Form.Field name="birthday" label="Birthday">
79
+ <Form.Field name="birthday" label="Birthday" required>
80
80
  <DatePicker />
81
81
  </Form.Field>
82
82
  </Grid.Item>
@@ -56,5 +56,20 @@
56
56
  color: var(--yee-error-color);
57
57
  }
58
58
  }
59
+
60
+ // 表单校验态:在此重定义控件读取的 border / box-shadow 变量,
61
+ // 后代里的 Input / Selector / InputNumber / TextArea 等通过 CSS 变量继承自动变色,
62
+ // 无需在每个组件里重复 .yee-form-item-error 块,也不存在 specificity / !important 问题。
63
+ &&-error {
64
+ --yee-input-border-color: var(--yee-error-color);
65
+ --yee-input-hover-border-color: var(--yee-error-color-hover);
66
+ --yee-input-focus-bs-color: var(--yee-error-color-border);
67
+ }
68
+
69
+ &&-warning {
70
+ --yee-input-border-color: var(--yee-warning-color);
71
+ --yee-input-hover-border-color: var(--yee-warning-color-hover);
72
+ --yee-input-focus-bs-color: var(--yee-warning-color-border);
73
+ }
59
74
  }
60
75
  }
@@ -69,6 +69,25 @@
69
69
  }
70
70
  }
71
71
 
72
+ // size
73
+ &-small {
74
+ height: var(--yee-input-small-height, 24px);
75
+ padding: var(--yee-input-small-padding, 0 6px);
76
+ font-size: var(--yee-input-small-font-size);
77
+ line-height: var(--yee-input-small-line-height);
78
+
79
+ &::placeholder {
80
+ font-size: var(--yee-input-small-font-size);
81
+ }
82
+ }
83
+
84
+ &-large {
85
+ height: var(--yee-input-large-height, 40px);
86
+ padding: var(--yee-input-large-padding, 4px 12px);
87
+ font-size: var(--yee-input-large-font-size);
88
+ line-height: var(--yee-input-large-line-height);
89
+ }
90
+
72
91
  &-password {
73
92
  flex: 1;
74
93
  outline: none;
@@ -91,20 +110,3 @@ input[type='number']::-webkit-outer-spin-button {
91
110
  input::placeholder {
92
111
  color: var(--yee-placeholder-color);
93
112
  }
94
-
95
- // form error status
96
- .yee-form-item-error {
97
- @{pls} {
98
- border-color: var(--yee-error-color);
99
-
100
- &:hover {
101
- border-color: var(--yee-error-color-hover);
102
- }
103
- }
104
- }
105
-
106
- .yee-form-item-warning {
107
- @{pls} {
108
- border-color: var(--yee-warning-color);
109
- }
110
- }
@@ -185,32 +185,3 @@
185
185
  padding-right: 0;
186
186
  }
187
187
  }
188
-
189
- // Form error status
190
- .yee-form-item-error {
191
- @{pls} {
192
- border-color: var(--yee-error-color);
193
-
194
- &:not(@{pls}-disabled):hover {
195
- border-color: var(--yee-error-color);
196
- }
197
-
198
- &-focused {
199
- box-shadow: 0 0 0 2px var(--yee-input-content-error-focus-bs-color);
200
- }
201
- }
202
- }
203
-
204
- .yee-form-item-warning {
205
- @{pls} {
206
- border-color: var(--yee-warning-color);
207
-
208
- &:not(@{pls}-disabled):hover {
209
- border-color: var(--yee-warning-color);
210
- }
211
-
212
- &-focused {
213
- box-shadow: 0 0 0 2px var(--yee-input-content-warning-focus-bs-color);
214
- }
215
- }
216
- }
@@ -1,4 +1,5 @@
1
1
  import { Dayjs } from 'dayjs';
2
+ import type { usePanelConfigs } from './configs/locale-adapter';
2
3
  export type PickerType =
3
4
  | 'date'
4
5
  | 'week'
@@ -18,6 +19,9 @@ export type SemanticType =
18
19
 
19
20
  export type UnitType = 'day' | 'hour' | 'minute' | 'second';
20
21
 
22
+ /** Hour/minute/second granularity used by the time sub-panels. */
23
+ export type TimeUnit = 'hour' | 'minute' | 'second';
24
+
21
25
  interface HeaderProps {
22
26
  showPrevIcon?: boolean;
23
27
  showNextIcon?: boolean;
@@ -115,13 +119,50 @@ export interface PickerPanelProps extends HeaderProps {
115
119
  /**
116
120
  * Hover range dates [start date, end date]
117
121
  */
118
- hoverRange?: Array<Dayjs | null>;
122
+ hoverRange?: Array<Dayjs | null | undefined>;
119
123
  /**
120
124
  * Selected range dates [start date, end date]
121
125
  */
122
- selectedRange?: Array<Dayjs | null>;
126
+ selectedRange?: Array<Dayjs | null | undefined>;
123
127
  /**
124
128
  * Disabled date function
125
129
  */
126
130
  disabledDate?: (current: Dayjs) => boolean;
127
131
  }
132
+
133
+ /**
134
+ * Locale/config bag produced by `usePanelConfigs`, shared by every panel.
135
+ */
136
+ export type PanelConfigs = ReturnType<typeof usePanelConfigs>;
137
+
138
+ /**
139
+ * The `panelProps` bag shared by all date-picking panels, headers and bodies.
140
+ *
141
+ * Standalone (does not extend `PickerPanelProps`) so each panel only declares
142
+ * the fields it actually reads while still receiving the full bag via
143
+ * `{...props}` spreads (JSX spreads do not trigger excess-property checks).
144
+ */
145
+ export interface PanelSharedProps {
146
+ prefixCls?: string;
147
+ picker?: PickerType;
148
+ offset?: { year?: number; month?: number; day?: number };
149
+ viewDate: Dayjs;
150
+ selectedDate?: Dayjs;
151
+ panelConfigs: PanelConfigs;
152
+ handleMouseChange?: (date: Dayjs | '') => void;
153
+ onViewDateChange: (date: Dayjs) => void;
154
+ onPanelChange: (view: PickerType) => void;
155
+ onSelect?: (date: Dayjs) => void;
156
+ offsetYear?: number;
157
+ /** Never set in `panelProps`, so always `undefined` at runtime. */
158
+ nowDate?: Dayjs;
159
+ weekStart?: number;
160
+ showHeader?: boolean;
161
+ cellRender?: (date: Dayjs, panel: PickerType) => React.ReactNode;
162
+ prefixColumn?: (currentDate: Dayjs) => React.ReactNode;
163
+ getRowClassName?: (currentDate: Dayjs) => string;
164
+ hoverRange?: Array<Dayjs | null | undefined>;
165
+ selectedRange?: Array<Dayjs | null | undefined>;
166
+ maxDate?: Dayjs;
167
+ minDate?: Dayjs;
168
+ }
@@ -2,6 +2,7 @@ import clsx from 'clsx';
2
2
  import { Dayjs } from 'dayjs';
3
3
  import React from 'react';
4
4
  import useEvent from '../../../hooks/useEvent';
5
+ import type { PanelSharedProps } from '../../interface';
5
6
  import panelConfig from '../../configs';
6
7
  import pickerUtils from '../../utils/pickerUtils';
7
8
  import PanelBody from '../PanelBody';
@@ -10,7 +11,7 @@ const DATEPANEL_WEEK_DAY_COUNT = 7;
10
11
 
11
12
  const weekTitle = panelConfig.shortWeekList;
12
13
 
13
- function DateBody(props: any) {
14
+ function DateBody(props: PanelSharedProps) {
14
15
  const {
15
16
  prefixCls,
16
17
  viewDate,
@@ -2,10 +2,11 @@ import React from 'react';
2
2
  import Button from '../../../Button';
3
3
  import useEvent from '../../../hooks/useEvent';
4
4
  import { useLocale } from '../../../locale';
5
+ import type { PanelSharedProps } from '../../interface';
5
6
  import pickerUtils from '../../utils/pickerUtils';
6
7
  import Header from '../Header';
7
8
 
8
- export default function DateHeader(props: any) {
9
+ export default function DateHeader(props: PanelSharedProps) {
9
10
  const { locale, lang } = useLocale();
10
11
  const { datepicker } = locale;
11
12
 
@@ -15,7 +16,7 @@ export default function DateHeader(props: any) {
15
16
  const month = pickerUtils.getMonth(viewDate);
16
17
 
17
18
  if (offset?.year) {
18
- year = year + parseInt(offset.year);
19
+ year = year + offset.year;
19
20
  }
20
21
 
21
22
  const onSuperPrevClick = useEvent(() => {
@@ -1,8 +1,9 @@
1
1
  import React from 'react';
2
+ import type { PanelSharedProps } from '../../interface';
2
3
  import DateBody from './DateBody';
3
4
  import DateHeader from './DateHeader';
4
5
 
5
- export default function DatePanel(props: any) {
6
+ export default function DatePanel(props: PanelSharedProps) {
6
7
  const { prefixCls, showHeader = true } = props;
7
8
 
8
9
  return (
@@ -1,24 +1,31 @@
1
1
  import { Dayjs } from 'dayjs';
2
2
  import * as React from 'react';
3
+ import type { PickerType, PanelSharedProps } from '../../interface';
3
4
  import DatePanel from '../DatePanel';
4
5
  import TimePanel from '../TimePanel';
5
6
 
6
- function DateTimePanel(props: any) {
7
- const { prefixCls = 'yee-picker', onSelect, showTime } = props;
7
+ interface DateTimePanelProps extends Omit<PanelSharedProps, 'onSelect'> {
8
+ onSelect?: (panel: PickerType, date: Dayjs) => void;
9
+ showTime?: boolean;
10
+ }
11
+
12
+ function DateTimePanel(props: DateTimePanelProps) {
13
+ const { onSelect, showTime, ...rest } = props;
14
+ const prefixCls = rest.prefixCls ?? 'yee-picker';
8
15
 
9
16
  const handleSelect = (type: string, date: Dayjs) => {
10
- onSelect(type, date);
17
+ onSelect?.(type as PickerType, date);
11
18
  };
12
19
 
13
20
  return (
14
21
  <div className={`${prefixCls}-datetime-panel`}>
15
22
  <DatePanel
16
- {...props}
23
+ {...rest}
17
24
  onSelect={(date: Dayjs) => handleSelect('date', date)}
18
25
  />
19
26
  {showTime ? (
20
27
  <TimePanel
21
- {...props}
28
+ {...rest}
22
29
  onSelect={(date: Dayjs) => handleSelect('datetimetime', date)}
23
30
  showHeader
24
31
  />
@@ -2,11 +2,12 @@ import clsx from 'clsx';
2
2
  import { Dayjs } from 'dayjs';
3
3
  import * as React from 'react';
4
4
  import useEvent from '../../../hooks/useEvent';
5
+ import type { PanelSharedProps } from '../../interface';
5
6
  import pickerUtils from '../../utils/pickerUtils';
6
7
  import PanelBody from '../PanelBody';
7
8
 
8
- function DecadeBody(props: any) {
9
- const { prefixCls, viewDate, offsetYear } = props;
9
+ function DecadeBody(props: PanelSharedProps) {
10
+ const { prefixCls, viewDate, offsetYear = 0 } = props;
10
11
 
11
12
  const baseDate = pickerUtils.getBaseDate('decade', viewDate);
12
13
 
@@ -1,10 +1,11 @@
1
1
  import * as React from 'react';
2
2
  import useEvent from '../../../hooks/useEvent';
3
+ import type { PanelSharedProps } from '../../interface';
3
4
  import pickerUtils from '../../utils/pickerUtils';
4
5
  import Header from '../Header';
5
6
 
6
- export default function DecadeHeader(props: any) {
7
- const { viewDate, offsetYear, onViewDateChange } = props;
7
+ export default function DecadeHeader(props: PanelSharedProps) {
8
+ const { viewDate, offsetYear = 0, onViewDateChange } = props;
8
9
  const onSuperPrevClick = useEvent(() => {
9
10
  onViewDateChange(pickerUtils.addYear(viewDate, -100));
10
11
  });
@@ -1,14 +1,15 @@
1
1
  import * as React from 'react';
2
+ import type { PanelSharedProps } from '../../interface';
2
3
 
3
4
  import DecadeBody from './DecadeBody';
4
5
  import DecadeHeader from './DecadeHeader';
5
6
 
6
- export default function DecadePanel(props: any) {
7
+ export default function DecadePanel(props: PanelSharedProps) {
7
8
  const { prefixCls, offset } = props;
8
9
 
9
10
  let offsetYear = 0;
10
11
  if (offset?.year) {
11
- offsetYear = parseInt(offset.year);
12
+ offsetYear = offset.year;
12
13
  }
13
14
 
14
15
  return (
@@ -7,7 +7,20 @@ import {
7
7
  import React from 'react';
8
8
  import Button from '../../Button';
9
9
 
10
- export default function Header(props: any) {
10
+ export interface PanelHeaderProps {
11
+ prefixCls?: string;
12
+ onPrevClick?: () => void;
13
+ onSuperPrevClick?: () => void;
14
+ onNextClick?: () => void;
15
+ onSuperNextClick?: () => void;
16
+ showPrevIcon?: boolean;
17
+ showNextIcon?: boolean;
18
+ showSuperPrevIcon?: boolean;
19
+ showSuperNextIcon?: boolean;
20
+ children?: React.ReactNode;
21
+ }
22
+
23
+ export default function Header(props: PanelHeaderProps) {
11
24
  const {
12
25
  prefixCls,
13
26
  onPrevClick,