@customafk/lunas-ui 0.2.82 → 0.2.84

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 (410) hide show
  1. package/dist/action-submit-BHY2dndL.mjs +2 -0
  2. package/dist/{action-submit-DVNxnW4-.mjs.map → action-submit-BHY2dndL.mjs.map} +1 -1
  3. package/dist/action-submit-tpgKvZ47.cjs +2 -0
  4. package/dist/{action-submit-kYjq-iPD.cjs.map → action-submit-tpgKvZ47.cjs.map} +1 -1
  5. package/dist/actions-form-PByL8_M5.mjs +2 -0
  6. package/dist/{actions-form-DRrkiGzh.mjs.map → actions-form-PByL8_M5.mjs.map} +1 -1
  7. package/dist/actions-form-X46W7FVa.cjs +2 -0
  8. package/dist/{actions-form-CwicJU89.cjs.map → actions-form-X46W7FVa.cjs.map} +1 -1
  9. package/dist/{analysis-panel-BoKjkPYz.cjs → analysis-panel-B4ynYuwg.cjs} +2 -2
  10. package/dist/{analysis-panel-BoKjkPYz.cjs.map → analysis-panel-B4ynYuwg.cjs.map} +1 -1
  11. package/dist/{analysis-panel-CZ8g9AAO.mjs → analysis-panel-CcM3tBcc.mjs} +2 -2
  12. package/dist/{analysis-panel-CZ8g9AAO.mjs.map → analysis-panel-CcM3tBcc.mjs.map} +1 -1
  13. package/dist/{badge-BPiU1Ss2.d.cts → badge-C_NPjGXe.d.cts} +9 -2
  14. package/dist/{badge-BPiU1Ss2.d.mts → badge-C_NPjGXe.d.mts} +9 -2
  15. package/dist/{badge-display-DHbCN998.cjs → badge-display-C1_Fc3Sj.cjs} +2 -2
  16. package/dist/{badge-display-DHbCN998.cjs.map → badge-display-C1_Fc3Sj.cjs.map} +1 -1
  17. package/dist/{badge-display-B5m09_Hs.mjs → badge-display-DRmVhZ-C.mjs} +2 -2
  18. package/dist/{badge-display-B5m09_Hs.mjs.map → badge-display-DRmVhZ-C.mjs.map} +1 -1
  19. package/dist/{boolean-display-CzHHDfHW.mjs → boolean-display-ByTs3aOa.mjs} +2 -2
  20. package/dist/{boolean-display-CzHHDfHW.mjs.map → boolean-display-ByTs3aOa.mjs.map} +1 -1
  21. package/dist/{boolean-display-D2wjQhNX.cjs → boolean-display-DUA-6Q13.cjs} +2 -2
  22. package/dist/{boolean-display-D2wjQhNX.cjs.map → boolean-display-DUA-6Q13.cjs.map} +1 -1
  23. package/dist/{button-BnoPktln.d.cts → button-BGW-LZ3i.d.cts} +2 -2
  24. package/dist/{button-BnoPktln.d.mts → button-BGW-LZ3i.d.mts} +2 -2
  25. package/dist/{calendar-BkV5hTX2.d.mts → calendar-BNTvKnwd.d.cts} +2 -2
  26. package/dist/{calendar-iDMPT1kI.d.cts → calendar-DbaIaWr0.d.mts} +2 -2
  27. package/dist/{carousel-D7VXWJ3S.d.mts → carousel-Bw-VhPR3.d.mts} +2 -2
  28. package/dist/{carousel-bBvM31sh.d.cts → carousel-DRqMTyKS.d.cts} +2 -2
  29. package/dist/checkbox-field-BG35eKvM.cjs +2 -0
  30. package/dist/{checkbox-field-DBUjQC_4.cjs.map → checkbox-field-BG35eKvM.cjs.map} +1 -1
  31. package/dist/checkbox-field-C-NyMjEm.mjs +2 -0
  32. package/dist/{checkbox-field-BN3Vd9qq.mjs.map → checkbox-field-C-NyMjEm.mjs.map} +1 -1
  33. package/dist/{cms-layout-Ba_5wSnr.mjs → cms-layout-BHLo0_L_.mjs} +2 -2
  34. package/dist/{cms-layout-Ba_5wSnr.mjs.map → cms-layout-BHLo0_L_.mjs.map} +1 -1
  35. package/dist/{cms-layout-DCJhB-GY.cjs → cms-layout-DYEmSqzx.cjs} +2 -2
  36. package/dist/{cms-layout-DCJhB-GY.cjs.map → cms-layout-DYEmSqzx.cjs.map} +1 -1
  37. package/dist/combobox-Bhgo112r.cjs +2 -0
  38. package/dist/{combobox-kp_kPY8o.cjs.map → combobox-Bhgo112r.cjs.map} +1 -1
  39. package/dist/combobox-C0nno01T.mjs +2 -0
  40. package/dist/{combobox-C64Rvd7n.mjs.map → combobox-C0nno01T.mjs.map} +1 -1
  41. package/dist/combobox-field-Cx0A-CD4.mjs +2 -0
  42. package/dist/{combobox-field-Bug1qI5B.mjs.map → combobox-field-Cx0A-CD4.mjs.map} +1 -1
  43. package/dist/combobox-field-ROYquFD8.cjs +2 -0
  44. package/dist/{combobox-field-BE9miJ3D.cjs.map → combobox-field-ROYquFD8.cjs.map} +1 -1
  45. package/dist/{currency-display-B06kc2IG.cjs → currency-display-DefLJLqL.cjs} +2 -2
  46. package/dist/{currency-display-B06kc2IG.cjs.map → currency-display-DefLJLqL.cjs.map} +1 -1
  47. package/dist/{currency-display-7w-ZjVUw.mjs → currency-display-DpbtUluj.mjs} +2 -2
  48. package/dist/{currency-display-7w-ZjVUw.mjs.map → currency-display-DpbtUluj.mjs.map} +1 -1
  49. package/dist/data-display/country.cjs +1 -1
  50. package/dist/data-display/phone-number.cjs +1 -1
  51. package/dist/data-display/phone-number.cjs.map +1 -1
  52. package/dist/data-display/phone-number.d.cts +1 -1
  53. package/dist/data-display/phone-number.d.mts +1 -1
  54. package/dist/data-display/phone-number.mjs +1 -1
  55. package/dist/data-display/phone-number.mjs.map +1 -1
  56. package/dist/{date-display-BO7OY_AC.mjs → date-display-ByvkuSk0.mjs} +2 -2
  57. package/dist/{date-display-BO7OY_AC.mjs.map → date-display-ByvkuSk0.mjs.map} +1 -1
  58. package/dist/{date-display-DHnZr_yf.cjs → date-display-CkPBLlWz.cjs} +2 -2
  59. package/dist/{date-display-DHnZr_yf.cjs.map → date-display-CkPBLlWz.cjs.map} +1 -1
  60. package/dist/date-field-46UtGmEV.cjs +2 -0
  61. package/dist/{date-field-CYoPe74G.cjs.map → date-field-46UtGmEV.cjs.map} +1 -1
  62. package/dist/date-field-zoPch5tC.mjs +2 -0
  63. package/dist/{date-field-D_qpBb-t.mjs.map → date-field-zoPch5tC.mjs.map} +1 -1
  64. package/dist/{description-display-CBfoP3Y2.mjs → description-display-BFTBwDmB.mjs} +2 -2
  65. package/dist/{description-display-CBfoP3Y2.mjs.map → description-display-BFTBwDmB.mjs.map} +1 -1
  66. package/dist/{description-display-Cckihd1s.cjs → description-display-DeEwppdC.cjs} +2 -2
  67. package/dist/{description-display-Cckihd1s.cjs.map → description-display-DeEwppdC.cjs.map} +1 -1
  68. package/dist/descriptions-Bw9GSCjo.mjs +3 -0
  69. package/dist/descriptions-Bw9GSCjo.mjs.map +1 -0
  70. package/dist/descriptions-DUsJjqd2.cjs +3 -0
  71. package/dist/descriptions-DUsJjqd2.cjs.map +1 -0
  72. package/dist/dialog-form-BRV1niqF.mjs +2 -0
  73. package/dist/{dialog-form-CCIcht28.mjs.map → dialog-form-BRV1niqF.mjs.map} +1 -1
  74. package/dist/dialog-form-X9MxC8pq.cjs +2 -0
  75. package/dist/{dialog-form-BTZZwz3T.cjs.map → dialog-form-X9MxC8pq.cjs.map} +1 -1
  76. package/dist/dialogs/detail-dialog/components/sidebar.d.cts +1 -1
  77. package/dist/dialogs/detail-dialog/components/sidebar.d.mts +1 -1
  78. package/dist/{dist-DzA--RwW.cjs → dist-CIdWHwhj.cjs} +2 -2
  79. package/dist/{dist-DzA--RwW.cjs.map → dist-CIdWHwhj.cjs.map} +1 -1
  80. package/dist/{email-display-w-hRYIeL.cjs → email-display-BXw4IbbW.cjs} +2 -2
  81. package/dist/{email-display-w-hRYIeL.cjs.map → email-display-BXw4IbbW.cjs.map} +1 -1
  82. package/dist/{email-display-Bk_furIx.mjs → email-display-qxdrnYmK.mjs} +2 -2
  83. package/dist/{email-display-Bk_furIx.mjs.map → email-display-qxdrnYmK.mjs.map} +1 -1
  84. package/dist/email-field-0UjeYtnM.cjs +2 -0
  85. package/dist/{email-field-DJa7iASY.cjs.map → email-field-0UjeYtnM.cjs.map} +1 -1
  86. package/dist/email-field-CPEVNvn8.mjs +2 -0
  87. package/dist/{email-field-DxSNJ6tf.mjs.map → email-field-CPEVNvn8.mjs.map} +1 -1
  88. package/dist/features/descriptions/index.cjs +1 -2
  89. package/dist/features/descriptions/index.d.cts +2 -2
  90. package/dist/features/descriptions/index.d.mts +2 -2
  91. package/dist/features/descriptions/index.mjs +1 -2
  92. package/dist/features/tables/index.cjs +1 -1
  93. package/dist/features/tables/index.d.cts +1 -1
  94. package/dist/features/tables/index.d.mts +1 -1
  95. package/dist/features/tables/index.mjs +1 -1
  96. package/dist/features/tanstack-form/index.cjs +1 -1
  97. package/dist/features/tanstack-form/index.d.cts +1 -1
  98. package/dist/features/tanstack-form/index.d.mts +1 -1
  99. package/dist/features/tanstack-form/index.mjs +1 -1
  100. package/dist/features/text-editor/index.cjs +1 -1
  101. package/dist/features/text-editor/index.d.cts +1 -1
  102. package/dist/features/text-editor/index.d.mts +1 -1
  103. package/dist/features/text-editor/index.mjs +1 -1
  104. package/dist/{filter-BO7ISTIR.mjs → filter-DM4QLW77.mjs} +2 -2
  105. package/dist/{filter-BO7ISTIR.mjs.map → filter-DM4QLW77.mjs.map} +1 -1
  106. package/dist/{filter-CQ9BD0MV.cjs → filter-DQEjSnOP.cjs} +2 -2
  107. package/dist/{filter-CQ9BD0MV.cjs.map → filter-DQEjSnOP.cjs.map} +1 -1
  108. package/dist/{flex-CrxTaAXE.d.cts → flex-D7IE_cdR.d.cts} +8 -6
  109. package/dist/{flex-CrxTaAXE.d.mts → flex-D7IE_cdR.d.mts} +8 -6
  110. package/dist/group-field-Cs0uWHg0.mjs +2 -0
  111. package/dist/{group-field-gejvx_Td.mjs.map → group-field-Cs0uWHg0.mjs.map} +1 -1
  112. package/dist/group-field-DJXL9sRy.cjs +2 -0
  113. package/dist/{group-field-sVykO2JZ.cjs.map → group-field-DJXL9sRy.cjs.map} +1 -1
  114. package/dist/{index-DvC1inRy.d.cts → index-0HuXxgjQ.d.cts} +13 -10
  115. package/dist/{index-DvC1inRy.d.mts → index-CZ_2KVir.d.mts} +13 -10
  116. package/dist/index-Cp4Db57w.d.cts +598 -0
  117. package/dist/index-CqE3mOHo.d.mts +598 -0
  118. package/dist/{index-DRAyYm8g.d.cts → index-CvFEJoon.d.cts} +12 -3
  119. package/dist/{index-DRAyYm8g.d.mts → index-CvFEJoon.d.mts} +12 -3
  120. package/dist/{index-BPo-Lg3p.d.mts → index-DJY2uC2H.d.mts} +14 -14
  121. package/dist/{index-DaLpXe5l.d.cts → index-UZik7mgS.d.cts} +14 -14
  122. package/dist/index.cjs +1 -1
  123. package/dist/index.d.cts +17 -17
  124. package/dist/index.d.mts +17 -17
  125. package/dist/index.mjs +1 -1
  126. package/dist/{input-DxNK7Wo6.d.cts → input-D73TrUof.d.cts} +2 -2
  127. package/dist/{input-DxNK7Wo6.d.mts → input-D73TrUof.d.mts} +2 -2
  128. package/dist/layouts/cms-layout/index.cjs +1 -1
  129. package/dist/layouts/cms-layout/index.mjs +1 -1
  130. package/dist/layouts/flex.cjs +1 -1
  131. package/dist/layouts/flex.cjs.map +1 -1
  132. package/dist/layouts/flex.d.cts +1 -1
  133. package/dist/layouts/flex.d.mts +1 -1
  134. package/dist/layouts/flex.mjs +1 -1
  135. package/dist/layouts/flex.mjs.map +1 -1
  136. package/dist/layouts/payment-layout/index.cjs +1 -1
  137. package/dist/layouts/payment-layout/index.mjs +1 -1
  138. package/dist/layouts/ui-grid.cjs +1 -1
  139. package/dist/layouts/ui-grid.cjs.map +1 -1
  140. package/dist/layouts/ui-grid.d.cts +1 -1
  141. package/dist/layouts/ui-grid.d.mts +1 -1
  142. package/dist/layouts/ui-grid.mjs +1 -1
  143. package/dist/layouts/ui-grid.mjs.map +1 -1
  144. package/dist/{list-display-DLsm8uAh.mjs → list-display-4tTkV29U.mjs} +2 -2
  145. package/dist/{list-display-DLsm8uAh.mjs.map → list-display-4tTkV29U.mjs.map} +1 -1
  146. package/dist/{list-display-DDeJoneW.cjs → list-display-CJvQ-wwT.cjs} +2 -2
  147. package/dist/{list-display-DDeJoneW.cjs.map → list-display-CJvQ-wwT.cjs.map} +1 -1
  148. package/dist/{name-display-H5HFH1fU.mjs → name-display-BFoDcvt2.mjs} +2 -2
  149. package/dist/{name-display-H5HFH1fU.mjs.map → name-display-BFoDcvt2.mjs.map} +1 -1
  150. package/dist/{name-display-CKnyugrP.cjs → name-display-Br7rcdqi.cjs} +2 -2
  151. package/dist/{name-display-CKnyugrP.cjs.map → name-display-Br7rcdqi.cjs.map} +1 -1
  152. package/dist/number-field-CMskIrWP.cjs +2 -0
  153. package/dist/{number-field-DKZz-27X.cjs.map → number-field-CMskIrWP.cjs.map} +1 -1
  154. package/dist/number-field-DSGwWg7y.mjs +2 -0
  155. package/dist/{number-field-5INgdUUv.mjs.map → number-field-DSGwWg7y.mjs.map} +1 -1
  156. package/dist/{pagination-BRw-yZBY.d.cts → pagination-DDcO-TPf.d.cts} +2 -2
  157. package/dist/{pagination-BlLiOvY9.d.mts → pagination-DWg3Xv34.d.mts} +2 -2
  158. package/dist/{paragraph-CRo5eC7H.d.mts → paragraph--8GcgnQL.d.cts} +3 -3
  159. package/dist/{paragraph-CkCNIsvz.d.cts → paragraph-BOa0VlGX.d.mts} +3 -3
  160. package/dist/password-field-BxJqTPhN.cjs +2 -0
  161. package/dist/{password-field-BuWARi35.cjs.map → password-field-BxJqTPhN.cjs.map} +1 -1
  162. package/dist/password-field-DsmwNZep.mjs +2 -0
  163. package/dist/{password-field-DOIe6wTv.mjs.map → password-field-DsmwNZep.mjs.map} +1 -1
  164. package/dist/{payment-layout-BSl9DYQA.mjs → payment-layout--b7bhmR1.mjs} +2 -2
  165. package/dist/{payment-layout-BSl9DYQA.mjs.map → payment-layout--b7bhmR1.mjs.map} +1 -1
  166. package/dist/payment-layout-C38xIc2X.cjs +2 -0
  167. package/dist/{payment-layout-DDcLanA0.cjs.map → payment-layout-C38xIc2X.cjs.map} +1 -1
  168. package/dist/{permalink-CaCx9fi6.mjs → permalink-BPCF_npZ.mjs} +2 -2
  169. package/dist/{permalink-CaCx9fi6.mjs.map → permalink-BPCF_npZ.mjs.map} +1 -1
  170. package/dist/{permalink-azuGQg2b.cjs → permalink-DCvWlrAT.cjs} +2 -2
  171. package/dist/{permalink-azuGQg2b.cjs.map → permalink-DCvWlrAT.cjs.map} +1 -1
  172. package/dist/phone-CTTjc3mv.mjs +2 -0
  173. package/dist/phone-CTTjc3mv.mjs.map +1 -0
  174. package/dist/phone-CUxXVTg6.cjs +2 -0
  175. package/dist/phone-CUxXVTg6.cjs.map +1 -0
  176. package/dist/{phone-number-D9j5xYDW.d.cts → phone-number-B1bLIt8i.d.cts} +3 -3
  177. package/dist/{phone-number-D9j5xYDW.d.mts → phone-number-B1bLIt8i.d.mts} +3 -3
  178. package/dist/{phone-number-Ba-f4s1Y.mjs → phone-number-DHFLnHWO.mjs} +2 -2
  179. package/dist/{phone-number-Ba-f4s1Y.mjs.map → phone-number-DHFLnHWO.mjs.map} +1 -1
  180. package/dist/{phone-number-BqRhKQdr.cjs → phone-number-YzmDmFBU.cjs} +2 -2
  181. package/dist/{phone-number-BqRhKQdr.cjs.map → phone-number-YzmDmFBU.cjs.map} +1 -1
  182. package/dist/popover-form-BUc5ivCF.mjs +2 -0
  183. package/dist/{popover-form-BsapHJck.mjs.map → popover-form-BUc5ivCF.mjs.map} +1 -1
  184. package/dist/popover-form-CdXVFl0t.cjs +2 -0
  185. package/dist/{popover-form-Bq2GcuZu.cjs.map → popover-form-CdXVFl0t.cjs.map} +1 -1
  186. package/dist/{progress-display-CiYWPOnq.cjs → progress-display-57LT7U37.cjs} +2 -2
  187. package/dist/{progress-display-CiYWPOnq.cjs.map → progress-display-57LT7U37.cjs.map} +1 -1
  188. package/dist/{progress-display-0UsBzt_r.mjs → progress-display-AfoHitiE.mjs} +2 -2
  189. package/dist/{progress-display-0UsBzt_r.mjs.map → progress-display-AfoHitiE.mjs.map} +1 -1
  190. package/dist/radio-group-field-CmCo87tm.mjs +2 -0
  191. package/dist/{radio-group-field-DOJ4jVSr.mjs.map → radio-group-field-CmCo87tm.mjs.map} +1 -1
  192. package/dist/radio-group-field-gHNAwrdr.cjs +2 -0
  193. package/dist/{radio-group-field-kTgtvp1p.cjs.map → radio-group-field-gHNAwrdr.cjs.map} +1 -1
  194. package/dist/{resizable-C3uADYIg.d.cts → resizable-C6JLqxF3.d.cts} +2 -2
  195. package/dist/{resizable-C3uADYIg.d.mts → resizable-C6JLqxF3.d.mts} +2 -2
  196. package/dist/rolldown-runtime-DWNI8pZO.cjs +1 -0
  197. package/dist/{search-input-C8feOKe2.d.cts → search-input-DEvYI6Rm.d.mts} +2 -2
  198. package/dist/{search-input-CoqwakbI.d.mts → search-input-h_3MoMqK.d.cts} +2 -2
  199. package/dist/select-field-8PfksL_U.mjs +2 -0
  200. package/dist/{select-field-BcsFBbNJ.mjs.map → select-field-8PfksL_U.mjs.map} +1 -1
  201. package/dist/select-field-Ce53hZ3J.cjs +2 -0
  202. package/dist/{select-field-CURv37h4.cjs.map → select-field-Ce53hZ3J.cjs.map} +1 -1
  203. package/dist/simple-array-field-BAR4MjDR.cjs +2 -0
  204. package/dist/{simple-array-field-bCUuPMgT.cjs.map → simple-array-field-BAR4MjDR.cjs.map} +1 -1
  205. package/dist/simple-array-field-C0kpO1cq.mjs +2 -0
  206. package/dist/{simple-array-field-wFE_DUOV.mjs.map → simple-array-field-C0kpO1cq.mjs.map} +1 -1
  207. package/dist/simple-boolean-field-36jmOxCR.cjs +2 -0
  208. package/dist/{simple-boolean-field-DRapzNrB.cjs.map → simple-boolean-field-36jmOxCR.cjs.map} +1 -1
  209. package/dist/simple-boolean-field-Bdc4wuUU.mjs +2 -0
  210. package/dist/{simple-boolean-field-GQJyeyVS.mjs.map → simple-boolean-field-Bdc4wuUU.mjs.map} +1 -1
  211. package/dist/simple-combobox-field-BPDtPj1W.cjs +2 -0
  212. package/dist/{simple-combobox-field-Cp5dfQv3.cjs.map → simple-combobox-field-BPDtPj1W.cjs.map} +1 -1
  213. package/dist/simple-combobox-field-CR5Q6Nsd.mjs +2 -0
  214. package/dist/{simple-combobox-field-D6IaMJKl.mjs.map → simple-combobox-field-CR5Q6Nsd.mjs.map} +1 -1
  215. package/dist/simple-date-field-DUPnGa5d.cjs +2 -0
  216. package/dist/{simple-date-field-_PSkIXAt.cjs.map → simple-date-field-DUPnGa5d.cjs.map} +1 -1
  217. package/dist/simple-date-field-DkhG2o7I.mjs +2 -0
  218. package/dist/{simple-date-field-dszQs7Ik.mjs.map → simple-date-field-DkhG2o7I.mjs.map} +1 -1
  219. package/dist/simple-email-field-BTYqiFp8.cjs +2 -0
  220. package/dist/{simple-email-field-DIHwYrhk.cjs.map → simple-email-field-BTYqiFp8.cjs.map} +1 -1
  221. package/dist/simple-email-field-CpxklyKr.mjs +2 -0
  222. package/dist/{simple-email-field-CwyoXqWo.mjs.map → simple-email-field-CpxklyKr.mjs.map} +1 -1
  223. package/dist/simple-number-field-CTFyTMgw.cjs +2 -0
  224. package/dist/{simple-number-field-VdEeaIiC.cjs.map → simple-number-field-CTFyTMgw.cjs.map} +1 -1
  225. package/dist/simple-number-field-DuCvwUG9.mjs +2 -0
  226. package/dist/{simple-number-field-Id1kV5yR.mjs.map → simple-number-field-DuCvwUG9.mjs.map} +1 -1
  227. package/dist/simple-password-field-BaeUvVB1.cjs +2 -0
  228. package/dist/{simple-password-field-7xbVB1H3.cjs.map → simple-password-field-BaeUvVB1.cjs.map} +1 -1
  229. package/dist/simple-password-field-Cu_JvDEE.mjs +2 -0
  230. package/dist/{simple-password-field-DIO9FwQy.mjs.map → simple-password-field-Cu_JvDEE.mjs.map} +1 -1
  231. package/dist/simple-radio-group-field-DiU4eQ_c.cjs +2 -0
  232. package/dist/{simple-radio-group-field-CxVAr6yW.cjs.map → simple-radio-group-field-DiU4eQ_c.cjs.map} +1 -1
  233. package/dist/simple-radio-group-field-RJ_cEsxK.mjs +2 -0
  234. package/dist/{simple-radio-group-field-BmHWRnns.mjs.map → simple-radio-group-field-RJ_cEsxK.mjs.map} +1 -1
  235. package/dist/simple-select-field-B3uEUqvQ.mjs +2 -0
  236. package/dist/{simple-select-field-DfZk0zPa.mjs.map → simple-select-field-B3uEUqvQ.mjs.map} +1 -1
  237. package/dist/simple-select-field-C8vmeHbL.cjs +2 -0
  238. package/dist/{simple-select-field-C9u7Pg9u.cjs.map → simple-select-field-C8vmeHbL.cjs.map} +1 -1
  239. package/dist/simple-text-field-BEoQmd1b.mjs +2 -0
  240. package/dist/{simple-text-field-CT9KFUSK.mjs.map → simple-text-field-BEoQmd1b.mjs.map} +1 -1
  241. package/dist/simple-text-field-zFJt_99J.cjs +2 -0
  242. package/dist/{simple-text-field-BxPjcB4c.cjs.map → simple-text-field-zFJt_99J.cjs.map} +1 -1
  243. package/dist/simple-textarea-field-CzpApMiv.mjs +2 -0
  244. package/dist/{simple-textarea-field-B22rT6zS.mjs.map → simple-textarea-field-CzpApMiv.mjs.map} +1 -1
  245. package/dist/simple-textarea-field-DyQZEDTe.cjs +2 -0
  246. package/dist/{simple-textarea-field-DG9oPtP-.cjs.map → simple-textarea-field-DyQZEDTe.cjs.map} +1 -1
  247. package/dist/{statistic-CE_Jg8SN.cjs → statistic-CXBTEgKI.cjs} +2 -2
  248. package/dist/{statistic-CE_Jg8SN.cjs.map → statistic-CXBTEgKI.cjs.map} +1 -1
  249. package/dist/{statistic-639yMA2d.mjs → statistic-CvgurN5Z.mjs} +2 -2
  250. package/dist/{statistic-639yMA2d.mjs.map → statistic-CvgurN5Z.mjs.map} +1 -1
  251. package/dist/{status-display-BCYpNJmd.mjs → status-display-Caae2aYf.mjs} +2 -2
  252. package/dist/{status-display-BCYpNJmd.mjs.map → status-display-Caae2aYf.mjs.map} +1 -1
  253. package/dist/{status-display-xcCCGpGS.cjs → status-display-EVwkPrm6.cjs} +2 -2
  254. package/dist/{status-display-xcCCGpGS.cjs.map → status-display-EVwkPrm6.cjs.map} +1 -1
  255. package/dist/{summary-bar-C3NAnI3V.mjs → summary-bar-B6B_wmZA.mjs} +2 -2
  256. package/dist/{summary-bar-C3NAnI3V.mjs.map → summary-bar-B6B_wmZA.mjs.map} +1 -1
  257. package/dist/{summary-bar-C08g8bb1.cjs → summary-bar-D36n4fox.cjs} +2 -2
  258. package/dist/{summary-bar-C08g8bb1.cjs.map → summary-bar-D36n4fox.cjs.map} +1 -1
  259. package/dist/switch-field-CsI6eXJu.cjs +2 -0
  260. package/dist/{switch-field-yE4A6EoF.cjs.map → switch-field-CsI6eXJu.cjs.map} +1 -1
  261. package/dist/switch-field-D2SWDM1l.mjs +2 -0
  262. package/dist/{switch-field-Cz4lDf1D.mjs.map → switch-field-D2SWDM1l.mjs.map} +1 -1
  263. package/dist/{tables-Dg3KMBKA.mjs → tables-CuoBQNqx.mjs} +2 -2
  264. package/dist/{tables-Dg3KMBKA.mjs.map → tables-CuoBQNqx.mjs.map} +1 -1
  265. package/dist/{tables-BqZ4Zs6e.cjs → tables-DdLEj1dI.cjs} +2 -2
  266. package/dist/{tables-BqZ4Zs6e.cjs.map → tables-DdLEj1dI.cjs.map} +1 -1
  267. package/dist/tanstack-form-BiOihtxs.cjs +2 -0
  268. package/dist/tanstack-form-BiOihtxs.cjs.map +1 -0
  269. package/dist/tanstack-form-Do6xL2kv.mjs +2 -0
  270. package/dist/tanstack-form-Do6xL2kv.mjs.map +1 -0
  271. package/dist/text-editor-DWZf3yrW.cjs +2 -0
  272. package/dist/text-editor-DWZf3yrW.cjs.map +1 -0
  273. package/dist/text-editor-XBOAwJk-.mjs +2 -0
  274. package/dist/text-editor-XBOAwJk-.mjs.map +1 -0
  275. package/dist/text-field-D9CYYDKM.cjs +2 -0
  276. package/dist/{text-field-BQovKYN-.cjs.map → text-field-D9CYYDKM.cjs.map} +1 -1
  277. package/dist/text-field-wes_PQEd.mjs +2 -0
  278. package/dist/{text-field-B3xlvEUN.mjs.map → text-field-wes_PQEd.mjs.map} +1 -1
  279. package/dist/textarea-field-BiNmDHgL.mjs +2 -0
  280. package/dist/{textarea-field-u2UUwtr_.mjs.map → textarea-field-BiNmDHgL.mjs.map} +1 -1
  281. package/dist/textarea-field-CRf0M2Eb.cjs +2 -0
  282. package/dist/{textarea-field-B38SnNv4.cjs.map → textarea-field-CRf0M2Eb.cjs.map} +1 -1
  283. package/dist/title-field-B9LLoqIi.cjs +2 -0
  284. package/dist/{title-field-B2hM3S_S.cjs.map → title-field-B9LLoqIi.cjs.map} +1 -1
  285. package/dist/title-field-C4BmSDR2.mjs +2 -0
  286. package/dist/{title-field-oAqHRw59.mjs.map → title-field-C4BmSDR2.mjs.map} +1 -1
  287. package/dist/{tooltip-BVzKgxrZ.cjs → tooltip-CUyGXE9e.cjs} +3 -3
  288. package/dist/{tooltip-BVzKgxrZ.cjs.map → tooltip-CUyGXE9e.cjs.map} +1 -1
  289. package/dist/{tooltip-D7U_Nl5c.mjs → tooltip-DSxSeIak.mjs} +3 -3
  290. package/dist/{tooltip-D7U_Nl5c.mjs.map → tooltip-DSxSeIak.mjs.map} +1 -1
  291. package/dist/typography/paragraph.d.cts +1 -1
  292. package/dist/typography/paragraph.d.mts +1 -1
  293. package/dist/ui/badge.cjs +1 -1
  294. package/dist/ui/badge.cjs.map +1 -1
  295. package/dist/ui/badge.d.cts +2 -2
  296. package/dist/ui/badge.d.mts +2 -2
  297. package/dist/ui/badge.mjs +1 -1
  298. package/dist/ui/badge.mjs.map +1 -1
  299. package/dist/ui/breadcrumb.cjs +1 -1
  300. package/dist/ui/button-group.cjs +1 -1
  301. package/dist/ui/button.cjs +1 -1
  302. package/dist/ui/button.d.cts +1 -1
  303. package/dist/ui/button.d.mts +1 -1
  304. package/dist/ui/calendar.d.cts +1 -1
  305. package/dist/ui/calendar.d.mts +1 -1
  306. package/dist/ui/carousel.cjs +1 -1
  307. package/dist/ui/carousel.d.cts +1 -1
  308. package/dist/ui/carousel.d.mts +1 -1
  309. package/dist/ui/combobox.cjs +1 -1
  310. package/dist/ui/combobox.mjs +1 -1
  311. package/dist/ui/dropdown-menu.cjs +1 -1
  312. package/dist/ui/dropdown-menu.cjs.map +1 -1
  313. package/dist/ui/dropdown-menu.mjs +1 -1
  314. package/dist/ui/dropdown-menu.mjs.map +1 -1
  315. package/dist/ui/file-uploader.cjs +1 -1
  316. package/dist/ui/input.d.cts +1 -1
  317. package/dist/ui/input.d.mts +1 -1
  318. package/dist/ui/inputs/search-input.d.cts +1 -1
  319. package/dist/ui/inputs/search-input.d.mts +1 -1
  320. package/dist/ui/item.cjs +1 -1
  321. package/dist/ui/pagination.d.cts +1 -1
  322. package/dist/ui/pagination.d.mts +1 -1
  323. package/dist/ui/resizable.cjs +1 -1
  324. package/dist/ui/resizable.d.cts +1 -1
  325. package/dist/ui/resizable.d.mts +1 -1
  326. package/dist/{ui-grid-CzL5J7cm.d.cts → ui-grid-D1-Ponqs.d.cts} +5 -5
  327. package/dist/{ui-grid-CzL5J7cm.d.mts → ui-grid-D1-Ponqs.d.mts} +5 -5
  328. package/package.json +8 -4
  329. package/styles/text-editor.css +205 -38
  330. package/ai-docs.md +0 -419
  331. package/dist/action-submit-DVNxnW4-.mjs +0 -2
  332. package/dist/action-submit-kYjq-iPD.cjs +0 -2
  333. package/dist/actions-form-CwicJU89.cjs +0 -2
  334. package/dist/actions-form-DRrkiGzh.mjs +0 -2
  335. package/dist/checkbox-field-BN3Vd9qq.mjs +0 -2
  336. package/dist/checkbox-field-DBUjQC_4.cjs +0 -2
  337. package/dist/combobox-C64Rvd7n.mjs +0 -2
  338. package/dist/combobox-field-BE9miJ3D.cjs +0 -2
  339. package/dist/combobox-field-Bug1qI5B.mjs +0 -2
  340. package/dist/combobox-kp_kPY8o.cjs +0 -2
  341. package/dist/date-field-CYoPe74G.cjs +0 -2
  342. package/dist/date-field-D_qpBb-t.mjs +0 -2
  343. package/dist/dialog-form-BTZZwz3T.cjs +0 -2
  344. package/dist/dialog-form-CCIcht28.mjs +0 -2
  345. package/dist/email-field-DJa7iASY.cjs +0 -2
  346. package/dist/email-field-DxSNJ6tf.mjs +0 -2
  347. package/dist/features/descriptions/index.cjs.map +0 -1
  348. package/dist/features/descriptions/index.mjs.map +0 -1
  349. package/dist/field-BSLi-P0Q.cjs +0 -2
  350. package/dist/field-BSLi-P0Q.cjs.map +0 -1
  351. package/dist/field-V2DoD8qL.mjs +0 -2
  352. package/dist/field-V2DoD8qL.mjs.map +0 -1
  353. package/dist/group-field-gejvx_Td.mjs +0 -2
  354. package/dist/group-field-sVykO2JZ.cjs +0 -2
  355. package/dist/index-BMuVmm7f.d.mts +0 -236
  356. package/dist/index-CLx89ATZ.d.cts +0 -236
  357. package/dist/number-field-5INgdUUv.mjs +0 -2
  358. package/dist/number-field-DKZz-27X.cjs +0 -2
  359. package/dist/password-field-BuWARi35.cjs +0 -2
  360. package/dist/password-field-DOIe6wTv.mjs +0 -2
  361. package/dist/payment-layout-DDcLanA0.cjs +0 -2
  362. package/dist/popover-form-Bq2GcuZu.cjs +0 -2
  363. package/dist/popover-form-BsapHJck.mjs +0 -2
  364. package/dist/radio-group-field-DOJ4jVSr.mjs +0 -2
  365. package/dist/radio-group-field-kTgtvp1p.cjs +0 -2
  366. package/dist/rolldown-runtime-CMqjfN_6.cjs +0 -1
  367. package/dist/select-field-BcsFBbNJ.mjs +0 -2
  368. package/dist/select-field-CURv37h4.cjs +0 -2
  369. package/dist/simple-array-field-bCUuPMgT.cjs +0 -2
  370. package/dist/simple-array-field-wFE_DUOV.mjs +0 -2
  371. package/dist/simple-boolean-field-DRapzNrB.cjs +0 -2
  372. package/dist/simple-boolean-field-GQJyeyVS.mjs +0 -2
  373. package/dist/simple-combobox-field-Cp5dfQv3.cjs +0 -2
  374. package/dist/simple-combobox-field-D6IaMJKl.mjs +0 -2
  375. package/dist/simple-date-field-_PSkIXAt.cjs +0 -2
  376. package/dist/simple-date-field-dszQs7Ik.mjs +0 -2
  377. package/dist/simple-email-field-CwyoXqWo.mjs +0 -2
  378. package/dist/simple-email-field-DIHwYrhk.cjs +0 -2
  379. package/dist/simple-number-field-Id1kV5yR.mjs +0 -2
  380. package/dist/simple-number-field-VdEeaIiC.cjs +0 -2
  381. package/dist/simple-password-field-7xbVB1H3.cjs +0 -2
  382. package/dist/simple-password-field-DIO9FwQy.mjs +0 -2
  383. package/dist/simple-radio-group-field-BmHWRnns.mjs +0 -2
  384. package/dist/simple-radio-group-field-CxVAr6yW.cjs +0 -2
  385. package/dist/simple-select-field-C9u7Pg9u.cjs +0 -2
  386. package/dist/simple-select-field-DfZk0zPa.mjs +0 -2
  387. package/dist/simple-text-field-BxPjcB4c.cjs +0 -2
  388. package/dist/simple-text-field-CT9KFUSK.mjs +0 -2
  389. package/dist/simple-textarea-field-B22rT6zS.mjs +0 -2
  390. package/dist/simple-textarea-field-DG9oPtP-.cjs +0 -2
  391. package/dist/switch-field-Cz4lDf1D.mjs +0 -2
  392. package/dist/switch-field-yE4A6EoF.cjs +0 -2
  393. package/dist/tanstack-form-BxqS40rB.cjs +0 -2
  394. package/dist/tanstack-form-BxqS40rB.cjs.map +0 -1
  395. package/dist/tanstack-form-q9hDCc0Y.mjs +0 -2
  396. package/dist/tanstack-form-q9hDCc0Y.mjs.map +0 -1
  397. package/dist/text-editor-BtfyZSgR.cjs +0 -2
  398. package/dist/text-editor-BtfyZSgR.cjs.map +0 -1
  399. package/dist/text-editor-CtR27_PR.mjs +0 -2
  400. package/dist/text-editor-CtR27_PR.mjs.map +0 -1
  401. package/dist/text-editor-field-CQ8tnZFw.mjs +0 -2
  402. package/dist/text-editor-field-CQ8tnZFw.mjs.map +0 -1
  403. package/dist/text-editor-field-CxU-KMMn.cjs +0 -2
  404. package/dist/text-editor-field-CxU-KMMn.cjs.map +0 -1
  405. package/dist/text-field-B3xlvEUN.mjs +0 -2
  406. package/dist/text-field-BQovKYN-.cjs +0 -2
  407. package/dist/textarea-field-B38SnNv4.cjs +0 -2
  408. package/dist/textarea-field-u2UUwtr_.mjs +0 -2
  409. package/dist/title-field-B2hM3S_S.cjs +0 -2
  410. package/dist/title-field-oAqHRw59.mjs +0 -2
@@ -1 +1 @@
1
- {"version":3,"file":"text-field-BQovKYN-.cjs","names":["useTanStackFieldContext","FieldGroup","Field","FieldContent","FieldLabel","FieldTooltip","FieldDescription","FieldContentMain","Input","XIcon","Loader2Icon","BanIcon","FieldError","FieldNote","FieldSeparator"],"sources":["../packages/components/features/tanstack-form/components/fields/text-field.tsx"],"sourcesContent":["'use client';\n\nimport { memo, useCallback, useId, useRef } from 'react';\n\nimport { useStore } from '@tanstack/react-form';\n\nimport { BanIcon, Loader2Icon, XIcon } from 'lucide-react';\n\nimport { cn } from '@customafk/react-toolkit/utils';\n\nimport { Input } from '@/components/ui/input';\nimport {\n Field,\n FieldContent,\n FieldContentMain,\n FieldDescription,\n FieldError,\n FieldGroup,\n FieldLabel,\n FieldNote,\n FieldSeparator,\n FieldTooltip,\n} from '@/components/features/tanstack-form/components/ui/field';\nimport { useTanStackFieldContext } from '../form-context';\n\nimport type { TextFieldProps as Props } from '../../types';\n\n/** Fraction of maxLength at which the counter turns warning color (80%). */\nconst COUNTER_WARNING_THRESHOLD = 0.8;\n\n/** Pixel size for inline adornment icons (error ban, loading spinner). */\nconst ADORNMENT_ICON_SIZE = 14;\n\n// Static handler — no closure deps, shared across all TextField instances\nconst onKeyDown: React.KeyboardEventHandler<HTMLInputElement> = e => {\n if (e.key === 'Enter') e.preventDefault();\n};\n\n/**\n * A TanStack Form-connected single-line text input with label, validation, and optional features.\n *\n * Must be rendered inside an `AppField` context from `useTanStackForm`.\n * The field value type is `string | null` — `null` represents an empty/unset state.\n *\n * ---\n *\n * **Basic usage**\n * @example\n * const { AppField } = useTanStackForm({ defaultValues: { name: null } });\n *\n * <AppField name=\"name\">\n * {field => <field.TextField label=\"Full name\" placeholder=\"Nguyễn Văn A\" />}\n * </AppField>\n *\n * ---\n *\n * **With validation**\n * @example\n * <AppField\n * name=\"username\"\n * validators={{ onChange: ({ value }) => !value ? 'Bắt buộc' : undefined }}\n * >\n * {field => <field.TextField label=\"Username\" required />}\n * </AppField>\n *\n * ---\n *\n * **With character counter and max length**\n * @example\n * <AppField name=\"bio\">\n * {field => (\n * <field.TextField\n * label=\"Bio\"\n * counter\n * maxLength={160}\n * placeholder=\"Giới thiệu bản thân…\"\n * />\n * )}\n * </AppField>\n *\n * ---\n *\n * **With clear button and helper note**\n * @example\n * <AppField name=\"search\">\n * {field => (\n * <field.TextField\n * label=\"Tìm kiếm\"\n * showClearButton\n * helperText=\"Nhập ít nhất 3 ký tự để tìm kiếm.\"\n * />\n * )}\n * </AppField>\n *\n * ---\n *\n * **Horizontal layout**\n * @example\n * <AppField name=\"code\">\n * {field => (\n * <field.TextField\n * label=\"Mã sản phẩm\"\n * orientation=\"horizontal\"\n * tooltip=\"Mã duy nhất định danh sản phẩm trong hệ thống.\"\n * />\n * )}\n * </AppField>\n */\nexport const TextField = memo<Props>(\n ({\n label,\n description,\n placeholder,\n\n tooltip,\n helperText,\n counter = false,\n orientation = 'responsive',\n showClearButton = false,\n showErrorMessage = true,\n\n required = false,\n disabled = false,\n maxLength,\n }) => {\n const id = useId();\n const errorId = useId();\n const inputRef = useRef<HTMLInputElement>(null);\n const { form, name, state, handleBlur, handleChange } = useTanStackFieldContext<string | null>();\n\n const isSubmitting = useStore(form.store, ({ isSubmitting }) => isSubmitting);\n const isDisabled = disabled || isSubmitting;\n\n const _touched = state.meta.isDirty || state.meta.isTouched;\n const _invalid = _touched && !state.meta.isValid;\n const _isEmpty = required && state.value === null;\n const _hasErrors = state.meta.errors.length > 0;\n const _showClearButton = showClearButton && !isDisabled && !!state.value;\n\n // Counter values are only computed when the feature is active\n const _count = counter ? (state.value?.length ?? 0) : 0;\n const _isNearLimit = counter && !!maxLength && _count >= maxLength * COUNTER_WARNING_THRESHOLD;\n const _isAtLimit = counter && !!maxLength && _count >= maxLength;\n const _countText = counter ? (maxLength ? `${_count} / ${maxLength} ký tự` : `${_count} ký tự`) : null;\n\n // Skip the bottom row entirely when neither error nor counter will render\n const _showBottomRow = counter || (_touched && showErrorMessage && _hasErrors);\n\n const onChange = useCallback<React.ChangeEventHandler<HTMLInputElement>>(\n ({ target: { value } }) => {\n if (counter && maxLength && value.length > maxLength) return;\n handleChange(value || null);\n },\n [counter, maxLength, handleChange]\n );\n\n const onClear = useCallback(() => {\n handleChange(null);\n inputRef.current?.focus();\n }, [handleChange]);\n\n return (\n <FieldGroup className=\"gap-y-4 px-4\">\n <Field orientation={orientation} data-invalid={_invalid}>\n <FieldContent>\n <FieldLabel aria-required={_isEmpty} htmlFor={id}>\n {label}\n {tooltip && <FieldTooltip tooltip={tooltip} />}\n </FieldLabel>\n {description && <FieldDescription>{description}</FieldDescription>}\n </FieldContent>\n <FieldContentMain>\n <Input\n ref={inputRef}\n id={id}\n name={name}\n value={state.value ?? ''}\n aria-invalid={_invalid}\n aria-describedby={errorId}\n autoComplete=\"off\"\n placeholder={placeholder}\n autoCapitalize=\"none\"\n autoCorrect=\"off\"\n disabled={isDisabled}\n className={cn('pr-6', isDisabled && 'pointer-events-none bg-muted-muted opacity-60')}\n onBlur={handleBlur}\n onChange={onChange}\n onKeyDown={onKeyDown}\n />\n {_showClearButton && (\n <button\n type=\"button\"\n aria-label=\"Xóa\"\n className=\"absolute inset-e-1 top-2.5 flex size-4 cursor-pointer items-center justify-center rounded-md text-text-positive-weak outline-none transition-[color,transform] hover:text-text-positive focus-visible:text-primary-strong focus-visible:[&>svg]:scale-125 [&>svg]:size-3.5 [&>svg]:transition-transform\"\n onClick={onClear}\n >\n <XIcon aria-hidden=\"true\" />\n </button>\n )}\n {isSubmitting && (\n <div className=\"absolute inset-e-2 inset-y-0 top-2.5 text-muted-weak\">\n <Loader2Icon size={ADORNMENT_ICON_SIZE} className=\"animate-spin text-primary-strong\" />\n </div>\n )}\n {!_showClearButton && _touched && showErrorMessage && _hasErrors && (\n <div className=\"absolute inset-e-2 inset-y-0 top-2.5 text-danger-strong\">\n <BanIcon aria-hidden=\"true\" size={ADORNMENT_ICON_SIZE} />\n </div>\n )}\n {_showBottomRow && (\n <div className=\"my-1 flex w-full items-start justify-between gap-x-2\">\n {_touched && showErrorMessage ? <FieldError id={errorId} className=\"flex-1\" errors={state.meta.errors} /> : <div />}\n {counter && (\n <p\n className={cn(\n 'h-4 flex-0 text-nowrap text-end text-xs tabular-nums transition-colors',\n _isAtLimit ? 'font-medium text-danger-strong' : _isNearLimit ? 'text-warning-strong' : 'text-text-positive-weak'\n )}\n >\n {_countText}\n </p>\n )}\n </div>\n )}\n <FieldNote isShow={!!helperText}>{helperText}</FieldNote>\n </FieldContentMain>\n </Field>\n <FieldSeparator />\n </FieldGroup>\n );\n }\n);\n\nTextField.displayName = 'TextField';\n"],"mappings":"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"}
1
+ {"version":3,"file":"text-field-D9CYYDKM.cjs","names":["useTanStackFieldContext","FieldGroup","Field","FieldContent","FieldLabel","FieldTooltip","FieldDescription","FieldContentMain","Input","XIcon","Loader2Icon","BanIcon","FieldError","FieldNote","FieldSeparator"],"sources":["../packages/components/features/tanstack-form/components/fields/text-field.tsx"],"sourcesContent":["'use client';\n\nimport { memo, useCallback, useId, useRef } from 'react';\n\nimport { useStore } from '@tanstack/react-form';\n\nimport { BanIcon, Loader2Icon, XIcon } from 'lucide-react';\n\nimport { cn } from '@customafk/react-toolkit/utils';\n\nimport { Input } from '@/components/ui/input';\nimport {\n Field,\n FieldContent,\n FieldContentMain,\n FieldDescription,\n FieldError,\n FieldGroup,\n FieldLabel,\n FieldNote,\n FieldSeparator,\n FieldTooltip,\n} from '@/components/features/tanstack-form/components/ui/field';\nimport { useTanStackFieldContext } from '../form-context';\n\nimport type { TextFieldProps as Props } from '../../types';\n\n/** Fraction of maxLength at which the counter turns warning color (80%). */\nconst COUNTER_WARNING_THRESHOLD = 0.8;\n\n/** Pixel size for inline adornment icons (error ban, loading spinner). */\nconst ADORNMENT_ICON_SIZE = 14;\n\n// Static handler — no closure deps, shared across all TextField instances\nconst onKeyDown: React.KeyboardEventHandler<HTMLInputElement> = e => {\n if (e.key === 'Enter') e.preventDefault();\n};\n\n/**\n * A TanStack Form-connected single-line text input with label, validation, and optional features.\n *\n * Must be rendered inside an `AppField` context from `useTanStackForm`.\n * The field value type is `string | null` — `null` represents an empty/unset state.\n *\n * ---\n *\n * **Basic usage**\n * @example\n * const { AppField } = useTanStackForm({ defaultValues: { name: null } });\n *\n * <AppField name=\"name\">\n * {field => <field.TextField label=\"Full name\" placeholder=\"Nguyễn Văn A\" />}\n * </AppField>\n *\n * ---\n *\n * **With validation**\n * @example\n * <AppField\n * name=\"username\"\n * validators={{ onChange: ({ value }) => !value ? 'Bắt buộc' : undefined }}\n * >\n * {field => <field.TextField label=\"Username\" required />}\n * </AppField>\n *\n * ---\n *\n * **With character counter and max length**\n * @example\n * <AppField name=\"bio\">\n * {field => (\n * <field.TextField\n * label=\"Bio\"\n * counter\n * maxLength={160}\n * placeholder=\"Giới thiệu bản thân…\"\n * />\n * )}\n * </AppField>\n *\n * ---\n *\n * **With clear button and helper note**\n * @example\n * <AppField name=\"search\">\n * {field => (\n * <field.TextField\n * label=\"Tìm kiếm\"\n * showClearButton\n * helperText=\"Nhập ít nhất 3 ký tự để tìm kiếm.\"\n * />\n * )}\n * </AppField>\n *\n * ---\n *\n * **Horizontal layout**\n * @example\n * <AppField name=\"code\">\n * {field => (\n * <field.TextField\n * label=\"Mã sản phẩm\"\n * orientation=\"horizontal\"\n * tooltip=\"Mã duy nhất định danh sản phẩm trong hệ thống.\"\n * />\n * )}\n * </AppField>\n */\nexport const TextField = memo<Props>(\n ({\n label,\n description,\n placeholder,\n\n tooltip,\n helperText,\n counter = false,\n orientation = 'responsive',\n showClearButton = false,\n showErrorMessage = true,\n\n required = false,\n disabled = false,\n maxLength,\n }) => {\n const id = useId();\n const errorId = useId();\n const inputRef = useRef<HTMLInputElement>(null);\n const { form, name, state, handleBlur, handleChange } = useTanStackFieldContext<string | null>();\n\n const isSubmitting = useStore(form.store, ({ isSubmitting }) => isSubmitting);\n const isDisabled = disabled || isSubmitting;\n\n const _touched = state.meta.isDirty || state.meta.isTouched;\n const _invalid = _touched && !state.meta.isValid;\n const _isEmpty = required && state.value === null;\n const _hasErrors = state.meta.errors.length > 0;\n const _showClearButton = showClearButton && !isDisabled && !!state.value;\n\n // Counter values are only computed when the feature is active\n const _count = counter ? (state.value?.length ?? 0) : 0;\n const _isNearLimit = counter && !!maxLength && _count >= maxLength * COUNTER_WARNING_THRESHOLD;\n const _isAtLimit = counter && !!maxLength && _count >= maxLength;\n const _countText = counter ? (maxLength ? `${_count} / ${maxLength} ký tự` : `${_count} ký tự`) : null;\n\n // Skip the bottom row entirely when neither error nor counter will render\n const _showBottomRow = counter || (_touched && showErrorMessage && _hasErrors);\n\n const onChange = useCallback<React.ChangeEventHandler<HTMLInputElement>>(\n ({ target: { value } }) => {\n if (counter && maxLength && value.length > maxLength) return;\n handleChange(value || null);\n },\n [counter, maxLength, handleChange]\n );\n\n const onClear = useCallback(() => {\n handleChange(null);\n inputRef.current?.focus();\n }, [handleChange]);\n\n return (\n <FieldGroup className=\"gap-y-4 px-4\">\n <Field orientation={orientation} data-invalid={_invalid}>\n <FieldContent>\n <FieldLabel aria-required={_isEmpty} htmlFor={id}>\n {label}\n {tooltip && <FieldTooltip tooltip={tooltip} />}\n </FieldLabel>\n {description && <FieldDescription>{description}</FieldDescription>}\n </FieldContent>\n <FieldContentMain>\n <Input\n ref={inputRef}\n id={id}\n name={name}\n value={state.value ?? ''}\n aria-invalid={_invalid}\n aria-describedby={errorId}\n autoComplete=\"off\"\n placeholder={placeholder}\n autoCapitalize=\"none\"\n autoCorrect=\"off\"\n disabled={isDisabled}\n className={cn('pr-6', isDisabled && 'pointer-events-none bg-muted-muted opacity-60')}\n onBlur={handleBlur}\n onChange={onChange}\n onKeyDown={onKeyDown}\n />\n {_showClearButton && (\n <button\n type=\"button\"\n aria-label=\"Xóa\"\n className=\"absolute inset-e-1 top-2.5 flex size-4 cursor-pointer items-center justify-center rounded-md text-text-positive-weak outline-none transition-[color,transform] hover:text-text-positive focus-visible:text-primary-strong focus-visible:[&>svg]:scale-125 [&>svg]:size-3.5 [&>svg]:transition-transform\"\n onClick={onClear}\n >\n <XIcon aria-hidden=\"true\" />\n </button>\n )}\n {isSubmitting && (\n <div className=\"absolute inset-e-2 inset-y-0 top-2.5 text-muted-weak\">\n <Loader2Icon size={ADORNMENT_ICON_SIZE} className=\"animate-spin text-primary-strong\" />\n </div>\n )}\n {!_showClearButton && _touched && showErrorMessage && _hasErrors && (\n <div className=\"absolute inset-e-2 inset-y-0 top-2.5 text-danger-strong\">\n <BanIcon aria-hidden=\"true\" size={ADORNMENT_ICON_SIZE} />\n </div>\n )}\n {_showBottomRow && (\n <div className=\"my-1 flex w-full items-start justify-between gap-x-2\">\n {_touched && showErrorMessage ? <FieldError id={errorId} className=\"flex-1\" errors={state.meta.errors} /> : <div />}\n {counter && (\n <p\n className={cn(\n 'h-4 flex-0 text-nowrap text-end text-xs tabular-nums transition-colors',\n _isAtLimit ? 'font-medium text-danger-strong' : _isNearLimit ? 'text-warning-strong' : 'text-text-positive-weak'\n )}\n >\n {_countText}\n </p>\n )}\n </div>\n )}\n <FieldNote isShow={!!helperText}>{helperText}</FieldNote>\n </FieldContentMain>\n </Field>\n <FieldSeparator />\n </FieldGroup>\n );\n }\n);\n\nTextField.displayName = 'TextField';\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import{$ as e,G as t,J as n,K as r,X as i,Y as a,Z as o,et as s,nt as c,q as l,rt as u}from"./tanstack-form-Do6xL2kv.mjs";import{Input as d}from"./ui/input.mjs";import{BanIcon as f,Loader2Icon as p,XIcon as m}from"lucide-react";import{memo as h,useCallback as g,useId as _,useRef as v}from"react";import{cn as y}from"@customafk/react-toolkit/utils";import{jsx as b,jsxs as x}from"react/jsx-runtime";import{useStore as S}from"@tanstack/react-form";const C=e=>{e.key===`Enter`&&e.preventDefault()},w=h(({label:h,description:w,placeholder:T,tooltip:E,helperText:D,counter:O=!1,orientation:k=`responsive`,showClearButton:A=!1,showErrorMessage:j=!0,required:M=!1,disabled:N=!1,maxLength:P})=>{let F=_(),I=_(),L=v(null),{form:R,name:z,state:B,handleBlur:V,handleChange:H}=u(),U=S(R.store,({isSubmitting:e})=>e),W=N||U,G=B.meta.isDirty||B.meta.isTouched,K=G&&!B.meta.isValid,q=M&&B.value===null,J=B.meta.errors.length>0,Y=A&&!W&&!!B.value,X=O?B.value?.length??0:0,Z=O&&!!P&&X>=P*.8,Q=O&&!!P&&X>=P,$=O?P?`${X} / ${P} ký tự`:`${X} ký tự`:null,ee=O||G&&j&&J,te=g(({target:{value:e}})=>{O&&P&&e.length>P||H(e||null)},[O,P,H]),ne=g(()=>{H(null),L.current?.focus()},[H]);return x(i,{className:`gap-y-4 px-4`,children:[x(t,{orientation:k,"data-invalid":K,children:[x(r,{children:[x(o,{"aria-required":q,htmlFor:F,children:[h,E&&b(c,{tooltip:E})]}),w&&b(n,{children:w})]}),x(l,{children:[b(d,{ref:L,id:F,name:z,value:B.value??``,"aria-invalid":K,"aria-describedby":I,autoComplete:`off`,placeholder:T,autoCapitalize:`none`,autoCorrect:`off`,disabled:W,className:y(`pr-6`,W&&`pointer-events-none bg-muted-muted opacity-60`),onBlur:V,onChange:te,onKeyDown:C}),Y&&b(`button`,{type:`button`,"aria-label":`Xóa`,className:`absolute inset-e-1 top-2.5 flex size-4 cursor-pointer items-center justify-center rounded-md text-text-positive-weak outline-none transition-[color,transform] hover:text-text-positive focus-visible:text-primary-strong focus-visible:[&>svg]:scale-125 [&>svg]:size-3.5 [&>svg]:transition-transform`,onClick:ne,children:b(m,{"aria-hidden":`true`})}),U&&b(`div`,{className:`absolute inset-e-2 inset-y-0 top-2.5 text-muted-weak`,children:b(p,{size:14,className:`animate-spin text-primary-strong`})}),!Y&&G&&j&&J&&b(`div`,{className:`absolute inset-e-2 inset-y-0 top-2.5 text-danger-strong`,children:b(f,{"aria-hidden":`true`,size:14})}),ee&&x(`div`,{className:`my-1 flex w-full items-start justify-between gap-x-2`,children:[G&&j?b(a,{id:I,className:`flex-1`,errors:B.meta.errors}):b(`div`,{}),O&&b(`p`,{className:y(`h-4 flex-0 text-nowrap text-end text-xs tabular-nums transition-colors`,Q?`font-medium text-danger-strong`:Z?`text-warning-strong`:`text-text-positive-weak`),children:$})]}),b(e,{isShow:!!D,children:D})]})]}),b(s,{})]})});w.displayName=`TextField`;export{w as TextField};
2
+ //# sourceMappingURL=text-field-wes_PQEd.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"text-field-B3xlvEUN.mjs","names":[],"sources":["../packages/components/features/tanstack-form/components/fields/text-field.tsx"],"sourcesContent":["'use client';\n\nimport { memo, useCallback, useId, useRef } from 'react';\n\nimport { useStore } from '@tanstack/react-form';\n\nimport { BanIcon, Loader2Icon, XIcon } from 'lucide-react';\n\nimport { cn } from '@customafk/react-toolkit/utils';\n\nimport { Input } from '@/components/ui/input';\nimport {\n Field,\n FieldContent,\n FieldContentMain,\n FieldDescription,\n FieldError,\n FieldGroup,\n FieldLabel,\n FieldNote,\n FieldSeparator,\n FieldTooltip,\n} from '@/components/features/tanstack-form/components/ui/field';\nimport { useTanStackFieldContext } from '../form-context';\n\nimport type { TextFieldProps as Props } from '../../types';\n\n/** Fraction of maxLength at which the counter turns warning color (80%). */\nconst COUNTER_WARNING_THRESHOLD = 0.8;\n\n/** Pixel size for inline adornment icons (error ban, loading spinner). */\nconst ADORNMENT_ICON_SIZE = 14;\n\n// Static handler — no closure deps, shared across all TextField instances\nconst onKeyDown: React.KeyboardEventHandler<HTMLInputElement> = e => {\n if (e.key === 'Enter') e.preventDefault();\n};\n\n/**\n * A TanStack Form-connected single-line text input with label, validation, and optional features.\n *\n * Must be rendered inside an `AppField` context from `useTanStackForm`.\n * The field value type is `string | null` — `null` represents an empty/unset state.\n *\n * ---\n *\n * **Basic usage**\n * @example\n * const { AppField } = useTanStackForm({ defaultValues: { name: null } });\n *\n * <AppField name=\"name\">\n * {field => <field.TextField label=\"Full name\" placeholder=\"Nguyễn Văn A\" />}\n * </AppField>\n *\n * ---\n *\n * **With validation**\n * @example\n * <AppField\n * name=\"username\"\n * validators={{ onChange: ({ value }) => !value ? 'Bắt buộc' : undefined }}\n * >\n * {field => <field.TextField label=\"Username\" required />}\n * </AppField>\n *\n * ---\n *\n * **With character counter and max length**\n * @example\n * <AppField name=\"bio\">\n * {field => (\n * <field.TextField\n * label=\"Bio\"\n * counter\n * maxLength={160}\n * placeholder=\"Giới thiệu bản thân…\"\n * />\n * )}\n * </AppField>\n *\n * ---\n *\n * **With clear button and helper note**\n * @example\n * <AppField name=\"search\">\n * {field => (\n * <field.TextField\n * label=\"Tìm kiếm\"\n * showClearButton\n * helperText=\"Nhập ít nhất 3 ký tự để tìm kiếm.\"\n * />\n * )}\n * </AppField>\n *\n * ---\n *\n * **Horizontal layout**\n * @example\n * <AppField name=\"code\">\n * {field => (\n * <field.TextField\n * label=\"Mã sản phẩm\"\n * orientation=\"horizontal\"\n * tooltip=\"Mã duy nhất định danh sản phẩm trong hệ thống.\"\n * />\n * )}\n * </AppField>\n */\nexport const TextField = memo<Props>(\n ({\n label,\n description,\n placeholder,\n\n tooltip,\n helperText,\n counter = false,\n orientation = 'responsive',\n showClearButton = false,\n showErrorMessage = true,\n\n required = false,\n disabled = false,\n maxLength,\n }) => {\n const id = useId();\n const errorId = useId();\n const inputRef = useRef<HTMLInputElement>(null);\n const { form, name, state, handleBlur, handleChange } = useTanStackFieldContext<string | null>();\n\n const isSubmitting = useStore(form.store, ({ isSubmitting }) => isSubmitting);\n const isDisabled = disabled || isSubmitting;\n\n const _touched = state.meta.isDirty || state.meta.isTouched;\n const _invalid = _touched && !state.meta.isValid;\n const _isEmpty = required && state.value === null;\n const _hasErrors = state.meta.errors.length > 0;\n const _showClearButton = showClearButton && !isDisabled && !!state.value;\n\n // Counter values are only computed when the feature is active\n const _count = counter ? (state.value?.length ?? 0) : 0;\n const _isNearLimit = counter && !!maxLength && _count >= maxLength * COUNTER_WARNING_THRESHOLD;\n const _isAtLimit = counter && !!maxLength && _count >= maxLength;\n const _countText = counter ? (maxLength ? `${_count} / ${maxLength} ký tự` : `${_count} ký tự`) : null;\n\n // Skip the bottom row entirely when neither error nor counter will render\n const _showBottomRow = counter || (_touched && showErrorMessage && _hasErrors);\n\n const onChange = useCallback<React.ChangeEventHandler<HTMLInputElement>>(\n ({ target: { value } }) => {\n if (counter && maxLength && value.length > maxLength) return;\n handleChange(value || null);\n },\n [counter, maxLength, handleChange]\n );\n\n const onClear = useCallback(() => {\n handleChange(null);\n inputRef.current?.focus();\n }, [handleChange]);\n\n return (\n <FieldGroup className=\"gap-y-4 px-4\">\n <Field orientation={orientation} data-invalid={_invalid}>\n <FieldContent>\n <FieldLabel aria-required={_isEmpty} htmlFor={id}>\n {label}\n {tooltip && <FieldTooltip tooltip={tooltip} />}\n </FieldLabel>\n {description && <FieldDescription>{description}</FieldDescription>}\n </FieldContent>\n <FieldContentMain>\n <Input\n ref={inputRef}\n id={id}\n name={name}\n value={state.value ?? ''}\n aria-invalid={_invalid}\n aria-describedby={errorId}\n autoComplete=\"off\"\n placeholder={placeholder}\n autoCapitalize=\"none\"\n autoCorrect=\"off\"\n disabled={isDisabled}\n className={cn('pr-6', isDisabled && 'pointer-events-none bg-muted-muted opacity-60')}\n onBlur={handleBlur}\n onChange={onChange}\n onKeyDown={onKeyDown}\n />\n {_showClearButton && (\n <button\n type=\"button\"\n aria-label=\"Xóa\"\n className=\"absolute inset-e-1 top-2.5 flex size-4 cursor-pointer items-center justify-center rounded-md text-text-positive-weak outline-none transition-[color,transform] hover:text-text-positive focus-visible:text-primary-strong focus-visible:[&>svg]:scale-125 [&>svg]:size-3.5 [&>svg]:transition-transform\"\n onClick={onClear}\n >\n <XIcon aria-hidden=\"true\" />\n </button>\n )}\n {isSubmitting && (\n <div className=\"absolute inset-e-2 inset-y-0 top-2.5 text-muted-weak\">\n <Loader2Icon size={ADORNMENT_ICON_SIZE} className=\"animate-spin text-primary-strong\" />\n </div>\n )}\n {!_showClearButton && _touched && showErrorMessage && _hasErrors && (\n <div className=\"absolute inset-e-2 inset-y-0 top-2.5 text-danger-strong\">\n <BanIcon aria-hidden=\"true\" size={ADORNMENT_ICON_SIZE} />\n </div>\n )}\n {_showBottomRow && (\n <div className=\"my-1 flex w-full items-start justify-between gap-x-2\">\n {_touched && showErrorMessage ? <FieldError id={errorId} className=\"flex-1\" errors={state.meta.errors} /> : <div />}\n {counter && (\n <p\n className={cn(\n 'h-4 flex-0 text-nowrap text-end text-xs tabular-nums transition-colors',\n _isAtLimit ? 'font-medium text-danger-strong' : _isNearLimit ? 'text-warning-strong' : 'text-text-positive-weak'\n )}\n >\n {_countText}\n </p>\n )}\n </div>\n )}\n <FieldNote isShow={!!helperText}>{helperText}</FieldNote>\n </FieldContentMain>\n </Field>\n <FieldSeparator />\n </FieldGroup>\n );\n }\n);\n\nTextField.displayName = 'TextField';\n"],"mappings":"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"}
1
+ {"version":3,"file":"text-field-wes_PQEd.mjs","names":[],"sources":["../packages/components/features/tanstack-form/components/fields/text-field.tsx"],"sourcesContent":["'use client';\n\nimport { memo, useCallback, useId, useRef } from 'react';\n\nimport { useStore } from '@tanstack/react-form';\n\nimport { BanIcon, Loader2Icon, XIcon } from 'lucide-react';\n\nimport { cn } from '@customafk/react-toolkit/utils';\n\nimport { Input } from '@/components/ui/input';\nimport {\n Field,\n FieldContent,\n FieldContentMain,\n FieldDescription,\n FieldError,\n FieldGroup,\n FieldLabel,\n FieldNote,\n FieldSeparator,\n FieldTooltip,\n} from '@/components/features/tanstack-form/components/ui/field';\nimport { useTanStackFieldContext } from '../form-context';\n\nimport type { TextFieldProps as Props } from '../../types';\n\n/** Fraction of maxLength at which the counter turns warning color (80%). */\nconst COUNTER_WARNING_THRESHOLD = 0.8;\n\n/** Pixel size for inline adornment icons (error ban, loading spinner). */\nconst ADORNMENT_ICON_SIZE = 14;\n\n// Static handler — no closure deps, shared across all TextField instances\nconst onKeyDown: React.KeyboardEventHandler<HTMLInputElement> = e => {\n if (e.key === 'Enter') e.preventDefault();\n};\n\n/**\n * A TanStack Form-connected single-line text input with label, validation, and optional features.\n *\n * Must be rendered inside an `AppField` context from `useTanStackForm`.\n * The field value type is `string | null` — `null` represents an empty/unset state.\n *\n * ---\n *\n * **Basic usage**\n * @example\n * const { AppField } = useTanStackForm({ defaultValues: { name: null } });\n *\n * <AppField name=\"name\">\n * {field => <field.TextField label=\"Full name\" placeholder=\"Nguyễn Văn A\" />}\n * </AppField>\n *\n * ---\n *\n * **With validation**\n * @example\n * <AppField\n * name=\"username\"\n * validators={{ onChange: ({ value }) => !value ? 'Bắt buộc' : undefined }}\n * >\n * {field => <field.TextField label=\"Username\" required />}\n * </AppField>\n *\n * ---\n *\n * **With character counter and max length**\n * @example\n * <AppField name=\"bio\">\n * {field => (\n * <field.TextField\n * label=\"Bio\"\n * counter\n * maxLength={160}\n * placeholder=\"Giới thiệu bản thân…\"\n * />\n * )}\n * </AppField>\n *\n * ---\n *\n * **With clear button and helper note**\n * @example\n * <AppField name=\"search\">\n * {field => (\n * <field.TextField\n * label=\"Tìm kiếm\"\n * showClearButton\n * helperText=\"Nhập ít nhất 3 ký tự để tìm kiếm.\"\n * />\n * )}\n * </AppField>\n *\n * ---\n *\n * **Horizontal layout**\n * @example\n * <AppField name=\"code\">\n * {field => (\n * <field.TextField\n * label=\"Mã sản phẩm\"\n * orientation=\"horizontal\"\n * tooltip=\"Mã duy nhất định danh sản phẩm trong hệ thống.\"\n * />\n * )}\n * </AppField>\n */\nexport const TextField = memo<Props>(\n ({\n label,\n description,\n placeholder,\n\n tooltip,\n helperText,\n counter = false,\n orientation = 'responsive',\n showClearButton = false,\n showErrorMessage = true,\n\n required = false,\n disabled = false,\n maxLength,\n }) => {\n const id = useId();\n const errorId = useId();\n const inputRef = useRef<HTMLInputElement>(null);\n const { form, name, state, handleBlur, handleChange } = useTanStackFieldContext<string | null>();\n\n const isSubmitting = useStore(form.store, ({ isSubmitting }) => isSubmitting);\n const isDisabled = disabled || isSubmitting;\n\n const _touched = state.meta.isDirty || state.meta.isTouched;\n const _invalid = _touched && !state.meta.isValid;\n const _isEmpty = required && state.value === null;\n const _hasErrors = state.meta.errors.length > 0;\n const _showClearButton = showClearButton && !isDisabled && !!state.value;\n\n // Counter values are only computed when the feature is active\n const _count = counter ? (state.value?.length ?? 0) : 0;\n const _isNearLimit = counter && !!maxLength && _count >= maxLength * COUNTER_WARNING_THRESHOLD;\n const _isAtLimit = counter && !!maxLength && _count >= maxLength;\n const _countText = counter ? (maxLength ? `${_count} / ${maxLength} ký tự` : `${_count} ký tự`) : null;\n\n // Skip the bottom row entirely when neither error nor counter will render\n const _showBottomRow = counter || (_touched && showErrorMessage && _hasErrors);\n\n const onChange = useCallback<React.ChangeEventHandler<HTMLInputElement>>(\n ({ target: { value } }) => {\n if (counter && maxLength && value.length > maxLength) return;\n handleChange(value || null);\n },\n [counter, maxLength, handleChange]\n );\n\n const onClear = useCallback(() => {\n handleChange(null);\n inputRef.current?.focus();\n }, [handleChange]);\n\n return (\n <FieldGroup className=\"gap-y-4 px-4\">\n <Field orientation={orientation} data-invalid={_invalid}>\n <FieldContent>\n <FieldLabel aria-required={_isEmpty} htmlFor={id}>\n {label}\n {tooltip && <FieldTooltip tooltip={tooltip} />}\n </FieldLabel>\n {description && <FieldDescription>{description}</FieldDescription>}\n </FieldContent>\n <FieldContentMain>\n <Input\n ref={inputRef}\n id={id}\n name={name}\n value={state.value ?? ''}\n aria-invalid={_invalid}\n aria-describedby={errorId}\n autoComplete=\"off\"\n placeholder={placeholder}\n autoCapitalize=\"none\"\n autoCorrect=\"off\"\n disabled={isDisabled}\n className={cn('pr-6', isDisabled && 'pointer-events-none bg-muted-muted opacity-60')}\n onBlur={handleBlur}\n onChange={onChange}\n onKeyDown={onKeyDown}\n />\n {_showClearButton && (\n <button\n type=\"button\"\n aria-label=\"Xóa\"\n className=\"absolute inset-e-1 top-2.5 flex size-4 cursor-pointer items-center justify-center rounded-md text-text-positive-weak outline-none transition-[color,transform] hover:text-text-positive focus-visible:text-primary-strong focus-visible:[&>svg]:scale-125 [&>svg]:size-3.5 [&>svg]:transition-transform\"\n onClick={onClear}\n >\n <XIcon aria-hidden=\"true\" />\n </button>\n )}\n {isSubmitting && (\n <div className=\"absolute inset-e-2 inset-y-0 top-2.5 text-muted-weak\">\n <Loader2Icon size={ADORNMENT_ICON_SIZE} className=\"animate-spin text-primary-strong\" />\n </div>\n )}\n {!_showClearButton && _touched && showErrorMessage && _hasErrors && (\n <div className=\"absolute inset-e-2 inset-y-0 top-2.5 text-danger-strong\">\n <BanIcon aria-hidden=\"true\" size={ADORNMENT_ICON_SIZE} />\n </div>\n )}\n {_showBottomRow && (\n <div className=\"my-1 flex w-full items-start justify-between gap-x-2\">\n {_touched && showErrorMessage ? <FieldError id={errorId} className=\"flex-1\" errors={state.meta.errors} /> : <div />}\n {counter && (\n <p\n className={cn(\n 'h-4 flex-0 text-nowrap text-end text-xs tabular-nums transition-colors',\n _isAtLimit ? 'font-medium text-danger-strong' : _isNearLimit ? 'text-warning-strong' : 'text-text-positive-weak'\n )}\n >\n {_countText}\n </p>\n )}\n </div>\n )}\n <FieldNote isShow={!!helperText}>{helperText}</FieldNote>\n </FieldContentMain>\n </Field>\n <FieldSeparator />\n </FieldGroup>\n );\n }\n);\n\nTextField.displayName = 'TextField';\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import{$ as e,G as t,J as n,K as r,X as i,Y as a,Z as o,et as s,nt as c,q as l,rt as u}from"./tanstack-form-Do6xL2kv.mjs";import{Textarea as d}from"./ui/textarea.mjs";import{BanIcon as f,CheckIcon as p,CopyIcon as ee,Loader2Icon as m}from"lucide-react";import{memo as h,useCallback as g,useEffect as _,useId as v,useMemo as y,useRef as b,useState as x}from"react";import{cn as S}from"@customafk/react-toolkit/utils";import{jsx as C,jsxs as w}from"react/jsx-runtime";import{useStore as T}from"@tanstack/react-form";const E=h(({label:h,description:E,placeholder:te,tooltip:D,helperText:O,counter:k=!1,orientation:A=`responsive`,showErrorMessage:j=!0,required:M=!1,disabled:N=!1,maxLength:P})=>{let F=v(),I=v(),[L,R]=x(!1),z=b(null),{form:B,state:V,name:H,handleBlur:U,handleChange:W}=u(),G=T(B.store,({isSubmitting:e})=>e),K=N||G,q=V.value?.length??0,J=y(()=>k?P?`${q} / ${P} ký tự`:`${q} ký tự`:``,[q,k,P]),Y=!!P&&q>=P*.8,X=!!P&&q>=P,Z=V.meta.isDirty||V.meta.isTouched,Q=Z&&!V.meta.isValid,ne=M&&V.value===null,re=!!V.meta.errors.length,$=!!V.value&&!K,ie=y(()=>S(`h-4 flex-0 text-nowrap text-end text-xs tabular-nums transition-colors`,X?`font-medium text-danger-strong`:Y?`text-warning-strong`:`text-text-positive-weak`),[X,Y]),ae=g(({target:{value:e}})=>{K||k&&P&&e.length>P||W(e||null)},[K,k,P,W]),oe=g(async()=>{V.value&&(await navigator.clipboard.writeText(V.value),z.current!==null&&window.clearTimeout(z.current),R(!0),z.current=window.setTimeout(()=>R(!1),1500))},[V.value]);return _(()=>()=>{z.current!==null&&window.clearTimeout(z.current)},[]),w(i,{className:`gap-y-4 px-4`,children:[w(t,{orientation:A,"data-invalid":Q,children:[w(r,{children:[w(o,{"aria-required":ne,htmlFor:F,children:[h,D&&C(c,{tooltip:D})]}),C(n,{children:E})]}),w(l,{children:[C(d,{id:F,name:H,value:V.value??``,"aria-invalid":Q,"aria-describedby":I,autoCapitalize:`none`,autoComplete:`off`,autoCorrect:`off`,placeholder:te,disabled:K,className:S(K&&`pointer-events-none bg-muted-muted opacity-60`),onChange:ae,onBlur:U}),$&&C(`button`,{type:`button`,"aria-label":`Sao chép`,className:`absolute inset-e-1 top-2 flex size-4 cursor-pointer items-center justify-center rounded-md outline-none transition-[color,transform] focus-visible:[&>svg]:scale-125 [&>svg]:size-3.5 [&>svg]:transition-transform`,onClick:oe,children:L?C(p,{"aria-hidden":`true`,className:`text-success-strong`}):C(ee,{"aria-hidden":`true`,className:`text-text-positive-weak transition-colors hover:text-text-positive focus-visible:text-primary-strong`})}),G&&C(`div`,{className:`absolute inset-e-2 inset-y-0 top-2.5 text-muted-weak`,children:C(m,{size:14,className:`animate-spin text-primary-strong`})}),!$&&Z&&j&&re&&C(`div`,{className:`absolute inset-e-2 inset-y-0 top-2.5 text-danger-strong`,children:C(f,{size:14})}),w(`div`,{className:`my-1 flex w-full items-start justify-between gap-x-2`,children:[Z&&j?C(a,{id:I,className:`flex-1`,errors:V.meta.errors}):C(`div`,{}),!!k&&C(`p`,{className:ie,children:J})]}),C(e,{isShow:!!O,children:O})]})]}),C(s,{})]})});E.displayName=`TextareaField`;export{E as TextareaField};
2
+ //# sourceMappingURL=textarea-field-BiNmDHgL.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"textarea-field-u2UUwtr_.mjs","names":[],"sources":["../packages/components/features/tanstack-form/components/fields/textarea-field.tsx"],"sourcesContent":["'use client';\n\nimport { memo, useCallback, useEffect, useId, useMemo, useRef, useState } from 'react';\n\nimport { useStore } from '@tanstack/react-form';\n\nimport { BanIcon, CheckIcon, CopyIcon, Loader2Icon } from 'lucide-react';\n\nimport { cn } from '@customafk/react-toolkit/utils';\n\nimport { Textarea } from '@/components/ui/textarea';\n\nimport { useTanStackFieldContext } from '../form-context';\nimport {\n Field,\n FieldContent,\n FieldContentMain,\n FieldDescription,\n FieldError,\n FieldGroup,\n FieldLabel,\n FieldNote,\n FieldSeparator,\n FieldTooltip,\n} from '../ui/field';\n\nimport type { TextareaFieldProps as Props } from '../../types';\n\nexport const TextareaField = memo<Props>(\n ({\n label,\n description,\n placeholder,\n\n tooltip,\n helperText,\n counter = false,\n orientation = 'responsive',\n showErrorMessage = true,\n\n required = false,\n disabled = false,\n maxLength,\n }) => {\n const id = useId();\n const errorId = useId();\n const [copied, setCopied] = useState(false);\n const copyTimeoutRef = useRef<number | null>(null);\n\n const { form, state, name, handleBlur, handleChange } = useTanStackFieldContext<string | null>();\n\n const isSubmitting = useStore(form.store, ({ isSubmitting }) => isSubmitting);\n const isDisabled = disabled || isSubmitting;\n\n const _count = state.value?.length ?? 0;\n\n const _countText = useMemo(() => {\n if (!counter) return '';\n return maxLength ? `${_count} / ${maxLength} ký tự` : `${_count} ký tự`;\n }, [_count, counter, maxLength]);\n\n const _isNearLimit = !!maxLength && _count >= maxLength * 0.8;\n const _isAtLimit = !!maxLength && _count >= maxLength;\n\n const _touched = state.meta.isDirty || state.meta.isTouched;\n const _invalid = _touched && !state.meta.isValid;\n const _isEmpty = required && state.value === null;\n const _hasErrors = !!state.meta.errors.length;\n const _showCopy = !!state.value && !isDisabled;\n\n const _counterClass = useMemo(\n () =>\n cn(\n 'h-4 flex-0 text-nowrap text-end text-xs tabular-nums transition-colors',\n _isAtLimit ? 'font-medium text-danger-strong' : _isNearLimit ? 'text-warning-strong' : 'text-text-positive-weak'\n ),\n [_isAtLimit, _isNearLimit]\n );\n\n const onChange = useCallback<React.ChangeEventHandler<HTMLTextAreaElement>>(\n ({ target: { value } }) => {\n if (isDisabled) return;\n if (counter && maxLength && value.length > maxLength) return;\n handleChange(value || null);\n },\n [isDisabled, counter, maxLength, handleChange]\n );\n\n const onCopy = useCallback(async () => {\n if (!state.value) return;\n await navigator.clipboard.writeText(state.value);\n if (copyTimeoutRef.current !== null) window.clearTimeout(copyTimeoutRef.current);\n setCopied(true);\n copyTimeoutRef.current = window.setTimeout(() => setCopied(false), 1500);\n }, [state.value]);\n\n useEffect(() => {\n return () => {\n if (copyTimeoutRef.current !== null) window.clearTimeout(copyTimeoutRef.current);\n };\n }, []);\n\n return (\n <FieldGroup className=\"gap-y-4 px-4\">\n <Field orientation={orientation} data-invalid={_invalid}>\n <FieldContent>\n <FieldLabel aria-required={_isEmpty} htmlFor={id}>\n {label}\n {tooltip && <FieldTooltip tooltip={tooltip} />}\n </FieldLabel>\n <FieldDescription>{description}</FieldDescription>\n </FieldContent>\n <FieldContentMain>\n <Textarea\n id={id}\n name={name}\n value={state.value ?? ''}\n aria-invalid={_invalid}\n aria-describedby={errorId}\n autoCapitalize=\"none\"\n autoComplete=\"off\"\n autoCorrect=\"off\"\n placeholder={placeholder}\n disabled={isDisabled}\n className={cn(isDisabled && 'pointer-events-none bg-muted-muted opacity-60')}\n onChange={onChange}\n onBlur={handleBlur}\n />\n {_showCopy && (\n <button\n type=\"button\"\n aria-label=\"Sao chép\"\n className=\"absolute inset-e-1 top-2 flex size-4 cursor-pointer items-center justify-center rounded-md outline-none transition-[color,transform] focus-visible:[&>svg]:scale-125 [&>svg]:size-3.5 [&>svg]:transition-transform\"\n onClick={onCopy}\n >\n {copied ? (\n <CheckIcon aria-hidden=\"true\" className=\"text-success-strong\" />\n ) : (\n <CopyIcon\n aria-hidden=\"true\"\n className=\"text-text-positive-weak transition-colors hover:text-text-positive focus-visible:text-primary-strong\"\n />\n )}\n </button>\n )}\n {isSubmitting && (\n <div className=\"absolute inset-e-2 inset-y-0 top-2.5 text-muted-weak\">\n <Loader2Icon size={14} className=\"animate-spin text-primary-strong\" />\n </div>\n )}\n {!_showCopy && _touched && showErrorMessage && _hasErrors && (\n <div className=\"absolute inset-e-2 inset-y-0 top-2.5 text-danger-strong\">\n <BanIcon size={14} />\n </div>\n )}\n <div className=\"my-1 flex w-full items-start justify-between gap-x-2\">\n {_touched && showErrorMessage ? <FieldError id={errorId} className=\"flex-1\" errors={state.meta.errors} /> : <div />}\n {!!counter && <p className={_counterClass}>{_countText}</p>}\n </div>\n <FieldNote isShow={!!helperText}>{helperText}</FieldNote>\n </FieldContentMain>\n </Field>\n <FieldSeparator />\n </FieldGroup>\n );\n }\n);\n\nTextareaField.displayName = 'TextareaField';\n"],"mappings":"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"}
1
+ {"version":3,"file":"textarea-field-BiNmDHgL.mjs","names":[],"sources":["../packages/components/features/tanstack-form/components/fields/textarea-field.tsx"],"sourcesContent":["'use client';\n\nimport { memo, useCallback, useEffect, useId, useMemo, useRef, useState } from 'react';\n\nimport { useStore } from '@tanstack/react-form';\n\nimport { BanIcon, CheckIcon, CopyIcon, Loader2Icon } from 'lucide-react';\n\nimport { cn } from '@customafk/react-toolkit/utils';\n\nimport { Textarea } from '@/components/ui/textarea';\n\nimport { useTanStackFieldContext } from '../form-context';\nimport {\n Field,\n FieldContent,\n FieldContentMain,\n FieldDescription,\n FieldError,\n FieldGroup,\n FieldLabel,\n FieldNote,\n FieldSeparator,\n FieldTooltip,\n} from '../ui/field';\n\nimport type { TextareaFieldProps as Props } from '../../types';\n\nexport const TextareaField = memo<Props>(\n ({\n label,\n description,\n placeholder,\n\n tooltip,\n helperText,\n counter = false,\n orientation = 'responsive',\n showErrorMessage = true,\n\n required = false,\n disabled = false,\n maxLength,\n }) => {\n const id = useId();\n const errorId = useId();\n const [copied, setCopied] = useState(false);\n const copyTimeoutRef = useRef<number | null>(null);\n\n const { form, state, name, handleBlur, handleChange } = useTanStackFieldContext<string | null>();\n\n const isSubmitting = useStore(form.store, ({ isSubmitting }) => isSubmitting);\n const isDisabled = disabled || isSubmitting;\n\n const _count = state.value?.length ?? 0;\n\n const _countText = useMemo(() => {\n if (!counter) return '';\n return maxLength ? `${_count} / ${maxLength} ký tự` : `${_count} ký tự`;\n }, [_count, counter, maxLength]);\n\n const _isNearLimit = !!maxLength && _count >= maxLength * 0.8;\n const _isAtLimit = !!maxLength && _count >= maxLength;\n\n const _touched = state.meta.isDirty || state.meta.isTouched;\n const _invalid = _touched && !state.meta.isValid;\n const _isEmpty = required && state.value === null;\n const _hasErrors = !!state.meta.errors.length;\n const _showCopy = !!state.value && !isDisabled;\n\n const _counterClass = useMemo(\n () =>\n cn(\n 'h-4 flex-0 text-nowrap text-end text-xs tabular-nums transition-colors',\n _isAtLimit ? 'font-medium text-danger-strong' : _isNearLimit ? 'text-warning-strong' : 'text-text-positive-weak'\n ),\n [_isAtLimit, _isNearLimit]\n );\n\n const onChange = useCallback<React.ChangeEventHandler<HTMLTextAreaElement>>(\n ({ target: { value } }) => {\n if (isDisabled) return;\n if (counter && maxLength && value.length > maxLength) return;\n handleChange(value || null);\n },\n [isDisabled, counter, maxLength, handleChange]\n );\n\n const onCopy = useCallback(async () => {\n if (!state.value) return;\n await navigator.clipboard.writeText(state.value);\n if (copyTimeoutRef.current !== null) window.clearTimeout(copyTimeoutRef.current);\n setCopied(true);\n copyTimeoutRef.current = window.setTimeout(() => setCopied(false), 1500);\n }, [state.value]);\n\n useEffect(() => {\n return () => {\n if (copyTimeoutRef.current !== null) window.clearTimeout(copyTimeoutRef.current);\n };\n }, []);\n\n return (\n <FieldGroup className=\"gap-y-4 px-4\">\n <Field orientation={orientation} data-invalid={_invalid}>\n <FieldContent>\n <FieldLabel aria-required={_isEmpty} htmlFor={id}>\n {label}\n {tooltip && <FieldTooltip tooltip={tooltip} />}\n </FieldLabel>\n <FieldDescription>{description}</FieldDescription>\n </FieldContent>\n <FieldContentMain>\n <Textarea\n id={id}\n name={name}\n value={state.value ?? ''}\n aria-invalid={_invalid}\n aria-describedby={errorId}\n autoCapitalize=\"none\"\n autoComplete=\"off\"\n autoCorrect=\"off\"\n placeholder={placeholder}\n disabled={isDisabled}\n className={cn(isDisabled && 'pointer-events-none bg-muted-muted opacity-60')}\n onChange={onChange}\n onBlur={handleBlur}\n />\n {_showCopy && (\n <button\n type=\"button\"\n aria-label=\"Sao chép\"\n className=\"absolute inset-e-1 top-2 flex size-4 cursor-pointer items-center justify-center rounded-md outline-none transition-[color,transform] focus-visible:[&>svg]:scale-125 [&>svg]:size-3.5 [&>svg]:transition-transform\"\n onClick={onCopy}\n >\n {copied ? (\n <CheckIcon aria-hidden=\"true\" className=\"text-success-strong\" />\n ) : (\n <CopyIcon\n aria-hidden=\"true\"\n className=\"text-text-positive-weak transition-colors hover:text-text-positive focus-visible:text-primary-strong\"\n />\n )}\n </button>\n )}\n {isSubmitting && (\n <div className=\"absolute inset-e-2 inset-y-0 top-2.5 text-muted-weak\">\n <Loader2Icon size={14} className=\"animate-spin text-primary-strong\" />\n </div>\n )}\n {!_showCopy && _touched && showErrorMessage && _hasErrors && (\n <div className=\"absolute inset-e-2 inset-y-0 top-2.5 text-danger-strong\">\n <BanIcon size={14} />\n </div>\n )}\n <div className=\"my-1 flex w-full items-start justify-between gap-x-2\">\n {_touched && showErrorMessage ? <FieldError id={errorId} className=\"flex-1\" errors={state.meta.errors} /> : <div />}\n {!!counter && <p className={_counterClass}>{_countText}</p>}\n </div>\n <FieldNote isShow={!!helperText}>{helperText}</FieldNote>\n </FieldContentMain>\n </Field>\n <FieldSeparator />\n </FieldGroup>\n );\n }\n);\n\nTextareaField.displayName = 'TextareaField';\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ const e=require("./tanstack-form-BiOihtxs.cjs"),t=require("./ui/textarea.cjs");let n=require("lucide-react"),r=require("react"),i=require("@customafk/react-toolkit/utils"),a=require("react/jsx-runtime"),o=require("@tanstack/react-form");const s=(0,r.memo)(({label:s,description:c,placeholder:l,tooltip:u,helperText:d,counter:f=!1,orientation:p=`responsive`,showErrorMessage:m=!0,required:h=!1,disabled:g=!1,maxLength:_})=>{let v=(0,r.useId)(),y=(0,r.useId)(),[b,x]=(0,r.useState)(!1),S=(0,r.useRef)(null),{form:C,state:w,name:T,handleBlur:E,handleChange:D}=e.rt(),O=(0,o.useStore)(C.store,({isSubmitting:e})=>e),k=g||O,A=w.value?.length??0,j=(0,r.useMemo)(()=>f?_?`${A} / ${_} ký tự`:`${A} ký tự`:``,[A,f,_]),M=!!_&&A>=_*.8,N=!!_&&A>=_,P=w.meta.isDirty||w.meta.isTouched,F=P&&!w.meta.isValid,I=h&&w.value===null,L=!!w.meta.errors.length,R=!!w.value&&!k,z=(0,r.useMemo)(()=>(0,i.cn)(`h-4 flex-0 text-nowrap text-end text-xs tabular-nums transition-colors`,N?`font-medium text-danger-strong`:M?`text-warning-strong`:`text-text-positive-weak`),[N,M]),B=(0,r.useCallback)(({target:{value:e}})=>{k||f&&_&&e.length>_||D(e||null)},[k,f,_,D]),V=(0,r.useCallback)(async()=>{w.value&&(await navigator.clipboard.writeText(w.value),S.current!==null&&window.clearTimeout(S.current),x(!0),S.current=window.setTimeout(()=>x(!1),1500))},[w.value]);return(0,r.useEffect)(()=>()=>{S.current!==null&&window.clearTimeout(S.current)},[]),(0,a.jsxs)(e.X,{className:`gap-y-4 px-4`,children:[(0,a.jsxs)(e.G,{orientation:p,"data-invalid":F,children:[(0,a.jsxs)(e.K,{children:[(0,a.jsxs)(e.Z,{"aria-required":I,htmlFor:v,children:[s,u&&(0,a.jsx)(e.nt,{tooltip:u})]}),(0,a.jsx)(e.J,{children:c})]}),(0,a.jsxs)(e.q,{children:[(0,a.jsx)(t.Textarea,{id:v,name:T,value:w.value??``,"aria-invalid":F,"aria-describedby":y,autoCapitalize:`none`,autoComplete:`off`,autoCorrect:`off`,placeholder:l,disabled:k,className:(0,i.cn)(k&&`pointer-events-none bg-muted-muted opacity-60`),onChange:B,onBlur:E}),R&&(0,a.jsx)(`button`,{type:`button`,"aria-label":`Sao chép`,className:`absolute inset-e-1 top-2 flex size-4 cursor-pointer items-center justify-center rounded-md outline-none transition-[color,transform] focus-visible:[&>svg]:scale-125 [&>svg]:size-3.5 [&>svg]:transition-transform`,onClick:V,children:b?(0,a.jsx)(n.CheckIcon,{"aria-hidden":`true`,className:`text-success-strong`}):(0,a.jsx)(n.CopyIcon,{"aria-hidden":`true`,className:`text-text-positive-weak transition-colors hover:text-text-positive focus-visible:text-primary-strong`})}),O&&(0,a.jsx)(`div`,{className:`absolute inset-e-2 inset-y-0 top-2.5 text-muted-weak`,children:(0,a.jsx)(n.Loader2Icon,{size:14,className:`animate-spin text-primary-strong`})}),!R&&P&&m&&L&&(0,a.jsx)(`div`,{className:`absolute inset-e-2 inset-y-0 top-2.5 text-danger-strong`,children:(0,a.jsx)(n.BanIcon,{size:14})}),(0,a.jsxs)(`div`,{className:`my-1 flex w-full items-start justify-between gap-x-2`,children:[P&&m?(0,a.jsx)(e.Y,{id:y,className:`flex-1`,errors:w.meta.errors}):(0,a.jsx)(`div`,{}),!!f&&(0,a.jsx)(`p`,{className:z,children:j})]}),(0,a.jsx)(e.$,{isShow:!!d,children:d})]})]}),(0,a.jsx)(e.et,{})]})});s.displayName=`TextareaField`,exports.TextareaField=s;
2
+ //# sourceMappingURL=textarea-field-CRf0M2Eb.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"textarea-field-B38SnNv4.cjs","names":["useTanStackFieldContext","FieldGroup","Field","FieldContent","FieldLabel","FieldTooltip","FieldDescription","FieldContentMain","Textarea","CheckIcon","CopyIcon","Loader2Icon","BanIcon","FieldError","FieldNote","FieldSeparator"],"sources":["../packages/components/features/tanstack-form/components/fields/textarea-field.tsx"],"sourcesContent":["'use client';\n\nimport { memo, useCallback, useEffect, useId, useMemo, useRef, useState } from 'react';\n\nimport { useStore } from '@tanstack/react-form';\n\nimport { BanIcon, CheckIcon, CopyIcon, Loader2Icon } from 'lucide-react';\n\nimport { cn } from '@customafk/react-toolkit/utils';\n\nimport { Textarea } from '@/components/ui/textarea';\n\nimport { useTanStackFieldContext } from '../form-context';\nimport {\n Field,\n FieldContent,\n FieldContentMain,\n FieldDescription,\n FieldError,\n FieldGroup,\n FieldLabel,\n FieldNote,\n FieldSeparator,\n FieldTooltip,\n} from '../ui/field';\n\nimport type { TextareaFieldProps as Props } from '../../types';\n\nexport const TextareaField = memo<Props>(\n ({\n label,\n description,\n placeholder,\n\n tooltip,\n helperText,\n counter = false,\n orientation = 'responsive',\n showErrorMessage = true,\n\n required = false,\n disabled = false,\n maxLength,\n }) => {\n const id = useId();\n const errorId = useId();\n const [copied, setCopied] = useState(false);\n const copyTimeoutRef = useRef<number | null>(null);\n\n const { form, state, name, handleBlur, handleChange } = useTanStackFieldContext<string | null>();\n\n const isSubmitting = useStore(form.store, ({ isSubmitting }) => isSubmitting);\n const isDisabled = disabled || isSubmitting;\n\n const _count = state.value?.length ?? 0;\n\n const _countText = useMemo(() => {\n if (!counter) return '';\n return maxLength ? `${_count} / ${maxLength} ký tự` : `${_count} ký tự`;\n }, [_count, counter, maxLength]);\n\n const _isNearLimit = !!maxLength && _count >= maxLength * 0.8;\n const _isAtLimit = !!maxLength && _count >= maxLength;\n\n const _touched = state.meta.isDirty || state.meta.isTouched;\n const _invalid = _touched && !state.meta.isValid;\n const _isEmpty = required && state.value === null;\n const _hasErrors = !!state.meta.errors.length;\n const _showCopy = !!state.value && !isDisabled;\n\n const _counterClass = useMemo(\n () =>\n cn(\n 'h-4 flex-0 text-nowrap text-end text-xs tabular-nums transition-colors',\n _isAtLimit ? 'font-medium text-danger-strong' : _isNearLimit ? 'text-warning-strong' : 'text-text-positive-weak'\n ),\n [_isAtLimit, _isNearLimit]\n );\n\n const onChange = useCallback<React.ChangeEventHandler<HTMLTextAreaElement>>(\n ({ target: { value } }) => {\n if (isDisabled) return;\n if (counter && maxLength && value.length > maxLength) return;\n handleChange(value || null);\n },\n [isDisabled, counter, maxLength, handleChange]\n );\n\n const onCopy = useCallback(async () => {\n if (!state.value) return;\n await navigator.clipboard.writeText(state.value);\n if (copyTimeoutRef.current !== null) window.clearTimeout(copyTimeoutRef.current);\n setCopied(true);\n copyTimeoutRef.current = window.setTimeout(() => setCopied(false), 1500);\n }, [state.value]);\n\n useEffect(() => {\n return () => {\n if (copyTimeoutRef.current !== null) window.clearTimeout(copyTimeoutRef.current);\n };\n }, []);\n\n return (\n <FieldGroup className=\"gap-y-4 px-4\">\n <Field orientation={orientation} data-invalid={_invalid}>\n <FieldContent>\n <FieldLabel aria-required={_isEmpty} htmlFor={id}>\n {label}\n {tooltip && <FieldTooltip tooltip={tooltip} />}\n </FieldLabel>\n <FieldDescription>{description}</FieldDescription>\n </FieldContent>\n <FieldContentMain>\n <Textarea\n id={id}\n name={name}\n value={state.value ?? ''}\n aria-invalid={_invalid}\n aria-describedby={errorId}\n autoCapitalize=\"none\"\n autoComplete=\"off\"\n autoCorrect=\"off\"\n placeholder={placeholder}\n disabled={isDisabled}\n className={cn(isDisabled && 'pointer-events-none bg-muted-muted opacity-60')}\n onChange={onChange}\n onBlur={handleBlur}\n />\n {_showCopy && (\n <button\n type=\"button\"\n aria-label=\"Sao chép\"\n className=\"absolute inset-e-1 top-2 flex size-4 cursor-pointer items-center justify-center rounded-md outline-none transition-[color,transform] focus-visible:[&>svg]:scale-125 [&>svg]:size-3.5 [&>svg]:transition-transform\"\n onClick={onCopy}\n >\n {copied ? (\n <CheckIcon aria-hidden=\"true\" className=\"text-success-strong\" />\n ) : (\n <CopyIcon\n aria-hidden=\"true\"\n className=\"text-text-positive-weak transition-colors hover:text-text-positive focus-visible:text-primary-strong\"\n />\n )}\n </button>\n )}\n {isSubmitting && (\n <div className=\"absolute inset-e-2 inset-y-0 top-2.5 text-muted-weak\">\n <Loader2Icon size={14} className=\"animate-spin text-primary-strong\" />\n </div>\n )}\n {!_showCopy && _touched && showErrorMessage && _hasErrors && (\n <div className=\"absolute inset-e-2 inset-y-0 top-2.5 text-danger-strong\">\n <BanIcon size={14} />\n </div>\n )}\n <div className=\"my-1 flex w-full items-start justify-between gap-x-2\">\n {_touched && showErrorMessage ? <FieldError id={errorId} className=\"flex-1\" errors={state.meta.errors} /> : <div />}\n {!!counter && <p className={_counterClass}>{_countText}</p>}\n </div>\n <FieldNote isShow={!!helperText}>{helperText}</FieldNote>\n </FieldContentMain>\n </Field>\n <FieldSeparator />\n </FieldGroup>\n );\n }\n);\n\nTextareaField.displayName = 'TextareaField';\n"],"mappings":"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"}
1
+ {"version":3,"file":"textarea-field-CRf0M2Eb.cjs","names":["useTanStackFieldContext","FieldGroup","Field","FieldContent","FieldLabel","FieldTooltip","FieldDescription","FieldContentMain","Textarea","CheckIcon","CopyIcon","Loader2Icon","BanIcon","FieldError","FieldNote","FieldSeparator"],"sources":["../packages/components/features/tanstack-form/components/fields/textarea-field.tsx"],"sourcesContent":["'use client';\n\nimport { memo, useCallback, useEffect, useId, useMemo, useRef, useState } from 'react';\n\nimport { useStore } from '@tanstack/react-form';\n\nimport { BanIcon, CheckIcon, CopyIcon, Loader2Icon } from 'lucide-react';\n\nimport { cn } from '@customafk/react-toolkit/utils';\n\nimport { Textarea } from '@/components/ui/textarea';\n\nimport { useTanStackFieldContext } from '../form-context';\nimport {\n Field,\n FieldContent,\n FieldContentMain,\n FieldDescription,\n FieldError,\n FieldGroup,\n FieldLabel,\n FieldNote,\n FieldSeparator,\n FieldTooltip,\n} from '../ui/field';\n\nimport type { TextareaFieldProps as Props } from '../../types';\n\nexport const TextareaField = memo<Props>(\n ({\n label,\n description,\n placeholder,\n\n tooltip,\n helperText,\n counter = false,\n orientation = 'responsive',\n showErrorMessage = true,\n\n required = false,\n disabled = false,\n maxLength,\n }) => {\n const id = useId();\n const errorId = useId();\n const [copied, setCopied] = useState(false);\n const copyTimeoutRef = useRef<number | null>(null);\n\n const { form, state, name, handleBlur, handleChange } = useTanStackFieldContext<string | null>();\n\n const isSubmitting = useStore(form.store, ({ isSubmitting }) => isSubmitting);\n const isDisabled = disabled || isSubmitting;\n\n const _count = state.value?.length ?? 0;\n\n const _countText = useMemo(() => {\n if (!counter) return '';\n return maxLength ? `${_count} / ${maxLength} ký tự` : `${_count} ký tự`;\n }, [_count, counter, maxLength]);\n\n const _isNearLimit = !!maxLength && _count >= maxLength * 0.8;\n const _isAtLimit = !!maxLength && _count >= maxLength;\n\n const _touched = state.meta.isDirty || state.meta.isTouched;\n const _invalid = _touched && !state.meta.isValid;\n const _isEmpty = required && state.value === null;\n const _hasErrors = !!state.meta.errors.length;\n const _showCopy = !!state.value && !isDisabled;\n\n const _counterClass = useMemo(\n () =>\n cn(\n 'h-4 flex-0 text-nowrap text-end text-xs tabular-nums transition-colors',\n _isAtLimit ? 'font-medium text-danger-strong' : _isNearLimit ? 'text-warning-strong' : 'text-text-positive-weak'\n ),\n [_isAtLimit, _isNearLimit]\n );\n\n const onChange = useCallback<React.ChangeEventHandler<HTMLTextAreaElement>>(\n ({ target: { value } }) => {\n if (isDisabled) return;\n if (counter && maxLength && value.length > maxLength) return;\n handleChange(value || null);\n },\n [isDisabled, counter, maxLength, handleChange]\n );\n\n const onCopy = useCallback(async () => {\n if (!state.value) return;\n await navigator.clipboard.writeText(state.value);\n if (copyTimeoutRef.current !== null) window.clearTimeout(copyTimeoutRef.current);\n setCopied(true);\n copyTimeoutRef.current = window.setTimeout(() => setCopied(false), 1500);\n }, [state.value]);\n\n useEffect(() => {\n return () => {\n if (copyTimeoutRef.current !== null) window.clearTimeout(copyTimeoutRef.current);\n };\n }, []);\n\n return (\n <FieldGroup className=\"gap-y-4 px-4\">\n <Field orientation={orientation} data-invalid={_invalid}>\n <FieldContent>\n <FieldLabel aria-required={_isEmpty} htmlFor={id}>\n {label}\n {tooltip && <FieldTooltip tooltip={tooltip} />}\n </FieldLabel>\n <FieldDescription>{description}</FieldDescription>\n </FieldContent>\n <FieldContentMain>\n <Textarea\n id={id}\n name={name}\n value={state.value ?? ''}\n aria-invalid={_invalid}\n aria-describedby={errorId}\n autoCapitalize=\"none\"\n autoComplete=\"off\"\n autoCorrect=\"off\"\n placeholder={placeholder}\n disabled={isDisabled}\n className={cn(isDisabled && 'pointer-events-none bg-muted-muted opacity-60')}\n onChange={onChange}\n onBlur={handleBlur}\n />\n {_showCopy && (\n <button\n type=\"button\"\n aria-label=\"Sao chép\"\n className=\"absolute inset-e-1 top-2 flex size-4 cursor-pointer items-center justify-center rounded-md outline-none transition-[color,transform] focus-visible:[&>svg]:scale-125 [&>svg]:size-3.5 [&>svg]:transition-transform\"\n onClick={onCopy}\n >\n {copied ? (\n <CheckIcon aria-hidden=\"true\" className=\"text-success-strong\" />\n ) : (\n <CopyIcon\n aria-hidden=\"true\"\n className=\"text-text-positive-weak transition-colors hover:text-text-positive focus-visible:text-primary-strong\"\n />\n )}\n </button>\n )}\n {isSubmitting && (\n <div className=\"absolute inset-e-2 inset-y-0 top-2.5 text-muted-weak\">\n <Loader2Icon size={14} className=\"animate-spin text-primary-strong\" />\n </div>\n )}\n {!_showCopy && _touched && showErrorMessage && _hasErrors && (\n <div className=\"absolute inset-e-2 inset-y-0 top-2.5 text-danger-strong\">\n <BanIcon size={14} />\n </div>\n )}\n <div className=\"my-1 flex w-full items-start justify-between gap-x-2\">\n {_touched && showErrorMessage ? <FieldError id={errorId} className=\"flex-1\" errors={state.meta.errors} /> : <div />}\n {!!counter && <p className={_counterClass}>{_countText}</p>}\n </div>\n <FieldNote isShow={!!helperText}>{helperText}</FieldNote>\n </FieldContentMain>\n </Field>\n <FieldSeparator />\n </FieldGroup>\n );\n }\n);\n\nTextareaField.displayName = 'TextareaField';\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ const e=require("./tanstack-form-BiOihtxs.cjs");let t=require("react/jsx-runtime");const n=({title:n,description:r,helperText:i})=>(0,t.jsxs)(e.X,{className:`gap-y-4 px-4`,children:[(0,t.jsxs)(e.G,{className:`gap-0`,children:[(0,t.jsxs)(e.K,{children:[(0,t.jsx)(e.Q,{className:`mb-1`,children:n}),(0,t.jsx)(e.J,{children:r})]}),(0,t.jsx)(e.$,{isShow:!!i,children:i})]}),(0,t.jsx)(e.et,{})]});exports.TanStackTitleField=n;
2
+ //# sourceMappingURL=title-field-B9LLoqIi.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"title-field-B2hM3S_S.cjs","names":["FieldGroup","Field","FieldContent","FieldLegend","FieldDescription","FieldNote","FieldSeparator"],"sources":["../packages/components/features/tanstack-form/components/forms/title-field.tsx"],"sourcesContent":["import { Field, FieldContent, FieldDescription, FieldGroup, FieldLegend, FieldNote, FieldSeparator } from '../ui/field';\n\n/**\n * Renders a standalone section title with an optional description and helper note, followed by a separator.\n *\n * @example\n * import { TanStackTitleField } from '@customafk/lunas-ui/features/tanstack-form';\n *\n * <TanStackTitleField\n * title=\"Billing Address\"\n * description=\"Provide the address associated with your payment method.\"\n * helperText=\"Must match your bank records.\"\n * />\n */\nexport const TanStackTitleField: React.FC<{\n /** The heading text rendered as a legend element. */\n title: string;\n /** Optional supplementary text displayed beneath the title. */\n description?: string;\n /** Optional helper note shown below the description area. */\n helperText?: string;\n}> = ({ title, description, helperText }) => {\n return (\n <FieldGroup className=\"gap-y-4 px-4\">\n <Field className=\"gap-0\">\n <FieldContent>\n <FieldLegend className=\"mb-1\">{title}</FieldLegend>\n <FieldDescription>{description}</FieldDescription>\n </FieldContent>\n <FieldNote isShow={!!helperText}>{helperText}</FieldNote>\n </Field>\n <FieldSeparator />\n </FieldGroup>\n );\n};\n"],"mappings":"2EAcA,MAAa,GAOP,CAAE,QAAO,cAAa,iBAExB,EAAA,EAAA,KAAA,CAACA,EAAAA,WAAD,CAAY,UAAU,eAAtB,SAAA,EACE,EAAA,EAAA,KAAA,CAACC,EAAAA,MAAD,CAAO,UAAU,QAAjB,SAAA,EACE,EAAA,EAAA,KAAA,CAACC,EAAAA,aAAD,CAAA,SAAA,EACE,EAAA,EAAA,IAAA,CAACC,EAAAA,YAAD,CAAa,UAAU,OAAQ,SAAA,CAAmB,CAAA,GAClD,EAAA,EAAA,IAAA,CAACC,EAAAA,iBAAD,CAAA,SAAmB,CAA8B,CAAA,CACrC,CAAA,CAAA,GACd,EAAA,EAAA,IAAA,CAACC,EAAAA,UAAD,CAAW,OAAQ,CAAC,CAAC,EAAa,SAAA,CAAsB,CAAA,CACnD,CACP,CAAA,GAAA,EAAA,EAAA,IAAA,CAACC,EAAAA,eAAD,CAAiB,CAAA,CACP"}
1
+ {"version":3,"file":"title-field-B9LLoqIi.cjs","names":["FieldGroup","Field","FieldContent","FieldLegend","FieldDescription","FieldNote","FieldSeparator"],"sources":["../packages/components/features/tanstack-form/components/forms/title-field.tsx"],"sourcesContent":["import { Field, FieldContent, FieldDescription, FieldGroup, FieldLegend, FieldNote, FieldSeparator } from '../ui/field';\n\n/**\n * Renders a standalone section title with an optional description and helper note, followed by a separator.\n *\n * @example\n * import { TanStackTitleField } from '@customafk/lunas-ui/features/tanstack-form';\n *\n * <TanStackTitleField\n * title=\"Billing Address\"\n * description=\"Provide the address associated with your payment method.\"\n * helperText=\"Must match your bank records.\"\n * />\n */\nexport const TanStackTitleField: React.FC<{\n /** The heading text rendered as a legend element. */\n title: string;\n /** Optional supplementary text displayed beneath the title. */\n description?: string;\n /** Optional helper note shown below the description area. */\n helperText?: string;\n}> = ({ title, description, helperText }) => {\n return (\n <FieldGroup className=\"gap-y-4 px-4\">\n <Field className=\"gap-0\">\n <FieldContent>\n <FieldLegend className=\"mb-1\">{title}</FieldLegend>\n <FieldDescription>{description}</FieldDescription>\n </FieldContent>\n <FieldNote isShow={!!helperText}>{helperText}</FieldNote>\n </Field>\n <FieldSeparator />\n </FieldGroup>\n );\n};\n"],"mappings":"mFAcA,MAAa,GAOP,CAAE,QAAO,cAAa,iBAExB,EAAA,EAAA,KAAA,CAACA,EAAAA,EAAD,CAAY,UAAU,eAAtB,SAAA,EACE,EAAA,EAAA,KAAA,CAACC,EAAAA,EAAD,CAAO,UAAU,QAAjB,SAAA,EACE,EAAA,EAAA,KAAA,CAACC,EAAAA,EAAD,CAAA,SAAA,EACE,EAAA,EAAA,IAAA,CAACC,EAAAA,EAAD,CAAa,UAAU,OAAQ,SAAA,CAAmB,CAAA,GAClD,EAAA,EAAA,IAAA,CAACC,EAAAA,EAAD,CAAA,SAAmB,CAA8B,CAAA,CACrC,CAAA,CAAA,GACd,EAAA,EAAA,IAAA,CAACC,EAAAA,EAAD,CAAW,OAAQ,CAAC,CAAC,EAAa,SAAA,CAAsB,CAAA,CACnD,CACP,CAAA,GAAA,EAAA,EAAA,IAAA,CAACC,EAAAA,GAAD,CAAiB,CAAA,CACP"}
@@ -0,0 +1,2 @@
1
+ import{$ as e,G as t,J as n,K as r,Q as i,X as a,et as o}from"./tanstack-form-Do6xL2kv.mjs";import{jsx as s,jsxs as c}from"react/jsx-runtime";const l=({title:l,description:u,helperText:d})=>c(a,{className:`gap-y-4 px-4`,children:[c(t,{className:`gap-0`,children:[c(r,{children:[s(i,{className:`mb-1`,children:l}),s(n,{children:u})]}),s(e,{isShow:!!d,children:d})]}),s(o,{})]});export{l as TanStackTitleField};
2
+ //# sourceMappingURL=title-field-C4BmSDR2.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"title-field-oAqHRw59.mjs","names":[],"sources":["../packages/components/features/tanstack-form/components/forms/title-field.tsx"],"sourcesContent":["import { Field, FieldContent, FieldDescription, FieldGroup, FieldLegend, FieldNote, FieldSeparator } from '../ui/field';\n\n/**\n * Renders a standalone section title with an optional description and helper note, followed by a separator.\n *\n * @example\n * import { TanStackTitleField } from '@customafk/lunas-ui/features/tanstack-form';\n *\n * <TanStackTitleField\n * title=\"Billing Address\"\n * description=\"Provide the address associated with your payment method.\"\n * helperText=\"Must match your bank records.\"\n * />\n */\nexport const TanStackTitleField: React.FC<{\n /** The heading text rendered as a legend element. */\n title: string;\n /** Optional supplementary text displayed beneath the title. */\n description?: string;\n /** Optional helper note shown below the description area. */\n helperText?: string;\n}> = ({ title, description, helperText }) => {\n return (\n <FieldGroup className=\"gap-y-4 px-4\">\n <Field className=\"gap-0\">\n <FieldContent>\n <FieldLegend className=\"mb-1\">{title}</FieldLegend>\n <FieldDescription>{description}</FieldDescription>\n </FieldContent>\n <FieldNote isShow={!!helperText}>{helperText}</FieldNote>\n </Field>\n <FieldSeparator />\n </FieldGroup>\n );\n};\n"],"mappings":"2MAcA,MAAa,GAOP,CAAE,QAAO,cAAa,gBAExB,EAAC,EAAD,CAAY,UAAU,eAAtB,SAAA,CACE,EAAC,EAAD,CAAO,UAAU,QAAjB,SAAA,CACE,EAAC,EAAD,CAAA,SAAA,CACE,EAAC,EAAD,CAAa,UAAU,OAAQ,SAAA,CAAmB,CAAA,EAClD,EAAC,EAAD,CAAA,SAAmB,CAA8B,CAAA,CACrC,CAAA,CAAA,EACd,EAAC,EAAD,CAAW,OAAQ,CAAC,CAAC,EAAa,SAAA,CAAsB,CAAA,CACnD,CACP,CAAA,EAAA,EAAC,EAAD,CAAiB,CAAA,CACP"}
1
+ {"version":3,"file":"title-field-C4BmSDR2.mjs","names":[],"sources":["../packages/components/features/tanstack-form/components/forms/title-field.tsx"],"sourcesContent":["import { Field, FieldContent, FieldDescription, FieldGroup, FieldLegend, FieldNote, FieldSeparator } from '../ui/field';\n\n/**\n * Renders a standalone section title with an optional description and helper note, followed by a separator.\n *\n * @example\n * import { TanStackTitleField } from '@customafk/lunas-ui/features/tanstack-form';\n *\n * <TanStackTitleField\n * title=\"Billing Address\"\n * description=\"Provide the address associated with your payment method.\"\n * helperText=\"Must match your bank records.\"\n * />\n */\nexport const TanStackTitleField: React.FC<{\n /** The heading text rendered as a legend element. */\n title: string;\n /** Optional supplementary text displayed beneath the title. */\n description?: string;\n /** Optional helper note shown below the description area. */\n helperText?: string;\n}> = ({ title, description, helperText }) => {\n return (\n <FieldGroup className=\"gap-y-4 px-4\">\n <Field className=\"gap-0\">\n <FieldContent>\n <FieldLegend className=\"mb-1\">{title}</FieldLegend>\n <FieldDescription>{description}</FieldDescription>\n </FieldContent>\n <FieldNote isShow={!!helperText}>{helperText}</FieldNote>\n </Field>\n <FieldSeparator />\n </FieldGroup>\n );\n};\n"],"mappings":"8IAcA,MAAa,GAOP,CAAE,QAAO,cAAa,gBAExB,EAAC,EAAD,CAAY,UAAU,eAAtB,SAAA,CACE,EAAC,EAAD,CAAO,UAAU,QAAjB,SAAA,CACE,EAAC,EAAD,CAAA,SAAA,CACE,EAAC,EAAD,CAAa,UAAU,OAAQ,SAAA,CAAmB,CAAA,EAClD,EAAC,EAAD,CAAA,SAAmB,CAA8B,CAAA,CACrC,CAAA,CAAA,EACd,EAAC,EAAD,CAAW,OAAQ,CAAC,CAAC,EAAa,SAAA,CAAsB,CAAA,CACnD,CACP,CAAA,EAAA,EAAC,EAAD,CAAiB,CAAA,CACP"}
@@ -1,4 +1,4 @@
1
- const e=require("./tables-BqZ4Zs6e.cjs"),t=require("./ui/input.cjs");let n=require("lucide-react"),r=require("react"),i=require("@customafk/react-toolkit/utils"),a=require("react/jsx-runtime"),o=require("@customafk/react-toolkit/hooks/useDebounceCallback");function s(e){if(e==null)return``;if(typeof e==`number`)return String(e);if(typeof e==`boolean`)return e?`true`:`false`;let t=String(e);return t.includes(`,`)||t.includes(`"`)||t.includes(`
1
+ const e=require("./ui/input.cjs"),t=require("./tables-DdLEj1dI.cjs");let n=require("lucide-react"),r=require("react"),i=require("@customafk/react-toolkit/utils"),a=require("react/jsx-runtime"),o=require("@customafk/react-toolkit/hooks/useDebounceCallback");function s(e){if(e==null)return``;if(typeof e==`number`)return String(e);if(typeof e==`boolean`)return e?`true`:`false`;let t=String(e);return t.includes(`,`)||t.includes(`"`)||t.includes(`
2
2
  `)||t.includes(`\r`)?`"${t.replace(/"/g,`""`)}"`:t}function c(e){if(e.length===0)return``;let t=e[0].map(e=>s(e.label)),n=e.map(e=>e.map(e=>s(e.value)).join(`,`));return[t.join(`,`),...n].join(`
3
- `)}function l(e,t){let n=c(e);if(!n)return;let r=new Blob([n],{type:`text/csv;charset=utf-8;`}),i=URL.createObjectURL(r),a=document.createElement(`a`);a.href=i,a.download=`${t}.csv`,a.click(),URL.revokeObjectURL(i)}const u=({onSearch:e,onChange:r,...i})=>{let s=(0,o.useDebounceCallback)(t=>{e?.(t)},500);return(0,a.jsxs)(`div`,{className:`relative w-full max-w-80 flex-1`,children:[(0,a.jsx)(t.Input,{...i,size:`lg`,type:`search`,placeholder:`Tìm kiếm...`,className:`flex-1 ps-9 pe-9`,onChange:e=>{r?.(e),s(e.target.value??``)}}),(0,a.jsx)(`div`,{className:`pointer-events-none absolute inset-y-0 inset-s-0 flex items-center justify-center ps-3 text-text-positive-weak peer-disabled:opacity-50`,children:(0,a.jsx)(n.SearchIcon,{size:16})}),(0,a.jsx)(`button`,{className:`absolute inset-y-0 inset-e-0 flex h-full w-9 items-center justify-center rounded-e-md text-text-positive-weak outline-none transition-[color,box-shadow] hover:text-text-positive focus:z-10 focus-visible:border focus-visible:border-primary-strong focus-visible:ring-[3px] focus-visible:ring-primary-weak disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50`,"aria-label":`Submit search`,type:`submit`,children:(0,a.jsx)(n.ArrowRightIcon,{size:16,"aria-hidden":`true`})})]})},d=({children:e,disabled:t,onClick:n,className:r,...o})=>(0,a.jsx)(`button`,{type:`button`,disabled:t,className:(0,i.cn)(`flex cursor-pointer items-center gap-x-1 rounded-sm border border-border bg-background p-2.5 text-sm text-text-positive-weak outline-none transition-all hover:shadow-card focus:border-border-emphasis focus:bg-muted-muted active:border-border-emphasis active:bg-muted-muted active:text-text-positive disabled:pointer-events-none disabled:cursor-default disabled:opacity-60 [&_svg]:size-3.5`,r),onClick:n,...o,children:e}),f=({onCreate:t,onCreateMultiple:i,onDownload:o,onRefresh:s})=>{let{table:c,csvData:u,csvFileName:f,title:p,showAnalysisPanel:m,summary:h}=e.Y(),{isOpen:g,toggle:_}=e.q(),{isOpen:v,toggle:y}=e.Z(),b=(0,r.useCallback)(()=>{if(o){o();return}if(!u||u.length===0)return;let e=c.getSelectedRowModel().flatRows;l(e.length>0?e.map(e=>u[e.index]).filter(Boolean):u,f||p)},[o,u,f,c,p]),x=!!(o||u&&u.length>0);return(0,a.jsxs)(`div`,{className:`flex [&>*:not(:first-child)]:rounded-l-none [&>*:not(:first-child)]:border-l-0 [&>*:not(:last-child)]:rounded-r-none`,children:[(0,a.jsx)(d,{disabled:!t,"aria-label":`Tạo mới`,onClick:e=>{t?.(),e.stopPropagation(),e.preventDefault()},children:(0,a.jsx)(n.CirclePlus,{})}),(0,a.jsx)(d,{disabled:!i,"aria-label":`Tạo nhiều`,onClick:e=>{i?.(),e.stopPropagation(),e.preventDefault()},children:(0,a.jsx)(n.CopyPlusIcon,{})}),(0,a.jsx)(d,{disabled:!s,"aria-label":`Làm mới`,onClick:e=>{s?.(),e.stopPropagation(),e.preventDefault()},children:(0,a.jsx)(n.RefreshCwIcon,{})}),(0,a.jsx)(d,{disabled:!x,"aria-label":`Tải xuống`,onClick:e=>{b(),e.stopPropagation(),e.preventDefault()},children:(0,a.jsx)(n.DownloadIcon,{})}),h&&h.length>0&&(0,a.jsx)(d,{onClick:e=>{y(),e.stopPropagation(),e.preventDefault()},"aria-pressed":v,"aria-label":v?`Ẩn tổng quan`:`Hiện tổng quan`,className:v?`bg-muted-muted text-text-positive`:void 0,children:(0,a.jsx)(n.LayoutDashboardIcon,{})}),m&&(0,a.jsx)(d,{onClick:e=>{_(),e.stopPropagation(),e.preventDefault()},"aria-pressed":g,className:g?`bg-muted-muted text-text-positive`:void 0,children:(0,a.jsx)(n.BarChart2Icon,{})})]})},p=({children:t})=>{let{title:n,description:r,headerActions:i}=e.Y();return(0,a.jsxs)(`div`,{"data-slot":`table-tooltip`,className:`relative grid w-full grid-cols-1 gap-2 px-2 py-0 text-sm`,children:[(0,a.jsxs)(`div`,{className:`grid w-full grid-cols-[1fr_auto] items-start gap-4`,children:[(0,a.jsxs)(`div`,{className:`grid grid-cols-1 gap-0.5`,children:[(0,a.jsx)(`h3`,{className:`font-semibold text-base text-text-positive`,children:n}),!!r&&(0,a.jsx)(`p`,{className:`text-muted-foreground text-sm`,children:r})]}),!!i&&(0,a.jsx)(`div`,{className:`flex shrink-0 items-center gap-2`,children:i})]}),(0,a.jsx)(`div`,{className:`grid w-full grid-cols-[1fr_auto] gap-x-2`,children:t})]})};p.displayName=`UITableTooltip`,exports.UITableTooltip=p,exports.UITableTooltipActions=f,exports.UITableTooltipFilter=u;
4
- //# sourceMappingURL=tooltip-BVzKgxrZ.cjs.map
3
+ `)}function l(e,t){let n=c(e);if(!n)return;let r=new Blob([n],{type:`text/csv;charset=utf-8;`}),i=URL.createObjectURL(r),a=document.createElement(`a`);a.href=i,a.download=`${t}.csv`,a.click(),URL.revokeObjectURL(i)}const u=({onSearch:t,onChange:r,...i})=>{let s=(0,o.useDebounceCallback)(e=>{t?.(e)},500);return(0,a.jsxs)(`div`,{className:`relative w-full max-w-80 flex-1`,children:[(0,a.jsx)(e.Input,{...i,size:`lg`,type:`search`,placeholder:`Tìm kiếm...`,className:`flex-1 ps-9 pe-9`,onChange:e=>{r?.(e),s(e.target.value??``)}}),(0,a.jsx)(`div`,{className:`pointer-events-none absolute inset-y-0 inset-s-0 flex items-center justify-center ps-3 text-text-positive-weak peer-disabled:opacity-50`,children:(0,a.jsx)(n.SearchIcon,{size:16})}),(0,a.jsx)(`button`,{className:`absolute inset-y-0 inset-e-0 flex h-full w-9 items-center justify-center rounded-e-md text-text-positive-weak outline-none transition-[color,box-shadow] hover:text-text-positive focus:z-10 focus-visible:border focus-visible:border-primary-strong focus-visible:ring-[3px] focus-visible:ring-primary-weak disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50`,"aria-label":`Submit search`,type:`submit`,children:(0,a.jsx)(n.ArrowRightIcon,{size:16,"aria-hidden":`true`})})]})},d=({children:e,disabled:t,onClick:n,className:r,...o})=>(0,a.jsx)(`button`,{type:`button`,disabled:t,className:(0,i.cn)(`flex cursor-pointer items-center gap-x-1 rounded-sm border border-border bg-background p-2.5 text-sm text-text-positive-weak outline-none transition-all hover:shadow-card focus:border-border-emphasis focus:bg-muted-muted active:border-border-emphasis active:bg-muted-muted active:text-text-positive disabled:pointer-events-none disabled:cursor-default disabled:opacity-60 [&_svg]:size-3.5`,r),onClick:n,...o,children:e}),f=({onCreate:e,onCreateMultiple:i,onDownload:o,onRefresh:s})=>{let{table:c,csvData:u,csvFileName:f,title:p,showAnalysisPanel:m,summary:h}=t.Y(),{isOpen:g,toggle:_}=t.q(),{isOpen:v,toggle:y}=t.Z(),b=(0,r.useCallback)(()=>{if(o){o();return}if(!u||u.length===0)return;let e=c.getSelectedRowModel().flatRows;l(e.length>0?e.map(e=>u[e.index]).filter(Boolean):u,f||p)},[o,u,f,c,p]),x=!!(o||u&&u.length>0);return(0,a.jsxs)(`div`,{className:`flex [&>*:not(:first-child)]:rounded-l-none [&>*:not(:first-child)]:border-l-0 [&>*:not(:last-child)]:rounded-r-none`,children:[(0,a.jsx)(d,{disabled:!e,"aria-label":`Tạo mới`,onClick:t=>{e?.(),t.stopPropagation(),t.preventDefault()},children:(0,a.jsx)(n.CirclePlus,{})}),(0,a.jsx)(d,{disabled:!i,"aria-label":`Tạo nhiều`,onClick:e=>{i?.(),e.stopPropagation(),e.preventDefault()},children:(0,a.jsx)(n.CopyPlusIcon,{})}),(0,a.jsx)(d,{disabled:!s,"aria-label":`Làm mới`,onClick:e=>{s?.(),e.stopPropagation(),e.preventDefault()},children:(0,a.jsx)(n.RefreshCwIcon,{})}),(0,a.jsx)(d,{disabled:!x,"aria-label":`Tải xuống`,onClick:e=>{b(),e.stopPropagation(),e.preventDefault()},children:(0,a.jsx)(n.DownloadIcon,{})}),h&&h.length>0&&(0,a.jsx)(d,{onClick:e=>{y(),e.stopPropagation(),e.preventDefault()},"aria-pressed":v,"aria-label":v?`Ẩn tổng quan`:`Hiện tổng quan`,className:v?`bg-muted-muted text-text-positive`:void 0,children:(0,a.jsx)(n.LayoutDashboardIcon,{})}),m&&(0,a.jsx)(d,{onClick:e=>{_(),e.stopPropagation(),e.preventDefault()},"aria-pressed":g,className:g?`bg-muted-muted text-text-positive`:void 0,children:(0,a.jsx)(n.BarChart2Icon,{})})]})},p=({children:e})=>{let{title:n,description:r,headerActions:i}=t.Y();return(0,a.jsxs)(`div`,{"data-slot":`table-tooltip`,className:`relative grid w-full grid-cols-1 gap-2 px-2 py-0 text-sm`,children:[(0,a.jsxs)(`div`,{className:`grid w-full grid-cols-[1fr_auto] items-start gap-4`,children:[(0,a.jsxs)(`div`,{className:`grid grid-cols-1 gap-0.5`,children:[(0,a.jsx)(`h3`,{className:`font-semibold text-base text-text-positive`,children:n}),!!r&&(0,a.jsx)(`p`,{className:`text-muted-foreground text-sm`,children:r})]}),!!i&&(0,a.jsx)(`div`,{className:`flex shrink-0 items-center gap-2`,children:i})]}),(0,a.jsx)(`div`,{className:`grid w-full grid-cols-[1fr_auto] gap-x-2`,children:e})]})};p.displayName=`UITableTooltip`,exports.UITableTooltip=p,exports.UITableTooltipActions=f,exports.UITableTooltipFilter=u;
4
+ //# sourceMappingURL=tooltip-CUyGXE9e.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"tooltip-BVzKgxrZ.cjs","names":["Input","SearchIcon","ArrowRightIcon","useUITableContext","useUITableAnalysisContext","useUITableSummaryContext","CirclePlus","CopyPlusIcon","RefreshCwIcon","DownloadIcon","LayoutDashboardIcon","BarChart2Icon"],"sources":["../packages/components/features/tables/utils/csv.ts","../packages/components/features/tables/components/table/tooltip.tsx"],"sourcesContent":["'use client';\n\nimport type { CsvCell } from '../types';\n\nfunction formatCell(value: CsvCell['value']): string {\n if (value === null || value === undefined) return '';\n if (typeof value === 'number') return String(value);\n if (typeof value === 'boolean') return value ? 'true' : 'false';\n const str = String(value);\n if (str.includes(',') || str.includes('\"') || str.includes('\\n') || str.includes('\\r')) {\n return `\"${str.replace(/\"/g, '\"\"')}\"`;\n }\n return str;\n}\n\nexport function buildCsvContent(rows: CsvCell[][]): string {\n if (rows.length === 0) return '';\n const headers = rows[0].map(cell => formatCell(cell.label));\n const dataRows = rows.map(row => row.map(cell => formatCell(cell.value)).join(','));\n return [headers.join(','), ...dataRows].join('\\n');\n}\n\nexport function downloadCsv(rows: CsvCell[][], fileName: string): void {\n const content = buildCsvContent(rows);\n if (!content) return;\n const blob = new Blob([content], { type: 'text/csv;charset=utf-8;' });\n const url = URL.createObjectURL(blob);\n const link = document.createElement('a');\n link.href = url;\n link.download = `${fileName}.csv`;\n link.click();\n URL.revokeObjectURL(url);\n}\n","/**\n * @file tooltip.tsx\n * Toolbar components rendered above the table: a debounced search input,\n * an action button group (create / refresh / download), and the outer\n * toolbar shell that displays the table title.\n */\nimport { useCallback } from 'react';\n\nimport { ArrowRightIcon, BarChart2Icon, CirclePlus, CopyPlusIcon, DownloadIcon, LayoutDashboardIcon, RefreshCwIcon, SearchIcon } from 'lucide-react';\n\nimport { useDebounceCallback } from '@customafk/react-toolkit/hooks/useDebounceCallback';\nimport { cn } from '@customafk/react-toolkit/utils';\n\nimport { Input } from '@/components/ui/input';\n\nimport { useUITableAnalysisContext, useUITableContext, useUITableSummaryContext } from '../../hooks/use-context';\nimport { downloadCsv } from '../../utils/csv';\n\n/**\n * Debounced search input rendered inside the table toolbar.\n *\n * Fires `onSearch` 500 ms after the user stops typing and delegates all other\n * native input events via the spread `props`.\n *\n * @example\n * ```tsx\n * import { UITableTooltipFilter } from '@customafk/lunas-ui/features/tables';\n *\n * <UITableTooltipFilter\n * placeholder=\"Search users…\"\n * onSearch={value => setQuery(value)}\n * />\n * ```\n */\nexport const UITableTooltipFilter: React.FC<\n Omit<React.ComponentProps<typeof Input>, 'className'> & {\n onSearch?: (value: string) => void;\n }\n> = ({ onSearch, onChange, ...props }) => {\n const debouncedSearch = useDebounceCallback((value: string) => {\n onSearch?.(value);\n }, 500);\n return (\n <div className=\"relative w-full max-w-80 flex-1\">\n <Input\n {...props}\n size=\"lg\"\n type=\"search\"\n placeholder=\"Tìm kiếm...\"\n className=\"flex-1 ps-9 pe-9\"\n onChange={e => {\n onChange?.(e);\n debouncedSearch(e.target.value ?? '');\n }}\n />\n <div className=\"pointer-events-none absolute inset-y-0 inset-s-0 flex items-center justify-center ps-3 text-text-positive-weak peer-disabled:opacity-50\">\n <SearchIcon size={16} />\n </div>\n <button\n className=\"absolute inset-y-0 inset-e-0 flex h-full w-9 items-center justify-center rounded-e-md text-text-positive-weak outline-none transition-[color,box-shadow] hover:text-text-positive focus:z-10 focus-visible:border focus-visible:border-primary-strong focus-visible:ring-[3px] focus-visible:ring-primary-weak disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50\"\n aria-label=\"Submit search\"\n type=\"submit\"\n >\n <ArrowRightIcon size={16} aria-hidden=\"true\" />\n </button>\n </div>\n );\n};\n\nconst ActionButton: React.FC<React.PropsWithChildren<React.ComponentProps<'button'>>> = ({ children, disabled, onClick, className, ...props }) => {\n return (\n <button\n type=\"button\"\n disabled={disabled}\n className={cn(\n 'flex cursor-pointer items-center gap-x-1 rounded-sm border border-border bg-background p-2.5 text-sm text-text-positive-weak outline-none transition-all hover:shadow-card focus:border-border-emphasis focus:bg-muted-muted active:border-border-emphasis active:bg-muted-muted active:text-text-positive disabled:pointer-events-none disabled:cursor-default disabled:opacity-60 [&_svg]:size-3.5',\n className\n )}\n onClick={onClick}\n {...props}\n >\n {children}\n </button>\n );\n};\n\n/**\n * Grouped action buttons (create, refresh, download) displayed in the table\n * toolbar.\n *\n * Each button is disabled automatically when the corresponding handler prop is\n * omitted, so only the actions relevant to a given table need to be provided.\n * A toggle for `UITableSummaryBar` appears automatically when `summary` is\n * non-empty, and a toggle for `UITableAnalysisPanel` appears when\n * `showAnalysisPanel` is `true` (both set on `UITableProvider`).\n * `onCreateMultiple` renders a separate \"bulk create\" button next to the\n * single-item create button; omit it to hide the button entirely.\n *\n * @example\n * ```tsx\n * import { UITableTooltipActions } from '@customafk/lunas-ui/features/tables';\n *\n * <UITableTooltipActions\n * onCreate={() => setOpenCreate(true)}\n * onCreateMultiple={() => setOpenBulkCreate(true)}\n * onRefresh={() => refetch()}\n * />\n * ```\n */\nexport const UITableTooltipActions: React.FC<{\n onCreate?: () => void;\n onCreateMultiple?: () => void;\n onRefresh?: () => void;\n onDownload?: () => void;\n}> = ({ onCreate, onCreateMultiple, onDownload, onRefresh }) => {\n const { table, csvData, csvFileName, title, showAnalysisPanel, summary } = useUITableContext();\n const { isOpen: isAnalysisOpen, toggle: toggleAnalysis } = useUITableAnalysisContext();\n const { isOpen: isSummaryOpen, toggle: toggleSummary } = useUITableSummaryContext();\n\n const handleDownload = useCallback(() => {\n if (onDownload) {\n onDownload();\n return;\n }\n if (!csvData || csvData.length === 0) return;\n const selectedRows = table.getSelectedRowModel().flatRows;\n const rows = selectedRows.length > 0 ? selectedRows.map(row => csvData[row.index]).filter(Boolean) : csvData;\n downloadCsv(rows, csvFileName || title);\n }, [onDownload, csvData, csvFileName, table, title]);\n\n const isDownloadEnabled = !!(onDownload || (csvData && csvData.length > 0));\n\n return (\n <div className=\"flex [&>*:not(:first-child)]:rounded-l-none [&>*:not(:first-child)]:border-l-0 [&>*:not(:last-child)]:rounded-r-none\">\n <ActionButton\n disabled={!onCreate}\n aria-label=\"Tạo mới\"\n onClick={e => {\n onCreate?.();\n e.stopPropagation();\n e.preventDefault();\n }}\n >\n <CirclePlus />\n </ActionButton>\n <ActionButton\n disabled={!onCreateMultiple}\n aria-label=\"Tạo nhiều\"\n onClick={e => {\n onCreateMultiple?.();\n e.stopPropagation();\n e.preventDefault();\n }}\n >\n <CopyPlusIcon />\n </ActionButton>\n <ActionButton\n disabled={!onRefresh}\n aria-label=\"Làm mới\"\n onClick={e => {\n onRefresh?.();\n e.stopPropagation();\n e.preventDefault();\n }}\n >\n <RefreshCwIcon />\n </ActionButton>\n <ActionButton\n disabled={!isDownloadEnabled}\n aria-label=\"Tải xuống\"\n onClick={e => {\n handleDownload();\n e.stopPropagation();\n e.preventDefault();\n }}\n >\n <DownloadIcon />\n </ActionButton>\n {summary && summary.length > 0 && (\n <ActionButton\n onClick={e => {\n toggleSummary();\n e.stopPropagation();\n e.preventDefault();\n }}\n aria-pressed={isSummaryOpen}\n aria-label={isSummaryOpen ? 'Ẩn tổng quan' : 'Hiện tổng quan'}\n className={isSummaryOpen ? 'bg-muted-muted text-text-positive' : undefined}\n >\n <LayoutDashboardIcon />\n </ActionButton>\n )}\n {showAnalysisPanel && (\n <ActionButton\n onClick={e => {\n toggleAnalysis();\n e.stopPropagation();\n e.preventDefault();\n }}\n aria-pressed={isAnalysisOpen}\n className={isAnalysisOpen ? 'bg-muted-muted text-text-positive' : undefined}\n >\n <BarChart2Icon />\n </ActionButton>\n )}\n </div>\n );\n};\n\n/**\n * Outer toolbar shell for the UITable component.\n *\n * Reads the table `title` from `UITableContext` and renders it as a heading\n * above the `children` slot, which typically contains a\n * `UITableTooltipFilter` and/or `UITableTooltipActions`.\n *\n * @example\n * ```tsx\n * import {\n * UITableTooltip,\n * UITableTooltipFilter,\n * UITableTooltipActions,\n * } from '@customafk/lunas-ui/features/tables';\n *\n * <UITableTooltip>\n * <UITableTooltipFilter onSearch={setQuery} />\n * <UITableTooltipActions onCreate={handleCreate} onRefresh={refetch} />\n * </UITableTooltip>\n * ```\n */\nexport const UITableTooltip: React.FC<React.PropsWithChildren> = ({ children }) => {\n const { title, description, headerActions } = useUITableContext();\n return (\n <div data-slot=\"table-tooltip\" className=\"relative grid w-full grid-cols-1 gap-2 px-2 py-0 text-sm\">\n <div className=\"grid w-full grid-cols-[1fr_auto] items-start gap-4\">\n <div className=\"grid grid-cols-1 gap-0.5\">\n <h3 className=\"font-semibold text-base text-text-positive\">{title}</h3>\n {!!description && <p className=\"text-muted-foreground text-sm\">{description}</p>}\n </div>\n {!!headerActions && <div className=\"flex shrink-0 items-center gap-2\">{headerActions}</div>}\n </div>\n <div className=\"grid w-full grid-cols-[1fr_auto] gap-x-2\">{children}</div>\n </div>\n );\n};\nUITableTooltip.displayName = 'UITableTooltip';\n"],"mappings":"iQAIA,SAAS,EAAW,EAAiC,CACnD,GAAI,GAAU,KAA6B,MAAO,GAClD,GAAI,OAAO,GAAU,SAAU,OAAO,OAAO,CAAK,EAClD,GAAI,OAAO,GAAU,UAAW,OAAO,EAAQ,OAAS,QACxD,IAAM,EAAM,OAAO,CAAK,EAIxB,OAHI,EAAI,SAAS,GAAG,GAAK,EAAI,SAAS,GAAG,GAAK,EAAI,SAAS;CAAI,GAAK,EAAI,SAAS,IAAI,EAC5E,IAAI,EAAI,QAAQ,KAAM,IAAI,EAAE,GAE9B,CACT,CAEA,SAAgB,EAAgB,EAA2B,CACzD,GAAI,EAAK,SAAW,EAAG,MAAO,GAC9B,IAAM,EAAU,EAAK,EAAE,CAAC,IAAI,GAAQ,EAAW,EAAK,KAAK,CAAC,EACpD,EAAW,EAAK,IAAI,GAAO,EAAI,IAAI,GAAQ,EAAW,EAAK,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,EAClF,MAAO,CAAC,EAAQ,KAAK,GAAG,EAAG,GAAG,CAAQ,CAAC,CAAC,KAAK;CAAI,CACnD,CAEA,SAAgB,EAAY,EAAmB,EAAwB,CACrE,IAAM,EAAU,EAAgB,CAAI,EACpC,GAAI,CAAC,EAAS,OACd,IAAM,EAAO,IAAI,KAAK,CAAC,CAAO,EAAG,CAAE,KAAM,yBAA0B,CAAC,EAC9D,EAAM,IAAI,gBAAgB,CAAI,EAC9B,EAAO,SAAS,cAAc,GAAG,EACvC,EAAK,KAAO,EACZ,EAAK,SAAW,GAAG,EAAS,MAC5B,EAAK,MAAM,EACX,IAAI,gBAAgB,CAAG,CACzB,CCEA,MAAa,GAIR,CAAE,WAAU,WAAU,GAAG,KAAY,CACxC,IAAM,GAAA,EAAA,EAAA,oBAAA,CAAuC,GAAkB,CAC7D,IAAW,CAAK,CAClB,EAAG,GAAG,EACN,OACE,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,kCAAf,SAAA,EACE,EAAA,EAAA,IAAA,CAACA,EAAAA,MAAD,CACE,GAAI,EACJ,KAAK,KACL,KAAK,SACL,YAAY,cACZ,UAAU,mBACV,SAAU,GAAK,CACb,IAAW,CAAC,EACZ,EAAgB,EAAE,OAAO,OAAS,EAAE,CACtC,CACD,CAAA,GACD,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,0IACb,UAAA,EAAA,EAAA,IAAA,CAACC,EAAAA,WAAD,CAAY,KAAM,EAAK,CAAA,CACpB,CAAA,GACL,EAAA,EAAA,IAAA,CAAC,SAAD,CACE,UAAU,8XACV,aAAW,gBACX,KAAK,SAEL,UAAA,EAAA,EAAA,IAAA,CAACC,EAAAA,eAAD,CAAgB,KAAM,GAAI,cAAY,MAAQ,CAAA,CACxC,CAAA,CACL,GAET,EAEM,GAAmF,CAAE,WAAU,WAAU,UAAS,YAAW,GAAG,MAElI,EAAA,EAAA,IAAA,CAAC,SAAD,CACE,KAAK,SACK,WACV,WAAA,EAAA,EAAA,GAAA,CACE,uYACA,CACF,EACS,UACT,GAAI,EAEH,UACK,CAAA,EA2BC,GAKP,CAAE,WAAU,mBAAkB,aAAY,eAAgB,CAC9D,GAAM,CAAE,QAAO,UAAS,cAAa,QAAO,oBAAmB,WAAYC,EAAAA,EAAkB,EACvF,CAAE,OAAQ,EAAgB,OAAQ,GAAmBC,EAAAA,EAA0B,EAC/E,CAAE,OAAQ,EAAe,OAAQ,GAAkBC,EAAAA,EAAyB,EAE5E,GAAA,EAAA,EAAA,YAAA,KAAmC,CACvC,GAAI,EAAY,CACd,EAAW,EACX,MACF,CACA,GAAI,CAAC,GAAW,EAAQ,SAAW,EAAG,OACtC,IAAM,EAAe,EAAM,oBAAoB,CAAC,CAAC,SAEjD,EADa,EAAa,OAAS,EAAI,EAAa,IAAI,GAAO,EAAQ,EAAI,MAAM,CAAC,CAAC,OAAO,OAAO,EAAI,EACnF,GAAe,CAAK,CACxC,EAAG,CAAC,EAAY,EAAS,EAAa,EAAO,CAAK,CAAC,EAE7C,EAAoB,CAAC,EAAE,GAAe,GAAW,EAAQ,OAAS,GAExE,OACE,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,uHAAf,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,SAAU,CAAC,EACX,aAAW,UACX,QAAS,GAAK,CACZ,IAAW,EACX,EAAE,gBAAgB,EAClB,EAAE,eAAe,CACnB,EAEA,UAAA,EAAA,EAAA,IAAA,CAACC,EAAAA,WAAD,CAAa,CAAA,CACD,CAAA,GACd,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,SAAU,CAAC,EACX,aAAW,YACX,QAAS,GAAK,CACZ,IAAmB,EACnB,EAAE,gBAAgB,EAClB,EAAE,eAAe,CACnB,EAEA,UAAA,EAAA,EAAA,IAAA,CAACC,EAAAA,aAAD,CAAe,CAAA,CACH,CAAA,GACd,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,SAAU,CAAC,EACX,aAAW,UACX,QAAS,GAAK,CACZ,IAAY,EACZ,EAAE,gBAAgB,EAClB,EAAE,eAAe,CACnB,EAEA,UAAA,EAAA,EAAA,IAAA,CAACC,EAAAA,cAAD,CAAgB,CAAA,CACJ,CAAA,GACd,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,SAAU,CAAC,EACX,aAAW,YACX,QAAS,GAAK,CACZ,EAAe,EACf,EAAE,gBAAgB,EAClB,EAAE,eAAe,CACnB,EAEA,UAAA,EAAA,EAAA,IAAA,CAACC,EAAAA,aAAD,CAAe,CAAA,CACH,CAAA,EACb,GAAW,EAAQ,OAAS,IAC3B,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,QAAS,GAAK,CACZ,EAAc,EACd,EAAE,gBAAgB,EAClB,EAAE,eAAe,CACnB,EACA,eAAc,EACd,aAAY,EAAgB,eAAiB,iBAC7C,UAAW,EAAgB,oCAAsC,IAAA,GAEjE,UAAA,EAAA,EAAA,IAAA,CAACC,EAAAA,oBAAD,CAAsB,CAAA,CACV,CAAA,EAEf,IACC,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,QAAS,GAAK,CACZ,EAAe,EACf,EAAE,gBAAgB,EAClB,EAAE,eAAe,CACnB,EACA,eAAc,EACd,UAAW,EAAiB,oCAAsC,IAAA,GAElE,UAAA,EAAA,EAAA,IAAA,CAACC,EAAAA,cAAD,CAAgB,CAAA,CACJ,CAAA,CAEb,GAET,EAuBa,GAAqD,CAAE,cAAe,CACjF,GAAM,CAAE,QAAO,cAAa,iBAAkBR,EAAAA,EAAkB,EAChE,OACE,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,YAAU,gBAAgB,UAAU,2DAAzC,SAAA,EACE,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,qDAAf,SAAA,EACE,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,2BAAf,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,KAAD,CAAI,UAAU,6CAA8C,SAAA,CAAU,CAAA,EACrE,CAAC,CAAC,IAAe,EAAA,EAAA,IAAA,CAAC,IAAD,CAAG,UAAU,gCAAiC,SAAA,CAAe,CAAA,CAC5E,CACJ,CAAA,EAAA,CAAC,CAAC,IAAiB,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,mCAAoC,SAAA,CAAmB,CAAA,CACvF,CACL,CAAA,GAAA,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,2CAA4C,UAAc,CAAA,CACtE,GAET,EACA,EAAe,YAAc"}
1
+ {"version":3,"file":"tooltip-CUyGXE9e.cjs","names":["Input","SearchIcon","ArrowRightIcon","useUITableContext","useUITableAnalysisContext","useUITableSummaryContext","CirclePlus","CopyPlusIcon","RefreshCwIcon","DownloadIcon","LayoutDashboardIcon","BarChart2Icon"],"sources":["../packages/components/features/tables/utils/csv.ts","../packages/components/features/tables/components/table/tooltip.tsx"],"sourcesContent":["'use client';\n\nimport type { CsvCell } from '../types';\n\nfunction formatCell(value: CsvCell['value']): string {\n if (value === null || value === undefined) return '';\n if (typeof value === 'number') return String(value);\n if (typeof value === 'boolean') return value ? 'true' : 'false';\n const str = String(value);\n if (str.includes(',') || str.includes('\"') || str.includes('\\n') || str.includes('\\r')) {\n return `\"${str.replace(/\"/g, '\"\"')}\"`;\n }\n return str;\n}\n\nexport function buildCsvContent(rows: CsvCell[][]): string {\n if (rows.length === 0) return '';\n const headers = rows[0].map(cell => formatCell(cell.label));\n const dataRows = rows.map(row => row.map(cell => formatCell(cell.value)).join(','));\n return [headers.join(','), ...dataRows].join('\\n');\n}\n\nexport function downloadCsv(rows: CsvCell[][], fileName: string): void {\n const content = buildCsvContent(rows);\n if (!content) return;\n const blob = new Blob([content], { type: 'text/csv;charset=utf-8;' });\n const url = URL.createObjectURL(blob);\n const link = document.createElement('a');\n link.href = url;\n link.download = `${fileName}.csv`;\n link.click();\n URL.revokeObjectURL(url);\n}\n","/**\n * @file tooltip.tsx\n * Toolbar components rendered above the table: a debounced search input,\n * an action button group (create / refresh / download), and the outer\n * toolbar shell that displays the table title.\n */\nimport { useCallback } from 'react';\n\nimport { ArrowRightIcon, BarChart2Icon, CirclePlus, CopyPlusIcon, DownloadIcon, LayoutDashboardIcon, RefreshCwIcon, SearchIcon } from 'lucide-react';\n\nimport { useDebounceCallback } from '@customafk/react-toolkit/hooks/useDebounceCallback';\nimport { cn } from '@customafk/react-toolkit/utils';\n\nimport { Input } from '@/components/ui/input';\n\nimport { useUITableAnalysisContext, useUITableContext, useUITableSummaryContext } from '../../hooks/use-context';\nimport { downloadCsv } from '../../utils/csv';\n\n/**\n * Debounced search input rendered inside the table toolbar.\n *\n * Fires `onSearch` 500 ms after the user stops typing and delegates all other\n * native input events via the spread `props`.\n *\n * @example\n * ```tsx\n * import { UITableTooltipFilter } from '@customafk/lunas-ui/features/tables';\n *\n * <UITableTooltipFilter\n * placeholder=\"Search users…\"\n * onSearch={value => setQuery(value)}\n * />\n * ```\n */\nexport const UITableTooltipFilter: React.FC<\n Omit<React.ComponentProps<typeof Input>, 'className'> & {\n onSearch?: (value: string) => void;\n }\n> = ({ onSearch, onChange, ...props }) => {\n const debouncedSearch = useDebounceCallback((value: string) => {\n onSearch?.(value);\n }, 500);\n return (\n <div className=\"relative w-full max-w-80 flex-1\">\n <Input\n {...props}\n size=\"lg\"\n type=\"search\"\n placeholder=\"Tìm kiếm...\"\n className=\"flex-1 ps-9 pe-9\"\n onChange={e => {\n onChange?.(e);\n debouncedSearch(e.target.value ?? '');\n }}\n />\n <div className=\"pointer-events-none absolute inset-y-0 inset-s-0 flex items-center justify-center ps-3 text-text-positive-weak peer-disabled:opacity-50\">\n <SearchIcon size={16} />\n </div>\n <button\n className=\"absolute inset-y-0 inset-e-0 flex h-full w-9 items-center justify-center rounded-e-md text-text-positive-weak outline-none transition-[color,box-shadow] hover:text-text-positive focus:z-10 focus-visible:border focus-visible:border-primary-strong focus-visible:ring-[3px] focus-visible:ring-primary-weak disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50\"\n aria-label=\"Submit search\"\n type=\"submit\"\n >\n <ArrowRightIcon size={16} aria-hidden=\"true\" />\n </button>\n </div>\n );\n};\n\nconst ActionButton: React.FC<React.PropsWithChildren<React.ComponentProps<'button'>>> = ({ children, disabled, onClick, className, ...props }) => {\n return (\n <button\n type=\"button\"\n disabled={disabled}\n className={cn(\n 'flex cursor-pointer items-center gap-x-1 rounded-sm border border-border bg-background p-2.5 text-sm text-text-positive-weak outline-none transition-all hover:shadow-card focus:border-border-emphasis focus:bg-muted-muted active:border-border-emphasis active:bg-muted-muted active:text-text-positive disabled:pointer-events-none disabled:cursor-default disabled:opacity-60 [&_svg]:size-3.5',\n className\n )}\n onClick={onClick}\n {...props}\n >\n {children}\n </button>\n );\n};\n\n/**\n * Grouped action buttons (create, refresh, download) displayed in the table\n * toolbar.\n *\n * Each button is disabled automatically when the corresponding handler prop is\n * omitted, so only the actions relevant to a given table need to be provided.\n * A toggle for `UITableSummaryBar` appears automatically when `summary` is\n * non-empty, and a toggle for `UITableAnalysisPanel` appears when\n * `showAnalysisPanel` is `true` (both set on `UITableProvider`).\n * `onCreateMultiple` renders a separate \"bulk create\" button next to the\n * single-item create button; omit it to hide the button entirely.\n *\n * @example\n * ```tsx\n * import { UITableTooltipActions } from '@customafk/lunas-ui/features/tables';\n *\n * <UITableTooltipActions\n * onCreate={() => setOpenCreate(true)}\n * onCreateMultiple={() => setOpenBulkCreate(true)}\n * onRefresh={() => refetch()}\n * />\n * ```\n */\nexport const UITableTooltipActions: React.FC<{\n onCreate?: () => void;\n onCreateMultiple?: () => void;\n onRefresh?: () => void;\n onDownload?: () => void;\n}> = ({ onCreate, onCreateMultiple, onDownload, onRefresh }) => {\n const { table, csvData, csvFileName, title, showAnalysisPanel, summary } = useUITableContext();\n const { isOpen: isAnalysisOpen, toggle: toggleAnalysis } = useUITableAnalysisContext();\n const { isOpen: isSummaryOpen, toggle: toggleSummary } = useUITableSummaryContext();\n\n const handleDownload = useCallback(() => {\n if (onDownload) {\n onDownload();\n return;\n }\n if (!csvData || csvData.length === 0) return;\n const selectedRows = table.getSelectedRowModel().flatRows;\n const rows = selectedRows.length > 0 ? selectedRows.map(row => csvData[row.index]).filter(Boolean) : csvData;\n downloadCsv(rows, csvFileName || title);\n }, [onDownload, csvData, csvFileName, table, title]);\n\n const isDownloadEnabled = !!(onDownload || (csvData && csvData.length > 0));\n\n return (\n <div className=\"flex [&>*:not(:first-child)]:rounded-l-none [&>*:not(:first-child)]:border-l-0 [&>*:not(:last-child)]:rounded-r-none\">\n <ActionButton\n disabled={!onCreate}\n aria-label=\"Tạo mới\"\n onClick={e => {\n onCreate?.();\n e.stopPropagation();\n e.preventDefault();\n }}\n >\n <CirclePlus />\n </ActionButton>\n <ActionButton\n disabled={!onCreateMultiple}\n aria-label=\"Tạo nhiều\"\n onClick={e => {\n onCreateMultiple?.();\n e.stopPropagation();\n e.preventDefault();\n }}\n >\n <CopyPlusIcon />\n </ActionButton>\n <ActionButton\n disabled={!onRefresh}\n aria-label=\"Làm mới\"\n onClick={e => {\n onRefresh?.();\n e.stopPropagation();\n e.preventDefault();\n }}\n >\n <RefreshCwIcon />\n </ActionButton>\n <ActionButton\n disabled={!isDownloadEnabled}\n aria-label=\"Tải xuống\"\n onClick={e => {\n handleDownload();\n e.stopPropagation();\n e.preventDefault();\n }}\n >\n <DownloadIcon />\n </ActionButton>\n {summary && summary.length > 0 && (\n <ActionButton\n onClick={e => {\n toggleSummary();\n e.stopPropagation();\n e.preventDefault();\n }}\n aria-pressed={isSummaryOpen}\n aria-label={isSummaryOpen ? 'Ẩn tổng quan' : 'Hiện tổng quan'}\n className={isSummaryOpen ? 'bg-muted-muted text-text-positive' : undefined}\n >\n <LayoutDashboardIcon />\n </ActionButton>\n )}\n {showAnalysisPanel && (\n <ActionButton\n onClick={e => {\n toggleAnalysis();\n e.stopPropagation();\n e.preventDefault();\n }}\n aria-pressed={isAnalysisOpen}\n className={isAnalysisOpen ? 'bg-muted-muted text-text-positive' : undefined}\n >\n <BarChart2Icon />\n </ActionButton>\n )}\n </div>\n );\n};\n\n/**\n * Outer toolbar shell for the UITable component.\n *\n * Reads the table `title` from `UITableContext` and renders it as a heading\n * above the `children` slot, which typically contains a\n * `UITableTooltipFilter` and/or `UITableTooltipActions`.\n *\n * @example\n * ```tsx\n * import {\n * UITableTooltip,\n * UITableTooltipFilter,\n * UITableTooltipActions,\n * } from '@customafk/lunas-ui/features/tables';\n *\n * <UITableTooltip>\n * <UITableTooltipFilter onSearch={setQuery} />\n * <UITableTooltipActions onCreate={handleCreate} onRefresh={refetch} />\n * </UITableTooltip>\n * ```\n */\nexport const UITableTooltip: React.FC<React.PropsWithChildren> = ({ children }) => {\n const { title, description, headerActions } = useUITableContext();\n return (\n <div data-slot=\"table-tooltip\" className=\"relative grid w-full grid-cols-1 gap-2 px-2 py-0 text-sm\">\n <div className=\"grid w-full grid-cols-[1fr_auto] items-start gap-4\">\n <div className=\"grid grid-cols-1 gap-0.5\">\n <h3 className=\"font-semibold text-base text-text-positive\">{title}</h3>\n {!!description && <p className=\"text-muted-foreground text-sm\">{description}</p>}\n </div>\n {!!headerActions && <div className=\"flex shrink-0 items-center gap-2\">{headerActions}</div>}\n </div>\n <div className=\"grid w-full grid-cols-[1fr_auto] gap-x-2\">{children}</div>\n </div>\n );\n};\nUITableTooltip.displayName = 'UITableTooltip';\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import{Y as e,Z as t,q as n}from"./tables-Dg3KMBKA.mjs";import{Input as r}from"./ui/input.mjs";import{ArrowRightIcon as i,BarChart2Icon as a,CirclePlus as o,CopyPlusIcon as s,DownloadIcon as c,LayoutDashboardIcon as l,RefreshCwIcon as u,SearchIcon as d}from"lucide-react";import{useCallback as f}from"react";import{cn as p}from"@customafk/react-toolkit/utils";import{jsx as m,jsxs as h}from"react/jsx-runtime";import{useDebounceCallback as g}from"@customafk/react-toolkit/hooks/useDebounceCallback";function _(e){if(e==null)return``;if(typeof e==`number`)return String(e);if(typeof e==`boolean`)return e?`true`:`false`;let t=String(e);return t.includes(`,`)||t.includes(`"`)||t.includes(`
1
+ import{Input as e}from"./ui/input.mjs";import{Y as t,Z as n,q as r}from"./tables-CuoBQNqx.mjs";import{ArrowRightIcon as i,BarChart2Icon as a,CirclePlus as o,CopyPlusIcon as s,DownloadIcon as c,LayoutDashboardIcon as l,RefreshCwIcon as u,SearchIcon as d}from"lucide-react";import{useCallback as f}from"react";import{cn as p}from"@customafk/react-toolkit/utils";import{jsx as m,jsxs as h}from"react/jsx-runtime";import{useDebounceCallback as g}from"@customafk/react-toolkit/hooks/useDebounceCallback";function _(e){if(e==null)return``;if(typeof e==`number`)return String(e);if(typeof e==`boolean`)return e?`true`:`false`;let t=String(e);return t.includes(`,`)||t.includes(`"`)||t.includes(`
2
2
  `)||t.includes(`\r`)?`"${t.replace(/"/g,`""`)}"`:t}function v(e){if(e.length===0)return``;let t=e[0].map(e=>_(e.label)),n=e.map(e=>e.map(e=>_(e.value)).join(`,`));return[t.join(`,`),...n].join(`
3
- `)}function y(e,t){let n=v(e);if(!n)return;let r=new Blob([n],{type:`text/csv;charset=utf-8;`}),i=URL.createObjectURL(r),a=document.createElement(`a`);a.href=i,a.download=`${t}.csv`,a.click(),URL.revokeObjectURL(i)}const b=({onSearch:e,onChange:t,...n})=>{let a=g(t=>{e?.(t)},500);return h(`div`,{className:`relative w-full max-w-80 flex-1`,children:[m(r,{...n,size:`lg`,type:`search`,placeholder:`Tìm kiếm...`,className:`flex-1 ps-9 pe-9`,onChange:e=>{t?.(e),a(e.target.value??``)}}),m(`div`,{className:`pointer-events-none absolute inset-y-0 inset-s-0 flex items-center justify-center ps-3 text-text-positive-weak peer-disabled:opacity-50`,children:m(d,{size:16})}),m(`button`,{className:`absolute inset-y-0 inset-e-0 flex h-full w-9 items-center justify-center rounded-e-md text-text-positive-weak outline-none transition-[color,box-shadow] hover:text-text-positive focus:z-10 focus-visible:border focus-visible:border-primary-strong focus-visible:ring-[3px] focus-visible:ring-primary-weak disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50`,"aria-label":`Submit search`,type:`submit`,children:m(i,{size:16,"aria-hidden":`true`})})]})},x=({children:e,disabled:t,onClick:n,className:r,...i})=>m(`button`,{type:`button`,disabled:t,className:p(`flex cursor-pointer items-center gap-x-1 rounded-sm border border-border bg-background p-2.5 text-sm text-text-positive-weak outline-none transition-all hover:shadow-card focus:border-border-emphasis focus:bg-muted-muted active:border-border-emphasis active:bg-muted-muted active:text-text-positive disabled:pointer-events-none disabled:cursor-default disabled:opacity-60 [&_svg]:size-3.5`,r),onClick:n,...i,children:e}),S=({onCreate:r,onCreateMultiple:i,onDownload:d,onRefresh:p})=>{let{table:g,csvData:_,csvFileName:v,title:b,showAnalysisPanel:S,summary:C}=e(),{isOpen:w,toggle:T}=n(),{isOpen:E,toggle:D}=t(),O=f(()=>{if(d){d();return}if(!_||_.length===0)return;let e=g.getSelectedRowModel().flatRows;y(e.length>0?e.map(e=>_[e.index]).filter(Boolean):_,v||b)},[d,_,v,g,b]),k=!!(d||_&&_.length>0);return h(`div`,{className:`flex [&>*:not(:first-child)]:rounded-l-none [&>*:not(:first-child)]:border-l-0 [&>*:not(:last-child)]:rounded-r-none`,children:[m(x,{disabled:!r,"aria-label":`Tạo mới`,onClick:e=>{r?.(),e.stopPropagation(),e.preventDefault()},children:m(o,{})}),m(x,{disabled:!i,"aria-label":`Tạo nhiều`,onClick:e=>{i?.(),e.stopPropagation(),e.preventDefault()},children:m(s,{})}),m(x,{disabled:!p,"aria-label":`Làm mới`,onClick:e=>{p?.(),e.stopPropagation(),e.preventDefault()},children:m(u,{})}),m(x,{disabled:!k,"aria-label":`Tải xuống`,onClick:e=>{O(),e.stopPropagation(),e.preventDefault()},children:m(c,{})}),C&&C.length>0&&m(x,{onClick:e=>{D(),e.stopPropagation(),e.preventDefault()},"aria-pressed":E,"aria-label":E?`Ẩn tổng quan`:`Hiện tổng quan`,className:E?`bg-muted-muted text-text-positive`:void 0,children:m(l,{})}),S&&m(x,{onClick:e=>{T(),e.stopPropagation(),e.preventDefault()},"aria-pressed":w,className:w?`bg-muted-muted text-text-positive`:void 0,children:m(a,{})})]})},C=({children:t})=>{let{title:n,description:r,headerActions:i}=e();return h(`div`,{"data-slot":`table-tooltip`,className:`relative grid w-full grid-cols-1 gap-2 px-2 py-0 text-sm`,children:[h(`div`,{className:`grid w-full grid-cols-[1fr_auto] items-start gap-4`,children:[h(`div`,{className:`grid grid-cols-1 gap-0.5`,children:[m(`h3`,{className:`font-semibold text-base text-text-positive`,children:n}),!!r&&m(`p`,{className:`text-muted-foreground text-sm`,children:r})]}),!!i&&m(`div`,{className:`flex shrink-0 items-center gap-2`,children:i})]}),m(`div`,{className:`grid w-full grid-cols-[1fr_auto] gap-x-2`,children:t})]})};C.displayName=`UITableTooltip`;export{C as UITableTooltip,S as UITableTooltipActions,b as UITableTooltipFilter};
4
- //# sourceMappingURL=tooltip-D7U_Nl5c.mjs.map
3
+ `)}function y(e,t){let n=v(e);if(!n)return;let r=new Blob([n],{type:`text/csv;charset=utf-8;`}),i=URL.createObjectURL(r),a=document.createElement(`a`);a.href=i,a.download=`${t}.csv`,a.click(),URL.revokeObjectURL(i)}const b=({onSearch:t,onChange:n,...r})=>{let a=g(e=>{t?.(e)},500);return h(`div`,{className:`relative w-full max-w-80 flex-1`,children:[m(e,{...r,size:`lg`,type:`search`,placeholder:`Tìm kiếm...`,className:`flex-1 ps-9 pe-9`,onChange:e=>{n?.(e),a(e.target.value??``)}}),m(`div`,{className:`pointer-events-none absolute inset-y-0 inset-s-0 flex items-center justify-center ps-3 text-text-positive-weak peer-disabled:opacity-50`,children:m(d,{size:16})}),m(`button`,{className:`absolute inset-y-0 inset-e-0 flex h-full w-9 items-center justify-center rounded-e-md text-text-positive-weak outline-none transition-[color,box-shadow] hover:text-text-positive focus:z-10 focus-visible:border focus-visible:border-primary-strong focus-visible:ring-[3px] focus-visible:ring-primary-weak disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50`,"aria-label":`Submit search`,type:`submit`,children:m(i,{size:16,"aria-hidden":`true`})})]})},x=({children:e,disabled:t,onClick:n,className:r,...i})=>m(`button`,{type:`button`,disabled:t,className:p(`flex cursor-pointer items-center gap-x-1 rounded-sm border border-border bg-background p-2.5 text-sm text-text-positive-weak outline-none transition-all hover:shadow-card focus:border-border-emphasis focus:bg-muted-muted active:border-border-emphasis active:bg-muted-muted active:text-text-positive disabled:pointer-events-none disabled:cursor-default disabled:opacity-60 [&_svg]:size-3.5`,r),onClick:n,...i,children:e}),S=({onCreate:e,onCreateMultiple:i,onDownload:d,onRefresh:p})=>{let{table:g,csvData:_,csvFileName:v,title:b,showAnalysisPanel:S,summary:C}=t(),{isOpen:w,toggle:T}=r(),{isOpen:E,toggle:D}=n(),O=f(()=>{if(d){d();return}if(!_||_.length===0)return;let e=g.getSelectedRowModel().flatRows;y(e.length>0?e.map(e=>_[e.index]).filter(Boolean):_,v||b)},[d,_,v,g,b]),k=!!(d||_&&_.length>0);return h(`div`,{className:`flex [&>*:not(:first-child)]:rounded-l-none [&>*:not(:first-child)]:border-l-0 [&>*:not(:last-child)]:rounded-r-none`,children:[m(x,{disabled:!e,"aria-label":`Tạo mới`,onClick:t=>{e?.(),t.stopPropagation(),t.preventDefault()},children:m(o,{})}),m(x,{disabled:!i,"aria-label":`Tạo nhiều`,onClick:e=>{i?.(),e.stopPropagation(),e.preventDefault()},children:m(s,{})}),m(x,{disabled:!p,"aria-label":`Làm mới`,onClick:e=>{p?.(),e.stopPropagation(),e.preventDefault()},children:m(u,{})}),m(x,{disabled:!k,"aria-label":`Tải xuống`,onClick:e=>{O(),e.stopPropagation(),e.preventDefault()},children:m(c,{})}),C&&C.length>0&&m(x,{onClick:e=>{D(),e.stopPropagation(),e.preventDefault()},"aria-pressed":E,"aria-label":E?`Ẩn tổng quan`:`Hiện tổng quan`,className:E?`bg-muted-muted text-text-positive`:void 0,children:m(l,{})}),S&&m(x,{onClick:e=>{T(),e.stopPropagation(),e.preventDefault()},"aria-pressed":w,className:w?`bg-muted-muted text-text-positive`:void 0,children:m(a,{})})]})},C=({children:e})=>{let{title:n,description:r,headerActions:i}=t();return h(`div`,{"data-slot":`table-tooltip`,className:`relative grid w-full grid-cols-1 gap-2 px-2 py-0 text-sm`,children:[h(`div`,{className:`grid w-full grid-cols-[1fr_auto] items-start gap-4`,children:[h(`div`,{className:`grid grid-cols-1 gap-0.5`,children:[m(`h3`,{className:`font-semibold text-base text-text-positive`,children:n}),!!r&&m(`p`,{className:`text-muted-foreground text-sm`,children:r})]}),!!i&&m(`div`,{className:`flex shrink-0 items-center gap-2`,children:i})]}),m(`div`,{className:`grid w-full grid-cols-[1fr_auto] gap-x-2`,children:e})]})};C.displayName=`UITableTooltip`;export{C as UITableTooltip,S as UITableTooltipActions,b as UITableTooltipFilter};
4
+ //# sourceMappingURL=tooltip-DSxSeIak.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"tooltip-D7U_Nl5c.mjs","names":[],"sources":["../packages/components/features/tables/utils/csv.ts","../packages/components/features/tables/components/table/tooltip.tsx"],"sourcesContent":["'use client';\n\nimport type { CsvCell } from '../types';\n\nfunction formatCell(value: CsvCell['value']): string {\n if (value === null || value === undefined) return '';\n if (typeof value === 'number') return String(value);\n if (typeof value === 'boolean') return value ? 'true' : 'false';\n const str = String(value);\n if (str.includes(',') || str.includes('\"') || str.includes('\\n') || str.includes('\\r')) {\n return `\"${str.replace(/\"/g, '\"\"')}\"`;\n }\n return str;\n}\n\nexport function buildCsvContent(rows: CsvCell[][]): string {\n if (rows.length === 0) return '';\n const headers = rows[0].map(cell => formatCell(cell.label));\n const dataRows = rows.map(row => row.map(cell => formatCell(cell.value)).join(','));\n return [headers.join(','), ...dataRows].join('\\n');\n}\n\nexport function downloadCsv(rows: CsvCell[][], fileName: string): void {\n const content = buildCsvContent(rows);\n if (!content) return;\n const blob = new Blob([content], { type: 'text/csv;charset=utf-8;' });\n const url = URL.createObjectURL(blob);\n const link = document.createElement('a');\n link.href = url;\n link.download = `${fileName}.csv`;\n link.click();\n URL.revokeObjectURL(url);\n}\n","/**\n * @file tooltip.tsx\n * Toolbar components rendered above the table: a debounced search input,\n * an action button group (create / refresh / download), and the outer\n * toolbar shell that displays the table title.\n */\nimport { useCallback } from 'react';\n\nimport { ArrowRightIcon, BarChart2Icon, CirclePlus, CopyPlusIcon, DownloadIcon, LayoutDashboardIcon, RefreshCwIcon, SearchIcon } from 'lucide-react';\n\nimport { useDebounceCallback } from '@customafk/react-toolkit/hooks/useDebounceCallback';\nimport { cn } from '@customafk/react-toolkit/utils';\n\nimport { Input } from '@/components/ui/input';\n\nimport { useUITableAnalysisContext, useUITableContext, useUITableSummaryContext } from '../../hooks/use-context';\nimport { downloadCsv } from '../../utils/csv';\n\n/**\n * Debounced search input rendered inside the table toolbar.\n *\n * Fires `onSearch` 500 ms after the user stops typing and delegates all other\n * native input events via the spread `props`.\n *\n * @example\n * ```tsx\n * import { UITableTooltipFilter } from '@customafk/lunas-ui/features/tables';\n *\n * <UITableTooltipFilter\n * placeholder=\"Search users…\"\n * onSearch={value => setQuery(value)}\n * />\n * ```\n */\nexport const UITableTooltipFilter: React.FC<\n Omit<React.ComponentProps<typeof Input>, 'className'> & {\n onSearch?: (value: string) => void;\n }\n> = ({ onSearch, onChange, ...props }) => {\n const debouncedSearch = useDebounceCallback((value: string) => {\n onSearch?.(value);\n }, 500);\n return (\n <div className=\"relative w-full max-w-80 flex-1\">\n <Input\n {...props}\n size=\"lg\"\n type=\"search\"\n placeholder=\"Tìm kiếm...\"\n className=\"flex-1 ps-9 pe-9\"\n onChange={e => {\n onChange?.(e);\n debouncedSearch(e.target.value ?? '');\n }}\n />\n <div className=\"pointer-events-none absolute inset-y-0 inset-s-0 flex items-center justify-center ps-3 text-text-positive-weak peer-disabled:opacity-50\">\n <SearchIcon size={16} />\n </div>\n <button\n className=\"absolute inset-y-0 inset-e-0 flex h-full w-9 items-center justify-center rounded-e-md text-text-positive-weak outline-none transition-[color,box-shadow] hover:text-text-positive focus:z-10 focus-visible:border focus-visible:border-primary-strong focus-visible:ring-[3px] focus-visible:ring-primary-weak disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50\"\n aria-label=\"Submit search\"\n type=\"submit\"\n >\n <ArrowRightIcon size={16} aria-hidden=\"true\" />\n </button>\n </div>\n );\n};\n\nconst ActionButton: React.FC<React.PropsWithChildren<React.ComponentProps<'button'>>> = ({ children, disabled, onClick, className, ...props }) => {\n return (\n <button\n type=\"button\"\n disabled={disabled}\n className={cn(\n 'flex cursor-pointer items-center gap-x-1 rounded-sm border border-border bg-background p-2.5 text-sm text-text-positive-weak outline-none transition-all hover:shadow-card focus:border-border-emphasis focus:bg-muted-muted active:border-border-emphasis active:bg-muted-muted active:text-text-positive disabled:pointer-events-none disabled:cursor-default disabled:opacity-60 [&_svg]:size-3.5',\n className\n )}\n onClick={onClick}\n {...props}\n >\n {children}\n </button>\n );\n};\n\n/**\n * Grouped action buttons (create, refresh, download) displayed in the table\n * toolbar.\n *\n * Each button is disabled automatically when the corresponding handler prop is\n * omitted, so only the actions relevant to a given table need to be provided.\n * A toggle for `UITableSummaryBar` appears automatically when `summary` is\n * non-empty, and a toggle for `UITableAnalysisPanel` appears when\n * `showAnalysisPanel` is `true` (both set on `UITableProvider`).\n * `onCreateMultiple` renders a separate \"bulk create\" button next to the\n * single-item create button; omit it to hide the button entirely.\n *\n * @example\n * ```tsx\n * import { UITableTooltipActions } from '@customafk/lunas-ui/features/tables';\n *\n * <UITableTooltipActions\n * onCreate={() => setOpenCreate(true)}\n * onCreateMultiple={() => setOpenBulkCreate(true)}\n * onRefresh={() => refetch()}\n * />\n * ```\n */\nexport const UITableTooltipActions: React.FC<{\n onCreate?: () => void;\n onCreateMultiple?: () => void;\n onRefresh?: () => void;\n onDownload?: () => void;\n}> = ({ onCreate, onCreateMultiple, onDownload, onRefresh }) => {\n const { table, csvData, csvFileName, title, showAnalysisPanel, summary } = useUITableContext();\n const { isOpen: isAnalysisOpen, toggle: toggleAnalysis } = useUITableAnalysisContext();\n const { isOpen: isSummaryOpen, toggle: toggleSummary } = useUITableSummaryContext();\n\n const handleDownload = useCallback(() => {\n if (onDownload) {\n onDownload();\n return;\n }\n if (!csvData || csvData.length === 0) return;\n const selectedRows = table.getSelectedRowModel().flatRows;\n const rows = selectedRows.length > 0 ? selectedRows.map(row => csvData[row.index]).filter(Boolean) : csvData;\n downloadCsv(rows, csvFileName || title);\n }, [onDownload, csvData, csvFileName, table, title]);\n\n const isDownloadEnabled = !!(onDownload || (csvData && csvData.length > 0));\n\n return (\n <div className=\"flex [&>*:not(:first-child)]:rounded-l-none [&>*:not(:first-child)]:border-l-0 [&>*:not(:last-child)]:rounded-r-none\">\n <ActionButton\n disabled={!onCreate}\n aria-label=\"Tạo mới\"\n onClick={e => {\n onCreate?.();\n e.stopPropagation();\n e.preventDefault();\n }}\n >\n <CirclePlus />\n </ActionButton>\n <ActionButton\n disabled={!onCreateMultiple}\n aria-label=\"Tạo nhiều\"\n onClick={e => {\n onCreateMultiple?.();\n e.stopPropagation();\n e.preventDefault();\n }}\n >\n <CopyPlusIcon />\n </ActionButton>\n <ActionButton\n disabled={!onRefresh}\n aria-label=\"Làm mới\"\n onClick={e => {\n onRefresh?.();\n e.stopPropagation();\n e.preventDefault();\n }}\n >\n <RefreshCwIcon />\n </ActionButton>\n <ActionButton\n disabled={!isDownloadEnabled}\n aria-label=\"Tải xuống\"\n onClick={e => {\n handleDownload();\n e.stopPropagation();\n e.preventDefault();\n }}\n >\n <DownloadIcon />\n </ActionButton>\n {summary && summary.length > 0 && (\n <ActionButton\n onClick={e => {\n toggleSummary();\n e.stopPropagation();\n e.preventDefault();\n }}\n aria-pressed={isSummaryOpen}\n aria-label={isSummaryOpen ? 'Ẩn tổng quan' : 'Hiện tổng quan'}\n className={isSummaryOpen ? 'bg-muted-muted text-text-positive' : undefined}\n >\n <LayoutDashboardIcon />\n </ActionButton>\n )}\n {showAnalysisPanel && (\n <ActionButton\n onClick={e => {\n toggleAnalysis();\n e.stopPropagation();\n e.preventDefault();\n }}\n aria-pressed={isAnalysisOpen}\n className={isAnalysisOpen ? 'bg-muted-muted text-text-positive' : undefined}\n >\n <BarChart2Icon />\n </ActionButton>\n )}\n </div>\n );\n};\n\n/**\n * Outer toolbar shell for the UITable component.\n *\n * Reads the table `title` from `UITableContext` and renders it as a heading\n * above the `children` slot, which typically contains a\n * `UITableTooltipFilter` and/or `UITableTooltipActions`.\n *\n * @example\n * ```tsx\n * import {\n * UITableTooltip,\n * UITableTooltipFilter,\n * UITableTooltipActions,\n * } from '@customafk/lunas-ui/features/tables';\n *\n * <UITableTooltip>\n * <UITableTooltipFilter onSearch={setQuery} />\n * <UITableTooltipActions onCreate={handleCreate} onRefresh={refetch} />\n * </UITableTooltip>\n * ```\n */\nexport const UITableTooltip: React.FC<React.PropsWithChildren> = ({ children }) => {\n const { title, description, headerActions } = useUITableContext();\n return (\n <div data-slot=\"table-tooltip\" className=\"relative grid w-full grid-cols-1 gap-2 px-2 py-0 text-sm\">\n <div className=\"grid w-full grid-cols-[1fr_auto] items-start gap-4\">\n <div className=\"grid grid-cols-1 gap-0.5\">\n <h3 className=\"font-semibold text-base text-text-positive\">{title}</h3>\n {!!description && <p className=\"text-muted-foreground text-sm\">{description}</p>}\n </div>\n {!!headerActions && <div className=\"flex shrink-0 items-center gap-2\">{headerActions}</div>}\n </div>\n <div className=\"grid w-full grid-cols-[1fr_auto] gap-x-2\">{children}</div>\n </div>\n );\n};\nUITableTooltip.displayName = 'UITableTooltip';\n"],"mappings":"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"}
1
+ {"version":3,"file":"tooltip-DSxSeIak.mjs","names":[],"sources":["../packages/components/features/tables/utils/csv.ts","../packages/components/features/tables/components/table/tooltip.tsx"],"sourcesContent":["'use client';\n\nimport type { CsvCell } from '../types';\n\nfunction formatCell(value: CsvCell['value']): string {\n if (value === null || value === undefined) return '';\n if (typeof value === 'number') return String(value);\n if (typeof value === 'boolean') return value ? 'true' : 'false';\n const str = String(value);\n if (str.includes(',') || str.includes('\"') || str.includes('\\n') || str.includes('\\r')) {\n return `\"${str.replace(/\"/g, '\"\"')}\"`;\n }\n return str;\n}\n\nexport function buildCsvContent(rows: CsvCell[][]): string {\n if (rows.length === 0) return '';\n const headers = rows[0].map(cell => formatCell(cell.label));\n const dataRows = rows.map(row => row.map(cell => formatCell(cell.value)).join(','));\n return [headers.join(','), ...dataRows].join('\\n');\n}\n\nexport function downloadCsv(rows: CsvCell[][], fileName: string): void {\n const content = buildCsvContent(rows);\n if (!content) return;\n const blob = new Blob([content], { type: 'text/csv;charset=utf-8;' });\n const url = URL.createObjectURL(blob);\n const link = document.createElement('a');\n link.href = url;\n link.download = `${fileName}.csv`;\n link.click();\n URL.revokeObjectURL(url);\n}\n","/**\n * @file tooltip.tsx\n * Toolbar components rendered above the table: a debounced search input,\n * an action button group (create / refresh / download), and the outer\n * toolbar shell that displays the table title.\n */\nimport { useCallback } from 'react';\n\nimport { ArrowRightIcon, BarChart2Icon, CirclePlus, CopyPlusIcon, DownloadIcon, LayoutDashboardIcon, RefreshCwIcon, SearchIcon } from 'lucide-react';\n\nimport { useDebounceCallback } from '@customafk/react-toolkit/hooks/useDebounceCallback';\nimport { cn } from '@customafk/react-toolkit/utils';\n\nimport { Input } from '@/components/ui/input';\n\nimport { useUITableAnalysisContext, useUITableContext, useUITableSummaryContext } from '../../hooks/use-context';\nimport { downloadCsv } from '../../utils/csv';\n\n/**\n * Debounced search input rendered inside the table toolbar.\n *\n * Fires `onSearch` 500 ms after the user stops typing and delegates all other\n * native input events via the spread `props`.\n *\n * @example\n * ```tsx\n * import { UITableTooltipFilter } from '@customafk/lunas-ui/features/tables';\n *\n * <UITableTooltipFilter\n * placeholder=\"Search users…\"\n * onSearch={value => setQuery(value)}\n * />\n * ```\n */\nexport const UITableTooltipFilter: React.FC<\n Omit<React.ComponentProps<typeof Input>, 'className'> & {\n onSearch?: (value: string) => void;\n }\n> = ({ onSearch, onChange, ...props }) => {\n const debouncedSearch = useDebounceCallback((value: string) => {\n onSearch?.(value);\n }, 500);\n return (\n <div className=\"relative w-full max-w-80 flex-1\">\n <Input\n {...props}\n size=\"lg\"\n type=\"search\"\n placeholder=\"Tìm kiếm...\"\n className=\"flex-1 ps-9 pe-9\"\n onChange={e => {\n onChange?.(e);\n debouncedSearch(e.target.value ?? '');\n }}\n />\n <div className=\"pointer-events-none absolute inset-y-0 inset-s-0 flex items-center justify-center ps-3 text-text-positive-weak peer-disabled:opacity-50\">\n <SearchIcon size={16} />\n </div>\n <button\n className=\"absolute inset-y-0 inset-e-0 flex h-full w-9 items-center justify-center rounded-e-md text-text-positive-weak outline-none transition-[color,box-shadow] hover:text-text-positive focus:z-10 focus-visible:border focus-visible:border-primary-strong focus-visible:ring-[3px] focus-visible:ring-primary-weak disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50\"\n aria-label=\"Submit search\"\n type=\"submit\"\n >\n <ArrowRightIcon size={16} aria-hidden=\"true\" />\n </button>\n </div>\n );\n};\n\nconst ActionButton: React.FC<React.PropsWithChildren<React.ComponentProps<'button'>>> = ({ children, disabled, onClick, className, ...props }) => {\n return (\n <button\n type=\"button\"\n disabled={disabled}\n className={cn(\n 'flex cursor-pointer items-center gap-x-1 rounded-sm border border-border bg-background p-2.5 text-sm text-text-positive-weak outline-none transition-all hover:shadow-card focus:border-border-emphasis focus:bg-muted-muted active:border-border-emphasis active:bg-muted-muted active:text-text-positive disabled:pointer-events-none disabled:cursor-default disabled:opacity-60 [&_svg]:size-3.5',\n className\n )}\n onClick={onClick}\n {...props}\n >\n {children}\n </button>\n );\n};\n\n/**\n * Grouped action buttons (create, refresh, download) displayed in the table\n * toolbar.\n *\n * Each button is disabled automatically when the corresponding handler prop is\n * omitted, so only the actions relevant to a given table need to be provided.\n * A toggle for `UITableSummaryBar` appears automatically when `summary` is\n * non-empty, and a toggle for `UITableAnalysisPanel` appears when\n * `showAnalysisPanel` is `true` (both set on `UITableProvider`).\n * `onCreateMultiple` renders a separate \"bulk create\" button next to the\n * single-item create button; omit it to hide the button entirely.\n *\n * @example\n * ```tsx\n * import { UITableTooltipActions } from '@customafk/lunas-ui/features/tables';\n *\n * <UITableTooltipActions\n * onCreate={() => setOpenCreate(true)}\n * onCreateMultiple={() => setOpenBulkCreate(true)}\n * onRefresh={() => refetch()}\n * />\n * ```\n */\nexport const UITableTooltipActions: React.FC<{\n onCreate?: () => void;\n onCreateMultiple?: () => void;\n onRefresh?: () => void;\n onDownload?: () => void;\n}> = ({ onCreate, onCreateMultiple, onDownload, onRefresh }) => {\n const { table, csvData, csvFileName, title, showAnalysisPanel, summary } = useUITableContext();\n const { isOpen: isAnalysisOpen, toggle: toggleAnalysis } = useUITableAnalysisContext();\n const { isOpen: isSummaryOpen, toggle: toggleSummary } = useUITableSummaryContext();\n\n const handleDownload = useCallback(() => {\n if (onDownload) {\n onDownload();\n return;\n }\n if (!csvData || csvData.length === 0) return;\n const selectedRows = table.getSelectedRowModel().flatRows;\n const rows = selectedRows.length > 0 ? selectedRows.map(row => csvData[row.index]).filter(Boolean) : csvData;\n downloadCsv(rows, csvFileName || title);\n }, [onDownload, csvData, csvFileName, table, title]);\n\n const isDownloadEnabled = !!(onDownload || (csvData && csvData.length > 0));\n\n return (\n <div className=\"flex [&>*:not(:first-child)]:rounded-l-none [&>*:not(:first-child)]:border-l-0 [&>*:not(:last-child)]:rounded-r-none\">\n <ActionButton\n disabled={!onCreate}\n aria-label=\"Tạo mới\"\n onClick={e => {\n onCreate?.();\n e.stopPropagation();\n e.preventDefault();\n }}\n >\n <CirclePlus />\n </ActionButton>\n <ActionButton\n disabled={!onCreateMultiple}\n aria-label=\"Tạo nhiều\"\n onClick={e => {\n onCreateMultiple?.();\n e.stopPropagation();\n e.preventDefault();\n }}\n >\n <CopyPlusIcon />\n </ActionButton>\n <ActionButton\n disabled={!onRefresh}\n aria-label=\"Làm mới\"\n onClick={e => {\n onRefresh?.();\n e.stopPropagation();\n e.preventDefault();\n }}\n >\n <RefreshCwIcon />\n </ActionButton>\n <ActionButton\n disabled={!isDownloadEnabled}\n aria-label=\"Tải xuống\"\n onClick={e => {\n handleDownload();\n e.stopPropagation();\n e.preventDefault();\n }}\n >\n <DownloadIcon />\n </ActionButton>\n {summary && summary.length > 0 && (\n <ActionButton\n onClick={e => {\n toggleSummary();\n e.stopPropagation();\n e.preventDefault();\n }}\n aria-pressed={isSummaryOpen}\n aria-label={isSummaryOpen ? 'Ẩn tổng quan' : 'Hiện tổng quan'}\n className={isSummaryOpen ? 'bg-muted-muted text-text-positive' : undefined}\n >\n <LayoutDashboardIcon />\n </ActionButton>\n )}\n {showAnalysisPanel && (\n <ActionButton\n onClick={e => {\n toggleAnalysis();\n e.stopPropagation();\n e.preventDefault();\n }}\n aria-pressed={isAnalysisOpen}\n className={isAnalysisOpen ? 'bg-muted-muted text-text-positive' : undefined}\n >\n <BarChart2Icon />\n </ActionButton>\n )}\n </div>\n );\n};\n\n/**\n * Outer toolbar shell for the UITable component.\n *\n * Reads the table `title` from `UITableContext` and renders it as a heading\n * above the `children` slot, which typically contains a\n * `UITableTooltipFilter` and/or `UITableTooltipActions`.\n *\n * @example\n * ```tsx\n * import {\n * UITableTooltip,\n * UITableTooltipFilter,\n * UITableTooltipActions,\n * } from '@customafk/lunas-ui/features/tables';\n *\n * <UITableTooltip>\n * <UITableTooltipFilter onSearch={setQuery} />\n * <UITableTooltipActions onCreate={handleCreate} onRefresh={refetch} />\n * </UITableTooltip>\n * ```\n */\nexport const UITableTooltip: React.FC<React.PropsWithChildren> = ({ children }) => {\n const { title, description, headerActions } = useUITableContext();\n return (\n <div data-slot=\"table-tooltip\" className=\"relative grid w-full grid-cols-1 gap-2 px-2 py-0 text-sm\">\n <div className=\"grid w-full grid-cols-[1fr_auto] items-start gap-4\">\n <div className=\"grid grid-cols-1 gap-0.5\">\n <h3 className=\"font-semibold text-base text-text-positive\">{title}</h3>\n {!!description && <p className=\"text-muted-foreground text-sm\">{description}</p>}\n </div>\n {!!headerActions && <div className=\"flex shrink-0 items-center gap-2\">{headerActions}</div>}\n </div>\n <div className=\"grid w-full grid-cols-[1fr_auto] gap-x-2\">{children}</div>\n </div>\n );\n};\nUITableTooltip.displayName = 'UITableTooltip';\n"],"mappings":"mfAIA,SAAS,EAAW,EAAiC,CACnD,GAAI,GAAU,KAA6B,MAAO,GAClD,GAAI,OAAO,GAAU,SAAU,OAAO,OAAO,CAAK,EAClD,GAAI,OAAO,GAAU,UAAW,OAAO,EAAQ,OAAS,QACxD,IAAM,EAAM,OAAO,CAAK,EAIxB,OAHI,EAAI,SAAS,GAAG,GAAK,EAAI,SAAS,GAAG,GAAK,EAAI,SAAS;CAAI,GAAK,EAAI,SAAS,IAAI,EAC5E,IAAI,EAAI,QAAQ,KAAM,IAAI,EAAE,GAE9B,CACT,CAEA,SAAgB,EAAgB,EAA2B,CACzD,GAAI,EAAK,SAAW,EAAG,MAAO,GAC9B,IAAM,EAAU,EAAK,EAAE,CAAC,IAAI,GAAQ,EAAW,EAAK,KAAK,CAAC,EACpD,EAAW,EAAK,IAAI,GAAO,EAAI,IAAI,GAAQ,EAAW,EAAK,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,EAClF,MAAO,CAAC,EAAQ,KAAK,GAAG,EAAG,GAAG,CAAQ,CAAC,CAAC,KAAK;CAAI,CACnD,CAEA,SAAgB,EAAY,EAAmB,EAAwB,CACrE,IAAM,EAAU,EAAgB,CAAI,EACpC,GAAI,CAAC,EAAS,OACd,IAAM,EAAO,IAAI,KAAK,CAAC,CAAO,EAAG,CAAE,KAAM,yBAA0B,CAAC,EAC9D,EAAM,IAAI,gBAAgB,CAAI,EAC9B,EAAO,SAAS,cAAc,GAAG,EACvC,EAAK,KAAO,EACZ,EAAK,SAAW,GAAG,EAAS,MAC5B,EAAK,MAAM,EACX,IAAI,gBAAgB,CAAG,CACzB,CCEA,MAAa,GAIR,CAAE,WAAU,WAAU,GAAG,KAAY,CACxC,IAAM,EAAkB,EAAqB,GAAkB,CAC7D,IAAW,CAAK,CAClB,EAAG,GAAG,EACN,OACE,EAAC,MAAD,CAAK,UAAU,kCAAf,SAAA,CACE,EAAC,EAAD,CACE,GAAI,EACJ,KAAK,KACL,KAAK,SACL,YAAY,cACZ,UAAU,mBACV,SAAU,GAAK,CACb,IAAW,CAAC,EACZ,EAAgB,EAAE,OAAO,OAAS,EAAE,CACtC,CACD,CAAA,EACD,EAAC,MAAD,CAAK,UAAU,0IACb,SAAA,EAAC,EAAD,CAAY,KAAM,EAAK,CAAA,CACpB,CAAA,EACL,EAAC,SAAD,CACE,UAAU,8XACV,aAAW,gBACX,KAAK,SAEL,SAAA,EAAC,EAAD,CAAgB,KAAM,GAAI,cAAY,MAAQ,CAAA,CACxC,CAAA,CACL,GAET,EAEM,GAAmF,CAAE,WAAU,WAAU,UAAS,YAAW,GAAG,KAElI,EAAC,SAAD,CACE,KAAK,SACK,WACV,UAAW,EACT,uYACA,CACF,EACS,UACT,GAAI,EAEH,UACK,CAAA,EA2BC,GAKP,CAAE,WAAU,mBAAkB,aAAY,eAAgB,CAC9D,GAAM,CAAE,QAAO,UAAS,cAAa,QAAO,oBAAmB,WAAY,EAAkB,EACvF,CAAE,OAAQ,EAAgB,OAAQ,GAAmB,EAA0B,EAC/E,CAAE,OAAQ,EAAe,OAAQ,GAAkB,EAAyB,EAE5E,EAAiB,MAAkB,CACvC,GAAI,EAAY,CACd,EAAW,EACX,MACF,CACA,GAAI,CAAC,GAAW,EAAQ,SAAW,EAAG,OACtC,IAAM,EAAe,EAAM,oBAAoB,CAAC,CAAC,SAEjD,EADa,EAAa,OAAS,EAAI,EAAa,IAAI,GAAO,EAAQ,EAAI,MAAM,CAAC,CAAC,OAAO,OAAO,EAAI,EACnF,GAAe,CAAK,CACxC,EAAG,CAAC,EAAY,EAAS,EAAa,EAAO,CAAK,CAAC,EAE7C,EAAoB,CAAC,EAAE,GAAe,GAAW,EAAQ,OAAS,GAExE,OACE,EAAC,MAAD,CAAK,UAAU,uHAAf,SAAA,CACE,EAAC,EAAD,CACE,SAAU,CAAC,EACX,aAAW,UACX,QAAS,GAAK,CACZ,IAAW,EACX,EAAE,gBAAgB,EAClB,EAAE,eAAe,CACnB,EAEA,SAAA,EAAC,EAAD,CAAa,CAAA,CACD,CAAA,EACd,EAAC,EAAD,CACE,SAAU,CAAC,EACX,aAAW,YACX,QAAS,GAAK,CACZ,IAAmB,EACnB,EAAE,gBAAgB,EAClB,EAAE,eAAe,CACnB,EAEA,SAAA,EAAC,EAAD,CAAe,CAAA,CACH,CAAA,EACd,EAAC,EAAD,CACE,SAAU,CAAC,EACX,aAAW,UACX,QAAS,GAAK,CACZ,IAAY,EACZ,EAAE,gBAAgB,EAClB,EAAE,eAAe,CACnB,EAEA,SAAA,EAAC,EAAD,CAAgB,CAAA,CACJ,CAAA,EACd,EAAC,EAAD,CACE,SAAU,CAAC,EACX,aAAW,YACX,QAAS,GAAK,CACZ,EAAe,EACf,EAAE,gBAAgB,EAClB,EAAE,eAAe,CACnB,EAEA,SAAA,EAAC,EAAD,CAAe,CAAA,CACH,CAAA,EACb,GAAW,EAAQ,OAAS,GAC3B,EAAC,EAAD,CACE,QAAS,GAAK,CACZ,EAAc,EACd,EAAE,gBAAgB,EAClB,EAAE,eAAe,CACnB,EACA,eAAc,EACd,aAAY,EAAgB,eAAiB,iBAC7C,UAAW,EAAgB,oCAAsC,IAAA,GAEjE,SAAA,EAAC,EAAD,CAAsB,CAAA,CACV,CAAA,EAEf,GACC,EAAC,EAAD,CACE,QAAS,GAAK,CACZ,EAAe,EACf,EAAE,gBAAgB,EAClB,EAAE,eAAe,CACnB,EACA,eAAc,EACd,UAAW,EAAiB,oCAAsC,IAAA,GAElE,SAAA,EAAC,EAAD,CAAgB,CAAA,CACJ,CAAA,CAEb,GAET,EAuBa,GAAqD,CAAE,cAAe,CACjF,GAAM,CAAE,QAAO,cAAa,iBAAkB,EAAkB,EAChE,OACE,EAAC,MAAD,CAAK,YAAU,gBAAgB,UAAU,2DAAzC,SAAA,CACE,EAAC,MAAD,CAAK,UAAU,qDAAf,SAAA,CACE,EAAC,MAAD,CAAK,UAAU,2BAAf,SAAA,CACE,EAAC,KAAD,CAAI,UAAU,6CAA8C,SAAA,CAAU,CAAA,EACrE,CAAC,CAAC,GAAe,EAAC,IAAD,CAAG,UAAU,gCAAiC,SAAA,CAAe,CAAA,CAC5E,CACJ,CAAA,EAAA,CAAC,CAAC,GAAiB,EAAC,MAAD,CAAK,UAAU,mCAAoC,SAAA,CAAmB,CAAA,CACvF,CACL,CAAA,EAAA,EAAC,MAAD,CAAK,UAAU,2CAA4C,UAAc,CAAA,CACtE,GAET,EACA,EAAe,YAAc"}
@@ -1,2 +1,2 @@
1
- import { n as ParagraphProps, r as paragraphVariants, t as Paragraph } from "../paragraph-CkCNIsvz.cjs";
1
+ import { n as ParagraphProps, r as paragraphVariants, t as Paragraph } from "../paragraph--8GcgnQL.cjs";
2
2
  export { Paragraph, ParagraphProps, paragraphVariants };
@@ -1,2 +1,2 @@
1
- import { n as ParagraphProps, r as paragraphVariants, t as Paragraph } from "../paragraph-CRo5eC7H.mjs";
1
+ import { n as ParagraphProps, r as paragraphVariants, t as Paragraph } from "../paragraph-BOa0VlGX.mjs";
2
2
  export { Paragraph, ParagraphProps, paragraphVariants };
package/dist/ui/badge.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use client";Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require("@customafk/react-toolkit/utils"),t=require("class-variance-authority"),n=require("react/jsx-runtime");const r=(0,t.cva)(`inline-flex items-center justify-center font-medium transition-colors duration-150 focus:ring-2 focus:ring-offset-2 focus:outline-hidden focus:ring-ring forced-colors:outline`,{variants:{variant:{solid:`shadow-btn`,soft:``,outline:`bg-transparent border`},color:{primary:``,secondary:``,muted:``,accent:``,info:``,success:``,warning:``,danger:``},size:{xs:`text-[10px]/3 px-1.5 py-0.5 gap-1`,sm:`text-xs px-2 py-0.5 gap-1`,md:`text-sm px-2.5 py-0.5 gap-1.5`,lg:`text-base px-3 py-1 gap-1.5`,xl:`text-lg px-3.5 py-1 gap-1.5`},pill:{true:`rounded-full`,false:`rounded`}},defaultVariants:{variant:`solid`,color:`primary`,size:`md`,pill:!0},compoundVariants:[{variant:`solid`,color:`primary`,className:`bg-primary text-primary-foreground`},{variant:`solid`,color:`secondary`,className:`bg-secondary text-secondary-foreground`},{variant:`solid`,color:`muted`,className:`bg-muted text-text-negative`},{variant:`solid`,color:`accent`,className:`bg-accent text-text-negative`},{variant:`solid`,color:`info`,className:`bg-info text-info-foreground`},{variant:`solid`,color:`success`,className:`bg-success text-success-foreground`},{variant:`solid`,color:`warning`,className:`bg-warning text-text-negative`},{variant:`solid`,color:`danger`,className:`bg-danger text-danger-foreground`},{variant:`soft`,color:`primary`,className:`bg-primary-bg-subtle text-primary-intense`},{variant:`soft`,color:`secondary`,className:`bg-secondary-bg-subtle text-secondary-intense`},{variant:`soft`,color:`muted`,className:`bg-muted-bg-subtle text-muted-intense`},{variant:`soft`,color:`accent`,className:`bg-accent-bg-subtle text-accent-intense`},{variant:`soft`,color:`info`,className:`bg-info-bg-subtle text-info-intense`},{variant:`soft`,color:`success`,className:`bg-success-bg-subtle text-success-intense`},{variant:`soft`,color:`warning`,className:`bg-warning-bg-subtle text-warning-intense`},{variant:`soft`,color:`danger`,className:`bg-danger-bg-subtle text-danger-intense`},{variant:`outline`,color:`primary`,className:`border-primary text-primary`},{variant:`outline`,color:`secondary`,className:`border-secondary text-secondary`},{variant:`outline`,color:`muted`,className:`border-muted text-muted`},{variant:`outline`,color:`accent`,className:`border-accent text-accent`},{variant:`outline`,color:`info`,className:`border-info text-info`},{variant:`outline`,color:`success`,className:`border-success text-success`},{variant:`outline`,color:`warning`,className:`border-warning text-warning`},{variant:`outline`,color:`danger`,className:`border-danger text-danger`}]});function i({className:t,variant:i,color:a,size:o,pill:s,...c}){return(0,n.jsx)(`span`,{className:(0,e.cn)(r({variant:i,color:a,pill:s,size:o}),t),...c})}exports.Badge=i,exports.badgeVariants=r;
1
+ "use client";Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require("@customafk/react-toolkit/utils"),t=require("class-variance-authority"),n=require("react/jsx-runtime");const r=(0,t.cva)(`inline-flex items-center justify-center font-medium transition-colors duration-150 focus:ring-2 focus:ring-offset-2 focus:outline-hidden focus:ring-ring forced-colors:outline`,{variants:{variant:{solid:`shadow-btn`,soft:``,outline:`bg-transparent border`},color:{primary:``,secondary:``,muted:``,accent:``,info:``,success:``,warning:``,danger:``},size:{xs:`text-[10px]/3 px-1.5 py-0.5 gap-1`,sm:`text-xs px-2 py-0.5 gap-1`,md:`text-sm px-2.5 py-0.5 gap-1.5`,lg:`text-base px-3 py-1 gap-1.5`,xl:`text-lg px-3.5 py-1 gap-1.5`},pill:{true:`rounded-full`,false:`rounded`}},defaultVariants:{variant:`solid`,color:`primary`,size:`md`,pill:!0},compoundVariants:[{variant:`solid`,color:`primary`,className:`bg-primary text-primary-foreground`},{variant:`solid`,color:`secondary`,className:`bg-secondary text-secondary-foreground`},{variant:`solid`,color:`muted`,className:`bg-muted text-text-negative`},{variant:`solid`,color:`accent`,className:`bg-accent text-text-negative`},{variant:`solid`,color:`info`,className:`bg-info text-info-foreground`},{variant:`solid`,color:`success`,className:`bg-success text-success-foreground`},{variant:`solid`,color:`warning`,className:`bg-warning text-text-negative`},{variant:`solid`,color:`danger`,className:`bg-danger text-danger-foreground`},{variant:`soft`,color:`primary`,className:`bg-primary-bg-subtle text-primary-intense`},{variant:`soft`,color:`secondary`,className:`bg-secondary-bg-subtle text-secondary-intense`},{variant:`soft`,color:`muted`,className:`bg-muted-bg-subtle text-muted-intense`},{variant:`soft`,color:`accent`,className:`bg-accent-bg-subtle text-accent-intense`},{variant:`soft`,color:`info`,className:`bg-info-bg-subtle text-info-intense`},{variant:`soft`,color:`success`,className:`bg-success-bg-subtle text-success-intense`},{variant:`soft`,color:`warning`,className:`bg-warning-bg-subtle text-warning-intense`},{variant:`soft`,color:`danger`,className:`bg-danger-bg-subtle text-danger-intense`},{variant:`outline`,color:`primary`,className:`border-primary text-primary`},{variant:`outline`,color:`secondary`,className:`border-secondary text-secondary`},{variant:`outline`,color:`muted`,className:`border-muted text-muted`},{variant:`outline`,color:`accent`,className:`border-accent text-accent`},{variant:`outline`,color:`info`,className:`border-info text-info`},{variant:`outline`,color:`success`,className:`border-success text-success`},{variant:`outline`,color:`warning`,className:`border-warning text-warning`},{variant:`outline`,color:`danger`,className:`border-danger text-danger`}]});function i({className:t,variant:i,color:a,size:o,pill:s,...c}){return(0,n.jsx)(`span`,{className:(0,e.cn)(r({variant:i,color:a,pill:s,size:o}),t),...c})}const a=(0,t.cva)(`inline-block size-1.5 shrink-0 rounded-full`,{variants:{color:{primary:`bg-primary`,secondary:`bg-secondary`,muted:`bg-muted`,accent:`bg-accent`,info:`bg-info`,success:`bg-success`,warning:`bg-warning`,danger:`bg-danger`}},defaultVariants:{color:`primary`}});exports.Badge=i,exports.badgeDotVariants=a,exports.badgeVariants=r;
2
2
  //# sourceMappingURL=badge.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"badge.cjs","names":[],"sources":["../../packages/components/ui/badge.tsx"],"sourcesContent":["'use client';\n\nimport { cn } from '@customafk/react-toolkit/utils';\n\nimport { cva, type VariantProps } from 'class-variance-authority';\n\nconst badgeVariants = cva(\n 'inline-flex items-center justify-center font-medium transition-colors duration-150 focus:ring-2 focus:ring-offset-2 focus:outline-hidden focus:ring-ring forced-colors:outline',\n {\n variants: {\n variant: {\n solid: 'shadow-btn',\n soft: '',\n outline: 'bg-transparent border',\n },\n color: {\n primary: '',\n secondary: '',\n muted: '',\n accent: '',\n info: '',\n success: '',\n warning: '',\n danger: '',\n },\n size: {\n xs: 'text-[10px]/3 px-1.5 py-0.5 gap-1',\n sm: 'text-xs px-2 py-0.5 gap-1',\n md: 'text-sm px-2.5 py-0.5 gap-1.5',\n lg: 'text-base px-3 py-1 gap-1.5',\n xl: 'text-lg px-3.5 py-1 gap-1.5',\n },\n pill: {\n true: 'rounded-full',\n false: 'rounded',\n },\n },\n defaultVariants: {\n variant: 'solid',\n color: 'primary',\n size: 'md',\n pill: true,\n },\n compoundVariants: [\n // solid\n { variant: 'solid', color: 'primary', className: 'bg-primary text-primary-foreground' },\n { variant: 'solid', color: 'secondary', className: 'bg-secondary text-secondary-foreground' },\n { variant: 'solid', color: 'muted', className: 'bg-muted text-text-negative' },\n { variant: 'solid', color: 'accent', className: 'bg-accent text-text-negative' },\n { variant: 'solid', color: 'info', className: 'bg-info text-info-foreground' },\n { variant: 'solid', color: 'success', className: 'bg-success text-success-foreground' },\n { variant: 'solid', color: 'warning', className: 'bg-warning text-text-negative' },\n { variant: 'solid', color: 'danger', className: 'bg-danger text-danger-foreground' },\n // soft\n { variant: 'soft', color: 'primary', className: 'bg-primary-bg-subtle text-primary-intense' },\n { variant: 'soft', color: 'secondary', className: 'bg-secondary-bg-subtle text-secondary-intense' },\n { variant: 'soft', color: 'muted', className: 'bg-muted-bg-subtle text-muted-intense' },\n { variant: 'soft', color: 'accent', className: 'bg-accent-bg-subtle text-accent-intense' },\n { variant: 'soft', color: 'info', className: 'bg-info-bg-subtle text-info-intense' },\n { variant: 'soft', color: 'success', className: 'bg-success-bg-subtle text-success-intense' },\n { variant: 'soft', color: 'warning', className: 'bg-warning-bg-subtle text-warning-intense' },\n { variant: 'soft', color: 'danger', className: 'bg-danger-bg-subtle text-danger-intense' },\n // outline\n { variant: 'outline', color: 'primary', className: 'border-primary text-primary' },\n { variant: 'outline', color: 'secondary', className: 'border-secondary text-secondary' },\n { variant: 'outline', color: 'muted', className: 'border-muted text-muted' },\n { variant: 'outline', color: 'accent', className: 'border-accent text-accent' },\n { variant: 'outline', color: 'info', className: 'border-info text-info' },\n { variant: 'outline', color: 'success', className: 'border-success text-success' },\n { variant: 'outline', color: 'warning', className: 'border-warning text-warning' },\n { variant: 'outline', color: 'danger', className: 'border-danger text-danger' },\n ],\n }\n);\n\n/**\n * Props for the `Badge` component.\n *\n * @property variant - Visual fill style — `'solid'` (filled, default), `'soft'` (tinted background), or `'outline'` (border only).\n * @property color - Semantic color token — `'primary'` | `'secondary'` | `'muted'` | `'accent'` | `'info'` | `'success'` | `'warning'` | `'danger'`. Defaults to `'primary'`.\n * @property size - Badge size — `'xs'` | `'sm'` | `'md'` (default) | `'lg'` | `'xl'`.\n * @property pill - When `true` (default), renders with fully rounded corners (`rounded-full`); when `false`, uses `rounded-sm`.\n */\nexport type BadgeProps = VariantProps<typeof badgeVariants> & React.ComponentPropsWithoutRef<'span'>;\n\n/**\n * Inline status label rendered as a `<span>` with CVA-driven variant, color, size, and shape options.\n *\n * @example\n * ```tsx\n * import { Badge } from '@customafk/lunas-ui/ui/badge';\n *\n * <Badge variant=\"soft\" color=\"success\" size=\"sm\">Active</Badge>\n * <Badge variant=\"outline\" color=\"danger\">Overdue</Badge>\n * ```\n */\nfunction Badge({ className, variant, color, size, pill, ...props }: BadgeProps) {\n return <span className={cn(badgeVariants({ variant, color, pill, size }), className)} {...props} />;\n}\n\n// eslint-disable-next-line react-refresh/only-export-components\nexport { Badge, badgeVariants };\n"],"mappings":"qMAMA,MAAM,GAAA,EAAA,EAAA,IAAA,CACJ,iLACA,CACE,SAAU,CACR,QAAS,CACP,MAAO,aACP,KAAM,GACN,QAAS,uBACX,EACA,MAAO,CACL,QAAS,GACT,UAAW,GACX,MAAO,GACP,OAAQ,GACR,KAAM,GACN,QAAS,GACT,QAAS,GACT,OAAQ,EACV,EACA,KAAM,CACJ,GAAI,oCACJ,GAAI,4BACJ,GAAI,gCACJ,GAAI,8BACJ,GAAI,6BACN,EACA,KAAM,CACJ,KAAM,eACN,MAAO,SACT,CACF,EACA,gBAAiB,CACf,QAAS,QACT,MAAO,UACP,KAAM,KACN,KAAM,EACR,EACA,iBAAkB,CAEhB,CAAE,QAAS,QAAS,MAAO,UAAW,UAAW,oCAAqC,EACtF,CAAE,QAAS,QAAS,MAAO,YAAa,UAAW,wCAAyC,EAC5F,CAAE,QAAS,QAAS,MAAO,QAAS,UAAW,6BAA8B,EAC7E,CAAE,QAAS,QAAS,MAAO,SAAU,UAAW,8BAA+B,EAC/E,CAAE,QAAS,QAAS,MAAO,OAAQ,UAAW,8BAA+B,EAC7E,CAAE,QAAS,QAAS,MAAO,UAAW,UAAW,oCAAqC,EACtF,CAAE,QAAS,QAAS,MAAO,UAAW,UAAW,+BAAgC,EACjF,CAAE,QAAS,QAAS,MAAO,SAAU,UAAW,kCAAmC,EAEnF,CAAE,QAAS,OAAQ,MAAO,UAAW,UAAW,2CAA4C,EAC5F,CAAE,QAAS,OAAQ,MAAO,YAAa,UAAW,+CAAgD,EAClG,CAAE,QAAS,OAAQ,MAAO,QAAS,UAAW,uCAAwC,EACtF,CAAE,QAAS,OAAQ,MAAO,SAAU,UAAW,yCAA0C,EACzF,CAAE,QAAS,OAAQ,MAAO,OAAQ,UAAW,qCAAsC,EACnF,CAAE,QAAS,OAAQ,MAAO,UAAW,UAAW,2CAA4C,EAC5F,CAAE,QAAS,OAAQ,MAAO,UAAW,UAAW,2CAA4C,EAC5F,CAAE,QAAS,OAAQ,MAAO,SAAU,UAAW,yCAA0C,EAEzF,CAAE,QAAS,UAAW,MAAO,UAAW,UAAW,6BAA8B,EACjF,CAAE,QAAS,UAAW,MAAO,YAAa,UAAW,iCAAkC,EACvF,CAAE,QAAS,UAAW,MAAO,QAAS,UAAW,yBAA0B,EAC3E,CAAE,QAAS,UAAW,MAAO,SAAU,UAAW,2BAA4B,EAC9E,CAAE,QAAS,UAAW,MAAO,OAAQ,UAAW,uBAAwB,EACxE,CAAE,QAAS,UAAW,MAAO,UAAW,UAAW,6BAA8B,EACjF,CAAE,QAAS,UAAW,MAAO,UAAW,UAAW,6BAA8B,EACjF,CAAE,QAAS,UAAW,MAAO,SAAU,UAAW,2BAA4B,CAChF,CACF,CACF,EAuBA,SAAS,EAAM,CAAE,YAAW,UAAS,QAAO,OAAM,OAAM,GAAG,GAAqB,CAC9E,OAAO,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,WAAA,EAAA,EAAA,GAAA,CAAc,EAAc,CAAE,UAAS,QAAO,OAAM,MAAK,CAAC,EAAG,CAAS,EAAG,GAAI,CAAQ,CAAA,CACpG"}
1
+ {"version":3,"file":"badge.cjs","names":[],"sources":["../../packages/components/ui/badge.tsx"],"sourcesContent":["'use client';\n\nimport { cn } from '@customafk/react-toolkit/utils';\n\nimport { cva, type VariantProps } from 'class-variance-authority';\n\nconst badgeVariants = cva(\n 'inline-flex items-center justify-center font-medium transition-colors duration-150 focus:ring-2 focus:ring-offset-2 focus:outline-hidden focus:ring-ring forced-colors:outline',\n {\n variants: {\n variant: {\n solid: 'shadow-btn',\n soft: '',\n outline: 'bg-transparent border',\n },\n color: {\n primary: '',\n secondary: '',\n muted: '',\n accent: '',\n info: '',\n success: '',\n warning: '',\n danger: '',\n },\n size: {\n xs: 'text-[10px]/3 px-1.5 py-0.5 gap-1',\n sm: 'text-xs px-2 py-0.5 gap-1',\n md: 'text-sm px-2.5 py-0.5 gap-1.5',\n lg: 'text-base px-3 py-1 gap-1.5',\n xl: 'text-lg px-3.5 py-1 gap-1.5',\n },\n pill: {\n true: 'rounded-full',\n false: 'rounded',\n },\n },\n defaultVariants: {\n variant: 'solid',\n color: 'primary',\n size: 'md',\n pill: true,\n },\n compoundVariants: [\n // solid\n { variant: 'solid', color: 'primary', className: 'bg-primary text-primary-foreground' },\n { variant: 'solid', color: 'secondary', className: 'bg-secondary text-secondary-foreground' },\n { variant: 'solid', color: 'muted', className: 'bg-muted text-text-negative' },\n { variant: 'solid', color: 'accent', className: 'bg-accent text-text-negative' },\n { variant: 'solid', color: 'info', className: 'bg-info text-info-foreground' },\n { variant: 'solid', color: 'success', className: 'bg-success text-success-foreground' },\n { variant: 'solid', color: 'warning', className: 'bg-warning text-text-negative' },\n { variant: 'solid', color: 'danger', className: 'bg-danger text-danger-foreground' },\n // soft\n { variant: 'soft', color: 'primary', className: 'bg-primary-bg-subtle text-primary-intense' },\n { variant: 'soft', color: 'secondary', className: 'bg-secondary-bg-subtle text-secondary-intense' },\n { variant: 'soft', color: 'muted', className: 'bg-muted-bg-subtle text-muted-intense' },\n { variant: 'soft', color: 'accent', className: 'bg-accent-bg-subtle text-accent-intense' },\n { variant: 'soft', color: 'info', className: 'bg-info-bg-subtle text-info-intense' },\n { variant: 'soft', color: 'success', className: 'bg-success-bg-subtle text-success-intense' },\n { variant: 'soft', color: 'warning', className: 'bg-warning-bg-subtle text-warning-intense' },\n { variant: 'soft', color: 'danger', className: 'bg-danger-bg-subtle text-danger-intense' },\n // outline\n { variant: 'outline', color: 'primary', className: 'border-primary text-primary' },\n { variant: 'outline', color: 'secondary', className: 'border-secondary text-secondary' },\n { variant: 'outline', color: 'muted', className: 'border-muted text-muted' },\n { variant: 'outline', color: 'accent', className: 'border-accent text-accent' },\n { variant: 'outline', color: 'info', className: 'border-info text-info' },\n { variant: 'outline', color: 'success', className: 'border-success text-success' },\n { variant: 'outline', color: 'warning', className: 'border-warning text-warning' },\n { variant: 'outline', color: 'danger', className: 'border-danger text-danger' },\n ],\n }\n);\n\n/**\n * Props for the `Badge` component.\n *\n * @property variant - Visual fill style — `'solid'` (filled, default), `'soft'` (tinted background), or `'outline'` (border only).\n * @property color - Semantic color token — `'primary'` | `'secondary'` | `'muted'` | `'accent'` | `'info'` | `'success'` | `'warning'` | `'danger'`. Defaults to `'primary'`.\n * @property size - Badge size — `'xs'` | `'sm'` | `'md'` (default) | `'lg'` | `'xl'`.\n * @property pill - When `true` (default), renders with fully rounded corners (`rounded-full`); when `false`, uses `rounded-sm`.\n */\nexport type BadgeProps = VariantProps<typeof badgeVariants> & React.ComponentPropsWithoutRef<'span'>;\n\n/**\n * Inline status label rendered as a `<span>` with CVA-driven variant, color, size, and shape options.\n *\n * @example\n * ```tsx\n * import { Badge } from '@customafk/lunas-ui/ui/badge';\n *\n * <Badge variant=\"soft\" color=\"success\" size=\"sm\">Active</Badge>\n * <Badge variant=\"outline\" color=\"danger\">Overdue</Badge>\n * ```\n */\nfunction Badge({ className, variant, color, size, pill, ...props }: BadgeProps) {\n return <span className={cn(badgeVariants({ variant, color, pill, size }), className)} {...props} />;\n}\n\n/**\n * Dot indicator fill color, keyed by the same `color` union as `badgeVariants`, so the palette\n * has a single home instead of being re-declared by each consumer that pairs a status dot with a Badge.\n */\nexport const badgeDotVariants = cva('inline-block size-1.5 shrink-0 rounded-full', {\n variants: {\n color: {\n primary: 'bg-primary',\n secondary: 'bg-secondary',\n muted: 'bg-muted',\n accent: 'bg-accent',\n info: 'bg-info',\n success: 'bg-success',\n warning: 'bg-warning',\n danger: 'bg-danger',\n },\n },\n defaultVariants: {\n color: 'primary',\n },\n});\n\n// eslint-disable-next-line react-refresh/only-export-components\nexport { Badge, badgeVariants };\n"],"mappings":"qMAMA,MAAM,GAAA,EAAA,EAAA,IAAA,CACJ,iLACA,CACE,SAAU,CACR,QAAS,CACP,MAAO,aACP,KAAM,GACN,QAAS,uBACX,EACA,MAAO,CACL,QAAS,GACT,UAAW,GACX,MAAO,GACP,OAAQ,GACR,KAAM,GACN,QAAS,GACT,QAAS,GACT,OAAQ,EACV,EACA,KAAM,CACJ,GAAI,oCACJ,GAAI,4BACJ,GAAI,gCACJ,GAAI,8BACJ,GAAI,6BACN,EACA,KAAM,CACJ,KAAM,eACN,MAAO,SACT,CACF,EACA,gBAAiB,CACf,QAAS,QACT,MAAO,UACP,KAAM,KACN,KAAM,EACR,EACA,iBAAkB,CAEhB,CAAE,QAAS,QAAS,MAAO,UAAW,UAAW,oCAAqC,EACtF,CAAE,QAAS,QAAS,MAAO,YAAa,UAAW,wCAAyC,EAC5F,CAAE,QAAS,QAAS,MAAO,QAAS,UAAW,6BAA8B,EAC7E,CAAE,QAAS,QAAS,MAAO,SAAU,UAAW,8BAA+B,EAC/E,CAAE,QAAS,QAAS,MAAO,OAAQ,UAAW,8BAA+B,EAC7E,CAAE,QAAS,QAAS,MAAO,UAAW,UAAW,oCAAqC,EACtF,CAAE,QAAS,QAAS,MAAO,UAAW,UAAW,+BAAgC,EACjF,CAAE,QAAS,QAAS,MAAO,SAAU,UAAW,kCAAmC,EAEnF,CAAE,QAAS,OAAQ,MAAO,UAAW,UAAW,2CAA4C,EAC5F,CAAE,QAAS,OAAQ,MAAO,YAAa,UAAW,+CAAgD,EAClG,CAAE,QAAS,OAAQ,MAAO,QAAS,UAAW,uCAAwC,EACtF,CAAE,QAAS,OAAQ,MAAO,SAAU,UAAW,yCAA0C,EACzF,CAAE,QAAS,OAAQ,MAAO,OAAQ,UAAW,qCAAsC,EACnF,CAAE,QAAS,OAAQ,MAAO,UAAW,UAAW,2CAA4C,EAC5F,CAAE,QAAS,OAAQ,MAAO,UAAW,UAAW,2CAA4C,EAC5F,CAAE,QAAS,OAAQ,MAAO,SAAU,UAAW,yCAA0C,EAEzF,CAAE,QAAS,UAAW,MAAO,UAAW,UAAW,6BAA8B,EACjF,CAAE,QAAS,UAAW,MAAO,YAAa,UAAW,iCAAkC,EACvF,CAAE,QAAS,UAAW,MAAO,QAAS,UAAW,yBAA0B,EAC3E,CAAE,QAAS,UAAW,MAAO,SAAU,UAAW,2BAA4B,EAC9E,CAAE,QAAS,UAAW,MAAO,OAAQ,UAAW,uBAAwB,EACxE,CAAE,QAAS,UAAW,MAAO,UAAW,UAAW,6BAA8B,EACjF,CAAE,QAAS,UAAW,MAAO,UAAW,UAAW,6BAA8B,EACjF,CAAE,QAAS,UAAW,MAAO,SAAU,UAAW,2BAA4B,CAChF,CACF,CACF,EAuBA,SAAS,EAAM,CAAE,YAAW,UAAS,QAAO,OAAM,OAAM,GAAG,GAAqB,CAC9E,OAAO,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,WAAA,EAAA,EAAA,GAAA,CAAc,EAAc,CAAE,UAAS,QAAO,OAAM,MAAK,CAAC,EAAG,CAAS,EAAG,GAAI,CAAQ,CAAA,CACpG,CAMA,MAAa,GAAA,EAAA,EAAA,IAAA,CAAuB,8CAA+C,CACjF,SAAU,CACR,MAAO,CACL,QAAS,aACT,UAAW,eACX,MAAO,WACP,OAAQ,YACR,KAAM,UACN,QAAS,aACT,QAAS,aACT,OAAQ,WACV,CACF,EACA,gBAAiB,CACf,MAAO,SACT,CACF,CAAC"}