@7pmlabs/design-system 2.0.8 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (377) hide show
  1. package/README.md +4 -4
  2. package/dist/design-system.css +1 -1
  3. package/dist/design-system.js +65 -59
  4. package/dist/design-system100.js +1 -1
  5. package/dist/design-system100.js.map +1 -1
  6. package/dist/design-system101.js +87 -53
  7. package/dist/design-system101.js.map +1 -1
  8. package/dist/design-system103.js +5 -13
  9. package/dist/design-system103.js.map +1 -1
  10. package/dist/design-system104.js +53 -108
  11. package/dist/design-system104.js.map +1 -1
  12. package/dist/{design-system102.js → design-system105.js} +1 -1
  13. package/dist/{design-system102.js.map → design-system105.js.map} +1 -1
  14. package/dist/design-system106.js +13 -6
  15. package/dist/design-system106.js.map +1 -1
  16. package/dist/design-system107.js +93 -190
  17. package/dist/design-system107.js.map +1 -1
  18. package/dist/design-system109.js +2 -2
  19. package/dist/design-system109.js.map +1 -1
  20. package/dist/design-system110.js +183 -484
  21. package/dist/design-system110.js.map +1 -1
  22. package/dist/design-system112.js +5 -4
  23. package/dist/design-system112.js.map +1 -1
  24. package/dist/design-system113.js +507 -7
  25. package/dist/design-system113.js.map +1 -1
  26. package/dist/design-system115.js +8 -0
  27. package/dist/design-system115.js.map +1 -0
  28. package/dist/design-system116.js +7 -6
  29. package/dist/design-system116.js.map +1 -1
  30. package/dist/design-system117.js +154 -169
  31. package/dist/design-system117.js.map +1 -1
  32. package/dist/design-system119.js +2 -2
  33. package/dist/design-system119.js.map +1 -1
  34. package/dist/design-system120.js +210 -149
  35. package/dist/design-system120.js.map +1 -1
  36. package/dist/design-system122.js +5 -4
  37. package/dist/design-system122.js.map +1 -1
  38. package/dist/design-system123.js +160 -9
  39. package/dist/design-system123.js.map +1 -1
  40. package/dist/design-system125.js +8 -0
  41. package/dist/design-system125.js.map +1 -0
  42. package/dist/design-system126.js +176 -6
  43. package/dist/design-system126.js.map +1 -1
  44. package/dist/design-system128.js +8 -0
  45. package/dist/design-system128.js.map +1 -0
  46. package/dist/design-system129.js +213 -5
  47. package/dist/design-system129.js.map +1 -1
  48. package/dist/design-system131.js +5 -90
  49. package/dist/design-system131.js.map +1 -1
  50. package/dist/design-system132.js +166 -0
  51. package/dist/design-system132.js.map +1 -0
  52. package/dist/design-system134.js +5 -42
  53. package/dist/design-system134.js.map +1 -1
  54. package/dist/design-system135.js +12 -0
  55. package/dist/design-system135.js.map +1 -0
  56. package/dist/design-system136.js +274 -5
  57. package/dist/design-system136.js.map +1 -1
  58. package/dist/design-system138.js +9 -0
  59. package/dist/{design-system124.js.map → design-system138.js.map} +1 -1
  60. package/dist/design-system139.js +16 -5
  61. package/dist/design-system139.js.map +1 -1
  62. package/dist/design-system141.js +8 -0
  63. package/dist/{design-system127.js.map → design-system141.js.map} +1 -1
  64. package/dist/design-system142.js +12 -5
  65. package/dist/design-system142.js.map +1 -1
  66. package/dist/design-system143.js +78 -83
  67. package/dist/design-system143.js.map +1 -1
  68. package/dist/design-system145.js +1 -1
  69. package/dist/design-system145.js.map +1 -1
  70. package/dist/design-system146.js +42 -9
  71. package/dist/design-system146.js.map +1 -1
  72. package/dist/design-system148.js +3 -2
  73. package/dist/design-system148.js.map +1 -1
  74. package/dist/design-system149.js +230 -18
  75. package/dist/design-system149.js.map +1 -1
  76. package/dist/design-system151.js +5 -158
  77. package/dist/design-system151.js.map +1 -1
  78. package/dist/{design-system140.js → design-system152.js} +6 -6
  79. package/dist/{design-system140.js.map → design-system152.js.map} +1 -1
  80. package/dist/design-system154.js +5 -307
  81. package/dist/design-system154.js.map +1 -1
  82. package/dist/design-system155.js +98 -0
  83. package/dist/design-system155.js.map +1 -0
  84. package/dist/design-system157.js +5 -240
  85. package/dist/design-system157.js.map +1 -1
  86. package/dist/design-system158.js +12 -0
  87. package/dist/design-system158.js.map +1 -0
  88. package/dist/design-system159.js +37 -5
  89. package/dist/design-system159.js.map +1 -1
  90. package/dist/design-system160.js +4 -189
  91. package/dist/design-system160.js.map +1 -1
  92. package/dist/design-system161.js +24 -0
  93. package/dist/{design-system150.js.map → design-system161.js.map} +1 -1
  94. package/dist/design-system162.js +2 -3
  95. package/dist/design-system162.js.map +1 -1
  96. package/dist/design-system163.js +158 -3
  97. package/dist/design-system163.js.map +1 -1
  98. package/dist/{design-system153.js → design-system165.js} +2 -2
  99. package/dist/{design-system153.js.map → design-system165.js.map} +1 -1
  100. package/dist/design-system166.js +307 -6
  101. package/dist/design-system166.js.map +1 -1
  102. package/dist/{design-system156.js → design-system168.js} +2 -2
  103. package/dist/{design-system156.js.map → design-system168.js.map} +1 -1
  104. package/dist/design-system169.js +167 -6
  105. package/dist/design-system169.js.map +1 -1
  106. package/dist/design-system171.js +8 -0
  107. package/dist/design-system171.js.map +1 -0
  108. package/dist/design-system172.js +240 -6
  109. package/dist/design-system172.js.map +1 -1
  110. package/dist/design-system174.js +8 -0
  111. package/dist/design-system174.js.map +1 -0
  112. package/dist/design-system175.js +189 -6
  113. package/dist/design-system175.js.map +1 -1
  114. package/dist/design-system177.js +8 -0
  115. package/dist/design-system177.js.map +1 -0
  116. package/dist/design-system178.js +3 -5
  117. package/dist/design-system178.js.map +1 -1
  118. package/dist/design-system179.js +58 -11
  119. package/dist/design-system179.js.map +1 -1
  120. package/dist/design-system181.js +9 -0
  121. package/dist/design-system181.js.map +1 -0
  122. package/dist/design-system182.js +56 -6
  123. package/dist/design-system182.js.map +1 -1
  124. package/dist/design-system184.js +9 -0
  125. package/dist/{design-system167.js.map → design-system184.js.map} +1 -1
  126. package/dist/design-system185.js +69 -5
  127. package/dist/design-system185.js.map +1 -1
  128. package/dist/design-system187.js +9 -0
  129. package/dist/{design-system170.js.map → design-system187.js.map} +1 -1
  130. package/dist/design-system188.js +182 -5
  131. package/dist/design-system188.js.map +1 -1
  132. package/dist/design-system190.js +9 -0
  133. package/dist/design-system190.js.map +1 -0
  134. package/dist/design-system191.js +115 -5
  135. package/dist/design-system191.js.map +1 -1
  136. package/dist/design-system193.js +8 -0
  137. package/dist/{design-system176.js.map → design-system193.js.map} +1 -1
  138. package/dist/design-system194.js +11 -5
  139. package/dist/design-system194.js.map +1 -1
  140. package/dist/design-system195.js +453 -24
  141. package/dist/design-system195.js.map +1 -1
  142. package/dist/design-system197.js +5 -4
  143. package/dist/design-system197.js.map +1 -1
  144. package/dist/design-system198.js +20 -16
  145. package/dist/design-system198.js.map +1 -1
  146. package/dist/design-system200.js +1 -1
  147. package/dist/design-system200.js.map +1 -1
  148. package/dist/design-system201.js +70 -314
  149. package/dist/design-system201.js.map +1 -1
  150. package/dist/design-system203.js +1 -1
  151. package/dist/design-system203.js.map +1 -1
  152. package/dist/design-system204.js +24 -89
  153. package/dist/design-system204.js.map +1 -1
  154. package/dist/design-system206.js +1 -1
  155. package/dist/design-system206.js.map +1 -1
  156. package/dist/design-system207.js +26 -17
  157. package/dist/design-system207.js.map +1 -1
  158. package/dist/design-system209.js +5 -3
  159. package/dist/design-system209.js.map +1 -1
  160. package/dist/design-system210.js +22 -408
  161. package/dist/design-system210.js.map +1 -1
  162. package/dist/design-system212.js +1 -1
  163. package/dist/design-system212.js.map +1 -1
  164. package/dist/design-system213.js +24 -52
  165. package/dist/design-system213.js.map +1 -1
  166. package/dist/design-system215.js +1 -1
  167. package/dist/design-system215.js.map +1 -1
  168. package/dist/design-system216.js +329 -85
  169. package/dist/design-system216.js.map +1 -1
  170. package/dist/design-system218.js +5 -108
  171. package/dist/design-system218.js.map +1 -1
  172. package/dist/design-system219.js +103 -0
  173. package/dist/design-system219.js.map +1 -0
  174. package/dist/design-system221.js +5 -106
  175. package/dist/design-system221.js.map +1 -1
  176. package/dist/design-system222.js +22 -0
  177. package/dist/{design-system208.js.map → design-system222.js.map} +1 -1
  178. package/dist/design-system223.js +4 -6
  179. package/dist/design-system223.js.map +1 -1
  180. package/dist/design-system224.js +3 -737
  181. package/dist/design-system224.js.map +1 -1
  182. package/dist/design-system225.js +422 -0
  183. package/dist/design-system225.js.map +1 -0
  184. package/dist/design-system227.js +5 -11
  185. package/dist/design-system227.js.map +1 -1
  186. package/dist/design-system228.js +51 -517
  187. package/dist/design-system228.js.map +1 -1
  188. package/dist/design-system230.js +1 -1
  189. package/dist/design-system230.js.map +1 -1
  190. package/dist/design-system231.js +88 -3
  191. package/dist/design-system231.js.map +1 -1
  192. package/dist/design-system232.js +4 -46
  193. package/dist/design-system232.js.map +1 -1
  194. package/dist/design-system233.js +108 -4
  195. package/dist/design-system233.js.map +1 -1
  196. package/dist/{design-system220.js → design-system235.js} +2 -2
  197. package/dist/{design-system220.js.map → design-system235.js.map} +1 -1
  198. package/dist/design-system236.js +106 -5
  199. package/dist/design-system236.js.map +1 -1
  200. package/dist/design-system238.js +9 -0
  201. package/dist/design-system238.js.map +1 -0
  202. package/dist/design-system239.js +737 -5
  203. package/dist/design-system239.js.map +1 -1
  204. package/dist/{design-system226.js → design-system241.js} +2 -2
  205. package/dist/{design-system226.js.map → design-system241.js.map} +1 -1
  206. package/dist/design-system242.js +3 -5
  207. package/dist/design-system242.js.map +1 -1
  208. package/dist/design-system243.js +42 -50
  209. package/dist/design-system243.js.map +1 -1
  210. package/dist/design-system244.js +1 -1
  211. package/dist/design-system244.js.map +1 -1
  212. package/dist/design-system245.js +254 -141
  213. package/dist/design-system245.js.map +1 -1
  214. package/dist/design-system247.js +1 -1
  215. package/dist/design-system247.js.map +1 -1
  216. package/dist/design-system248.js +119 -7
  217. package/dist/design-system248.js.map +1 -1
  218. package/dist/design-system250.js +8 -0
  219. package/dist/design-system250.js.map +1 -0
  220. package/dist/design-system251.js +172 -5
  221. package/dist/design-system251.js.map +1 -1
  222. package/dist/design-system253.js +8 -0
  223. package/dist/design-system253.js.map +1 -0
  224. package/dist/design-system254.js +11 -6
  225. package/dist/design-system254.js.map +1 -1
  226. package/dist/design-system255.js +525 -9
  227. package/dist/design-system255.js.map +1 -1
  228. package/dist/design-system257.js +8 -0
  229. package/dist/design-system257.js.map +1 -0
  230. package/dist/design-system258.js +112 -6
  231. package/dist/design-system258.js.map +1 -1
  232. package/dist/design-system260.js +5 -374
  233. package/dist/design-system260.js.map +1 -1
  234. package/dist/design-system261.js +57 -0
  235. package/dist/design-system261.js.map +1 -0
  236. package/dist/design-system262.js +4 -6
  237. package/dist/design-system262.js.map +1 -1
  238. package/dist/design-system263.js +173 -0
  239. package/dist/design-system263.js.map +1 -0
  240. package/dist/design-system265.js +8 -0
  241. package/dist/design-system265.js.map +1 -0
  242. package/dist/design-system266.js +10 -0
  243. package/dist/design-system266.js.map +1 -0
  244. package/dist/{design-system249.js → design-system267.js} +2 -2
  245. package/dist/{design-system249.js.map → design-system267.js.map} +1 -1
  246. package/dist/design-system269.js +8 -0
  247. package/dist/design-system269.js.map +1 -0
  248. package/dist/{design-system252.js → design-system270.js} +1 -1
  249. package/dist/{design-system252.js.map → design-system270.js.map} +1 -1
  250. package/dist/design-system272.js +9 -0
  251. package/dist/design-system272.js.map +1 -0
  252. package/dist/design-system273.js +12 -0
  253. package/dist/design-system273.js.map +1 -0
  254. package/dist/{design-system256.js → design-system274.js} +2 -2
  255. package/dist/{design-system256.js.map → design-system274.js.map} +1 -1
  256. package/dist/design-system276.js +9 -0
  257. package/dist/design-system276.js.map +1 -0
  258. package/dist/{design-system259.js → design-system277.js} +1 -1
  259. package/dist/{design-system259.js.map → design-system277.js.map} +1 -1
  260. package/dist/design-system278.js +377 -0
  261. package/dist/design-system278.js.map +1 -0
  262. package/dist/design-system280.js +9 -0
  263. package/dist/design-system280.js.map +1 -0
  264. package/dist/design-system69.js +182 -13
  265. package/dist/design-system69.js.map +1 -1
  266. package/dist/design-system71.js +8 -0
  267. package/dist/design-system71.js.map +1 -0
  268. package/dist/design-system72.js +13 -5
  269. package/dist/design-system72.js.map +1 -1
  270. package/dist/design-system73.js +677 -139
  271. package/dist/design-system73.js.map +1 -1
  272. package/dist/design-system75.js +1 -1
  273. package/dist/design-system75.js.map +1 -1
  274. package/dist/design-system76.js +152 -23
  275. package/dist/design-system76.js.map +1 -1
  276. package/dist/design-system78.js +5 -49
  277. package/dist/design-system78.js.map +1 -1
  278. package/dist/design-system79.js +32 -0
  279. package/dist/design-system79.js.map +1 -0
  280. package/dist/design-system80.js +2 -3
  281. package/dist/design-system80.js.map +1 -1
  282. package/dist/design-system81.js +38 -188
  283. package/dist/design-system81.js.map +1 -1
  284. package/dist/design-system83.js +1 -1
  285. package/dist/design-system83.js.map +1 -1
  286. package/dist/design-system84.js +199 -7
  287. package/dist/design-system84.js.map +1 -1
  288. package/dist/design-system86.js +8 -0
  289. package/dist/design-system86.js.map +1 -0
  290. package/dist/design-system87.js +7 -5
  291. package/dist/design-system87.js.map +1 -1
  292. package/dist/design-system88.js +264 -48
  293. package/dist/design-system88.js.map +1 -1
  294. package/dist/design-system90.js +1 -1
  295. package/dist/design-system90.js.map +1 -1
  296. package/dist/design-system91.js +57 -11
  297. package/dist/design-system91.js.map +1 -1
  298. package/dist/design-system93.js +8 -0
  299. package/dist/design-system93.js.map +1 -0
  300. package/dist/design-system94.js +11 -5
  301. package/dist/design-system94.js.map +1 -1
  302. package/dist/design-system95.js +92 -59
  303. package/dist/design-system95.js.map +1 -1
  304. package/dist/design-system97.js +1 -1
  305. package/dist/design-system97.js.map +1 -1
  306. package/dist/design-system98.js +56 -78
  307. package/dist/design-system98.js.map +1 -1
  308. package/dist/types/components/BContextMenu/BContextMenu.spec.d.ts +1 -0
  309. package/dist/types/components/BContextMenu/BContextMenu.vue.d.ts +42 -0
  310. package/dist/types/components/BContextMenu/index.d.ts +2 -0
  311. package/dist/types/components/BContextMenu/types.d.ts +23 -0
  312. package/dist/types/components/BInputTags/BInputTags.spec.d.ts +1 -0
  313. package/dist/types/components/BInputTags/BInputTags.vue.d.ts +54 -0
  314. package/dist/types/components/BInputTags/index.d.ts +1 -0
  315. package/dist/types/components/BLink/BLink.spec.d.ts +1 -0
  316. package/dist/types/components/BLink/BLink.vue.d.ts +100 -0
  317. package/dist/types/components/BLink/index.d.ts +1 -0
  318. package/dist/types/components/BListbox/BListbox.spec.d.ts +1 -0
  319. package/dist/types/components/BListbox/BListbox.vue.d.ts +52 -0
  320. package/dist/types/components/BListbox/index.d.ts +1 -0
  321. package/dist/types/components/BModal/BModal.spec.d.ts +1 -0
  322. package/dist/types/components/BPinInput/BPinInput.spec.d.ts +1 -0
  323. package/dist/types/components/BPinInput/BPinInput.vue.d.ts +43 -0
  324. package/dist/types/components/BPinInput/index.d.ts +1 -0
  325. package/dist/types/components/BProgress/BProgress.vue.d.ts +47 -2
  326. package/dist/types/components/BTextarea/BTextarea.spec.d.ts +1 -0
  327. package/dist/types/components/BTextarea/BTextarea.vue.d.ts +77 -0
  328. package/dist/types/components/BTextarea/index.d.ts +1 -0
  329. package/dist/types/components/index.d.ts +7 -1
  330. package/package.json +1 -1
  331. package/dist/design-system114.js +0 -212
  332. package/dist/design-system114.js.map +0 -1
  333. package/dist/design-system124.js +0 -277
  334. package/dist/design-system127.js +0 -19
  335. package/dist/design-system130.js +0 -15
  336. package/dist/design-system130.js.map +0 -1
  337. package/dist/design-system133.js +0 -8
  338. package/dist/design-system133.js.map +0 -1
  339. package/dist/design-system137.js +0 -236
  340. package/dist/design-system137.js.map +0 -1
  341. package/dist/design-system147.js +0 -40
  342. package/dist/design-system147.js.map +0 -1
  343. package/dist/design-system150.js +0 -7
  344. package/dist/design-system164.js +0 -61
  345. package/dist/design-system164.js.map +0 -1
  346. package/dist/design-system167.js +0 -59
  347. package/dist/design-system170.js +0 -72
  348. package/dist/design-system173.js +0 -185
  349. package/dist/design-system173.js.map +0 -1
  350. package/dist/design-system176.js +0 -118
  351. package/dist/design-system180.js +0 -465
  352. package/dist/design-system180.js.map +0 -1
  353. package/dist/design-system183.js +0 -38
  354. package/dist/design-system183.js.map +0 -1
  355. package/dist/design-system186.js +0 -91
  356. package/dist/design-system186.js.map +0 -1
  357. package/dist/design-system189.js +0 -38
  358. package/dist/design-system189.js.map +0 -1
  359. package/dist/design-system192.js +0 -31
  360. package/dist/design-system192.js.map +0 -1
  361. package/dist/design-system208.js +0 -7
  362. package/dist/design-system217.js +0 -7
  363. package/dist/design-system217.js.map +0 -1
  364. package/dist/design-system234.js +0 -286
  365. package/dist/design-system234.js.map +0 -1
  366. package/dist/design-system237.js +0 -122
  367. package/dist/design-system237.js.map +0 -1
  368. package/dist/design-system240.js +0 -115
  369. package/dist/design-system240.js.map +0 -1
  370. package/dist/design-system70.js +0 -699
  371. package/dist/design-system70.js.map +0 -1
  372. package/dist/design-system77.js +0 -7
  373. package/dist/design-system77.js.map +0 -1
  374. package/dist/design-system85.js +0 -276
  375. package/dist/design-system85.js.map +0 -1
  376. package/dist/design-system92.js +0 -102
  377. package/dist/design-system92.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"design-system228.js","names":[],"sources":["../src/components/BTimePicker/BTimePicker.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { useComponentId } from '@/composables/useComponentId.ts';\nimport { computed, nextTick, onBeforeUnmount, onMounted, ref, watch } from 'vue';\n\nimport {\n BTimePickerPlacement,\n BTimePickerSize,\n BTimePickerStatus,\n BTimePickerVariant,\n type BTimePickerDisabledTime,\n} from './types';\n\nconst {\n size = BTimePickerSize.Medium,\n variant = BTimePickerVariant.Outlined,\n placeholder = 'Select time',\n disabled = false,\n inputReadOnly = false,\n allowClear = true,\n showNow = true,\n use12Hours = false,\n hourStep = 1,\n minuteStep = 1,\n secondStep = 1,\n format,\n placement: _placement = BTimePickerPlacement.BottomLeft,\n status,\n hideDisabledOptions = false,\n needConfirm = true,\n changeOnScroll = false,\n showHour = true,\n showMinute = true,\n showSecond = true,\n defaultOpen = false,\n defaultValue,\n open,\n disabledTime,\n} = defineProps<{\n /** Size of the input */\n size?: `${BTimePickerSize}`;\n /** Visual variant */\n variant?: `${BTimePickerVariant}`;\n /** Placeholder text */\n placeholder?: string;\n /** Disable the picker */\n disabled?: boolean;\n /** Make input read-only (useful for touch devices) */\n inputReadOnly?: boolean;\n /** Show clear button */\n allowClear?: boolean;\n /** Show \"Now\" button in footer */\n showNow?: boolean;\n /** Use 12-hour format with AM/PM */\n use12Hours?: boolean;\n /** Hour selection step */\n hourStep?: number;\n /** Minute selection step */\n minuteStep?: number;\n /** Second selection step */\n secondStep?: number;\n /** Time format string (e.g. 'HH:mm:ss', 'hh:mm a') */\n format?: string;\n /** Popup placement */\n placement?: `${BTimePickerPlacement}`;\n /** Validation status */\n status?: `${BTimePickerStatus}`;\n /** Hide disabled time options from columns */\n hideDisabledOptions?: boolean;\n /** Require OK button confirmation before applying value */\n needConfirm?: boolean;\n /** Update value on scroll instead of click */\n changeOnScroll?: boolean;\n /** Show hour column */\n showHour?: boolean;\n /** Show minute column */\n showMinute?: boolean;\n /** Show second column */\n showSecond?: boolean;\n /** Default open state */\n defaultOpen?: boolean;\n /** Default value (uncontrolled) */\n defaultValue?: Date;\n /** Controlled open state */\n open?: boolean;\n /** Function returning disabled hours/minutes/seconds */\n disabledTime?: () => BTimePickerDisabledTime;\n}>();\n\nconst model = defineModel<Date | null>({ default: undefined });\n\nconst emit = defineEmits<{\n change: [time: Date | null, timeString: string];\n openChange: [open: boolean];\n}>();\n\nconst inputEl = ref<HTMLInputElement | null>(null);\nconst panelEl = ref<HTMLElement | null>(null);\nconst hourColEl = ref<HTMLElement | null>(null);\nconst minuteColEl = ref<HTMLElement | null>(null);\nconst secondColEl = ref<HTMLElement | null>(null);\nconst ampmColEl = ref<HTMLElement | null>(null);\n\ndefineExpose({\n focus: () => inputEl.value?.focus(),\n blur: () => inputEl.value?.blur(),\n});\n\nconst { componentUID } = useComponentId();\nconst anchorName = computed(() => `--b-time-picker-${componentUID.value}`);\n\n// ─────────────────────────────────────────────\n// State\n// ─────────────────────────────────────────────\nconst isOpen = ref(defaultOpen);\nconst isPanelOpen = ref(open !== undefined ? !!open : defaultOpen);\nconst internalValue = ref<Date | null>(defaultValue ?? null);\nconst pendingHour = ref<number | null>(null);\nconst pendingMinute = ref<number | null>(null);\nconst pendingSecond = ref<number | null>(null);\nconst pendingAmpm = ref<'AM' | 'PM' | null>(null);\nconst inputText = ref('');\nconst focusedColumn = ref<'hour' | 'minute' | 'second' | 'ampm'>('hour');\n\nconst selectedTime = computed({\n get: () => model.value ?? internalValue.value,\n set: (val) => {\n internalValue.value = val;\n model.value = val;\n },\n});\n\n// ─────────────────────────────────────────────\n// Format\n// ─────────────────────────────────────────────\nconst activeFormat = computed(() => {\n if (format) return format;\n const parts: string[] = [];\n if (showHour) parts.push(use12Hours ? 'hh' : 'HH');\n if (showMinute) parts.push('mm');\n if (showSecond) parts.push('ss');\n const base = parts.join(':');\n return use12Hours ? `${base} A` : base;\n});\n\nfunction pad(n: number): string {\n return String(n).padStart(2, '0');\n}\n\nfunction formatTime(d: Date | null): string {\n if (!d) return '';\n const h = d.getHours();\n const m = d.getMinutes();\n const s = d.getSeconds();\n const ampm = h >= 12 ? 'PM' : 'AM';\n\n let result = activeFormat.value;\n if (use12Hours) {\n const h12 = h % 12 || 12;\n result = result.replace('hh', pad(h12));\n result = result.replace('h', String(h12));\n result = result.replace('A', ampm);\n result = result.replace('a', ampm.toLowerCase());\n } else {\n result = result.replace('HH', pad(h));\n result = result.replace('H', String(h));\n }\n result = result.replace('mm', pad(m));\n result = result.replace('ss', pad(s));\n return result;\n}\n\nfunction parseTimeString(str: string): Date | null {\n if (!str.trim()) return null;\n const timeRegex12 = /(\\d{1,2}):(\\d{2})(?::(\\d{2}))?\\s*(AM|PM|am|pm)?/;\n const match = str.match(timeRegex12);\n if (!match) return null;\n\n let h = parseInt(match[1], 10);\n const m = parseInt(match[2], 10);\n const s = match[3] ? parseInt(match[3], 10) : 0;\n const period = match[4]?.toUpperCase();\n\n if (use12Hours && period) {\n if (period === 'PM' && h < 12) h += 12;\n if (period === 'AM' && h === 12) h = 0;\n }\n\n if (h < 0 || h > 23 || m < 0 || m > 59 || s < 0 || s > 59) return null;\n\n const d = new Date();\n d.setHours(h, m, s, 0);\n return d;\n}\n\n// ─────────────────────────────────────────────\n// Disabled time logic\n// ─────────────────────────────────────────────\nconst disabledHours = computed<number[]>(() => {\n if (!disabledTime) return [];\n const dt = disabledTime();\n return dt.disabledHours?.() ?? [];\n});\n\nconst disabledMinutes = computed<number[]>(() => {\n if (!disabledTime) return [];\n const dt = disabledTime();\n const h = pendingHour.value ?? selectedTime.value?.getHours() ?? 0;\n return dt.disabledMinutes?.(h) ?? [];\n});\n\nconst disabledSeconds = computed<number[]>(() => {\n if (!disabledTime) return [];\n const dt = disabledTime();\n const h = pendingHour.value ?? selectedTime.value?.getHours() ?? 0;\n const m = pendingMinute.value ?? selectedTime.value?.getMinutes() ?? 0;\n return dt.disabledSeconds?.(h, m) ?? [];\n});\n\n// ─────────────────────────────────────────────\n// Column data\n// ─────────────────────────────────────────────\nconst hours = computed(() => {\n const list: number[] = [];\n if (use12Hours) {\n for (let i = 1; i <= 12; i += hourStep) list.push(i);\n } else {\n for (let i = 0; i < 24; i += hourStep) list.push(i);\n }\n if (hideDisabledOptions) {\n return list.filter((h) => !disabledHours.value.includes(use12Hours ? to24Hour(h, pendingAmpm.value ?? 'AM') : h));\n }\n return list;\n});\n\nconst minutes = computed(() => {\n const list: number[] = [];\n for (let i = 0; i < 60; i += minuteStep) list.push(i);\n if (hideDisabledOptions) {\n return list.filter((m) => !disabledMinutes.value.includes(m));\n }\n return list;\n});\n\nconst seconds = computed(() => {\n const list: number[] = [];\n for (let i = 0; i < 60; i += secondStep) list.push(i);\n if (hideDisabledOptions) {\n return list.filter((s) => !disabledSeconds.value.includes(s));\n }\n return list;\n});\n\nfunction to24Hour(h12: number, period: 'AM' | 'PM'): number {\n if (period === 'AM') return h12 === 12 ? 0 : h12;\n return h12 === 12 ? 12 : h12 + 12;\n}\n\nfunction to12Hour(h24: number): { hour: number; period: 'AM' | 'PM' } {\n const period: 'AM' | 'PM' = h24 >= 12 ? 'PM' : 'AM';\n const hour = h24 % 12 || 12;\n return { hour, period };\n}\n\n// ─────────────────────────────────────────────\n// Panel open/close\n// ─────────────────────────────────────────────\nfunction openPanel() {\n if (disabled) return;\n isOpen.value = true;\n isPanelOpen.value = true;\n emit('openChange', true);\n panelEl.value?.showPopover?.();\n syncPendingFromValue();\n nextTick(() => scrollToSelected());\n}\n\nfunction closePanel() {\n isOpen.value = false;\n isPanelOpen.value = false;\n emit('openChange', false);\n panelEl.value?.hidePopover?.();\n inputEl.value?.focus();\n}\n\nfunction togglePanel() {\n if (isPanelOpen.value) closePanel();\n else openPanel();\n}\n\nfunction handlePopoverToggle(e: Event) {\n const toggleEvent = e as ToggleEvent;\n const nowOpen = toggleEvent.newState === 'open';\n isOpen.value = nowOpen;\n isPanelOpen.value = nowOpen;\n if (!nowOpen) emit('openChange', false);\n}\n\n// ─────────────────────────────────────────────\n// Sync pending state\n// ─────────────────────────────────────────────\nfunction syncPendingFromValue() {\n const t = selectedTime.value;\n if (t) {\n if (use12Hours) {\n const { hour, period } = to12Hour(t.getHours());\n pendingHour.value = hour;\n pendingAmpm.value = period;\n } else {\n pendingHour.value = t.getHours();\n }\n pendingMinute.value = t.getMinutes();\n pendingSecond.value = t.getSeconds();\n } else {\n pendingHour.value = null;\n pendingMinute.value = null;\n pendingSecond.value = null;\n pendingAmpm.value = null;\n }\n}\n\n// ─────────────────────────────────────────────\n// Selection\n// ─────────────────────────────────────────────\nfunction selectHour(h: number) {\n const h24 = use12Hours ? to24Hour(h, pendingAmpm.value ?? 'AM') : h;\n if (disabledHours.value.includes(h24)) return;\n pendingHour.value = h;\n if (!needConfirm && !changeOnScroll) applyPendingIfComplete();\n else if (changeOnScroll) applyPending();\n}\n\nfunction selectMinute(m: number) {\n if (disabledMinutes.value.includes(m)) return;\n pendingMinute.value = m;\n if (!needConfirm && !changeOnScroll) applyPendingIfComplete();\n else if (changeOnScroll) applyPending();\n}\n\nfunction selectSecond(s: number) {\n if (disabledSeconds.value.includes(s)) return;\n pendingSecond.value = s;\n if (!needConfirm && !changeOnScroll) applyPendingIfComplete();\n else if (changeOnScroll) applyPending();\n}\n\nfunction selectAmpm(val: 'AM' | 'PM') {\n pendingAmpm.value = val;\n if (!needConfirm && !changeOnScroll) applyPendingIfComplete();\n else if (changeOnScroll) applyPending();\n}\n\nfunction applyPendingIfComplete() {\n if (pendingHour.value !== null && pendingMinute.value !== null) {\n if (showSecond && pendingSecond.value === null) return;\n if (use12Hours && pendingAmpm.value === null) return;\n applyPending();\n closePanel();\n }\n}\n\nfunction applyPending() {\n const h = pendingHour.value ?? 0;\n const m = pendingMinute.value ?? 0;\n const s = pendingSecond.value ?? 0;\n const h24 = use12Hours ? to24Hour(h, pendingAmpm.value ?? 'AM') : h;\n\n const d = new Date();\n d.setHours(h24, m, s, 0);\n selectedTime.value = d;\n inputText.value = formatTime(d);\n emit('change', d, formatTime(d));\n}\n\nfunction handleOk() {\n applyPending();\n closePanel();\n}\n\nfunction handleNow() {\n const now = new Date();\n if (use12Hours) {\n const { hour, period } = to12Hour(now.getHours());\n pendingHour.value = hour;\n pendingAmpm.value = period;\n } else {\n pendingHour.value = now.getHours();\n }\n pendingMinute.value = now.getMinutes();\n pendingSecond.value = now.getSeconds();\n nextTick(() => scrollToSelected());\n if (!needConfirm) {\n applyPending();\n closePanel();\n }\n}\n\nfunction handleClear(e: Event) {\n e.stopPropagation();\n selectedTime.value = null;\n inputText.value = '';\n pendingHour.value = null;\n pendingMinute.value = null;\n pendingSecond.value = null;\n pendingAmpm.value = null;\n emit('change', null, '');\n}\n\n// ─────────────────────────────────────────────\n// Input handling\n// ─────────────────────────────────────────────\nfunction handleInputChange(e: Event) {\n const val = (e.target as HTMLInputElement).value;\n inputText.value = val;\n}\n\nfunction handleInputBlur() {\n if (!isPanelOpen.value) {\n const parsed = parseTimeString(inputText.value);\n if (parsed) {\n selectedTime.value = parsed;\n inputText.value = formatTime(parsed);\n emit('change', parsed, formatTime(parsed));\n } else if (inputText.value === '') {\n selectedTime.value = null;\n emit('change', null, '');\n } else {\n inputText.value = formatTime(selectedTime.value);\n }\n }\n}\n\nfunction handleInputKeydown(e: KeyboardEvent) {\n if (e.key === 'Enter' || e.key === ' ') {\n if (!isPanelOpen.value) {\n e.preventDefault();\n openPanel();\n } else if (e.key === 'Enter') {\n e.preventDefault();\n const parsed = parseTimeString(inputText.value);\n if (parsed) {\n selectedTime.value = parsed;\n inputText.value = formatTime(parsed);\n emit('change', parsed, formatTime(parsed));\n }\n closePanel();\n }\n } else if (e.key === 'Escape') {\n if (isPanelOpen.value) {\n e.preventDefault();\n closePanel();\n }\n }\n}\n\n// ─────────────────────────────────────────────\n// Panel keyboard navigation\n// ─────────────────────────────────────────────\nfunction handlePanelKeydown(e: KeyboardEvent) {\n if (e.key === 'Escape') {\n e.preventDefault();\n closePanel();\n return;\n }\n\n if (e.key === 'Tab') {\n const columns: ('hour' | 'minute' | 'second' | 'ampm')[] = [];\n if (showHour) columns.push('hour');\n if (showMinute) columns.push('minute');\n if (showSecond) columns.push('second');\n if (use12Hours) columns.push('ampm');\n\n const idx = columns.indexOf(focusedColumn.value);\n if (e.shiftKey) {\n if (idx > 0) {\n e.preventDefault();\n focusedColumn.value = columns[idx - 1];\n }\n } else {\n if (idx < columns.length - 1) {\n e.preventDefault();\n focusedColumn.value = columns[idx + 1];\n }\n }\n return;\n }\n\n if (e.key === 'ArrowUp' || e.key === 'ArrowDown') {\n e.preventDefault();\n const delta = e.key === 'ArrowUp' ? -1 : 1;\n adjustFocusedColumn(delta);\n return;\n }\n\n if (e.key === 'Enter') {\n e.preventDefault();\n handleOk();\n }\n}\n\nfunction adjustFocusedColumn(delta: number) {\n if (focusedColumn.value === 'hour') {\n const list = hours.value;\n const current = pendingHour.value ?? list[0];\n const idx = list.indexOf(current);\n const next = list[Math.max(0, Math.min(list.length - 1, idx + delta))];\n selectHour(next);\n scrollColumnTo(hourColEl.value, list.indexOf(next));\n } else if (focusedColumn.value === 'minute') {\n const list = minutes.value;\n const current = pendingMinute.value ?? list[0];\n const idx = list.indexOf(current);\n const next = list[Math.max(0, Math.min(list.length - 1, idx + delta))];\n selectMinute(next);\n scrollColumnTo(minuteColEl.value, list.indexOf(next));\n } else if (focusedColumn.value === 'second') {\n const list = seconds.value;\n const current = pendingSecond.value ?? list[0];\n const idx = list.indexOf(current);\n const next = list[Math.max(0, Math.min(list.length - 1, idx + delta))];\n selectSecond(next);\n scrollColumnTo(secondColEl.value, list.indexOf(next));\n } else if (focusedColumn.value === 'ampm') {\n const val = pendingAmpm.value === 'AM' ? 'PM' : 'AM';\n selectAmpm(val);\n }\n}\n\n// ─────────────────────────────────────────────\n// Scroll helpers\n// ─────────────────────────────────────────────\nfunction scrollColumnTo(col: HTMLElement | null, idx: number) {\n if (!col || !col.scrollTo) return;\n const cellHeight = 28;\n col.scrollTo({ top: idx * cellHeight, behavior: 'smooth' });\n}\n\nfunction scrollToSelected() {\n if (pendingHour.value !== null) {\n const idx = hours.value.indexOf(pendingHour.value);\n if (idx >= 0) scrollColumnTo(hourColEl.value, idx);\n }\n if (pendingMinute.value !== null) {\n const idx = minutes.value.indexOf(pendingMinute.value);\n if (idx >= 0) scrollColumnTo(minuteColEl.value, idx);\n }\n if (pendingSecond.value !== null && showSecond) {\n const idx = seconds.value.indexOf(pendingSecond.value);\n if (idx >= 0) scrollColumnTo(secondColEl.value, idx);\n }\n if (pendingAmpm.value && use12Hours) {\n const idx = pendingAmpm.value === 'AM' ? 0 : 1;\n scrollColumnTo(ampmColEl.value, idx);\n }\n}\n\n// ─────────────────────────────────────────────\n// Click outside\n// ─────────────────────────────────────────────\nfunction handleClickOutside(e: MouseEvent) {\n if (!isPanelOpen.value) return;\n const target = e.target as Node;\n if (panelEl.value?.contains(target)) return;\n if (inputEl.value?.parentElement?.contains(target)) return;\n closePanel();\n}\n\nonMounted(() => {\n document.addEventListener('mousedown', handleClickOutside);\n});\nonBeforeUnmount(() => {\n document.removeEventListener('mousedown', handleClickOutside);\n});\n\n// ─────────────────────────────────────────────\n// Watchers\n// ─────────────────────────────────────────────\nwatch(\n () => open,\n (val) => {\n if (val !== undefined) {\n if (val) openPanel();\n else closePanel();\n }\n },\n);\n\nwatch(selectedTime, (val) => {\n inputText.value = formatTime(val);\n});\n\n// Init display\ninputText.value = formatTime(selectedTime.value);\n\n// ─────────────────────────────────────────────\n// Computed classes\n// ─────────────────────────────────────────────\nconst rootClasses = computed(() => [\n 'b-time-picker',\n `b-time-picker--${size}`,\n `b-time-picker--${variant}`,\n {\n 'b-time-picker--disabled': disabled,\n 'b-time-picker--open': isPanelOpen.value,\n [`b-time-picker--${status}`]: !!status,\n },\n]);\n\nconst isHourDisabled = (h: number) => {\n const h24 = use12Hours ? to24Hour(h, pendingAmpm.value ?? 'AM') : h;\n return disabledHours.value.includes(h24);\n};\nconst isMinuteDisabled = (m: number) => disabledMinutes.value.includes(m);\nconst isSecondDisabled = (s: number) => disabledSeconds.value.includes(s);\n</script>\n\n<template>\n <div :class=\"rootClasses\">\n <div\n class=\"b-time-picker__input-wrap\"\n :style=\"{ anchorName }\"\n @click=\"togglePanel\"\n >\n <input\n :id=\"`b-time-picker-input-${componentUID}`\"\n ref=\"inputEl\"\n class=\"b-time-picker__input\"\n type=\"text\"\n role=\"combobox\"\n :aria-expanded=\"isPanelOpen\"\n aria-haspopup=\"dialog\"\n :aria-controls=\"isPanelOpen ? `b-time-picker-panel-${componentUID}` : undefined\"\n :aria-describedby=\"status ? `b-time-picker-status-${componentUID}` : undefined\"\n :aria-label=\"placeholder\"\n :placeholder=\"placeholder\"\n :disabled=\"disabled\"\n :readonly=\"inputReadOnly\"\n :value=\"inputText\"\n autocomplete=\"off\"\n @input=\"handleInputChange\"\n @blur=\"handleInputBlur\"\n @keydown=\"handleInputKeydown\"\n />\n <span class=\"b-time-picker__suffix\">\n <svg\n v-if=\"!allowClear || !selectedTime\"\n class=\"b-time-picker__icon\"\n aria-hidden=\"true\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n >\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <polyline points=\"12 6 12 12 16 14\" />\n </svg>\n <button\n v-else\n class=\"b-time-picker__clear\"\n type=\"button\"\n aria-label=\"Clear time\"\n tabindex=\"-1\"\n @click=\"handleClear\"\n >\n <svg\n aria-hidden=\"true\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n >\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <line x1=\"15\" y1=\"9\" x2=\"9\" y2=\"15\" />\n <line x1=\"9\" y1=\"9\" x2=\"15\" y2=\"15\" />\n </svg>\n </button>\n </span>\n <span\n v-if=\"status\"\n :id=\"`b-time-picker-status-${componentUID}`\"\n class=\"b-time-picker__status-text\"\n aria-live=\"polite\"\n >\n {{ status }}\n </span>\n </div>\n\n <div\n :id=\"`b-time-picker-panel-${componentUID}`\"\n ref=\"panelEl\"\n class=\"b-time-picker__panel\"\n popover\n role=\"dialog\"\n :aria-label=\"'Time picker'\"\n :aria-modal=\"true\"\n :style=\"{ positionAnchor: anchorName }\"\n @toggle=\"handlePopoverToggle\"\n @keydown=\"handlePanelKeydown\"\n >\n <div class=\"b-time-picker__columns\" role=\"group\" aria-label=\"Time selection columns\">\n <!-- Hour Column -->\n <div\n v-if=\"showHour\"\n ref=\"hourColEl\"\n class=\"b-time-picker__column\"\n role=\"listbox\"\n :aria-label=\"'Hours'\"\n :aria-activedescendant=\"pendingHour !== null ? `b-time-picker-hour-${pendingHour}-${componentUID}` : undefined\"\n >\n <div\n v-for=\"h in hours\"\n :id=\"`b-time-picker-hour-${h}-${componentUID}`\"\n :key=\"h\"\n class=\"b-time-picker__cell\"\n :class=\"{\n 'b-time-picker__cell--selected': pendingHour === h,\n 'b-time-picker__cell--disabled': isHourDisabled(h),\n 'b-time-picker__cell--focused': focusedColumn === 'hour' && pendingHour === h,\n }\"\n role=\"option\"\n :aria-selected=\"pendingHour === h\"\n :aria-disabled=\"isHourDisabled(h)\"\n @click=\"selectHour(h)\"\n >\n {{ pad(h) }}\n </div>\n </div>\n\n <!-- Minute Column -->\n <div\n v-if=\"showMinute\"\n ref=\"minuteColEl\"\n class=\"b-time-picker__column\"\n role=\"listbox\"\n :aria-label=\"'Minutes'\"\n :aria-activedescendant=\"pendingMinute !== null ? `b-time-picker-minute-${pendingMinute}-${componentUID}` : undefined\"\n >\n <div\n v-for=\"m in minutes\"\n :id=\"`b-time-picker-minute-${m}-${componentUID}`\"\n :key=\"m\"\n class=\"b-time-picker__cell\"\n :class=\"{\n 'b-time-picker__cell--selected': pendingMinute === m,\n 'b-time-picker__cell--disabled': isMinuteDisabled(m),\n 'b-time-picker__cell--focused': focusedColumn === 'minute' && pendingMinute === m,\n }\"\n role=\"option\"\n :aria-selected=\"pendingMinute === m\"\n :aria-disabled=\"isMinuteDisabled(m)\"\n @click=\"selectMinute(m)\"\n >\n {{ pad(m) }}\n </div>\n </div>\n\n <!-- Second Column -->\n <div\n v-if=\"showSecond\"\n ref=\"secondColEl\"\n class=\"b-time-picker__column\"\n role=\"listbox\"\n :aria-label=\"'Seconds'\"\n :aria-activedescendant=\"pendingSecond !== null ? `b-time-picker-second-${pendingSecond}-${componentUID}` : undefined\"\n >\n <div\n v-for=\"s in seconds\"\n :id=\"`b-time-picker-second-${s}-${componentUID}`\"\n :key=\"s\"\n class=\"b-time-picker__cell\"\n :class=\"{\n 'b-time-picker__cell--selected': pendingSecond === s,\n 'b-time-picker__cell--disabled': isSecondDisabled(s),\n 'b-time-picker__cell--focused': focusedColumn === 'second' && pendingSecond === s,\n }\"\n role=\"option\"\n :aria-selected=\"pendingSecond === s\"\n :aria-disabled=\"isSecondDisabled(s)\"\n @click=\"selectSecond(s)\"\n >\n {{ pad(s) }}\n </div>\n </div>\n\n <!-- AM/PM Column -->\n <div\n v-if=\"use12Hours\"\n ref=\"ampmColEl\"\n class=\"b-time-picker__column b-time-picker__column--ampm\"\n role=\"listbox\"\n aria-label=\"AM/PM\"\n >\n <div\n class=\"b-time-picker__cell\"\n :class=\"{\n 'b-time-picker__cell--selected': pendingAmpm === 'AM',\n 'b-time-picker__cell--focused': focusedColumn === 'ampm' && pendingAmpm === 'AM',\n }\"\n role=\"option\"\n :aria-selected=\"pendingAmpm === 'AM'\"\n @click=\"selectAmpm('AM')\"\n >\n AM\n </div>\n <div\n class=\"b-time-picker__cell\"\n :class=\"{\n 'b-time-picker__cell--selected': pendingAmpm === 'PM',\n 'b-time-picker__cell--focused': focusedColumn === 'ampm' && pendingAmpm === 'PM',\n }\"\n role=\"option\"\n :aria-selected=\"pendingAmpm === 'PM'\"\n @click=\"selectAmpm('PM')\"\n >\n PM\n </div>\n </div>\n </div>\n\n <div v-if=\"needConfirm || showNow\" class=\"b-time-picker__footer\">\n <button\n v-if=\"showNow\"\n class=\"b-time-picker__now-btn\"\n type=\"button\"\n @click=\"handleNow\"\n >\n Now\n </button>\n <button\n v-if=\"needConfirm\"\n class=\"b-time-picker__ok-btn\"\n type=\"button\"\n @click=\"handleOk\"\n >\n OK\n </button>\n </div>\n </div>\n </div>\n</template>\n\n<style>\n.b-time-picker {\n --b-time-picker-input-font-size: 14px;\n --b-time-picker-input-font-size-lg: 16px;\n --b-time-picker-input-font-size-sm: 14px;\n --b-time-picker-padding-block: 4px;\n --b-time-picker-padding-block-lg: 7px;\n --b-time-picker-padding-block-sm: 0px;\n --b-time-picker-padding-inline: 11px;\n --b-time-picker-padding-inline-lg: 11px;\n --b-time-picker-padding-inline-sm: 7px;\n --b-time-picker-border-color: #d9d9d9;\n --b-time-picker-hover-border-color: #4096ff;\n --b-time-picker-active-border-color: #1677ff;\n --b-time-picker-active-shadow: 0 0 0 2px rgba(5, 145, 255, 0.1);\n --b-time-picker-error-active-shadow: 0 0 0 2px rgba(255, 38, 5, 0.06);\n --b-time-picker-warning-active-shadow: 0 0 0 2px rgba(255, 215, 5, 0.1);\n --b-time-picker-bg: #ffffff;\n --b-time-picker-hover-bg: #ffffff;\n --b-time-picker-active-bg: #ffffff;\n --b-time-picker-text-color: rgba(0, 0, 0, 0.88);\n --b-time-picker-placeholder-color: rgba(0, 0, 0, 0.25);\n --b-time-picker-icon-color: rgba(0, 0, 0, 0.25);\n --b-time-picker-clear-color: rgba(0, 0, 0, 0.25);\n --b-time-picker-clear-hover-color: rgba(0, 0, 0, 0.45);\n --b-time-picker-disabled-bg: rgba(0, 0, 0, 0.04);\n --b-time-picker-disabled-color: rgba(0, 0, 0, 0.25);\n --b-time-picker-panel-bg: #ffffff;\n --b-time-picker-panel-shadow: 0 6px 16px 0 rgba(0, 0, 0, 0.08), 0 3px 6px -4px rgba(0, 0, 0, 0.12), 0 9px 28px 8px rgba(0, 0, 0, 0.05);\n --b-time-picker-cell-height: 28px;\n --b-time-picker-cell-width: 56px;\n --b-time-picker-cell-hover-bg: rgba(0, 0, 0, 0.04);\n --b-time-picker-cell-selected-bg: #e6f4ff;\n --b-time-picker-cell-disabled-bg: rgba(0, 0, 0, 0.04);\n --b-time-picker-cell-disabled-color: rgba(0, 0, 0, 0.25);\n --b-time-picker-column-height: 224px;\n --b-time-picker-column-width: 56px;\n --b-time-picker-footer-bg: #ffffff;\n --b-time-picker-border-radius: 6px;\n --b-time-picker-panel-border-radius: 8px;\n --b-time-picker-transition-duration: 0.2s;\n --b-time-picker-z-index-popup: 1050;\n\n position: relative;\n display: inline-flex;\n width: 100%;\n max-width: 200px;\n}\n\n/* ──── Input Wrap ──── */\n.b-time-picker__input-wrap {\n display: flex;\n align-items: center;\n width: 100%;\n background: var(--b-time-picker-bg);\n border: 1px solid var(--b-time-picker-border-color);\n border-radius: var(--b-time-picker-border-radius);\n padding: var(--b-time-picker-padding-block) var(--b-time-picker-padding-inline);\n cursor: pointer;\n transition:\n border-color var(--b-time-picker-transition-duration),\n box-shadow var(--b-time-picker-transition-duration),\n background var(--b-time-picker-transition-duration);\n}\n\n.b-time-picker__input-wrap:hover {\n border-color: var(--b-time-picker-hover-border-color);\n background: var(--b-time-picker-hover-bg);\n}\n\n.b-time-picker--open .b-time-picker__input-wrap {\n border-color: var(--b-time-picker-active-border-color);\n box-shadow: var(--b-time-picker-active-shadow);\n background: var(--b-time-picker-active-bg);\n}\n\n/* ──── Size Variants ──── */\n.b-time-picker--sm .b-time-picker__input-wrap {\n padding: var(--b-time-picker-padding-block-sm) var(--b-time-picker-padding-inline-sm);\n}\n\n.b-time-picker--sm .b-time-picker__input {\n font-size: var(--b-time-picker-input-font-size-sm);\n}\n\n.b-time-picker--lg .b-time-picker__input-wrap {\n padding: var(--b-time-picker-padding-block-lg) var(--b-time-picker-padding-inline-lg);\n}\n\n.b-time-picker--lg .b-time-picker__input {\n font-size: var(--b-time-picker-input-font-size-lg);\n}\n\n/* ──── Variant Styles ──── */\n.b-time-picker--filled .b-time-picker__input-wrap {\n background: rgba(0, 0, 0, 0.04);\n border-color: transparent;\n}\n\n.b-time-picker--filled .b-time-picker__input-wrap:hover {\n background: rgba(0, 0, 0, 0.06);\n}\n\n.b-time-picker--borderless .b-time-picker__input-wrap {\n border-color: transparent;\n background: transparent;\n box-shadow: none;\n}\n\n.b-time-picker--underlined .b-time-picker__input-wrap {\n border-radius: 0;\n border: none;\n border-bottom: 1px solid var(--b-time-picker-border-color);\n}\n\n.b-time-picker--underlined .b-time-picker__input-wrap:hover {\n border-bottom-color: var(--b-time-picker-hover-border-color);\n}\n\n.b-time-picker--underlined.b-time-picker--open .b-time-picker__input-wrap {\n border-bottom-color: var(--b-time-picker-active-border-color);\n box-shadow: none;\n}\n\n/* ──── Status ──── */\n.b-time-picker--error .b-time-picker__input-wrap {\n border-color: #ff4d4f;\n}\n\n.b-time-picker--error.b-time-picker--open .b-time-picker__input-wrap {\n box-shadow: var(--b-time-picker-error-active-shadow);\n}\n\n.b-time-picker--warning .b-time-picker__input-wrap {\n border-color: #faad14;\n}\n\n.b-time-picker--warning.b-time-picker--open .b-time-picker__input-wrap {\n box-shadow: var(--b-time-picker-warning-active-shadow);\n}\n\n/* ──── Disabled ──── */\n.b-time-picker--disabled .b-time-picker__input-wrap {\n background: var(--b-time-picker-disabled-bg);\n border-color: var(--b-time-picker-border-color);\n cursor: not-allowed;\n pointer-events: none;\n}\n\n.b-time-picker--disabled .b-time-picker__input {\n color: var(--b-time-picker-disabled-color);\n cursor: not-allowed;\n}\n\n/* ──── Input ──── */\n.b-time-picker__input {\n flex: 1;\n border: none;\n outline: none;\n background: transparent;\n font-size: var(--b-time-picker-input-font-size);\n color: var(--b-time-picker-text-color);\n line-height: 1.5;\n padding: 0;\n min-width: 0;\n}\n\n.b-time-picker__input::placeholder {\n color: var(--b-time-picker-placeholder-color);\n}\n\n/* ──── Suffix / Icons ──── */\n.b-time-picker__suffix {\n display: flex;\n align-items: center;\n margin-left: 4px;\n flex-shrink: 0;\n}\n\n.b-time-picker__icon {\n width: 14px;\n height: 14px;\n color: var(--b-time-picker-icon-color);\n}\n\n.b-time-picker__clear {\n display: flex;\n align-items: center;\n justify-content: center;\n border: none;\n background: none;\n padding: 0;\n cursor: pointer;\n color: var(--b-time-picker-clear-color);\n transition: color var(--b-time-picker-transition-duration);\n}\n\n.b-time-picker__clear:hover {\n color: var(--b-time-picker-clear-hover-color);\n}\n\n.b-time-picker__clear svg {\n width: 14px;\n height: 14px;\n}\n\n.b-time-picker__status-text {\n position: absolute;\n width: 1px;\n height: 1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n}\n\n/* ──── Panel ──── */\n.b-time-picker__panel {\n position: absolute;\n position-anchor: var(--b-time-picker-anchor);\n inset: unset;\n top: anchor(bottom);\n left: anchor(left);\n margin: 0;\n margin-top: 4px;\n padding: 0;\n border: none;\n border-radius: var(--b-time-picker-panel-border-radius);\n background: var(--b-time-picker-panel-bg);\n box-shadow: var(--b-time-picker-panel-shadow);\n z-index: var(--b-time-picker-z-index-popup);\n overflow: hidden;\n opacity: 0;\n transform: translateY(-4px);\n transition:\n opacity var(--b-time-picker-transition-duration) ease,\n transform var(--b-time-picker-transition-duration) ease;\n}\n\n.b-time-picker__panel:popover-open {\n opacity: 1;\n transform: translateY(0);\n}\n\n@starting-style {\n .b-time-picker__panel:popover-open {\n opacity: 0;\n transform: translateY(-4px);\n }\n}\n\n/* ──── Columns ──── */\n.b-time-picker__columns {\n display: flex;\n border-bottom: 1px solid #f0f0f0;\n}\n\n.b-time-picker__column {\n width: var(--b-time-picker-column-width);\n height: var(--b-time-picker-column-height);\n overflow-y: auto;\n overflow-x: hidden;\n border-right: 1px solid #f0f0f0;\n scroll-behavior: smooth;\n scrollbar-width: thin;\n}\n\n.b-time-picker__column:last-child {\n border-right: none;\n}\n\n/* ──── Cells ──── */\n.b-time-picker__cell {\n height: var(--b-time-picker-cell-height);\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n font-size: 14px;\n color: var(--b-time-picker-text-color);\n transition: background var(--b-time-picker-transition-duration);\n user-select: none;\n}\n\n.b-time-picker__cell:hover {\n background: var(--b-time-picker-cell-hover-bg);\n}\n\n.b-time-picker__cell--selected {\n background: var(--b-time-picker-cell-selected-bg);\n font-weight: 600;\n}\n\n.b-time-picker__cell--focused {\n outline: 2px solid var(--b-time-picker-active-border-color);\n outline-offset: -2px;\n}\n\n.b-time-picker__cell--disabled {\n color: var(--b-time-picker-cell-disabled-color);\n background: var(--b-time-picker-cell-disabled-bg);\n cursor: not-allowed;\n}\n\n.b-time-picker__cell--disabled:hover {\n background: var(--b-time-picker-cell-disabled-bg);\n}\n\n/* ──── Footer ──── */\n.b-time-picker__footer {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 4px 8px;\n background: var(--b-time-picker-footer-bg);\n}\n\n.b-time-picker__now-btn {\n border: none;\n background: none;\n color: var(--b-time-picker-active-border-color);\n cursor: pointer;\n font-size: 14px;\n padding: 4px 8px;\n border-radius: 4px;\n transition: background var(--b-time-picker-transition-duration);\n}\n\n.b-time-picker__now-btn:hover {\n background: rgba(0, 0, 0, 0.04);\n}\n\n.b-time-picker__ok-btn {\n border: none;\n background: var(--b-time-picker-active-border-color);\n color: #fff;\n cursor: pointer;\n font-size: 14px;\n padding: 2px 12px;\n border-radius: 4px;\n font-weight: 500;\n line-height: 1.5;\n transition:\n background var(--b-time-picker-transition-duration),\n opacity var(--b-time-picker-transition-duration);\n}\n\n.b-time-picker__ok-btn:hover {\n opacity: 0.85;\n}\n\n/* ──── Placement ──── */\n.b-time-picker--bottom-right .b-time-picker__panel {\n left: unset;\n right: anchor(right);\n}\n\n.b-time-picker--top-left .b-time-picker__panel {\n top: unset;\n bottom: anchor(top);\n margin-top: 0;\n margin-bottom: 4px;\n}\n\n.b-time-picker--top-right .b-time-picker__panel {\n top: unset;\n bottom: anchor(top);\n left: unset;\n right: anchor(right);\n margin-top: 0;\n margin-bottom: 4px;\n}\n\n/* ──── Dark Mode ──── */\n[data-prefers-color='dark'] .b-time-picker {\n --b-time-picker-bg: #141414;\n --b-time-picker-hover-bg: #141414;\n --b-time-picker-active-bg: #141414;\n --b-time-picker-border-color: #424242;\n --b-time-picker-hover-border-color: #165dff;\n --b-time-picker-active-border-color: #1668dc;\n --b-time-picker-active-shadow: 0 0 0 2px rgba(22, 104, 220, 0.15);\n --b-time-picker-text-color: rgba(255, 255, 255, 0.85);\n --b-time-picker-placeholder-color: rgba(255, 255, 255, 0.25);\n --b-time-picker-icon-color: rgba(255, 255, 255, 0.3);\n --b-time-picker-clear-color: rgba(255, 255, 255, 0.3);\n --b-time-picker-clear-hover-color: rgba(255, 255, 255, 0.55);\n --b-time-picker-disabled-bg: rgba(255, 255, 255, 0.08);\n --b-time-picker-disabled-color: rgba(255, 255, 255, 0.25);\n --b-time-picker-panel-bg: #1f1f1f;\n --b-time-picker-panel-shadow: 0 6px 16px 0 rgba(0, 0, 0, 0.32), 0 3px 6px -4px rgba(0, 0, 0, 0.48), 0 9px 28px 8px rgba(0, 0, 0, 0.2);\n --b-time-picker-cell-hover-bg: rgba(255, 255, 255, 0.08);\n --b-time-picker-cell-selected-bg: #111a2c;\n --b-time-picker-cell-disabled-bg: rgba(255, 255, 255, 0.04);\n --b-time-picker-cell-disabled-color: rgba(255, 255, 255, 0.25);\n --b-time-picker-footer-bg: #1f1f1f;\n --b-time-picker-error-active-shadow: 0 0 0 2px rgba(220, 56, 72, 0.15);\n --b-time-picker-warning-active-shadow: 0 0 0 2px rgba(217, 146, 0, 0.15);\n}\n\n@media (prefers-color-scheme: dark) {\n [data-prefers-color='system'] .b-time-picker {\n --b-time-picker-bg: #141414;\n --b-time-picker-hover-bg: #141414;\n --b-time-picker-active-bg: #141414;\n --b-time-picker-border-color: #424242;\n --b-time-picker-hover-border-color: #165dff;\n --b-time-picker-active-border-color: #1668dc;\n --b-time-picker-active-shadow: 0 0 0 2px rgba(22, 104, 220, 0.15);\n --b-time-picker-text-color: rgba(255, 255, 255, 0.85);\n --b-time-picker-placeholder-color: rgba(255, 255, 255, 0.25);\n --b-time-picker-icon-color: rgba(255, 255, 255, 0.3);\n --b-time-picker-clear-color: rgba(255, 255, 255, 0.3);\n --b-time-picker-clear-hover-color: rgba(255, 255, 255, 0.55);\n --b-time-picker-disabled-bg: rgba(255, 255, 255, 0.08);\n --b-time-picker-disabled-color: rgba(255, 255, 255, 0.25);\n --b-time-picker-panel-bg: #1f1f1f;\n --b-time-picker-panel-shadow: 0 6px 16px 0 rgba(0, 0, 0, 0.32), 0 3px 6px -4px rgba(0, 0, 0, 0.48), 0 9px 28px 8px rgba(0, 0, 0, 0.2);\n --b-time-picker-cell-hover-bg: rgba(255, 255, 255, 0.08);\n --b-time-picker-cell-selected-bg: #111a2c;\n --b-time-picker-cell-disabled-bg: rgba(255, 255, 255, 0.04);\n --b-time-picker-cell-disabled-color: rgba(255, 255, 255, 0.25);\n --b-time-picker-footer-bg: #1f1f1f;\n --b-time-picker-error-active-shadow: 0 0 0 2px rgba(220, 56, 72, 0.15);\n --b-time-picker-warning-active-shadow: 0 0 0 2px rgba(217, 146, 0, 0.15);\n }\n}\n\n/* ──── Reduced Motion ──── */\n@media (prefers-reduced-motion: reduce) {\n .b-time-picker,\n .b-time-picker * {\n --b-time-picker-transition-duration: 0ms;\n transition-duration: 0ms !important;\n animation-duration: 0ms !important;\n }\n\n .b-time-picker__column {\n scroll-behavior: auto;\n }\n}\n</style>\n"],"mappings":"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"}
1
+ {"version":3,"file":"design-system228.js","names":[],"sources":["../src/components/BStatistic/BStatistic.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, useSlots } from 'vue';\n\nimport type { BStatisticFormatter, BStatisticValue } from './types';\n\n// ─────────────────────────────────────────────\n// Props\n// ─────────────────────────────────────────────\nconst {\n title,\n value,\n prefix,\n suffix,\n precision,\n decimalSeparator = '.',\n groupSeparator = ',',\n loading = false,\n valueStyle,\n formatter,\n} = defineProps<{\n /** Display title shown above the value. Use `#title` slot for richer content. */\n title?: string;\n /** Display value. Numbers are formatted; strings render as-is. */\n value: BStatisticValue;\n /** Prefix text before the value. Use `#prefix` slot for richer content. */\n prefix?: string;\n /** Suffix text after the value. Use `#suffix` slot for richer content. */\n suffix?: string;\n /** Number of digits after the decimal point. Applied only to numeric values. */\n precision?: number;\n /** Character used as the decimal separator. @default '.' */\n decimalSeparator?: string;\n /** Character used as the thousands group separator. @default ',' */\n groupSeparator?: string;\n /** Show a skeleton placeholder instead of the value. @default false */\n loading?: boolean;\n /** Inline style applied to the value element. */\n valueStyle?: string | Record<string, string | number>;\n /** Function that returns a custom display string. Overridden by `#formatter` slot. */\n formatter?: BStatisticFormatter;\n}>();\n\n// ─────────────────────────────────────────────\n// Slots\n// ─────────────────────────────────────────────\ndefineSlots<{\n /** Custom title content; overrides `title` prop. */\n title?(): unknown;\n /** Prefix content; overrides `prefix` prop. */\n prefix?(): unknown;\n /** Suffix content; overrides `suffix` prop. */\n suffix?(): unknown;\n /** Custom value renderer; receives `{ value }`. Overrides `formatter` prop. */\n formatter?(payload: { value: BStatisticValue }): unknown;\n}>();\n\nconst slots = useSlots();\n\n// ─────────────────────────────────────────────\n// Number formatting\n// ─────────────────────────────────────────────\nconst formattedValue = computed<string>(() => {\n if (formatter) return String(formatter(value));\n if (typeof value !== 'number') return String(value ?? '');\n if (Number.isNaN(value)) return 'NaN';\n if (!Number.isFinite(value)) return String(value);\n\n const negative = value < 0;\n const abs = Math.abs(value);\n\n let str: string;\n if (precision != null && precision >= 0) {\n str = abs.toFixed(precision);\n } else {\n str = String(abs);\n }\n\n const [intPart, decPart] = str.split('.');\n const intWithGroups = intPart.replace(/\\B(?=(\\d{3})+(?!\\d))/g, groupSeparator);\n const result = decPart != null ? `${intWithGroups}${decimalSeparator}${decPart}` : intWithGroups;\n return negative ? `-${result}` : result;\n});\n\nconst hasTitle = computed(() => !!slots.title || (title != null && title !== ''));\nconst hasPrefix = computed(() => !!slots.prefix || (prefix != null && prefix !== ''));\nconst hasSuffix = computed(() => !!slots.suffix || (suffix != null && suffix !== ''));\n</script>\n\n<template>\n <div class=\"b-statistic\" :class=\"{ 'b-statistic--loading': loading }\">\n <div v-if=\"hasTitle\" class=\"b-statistic__title\">\n <slot name=\"title\">{{ title }}</slot>\n </div>\n <div class=\"b-statistic__content\" :style=\"valueStyle\" aria-live=\"polite\">\n <span\n v-if=\"loading\"\n class=\"b-statistic__skeleton\"\n role=\"status\"\n aria-busy=\"true\"\n aria-label=\"Loading\"\n />\n <template v-else>\n <span v-if=\"hasPrefix\" class=\"b-statistic__prefix\" aria-hidden=\"true\">\n <slot name=\"prefix\">{{ prefix }}</slot>\n </span>\n <span class=\"b-statistic__value\">\n <slot name=\"formatter\" :value=\"value\">{{ formattedValue }}</slot>\n </span>\n <span v-if=\"hasSuffix\" class=\"b-statistic__suffix\" aria-hidden=\"true\">\n <slot name=\"suffix\">{{ suffix }}</slot>\n </span>\n </template>\n </div>\n </div>\n</template>\n\n<style>\n/* ─────────────────────────────────────────────\n BStatistic - CSS custom properties (scoped to root)\n ───────────────────────────────────────────── */\n.b-statistic {\n /* ── Title ── */\n --b-statistic-title-color: oklch(45% 0.02 260);\n --b-statistic-title-font-size: 14px;\n --b-statistic-title-line-height: 1.5715;\n --b-statistic-title-margin-bottom: 4px;\n\n /* ── Content (value) ── */\n --b-statistic-content-color: oklch(20% 0.02 260);\n --b-statistic-content-font-size: 24px;\n --b-statistic-content-line-height: 1.5;\n --b-statistic-content-font-family: inherit;\n --b-statistic-content-font-weight: 400;\n\n /* ── Prefix / Suffix ── */\n --b-statistic-prefix-color: inherit;\n --b-statistic-prefix-font-size: inherit;\n --b-statistic-prefix-margin-end: 4px;\n --b-statistic-suffix-color: inherit;\n --b-statistic-suffix-font-size: inherit;\n --b-statistic-suffix-margin-start: 4px;\n\n /* ── Skeleton ── */\n --b-statistic-skeleton-color: oklch(92% 0.005 260);\n --b-statistic-skeleton-highlight: oklch(96% 0.003 260);\n --b-statistic-skeleton-width: 96px;\n --b-statistic-skeleton-height: 1em;\n --b-statistic-skeleton-radius: 4px;\n --b-statistic-skeleton-duration: 1.4s;\n\n font-family: var(--b-statistic-content-font-family);\n color: var(--b-statistic-content-color);\n}\n\n/* ─────────────────────────────────────────────\n Title\n ───────────────────────────────────────────── */\n.b-statistic__title {\n margin-bottom: var(--b-statistic-title-margin-bottom);\n color: var(--b-statistic-title-color);\n font-size: var(--b-statistic-title-font-size);\n line-height: var(--b-statistic-title-line-height);\n}\n\n/* ─────────────────────────────────────────────\n Content / value\n ───────────────────────────────────────────── */\n.b-statistic__content {\n display: inline-flex;\n align-items: baseline;\n color: var(--b-statistic-content-color);\n font-size: var(--b-statistic-content-font-size);\n font-weight: var(--b-statistic-content-font-weight);\n line-height: var(--b-statistic-content-line-height);\n font-feature-settings: 'tnum';\n font-variant-numeric: tabular-nums;\n word-break: break-word;\n max-width: 100%;\n}\n\n.b-statistic__value {\n display: inline-block;\n}\n\n.b-statistic__prefix {\n display: inline-flex;\n align-items: center;\n margin-inline-end: var(--b-statistic-prefix-margin-end);\n color: var(--b-statistic-prefix-color);\n font-size: var(--b-statistic-prefix-font-size);\n}\n\n.b-statistic__suffix {\n display: inline-flex;\n align-items: center;\n margin-inline-start: var(--b-statistic-suffix-margin-start);\n color: var(--b-statistic-suffix-color);\n font-size: var(--b-statistic-suffix-font-size);\n}\n\n/* ─────────────────────────────────────────────\n Loading skeleton\n ───────────────────────────────────────────── */\n.b-statistic__skeleton {\n display: inline-block;\n width: var(--b-statistic-skeleton-width);\n height: var(--b-statistic-skeleton-height);\n border-radius: var(--b-statistic-skeleton-radius);\n background: linear-gradient(\n 90deg,\n var(--b-statistic-skeleton-color) 25%,\n var(--b-statistic-skeleton-highlight) 37%,\n var(--b-statistic-skeleton-color) 63%\n );\n background-size: 400% 100%;\n animation: b-statistic-shimmer var(--b-statistic-skeleton-duration) ease infinite;\n}\n\n@keyframes b-statistic-shimmer {\n 0% {\n background-position: 100% 50%;\n }\n 100% {\n background-position: 0 50%;\n }\n}\n\n/* ─────────────────────────────────────────────\n Dark mode\n ───────────────────────────────────────────── */\n[data-prefers-color='dark'] .b-statistic {\n --b-statistic-title-color: oklch(70% 0.01 260);\n --b-statistic-content-color: oklch(92% 0.01 260);\n --b-statistic-skeleton-color: oklch(28% 0.01 260);\n --b-statistic-skeleton-highlight: oklch(35% 0.01 260);\n}\n\n@media (prefers-color-scheme: dark) {\n [data-prefers-color='system'] .b-statistic {\n --b-statistic-title-color: oklch(70% 0.01 260);\n --b-statistic-content-color: oklch(92% 0.01 260);\n --b-statistic-skeleton-color: oklch(28% 0.01 260);\n --b-statistic-skeleton-highlight: oklch(35% 0.01 260);\n }\n}\n\n/* ─────────────────────────────────────────────\n Reduced motion\n ───────────────────────────────────────────── */\n@media (prefers-reduced-motion: reduce) {\n .b-statistic {\n --b-statistic-skeleton-duration: 0ms;\n }\n .b-statistic__skeleton {\n animation: none;\n opacity: 0.6;\n }\n}\n</style>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAwDA,IAAM,IAAQ,GAAU,EAKlB,IAAiB,QAAuB;AAC5C,OAAI,EAAA,UAAW,QAAO,OAAO,EAAA,UAAU,EAAA,MAAM,CAAC;AAC9C,OAAI,OAAO,EAAA,SAAU,SAAU,QAAO,OAAO,EAAA,SAAS,GAAG;AACzD,OAAI,OAAO,MAAM,EAAA,MAAM,CAAE,QAAO;AAChC,OAAI,CAAC,OAAO,SAAS,EAAA,MAAM,CAAE,QAAO,OAAO,EAAA,MAAM;GAEjD,IAAM,IAAW,EAAA,QAAQ,GACnB,IAAM,KAAK,IAAI,EAAA,MAAM,EAEvB;AACJ,GAGE,IAHE,EAAA,aAAa,QAAQ,EAAA,aAAa,IAC9B,EAAI,QAAQ,EAAA,UAAU,GAEtB,OAAO,EAAI;GAGnB,IAAM,CAAC,GAAS,KAAW,EAAI,MAAM,IAAI,EACnC,IAAgB,EAAQ,QAAQ,yBAAyB,EAAA,eAAe,EACxE,IAAS,KAAW,OAAyD,IAAlD,GAAG,IAAgB,EAAA,mBAAmB;AACvE,UAAO,IAAW,IAAI,MAAW;IACjC,EAEI,IAAW,QAAe,CAAC,CAAC,EAAM,SAAU,EAAA,SAAS,QAAQ,EAAA,UAAU,GAAI,EAC3E,IAAY,QAAe,CAAC,CAAC,EAAM,UAAW,EAAA,UAAU,QAAQ,EAAA,WAAW,GAAI,EAC/E,IAAY,QAAe,CAAC,CAAC,EAAM,UAAW,EAAA,UAAU,QAAQ,EAAA,WAAW,GAAI;yBAInF,EAwBM,OAAA,EAxBD,OAAK,EAAA,CAAC,eAAa,EAAA,wBAAmC,EAAA,SAAO,CAAA,CAAA,EAAA,EAAA,CACrD,EAAA,SAAA,GAAA,EAAX,EAEM,OAFN,GAEM,CADJ,EAAqC,EAAA,QAAA,SAAA,EAAA,QAAA,CAAA,EAAA,EAAf,EAAA,MAAK,EAAA,EAAA,CAAA,CAAA,CAAA,CAAA,IAAA,EAAA,IAAA,GAAA,EAE7B,EAmBM,OAAA;GAnBD,OAAM;GAAwB,OAAK,EAAE,EAAA,WAAU;GAAE,aAAU;MAEtD,EAAA,WAAA,GAAA,EADR,EAME,QANF,EAME,KAAA,GAAA,EACF,EAUW,GAAA,EAAA,KAAA,GAAA,EAAA;GATG,EAAA,SAAA,GAAA,EAAZ,EAEO,QAFP,GAEO,CADL,EAAuC,EAAA,QAAA,UAAA,EAAA,QAAA,CAAA,EAAA,EAAhB,EAAA,OAAM,EAAA,EAAA,CAAA,CAAA,CAAA,CAAA,IAAA,EAAA,IAAA,GAAA;GAE/B,EAEO,QAFP,GAEO,CADL,EAAiE,EAAA,QAAA,aAAA,EAAzC,OAAO,EAAA,OAAK,QAA6B,CAAA,EAAA,EAAxB,EAAA,MAAc,EAAA,EAAA,CAAA,CAAA,CAAA,CAAA;GAE7C,EAAA,SAAA,GAAA,EAAZ,EAEO,QAFP,GAEO,CADL,EAAuC,EAAA,QAAA,UAAA,EAAA,QAAA,CAAA,EAAA,EAAhB,EAAA,OAAM,EAAA,EAAA,CAAA,CAAA,CAAA,CAAA,IAAA,EAAA,IAAA,GAAA"}
@@ -1,6 +1,6 @@
1
1
  import e from "./design-system228.js";
2
2
  /* empty css */
3
- //#region src/components/BTimePicker/BTimePicker.vue
3
+ //#region src/components/BStatistic/BStatistic.vue
4
4
  var t = e;
5
5
  //#endregion
6
6
  export { t as default };
@@ -1 +1 @@
1
- {"version":3,"file":"design-system230.js","names":[],"sources":["../src/components/BTimePicker/BTimePicker.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { useComponentId } from '@/composables/useComponentId.ts';\nimport { computed, nextTick, onBeforeUnmount, onMounted, ref, watch } from 'vue';\n\nimport {\n BTimePickerPlacement,\n BTimePickerSize,\n BTimePickerStatus,\n BTimePickerVariant,\n type BTimePickerDisabledTime,\n} from './types';\n\nconst {\n size = BTimePickerSize.Medium,\n variant = BTimePickerVariant.Outlined,\n placeholder = 'Select time',\n disabled = false,\n inputReadOnly = false,\n allowClear = true,\n showNow = true,\n use12Hours = false,\n hourStep = 1,\n minuteStep = 1,\n secondStep = 1,\n format,\n placement: _placement = BTimePickerPlacement.BottomLeft,\n status,\n hideDisabledOptions = false,\n needConfirm = true,\n changeOnScroll = false,\n showHour = true,\n showMinute = true,\n showSecond = true,\n defaultOpen = false,\n defaultValue,\n open,\n disabledTime,\n} = defineProps<{\n /** Size of the input */\n size?: `${BTimePickerSize}`;\n /** Visual variant */\n variant?: `${BTimePickerVariant}`;\n /** Placeholder text */\n placeholder?: string;\n /** Disable the picker */\n disabled?: boolean;\n /** Make input read-only (useful for touch devices) */\n inputReadOnly?: boolean;\n /** Show clear button */\n allowClear?: boolean;\n /** Show \"Now\" button in footer */\n showNow?: boolean;\n /** Use 12-hour format with AM/PM */\n use12Hours?: boolean;\n /** Hour selection step */\n hourStep?: number;\n /** Minute selection step */\n minuteStep?: number;\n /** Second selection step */\n secondStep?: number;\n /** Time format string (e.g. 'HH:mm:ss', 'hh:mm a') */\n format?: string;\n /** Popup placement */\n placement?: `${BTimePickerPlacement}`;\n /** Validation status */\n status?: `${BTimePickerStatus}`;\n /** Hide disabled time options from columns */\n hideDisabledOptions?: boolean;\n /** Require OK button confirmation before applying value */\n needConfirm?: boolean;\n /** Update value on scroll instead of click */\n changeOnScroll?: boolean;\n /** Show hour column */\n showHour?: boolean;\n /** Show minute column */\n showMinute?: boolean;\n /** Show second column */\n showSecond?: boolean;\n /** Default open state */\n defaultOpen?: boolean;\n /** Default value (uncontrolled) */\n defaultValue?: Date;\n /** Controlled open state */\n open?: boolean;\n /** Function returning disabled hours/minutes/seconds */\n disabledTime?: () => BTimePickerDisabledTime;\n}>();\n\nconst model = defineModel<Date | null>({ default: undefined });\n\nconst emit = defineEmits<{\n change: [time: Date | null, timeString: string];\n openChange: [open: boolean];\n}>();\n\nconst inputEl = ref<HTMLInputElement | null>(null);\nconst panelEl = ref<HTMLElement | null>(null);\nconst hourColEl = ref<HTMLElement | null>(null);\nconst minuteColEl = ref<HTMLElement | null>(null);\nconst secondColEl = ref<HTMLElement | null>(null);\nconst ampmColEl = ref<HTMLElement | null>(null);\n\ndefineExpose({\n focus: () => inputEl.value?.focus(),\n blur: () => inputEl.value?.blur(),\n});\n\nconst { componentUID } = useComponentId();\nconst anchorName = computed(() => `--b-time-picker-${componentUID.value}`);\n\n// ─────────────────────────────────────────────\n// State\n// ─────────────────────────────────────────────\nconst isOpen = ref(defaultOpen);\nconst isPanelOpen = ref(open !== undefined ? !!open : defaultOpen);\nconst internalValue = ref<Date | null>(defaultValue ?? null);\nconst pendingHour = ref<number | null>(null);\nconst pendingMinute = ref<number | null>(null);\nconst pendingSecond = ref<number | null>(null);\nconst pendingAmpm = ref<'AM' | 'PM' | null>(null);\nconst inputText = ref('');\nconst focusedColumn = ref<'hour' | 'minute' | 'second' | 'ampm'>('hour');\n\nconst selectedTime = computed({\n get: () => model.value ?? internalValue.value,\n set: (val) => {\n internalValue.value = val;\n model.value = val;\n },\n});\n\n// ─────────────────────────────────────────────\n// Format\n// ─────────────────────────────────────────────\nconst activeFormat = computed(() => {\n if (format) return format;\n const parts: string[] = [];\n if (showHour) parts.push(use12Hours ? 'hh' : 'HH');\n if (showMinute) parts.push('mm');\n if (showSecond) parts.push('ss');\n const base = parts.join(':');\n return use12Hours ? `${base} A` : base;\n});\n\nfunction pad(n: number): string {\n return String(n).padStart(2, '0');\n}\n\nfunction formatTime(d: Date | null): string {\n if (!d) return '';\n const h = d.getHours();\n const m = d.getMinutes();\n const s = d.getSeconds();\n const ampm = h >= 12 ? 'PM' : 'AM';\n\n let result = activeFormat.value;\n if (use12Hours) {\n const h12 = h % 12 || 12;\n result = result.replace('hh', pad(h12));\n result = result.replace('h', String(h12));\n result = result.replace('A', ampm);\n result = result.replace('a', ampm.toLowerCase());\n } else {\n result = result.replace('HH', pad(h));\n result = result.replace('H', String(h));\n }\n result = result.replace('mm', pad(m));\n result = result.replace('ss', pad(s));\n return result;\n}\n\nfunction parseTimeString(str: string): Date | null {\n if (!str.trim()) return null;\n const timeRegex12 = /(\\d{1,2}):(\\d{2})(?::(\\d{2}))?\\s*(AM|PM|am|pm)?/;\n const match = str.match(timeRegex12);\n if (!match) return null;\n\n let h = parseInt(match[1], 10);\n const m = parseInt(match[2], 10);\n const s = match[3] ? parseInt(match[3], 10) : 0;\n const period = match[4]?.toUpperCase();\n\n if (use12Hours && period) {\n if (period === 'PM' && h < 12) h += 12;\n if (period === 'AM' && h === 12) h = 0;\n }\n\n if (h < 0 || h > 23 || m < 0 || m > 59 || s < 0 || s > 59) return null;\n\n const d = new Date();\n d.setHours(h, m, s, 0);\n return d;\n}\n\n// ─────────────────────────────────────────────\n// Disabled time logic\n// ─────────────────────────────────────────────\nconst disabledHours = computed<number[]>(() => {\n if (!disabledTime) return [];\n const dt = disabledTime();\n return dt.disabledHours?.() ?? [];\n});\n\nconst disabledMinutes = computed<number[]>(() => {\n if (!disabledTime) return [];\n const dt = disabledTime();\n const h = pendingHour.value ?? selectedTime.value?.getHours() ?? 0;\n return dt.disabledMinutes?.(h) ?? [];\n});\n\nconst disabledSeconds = computed<number[]>(() => {\n if (!disabledTime) return [];\n const dt = disabledTime();\n const h = pendingHour.value ?? selectedTime.value?.getHours() ?? 0;\n const m = pendingMinute.value ?? selectedTime.value?.getMinutes() ?? 0;\n return dt.disabledSeconds?.(h, m) ?? [];\n});\n\n// ─────────────────────────────────────────────\n// Column data\n// ─────────────────────────────────────────────\nconst hours = computed(() => {\n const list: number[] = [];\n if (use12Hours) {\n for (let i = 1; i <= 12; i += hourStep) list.push(i);\n } else {\n for (let i = 0; i < 24; i += hourStep) list.push(i);\n }\n if (hideDisabledOptions) {\n return list.filter((h) => !disabledHours.value.includes(use12Hours ? to24Hour(h, pendingAmpm.value ?? 'AM') : h));\n }\n return list;\n});\n\nconst minutes = computed(() => {\n const list: number[] = [];\n for (let i = 0; i < 60; i += minuteStep) list.push(i);\n if (hideDisabledOptions) {\n return list.filter((m) => !disabledMinutes.value.includes(m));\n }\n return list;\n});\n\nconst seconds = computed(() => {\n const list: number[] = [];\n for (let i = 0; i < 60; i += secondStep) list.push(i);\n if (hideDisabledOptions) {\n return list.filter((s) => !disabledSeconds.value.includes(s));\n }\n return list;\n});\n\nfunction to24Hour(h12: number, period: 'AM' | 'PM'): number {\n if (period === 'AM') return h12 === 12 ? 0 : h12;\n return h12 === 12 ? 12 : h12 + 12;\n}\n\nfunction to12Hour(h24: number): { hour: number; period: 'AM' | 'PM' } {\n const period: 'AM' | 'PM' = h24 >= 12 ? 'PM' : 'AM';\n const hour = h24 % 12 || 12;\n return { hour, period };\n}\n\n// ─────────────────────────────────────────────\n// Panel open/close\n// ─────────────────────────────────────────────\nfunction openPanel() {\n if (disabled) return;\n isOpen.value = true;\n isPanelOpen.value = true;\n emit('openChange', true);\n panelEl.value?.showPopover?.();\n syncPendingFromValue();\n nextTick(() => scrollToSelected());\n}\n\nfunction closePanel() {\n isOpen.value = false;\n isPanelOpen.value = false;\n emit('openChange', false);\n panelEl.value?.hidePopover?.();\n inputEl.value?.focus();\n}\n\nfunction togglePanel() {\n if (isPanelOpen.value) closePanel();\n else openPanel();\n}\n\nfunction handlePopoverToggle(e: Event) {\n const toggleEvent = e as ToggleEvent;\n const nowOpen = toggleEvent.newState === 'open';\n isOpen.value = nowOpen;\n isPanelOpen.value = nowOpen;\n if (!nowOpen) emit('openChange', false);\n}\n\n// ─────────────────────────────────────────────\n// Sync pending state\n// ─────────────────────────────────────────────\nfunction syncPendingFromValue() {\n const t = selectedTime.value;\n if (t) {\n if (use12Hours) {\n const { hour, period } = to12Hour(t.getHours());\n pendingHour.value = hour;\n pendingAmpm.value = period;\n } else {\n pendingHour.value = t.getHours();\n }\n pendingMinute.value = t.getMinutes();\n pendingSecond.value = t.getSeconds();\n } else {\n pendingHour.value = null;\n pendingMinute.value = null;\n pendingSecond.value = null;\n pendingAmpm.value = null;\n }\n}\n\n// ─────────────────────────────────────────────\n// Selection\n// ─────────────────────────────────────────────\nfunction selectHour(h: number) {\n const h24 = use12Hours ? to24Hour(h, pendingAmpm.value ?? 'AM') : h;\n if (disabledHours.value.includes(h24)) return;\n pendingHour.value = h;\n if (!needConfirm && !changeOnScroll) applyPendingIfComplete();\n else if (changeOnScroll) applyPending();\n}\n\nfunction selectMinute(m: number) {\n if (disabledMinutes.value.includes(m)) return;\n pendingMinute.value = m;\n if (!needConfirm && !changeOnScroll) applyPendingIfComplete();\n else if (changeOnScroll) applyPending();\n}\n\nfunction selectSecond(s: number) {\n if (disabledSeconds.value.includes(s)) return;\n pendingSecond.value = s;\n if (!needConfirm && !changeOnScroll) applyPendingIfComplete();\n else if (changeOnScroll) applyPending();\n}\n\nfunction selectAmpm(val: 'AM' | 'PM') {\n pendingAmpm.value = val;\n if (!needConfirm && !changeOnScroll) applyPendingIfComplete();\n else if (changeOnScroll) applyPending();\n}\n\nfunction applyPendingIfComplete() {\n if (pendingHour.value !== null && pendingMinute.value !== null) {\n if (showSecond && pendingSecond.value === null) return;\n if (use12Hours && pendingAmpm.value === null) return;\n applyPending();\n closePanel();\n }\n}\n\nfunction applyPending() {\n const h = pendingHour.value ?? 0;\n const m = pendingMinute.value ?? 0;\n const s = pendingSecond.value ?? 0;\n const h24 = use12Hours ? to24Hour(h, pendingAmpm.value ?? 'AM') : h;\n\n const d = new Date();\n d.setHours(h24, m, s, 0);\n selectedTime.value = d;\n inputText.value = formatTime(d);\n emit('change', d, formatTime(d));\n}\n\nfunction handleOk() {\n applyPending();\n closePanel();\n}\n\nfunction handleNow() {\n const now = new Date();\n if (use12Hours) {\n const { hour, period } = to12Hour(now.getHours());\n pendingHour.value = hour;\n pendingAmpm.value = period;\n } else {\n pendingHour.value = now.getHours();\n }\n pendingMinute.value = now.getMinutes();\n pendingSecond.value = now.getSeconds();\n nextTick(() => scrollToSelected());\n if (!needConfirm) {\n applyPending();\n closePanel();\n }\n}\n\nfunction handleClear(e: Event) {\n e.stopPropagation();\n selectedTime.value = null;\n inputText.value = '';\n pendingHour.value = null;\n pendingMinute.value = null;\n pendingSecond.value = null;\n pendingAmpm.value = null;\n emit('change', null, '');\n}\n\n// ─────────────────────────────────────────────\n// Input handling\n// ─────────────────────────────────────────────\nfunction handleInputChange(e: Event) {\n const val = (e.target as HTMLInputElement).value;\n inputText.value = val;\n}\n\nfunction handleInputBlur() {\n if (!isPanelOpen.value) {\n const parsed = parseTimeString(inputText.value);\n if (parsed) {\n selectedTime.value = parsed;\n inputText.value = formatTime(parsed);\n emit('change', parsed, formatTime(parsed));\n } else if (inputText.value === '') {\n selectedTime.value = null;\n emit('change', null, '');\n } else {\n inputText.value = formatTime(selectedTime.value);\n }\n }\n}\n\nfunction handleInputKeydown(e: KeyboardEvent) {\n if (e.key === 'Enter' || e.key === ' ') {\n if (!isPanelOpen.value) {\n e.preventDefault();\n openPanel();\n } else if (e.key === 'Enter') {\n e.preventDefault();\n const parsed = parseTimeString(inputText.value);\n if (parsed) {\n selectedTime.value = parsed;\n inputText.value = formatTime(parsed);\n emit('change', parsed, formatTime(parsed));\n }\n closePanel();\n }\n } else if (e.key === 'Escape') {\n if (isPanelOpen.value) {\n e.preventDefault();\n closePanel();\n }\n }\n}\n\n// ─────────────────────────────────────────────\n// Panel keyboard navigation\n// ─────────────────────────────────────────────\nfunction handlePanelKeydown(e: KeyboardEvent) {\n if (e.key === 'Escape') {\n e.preventDefault();\n closePanel();\n return;\n }\n\n if (e.key === 'Tab') {\n const columns: ('hour' | 'minute' | 'second' | 'ampm')[] = [];\n if (showHour) columns.push('hour');\n if (showMinute) columns.push('minute');\n if (showSecond) columns.push('second');\n if (use12Hours) columns.push('ampm');\n\n const idx = columns.indexOf(focusedColumn.value);\n if (e.shiftKey) {\n if (idx > 0) {\n e.preventDefault();\n focusedColumn.value = columns[idx - 1];\n }\n } else {\n if (idx < columns.length - 1) {\n e.preventDefault();\n focusedColumn.value = columns[idx + 1];\n }\n }\n return;\n }\n\n if (e.key === 'ArrowUp' || e.key === 'ArrowDown') {\n e.preventDefault();\n const delta = e.key === 'ArrowUp' ? -1 : 1;\n adjustFocusedColumn(delta);\n return;\n }\n\n if (e.key === 'Enter') {\n e.preventDefault();\n handleOk();\n }\n}\n\nfunction adjustFocusedColumn(delta: number) {\n if (focusedColumn.value === 'hour') {\n const list = hours.value;\n const current = pendingHour.value ?? list[0];\n const idx = list.indexOf(current);\n const next = list[Math.max(0, Math.min(list.length - 1, idx + delta))];\n selectHour(next);\n scrollColumnTo(hourColEl.value, list.indexOf(next));\n } else if (focusedColumn.value === 'minute') {\n const list = minutes.value;\n const current = pendingMinute.value ?? list[0];\n const idx = list.indexOf(current);\n const next = list[Math.max(0, Math.min(list.length - 1, idx + delta))];\n selectMinute(next);\n scrollColumnTo(minuteColEl.value, list.indexOf(next));\n } else if (focusedColumn.value === 'second') {\n const list = seconds.value;\n const current = pendingSecond.value ?? list[0];\n const idx = list.indexOf(current);\n const next = list[Math.max(0, Math.min(list.length - 1, idx + delta))];\n selectSecond(next);\n scrollColumnTo(secondColEl.value, list.indexOf(next));\n } else if (focusedColumn.value === 'ampm') {\n const val = pendingAmpm.value === 'AM' ? 'PM' : 'AM';\n selectAmpm(val);\n }\n}\n\n// ─────────────────────────────────────────────\n// Scroll helpers\n// ─────────────────────────────────────────────\nfunction scrollColumnTo(col: HTMLElement | null, idx: number) {\n if (!col || !col.scrollTo) return;\n const cellHeight = 28;\n col.scrollTo({ top: idx * cellHeight, behavior: 'smooth' });\n}\n\nfunction scrollToSelected() {\n if (pendingHour.value !== null) {\n const idx = hours.value.indexOf(pendingHour.value);\n if (idx >= 0) scrollColumnTo(hourColEl.value, idx);\n }\n if (pendingMinute.value !== null) {\n const idx = minutes.value.indexOf(pendingMinute.value);\n if (idx >= 0) scrollColumnTo(minuteColEl.value, idx);\n }\n if (pendingSecond.value !== null && showSecond) {\n const idx = seconds.value.indexOf(pendingSecond.value);\n if (idx >= 0) scrollColumnTo(secondColEl.value, idx);\n }\n if (pendingAmpm.value && use12Hours) {\n const idx = pendingAmpm.value === 'AM' ? 0 : 1;\n scrollColumnTo(ampmColEl.value, idx);\n }\n}\n\n// ─────────────────────────────────────────────\n// Click outside\n// ─────────────────────────────────────────────\nfunction handleClickOutside(e: MouseEvent) {\n if (!isPanelOpen.value) return;\n const target = e.target as Node;\n if (panelEl.value?.contains(target)) return;\n if (inputEl.value?.parentElement?.contains(target)) return;\n closePanel();\n}\n\nonMounted(() => {\n document.addEventListener('mousedown', handleClickOutside);\n});\nonBeforeUnmount(() => {\n document.removeEventListener('mousedown', handleClickOutside);\n});\n\n// ─────────────────────────────────────────────\n// Watchers\n// ─────────────────────────────────────────────\nwatch(\n () => open,\n (val) => {\n if (val !== undefined) {\n if (val) openPanel();\n else closePanel();\n }\n },\n);\n\nwatch(selectedTime, (val) => {\n inputText.value = formatTime(val);\n});\n\n// Init display\ninputText.value = formatTime(selectedTime.value);\n\n// ─────────────────────────────────────────────\n// Computed classes\n// ─────────────────────────────────────────────\nconst rootClasses = computed(() => [\n 'b-time-picker',\n `b-time-picker--${size}`,\n `b-time-picker--${variant}`,\n {\n 'b-time-picker--disabled': disabled,\n 'b-time-picker--open': isPanelOpen.value,\n [`b-time-picker--${status}`]: !!status,\n },\n]);\n\nconst isHourDisabled = (h: number) => {\n const h24 = use12Hours ? to24Hour(h, pendingAmpm.value ?? 'AM') : h;\n return disabledHours.value.includes(h24);\n};\nconst isMinuteDisabled = (m: number) => disabledMinutes.value.includes(m);\nconst isSecondDisabled = (s: number) => disabledSeconds.value.includes(s);\n</script>\n\n<template>\n <div :class=\"rootClasses\">\n <div\n class=\"b-time-picker__input-wrap\"\n :style=\"{ anchorName }\"\n @click=\"togglePanel\"\n >\n <input\n :id=\"`b-time-picker-input-${componentUID}`\"\n ref=\"inputEl\"\n class=\"b-time-picker__input\"\n type=\"text\"\n role=\"combobox\"\n :aria-expanded=\"isPanelOpen\"\n aria-haspopup=\"dialog\"\n :aria-controls=\"isPanelOpen ? `b-time-picker-panel-${componentUID}` : undefined\"\n :aria-describedby=\"status ? `b-time-picker-status-${componentUID}` : undefined\"\n :aria-label=\"placeholder\"\n :placeholder=\"placeholder\"\n :disabled=\"disabled\"\n :readonly=\"inputReadOnly\"\n :value=\"inputText\"\n autocomplete=\"off\"\n @input=\"handleInputChange\"\n @blur=\"handleInputBlur\"\n @keydown=\"handleInputKeydown\"\n />\n <span class=\"b-time-picker__suffix\">\n <svg\n v-if=\"!allowClear || !selectedTime\"\n class=\"b-time-picker__icon\"\n aria-hidden=\"true\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n >\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <polyline points=\"12 6 12 12 16 14\" />\n </svg>\n <button\n v-else\n class=\"b-time-picker__clear\"\n type=\"button\"\n aria-label=\"Clear time\"\n tabindex=\"-1\"\n @click=\"handleClear\"\n >\n <svg\n aria-hidden=\"true\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n >\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <line x1=\"15\" y1=\"9\" x2=\"9\" y2=\"15\" />\n <line x1=\"9\" y1=\"9\" x2=\"15\" y2=\"15\" />\n </svg>\n </button>\n </span>\n <span\n v-if=\"status\"\n :id=\"`b-time-picker-status-${componentUID}`\"\n class=\"b-time-picker__status-text\"\n aria-live=\"polite\"\n >\n {{ status }}\n </span>\n </div>\n\n <div\n :id=\"`b-time-picker-panel-${componentUID}`\"\n ref=\"panelEl\"\n class=\"b-time-picker__panel\"\n popover\n role=\"dialog\"\n :aria-label=\"'Time picker'\"\n :aria-modal=\"true\"\n :style=\"{ positionAnchor: anchorName }\"\n @toggle=\"handlePopoverToggle\"\n @keydown=\"handlePanelKeydown\"\n >\n <div class=\"b-time-picker__columns\" role=\"group\" aria-label=\"Time selection columns\">\n <!-- Hour Column -->\n <div\n v-if=\"showHour\"\n ref=\"hourColEl\"\n class=\"b-time-picker__column\"\n role=\"listbox\"\n :aria-label=\"'Hours'\"\n :aria-activedescendant=\"pendingHour !== null ? `b-time-picker-hour-${pendingHour}-${componentUID}` : undefined\"\n >\n <div\n v-for=\"h in hours\"\n :id=\"`b-time-picker-hour-${h}-${componentUID}`\"\n :key=\"h\"\n class=\"b-time-picker__cell\"\n :class=\"{\n 'b-time-picker__cell--selected': pendingHour === h,\n 'b-time-picker__cell--disabled': isHourDisabled(h),\n 'b-time-picker__cell--focused': focusedColumn === 'hour' && pendingHour === h,\n }\"\n role=\"option\"\n :aria-selected=\"pendingHour === h\"\n :aria-disabled=\"isHourDisabled(h)\"\n @click=\"selectHour(h)\"\n >\n {{ pad(h) }}\n </div>\n </div>\n\n <!-- Minute Column -->\n <div\n v-if=\"showMinute\"\n ref=\"minuteColEl\"\n class=\"b-time-picker__column\"\n role=\"listbox\"\n :aria-label=\"'Minutes'\"\n :aria-activedescendant=\"pendingMinute !== null ? `b-time-picker-minute-${pendingMinute}-${componentUID}` : undefined\"\n >\n <div\n v-for=\"m in minutes\"\n :id=\"`b-time-picker-minute-${m}-${componentUID}`\"\n :key=\"m\"\n class=\"b-time-picker__cell\"\n :class=\"{\n 'b-time-picker__cell--selected': pendingMinute === m,\n 'b-time-picker__cell--disabled': isMinuteDisabled(m),\n 'b-time-picker__cell--focused': focusedColumn === 'minute' && pendingMinute === m,\n }\"\n role=\"option\"\n :aria-selected=\"pendingMinute === m\"\n :aria-disabled=\"isMinuteDisabled(m)\"\n @click=\"selectMinute(m)\"\n >\n {{ pad(m) }}\n </div>\n </div>\n\n <!-- Second Column -->\n <div\n v-if=\"showSecond\"\n ref=\"secondColEl\"\n class=\"b-time-picker__column\"\n role=\"listbox\"\n :aria-label=\"'Seconds'\"\n :aria-activedescendant=\"pendingSecond !== null ? `b-time-picker-second-${pendingSecond}-${componentUID}` : undefined\"\n >\n <div\n v-for=\"s in seconds\"\n :id=\"`b-time-picker-second-${s}-${componentUID}`\"\n :key=\"s\"\n class=\"b-time-picker__cell\"\n :class=\"{\n 'b-time-picker__cell--selected': pendingSecond === s,\n 'b-time-picker__cell--disabled': isSecondDisabled(s),\n 'b-time-picker__cell--focused': focusedColumn === 'second' && pendingSecond === s,\n }\"\n role=\"option\"\n :aria-selected=\"pendingSecond === s\"\n :aria-disabled=\"isSecondDisabled(s)\"\n @click=\"selectSecond(s)\"\n >\n {{ pad(s) }}\n </div>\n </div>\n\n <!-- AM/PM Column -->\n <div\n v-if=\"use12Hours\"\n ref=\"ampmColEl\"\n class=\"b-time-picker__column b-time-picker__column--ampm\"\n role=\"listbox\"\n aria-label=\"AM/PM\"\n >\n <div\n class=\"b-time-picker__cell\"\n :class=\"{\n 'b-time-picker__cell--selected': pendingAmpm === 'AM',\n 'b-time-picker__cell--focused': focusedColumn === 'ampm' && pendingAmpm === 'AM',\n }\"\n role=\"option\"\n :aria-selected=\"pendingAmpm === 'AM'\"\n @click=\"selectAmpm('AM')\"\n >\n AM\n </div>\n <div\n class=\"b-time-picker__cell\"\n :class=\"{\n 'b-time-picker__cell--selected': pendingAmpm === 'PM',\n 'b-time-picker__cell--focused': focusedColumn === 'ampm' && pendingAmpm === 'PM',\n }\"\n role=\"option\"\n :aria-selected=\"pendingAmpm === 'PM'\"\n @click=\"selectAmpm('PM')\"\n >\n PM\n </div>\n </div>\n </div>\n\n <div v-if=\"needConfirm || showNow\" class=\"b-time-picker__footer\">\n <button\n v-if=\"showNow\"\n class=\"b-time-picker__now-btn\"\n type=\"button\"\n @click=\"handleNow\"\n >\n Now\n </button>\n <button\n v-if=\"needConfirm\"\n class=\"b-time-picker__ok-btn\"\n type=\"button\"\n @click=\"handleOk\"\n >\n OK\n </button>\n </div>\n </div>\n </div>\n</template>\n\n<style>\n.b-time-picker {\n --b-time-picker-input-font-size: 14px;\n --b-time-picker-input-font-size-lg: 16px;\n --b-time-picker-input-font-size-sm: 14px;\n --b-time-picker-padding-block: 4px;\n --b-time-picker-padding-block-lg: 7px;\n --b-time-picker-padding-block-sm: 0px;\n --b-time-picker-padding-inline: 11px;\n --b-time-picker-padding-inline-lg: 11px;\n --b-time-picker-padding-inline-sm: 7px;\n --b-time-picker-border-color: #d9d9d9;\n --b-time-picker-hover-border-color: #4096ff;\n --b-time-picker-active-border-color: #1677ff;\n --b-time-picker-active-shadow: 0 0 0 2px rgba(5, 145, 255, 0.1);\n --b-time-picker-error-active-shadow: 0 0 0 2px rgba(255, 38, 5, 0.06);\n --b-time-picker-warning-active-shadow: 0 0 0 2px rgba(255, 215, 5, 0.1);\n --b-time-picker-bg: #ffffff;\n --b-time-picker-hover-bg: #ffffff;\n --b-time-picker-active-bg: #ffffff;\n --b-time-picker-text-color: rgba(0, 0, 0, 0.88);\n --b-time-picker-placeholder-color: rgba(0, 0, 0, 0.25);\n --b-time-picker-icon-color: rgba(0, 0, 0, 0.25);\n --b-time-picker-clear-color: rgba(0, 0, 0, 0.25);\n --b-time-picker-clear-hover-color: rgba(0, 0, 0, 0.45);\n --b-time-picker-disabled-bg: rgba(0, 0, 0, 0.04);\n --b-time-picker-disabled-color: rgba(0, 0, 0, 0.25);\n --b-time-picker-panel-bg: #ffffff;\n --b-time-picker-panel-shadow: 0 6px 16px 0 rgba(0, 0, 0, 0.08), 0 3px 6px -4px rgba(0, 0, 0, 0.12), 0 9px 28px 8px rgba(0, 0, 0, 0.05);\n --b-time-picker-cell-height: 28px;\n --b-time-picker-cell-width: 56px;\n --b-time-picker-cell-hover-bg: rgba(0, 0, 0, 0.04);\n --b-time-picker-cell-selected-bg: #e6f4ff;\n --b-time-picker-cell-disabled-bg: rgba(0, 0, 0, 0.04);\n --b-time-picker-cell-disabled-color: rgba(0, 0, 0, 0.25);\n --b-time-picker-column-height: 224px;\n --b-time-picker-column-width: 56px;\n --b-time-picker-footer-bg: #ffffff;\n --b-time-picker-border-radius: 6px;\n --b-time-picker-panel-border-radius: 8px;\n --b-time-picker-transition-duration: 0.2s;\n --b-time-picker-z-index-popup: 1050;\n\n position: relative;\n display: inline-flex;\n width: 100%;\n max-width: 200px;\n}\n\n/* ──── Input Wrap ──── */\n.b-time-picker__input-wrap {\n display: flex;\n align-items: center;\n width: 100%;\n background: var(--b-time-picker-bg);\n border: 1px solid var(--b-time-picker-border-color);\n border-radius: var(--b-time-picker-border-radius);\n padding: var(--b-time-picker-padding-block) var(--b-time-picker-padding-inline);\n cursor: pointer;\n transition:\n border-color var(--b-time-picker-transition-duration),\n box-shadow var(--b-time-picker-transition-duration),\n background var(--b-time-picker-transition-duration);\n}\n\n.b-time-picker__input-wrap:hover {\n border-color: var(--b-time-picker-hover-border-color);\n background: var(--b-time-picker-hover-bg);\n}\n\n.b-time-picker--open .b-time-picker__input-wrap {\n border-color: var(--b-time-picker-active-border-color);\n box-shadow: var(--b-time-picker-active-shadow);\n background: var(--b-time-picker-active-bg);\n}\n\n/* ──── Size Variants ──── */\n.b-time-picker--sm .b-time-picker__input-wrap {\n padding: var(--b-time-picker-padding-block-sm) var(--b-time-picker-padding-inline-sm);\n}\n\n.b-time-picker--sm .b-time-picker__input {\n font-size: var(--b-time-picker-input-font-size-sm);\n}\n\n.b-time-picker--lg .b-time-picker__input-wrap {\n padding: var(--b-time-picker-padding-block-lg) var(--b-time-picker-padding-inline-lg);\n}\n\n.b-time-picker--lg .b-time-picker__input {\n font-size: var(--b-time-picker-input-font-size-lg);\n}\n\n/* ──── Variant Styles ──── */\n.b-time-picker--filled .b-time-picker__input-wrap {\n background: rgba(0, 0, 0, 0.04);\n border-color: transparent;\n}\n\n.b-time-picker--filled .b-time-picker__input-wrap:hover {\n background: rgba(0, 0, 0, 0.06);\n}\n\n.b-time-picker--borderless .b-time-picker__input-wrap {\n border-color: transparent;\n background: transparent;\n box-shadow: none;\n}\n\n.b-time-picker--underlined .b-time-picker__input-wrap {\n border-radius: 0;\n border: none;\n border-bottom: 1px solid var(--b-time-picker-border-color);\n}\n\n.b-time-picker--underlined .b-time-picker__input-wrap:hover {\n border-bottom-color: var(--b-time-picker-hover-border-color);\n}\n\n.b-time-picker--underlined.b-time-picker--open .b-time-picker__input-wrap {\n border-bottom-color: var(--b-time-picker-active-border-color);\n box-shadow: none;\n}\n\n/* ──── Status ──── */\n.b-time-picker--error .b-time-picker__input-wrap {\n border-color: #ff4d4f;\n}\n\n.b-time-picker--error.b-time-picker--open .b-time-picker__input-wrap {\n box-shadow: var(--b-time-picker-error-active-shadow);\n}\n\n.b-time-picker--warning .b-time-picker__input-wrap {\n border-color: #faad14;\n}\n\n.b-time-picker--warning.b-time-picker--open .b-time-picker__input-wrap {\n box-shadow: var(--b-time-picker-warning-active-shadow);\n}\n\n/* ──── Disabled ──── */\n.b-time-picker--disabled .b-time-picker__input-wrap {\n background: var(--b-time-picker-disabled-bg);\n border-color: var(--b-time-picker-border-color);\n cursor: not-allowed;\n pointer-events: none;\n}\n\n.b-time-picker--disabled .b-time-picker__input {\n color: var(--b-time-picker-disabled-color);\n cursor: not-allowed;\n}\n\n/* ──── Input ──── */\n.b-time-picker__input {\n flex: 1;\n border: none;\n outline: none;\n background: transparent;\n font-size: var(--b-time-picker-input-font-size);\n color: var(--b-time-picker-text-color);\n line-height: 1.5;\n padding: 0;\n min-width: 0;\n}\n\n.b-time-picker__input::placeholder {\n color: var(--b-time-picker-placeholder-color);\n}\n\n/* ──── Suffix / Icons ──── */\n.b-time-picker__suffix {\n display: flex;\n align-items: center;\n margin-left: 4px;\n flex-shrink: 0;\n}\n\n.b-time-picker__icon {\n width: 14px;\n height: 14px;\n color: var(--b-time-picker-icon-color);\n}\n\n.b-time-picker__clear {\n display: flex;\n align-items: center;\n justify-content: center;\n border: none;\n background: none;\n padding: 0;\n cursor: pointer;\n color: var(--b-time-picker-clear-color);\n transition: color var(--b-time-picker-transition-duration);\n}\n\n.b-time-picker__clear:hover {\n color: var(--b-time-picker-clear-hover-color);\n}\n\n.b-time-picker__clear svg {\n width: 14px;\n height: 14px;\n}\n\n.b-time-picker__status-text {\n position: absolute;\n width: 1px;\n height: 1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n}\n\n/* ──── Panel ──── */\n.b-time-picker__panel {\n position: absolute;\n position-anchor: var(--b-time-picker-anchor);\n inset: unset;\n top: anchor(bottom);\n left: anchor(left);\n margin: 0;\n margin-top: 4px;\n padding: 0;\n border: none;\n border-radius: var(--b-time-picker-panel-border-radius);\n background: var(--b-time-picker-panel-bg);\n box-shadow: var(--b-time-picker-panel-shadow);\n z-index: var(--b-time-picker-z-index-popup);\n overflow: hidden;\n opacity: 0;\n transform: translateY(-4px);\n transition:\n opacity var(--b-time-picker-transition-duration) ease,\n transform var(--b-time-picker-transition-duration) ease;\n}\n\n.b-time-picker__panel:popover-open {\n opacity: 1;\n transform: translateY(0);\n}\n\n@starting-style {\n .b-time-picker__panel:popover-open {\n opacity: 0;\n transform: translateY(-4px);\n }\n}\n\n/* ──── Columns ──── */\n.b-time-picker__columns {\n display: flex;\n border-bottom: 1px solid #f0f0f0;\n}\n\n.b-time-picker__column {\n width: var(--b-time-picker-column-width);\n height: var(--b-time-picker-column-height);\n overflow-y: auto;\n overflow-x: hidden;\n border-right: 1px solid #f0f0f0;\n scroll-behavior: smooth;\n scrollbar-width: thin;\n}\n\n.b-time-picker__column:last-child {\n border-right: none;\n}\n\n/* ──── Cells ──── */\n.b-time-picker__cell {\n height: var(--b-time-picker-cell-height);\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n font-size: 14px;\n color: var(--b-time-picker-text-color);\n transition: background var(--b-time-picker-transition-duration);\n user-select: none;\n}\n\n.b-time-picker__cell:hover {\n background: var(--b-time-picker-cell-hover-bg);\n}\n\n.b-time-picker__cell--selected {\n background: var(--b-time-picker-cell-selected-bg);\n font-weight: 600;\n}\n\n.b-time-picker__cell--focused {\n outline: 2px solid var(--b-time-picker-active-border-color);\n outline-offset: -2px;\n}\n\n.b-time-picker__cell--disabled {\n color: var(--b-time-picker-cell-disabled-color);\n background: var(--b-time-picker-cell-disabled-bg);\n cursor: not-allowed;\n}\n\n.b-time-picker__cell--disabled:hover {\n background: var(--b-time-picker-cell-disabled-bg);\n}\n\n/* ──── Footer ──── */\n.b-time-picker__footer {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 4px 8px;\n background: var(--b-time-picker-footer-bg);\n}\n\n.b-time-picker__now-btn {\n border: none;\n background: none;\n color: var(--b-time-picker-active-border-color);\n cursor: pointer;\n font-size: 14px;\n padding: 4px 8px;\n border-radius: 4px;\n transition: background var(--b-time-picker-transition-duration);\n}\n\n.b-time-picker__now-btn:hover {\n background: rgba(0, 0, 0, 0.04);\n}\n\n.b-time-picker__ok-btn {\n border: none;\n background: var(--b-time-picker-active-border-color);\n color: #fff;\n cursor: pointer;\n font-size: 14px;\n padding: 2px 12px;\n border-radius: 4px;\n font-weight: 500;\n line-height: 1.5;\n transition:\n background var(--b-time-picker-transition-duration),\n opacity var(--b-time-picker-transition-duration);\n}\n\n.b-time-picker__ok-btn:hover {\n opacity: 0.85;\n}\n\n/* ──── Placement ──── */\n.b-time-picker--bottom-right .b-time-picker__panel {\n left: unset;\n right: anchor(right);\n}\n\n.b-time-picker--top-left .b-time-picker__panel {\n top: unset;\n bottom: anchor(top);\n margin-top: 0;\n margin-bottom: 4px;\n}\n\n.b-time-picker--top-right .b-time-picker__panel {\n top: unset;\n bottom: anchor(top);\n left: unset;\n right: anchor(right);\n margin-top: 0;\n margin-bottom: 4px;\n}\n\n/* ──── Dark Mode ──── */\n[data-prefers-color='dark'] .b-time-picker {\n --b-time-picker-bg: #141414;\n --b-time-picker-hover-bg: #141414;\n --b-time-picker-active-bg: #141414;\n --b-time-picker-border-color: #424242;\n --b-time-picker-hover-border-color: #165dff;\n --b-time-picker-active-border-color: #1668dc;\n --b-time-picker-active-shadow: 0 0 0 2px rgba(22, 104, 220, 0.15);\n --b-time-picker-text-color: rgba(255, 255, 255, 0.85);\n --b-time-picker-placeholder-color: rgba(255, 255, 255, 0.25);\n --b-time-picker-icon-color: rgba(255, 255, 255, 0.3);\n --b-time-picker-clear-color: rgba(255, 255, 255, 0.3);\n --b-time-picker-clear-hover-color: rgba(255, 255, 255, 0.55);\n --b-time-picker-disabled-bg: rgba(255, 255, 255, 0.08);\n --b-time-picker-disabled-color: rgba(255, 255, 255, 0.25);\n --b-time-picker-panel-bg: #1f1f1f;\n --b-time-picker-panel-shadow: 0 6px 16px 0 rgba(0, 0, 0, 0.32), 0 3px 6px -4px rgba(0, 0, 0, 0.48), 0 9px 28px 8px rgba(0, 0, 0, 0.2);\n --b-time-picker-cell-hover-bg: rgba(255, 255, 255, 0.08);\n --b-time-picker-cell-selected-bg: #111a2c;\n --b-time-picker-cell-disabled-bg: rgba(255, 255, 255, 0.04);\n --b-time-picker-cell-disabled-color: rgba(255, 255, 255, 0.25);\n --b-time-picker-footer-bg: #1f1f1f;\n --b-time-picker-error-active-shadow: 0 0 0 2px rgba(220, 56, 72, 0.15);\n --b-time-picker-warning-active-shadow: 0 0 0 2px rgba(217, 146, 0, 0.15);\n}\n\n@media (prefers-color-scheme: dark) {\n [data-prefers-color='system'] .b-time-picker {\n --b-time-picker-bg: #141414;\n --b-time-picker-hover-bg: #141414;\n --b-time-picker-active-bg: #141414;\n --b-time-picker-border-color: #424242;\n --b-time-picker-hover-border-color: #165dff;\n --b-time-picker-active-border-color: #1668dc;\n --b-time-picker-active-shadow: 0 0 0 2px rgba(22, 104, 220, 0.15);\n --b-time-picker-text-color: rgba(255, 255, 255, 0.85);\n --b-time-picker-placeholder-color: rgba(255, 255, 255, 0.25);\n --b-time-picker-icon-color: rgba(255, 255, 255, 0.3);\n --b-time-picker-clear-color: rgba(255, 255, 255, 0.3);\n --b-time-picker-clear-hover-color: rgba(255, 255, 255, 0.55);\n --b-time-picker-disabled-bg: rgba(255, 255, 255, 0.08);\n --b-time-picker-disabled-color: rgba(255, 255, 255, 0.25);\n --b-time-picker-panel-bg: #1f1f1f;\n --b-time-picker-panel-shadow: 0 6px 16px 0 rgba(0, 0, 0, 0.32), 0 3px 6px -4px rgba(0, 0, 0, 0.48), 0 9px 28px 8px rgba(0, 0, 0, 0.2);\n --b-time-picker-cell-hover-bg: rgba(255, 255, 255, 0.08);\n --b-time-picker-cell-selected-bg: #111a2c;\n --b-time-picker-cell-disabled-bg: rgba(255, 255, 255, 0.04);\n --b-time-picker-cell-disabled-color: rgba(255, 255, 255, 0.25);\n --b-time-picker-footer-bg: #1f1f1f;\n --b-time-picker-error-active-shadow: 0 0 0 2px rgba(220, 56, 72, 0.15);\n --b-time-picker-warning-active-shadow: 0 0 0 2px rgba(217, 146, 0, 0.15);\n }\n}\n\n/* ──── Reduced Motion ──── */\n@media (prefers-reduced-motion: reduce) {\n .b-time-picker,\n .b-time-picker * {\n --b-time-picker-transition-duration: 0ms;\n transition-duration: 0ms !important;\n animation-duration: 0ms !important;\n }\n\n .b-time-picker__column {\n scroll-behavior: auto;\n }\n}\n</style>\n"],"mappings":""}
1
+ {"version":3,"file":"design-system230.js","names":[],"sources":["../src/components/BStatistic/BStatistic.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, useSlots } from 'vue';\n\nimport type { BStatisticFormatter, BStatisticValue } from './types';\n\n// ─────────────────────────────────────────────\n// Props\n// ─────────────────────────────────────────────\nconst {\n title,\n value,\n prefix,\n suffix,\n precision,\n decimalSeparator = '.',\n groupSeparator = ',',\n loading = false,\n valueStyle,\n formatter,\n} = defineProps<{\n /** Display title shown above the value. Use `#title` slot for richer content. */\n title?: string;\n /** Display value. Numbers are formatted; strings render as-is. */\n value: BStatisticValue;\n /** Prefix text before the value. Use `#prefix` slot for richer content. */\n prefix?: string;\n /** Suffix text after the value. Use `#suffix` slot for richer content. */\n suffix?: string;\n /** Number of digits after the decimal point. Applied only to numeric values. */\n precision?: number;\n /** Character used as the decimal separator. @default '.' */\n decimalSeparator?: string;\n /** Character used as the thousands group separator. @default ',' */\n groupSeparator?: string;\n /** Show a skeleton placeholder instead of the value. @default false */\n loading?: boolean;\n /** Inline style applied to the value element. */\n valueStyle?: string | Record<string, string | number>;\n /** Function that returns a custom display string. Overridden by `#formatter` slot. */\n formatter?: BStatisticFormatter;\n}>();\n\n// ─────────────────────────────────────────────\n// Slots\n// ─────────────────────────────────────────────\ndefineSlots<{\n /** Custom title content; overrides `title` prop. */\n title?(): unknown;\n /** Prefix content; overrides `prefix` prop. */\n prefix?(): unknown;\n /** Suffix content; overrides `suffix` prop. */\n suffix?(): unknown;\n /** Custom value renderer; receives `{ value }`. Overrides `formatter` prop. */\n formatter?(payload: { value: BStatisticValue }): unknown;\n}>();\n\nconst slots = useSlots();\n\n// ─────────────────────────────────────────────\n// Number formatting\n// ─────────────────────────────────────────────\nconst formattedValue = computed<string>(() => {\n if (formatter) return String(formatter(value));\n if (typeof value !== 'number') return String(value ?? '');\n if (Number.isNaN(value)) return 'NaN';\n if (!Number.isFinite(value)) return String(value);\n\n const negative = value < 0;\n const abs = Math.abs(value);\n\n let str: string;\n if (precision != null && precision >= 0) {\n str = abs.toFixed(precision);\n } else {\n str = String(abs);\n }\n\n const [intPart, decPart] = str.split('.');\n const intWithGroups = intPart.replace(/\\B(?=(\\d{3})+(?!\\d))/g, groupSeparator);\n const result = decPart != null ? `${intWithGroups}${decimalSeparator}${decPart}` : intWithGroups;\n return negative ? `-${result}` : result;\n});\n\nconst hasTitle = computed(() => !!slots.title || (title != null && title !== ''));\nconst hasPrefix = computed(() => !!slots.prefix || (prefix != null && prefix !== ''));\nconst hasSuffix = computed(() => !!slots.suffix || (suffix != null && suffix !== ''));\n</script>\n\n<template>\n <div class=\"b-statistic\" :class=\"{ 'b-statistic--loading': loading }\">\n <div v-if=\"hasTitle\" class=\"b-statistic__title\">\n <slot name=\"title\">{{ title }}</slot>\n </div>\n <div class=\"b-statistic__content\" :style=\"valueStyle\" aria-live=\"polite\">\n <span\n v-if=\"loading\"\n class=\"b-statistic__skeleton\"\n role=\"status\"\n aria-busy=\"true\"\n aria-label=\"Loading\"\n />\n <template v-else>\n <span v-if=\"hasPrefix\" class=\"b-statistic__prefix\" aria-hidden=\"true\">\n <slot name=\"prefix\">{{ prefix }}</slot>\n </span>\n <span class=\"b-statistic__value\">\n <slot name=\"formatter\" :value=\"value\">{{ formattedValue }}</slot>\n </span>\n <span v-if=\"hasSuffix\" class=\"b-statistic__suffix\" aria-hidden=\"true\">\n <slot name=\"suffix\">{{ suffix }}</slot>\n </span>\n </template>\n </div>\n </div>\n</template>\n\n<style>\n/* ─────────────────────────────────────────────\n BStatistic - CSS custom properties (scoped to root)\n ───────────────────────────────────────────── */\n.b-statistic {\n /* ── Title ── */\n --b-statistic-title-color: oklch(45% 0.02 260);\n --b-statistic-title-font-size: 14px;\n --b-statistic-title-line-height: 1.5715;\n --b-statistic-title-margin-bottom: 4px;\n\n /* ── Content (value) ── */\n --b-statistic-content-color: oklch(20% 0.02 260);\n --b-statistic-content-font-size: 24px;\n --b-statistic-content-line-height: 1.5;\n --b-statistic-content-font-family: inherit;\n --b-statistic-content-font-weight: 400;\n\n /* ── Prefix / Suffix ── */\n --b-statistic-prefix-color: inherit;\n --b-statistic-prefix-font-size: inherit;\n --b-statistic-prefix-margin-end: 4px;\n --b-statistic-suffix-color: inherit;\n --b-statistic-suffix-font-size: inherit;\n --b-statistic-suffix-margin-start: 4px;\n\n /* ── Skeleton ── */\n --b-statistic-skeleton-color: oklch(92% 0.005 260);\n --b-statistic-skeleton-highlight: oklch(96% 0.003 260);\n --b-statistic-skeleton-width: 96px;\n --b-statistic-skeleton-height: 1em;\n --b-statistic-skeleton-radius: 4px;\n --b-statistic-skeleton-duration: 1.4s;\n\n font-family: var(--b-statistic-content-font-family);\n color: var(--b-statistic-content-color);\n}\n\n/* ─────────────────────────────────────────────\n Title\n ───────────────────────────────────────────── */\n.b-statistic__title {\n margin-bottom: var(--b-statistic-title-margin-bottom);\n color: var(--b-statistic-title-color);\n font-size: var(--b-statistic-title-font-size);\n line-height: var(--b-statistic-title-line-height);\n}\n\n/* ─────────────────────────────────────────────\n Content / value\n ───────────────────────────────────────────── */\n.b-statistic__content {\n display: inline-flex;\n align-items: baseline;\n color: var(--b-statistic-content-color);\n font-size: var(--b-statistic-content-font-size);\n font-weight: var(--b-statistic-content-font-weight);\n line-height: var(--b-statistic-content-line-height);\n font-feature-settings: 'tnum';\n font-variant-numeric: tabular-nums;\n word-break: break-word;\n max-width: 100%;\n}\n\n.b-statistic__value {\n display: inline-block;\n}\n\n.b-statistic__prefix {\n display: inline-flex;\n align-items: center;\n margin-inline-end: var(--b-statistic-prefix-margin-end);\n color: var(--b-statistic-prefix-color);\n font-size: var(--b-statistic-prefix-font-size);\n}\n\n.b-statistic__suffix {\n display: inline-flex;\n align-items: center;\n margin-inline-start: var(--b-statistic-suffix-margin-start);\n color: var(--b-statistic-suffix-color);\n font-size: var(--b-statistic-suffix-font-size);\n}\n\n/* ─────────────────────────────────────────────\n Loading skeleton\n ───────────────────────────────────────────── */\n.b-statistic__skeleton {\n display: inline-block;\n width: var(--b-statistic-skeleton-width);\n height: var(--b-statistic-skeleton-height);\n border-radius: var(--b-statistic-skeleton-radius);\n background: linear-gradient(\n 90deg,\n var(--b-statistic-skeleton-color) 25%,\n var(--b-statistic-skeleton-highlight) 37%,\n var(--b-statistic-skeleton-color) 63%\n );\n background-size: 400% 100%;\n animation: b-statistic-shimmer var(--b-statistic-skeleton-duration) ease infinite;\n}\n\n@keyframes b-statistic-shimmer {\n 0% {\n background-position: 100% 50%;\n }\n 100% {\n background-position: 0 50%;\n }\n}\n\n/* ─────────────────────────────────────────────\n Dark mode\n ───────────────────────────────────────────── */\n[data-prefers-color='dark'] .b-statistic {\n --b-statistic-title-color: oklch(70% 0.01 260);\n --b-statistic-content-color: oklch(92% 0.01 260);\n --b-statistic-skeleton-color: oklch(28% 0.01 260);\n --b-statistic-skeleton-highlight: oklch(35% 0.01 260);\n}\n\n@media (prefers-color-scheme: dark) {\n [data-prefers-color='system'] .b-statistic {\n --b-statistic-title-color: oklch(70% 0.01 260);\n --b-statistic-content-color: oklch(92% 0.01 260);\n --b-statistic-skeleton-color: oklch(28% 0.01 260);\n --b-statistic-skeleton-highlight: oklch(35% 0.01 260);\n }\n}\n\n/* ─────────────────────────────────────────────\n Reduced motion\n ───────────────────────────────────────────── */\n@media (prefers-reduced-motion: reduce) {\n .b-statistic {\n --b-statistic-skeleton-duration: 0ms;\n }\n .b-statistic__skeleton {\n animation: none;\n opacity: 0.6;\n }\n}\n</style>\n"],"mappings":""}
@@ -1,6 +1,91 @@
1
- //#region src/components/BTabs/types.ts
2
- var e = Symbol("BTabsContext");
1
+ import e from "./design-system230.js";
2
+ import { computed as t, createBlock as n, createSlots as r, defineComponent as i, onBeforeUnmount as a, onMounted as o, openBlock as s, ref as c, renderSlot as l, withCtx as u } from "vue";
3
+ //#region src/components/BStatistic/BStatisticTimer.vue?vue&type=script&setup=true&lang.ts
4
+ var d = 1e3 / 30, f = /* @__PURE__ */ i({
5
+ __name: "BStatisticTimer",
6
+ props: {
7
+ type: { default: "countdown" },
8
+ value: {},
9
+ format: { default: "HH:mm:ss" },
10
+ title: {},
11
+ prefix: {},
12
+ suffix: {},
13
+ valueStyle: {}
14
+ },
15
+ emits: ["finish", "change"],
16
+ setup(i, { emit: f }) {
17
+ let p = f, m = c(0), h = null, g = !1;
18
+ function _(e) {
19
+ return i.type === "countdown" ? Math.max(0, i.value - e) : Math.max(0, e - i.value);
20
+ }
21
+ function v() {
22
+ let e = Date.now();
23
+ m.value = e;
24
+ let t = _(e);
25
+ p("change", t), i.type === "countdown" && t <= 0 && !g && (g = !0, h &&= (clearInterval(h), null), p("finish"));
26
+ }
27
+ o(() => {
28
+ g = !1, m.value = Date.now(), p("change", _(m.value)), h = setInterval(v, d);
29
+ }), a(() => {
30
+ h &&= (clearInterval(h), null);
31
+ });
32
+ let y = t(() => m.value ? _(m.value) : _(Date.now()));
33
+ function b(e, t) {
34
+ let n = Math.floor(e / 864e5), r = e - n * 864e5, i = Math.floor(r / 36e5);
35
+ r -= i * 36e5;
36
+ let a = Math.floor(r / 6e4);
37
+ r -= a * 6e4;
38
+ let o = Math.floor(r / 1e3), s = r - o * 1e3;
39
+ return t.replace(/\[([^\]]*)\]|SSS|HH|mm|ss|D|H|m|s|S/g, (e, t) => {
40
+ if (t !== void 0) return t;
41
+ switch (e) {
42
+ case "SSS": return String(s).padStart(3, "0");
43
+ case "HH": return String(i).padStart(2, "0");
44
+ case "mm": return String(a).padStart(2, "0");
45
+ case "ss": return String(o).padStart(2, "0");
46
+ case "D": return String(n);
47
+ case "H": return String(i);
48
+ case "m": return String(a);
49
+ case "s": return String(o);
50
+ case "S": return String(s);
51
+ default: return e;
52
+ }
53
+ });
54
+ }
55
+ let x = t(() => b(y.value, i.format));
56
+ return (t, a) => (s(), n(e, {
57
+ class: "b-statistic-timer",
58
+ title: i.title,
59
+ value: x.value,
60
+ prefix: i.prefix,
61
+ suffix: i.suffix,
62
+ "value-style": i.valueStyle
63
+ }, r({ _: 2 }, [
64
+ t.$slots.title ? {
65
+ name: "title",
66
+ fn: u(() => [l(t.$slots, "title")]),
67
+ key: "0"
68
+ } : void 0,
69
+ t.$slots.prefix ? {
70
+ name: "prefix",
71
+ fn: u(() => [l(t.$slots, "prefix")]),
72
+ key: "1"
73
+ } : void 0,
74
+ t.$slots.suffix ? {
75
+ name: "suffix",
76
+ fn: u(() => [l(t.$slots, "suffix")]),
77
+ key: "2"
78
+ } : void 0
79
+ ]), 1032, [
80
+ "title",
81
+ "value",
82
+ "prefix",
83
+ "suffix",
84
+ "value-style"
85
+ ]));
86
+ }
87
+ });
3
88
  //#endregion
4
- export { e as BTabsContextKey };
89
+ export { f as default };
5
90
 
6
91
  //# sourceMappingURL=design-system231.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"design-system231.js","names":[],"sources":["../src/components/BTabs/types.ts"],"sourcesContent":["import type { ComputedRef, InjectionKey, VNode } from 'vue';\n\nexport type BTabsType = 'line' | 'card' | 'editable-card';\nexport type BTabsPlacement = 'top' | 'bottom' | 'left' | 'right';\nexport type BTabsSize = 'small' | 'middle' | 'large';\n\nexport interface BTabItem {\n /** Unique identifier for the tab. */\n key: string;\n /** Tab header text or VNode. */\n label?: string | VNode;\n /** Whether the tab is disabled. @default false */\n disabled?: boolean;\n /** Whether the close button is shown (editable-card only). @default true */\n closable?: boolean;\n /** Whether to destroy content when tab is hidden. @default false */\n destroyOnHidden?: boolean;\n /** Whether to force render content even when not active. @default false */\n forceRender?: boolean;\n /** Whether to keep this tab's component state alive when switching away. Overrides global keepAlive. */\n keepAlive?: boolean;\n}\n\n// ─────────────────────────────────────────────\n// BTabPane registration (provide/inject)\n// ─────────────────────────────────────────────\n\nexport interface BTabPaneRegistration {\n /** Unique key for this pane. */\n key: string;\n /** Tab label (text or VNode). */\n label?: string | VNode;\n /** Whether tab is disabled. */\n disabled?: boolean;\n /** Whether close button shows in editable-card mode. */\n closable?: boolean;\n /** Whether to destroy when hidden. */\n destroyOnHidden?: boolean;\n /** Whether to force render even when inactive. */\n forceRender?: boolean;\n /** Per-pane keepAlive override. */\n keepAlive?: boolean;\n /** Render function for the pane content (from BTabPane's default slot). */\n renderContent: () => VNode[];\n /** Optional render function for custom label (from BTabPane's tab slot). */\n renderLabel?: () => VNode[];\n}\n\n// ─────────────────────────────────────────────\n// Context injected from BTabs to BTabPane children\n// ─────────────────────────────────────────────\n\nexport interface BTabsContext {\n /** Currently active tab key. */\n activeKey: ComputedRef<string>;\n /** Tab type. */\n type: ComputedRef<BTabsType>;\n /** Tab size. */\n size: ComputedRef<BTabsSize>;\n /** Tab placement. */\n placement: ComputedRef<BTabsPlacement>;\n /** Global keepAlive setting. */\n keepAlive: ComputedRef<boolean>;\n /** Global destroyOnHidden setting. */\n destroyOnHidden: ComputedRef<boolean>;\n /** Register a pane. */\n register: (pane: BTabPaneRegistration) => void;\n /** Unregister a pane by key. */\n unregister: (key: string) => void;\n /** Update a registered pane's data (when props change reactively). */\n update: (key: string, pane: BTabPaneRegistration) => void;\n}\n\nexport const BTabsContextKey: InjectionKey<BTabsContext> = Symbol('BTabsContext');\n"],"mappings":";AAyEA,IAAa,IAA8C,OAAO,eAAe"}
1
+ {"version":3,"file":"design-system231.js","names":["$slots"],"sources":["../src/components/BStatistic/BStatisticTimer.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, onBeforeUnmount, onMounted, ref } from 'vue';\n\nimport BStatistic from './BStatistic.vue';\nimport type { BStatisticTimerType } from './types';\n\n// ─────────────────────────────────────────────\n// Props\n// ─────────────────────────────────────────────\nconst {\n type = 'countdown',\n value,\n format = 'HH:mm:ss',\n title,\n prefix,\n suffix,\n valueStyle,\n} = defineProps<{\n /**\n * Timer mode.\n * - `'countdown'` - counts down to `value` (a future timestamp in ms).\n * - `'countup'` - counts up from `value` (a past timestamp in ms).\n * @default 'countdown'\n */\n type?: BStatisticTimerType;\n /** Target/start timestamp in ms (e.g. `Date.now() + 60_000`). */\n value: number;\n /**\n * Format string. Tokens:\n * - `D` days\n * - `H` / `HH` hours\n * - `m` / `mm` minutes\n * - `s` / `ss` seconds\n * - `S` / `SSS` milliseconds\n * @default 'HH:mm:ss'\n */\n format?: string;\n /** Title text (mirrors `BStatistic#title`). */\n title?: string;\n /** Prefix text (mirrors `BStatistic#prefix`). */\n prefix?: string;\n /** Suffix text (mirrors `BStatistic#suffix`). */\n suffix?: string;\n /** Inline style on the value element. */\n valueStyle?: string | Record<string, string | number>;\n}>();\n\n// ─────────────────────────────────────────────\n// Emits\n// ─────────────────────────────────────────────\nconst emit = defineEmits<{\n /** Emitted once a countdown reaches zero. */\n finish: [];\n /** Emitted on every tick with the current ms remaining/elapsed. */\n change: [ms: number];\n}>();\n\ndefineSlots<{\n title?(): unknown;\n prefix?(): unknown;\n suffix?(): unknown;\n}>();\n\n// ─────────────────────────────────────────────\n// Tick\n// ─────────────────────────────────────────────\nconst TICK_MS = 1000 / 30; // ~33ms, smooth enough for sub-second formats\nconst now = ref<number>(0);\nlet timer: ReturnType<typeof setInterval> | null = null;\nlet finished = false;\n\nfunction compute(t: number): number {\n return type === 'countdown' ? Math.max(0, value - t) : Math.max(0, t - value);\n}\n\nfunction tick() {\n const t = Date.now();\n now.value = t;\n const ms = compute(t);\n emit('change', ms);\n if (type === 'countdown' && ms <= 0 && !finished) {\n finished = true;\n if (timer) {\n clearInterval(timer);\n timer = null;\n }\n emit('finish');\n }\n}\n\nonMounted(() => {\n // SSR-safe: timers only run in the browser\n finished = false;\n now.value = Date.now();\n // Emit initial change so consumers see the starting value\n emit('change', compute(now.value));\n timer = setInterval(tick, TICK_MS);\n});\n\nonBeforeUnmount(() => {\n if (timer) {\n clearInterval(timer);\n timer = null;\n }\n});\n\n// ─────────────────────────────────────────────\n// Formatting\n// ─────────────────────────────────────────────\nconst ms = computed<number>(() => (now.value ? compute(now.value) : compute(Date.now())));\n\nfunction formatDuration(t: number, fmt: string): string {\n const days = Math.floor(t / 86_400_000);\n let rem = t - days * 86_400_000;\n const hours = Math.floor(rem / 3_600_000);\n rem -= hours * 3_600_000;\n const minutes = Math.floor(rem / 60_000);\n rem -= minutes * 60_000;\n const seconds = Math.floor(rem / 1000);\n const milliseconds = rem - seconds * 1000;\n\n // Bracketed text is treated as a literal (dayjs-compatible).\n return fmt.replace(/\\[([^\\]]*)\\]|SSS|HH|mm|ss|D|H|m|s|S/g, (match, literal) => {\n if (literal !== undefined) return literal;\n switch (match) {\n case 'SSS':\n return String(milliseconds).padStart(3, '0');\n case 'HH':\n return String(hours).padStart(2, '0');\n case 'mm':\n return String(minutes).padStart(2, '0');\n case 'ss':\n return String(seconds).padStart(2, '0');\n case 'D':\n return String(days);\n case 'H':\n return String(hours);\n case 'm':\n return String(minutes);\n case 's':\n return String(seconds);\n case 'S':\n return String(milliseconds);\n default:\n return match;\n }\n });\n}\n\nconst formatted = computed<string>(() => formatDuration(ms.value, format));\n</script>\n\n<template>\n <BStatistic\n class=\"b-statistic-timer\"\n :title=\"title\"\n :value=\"formatted\"\n :prefix=\"prefix\"\n :suffix=\"suffix\"\n :value-style=\"valueStyle\"\n >\n <template v-if=\"$slots.title\" #title><slot name=\"title\" /></template>\n <template v-if=\"$slots.prefix\" #prefix><slot name=\"prefix\" /></template>\n <template v-if=\"$slots.suffix\" #suffix><slot name=\"suffix\" /></template>\n </BStatistic>\n</template>\n"],"mappings":";;;AAkEA,IAAM,IAAU,MAAO;;;;;;;;;;;;;EAhBvB,IAAM,IAAO,GAiBP,IAAM,EAAY,EAAE,EACtB,IAA+C,MAC/C,IAAW;EAEf,SAAS,EAAQ,GAAmB;AAClC,UAAO,EAAA,SAAS,cAAc,KAAK,IAAI,GAAG,EAAA,QAAQ,EAAE,GAAG,KAAK,IAAI,GAAG,IAAI,EAAA,MAAM;;EAG/E,SAAS,IAAO;GACd,IAAM,IAAI,KAAK,KAAK;AACpB,KAAI,QAAQ;GACZ,IAAM,IAAK,EAAQ,EAAE;AAErB,GADA,EAAK,UAAU,EAAG,EACd,EAAA,SAAS,eAAe,KAAM,KAAK,CAAC,MACtC,IAAW,IACX,AAEE,OADA,cAAc,EAAM,EACZ,OAEV,EAAK,SAAS;;AAalB,EATA,QAAgB;AAMd,GAJA,IAAW,IACX,EAAI,QAAQ,KAAK,KAAK,EAEtB,EAAK,UAAU,EAAQ,EAAI,MAAM,CAAC,EAClC,IAAQ,YAAY,GAAM,EAAQ;IAClC,EAEF,QAAsB;AACpB,GAEE,OADA,cAAc,EAAM,EACZ;IAEV;EAKF,IAAM,IAAK,QAAwB,EAAI,QAAQ,EAAQ,EAAI,MAAM,GAAG,EAAQ,KAAK,KAAK,CAAC,CAAE;EAEzF,SAAS,EAAe,GAAW,GAAqB;GACtD,IAAM,IAAO,KAAK,MAAM,IAAI,MAAW,EACnC,IAAM,IAAI,IAAO,OACf,IAAQ,KAAK,MAAM,IAAM,KAAU;AACzC,QAAO,IAAQ;GACf,IAAM,IAAU,KAAK,MAAM,IAAM,IAAO;AACxC,QAAO,IAAU;GACjB,IAAM,IAAU,KAAK,MAAM,IAAM,IAAK,EAChC,IAAe,IAAM,IAAU;AAGrC,UAAO,EAAI,QAAQ,yCAAyC,GAAO,MAAY;AAC7E,QAAI,MAAY,KAAA,EAAW,QAAO;AAClC,YAAQ,GAAR;KACE,KAAK,MACH,QAAO,OAAO,EAAa,CAAC,SAAS,GAAG,IAAI;KAC9C,KAAK,KACH,QAAO,OAAO,EAAM,CAAC,SAAS,GAAG,IAAI;KACvC,KAAK,KACH,QAAO,OAAO,EAAQ,CAAC,SAAS,GAAG,IAAI;KACzC,KAAK,KACH,QAAO,OAAO,EAAQ,CAAC,SAAS,GAAG,IAAI;KACzC,KAAK,IACH,QAAO,OAAO,EAAK;KACrB,KAAK,IACH,QAAO,OAAO,EAAM;KACtB,KAAK,IACH,QAAO,OAAO,EAAQ;KACxB,KAAK,IACH,QAAO,OAAO,EAAQ;KACxB,KAAK,IACH,QAAO,OAAO,EAAa;KAC7B,QACE,QAAO;;KAEX;;EAGJ,IAAM,IAAY,QAAuB,EAAe,EAAG,OAAO,EAAA,OAAO,CAAC;yBAIxE,EAWa,GAAA;GAVX,OAAM;GACL,OAAO,EAAA;GACP,OAAO,EAAA;GACP,QAAQ,EAAA;GACR,QAAQ,EAAA;GACR,eAAa,EAAA;;GAEEA,EAAAA,OAAO,QAAA;UAAQ;gBAA2B,CAArB,EAAqB,EAAA,QAAA,QAAA,CAAA,CAAA;;;GAC1CA,EAAAA,OAAO,SAAA;UAAS;gBAA6B,CAAtB,EAAsB,EAAA,QAAA,SAAA,CAAA,CAAA;;;GAC7CA,EAAAA,OAAO,SAAA;UAAS;gBAA6B,CAAtB,EAAsB,EAAA,QAAA,SAAA,CAAA,CAAA"}
@@ -1,49 +1,7 @@
1
- import { BTabsContextKey as e } from "./design-system231.js";
2
- import { createCommentVNode as t, defineComponent as n, inject as r, onBeforeUnmount as i, onMounted as a, useSlots as o, watch as s } from "vue";
3
- //#region src/components/BTabs/BTabPane.vue?vue&type=script&setup=true&lang.ts
4
- var c = /* @__PURE__ */ n({
5
- __name: "BTabPane",
6
- props: {
7
- tabKey: {},
8
- tab: {},
9
- disabled: { type: Boolean },
10
- closable: { type: Boolean },
11
- destroyOnHidden: { type: Boolean },
12
- forceRender: { type: Boolean },
13
- keepAlive: { type: Boolean }
14
- },
15
- setup(n) {
16
- let c = n, l = o(), u = r(e, null);
17
- function d() {
18
- return {
19
- key: c.tabKey,
20
- label: c.tab,
21
- disabled: c.disabled,
22
- closable: c.closable,
23
- destroyOnHidden: c.destroyOnHidden,
24
- forceRender: c.forceRender,
25
- keepAlive: c.keepAlive,
26
- renderContent: () => l.default?.() ?? [],
27
- renderLabel: l.tab ? () => l.tab() : void 0
28
- };
29
- }
30
- return a(() => {
31
- u?.register(d());
32
- }), i(() => {
33
- u?.unregister(c.tabKey);
34
- }), s(() => [
35
- c.tab,
36
- c.disabled,
37
- c.closable,
38
- c.destroyOnHidden,
39
- c.forceRender,
40
- c.keepAlive
41
- ], () => {
42
- u?.update(c.tabKey, d());
43
- }), (e, n) => t("", !0);
44
- }
45
- });
1
+ import e from "./design-system231.js";
2
+ //#region src/components/BStatistic/BStatisticTimer.vue
3
+ var t = e;
46
4
  //#endregion
47
- export { c as default };
5
+ export { t as default };
48
6
 
49
7
  //# sourceMappingURL=design-system232.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"design-system232.js","names":[],"sources":["../src/components/BTabs/BTabPane.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { VNode } from 'vue';\nimport { inject, onBeforeUnmount, onMounted, useSlots, watch } from 'vue';\n\nimport { BTabsContextKey } from './types';\n\n// ─────────────────────────────────────────────\n// Props\n// ─────────────────────────────────────────────\nconst props = defineProps<{\n /** Unique key identifying this tab pane. */\n tabKey: string;\n /** Tab header label text. Use the `tab` slot for rich labels. */\n tab?: string;\n /** Whether this tab is disabled. @default false */\n disabled?: boolean;\n /** Show close button in editable-card mode. @default true */\n closable?: boolean;\n /** Destroy content when tab is hidden. @default false */\n destroyOnHidden?: boolean;\n /** Force render content even when inactive. @default false */\n forceRender?: boolean;\n /** Keep component state alive when switching away. Overrides global setting. */\n keepAlive?: boolean;\n}>();\n\n// ─────────────────────────────────────────────\n// Slots\n// ─────────────────────────────────────────────\ndefineSlots<{\n /** Tab pane content. */\n default?: () => unknown;\n /** Custom tab label content. */\n tab?: () => unknown;\n}>();\n\nconst slots = useSlots();\n\n// ─────────────────────────────────────────────\n// Inject parent context\n// ─────────────────────────────────────────────\nconst tabsContext = inject(BTabsContextKey, null);\n\n// ─────────────────────────────────────────────\n// Registration helpers\n// ─────────────────────────────────────────────\nfunction buildRegistration() {\n return {\n key: props.tabKey,\n label: props.tab,\n disabled: props.disabled,\n closable: props.closable,\n destroyOnHidden: props.destroyOnHidden,\n forceRender: props.forceRender,\n keepAlive: props.keepAlive,\n renderContent: () => (slots.default?.() ?? []) as VNode[],\n renderLabel: slots.tab ? () => slots.tab!() as VNode[] : undefined,\n };\n}\n\nonMounted(() => {\n tabsContext?.register(buildRegistration());\n});\n\nonBeforeUnmount(() => {\n tabsContext?.unregister(props.tabKey);\n});\n\nwatch(\n () => [\n props.tab,\n props.disabled,\n props.closable,\n props.destroyOnHidden,\n props.forceRender,\n props.keepAlive,\n ],\n () => {\n tabsContext?.update(props.tabKey, buildRegistration());\n },\n);\n</script>\n\n<template>\n <!-- BTabPane is a registration-only component. All rendering is handled by BTabs. -->\n <slot v-if=\"false\" />\n</template>\n"],"mappings":";;;;;;;;;;;;;;;EASA,IAAM,IAAQ,GA2BR,IAAQ,GAAU,EAKlB,IAAc,EAAO,GAAiB,KAAK;EAKjD,SAAS,IAAoB;AAC3B,UAAO;IACL,KAAK,EAAM;IACX,OAAO,EAAM;IACb,UAAU,EAAM;IAChB,UAAU,EAAM;IAChB,iBAAiB,EAAM;IACvB,aAAa,EAAM;IACnB,WAAW,EAAM;IACjB,qBAAsB,EAAM,WAAW,IAAI,EAAE;IAC7C,aAAa,EAAM,YAAY,EAAM,KAAM,GAAc,KAAA;IAC1D;;SAGH,QAAgB;AACd,MAAa,SAAS,GAAmB,CAAC;IAC1C,EAEF,QAAsB;AACpB,MAAa,WAAW,EAAM,OAAO;IACrC,EAEF,QACQ;GACJ,EAAM;GACN,EAAM;GACN,EAAM;GACN,EAAM;GACN,EAAM;GACN,EAAM;GACP,QACK;AACJ,MAAa,OAAO,EAAM,QAAQ,GAAmB,CAAC;IAEzD"}
1
+ {"version":3,"file":"design-system232.js","names":[],"sources":["../src/components/BStatistic/BStatisticTimer.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, onBeforeUnmount, onMounted, ref } from 'vue';\n\nimport BStatistic from './BStatistic.vue';\nimport type { BStatisticTimerType } from './types';\n\n// ─────────────────────────────────────────────\n// Props\n// ─────────────────────────────────────────────\nconst {\n type = 'countdown',\n value,\n format = 'HH:mm:ss',\n title,\n prefix,\n suffix,\n valueStyle,\n} = defineProps<{\n /**\n * Timer mode.\n * - `'countdown'` - counts down to `value` (a future timestamp in ms).\n * - `'countup'` - counts up from `value` (a past timestamp in ms).\n * @default 'countdown'\n */\n type?: BStatisticTimerType;\n /** Target/start timestamp in ms (e.g. `Date.now() + 60_000`). */\n value: number;\n /**\n * Format string. Tokens:\n * - `D` days\n * - `H` / `HH` hours\n * - `m` / `mm` minutes\n * - `s` / `ss` seconds\n * - `S` / `SSS` milliseconds\n * @default 'HH:mm:ss'\n */\n format?: string;\n /** Title text (mirrors `BStatistic#title`). */\n title?: string;\n /** Prefix text (mirrors `BStatistic#prefix`). */\n prefix?: string;\n /** Suffix text (mirrors `BStatistic#suffix`). */\n suffix?: string;\n /** Inline style on the value element. */\n valueStyle?: string | Record<string, string | number>;\n}>();\n\n// ─────────────────────────────────────────────\n// Emits\n// ─────────────────────────────────────────────\nconst emit = defineEmits<{\n /** Emitted once a countdown reaches zero. */\n finish: [];\n /** Emitted on every tick with the current ms remaining/elapsed. */\n change: [ms: number];\n}>();\n\ndefineSlots<{\n title?(): unknown;\n prefix?(): unknown;\n suffix?(): unknown;\n}>();\n\n// ─────────────────────────────────────────────\n// Tick\n// ─────────────────────────────────────────────\nconst TICK_MS = 1000 / 30; // ~33ms, smooth enough for sub-second formats\nconst now = ref<number>(0);\nlet timer: ReturnType<typeof setInterval> | null = null;\nlet finished = false;\n\nfunction compute(t: number): number {\n return type === 'countdown' ? Math.max(0, value - t) : Math.max(0, t - value);\n}\n\nfunction tick() {\n const t = Date.now();\n now.value = t;\n const ms = compute(t);\n emit('change', ms);\n if (type === 'countdown' && ms <= 0 && !finished) {\n finished = true;\n if (timer) {\n clearInterval(timer);\n timer = null;\n }\n emit('finish');\n }\n}\n\nonMounted(() => {\n // SSR-safe: timers only run in the browser\n finished = false;\n now.value = Date.now();\n // Emit initial change so consumers see the starting value\n emit('change', compute(now.value));\n timer = setInterval(tick, TICK_MS);\n});\n\nonBeforeUnmount(() => {\n if (timer) {\n clearInterval(timer);\n timer = null;\n }\n});\n\n// ─────────────────────────────────────────────\n// Formatting\n// ─────────────────────────────────────────────\nconst ms = computed<number>(() => (now.value ? compute(now.value) : compute(Date.now())));\n\nfunction formatDuration(t: number, fmt: string): string {\n const days = Math.floor(t / 86_400_000);\n let rem = t - days * 86_400_000;\n const hours = Math.floor(rem / 3_600_000);\n rem -= hours * 3_600_000;\n const minutes = Math.floor(rem / 60_000);\n rem -= minutes * 60_000;\n const seconds = Math.floor(rem / 1000);\n const milliseconds = rem - seconds * 1000;\n\n // Bracketed text is treated as a literal (dayjs-compatible).\n return fmt.replace(/\\[([^\\]]*)\\]|SSS|HH|mm|ss|D|H|m|s|S/g, (match, literal) => {\n if (literal !== undefined) return literal;\n switch (match) {\n case 'SSS':\n return String(milliseconds).padStart(3, '0');\n case 'HH':\n return String(hours).padStart(2, '0');\n case 'mm':\n return String(minutes).padStart(2, '0');\n case 'ss':\n return String(seconds).padStart(2, '0');\n case 'D':\n return String(days);\n case 'H':\n return String(hours);\n case 'm':\n return String(minutes);\n case 's':\n return String(seconds);\n case 'S':\n return String(milliseconds);\n default:\n return match;\n }\n });\n}\n\nconst formatted = computed<string>(() => formatDuration(ms.value, format));\n</script>\n\n<template>\n <BStatistic\n class=\"b-statistic-timer\"\n :title=\"title\"\n :value=\"formatted\"\n :prefix=\"prefix\"\n :suffix=\"suffix\"\n :value-style=\"valueStyle\"\n >\n <template v-if=\"$slots.title\" #title><slot name=\"title\" /></template>\n <template v-if=\"$slots.prefix\" #prefix><slot name=\"prefix\" /></template>\n <template v-if=\"$slots.suffix\" #suffix><slot name=\"suffix\" /></template>\n </BStatistic>\n</template>\n"],"mappings":""}