@falcon-ui/falcon-ui 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (289) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +182 -0
  3. package/cjs/JsBarcode-BlUjuVmB.cjs +3519 -0
  4. package/cjs/JsBarcode-BlUjuVmB.cjs.map +1 -0
  5. package/cjs/chunk-D4y6LrGi.cjs +40 -0
  6. package/cjs/components/JsBarcode-BOXEZn4Q.cjs +3519 -0
  7. package/cjs/components/JsBarcode-BOXEZn4Q.cjs.map +1 -0
  8. package/cjs/components/barcode/JsBarcode-BOXEZn4Q.cjs +3519 -0
  9. package/cjs/components/barcode/JsBarcode-BOXEZn4Q.cjs.map +1 -0
  10. package/cjs/components/barcode/chunk-D4y6LrGi.cjs +40 -0
  11. package/cjs/components/barcode/index.cjs +211 -0
  12. package/cjs/components/barcode/index.cjs.map +1 -0
  13. package/cjs/components/barcode/src/JsBarcode-BOXEZn4Q.cjs +3519 -0
  14. package/cjs/components/barcode/src/JsBarcode-BOXEZn4Q.cjs.map +1 -0
  15. package/cjs/components/barcode/src/barcode.cjs +102 -0
  16. package/cjs/components/barcode/src/barcode.cjs.map +1 -0
  17. package/cjs/components/barcode/src/barcode.vue.cjs +200 -0
  18. package/cjs/components/barcode/src/barcode.vue.cjs.map +1 -0
  19. package/cjs/components/barcode/src/chunk-D4y6LrGi.cjs +40 -0
  20. package/cjs/components/button/index.cjs +135 -0
  21. package/cjs/components/button/index.cjs.map +1 -0
  22. package/cjs/components/button/src/button.cjs +16 -0
  23. package/cjs/components/button/src/button.cjs.map +1 -0
  24. package/cjs/components/button/src/button.vue.cjs +124 -0
  25. package/cjs/components/button/src/button.vue.cjs.map +1 -0
  26. package/cjs/components/chunk-D4y6LrGi.cjs +40 -0
  27. package/cjs/components/date-picker/index.cjs +164 -0
  28. package/cjs/components/date-picker/index.cjs.map +1 -0
  29. package/cjs/components/date-picker/src/date-picker.cjs +25 -0
  30. package/cjs/components/date-picker/src/date-picker.cjs.map +1 -0
  31. package/cjs/components/date-picker/src/date-picker.vue.cjs +153 -0
  32. package/cjs/components/date-picker/src/date-picker.vue.cjs.map +1 -0
  33. package/cjs/components/dialog/index.cjs +346 -0
  34. package/cjs/components/dialog/index.cjs.map +1 -0
  35. package/cjs/components/dialog/src/dialog.cjs +40 -0
  36. package/cjs/components/dialog/src/dialog.cjs.map +1 -0
  37. package/cjs/components/dialog/src/dialog.vue.cjs +343 -0
  38. package/cjs/components/dialog/src/dialog.vue.cjs.map +1 -0
  39. package/cjs/components/index.cjs +9450 -0
  40. package/cjs/components/index.cjs.map +1 -0
  41. package/cjs/components/input/index.cjs +175 -0
  42. package/cjs/components/input/index.cjs.map +1 -0
  43. package/cjs/components/input/src/input.cjs +27 -0
  44. package/cjs/components/input/src/input.cjs.map +1 -0
  45. package/cjs/components/input/src/input.vue.cjs +164 -0
  46. package/cjs/components/input/src/input.vue.cjs.map +1 -0
  47. package/cjs/components/input-number/index.cjs +374 -0
  48. package/cjs/components/input-number/index.cjs.map +1 -0
  49. package/cjs/components/input-number/src/input-number.cjs +48 -0
  50. package/cjs/components/input-number/src/input-number.cjs.map +1 -0
  51. package/cjs/components/input-number/src/input-number.vue.cjs +363 -0
  52. package/cjs/components/input-number/src/input-number.vue.cjs.map +1 -0
  53. package/cjs/components/input-search/index.cjs +286 -0
  54. package/cjs/components/input-search/index.cjs.map +1 -0
  55. package/cjs/components/input-search/src/input-search.cjs +55 -0
  56. package/cjs/components/input-search/src/input-search.cjs.map +1 -0
  57. package/cjs/components/input-search/src/input-search.vue.cjs +275 -0
  58. package/cjs/components/input-search/src/input-search.vue.cjs.map +1 -0
  59. package/cjs/components/qr-code/index.cjs +1975 -0
  60. package/cjs/components/qr-code/index.cjs.map +1 -0
  61. package/cjs/components/qr-code/src/qr-code.cjs +63 -0
  62. package/cjs/components/qr-code/src/qr-code.cjs.map +1 -0
  63. package/cjs/components/qr-code/src/qr-code.vue.cjs +1964 -0
  64. package/cjs/components/qr-code/src/qr-code.vue.cjs.map +1 -0
  65. package/cjs/components/radial-menu/index.cjs +983 -0
  66. package/cjs/components/radial-menu/index.cjs.map +1 -0
  67. package/cjs/components/radial-menu/src/radial-menu.cjs +96 -0
  68. package/cjs/components/radial-menu/src/radial-menu.cjs.map +1 -0
  69. package/cjs/components/radial-menu/src/radial-menu.vue.cjs +921 -0
  70. package/cjs/components/radial-menu/src/radial-menu.vue.cjs.map +1 -0
  71. package/cjs/components/select/index.cjs +163 -0
  72. package/cjs/components/select/index.cjs.map +1 -0
  73. package/cjs/components/select/src/select.cjs +16 -0
  74. package/cjs/components/select/src/select.cjs.map +1 -0
  75. package/cjs/components/select/src/select.vue.cjs +152 -0
  76. package/cjs/components/select/src/select.vue.cjs.map +1 -0
  77. package/cjs/components/table/index.cjs +3351 -0
  78. package/cjs/components/table/index.cjs.map +1 -0
  79. package/cjs/components/table/src/table.cjs +62 -0
  80. package/cjs/components/table/src/table.cjs.map +1 -0
  81. package/cjs/components/table/src/table.vue.cjs +3085 -0
  82. package/cjs/components/table/src/table.vue.cjs.map +1 -0
  83. package/cjs/dialog-CJU00aEV.cjs +614 -0
  84. package/cjs/dialog-CJU00aEV.cjs.map +1 -0
  85. package/cjs/dialog-DcH26KbE.cjs +2 -0
  86. package/cjs/hooks/dialog-DpYPBcKV.cjs +266 -0
  87. package/cjs/hooks/dialog-DpYPBcKV.cjs.map +1 -0
  88. package/cjs/hooks/hooks-D2Jaq5kO.cjs +328 -0
  89. package/cjs/hooks/hooks-D2Jaq5kO.cjs.map +1 -0
  90. package/cjs/hooks/index.cjs +8 -0
  91. package/cjs/icons/index.cjs +86 -0
  92. package/cjs/icons/index.cjs.map +1 -0
  93. package/cjs/index.cjs +9141 -0
  94. package/cjs/index.cjs.map +1 -0
  95. package/cjs/utils/index.cjs +69 -0
  96. package/cjs/utils/index.cjs.map +1 -0
  97. package/esm/JsBarcode-kVJER62m.js +3514 -0
  98. package/esm/JsBarcode-kVJER62m.js.map +1 -0
  99. package/esm/chunk-BuRq7rDw.js +23 -0
  100. package/esm/components/JsBarcode-CzzxrEd_.js +3514 -0
  101. package/esm/components/JsBarcode-CzzxrEd_.js.map +1 -0
  102. package/esm/components/barcode/JsBarcode-C5ux6wsb.js +3514 -0
  103. package/esm/components/barcode/JsBarcode-C5ux6wsb.js.map +1 -0
  104. package/esm/components/barcode/chunk--em_ddB3.js +23 -0
  105. package/esm/components/barcode/index.mjs +204 -0
  106. package/esm/components/barcode/index.mjs.map +1 -0
  107. package/esm/components/barcode/src/JsBarcode-C5ux6wsb.js +3514 -0
  108. package/esm/components/barcode/src/JsBarcode-C5ux6wsb.js.map +1 -0
  109. package/esm/components/barcode/src/barcode.mjs +98 -0
  110. package/esm/components/barcode/src/barcode.mjs.map +1 -0
  111. package/esm/components/barcode/src/barcode.vue.mjs +194 -0
  112. package/esm/components/barcode/src/barcode.vue.mjs.map +1 -0
  113. package/esm/components/barcode/src/chunk--em_ddB3.js +23 -0
  114. package/esm/components/button/index.mjs +126 -0
  115. package/esm/components/button/index.mjs.map +1 -0
  116. package/esm/components/button/src/button.mjs +14 -0
  117. package/esm/components/button/src/button.mjs.map +1 -0
  118. package/esm/components/button/src/button.vue.mjs +117 -0
  119. package/esm/components/button/src/button.vue.mjs.map +1 -0
  120. package/esm/components/chunk-BuRq7rDw.js +23 -0
  121. package/esm/components/date-picker/index.mjs +155 -0
  122. package/esm/components/date-picker/index.mjs.map +1 -0
  123. package/esm/components/date-picker/src/date-picker.mjs +23 -0
  124. package/esm/components/date-picker/src/date-picker.mjs.map +1 -0
  125. package/esm/components/date-picker/src/date-picker.vue.mjs +146 -0
  126. package/esm/components/date-picker/src/date-picker.vue.mjs.map +1 -0
  127. package/esm/components/dialog/index.mjs +335 -0
  128. package/esm/components/dialog/index.mjs.map +1 -0
  129. package/esm/components/dialog/src/dialog.mjs +38 -0
  130. package/esm/components/dialog/src/dialog.mjs.map +1 -0
  131. package/esm/components/dialog/src/dialog.vue.mjs +334 -0
  132. package/esm/components/dialog/src/dialog.vue.mjs.map +1 -0
  133. package/esm/components/index.mjs +9386 -0
  134. package/esm/components/index.mjs.map +1 -0
  135. package/esm/components/input/index.mjs +166 -0
  136. package/esm/components/input/index.mjs.map +1 -0
  137. package/esm/components/input/src/input.mjs +25 -0
  138. package/esm/components/input/src/input.mjs.map +1 -0
  139. package/esm/components/input/src/input.vue.mjs +157 -0
  140. package/esm/components/input/src/input.vue.mjs.map +1 -0
  141. package/esm/components/input-number/index.mjs +365 -0
  142. package/esm/components/input-number/index.mjs.map +1 -0
  143. package/esm/components/input-number/src/input-number.mjs +45 -0
  144. package/esm/components/input-number/src/input-number.mjs.map +1 -0
  145. package/esm/components/input-number/src/input-number.vue.mjs +356 -0
  146. package/esm/components/input-number/src/input-number.vue.mjs.map +1 -0
  147. package/esm/components/input-search/index.mjs +277 -0
  148. package/esm/components/input-search/index.mjs.map +1 -0
  149. package/esm/components/input-search/src/input-search.mjs +53 -0
  150. package/esm/components/input-search/src/input-search.mjs.map +1 -0
  151. package/esm/components/input-search/src/input-search.vue.mjs +268 -0
  152. package/esm/components/input-search/src/input-search.vue.mjs.map +1 -0
  153. package/esm/components/qr-code/index.mjs +1967 -0
  154. package/esm/components/qr-code/index.mjs.map +1 -0
  155. package/esm/components/qr-code/src/qr-code.mjs +59 -0
  156. package/esm/components/qr-code/src/qr-code.mjs.map +1 -0
  157. package/esm/components/qr-code/src/qr-code.vue.mjs +1958 -0
  158. package/esm/components/qr-code/src/qr-code.vue.mjs.map +1 -0
  159. package/esm/components/radial-menu/index.mjs +974 -0
  160. package/esm/components/radial-menu/index.mjs.map +1 -0
  161. package/esm/components/radial-menu/src/radial-menu.mjs +94 -0
  162. package/esm/components/radial-menu/src/radial-menu.mjs.map +1 -0
  163. package/esm/components/radial-menu/src/radial-menu.vue.mjs +916 -0
  164. package/esm/components/radial-menu/src/radial-menu.vue.mjs.map +1 -0
  165. package/esm/components/select/index.mjs +154 -0
  166. package/esm/components/select/index.mjs.map +1 -0
  167. package/esm/components/select/src/select.mjs +14 -0
  168. package/esm/components/select/src/select.mjs.map +1 -0
  169. package/esm/components/select/src/select.vue.mjs +145 -0
  170. package/esm/components/select/src/select.vue.mjs.map +1 -0
  171. package/esm/components/table/index.mjs +3342 -0
  172. package/esm/components/table/index.mjs.map +1 -0
  173. package/esm/components/table/src/table.mjs +60 -0
  174. package/esm/components/table/src/table.mjs.map +1 -0
  175. package/esm/components/table/src/table.vue.mjs +3080 -0
  176. package/esm/components/table/src/table.vue.mjs.map +1 -0
  177. package/esm/dialog-Cm3Px-Bu.js +537 -0
  178. package/esm/dialog-Cm3Px-Bu.js.map +1 -0
  179. package/esm/dialog-CzZm50XM.js +2 -0
  180. package/esm/hooks/dialog-d4SMZWbw.js +261 -0
  181. package/esm/hooks/dialog-d4SMZWbw.js.map +1 -0
  182. package/esm/hooks/hooks-DdjieG2I.js +281 -0
  183. package/esm/hooks/hooks-DdjieG2I.js.map +1 -0
  184. package/esm/hooks/index.mjs +2 -0
  185. package/esm/icons/index.mjs +79 -0
  186. package/esm/icons/index.mjs.map +1 -0
  187. package/esm/index.mjs +9065 -0
  188. package/esm/index.mjs.map +1 -0
  189. package/esm/utils/index.mjs +65 -0
  190. package/esm/utils/index.mjs.map +1 -0
  191. package/global.d.ts +39 -0
  192. package/package.json +131 -0
  193. package/theme/index.css +1 -0
  194. package/theme/index.scss +16 -0
  195. package/theme/src/barcode.scss +14 -0
  196. package/theme/src/button.scss +65 -0
  197. package/theme/src/date-picker.scss +87 -0
  198. package/theme/src/dialog.scss +146 -0
  199. package/theme/src/ep-vars.scss +11 -0
  200. package/theme/src/input-number.scss +66 -0
  201. package/theme/src/input-search.scss +78 -0
  202. package/theme/src/input.scss +66 -0
  203. package/theme/src/mixins/bem.scss +35 -0
  204. package/theme/src/mixins/color.scss +8 -0
  205. package/theme/src/qr-code.scss +23 -0
  206. package/theme/src/radial-menu.scss +346 -0
  207. package/theme/src/select.scss +44 -0
  208. package/theme/src/table.scss +143 -0
  209. package/theme/src/tokens.scss +26 -0
  210. package/theme/src/tree-select.scss +45 -0
  211. package/theme/src/tree.scss +369 -0
  212. package/types/components/barcode/index.d.ts +183 -0
  213. package/types/components/barcode/src/barcode.d.ts +147 -0
  214. package/types/components/barcode/src/barcode.vue.d.ts +184 -0
  215. package/types/components/button/index.d.ts +135 -0
  216. package/types/components/button/src/button.d.ts +33 -0
  217. package/types/components/button/src/button.vue.d.ts +138 -0
  218. package/types/components/date-picker/index.d.ts +508 -0
  219. package/types/components/date-picker/src/date-picker.d.ts +35 -0
  220. package/types/components/date-picker/src/date-picker.vue.d.ts +509 -0
  221. package/types/components/dialog/index.d.ts +630 -0
  222. package/types/components/dialog/src/dialog.d.ts +70 -0
  223. package/types/components/dialog/src/dialog.vue.d.ts +257 -0
  224. package/types/components/index.d.ts +27 -0
  225. package/types/components/input/index.d.ts +233 -0
  226. package/types/components/input/src/input.d.ts +65 -0
  227. package/types/components/input/src/input.vue.d.ts +239 -0
  228. package/types/components/input-number/index.d.ts +713 -0
  229. package/types/components/input-number/src/input-number.d.ts +101 -0
  230. package/types/components/input-number/src/input-number.vue.d.ts +283 -0
  231. package/types/components/input-search/index.d.ts +113 -0
  232. package/types/components/input-search/src/input-search.d.ts +128 -0
  233. package/types/components/input-search/src/input-search.vue.d.ts +114 -0
  234. package/types/components/qr-code/index.d.ts +109 -0
  235. package/types/components/qr-code/src/qr-code.d.ts +93 -0
  236. package/types/components/qr-code/src/qr-code.vue.d.ts +109 -0
  237. package/types/components/radial-menu/index.d.ts +499 -0
  238. package/types/components/radial-menu/src/radial-menu-item.d.ts +40 -0
  239. package/types/components/radial-menu/src/radial-menu-item.vue.d.ts +95 -0
  240. package/types/components/radial-menu/src/radial-menu.d.ts +92 -0
  241. package/types/components/radial-menu/src/radial-menu.vue.d.ts +200 -0
  242. package/types/components/radial-menu/src/types.d.ts +48 -0
  243. package/types/components/radial-menu/src/use-radial-menu-items.d.ts +19 -0
  244. package/types/components/radial-menu/src/use-radial-menu-keyboard.d.ts +17 -0
  245. package/types/components/radial-menu/src/use-radial-menu-position.d.ts +45 -0
  246. package/types/components/radial-menu/src/use-radial-menu-shortcut.d.ts +8 -0
  247. package/types/components/radial-menu/src/use-radial-menu-state.d.ts +15 -0
  248. package/types/components/select/index.d.ts +5 -0
  249. package/types/components/select/src/select.d.ts +30 -0
  250. package/types/components/select/src/select.vue.d.ts +25 -0
  251. package/types/components/table/index.d.ts +8 -0
  252. package/types/components/table/src/editor-registry.d.ts +24 -0
  253. package/types/components/table/src/proxy-data.d.ts +10 -0
  254. package/types/components/table/src/table-editor.d.ts +18 -0
  255. package/types/components/table/src/table-editor.vue.d.ts +43 -0
  256. package/types/components/table/src/table.d.ts +179 -0
  257. package/types/components/table/src/table.vue.d.ts +121 -0
  258. package/types/components/tree/index.d.ts +5 -0
  259. package/types/components/tree/src/tree-node.vue.d.ts +88 -0
  260. package/types/components/tree/src/tree-types.d.ts +90 -0
  261. package/types/components/tree/src/tree.d.ts +448 -0
  262. package/types/components/tree/src/tree.vue.d.ts +301 -0
  263. package/types/components/tree/src/use-tree-check-conduct.d.ts +43 -0
  264. package/types/components/tree/src/use-tree-checked-state.d.ts +34 -0
  265. package/types/components/tree/src/use-tree-drag.d.ts +45 -0
  266. package/types/components/tree/src/use-tree-expanded-state.d.ts +41 -0
  267. package/types/components/tree/src/use-tree-keyboard.d.ts +21 -0
  268. package/types/components/tree/src/use-tree-load.d.ts +25 -0
  269. package/types/components/tree/src/use-tree-scroll.d.ts +17 -0
  270. package/types/components/tree/src/use-tree-selected-state.d.ts +29 -0
  271. package/types/components/tree-select/index.d.ts +5 -0
  272. package/types/components/tree-select/src/tree-select.d.ts +26 -0
  273. package/types/components/tree-select/src/tree-select.vue.d.ts +25 -0
  274. package/types/falcon-ui/index.d.ts +8 -0
  275. package/types/hooks/index.d.ts +3 -0
  276. package/types/hooks/src/use-clearable-state.d.ts +10 -0
  277. package/types/hooks/src/use-component.d.ts +15 -0
  278. package/types/hooks/src/use-dialog.d.ts +49 -0
  279. package/types/icons/index.d.ts +1 -0
  280. package/types/icons/src/components/holder-outlined.vue.d.ts +3 -0
  281. package/types/icons/src/components/index.d.ts +3 -0
  282. package/types/icons/src/components/minus-square-outlined.vue.d.ts +3 -0
  283. package/types/icons/src/components/plus-square-outlined.vue.d.ts +3 -0
  284. package/types/utils/index.d.ts +3 -0
  285. package/types/utils/src/bem.d.ts +11 -0
  286. package/types/utils/src/component.d.ts +6 -0
  287. package/types/utils/src/install.d.ts +5 -0
  288. package/umd/falcon-ui.umd.js +13297 -0
  289. package/umd/falcon-ui.umd.js.map +1 -0
@@ -0,0 +1,277 @@
1
+ import { computed, createBlock, createElementVNode, createVNode, defineComponent, normalizeClass, openBlock, ref, unref, watch, withCtx, withKeys, withModifiers } from "vue";
2
+ import { Loading, Search } from "@element-plus/icons-vue";
3
+ import { ElIcon, ElInput } from "element-plus";
4
+ var defaultNamespace = "fl";
5
+ var statePrefix = "is-";
6
+ var buildBemName = (namespace, block, blockSuffix = "", element = "", modifier = "") => {
7
+ let className = `${namespace}-${block}`;
8
+ if (blockSuffix) className += `-${blockSuffix}`;
9
+ if (element) className += `__${element}`;
10
+ if (modifier) className += `--${modifier}`;
11
+ return className;
12
+ };
13
+ const useNamespace = (block, namespace = defaultNamespace) => {
14
+ const b = (blockSuffix = "") => buildBemName(namespace, block, blockSuffix);
15
+ const e = (element) => element ? buildBemName(namespace, block, "", element) : "";
16
+ const m = (modifier) => modifier ? buildBemName(namespace, block, "", "", modifier) : "";
17
+ const be = (blockSuffix, element) => {
18
+ if (!blockSuffix || !element) return "";
19
+ return buildBemName(namespace, block, blockSuffix, element);
20
+ };
21
+ const em = (element, modifier) => {
22
+ if (!element || !modifier) return "";
23
+ return buildBemName(namespace, block, "", element, modifier);
24
+ };
25
+ const bm = (blockSuffix, modifier) => {
26
+ if (!blockSuffix || !modifier) return "";
27
+ return buildBemName(namespace, block, blockSuffix, "", modifier);
28
+ };
29
+ const bem = (blockSuffix, element, modifier) => {
30
+ if (!blockSuffix && !element && !modifier) return b();
31
+ return buildBemName(namespace, block, blockSuffix, element, modifier);
32
+ };
33
+ const is = (name, state = true) => state ? `${statePrefix}${name}` : "";
34
+ return {
35
+ namespace,
36
+ b,
37
+ e,
38
+ m,
39
+ be,
40
+ em,
41
+ bm,
42
+ bem,
43
+ is
44
+ };
45
+ };
46
+ const withInstall = (component) => {
47
+ const installable = component;
48
+ installable.install = (app) => {
49
+ if (!component.name) return;
50
+ app.component(component.name, component);
51
+ };
52
+ return installable;
53
+ };
54
+ const FlInputSearch = withInstall(/* @__PURE__ */ defineComponent({
55
+ name: "FlInputSearch",
56
+ inheritAttrs: false,
57
+ __name: "input-search",
58
+ props: {
59
+ modelValue: {
60
+ type: [String, Number],
61
+ default: null
62
+ },
63
+ label: {
64
+ type: String,
65
+ default: ""
66
+ },
67
+ fetchApi: {
68
+ type: Function,
69
+ default: void 0
70
+ },
71
+ mapResult: {
72
+ type: Function,
73
+ required: true
74
+ },
75
+ placeholder: {
76
+ type: String,
77
+ default: ""
78
+ },
79
+ disabled: {
80
+ type: Boolean,
81
+ default: false
82
+ },
83
+ clearable: {
84
+ type: Boolean,
85
+ default: false
86
+ },
87
+ isError: {
88
+ type: Boolean,
89
+ default: false
90
+ },
91
+ isTable: {
92
+ type: Boolean,
93
+ default: false
94
+ },
95
+ clearOnBlurUnconfirmed: {
96
+ type: Boolean,
97
+ default: true
98
+ }
99
+ },
100
+ emits: {
101
+ "update:modelValue": (value) => value === null || typeof value === "string" || typeof value === "number",
102
+ "update:label": (value) => typeof value === "string",
103
+ openDialog: (payload) => typeof payload.keyword === "string" && (payload.reason === "manual" || payload.reason === "multi-match") && (payload.results === void 0 || Array.isArray(payload.results)),
104
+ "selection-commit": (payload) => typeof payload.label === "string" && payload.source === "enter" && (payload.value === null || typeof payload.value === "string" || typeof payload.value === "number"),
105
+ "search-error": (payload) => typeof payload.keyword === "string",
106
+ clear: (payload) => payload.reason === "manual-empty" || payload.reason === "blur-unconfirmed" || payload.reason === "error"
107
+ },
108
+ setup(__props, { expose: __expose, emit: __emit }) {
109
+ const props = __props;
110
+ const emit = __emit;
111
+ const ns = useNamespace("input-search");
112
+ const inputRef = ref(null);
113
+ const innerLabel = ref(props.label);
114
+ const isLoading = ref(false);
115
+ const latestSearchToken = ref(0);
116
+ const lastValidLabel = ref(props.label);
117
+ const lastValidValue = ref(props.modelValue);
118
+ const inputClass = computed(() => [ns.b(), {
119
+ "is-error": props.isError,
120
+ "is-table": props.isTable
121
+ }]);
122
+ const searchTriggerClass = ns.e("trigger");
123
+ const normalizeLabel = (value) => typeof value === "string" ? value : "";
124
+ const normalizeValue = (value) => {
125
+ if (value === null || typeof value === "string" || typeof value === "number") return value;
126
+ return null;
127
+ };
128
+ const syncSnapshot = (value, label) => {
129
+ lastValidValue.value = value;
130
+ lastValidLabel.value = label;
131
+ };
132
+ const clearSelection = (reason) => {
133
+ innerLabel.value = "";
134
+ syncSnapshot(null, "");
135
+ emit("update:modelValue", null);
136
+ emit("update:label", "");
137
+ emit("clear", { reason });
138
+ };
139
+ const commitSelection = (result) => {
140
+ const nextValue = normalizeValue(result.value);
141
+ const nextLabel = normalizeLabel(result.label);
142
+ innerLabel.value = nextLabel;
143
+ syncSnapshot(nextValue, nextLabel);
144
+ emit("update:modelValue", nextValue);
145
+ emit("update:label", nextLabel);
146
+ emit("selection-commit", {
147
+ value: nextValue,
148
+ label: nextLabel,
149
+ source: "enter"
150
+ });
151
+ };
152
+ const handleInput = (value) => {
153
+ const nextLabel = normalizeLabel(value);
154
+ innerLabel.value = nextLabel;
155
+ emit("update:label", nextLabel);
156
+ };
157
+ const handleManualSearch = () => {
158
+ emit("openDialog", {
159
+ keyword: innerLabel.value.trim(),
160
+ reason: "manual"
161
+ });
162
+ };
163
+ const handleEnter = async () => {
164
+ if (isLoading.value) return;
165
+ const keyword = innerLabel.value.trim();
166
+ if (!keyword) return;
167
+ if (!props.fetchApi) {
168
+ emit("openDialog", {
169
+ keyword,
170
+ reason: "manual"
171
+ });
172
+ return;
173
+ }
174
+ const currentToken = latestSearchToken.value + 1;
175
+ latestSearchToken.value = currentToken;
176
+ isLoading.value = true;
177
+ try {
178
+ const response = await props.fetchApi(keyword);
179
+ if (currentToken !== latestSearchToken.value) return;
180
+ const results = Array.isArray(response) ? response : [];
181
+ if (results.length === 1) {
182
+ commitSelection(props.mapResult(results[0]));
183
+ return;
184
+ }
185
+ if (results.length > 1) emit("openDialog", {
186
+ keyword,
187
+ reason: "multi-match",
188
+ results
189
+ });
190
+ } catch (error) {
191
+ if (currentToken !== latestSearchToken.value) return;
192
+ emit("search-error", {
193
+ keyword,
194
+ error
195
+ });
196
+ } finally {
197
+ if (currentToken === latestSearchToken.value) isLoading.value = false;
198
+ }
199
+ };
200
+ const handleNativeClear = () => {
201
+ clearSelection("manual-empty");
202
+ };
203
+ const handleBlur = () => {
204
+ if (isLoading.value) return;
205
+ const currentLabel = innerLabel.value;
206
+ if (currentLabel === lastValidLabel.value) return;
207
+ if (!currentLabel) {
208
+ clearSelection("manual-empty");
209
+ return;
210
+ }
211
+ if (props.clearOnBlurUnconfirmed) clearSelection("blur-unconfirmed");
212
+ };
213
+ const focus = () => {
214
+ inputRef.value?.focus();
215
+ };
216
+ const blur = () => {
217
+ inputRef.value?.blur();
218
+ };
219
+ const clear = () => {
220
+ inputRef.value?.clear();
221
+ };
222
+ watch(() => props.label, (value) => {
223
+ innerLabel.value = value;
224
+ });
225
+ watch(() => props.modelValue, (value) => {
226
+ if (value === lastValidValue.value) return;
227
+ syncSnapshot(normalizeValue(value), props.label);
228
+ });
229
+ watch(() => props.isError, (isError, previousIsError) => {
230
+ if (isError && previousIsError !== true) clearSelection("error");
231
+ }, { immediate: true });
232
+ __expose({
233
+ focus,
234
+ blur,
235
+ clear
236
+ });
237
+ return (_ctx, _cache) => {
238
+ return openBlock(), createBlock(unref(ElInput), {
239
+ ref_key: "inputRef",
240
+ ref: inputRef,
241
+ class: normalizeClass(inputClass.value),
242
+ clearable: props.clearable,
243
+ disabled: props.disabled || isLoading.value,
244
+ "model-value": innerLabel.value,
245
+ placeholder: props.placeholder,
246
+ onBlur: handleBlur,
247
+ onClear: handleNativeClear,
248
+ onKeydown: withKeys(withModifiers(handleEnter, ["prevent"]), ["enter"]),
249
+ "onUpdate:modelValue": handleInput
250
+ }, {
251
+ suffix: withCtx(() => [createElementVNode("span", {
252
+ class: normalizeClass(unref(searchTriggerClass)),
253
+ "aria-label": "Search",
254
+ role: "button",
255
+ tabindex: "-1",
256
+ onClick: handleManualSearch,
257
+ onMousedown: _cache[0] || (_cache[0] = withModifiers(() => {}, ["prevent"]))
258
+ }, [createVNode(unref(ElIcon), { class: normalizeClass(unref(ns).is("loading", isLoading.value)) }, {
259
+ default: withCtx(() => [isLoading.value ? (openBlock(), createBlock(unref(Loading), { key: 0 })) : (openBlock(), createBlock(unref(Search), { key: 1 }))]),
260
+ _: 1
261
+ }, 8, ["class"])], 34)]),
262
+ _: 1
263
+ }, 8, [
264
+ "class",
265
+ "clearable",
266
+ "disabled",
267
+ "model-value",
268
+ "placeholder",
269
+ "onKeydown"
270
+ ]);
271
+ };
272
+ }
273
+ }));
274
+ var input_search_default = FlInputSearch;
275
+ export { FlInputSearch, input_search_default as default };
276
+
277
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../../../../packages/utils/src/bem.ts","../../../../../packages/utils/src/install.ts","../../../../../packages/components/input-search/src/input-search.ts","../../../../../packages/components/input-search/src/input-search.vue","../../../../../packages/components/input-search/src/input-search.vue","../../../../../packages/components/input-search/index.ts"],"sourcesContent":["const defaultNamespace = 'fl'\r\nconst statePrefix = 'is-'\r\n\r\nconst buildBemName = (\r\n namespace: string,\r\n block: string,\r\n blockSuffix = '',\r\n element = '',\r\n modifier = ''\r\n) => {\r\n let className = `${namespace}-${block}`\r\n\r\n if (blockSuffix) {\r\n className += `-${blockSuffix}`\r\n }\r\n\r\n if (element) {\r\n className += `__${element}`\r\n }\r\n\r\n if (modifier) {\r\n className += `--${modifier}`\r\n }\r\n\r\n return className\r\n}\r\n\r\nexport const useNamespace = (block: string, namespace = defaultNamespace) => {\r\n const b = (blockSuffix = '') => buildBemName(namespace, block, blockSuffix)\r\n\r\n const e = (element?: string) => (element ? buildBemName(namespace, block, '', element) : '')\r\n\r\n const m = (modifier?: string) =>\r\n modifier ? buildBemName(namespace, block, '', '', modifier) : ''\r\n\r\n const be = (blockSuffix?: string, element?: string) => {\r\n if (!blockSuffix || !element) {\r\n return ''\r\n }\r\n\r\n return buildBemName(namespace, block, blockSuffix, element)\r\n }\r\n\r\n const em = (element?: string, modifier?: string) => {\r\n if (!element || !modifier) {\r\n return ''\r\n }\r\n\r\n return buildBemName(namespace, block, '', element, modifier)\r\n }\r\n\r\n const bm = (blockSuffix?: string, modifier?: string) => {\r\n if (!blockSuffix || !modifier) {\r\n return ''\r\n }\r\n\r\n return buildBemName(namespace, block, blockSuffix, '', modifier)\r\n }\r\n\r\n const bem = (blockSuffix?: string, element?: string, modifier?: string) => {\r\n if (!blockSuffix && !element && !modifier) {\r\n return b()\r\n }\r\n\r\n return buildBemName(namespace, block, blockSuffix, element, modifier)\r\n }\r\n\r\n const is = (name: string, state = true) => (state ? `${statePrefix}${name}` : '')\r\n\r\n return {\r\n namespace,\r\n b,\r\n e,\r\n m,\r\n be,\r\n em,\r\n bm,\r\n bem,\r\n is\r\n }\r\n}\r\n","import type { App, Plugin } from 'vue'\r\n\r\nexport type SFCWithInstall<T> = T & Plugin\r\n\r\nexport const withInstall = <T extends { name?: string }>(component: T): SFCWithInstall<T> => {\r\n const installable = component as SFCWithInstall<T>\r\n\r\n installable.install = (app: App) => {\r\n if (!component.name) {\r\n return\r\n }\r\n\r\n app.component(component.name, component as unknown as object)\r\n }\r\n\r\n return installable\r\n}\r\n","import type { ExtractPublicPropTypes, PropType } from 'vue'\r\n\r\nexport type FlInputSearchValue = string | number | null\r\n\r\nexport interface FlInputSearchMappedResult {\r\n label: string\r\n value: FlInputSearchValue\r\n}\r\n\r\nexport type FlInputSearchFetchApi = (keyword: string) => Promise<unknown[]>\r\nexport type FlInputSearchMapResult = (item: unknown) => FlInputSearchMappedResult\r\n\r\nexport const flInputSearchProps = {\r\n /**\r\n * 绑定值,通常为业务实体 ID。\r\n */\r\n modelValue: {\r\n type: [String, Number] as PropType<string | number | null>,\r\n default: null\r\n },\r\n /**\r\n * 输入框显示值(业务标签)。\r\n */\r\n label: {\r\n type: String,\r\n default: ''\r\n },\r\n /**\r\n * 回车检索方法。\r\n */\r\n fetchApi: {\r\n type: Function as PropType<FlInputSearchFetchApi>,\r\n default: undefined\r\n },\r\n /**\r\n * 外部结果映射方法,统一映射到 value/label。\r\n */\r\n mapResult: {\r\n type: Function as PropType<FlInputSearchMapResult>,\r\n required: true\r\n },\r\n /**\r\n * 占位提示文案。\r\n */\r\n placeholder: {\r\n type: String,\r\n default: ''\r\n },\r\n /**\r\n * 是否禁用输入。\r\n */\r\n disabled: {\r\n type: Boolean,\r\n default: false\r\n },\r\n /**\r\n * 是否显示清空按钮。\r\n */\r\n clearable: {\r\n type: Boolean,\r\n default: false\r\n },\r\n /**\r\n * 是否进入错误态。\r\n */\r\n isError: {\r\n type: Boolean,\r\n default: false\r\n },\r\n /**\r\n * 是否用于表格单元格输入。\r\n */\r\n isTable: {\r\n type: Boolean,\r\n default: false\r\n },\r\n /**\r\n * Blur 时未确认输入是否强制清空。\r\n */\r\n clearOnBlurUnconfirmed: {\r\n type: Boolean,\r\n default: true\r\n }\r\n} as const\r\n\r\nexport type FlInputSearchOpenDialogReason = 'manual' | 'multi-match'\r\n\r\nexport interface FlInputSearchOpenDialogPayload {\r\n keyword: string\r\n reason: FlInputSearchOpenDialogReason\r\n results?: unknown[]\r\n}\r\n\r\nexport interface FlInputSearchSelectionCommitPayload {\r\n label: string\r\n source: 'enter'\r\n value: FlInputSearchValue\r\n}\r\n\r\nexport interface FlInputSearchSearchErrorPayload {\r\n error: unknown\r\n keyword: string\r\n}\r\n\r\nexport interface FlInputSearchClearPayload {\r\n reason: 'manual-empty' | 'blur-unconfirmed' | 'error'\r\n}\r\n\r\nexport const flInputSearchEmits = {\r\n /**\r\n * 绑定值更新事件。\r\n */\r\n 'update:modelValue': (value: FlInputSearchValue) =>\r\n value === null || typeof value === 'string' || typeof value === 'number',\r\n /**\r\n * 显示值更新事件。\r\n */\r\n 'update:label': (value: string) => typeof value === 'string',\r\n /**\r\n * 触发外部弹窗占位事件。\r\n */\r\n openDialog: (payload: FlInputSearchOpenDialogPayload) =>\r\n typeof payload.keyword === 'string' &&\r\n (payload.reason === 'manual' || payload.reason === 'multi-match') &&\r\n (payload.results === undefined || Array.isArray(payload.results)),\r\n /**\r\n * 唯一结果选中提交事件。\r\n */\r\n 'selection-commit': (payload: FlInputSearchSelectionCommitPayload) =>\r\n typeof payload.label === 'string' &&\r\n payload.source === 'enter' &&\r\n (payload.value === null ||\r\n typeof payload.value === 'string' ||\r\n typeof payload.value === 'number'),\r\n /**\r\n * 回车检索失败事件。\r\n */\r\n 'search-error': (payload: FlInputSearchSearchErrorPayload) => typeof payload.keyword === 'string',\r\n /**\r\n * 清空行为事件。\r\n */\r\n clear: (payload: FlInputSearchClearPayload) =>\r\n payload.reason === 'manual-empty' ||\r\n payload.reason === 'blur-unconfirmed' ||\r\n payload.reason === 'error'\r\n} as const\r\n\r\nexport type FlInputSearchProps = ExtractPublicPropTypes<typeof flInputSearchProps>\r\nexport type FlInputSearchEmits = typeof flInputSearchEmits\r\n\r\nexport type InputSearchProps = FlInputSearchProps\r\nexport type InputSearchEmits = FlInputSearchEmits\r\n","<template>\r\n <el-input\r\n ref=\"inputRef\"\r\n :class=\"inputClass\"\r\n :clearable=\"props.clearable\"\r\n :disabled=\"props.disabled || isLoading\"\r\n :model-value=\"innerLabel\"\r\n :placeholder=\"props.placeholder\"\r\n @blur=\"handleBlur\"\r\n @clear=\"handleNativeClear\"\r\n @keydown.enter.prevent=\"handleEnter\"\r\n @update:model-value=\"handleInput\">\r\n <template #suffix>\r\n <span\r\n :class=\"searchTriggerClass\"\r\n aria-label=\"Search\"\r\n role=\"button\"\r\n tabindex=\"-1\"\r\n @click=\"handleManualSearch\"\r\n @mousedown.prevent>\r\n <el-icon :class=\"ns.is('loading', isLoading)\">\r\n <Loading v-if=\"isLoading\" />\r\n <Search v-else />\r\n </el-icon>\r\n </span>\r\n </template>\r\n </el-input>\r\n</template>\r\n\r\n<script lang=\"ts\" setup>\r\nimport { Loading, Search } from '@element-plus/icons-vue'\r\nimport { ElIcon, ElInput } from 'element-plus'\r\nimport { computed, ref, watch } from 'vue'\r\nimport { useNamespace } from '@falcon-ui/utils'\r\nimport type { FlInputSearchMappedResult, FlInputSearchValue } from './input-search'\r\nimport { flInputSearchEmits, flInputSearchProps } from './input-search'\r\n\r\ndefineOptions({\r\n name: 'FlInputSearch',\r\n inheritAttrs: false\r\n})\r\n\r\ntype ElInputExpose = {\r\n blur: () => void\r\n clear: () => void\r\n focus: () => void\r\n}\r\n\r\nconst props = defineProps(flInputSearchProps)\r\nconst emit = defineEmits(flInputSearchEmits)\r\nconst ns = useNamespace('input-search')\r\n\r\nconst inputRef = ref<ElInputExpose | null>(null)\r\nconst innerLabel = ref(props.label)\r\nconst isLoading = ref(false)\r\nconst latestSearchToken = ref(0)\r\nconst lastValidLabel = ref(props.label)\r\nconst lastValidValue = ref<FlInputSearchValue>(props.modelValue)\r\n\r\nconst inputClass = computed(() => [\r\n ns.b(),\r\n {\r\n 'is-error': props.isError,\r\n 'is-table': props.isTable\r\n }\r\n])\r\n\r\nconst searchTriggerClass = ns.e('trigger')\r\n\r\nconst normalizeLabel = (value: unknown): string => (typeof value === 'string' ? value : '')\r\n\r\nconst normalizeValue = (value: unknown): FlInputSearchValue => {\r\n if (value === null || typeof value === 'string' || typeof value === 'number') {\r\n return value\r\n }\r\n\r\n return null\r\n}\r\n\r\nconst syncSnapshot = (value: FlInputSearchValue, label: string) => {\r\n lastValidValue.value = value\r\n lastValidLabel.value = label\r\n}\r\n\r\nconst clearSelection = (reason: 'manual-empty' | 'blur-unconfirmed' | 'error') => {\r\n innerLabel.value = ''\r\n syncSnapshot(null, '')\r\n\r\n emit('update:modelValue', null)\r\n emit('update:label', '')\r\n emit('clear', { reason })\r\n}\r\n\r\nconst commitSelection = (result: FlInputSearchMappedResult) => {\r\n const nextValue = normalizeValue(result.value)\r\n const nextLabel = normalizeLabel(result.label)\r\n\r\n innerLabel.value = nextLabel\r\n syncSnapshot(nextValue, nextLabel)\r\n\r\n emit('update:modelValue', nextValue)\r\n emit('update:label', nextLabel)\r\n emit('selection-commit', {\r\n value: nextValue,\r\n label: nextLabel,\r\n source: 'enter'\r\n })\r\n}\r\n\r\nconst handleInput = (value: string) => {\r\n const nextLabel = normalizeLabel(value)\r\n innerLabel.value = nextLabel\r\n emit('update:label', nextLabel)\r\n}\r\n\r\nconst handleManualSearch = () => {\r\n emit('openDialog', {\r\n keyword: innerLabel.value.trim(),\r\n reason: 'manual'\r\n })\r\n}\r\n\r\nconst handleEnter = async () => {\r\n if (isLoading.value) {\r\n return\r\n }\r\n\r\n const keyword = innerLabel.value.trim()\r\n if (!keyword) {\r\n return\r\n }\r\n\r\n if (!props.fetchApi) {\r\n emit('openDialog', {\r\n keyword,\r\n reason: 'manual'\r\n })\r\n return\r\n }\r\n\r\n const currentToken = latestSearchToken.value + 1\r\n latestSearchToken.value = currentToken\r\n isLoading.value = true\r\n\r\n try {\r\n const response = await props.fetchApi(keyword)\r\n if (currentToken !== latestSearchToken.value) {\r\n return\r\n }\r\n\r\n const results = Array.isArray(response) ? response : []\r\n\r\n if (results.length === 1) {\r\n commitSelection(props.mapResult(results[0]))\r\n return\r\n }\r\n\r\n if (results.length > 1) {\r\n emit('openDialog', {\r\n keyword,\r\n reason: 'multi-match',\r\n results\r\n })\r\n }\r\n } catch (error) {\r\n if (currentToken !== latestSearchToken.value) {\r\n return\r\n }\r\n\r\n emit('search-error', {\r\n keyword,\r\n error\r\n })\r\n } finally {\r\n if (currentToken === latestSearchToken.value) {\r\n isLoading.value = false\r\n }\r\n }\r\n}\r\n\r\nconst handleNativeClear = () => {\r\n clearSelection('manual-empty')\r\n}\r\n\r\nconst handleBlur = () => {\r\n if (isLoading.value) {\r\n return\r\n }\r\n\r\n const currentLabel = innerLabel.value\r\n if (currentLabel === lastValidLabel.value) {\r\n return\r\n }\r\n\r\n if (!currentLabel) {\r\n clearSelection('manual-empty')\r\n return\r\n }\r\n\r\n if (props.clearOnBlurUnconfirmed) {\r\n clearSelection('blur-unconfirmed')\r\n }\r\n}\r\n\r\nconst focus = () => {\r\n inputRef.value?.focus()\r\n}\r\n\r\nconst blur = () => {\r\n inputRef.value?.blur()\r\n}\r\n\r\nconst clear = () => {\r\n inputRef.value?.clear()\r\n}\r\n\r\nwatch(\r\n () => props.label,\r\n (value) => {\r\n innerLabel.value = value\r\n }\r\n)\r\n\r\nwatch(\r\n () => props.modelValue,\r\n (value) => {\r\n if (value === lastValidValue.value) {\r\n return\r\n }\r\n\r\n syncSnapshot(normalizeValue(value), props.label)\r\n }\r\n)\r\n\r\nwatch(\r\n () => props.isError,\r\n (isError, previousIsError) => {\r\n if (isError && previousIsError !== true) {\r\n clearSelection('error')\r\n }\r\n },\r\n { immediate: true }\r\n)\r\n\r\ndefineExpose({\r\n focus,\r\n blur,\r\n clear\r\n})\r\n</script>\r\n","<template>\r\n <el-input\r\n ref=\"inputRef\"\r\n :class=\"inputClass\"\r\n :clearable=\"props.clearable\"\r\n :disabled=\"props.disabled || isLoading\"\r\n :model-value=\"innerLabel\"\r\n :placeholder=\"props.placeholder\"\r\n @blur=\"handleBlur\"\r\n @clear=\"handleNativeClear\"\r\n @keydown.enter.prevent=\"handleEnter\"\r\n @update:model-value=\"handleInput\">\r\n <template #suffix>\r\n <span\r\n :class=\"searchTriggerClass\"\r\n aria-label=\"Search\"\r\n role=\"button\"\r\n tabindex=\"-1\"\r\n @click=\"handleManualSearch\"\r\n @mousedown.prevent>\r\n <el-icon :class=\"ns.is('loading', isLoading)\">\r\n <Loading v-if=\"isLoading\" />\r\n <Search v-else />\r\n </el-icon>\r\n </span>\r\n </template>\r\n </el-input>\r\n</template>\r\n\r\n<script lang=\"ts\" setup>\r\nimport { Loading, Search } from '@element-plus/icons-vue'\r\nimport { ElIcon, ElInput } from 'element-plus'\r\nimport { computed, ref, watch } from 'vue'\r\nimport { useNamespace } from '@falcon-ui/utils'\r\nimport type { FlInputSearchMappedResult, FlInputSearchValue } from './input-search'\r\nimport { flInputSearchEmits, flInputSearchProps } from './input-search'\r\n\r\ndefineOptions({\r\n name: 'FlInputSearch',\r\n inheritAttrs: false\r\n})\r\n\r\ntype ElInputExpose = {\r\n blur: () => void\r\n clear: () => void\r\n focus: () => void\r\n}\r\n\r\nconst props = defineProps(flInputSearchProps)\r\nconst emit = defineEmits(flInputSearchEmits)\r\nconst ns = useNamespace('input-search')\r\n\r\nconst inputRef = ref<ElInputExpose | null>(null)\r\nconst innerLabel = ref(props.label)\r\nconst isLoading = ref(false)\r\nconst latestSearchToken = ref(0)\r\nconst lastValidLabel = ref(props.label)\r\nconst lastValidValue = ref<FlInputSearchValue>(props.modelValue)\r\n\r\nconst inputClass = computed(() => [\r\n ns.b(),\r\n {\r\n 'is-error': props.isError,\r\n 'is-table': props.isTable\r\n }\r\n])\r\n\r\nconst searchTriggerClass = ns.e('trigger')\r\n\r\nconst normalizeLabel = (value: unknown): string => (typeof value === 'string' ? value : '')\r\n\r\nconst normalizeValue = (value: unknown): FlInputSearchValue => {\r\n if (value === null || typeof value === 'string' || typeof value === 'number') {\r\n return value\r\n }\r\n\r\n return null\r\n}\r\n\r\nconst syncSnapshot = (value: FlInputSearchValue, label: string) => {\r\n lastValidValue.value = value\r\n lastValidLabel.value = label\r\n}\r\n\r\nconst clearSelection = (reason: 'manual-empty' | 'blur-unconfirmed' | 'error') => {\r\n innerLabel.value = ''\r\n syncSnapshot(null, '')\r\n\r\n emit('update:modelValue', null)\r\n emit('update:label', '')\r\n emit('clear', { reason })\r\n}\r\n\r\nconst commitSelection = (result: FlInputSearchMappedResult) => {\r\n const nextValue = normalizeValue(result.value)\r\n const nextLabel = normalizeLabel(result.label)\r\n\r\n innerLabel.value = nextLabel\r\n syncSnapshot(nextValue, nextLabel)\r\n\r\n emit('update:modelValue', nextValue)\r\n emit('update:label', nextLabel)\r\n emit('selection-commit', {\r\n value: nextValue,\r\n label: nextLabel,\r\n source: 'enter'\r\n })\r\n}\r\n\r\nconst handleInput = (value: string) => {\r\n const nextLabel = normalizeLabel(value)\r\n innerLabel.value = nextLabel\r\n emit('update:label', nextLabel)\r\n}\r\n\r\nconst handleManualSearch = () => {\r\n emit('openDialog', {\r\n keyword: innerLabel.value.trim(),\r\n reason: 'manual'\r\n })\r\n}\r\n\r\nconst handleEnter = async () => {\r\n if (isLoading.value) {\r\n return\r\n }\r\n\r\n const keyword = innerLabel.value.trim()\r\n if (!keyword) {\r\n return\r\n }\r\n\r\n if (!props.fetchApi) {\r\n emit('openDialog', {\r\n keyword,\r\n reason: 'manual'\r\n })\r\n return\r\n }\r\n\r\n const currentToken = latestSearchToken.value + 1\r\n latestSearchToken.value = currentToken\r\n isLoading.value = true\r\n\r\n try {\r\n const response = await props.fetchApi(keyword)\r\n if (currentToken !== latestSearchToken.value) {\r\n return\r\n }\r\n\r\n const results = Array.isArray(response) ? response : []\r\n\r\n if (results.length === 1) {\r\n commitSelection(props.mapResult(results[0]))\r\n return\r\n }\r\n\r\n if (results.length > 1) {\r\n emit('openDialog', {\r\n keyword,\r\n reason: 'multi-match',\r\n results\r\n })\r\n }\r\n } catch (error) {\r\n if (currentToken !== latestSearchToken.value) {\r\n return\r\n }\r\n\r\n emit('search-error', {\r\n keyword,\r\n error\r\n })\r\n } finally {\r\n if (currentToken === latestSearchToken.value) {\r\n isLoading.value = false\r\n }\r\n }\r\n}\r\n\r\nconst handleNativeClear = () => {\r\n clearSelection('manual-empty')\r\n}\r\n\r\nconst handleBlur = () => {\r\n if (isLoading.value) {\r\n return\r\n }\r\n\r\n const currentLabel = innerLabel.value\r\n if (currentLabel === lastValidLabel.value) {\r\n return\r\n }\r\n\r\n if (!currentLabel) {\r\n clearSelection('manual-empty')\r\n return\r\n }\r\n\r\n if (props.clearOnBlurUnconfirmed) {\r\n clearSelection('blur-unconfirmed')\r\n }\r\n}\r\n\r\nconst focus = () => {\r\n inputRef.value?.focus()\r\n}\r\n\r\nconst blur = () => {\r\n inputRef.value?.blur()\r\n}\r\n\r\nconst clear = () => {\r\n inputRef.value?.clear()\r\n}\r\n\r\nwatch(\r\n () => props.label,\r\n (value) => {\r\n innerLabel.value = value\r\n }\r\n)\r\n\r\nwatch(\r\n () => props.modelValue,\r\n (value) => {\r\n if (value === lastValidValue.value) {\r\n return\r\n }\r\n\r\n syncSnapshot(normalizeValue(value), props.label)\r\n }\r\n)\r\n\r\nwatch(\r\n () => props.isError,\r\n (isError, previousIsError) => {\r\n if (isError && previousIsError !== true) {\r\n clearSelection('error')\r\n }\r\n },\r\n { immediate: true }\r\n)\r\n\r\ndefineExpose({\r\n focus,\r\n blur,\r\n clear\r\n})\r\n</script>\r\n","import InputSearch from './src/input-search.vue'\r\nimport { withInstall } from '@falcon-ui/utils'\r\n\r\nexport const FlInputSearch = withInstall(InputSearch)\r\n\r\nexport default FlInputSearch\r\n\r\nexport type {\r\n FlInputSearchClearPayload,\r\n FlInputSearchEmits,\r\n FlInputSearchFetchApi,\r\n FlInputSearchMappedResult,\r\n FlInputSearchMapResult,\r\n FlInputSearchOpenDialogPayload,\r\n FlInputSearchOpenDialogReason,\r\n FlInputSearchProps,\r\n FlInputSearchSearchErrorPayload,\r\n FlInputSearchSelectionCommitPayload,\r\n FlInputSearchValue,\r\n InputSearchEmits,\r\n InputSearchProps\r\n} from './src/input-search'\r\n"],"mappings":"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"}
@@ -0,0 +1,53 @@
1
+ const flInputSearchProps = {
2
+ modelValue: {
3
+ type: [String, Number],
4
+ default: null
5
+ },
6
+ label: {
7
+ type: String,
8
+ default: ""
9
+ },
10
+ fetchApi: {
11
+ type: Function,
12
+ default: void 0
13
+ },
14
+ mapResult: {
15
+ type: Function,
16
+ required: true
17
+ },
18
+ placeholder: {
19
+ type: String,
20
+ default: ""
21
+ },
22
+ disabled: {
23
+ type: Boolean,
24
+ default: false
25
+ },
26
+ clearable: {
27
+ type: Boolean,
28
+ default: false
29
+ },
30
+ isError: {
31
+ type: Boolean,
32
+ default: false
33
+ },
34
+ isTable: {
35
+ type: Boolean,
36
+ default: false
37
+ },
38
+ clearOnBlurUnconfirmed: {
39
+ type: Boolean,
40
+ default: true
41
+ }
42
+ };
43
+ const flInputSearchEmits = {
44
+ "update:modelValue": (value) => value === null || typeof value === "string" || typeof value === "number",
45
+ "update:label": (value) => typeof value === "string",
46
+ openDialog: (payload) => typeof payload.keyword === "string" && (payload.reason === "manual" || payload.reason === "multi-match") && (payload.results === void 0 || Array.isArray(payload.results)),
47
+ "selection-commit": (payload) => typeof payload.label === "string" && payload.source === "enter" && (payload.value === null || typeof payload.value === "string" || typeof payload.value === "number"),
48
+ "search-error": (payload) => typeof payload.keyword === "string",
49
+ clear: (payload) => payload.reason === "manual-empty" || payload.reason === "blur-unconfirmed" || payload.reason === "error"
50
+ };
51
+ export { flInputSearchEmits, flInputSearchProps };
52
+
53
+ //# sourceMappingURL=input-search.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"input-search.mjs","names":[],"sources":["../../../../../../packages/components/input-search/src/input-search.ts"],"sourcesContent":["import type { ExtractPublicPropTypes, PropType } from 'vue'\r\n\r\nexport type FlInputSearchValue = string | number | null\r\n\r\nexport interface FlInputSearchMappedResult {\r\n label: string\r\n value: FlInputSearchValue\r\n}\r\n\r\nexport type FlInputSearchFetchApi = (keyword: string) => Promise<unknown[]>\r\nexport type FlInputSearchMapResult = (item: unknown) => FlInputSearchMappedResult\r\n\r\nexport const flInputSearchProps = {\r\n /**\r\n * 绑定值,通常为业务实体 ID。\r\n */\r\n modelValue: {\r\n type: [String, Number] as PropType<string | number | null>,\r\n default: null\r\n },\r\n /**\r\n * 输入框显示值(业务标签)。\r\n */\r\n label: {\r\n type: String,\r\n default: ''\r\n },\r\n /**\r\n * 回车检索方法。\r\n */\r\n fetchApi: {\r\n type: Function as PropType<FlInputSearchFetchApi>,\r\n default: undefined\r\n },\r\n /**\r\n * 外部结果映射方法,统一映射到 value/label。\r\n */\r\n mapResult: {\r\n type: Function as PropType<FlInputSearchMapResult>,\r\n required: true\r\n },\r\n /**\r\n * 占位提示文案。\r\n */\r\n placeholder: {\r\n type: String,\r\n default: ''\r\n },\r\n /**\r\n * 是否禁用输入。\r\n */\r\n disabled: {\r\n type: Boolean,\r\n default: false\r\n },\r\n /**\r\n * 是否显示清空按钮。\r\n */\r\n clearable: {\r\n type: Boolean,\r\n default: false\r\n },\r\n /**\r\n * 是否进入错误态。\r\n */\r\n isError: {\r\n type: Boolean,\r\n default: false\r\n },\r\n /**\r\n * 是否用于表格单元格输入。\r\n */\r\n isTable: {\r\n type: Boolean,\r\n default: false\r\n },\r\n /**\r\n * Blur 时未确认输入是否强制清空。\r\n */\r\n clearOnBlurUnconfirmed: {\r\n type: Boolean,\r\n default: true\r\n }\r\n} as const\r\n\r\nexport type FlInputSearchOpenDialogReason = 'manual' | 'multi-match'\r\n\r\nexport interface FlInputSearchOpenDialogPayload {\r\n keyword: string\r\n reason: FlInputSearchOpenDialogReason\r\n results?: unknown[]\r\n}\r\n\r\nexport interface FlInputSearchSelectionCommitPayload {\r\n label: string\r\n source: 'enter'\r\n value: FlInputSearchValue\r\n}\r\n\r\nexport interface FlInputSearchSearchErrorPayload {\r\n error: unknown\r\n keyword: string\r\n}\r\n\r\nexport interface FlInputSearchClearPayload {\r\n reason: 'manual-empty' | 'blur-unconfirmed' | 'error'\r\n}\r\n\r\nexport const flInputSearchEmits = {\r\n /**\r\n * 绑定值更新事件。\r\n */\r\n 'update:modelValue': (value: FlInputSearchValue) =>\r\n value === null || typeof value === 'string' || typeof value === 'number',\r\n /**\r\n * 显示值更新事件。\r\n */\r\n 'update:label': (value: string) => typeof value === 'string',\r\n /**\r\n * 触发外部弹窗占位事件。\r\n */\r\n openDialog: (payload: FlInputSearchOpenDialogPayload) =>\r\n typeof payload.keyword === 'string' &&\r\n (payload.reason === 'manual' || payload.reason === 'multi-match') &&\r\n (payload.results === undefined || Array.isArray(payload.results)),\r\n /**\r\n * 唯一结果选中提交事件。\r\n */\r\n 'selection-commit': (payload: FlInputSearchSelectionCommitPayload) =>\r\n typeof payload.label === 'string' &&\r\n payload.source === 'enter' &&\r\n (payload.value === null ||\r\n typeof payload.value === 'string' ||\r\n typeof payload.value === 'number'),\r\n /**\r\n * 回车检索失败事件。\r\n */\r\n 'search-error': (payload: FlInputSearchSearchErrorPayload) => typeof payload.keyword === 'string',\r\n /**\r\n * 清空行为事件。\r\n */\r\n clear: (payload: FlInputSearchClearPayload) =>\r\n payload.reason === 'manual-empty' ||\r\n payload.reason === 'blur-unconfirmed' ||\r\n payload.reason === 'error'\r\n} as const\r\n\r\nexport type FlInputSearchProps = ExtractPublicPropTypes<typeof flInputSearchProps>\r\nexport type FlInputSearchEmits = typeof flInputSearchEmits\r\n\r\nexport type InputSearchProps = FlInputSearchProps\r\nexport type InputSearchEmits = FlInputSearchEmits\r\n"],"mappings":"AAYA,MAAa,qBAAqB;CAIhC,YAAY;EACV,MAAM,CAAC,QAAQ,OAAO;EACtB,SAAS;EACV;CAID,OAAO;EACL,MAAM;EACN,SAAS;EACV;CAID,UAAU;EACR,MAAM;EACN,SAAS,KAAA;EACV;CAID,WAAW;EACT,MAAM;EACN,UAAU;EACX;CAID,aAAa;EACX,MAAM;EACN,SAAS;EACV;CAID,UAAU;EACR,MAAM;EACN,SAAS;EACV;CAID,WAAW;EACT,MAAM;EACN,SAAS;EACV;CAID,SAAS;EACP,MAAM;EACN,SAAS;EACV;CAID,SAAS;EACP,MAAM;EACN,SAAS;EACV;CAID,wBAAwB;EACtB,MAAM;EACN,SAAS;EACV;CACF;AAyBD,MAAa,qBAAqB;CAIhC,sBAAsB,UACpB,UAAU,QAAQ,OAAO,UAAU,YAAY,OAAO,UAAU;CAIlE,iBAAiB,UAAkB,OAAO,UAAU;CAIpD,aAAa,YACX,OAAO,QAAQ,YAAY,aAC1B,QAAQ,WAAW,YAAY,QAAQ,WAAW,mBAClD,QAAQ,YAAY,KAAA,KAAa,MAAM,QAAQ,QAAQ,QAAQ;CAIlE,qBAAqB,YACnB,OAAO,QAAQ,UAAU,YACzB,QAAQ,WAAW,YAClB,QAAQ,UAAU,QACjB,OAAO,QAAQ,UAAU,YACzB,OAAO,QAAQ,UAAU;CAI7B,iBAAiB,YAA6C,OAAO,QAAQ,YAAY;CAIzF,QAAQ,YACN,QAAQ,WAAW,kBACnB,QAAQ,WAAW,sBACnB,QAAQ,WAAW;CACtB"}
@@ -0,0 +1,268 @@
1
+ import { computed, createBlock, createElementVNode, createVNode, defineComponent, normalizeClass, openBlock, ref, unref, watch, withCtx, withKeys, withModifiers } from "vue";
2
+ import { Loading, Search } from "@element-plus/icons-vue";
3
+ import { ElIcon, ElInput } from "element-plus";
4
+ var defaultNamespace = "fl";
5
+ var statePrefix = "is-";
6
+ var buildBemName = (namespace, block, blockSuffix = "", element = "", modifier = "") => {
7
+ let className = `${namespace}-${block}`;
8
+ if (blockSuffix) className += `-${blockSuffix}`;
9
+ if (element) className += `__${element}`;
10
+ if (modifier) className += `--${modifier}`;
11
+ return className;
12
+ };
13
+ const useNamespace = (block, namespace = defaultNamespace) => {
14
+ const b = (blockSuffix = "") => buildBemName(namespace, block, blockSuffix);
15
+ const e = (element) => element ? buildBemName(namespace, block, "", element) : "";
16
+ const m = (modifier) => modifier ? buildBemName(namespace, block, "", "", modifier) : "";
17
+ const be = (blockSuffix, element) => {
18
+ if (!blockSuffix || !element) return "";
19
+ return buildBemName(namespace, block, blockSuffix, element);
20
+ };
21
+ const em = (element, modifier) => {
22
+ if (!element || !modifier) return "";
23
+ return buildBemName(namespace, block, "", element, modifier);
24
+ };
25
+ const bm = (blockSuffix, modifier) => {
26
+ if (!blockSuffix || !modifier) return "";
27
+ return buildBemName(namespace, block, blockSuffix, "", modifier);
28
+ };
29
+ const bem = (blockSuffix, element, modifier) => {
30
+ if (!blockSuffix && !element && !modifier) return b();
31
+ return buildBemName(namespace, block, blockSuffix, element, modifier);
32
+ };
33
+ const is = (name, state = true) => state ? `${statePrefix}${name}` : "";
34
+ return {
35
+ namespace,
36
+ b,
37
+ e,
38
+ m,
39
+ be,
40
+ em,
41
+ bm,
42
+ bem,
43
+ is
44
+ };
45
+ };
46
+ var input_search_default = /* @__PURE__ */ defineComponent({
47
+ name: "FlInputSearch",
48
+ inheritAttrs: false,
49
+ __name: "input-search",
50
+ props: {
51
+ modelValue: {
52
+ type: [String, Number],
53
+ default: null
54
+ },
55
+ label: {
56
+ type: String,
57
+ default: ""
58
+ },
59
+ fetchApi: {
60
+ type: Function,
61
+ default: void 0
62
+ },
63
+ mapResult: {
64
+ type: Function,
65
+ required: true
66
+ },
67
+ placeholder: {
68
+ type: String,
69
+ default: ""
70
+ },
71
+ disabled: {
72
+ type: Boolean,
73
+ default: false
74
+ },
75
+ clearable: {
76
+ type: Boolean,
77
+ default: false
78
+ },
79
+ isError: {
80
+ type: Boolean,
81
+ default: false
82
+ },
83
+ isTable: {
84
+ type: Boolean,
85
+ default: false
86
+ },
87
+ clearOnBlurUnconfirmed: {
88
+ type: Boolean,
89
+ default: true
90
+ }
91
+ },
92
+ emits: {
93
+ "update:modelValue": (value) => value === null || typeof value === "string" || typeof value === "number",
94
+ "update:label": (value) => typeof value === "string",
95
+ openDialog: (payload) => typeof payload.keyword === "string" && (payload.reason === "manual" || payload.reason === "multi-match") && (payload.results === void 0 || Array.isArray(payload.results)),
96
+ "selection-commit": (payload) => typeof payload.label === "string" && payload.source === "enter" && (payload.value === null || typeof payload.value === "string" || typeof payload.value === "number"),
97
+ "search-error": (payload) => typeof payload.keyword === "string",
98
+ clear: (payload) => payload.reason === "manual-empty" || payload.reason === "blur-unconfirmed" || payload.reason === "error"
99
+ },
100
+ setup(__props, { expose: __expose, emit: __emit }) {
101
+ const props = __props;
102
+ const emit = __emit;
103
+ const ns = useNamespace("input-search");
104
+ const inputRef = ref(null);
105
+ const innerLabel = ref(props.label);
106
+ const isLoading = ref(false);
107
+ const latestSearchToken = ref(0);
108
+ const lastValidLabel = ref(props.label);
109
+ const lastValidValue = ref(props.modelValue);
110
+ const inputClass = computed(() => [ns.b(), {
111
+ "is-error": props.isError,
112
+ "is-table": props.isTable
113
+ }]);
114
+ const searchTriggerClass = ns.e("trigger");
115
+ const normalizeLabel = (value) => typeof value === "string" ? value : "";
116
+ const normalizeValue = (value) => {
117
+ if (value === null || typeof value === "string" || typeof value === "number") return value;
118
+ return null;
119
+ };
120
+ const syncSnapshot = (value, label) => {
121
+ lastValidValue.value = value;
122
+ lastValidLabel.value = label;
123
+ };
124
+ const clearSelection = (reason) => {
125
+ innerLabel.value = "";
126
+ syncSnapshot(null, "");
127
+ emit("update:modelValue", null);
128
+ emit("update:label", "");
129
+ emit("clear", { reason });
130
+ };
131
+ const commitSelection = (result) => {
132
+ const nextValue = normalizeValue(result.value);
133
+ const nextLabel = normalizeLabel(result.label);
134
+ innerLabel.value = nextLabel;
135
+ syncSnapshot(nextValue, nextLabel);
136
+ emit("update:modelValue", nextValue);
137
+ emit("update:label", nextLabel);
138
+ emit("selection-commit", {
139
+ value: nextValue,
140
+ label: nextLabel,
141
+ source: "enter"
142
+ });
143
+ };
144
+ const handleInput = (value) => {
145
+ const nextLabel = normalizeLabel(value);
146
+ innerLabel.value = nextLabel;
147
+ emit("update:label", nextLabel);
148
+ };
149
+ const handleManualSearch = () => {
150
+ emit("openDialog", {
151
+ keyword: innerLabel.value.trim(),
152
+ reason: "manual"
153
+ });
154
+ };
155
+ const handleEnter = async () => {
156
+ if (isLoading.value) return;
157
+ const keyword = innerLabel.value.trim();
158
+ if (!keyword) return;
159
+ if (!props.fetchApi) {
160
+ emit("openDialog", {
161
+ keyword,
162
+ reason: "manual"
163
+ });
164
+ return;
165
+ }
166
+ const currentToken = latestSearchToken.value + 1;
167
+ latestSearchToken.value = currentToken;
168
+ isLoading.value = true;
169
+ try {
170
+ const response = await props.fetchApi(keyword);
171
+ if (currentToken !== latestSearchToken.value) return;
172
+ const results = Array.isArray(response) ? response : [];
173
+ if (results.length === 1) {
174
+ commitSelection(props.mapResult(results[0]));
175
+ return;
176
+ }
177
+ if (results.length > 1) emit("openDialog", {
178
+ keyword,
179
+ reason: "multi-match",
180
+ results
181
+ });
182
+ } catch (error) {
183
+ if (currentToken !== latestSearchToken.value) return;
184
+ emit("search-error", {
185
+ keyword,
186
+ error
187
+ });
188
+ } finally {
189
+ if (currentToken === latestSearchToken.value) isLoading.value = false;
190
+ }
191
+ };
192
+ const handleNativeClear = () => {
193
+ clearSelection("manual-empty");
194
+ };
195
+ const handleBlur = () => {
196
+ if (isLoading.value) return;
197
+ const currentLabel = innerLabel.value;
198
+ if (currentLabel === lastValidLabel.value) return;
199
+ if (!currentLabel) {
200
+ clearSelection("manual-empty");
201
+ return;
202
+ }
203
+ if (props.clearOnBlurUnconfirmed) clearSelection("blur-unconfirmed");
204
+ };
205
+ const focus = () => {
206
+ inputRef.value?.focus();
207
+ };
208
+ const blur = () => {
209
+ inputRef.value?.blur();
210
+ };
211
+ const clear = () => {
212
+ inputRef.value?.clear();
213
+ };
214
+ watch(() => props.label, (value) => {
215
+ innerLabel.value = value;
216
+ });
217
+ watch(() => props.modelValue, (value) => {
218
+ if (value === lastValidValue.value) return;
219
+ syncSnapshot(normalizeValue(value), props.label);
220
+ });
221
+ watch(() => props.isError, (isError, previousIsError) => {
222
+ if (isError && previousIsError !== true) clearSelection("error");
223
+ }, { immediate: true });
224
+ __expose({
225
+ focus,
226
+ blur,
227
+ clear
228
+ });
229
+ return (_ctx, _cache) => {
230
+ return openBlock(), createBlock(unref(ElInput), {
231
+ ref_key: "inputRef",
232
+ ref: inputRef,
233
+ class: normalizeClass(inputClass.value),
234
+ clearable: props.clearable,
235
+ disabled: props.disabled || isLoading.value,
236
+ "model-value": innerLabel.value,
237
+ placeholder: props.placeholder,
238
+ onBlur: handleBlur,
239
+ onClear: handleNativeClear,
240
+ onKeydown: withKeys(withModifiers(handleEnter, ["prevent"]), ["enter"]),
241
+ "onUpdate:modelValue": handleInput
242
+ }, {
243
+ suffix: withCtx(() => [createElementVNode("span", {
244
+ class: normalizeClass(unref(searchTriggerClass)),
245
+ "aria-label": "Search",
246
+ role: "button",
247
+ tabindex: "-1",
248
+ onClick: handleManualSearch,
249
+ onMousedown: _cache[0] || (_cache[0] = withModifiers(() => {}, ["prevent"]))
250
+ }, [createVNode(unref(ElIcon), { class: normalizeClass(unref(ns).is("loading", isLoading.value)) }, {
251
+ default: withCtx(() => [isLoading.value ? (openBlock(), createBlock(unref(Loading), { key: 0 })) : (openBlock(), createBlock(unref(Search), { key: 1 }))]),
252
+ _: 1
253
+ }, 8, ["class"])], 34)]),
254
+ _: 1
255
+ }, 8, [
256
+ "class",
257
+ "clearable",
258
+ "disabled",
259
+ "model-value",
260
+ "placeholder",
261
+ "onKeydown"
262
+ ]);
263
+ };
264
+ }
265
+ });
266
+ export { input_search_default as default };
267
+
268
+ //# sourceMappingURL=input-search.vue.mjs.map