buefy 3.0.5 → 3.0.7

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 (241) hide show
  1. package/dist/buefy.d.ts +63 -3
  2. package/dist/buefy.esm.js +209 -46
  3. package/dist/buefy.esm.min.js +2 -2
  4. package/dist/buefy.js +209 -44
  5. package/dist/buefy.min.js +2 -2
  6. package/dist/cjs/{Autocomplete-DEUs3z7g.js → Autocomplete-b0JUESTO.js} +3 -3
  7. package/dist/cjs/{Button-Cq7yqI8p.js → Button-Dw6VG6n7.js} +2 -2
  8. package/dist/cjs/{Checkbox-GPzAMQqM.js → Checkbox-cujzPKDl.js} +31 -3
  9. package/dist/cjs/{CompatFallthroughMixin-hhK0Gkhr.js → CompatFallthroughMixin-DI5L88ey.js} +1 -1
  10. package/dist/cjs/{Datepicker-DhsJpauU.js → Datepicker-DVB975q3.js} +9 -9
  11. package/dist/cjs/{Dropdown-BAXMPUCZ.js → Dropdown-CFh_lLvm.js} +1 -1
  12. package/dist/cjs/{DropdownItem-BOAAPdrW.js → DropdownItem-D2Ky1QIH.js} +1 -1
  13. package/dist/cjs/{Field-19ZCJFF8.js → Field-Dy73xhhY.js} +1 -1
  14. package/dist/cjs/{FormElementMixin-DavX4iOv.js → FormElementMixin-17PQ7TPR.js} +1 -1
  15. package/dist/cjs/{Icon-lsDKE2wQ.js → Icon-DrFLI3Zg.js} +48 -6
  16. package/dist/cjs/{Image-CocPwU3n.js → Image-D4AGl_2Z.js} +1 -1
  17. package/dist/cjs/{Input-BcloGeZ3.js → Input-z4Vlmbj8.js} +4 -4
  18. package/dist/cjs/{Modal-D1aZUehE.js → Modal-CVyLPawO.js} +1 -1
  19. package/dist/cjs/{NoticeMixin--3RjH43z.js → NoticeMixin-BlwAiMRV.js} +1 -1
  20. package/dist/cjs/{Pagination-D1MVdiLp.js → Pagination-54NHaQvi.js} +2 -2
  21. package/dist/cjs/{Progress-DT9Qc8Id.js → Progress-BlXLJ3zb.js} +1 -1
  22. package/dist/cjs/{Select-DayPKwCY.js → Select-DRXaEjlP.js} +3 -3
  23. package/dist/cjs/{TabbedChildMixin-B3JUUwcf.js → TabbedChildMixin-BFHsIyg6.js} +1 -1
  24. package/dist/cjs/{Tag-BprnwJJ1.js → Tag-BdL2uH8x.js} +1 -1
  25. package/dist/cjs/{Timepicker-DDYkLeNV.js → Timepicker-ujQPxzDF.js} +6 -6
  26. package/dist/cjs/{TimepickerMixin-C9WVvcUL.js → TimepickerMixin-C9OA8jWF.js} +3 -3
  27. package/dist/cjs/{Tooltip-Cgighv0j.js → Tooltip-j_3eF7QD.js} +1 -1
  28. package/dist/cjs/autocomplete.js +7 -6
  29. package/dist/cjs/breadcrumb.js +2 -2
  30. package/dist/cjs/button.js +4 -3
  31. package/dist/cjs/carousel.js +4 -3
  32. package/dist/cjs/checkbox.js +3 -1
  33. package/dist/cjs/clockpicker.js +8 -7
  34. package/dist/cjs/colorpicker.js +12 -11
  35. package/dist/cjs/{config-DR826Ki2.js → config-CXSF5Vky.js} +2 -1
  36. package/dist/cjs/config.js +1 -1
  37. package/dist/cjs/datepicker.js +11 -10
  38. package/dist/cjs/datetimepicker.js +13 -12
  39. package/dist/cjs/dialog.js +5 -4
  40. package/dist/cjs/dropdown.js +3 -3
  41. package/dist/cjs/field.js +2 -2
  42. package/dist/cjs/icon.js +5 -2
  43. package/dist/cjs/iconAliases-DoayKo0q.js +100 -0
  44. package/dist/cjs/image.js +2 -2
  45. package/dist/cjs/{index-BkFyTNWp.js → index-N35FRTpu.js} +8 -8
  46. package/dist/cjs/index.js +27 -24
  47. package/dist/cjs/input.js +6 -5
  48. package/dist/cjs/menu.js +4 -3
  49. package/dist/cjs/message.js +4 -3
  50. package/dist/cjs/modal.js +2 -2
  51. package/dist/cjs/navbar.js +2 -2
  52. package/dist/cjs/notification.js +5 -4
  53. package/dist/cjs/numberinput.js +6 -5
  54. package/dist/cjs/pagination.js +4 -3
  55. package/dist/cjs/progress.js +2 -2
  56. package/dist/cjs/rate.js +3 -2
  57. package/dist/cjs/select.js +6 -5
  58. package/dist/cjs/sidebar.js +1 -1
  59. package/dist/cjs/slider.js +3 -3
  60. package/dist/cjs/snackbar.js +2 -2
  61. package/dist/cjs/steps.js +4 -3
  62. package/dist/cjs/switch.js +1 -1
  63. package/dist/cjs/table.js +9 -8
  64. package/dist/cjs/tabs.js +4 -3
  65. package/dist/cjs/tag.js +4 -3
  66. package/dist/cjs/taginput.js +8 -7
  67. package/dist/cjs/timepicker.js +12 -11
  68. package/dist/cjs/toast.js +2 -2
  69. package/dist/cjs/tooltip.js +2 -2
  70. package/dist/cjs/upload.js +3 -3
  71. package/dist/components/autocomplete/index.js +122 -6
  72. package/dist/components/autocomplete/index.min.js +2 -2
  73. package/dist/components/breadcrumb/index.js +1 -1
  74. package/dist/components/breadcrumb/index.min.js +1 -1
  75. package/dist/components/button/index.js +122 -6
  76. package/dist/components/button/index.min.js +2 -2
  77. package/dist/components/carousel/index.js +122 -6
  78. package/dist/components/carousel/index.min.js +2 -2
  79. package/dist/components/checkbox/index.js +106 -4
  80. package/dist/components/checkbox/index.min.js +2 -2
  81. package/dist/components/clockpicker/index.js +126 -10
  82. package/dist/components/clockpicker/index.min.js +2 -2
  83. package/dist/components/collapse/index.js +1 -1
  84. package/dist/components/collapse/index.min.js +1 -1
  85. package/dist/components/colorpicker/index.js +126 -10
  86. package/dist/components/colorpicker/index.min.js +2 -2
  87. package/dist/components/datepicker/index.js +134 -18
  88. package/dist/components/datepicker/index.min.js +2 -2
  89. package/dist/components/datetimepicker/index.js +126 -10
  90. package/dist/components/datetimepicker/index.min.js +2 -2
  91. package/dist/components/dialog/index.js +122 -6
  92. package/dist/components/dialog/index.min.js +2 -2
  93. package/dist/components/dropdown/index.js +1 -1
  94. package/dist/components/dropdown/index.min.js +1 -1
  95. package/dist/components/field/index.js +1 -1
  96. package/dist/components/field/index.min.js +1 -1
  97. package/dist/components/icon/index.js +124 -6
  98. package/dist/components/icon/index.min.js +2 -2
  99. package/dist/components/image/index.js +1 -1
  100. package/dist/components/image/index.min.js +1 -1
  101. package/dist/components/input/index.js +122 -6
  102. package/dist/components/input/index.min.js +2 -2
  103. package/dist/components/loading/index.js +1 -1
  104. package/dist/components/loading/index.min.js +1 -1
  105. package/dist/components/menu/index.js +124 -8
  106. package/dist/components/menu/index.min.js +2 -2
  107. package/dist/components/message/index.js +122 -6
  108. package/dist/components/message/index.min.js +2 -2
  109. package/dist/components/modal/index.js +1 -1
  110. package/dist/components/modal/index.min.js +1 -1
  111. package/dist/components/navbar/index.js +1 -1
  112. package/dist/components/navbar/index.min.js +1 -1
  113. package/dist/components/notification/index.js +122 -6
  114. package/dist/components/notification/index.min.js +2 -2
  115. package/dist/components/numberinput/index.js +122 -6
  116. package/dist/components/numberinput/index.min.js +2 -2
  117. package/dist/components/pagination/index.js +122 -6
  118. package/dist/components/pagination/index.min.js +2 -2
  119. package/dist/components/progress/index.js +1 -1
  120. package/dist/components/progress/index.min.js +1 -1
  121. package/dist/components/radio/index.js +1 -1
  122. package/dist/components/radio/index.min.js +1 -1
  123. package/dist/components/rate/index.js +122 -6
  124. package/dist/components/rate/index.min.js +2 -2
  125. package/dist/components/select/index.js +122 -6
  126. package/dist/components/select/index.min.js +2 -2
  127. package/dist/components/sidebar/index.js +1 -1
  128. package/dist/components/sidebar/index.min.js +1 -1
  129. package/dist/components/skeleton/index.js +1 -1
  130. package/dist/components/skeleton/index.min.js +1 -1
  131. package/dist/components/slider/index.js +1 -1
  132. package/dist/components/slider/index.min.js +1 -1
  133. package/dist/components/snackbar/index.js +1 -1
  134. package/dist/components/snackbar/index.min.js +1 -1
  135. package/dist/components/steps/index.js +122 -6
  136. package/dist/components/steps/index.min.js +2 -2
  137. package/dist/components/switch/index.js +1 -1
  138. package/dist/components/switch/index.min.js +1 -1
  139. package/dist/components/table/index.js +156 -13
  140. package/dist/components/table/index.min.js +2 -2
  141. package/dist/components/tabs/index.js +122 -6
  142. package/dist/components/tabs/index.min.js +2 -2
  143. package/dist/components/tag/index.js +122 -6
  144. package/dist/components/tag/index.min.js +2 -2
  145. package/dist/components/taginput/index.js +122 -6
  146. package/dist/components/taginput/index.min.js +2 -2
  147. package/dist/components/timepicker/index.js +134 -18
  148. package/dist/components/timepicker/index.min.js +2 -2
  149. package/dist/components/toast/index.js +1 -1
  150. package/dist/components/toast/index.min.js +1 -1
  151. package/dist/components/tooltip/index.js +1 -1
  152. package/dist/components/tooltip/index.min.js +1 -1
  153. package/dist/components/upload/index.js +1 -1
  154. package/dist/components/upload/index.min.js +1 -1
  155. package/dist/css/buefy.css +21 -38
  156. package/dist/css/buefy.css.map +1 -1
  157. package/dist/css/buefy.min.css +1 -1
  158. package/dist/css/versions/buefy-no-reset.css +21 -38
  159. package/dist/css/versions/buefy-no-reset.css.map +1 -1
  160. package/dist/css/versions/buefy-no-reset.min.css +1 -1
  161. package/dist/css/versions/buefy-standalone.css +21 -38
  162. package/dist/css/versions/buefy-standalone.css.map +1 -1
  163. package/dist/css/versions/buefy-standalone.min.css +1 -1
  164. package/dist/esm/{Autocomplete-HsHD-6pc.js → Autocomplete-BsBIH0Mj.js} +3 -3
  165. package/dist/esm/{Button-Bvib75up.js → Button-BTP__-p5.js} +2 -2
  166. package/dist/esm/{Checkbox-u861Rije.js → Checkbox-C6pO3IzG.js} +31 -3
  167. package/dist/esm/{CompatFallthroughMixin-C8LPuwDr.js → CompatFallthroughMixin-LfFRwwlz.js} +1 -1
  168. package/dist/esm/{Datepicker-BZ5ORu0F.js → Datepicker-CrVKrZBF.js} +9 -9
  169. package/dist/esm/{Dropdown-BLadix4L.js → Dropdown-GHauDDcD.js} +1 -1
  170. package/dist/esm/{DropdownItem-Crhb4RQp.js → DropdownItem-By3tSZk2.js} +1 -1
  171. package/dist/esm/{Field-DZCOQuRO.js → Field-CU8ZBgMh.js} +1 -1
  172. package/dist/esm/{FormElementMixin-Dd_wkBN5.js → FormElementMixin-CKI7b4I4.js} +1 -1
  173. package/dist/esm/{Icon-iqPKMem5.js → Icon-pQAdaqZb.js} +49 -7
  174. package/dist/esm/{Image-By9o7ryD.js → Image-COmzg-EK.js} +1 -1
  175. package/dist/esm/{Input-JL4LWKyL.js → Input-CErQ1Jyw.js} +4 -4
  176. package/dist/esm/{Modal-BF2kchNd.js → Modal-C13NJijf.js} +1 -1
  177. package/dist/esm/{NoticeMixin-ByNlva3T.js → NoticeMixin-TQEF1Kx6.js} +1 -1
  178. package/dist/esm/{Pagination-BWFVCGiz.js → Pagination-DvgzxH87.js} +2 -2
  179. package/dist/esm/{Progress-BxT2PFEw.js → Progress-AeKn1Ttq.js} +1 -1
  180. package/dist/esm/{Select-dYTVc9W4.js → Select-CbkuxvSQ.js} +3 -3
  181. package/dist/esm/{TabbedChildMixin-BsuDQmWE.js → TabbedChildMixin-Bdu5A4iY.js} +1 -1
  182. package/dist/esm/{Tag-BFgiw0Ac.js → Tag-Dx_-Tavp.js} +1 -1
  183. package/dist/esm/{Timepicker-CYqyLHE9.js → Timepicker-0ojuPkqd.js} +6 -6
  184. package/dist/esm/{TimepickerMixin-Bikh6_Fg.js → TimepickerMixin-oNahYGFZ.js} +3 -3
  185. package/dist/esm/{Tooltip-Ds5fe3ZP.js → Tooltip-BnzQFdnQ.js} +1 -1
  186. package/dist/esm/autocomplete.js +7 -6
  187. package/dist/esm/breadcrumb.js +2 -2
  188. package/dist/esm/button.js +4 -3
  189. package/dist/esm/carousel.js +4 -3
  190. package/dist/esm/checkbox.js +3 -1
  191. package/dist/esm/clockpicker.js +8 -7
  192. package/dist/esm/colorpicker.js +12 -11
  193. package/dist/esm/{config-CKuo-p6e.js → config-f4Dyy8TN.js} +2 -1
  194. package/dist/esm/config.js +1 -1
  195. package/dist/esm/datepicker.js +11 -10
  196. package/dist/esm/datetimepicker.js +13 -12
  197. package/dist/esm/dialog.js +5 -4
  198. package/dist/esm/dropdown.js +3 -3
  199. package/dist/esm/field.js +2 -2
  200. package/dist/esm/icon.js +3 -2
  201. package/dist/esm/iconAliases-B-CydxNj.js +97 -0
  202. package/dist/esm/image.js +2 -2
  203. package/dist/esm/{index-mnzTDKh9.js → index-BYVep8cv.js} +8 -8
  204. package/dist/esm/index.js +26 -25
  205. package/dist/esm/input.js +6 -5
  206. package/dist/esm/menu.js +4 -3
  207. package/dist/esm/message.js +4 -3
  208. package/dist/esm/modal.js +2 -2
  209. package/dist/esm/navbar.js +2 -2
  210. package/dist/esm/notification.js +5 -4
  211. package/dist/esm/numberinput.js +6 -5
  212. package/dist/esm/pagination.js +4 -3
  213. package/dist/esm/progress.js +2 -2
  214. package/dist/esm/rate.js +3 -2
  215. package/dist/esm/select.js +6 -5
  216. package/dist/esm/sidebar.js +1 -1
  217. package/dist/esm/slider.js +3 -3
  218. package/dist/esm/snackbar.js +2 -2
  219. package/dist/esm/steps.js +4 -3
  220. package/dist/esm/switch.js +1 -1
  221. package/dist/esm/table.js +9 -8
  222. package/dist/esm/tabs.js +4 -3
  223. package/dist/esm/tag.js +4 -3
  224. package/dist/esm/taginput.js +8 -7
  225. package/dist/esm/timepicker.js +12 -11
  226. package/dist/esm/toast.js +2 -2
  227. package/dist/esm/tooltip.js +2 -2
  228. package/dist/esm/upload.js +3 -3
  229. package/package.json +2 -2
  230. package/src/components/checkbox/Checkbox.spec.ts +56 -26
  231. package/src/components/checkbox/Checkbox.vue +25 -1
  232. package/src/components/checkbox/__snapshots__/Checkbox.spec.ts.snap +1 -1
  233. package/src/components/datepicker/__snapshots__/Datepicker.spec.ts.snap +2 -2
  234. package/src/components/icon/Icon.spec.ts +67 -0
  235. package/src/components/icon/Icon.vue +40 -5
  236. package/src/components/icon/__snapshots__/Icon.spec.ts.snap +1 -1
  237. package/src/components/icon/index.ts +10 -0
  238. package/src/components/table/__snapshots__/TableMobileSort.spec.ts.snap +1 -1
  239. package/src/scss/components/_checkbox.scss +13 -15
  240. package/src/utils/config.ts +104 -2
  241. package/src/utils/iconAliases.ts +86 -0
package/dist/esm/toast.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { defineComponent, openBlock, createBlock, Transition, withCtx, withDirectives, createElementVNode, normalizeClass, renderSlot, createElementBlock, Fragment, createCommentVNode, vShow, createApp, h, inject } from 'vue';
2
- import { c as config } from './config-CKuo-p6e.js';
3
- import { N as NoticeMixin } from './NoticeMixin-ByNlva3T.js';
2
+ import { c as config } from './config-f4Dyy8TN.js';
3
+ import { N as NoticeMixin } from './NoticeMixin-TQEF1Kx6.js';
4
4
  import { _ as _export_sfc } from './_plugin-vue_export-helper-OJRSZE6i.js';
5
5
  import { getComponentFromVNode, copyAppContext } from './helpers.js';
6
6
  import { r as registerComponentProgrammatic } from './plugins-1tLsuIZF.js';
@@ -1,7 +1,7 @@
1
- import { T as Tooltip } from './Tooltip-Ds5fe3ZP.js';
1
+ import { T as Tooltip } from './Tooltip-BnzQFdnQ.js';
2
2
  import { a as registerComponent } from './plugins-1tLsuIZF.js';
3
3
  import 'vue';
4
- import './config-CKuo-p6e.js';
4
+ import './config-f4Dyy8TN.js';
5
5
  import './helpers.js';
6
6
  import './_plugin-vue_export-helper-OJRSZE6i.js';
7
7
 
@@ -1,10 +1,10 @@
1
1
  import { defineComponent, openBlock, createElementBlock, mergeProps, renderSlot, withModifiers, normalizeClass, createElementVNode } from 'vue';
2
- import { C as CompatFallthroughMixin } from './CompatFallthroughMixin-C8LPuwDr.js';
3
- import { F as FormElementMixin } from './FormElementMixin-Dd_wkBN5.js';
2
+ import { C as CompatFallthroughMixin } from './CompatFallthroughMixin-LfFRwwlz.js';
3
+ import { F as FormElementMixin } from './FormElementMixin-CKI7b4I4.js';
4
4
  import { F as File } from './ssr-C7yEpGLm.js';
5
5
  import { _ as _export_sfc } from './_plugin-vue_export-helper-OJRSZE6i.js';
6
6
  import { a as registerComponent } from './plugins-1tLsuIZF.js';
7
- import './config-CKuo-p6e.js';
7
+ import './config-f4Dyy8TN.js';
8
8
 
9
9
  const Upload$1 = defineComponent({
10
10
  name: "BUpload",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "buefy",
3
- "version": "3.0.5",
3
+ "version": "3.0.7",
4
4
  "description": "Lightweight UI components for Vue.js (v3) based on Bulma",
5
5
  "keywords": [
6
6
  "vuejs",
@@ -63,7 +63,7 @@
63
63
  },
64
64
  "devDependencies": {
65
65
  "@babel/plugin-transform-runtime": "^7.26.9",
66
- "@babel/preset-env": "^7.26.9",
66
+ "@babel/preset-env": "^7.29.5",
67
67
  "@microsoft/api-extractor": "^7.50.0",
68
68
  "@rollup/plugin-babel": "^6.0.4",
69
69
  "@rollup/plugin-commonjs": "^28.0.2",
@@ -1,5 +1,3 @@
1
- import { existsSync, readFileSync } from 'node:fs'
2
- import { join } from 'node:path'
3
1
  import { shallowMount } from '@vue/test-utils'
4
2
  import type { VueWrapper } from '@vue/test-utils'
5
3
  import { beforeEach, describe, expect, it, vi } from 'vitest'
@@ -44,31 +42,63 @@ describe('BCheckbox', () => {
44
42
  ).toHaveBeenCalled()
45
43
  })
46
44
 
47
- it('generates svg checkmark images from concrete colors in checkbox styles', () => {
48
- const scssPathCandidates = [
49
- join(process.cwd(), 'src/scss/components/_checkbox.scss'),
50
- join(process.cwd(), 'buefy/src/scss/components/_checkbox.scss')
51
- ]
52
- const scssPath = scssPathCandidates.find((candidate) =>
53
- existsSync(candidate)
54
- )
45
+ it('renders no SVG when unchecked', () => {
46
+ const w = shallowMount(BCheckbox)
47
+ expect(w.find('.check svg').exists()).toBe(false)
48
+ })
49
+
50
+ it('renders inline SVG checkmark when checked (boolean modelValue)', async () => {
51
+ const w = shallowMount(BCheckbox, {
52
+ props: { modelValue: true }
53
+ })
54
+ const svg = w.find('.check svg')
55
+ expect(svg.exists()).toBe(true)
56
+ const path = svg.find('path')
57
+ expect(path.attributes('fill')).toBe('currentColor')
58
+ expect(path.attributes('d')).toBeTruthy()
59
+ // Uses the 1x1 normalized viewBox for the checkmark
60
+ expect(svg.attributes('viewBox')).toBe('0 0 1 1')
61
+ })
62
+
63
+ it('renders inline SVG checkmark when checked (array modelValue)', async () => {
64
+ const w = shallowMount(BCheckbox, {
65
+ props: { modelValue: ['a', 'b'], nativeValue: 'a' }
66
+ })
67
+ expect(w.find('.check svg').exists()).toBe(true)
68
+ })
55
69
 
56
- expect(scssPath).toBeTruthy()
57
- if (!scssPath) {
58
- throw new Error(
59
- 'Unable to locate _checkbox.scss for regression assertion'
60
- )
61
- }
62
- const source = readFileSync(scssPath, 'utf8')
70
+ it('renders no SVG when value not in array', () => {
71
+ const w = shallowMount(BCheckbox, {
72
+ props: { modelValue: ['b'], nativeValue: 'a' }
73
+ })
74
+ expect(w.find('.check svg').exists()).toBe(false)
75
+ })
76
+
77
+ it('renders indeterminate SVG path when indeterminate prop is true', () => {
78
+ const w = shallowMount(BCheckbox, {
79
+ props: { indeterminate: true }
80
+ })
81
+ const svg = w.find('.check svg')
82
+ expect(svg.exists()).toBe(true)
83
+ // Indeterminate and checkmark paths are different
84
+ const indeterminatePath = w.vm.checkmarkAlias.path
85
+ expect(indeterminatePath).toContain('0.15') // rect-as-path signature
86
+ })
87
+
88
+ it('checkmark uses different path for indeterminate vs checked', () => {
89
+ const checked = shallowMount(BCheckbox, { props: { modelValue: true } })
90
+ const indeterminate = shallowMount(BCheckbox, { props: { indeterminate: true } })
91
+ expect(checked.vm.checkmarkAlias.path).not.toBe(indeterminate.vm.checkmarkAlias.path)
92
+ })
63
93
 
64
- // Regression: CSS variables inside data-uri SVG are not resolved by browsers.
65
- expect(source).toContain('fn.checkmark($checkbox-checkmark-color)')
66
- expect(source).toContain('fn.indeterminate($checkbox-checkmark-color)')
67
- expect(source).not.toContain(
68
- 'fn.checkmark(cv.getVar("checkbox-checkmark-color"))'
69
- )
70
- expect(source).not.toContain(
71
- 'fn.indeterminate(cv.getVar("checkbox-checkmark-color"))'
72
- )
94
+ it('SVG color is controlled via currentColor (not embedded in SVG data)', () => {
95
+ // Regression: previously _checkbox.scss embedded SVG colors as data-URIs;
96
+ // color could not be changed at runtime. Now SVG uses fill="currentColor"
97
+ // so the CSS `color` property on the parent drives the icon color.
98
+ const w = shallowMount(BCheckbox, { props: { modelValue: true } })
99
+ const path = w.find('.check svg path')
100
+ expect(path.attributes('fill')).toBe('currentColor')
101
+ // No inline fill color embedded in the path data
102
+ expect(path.attributes('d')).not.toContain('fill:')
73
103
  })
74
104
  })
@@ -27,7 +27,16 @@
27
27
  :false-value="falseValue"
28
28
  :aria-labelledby="ariaLabelledby"
29
29
  >
30
- <span class="check" :class="type" />
30
+ <span class="check" :class="type">
31
+ <svg
32
+ v-if="isChecked || indeterminate"
33
+ :viewBox="checkmarkAlias.viewBox || '0 0 1 1'"
34
+ xmlns="http://www.w3.org/2000/svg"
35
+ aria-hidden="true"
36
+ >
37
+ <path fill="currentColor" :d="checkmarkAlias.path" />
38
+ </svg>
39
+ </span>
31
40
  <span :id="ariaLabelledby" class="control-label"><slot /></span>
32
41
  </label>
33
42
  </template>
@@ -35,6 +44,8 @@
35
44
  <script lang="ts">
36
45
  import { defineComponent } from 'vue'
37
46
  import CheckRadioMixin from '../../utils/CheckRadioMixin'
47
+ import { resolveAlias } from '../../utils/iconAliases'
48
+ import type { SvgIconAlias } from '../../utils/config'
38
49
 
39
50
  export default defineComponent({
40
51
  name: 'BCheckbox',
@@ -58,6 +69,19 @@ export default defineComponent({
58
69
  type: String,
59
70
  default: ''
60
71
  }
72
+ },
73
+ computed: {
74
+ isChecked(): boolean {
75
+ const val = this.computedValue
76
+ if (Array.isArray(val)) {
77
+ return val.includes(this.nativeValue)
78
+ }
79
+ return val === this.trueValue
80
+ },
81
+ checkmarkAlias(): SvgIconAlias {
82
+ const key = this.indeterminate ? 'checkboxIndeterminate' : 'checkboxOn'
83
+ return resolveAlias(key) as SvgIconAlias
84
+ }
61
85
  }
62
86
  })
63
87
  </script>
@@ -4,6 +4,6 @@ exports[`BCheckbox > render correctly 1`] = `
4
4
  "<label class="b-checkbox checkbox">
5
5
  <!-- Checkbox needs to listen for a space event instead of a just a
6
6
  click and enter event so that that using the keyboard spacebar will also
7
- trigger the checkbox change in the b-table --><input id="" type="checkbox" autocomplete="on" true-value="true" false-value="false" value="false"><span class="check"></span><span class="control-label"></span>
7
+ trigger the checkbox change in the b-table --><input id="" type="checkbox" autocomplete="on" true-value="true" false-value="false" value="false"><span class="check"><!--v-if--></span><span class="control-label"></span>
8
8
  </label>"
9
9
  `;
@@ -16,9 +16,9 @@ exports[`BDatepicker > render correctly 1`] = `
16
16
  <div>
17
17
  <header class="datepicker-header">
18
18
  <div class="pagination field is-centered"><a class="pagination-previous" role="button" href="#">
19
- <b-icon-stub icon="chevron-left" type="is-primary is-clickable" both="true"></b-icon-stub>
19
+ <b-icon-stub type="is-primary is-clickable" icon="chevron-left" both="true"></b-icon-stub>
20
20
  </a><a class="pagination-next" role="button" href="#">
21
- <b-icon-stub icon="chevron-right" type="is-primary is-clickable" both="true"></b-icon-stub>
21
+ <b-icon-stub type="is-primary is-clickable" icon="chevron-right" both="true"></b-icon-stub>
22
22
  </a>
23
23
  <div class="pagination-list">
24
24
  <div class="field">
@@ -1,6 +1,8 @@
1
1
  import { shallowMount } from '@vue/test-utils'
2
2
  import { describe, expect, it } from 'vitest'
3
3
  import BIcon from '@components/icon/Icon.vue'
4
+ import type { ComponentIconAlias } from '@utils/config'
5
+ import config from '@utils/config'
4
6
 
5
7
  describe('BIcon', () => {
6
8
  it('render correctly', () => {
@@ -139,4 +141,69 @@ describe('BIcon', () => {
139
141
 
140
142
  expect(wrapper.find('i').classes()).toContain('foo-bar')
141
143
  })
144
+
145
+ it('renders inline SVG when alias resolves to a SvgIconAlias', () => {
146
+ const wrapper = shallowMount(BIcon, {
147
+ props: { alias: 'chevronLeft' }
148
+ })
149
+
150
+ const svg = wrapper.find('svg')
151
+ expect(svg.exists()).toBe(true)
152
+ expect(svg.attributes('aria-hidden')).toBe('true')
153
+ const path = svg.find('path')
154
+ expect(path.exists()).toBe(true)
155
+ expect(path.attributes('fill')).toBe('currentColor')
156
+ expect(path.attributes('d')).toBeTruthy()
157
+ })
158
+
159
+ it('renders viewBox from the alias on the SVG element', () => {
160
+ const wrapper = shallowMount(BIcon, {
161
+ props: { alias: 'checkboxOn' }
162
+ })
163
+
164
+ expect(wrapper.find('svg').attributes('viewBox')).toBe('0 0 1 1')
165
+ })
166
+
167
+ it('falls back to 0 0 24 24 viewBox when alias has none', () => {
168
+ const wrapper = shallowMount(BIcon, {
169
+ props: { alias: 'chevronLeft' }
170
+ })
171
+
172
+ expect(wrapper.find('svg').attributes('viewBox')).toBe('0 0 24 24')
173
+ })
174
+
175
+ it('renders a component alias (ComponentIconAlias)', () => {
176
+ const FakeIcon = { name: 'FakeIcon', template: '<span />' }
177
+ const alias: ComponentIconAlias = {
178
+ type: 'component',
179
+ component: FakeIcon,
180
+ icon: ['fas', 'check']
181
+ }
182
+
183
+ const original = config.iconAliases
184
+ config.iconAliases = { customAlias: alias }
185
+
186
+ const wrapper = shallowMount(BIcon, {
187
+ props: { alias: 'customAlias' }
188
+ })
189
+
190
+ const fakeIcon = wrapper.findComponent(FakeIcon)
191
+ expect(fakeIcon.exists()).toBe(true)
192
+
193
+ config.iconAliases = original
194
+ })
195
+
196
+ it('alias prop takes precedence over icon/pack when both are provided', () => {
197
+ const wrapper = shallowMount(BIcon, {
198
+ props: {
199
+ alias: 'chevronLeft',
200
+ icon: 'eye',
201
+ pack: 'mdi'
202
+ }
203
+ })
204
+
205
+ // Should render SVG (from alias), not <i> (from pack)
206
+ expect(wrapper.find('svg').exists()).toBe(true)
207
+ expect(wrapper.find('i').exists()).toBe(false)
208
+ })
142
209
  })
@@ -1,10 +1,24 @@
1
1
  <template>
2
2
  <span class="icon" :class="[newType, size]">
3
+ <svg
4
+ v-if="isSvgAlias"
5
+ :viewBox="resolvedAliasSvg.viewBox || '0 0 24 24'"
6
+ xmlns="http://www.w3.org/2000/svg"
7
+ :class="customClass"
8
+ aria-hidden="true"
9
+ >
10
+ <path fill="currentColor" :d="resolvedAliasSvg.path" />
11
+ </svg>
12
+ <component
13
+ v-else-if="isComponentAlias"
14
+ :is="resolvedAliasComponent.component"
15
+ :icon="resolvedAliasComponent.icon"
16
+ :class="customClass"
17
+ />
3
18
  <i
4
- v-if="!useIconComponent"
19
+ v-else-if="!useIconComponent"
5
20
  :class="[newPack, newIcon, newCustomSize, customClass]"
6
21
  />
7
-
8
22
  <component
9
23
  v-else
10
24
  :is="useIconComponent"
@@ -18,8 +32,9 @@
18
32
  <script lang="ts">
19
33
  import { defineComponent } from 'vue'
20
34
 
21
- import config from '../../utils/config'
35
+ import config, { type SvgIconAlias, type ComponentIconAlias } from '../../utils/config'
22
36
  import getIcons, { type InternalIconPack } from '../../utils/icons'
37
+ import { resolveAlias } from '../../utils/iconAliases'
23
38
 
24
39
  export default defineComponent({
25
40
  name: 'BIcon',
@@ -29,14 +44,34 @@ export default defineComponent({
29
44
  pack: String,
30
45
  icon: {
31
46
  type: String,
32
- required: true
47
+ required: false,
48
+ default: undefined
33
49
  },
50
+ /** Key into IconAliases (e.g. "chevronLeft"). Takes precedence over icon/pack. */
51
+ alias: String,
34
52
  size: String,
35
53
  customSize: String,
36
54
  customClass: String,
37
55
  both: Boolean // This is used internally to show both MDI and FA icon
38
56
  },
39
57
  computed: {
58
+ resolvedAlias() {
59
+ if (!this.alias) return null
60
+ return resolveAlias(this.alias) ?? null
61
+ },
62
+ isSvgAlias(): boolean {
63
+ return this.resolvedAlias?.type === 'svg'
64
+ },
65
+ isComponentAlias(): boolean {
66
+ return this.resolvedAlias?.type === 'component'
67
+ },
68
+ // Typed accessors used in the template
69
+ resolvedAliasSvg(): SvgIconAlias {
70
+ return this.resolvedAlias as SvgIconAlias
71
+ },
72
+ resolvedAliasComponent(): ComponentIconAlias {
73
+ return this.resolvedAlias as ComponentIconAlias
74
+ },
40
75
  iconConfig() {
41
76
  const allIcons = getIcons()
42
77
  return allIcons[this.newPack]
@@ -53,7 +88,7 @@ export default defineComponent({
53
88
  * internal icons are always MDI.
54
89
  */
55
90
  newIcon() {
56
- return `${this.iconPrefix}${this.getEquivalentIconOf(this.icon)}`
91
+ return `${this.iconPrefix}${this.getEquivalentIconOf(this.icon ?? '')}`
57
92
  },
58
93
  newPack() {
59
94
  return this.pack || config.defaultIconPack
@@ -1,3 +1,3 @@
1
1
  // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
2
 
3
- exports[`BIcon > render correctly 1`] = `"<span class="icon"><i class="mdi mdi-undefined mdi-24px"></i></span>"`;
3
+ exports[`BIcon > render correctly 1`] = `"<span class="icon"><i class="mdi mdi- mdi-24px"></i></span>"`;
@@ -15,3 +15,13 @@ export default Plugin
15
15
  export {
16
16
  Icon as BIcon
17
17
  }
18
+
19
+ export type {
20
+ IconAlias,
21
+ SvgIconAlias,
22
+ ComponentIconAlias,
23
+ CssIconAlias,
24
+ IconAliases
25
+ } from '../../utils/config'
26
+
27
+ export { resolveAlias, getIconAliases } from '../../utils/iconAliases'
@@ -5,7 +5,7 @@ exports[`BTableMobileSort > render correctly 1`] = `
5
5
  <div class="field has-addons">
6
6
  <b-select-stub modelvalue="-1" multiple="false" expanded=""></b-select-stub>
7
7
  <div class="control"><button class="button is-primary">
8
- <b-icon-stub icon="arrow-up" size="is-small" both="true" class="is-desc"></b-icon-stub>
8
+ <b-icon-stub size="is-small" icon="arrow-up" both="true" class="is-desc"></b-icon-stub>
9
9
  </button></div>
10
10
  </div>
11
11
  </div>"
@@ -4,7 +4,6 @@
4
4
  @use "bulma/sass/utilities/mixins" as mixins;
5
5
  @use "bulma/sass/utilities/controls" as controls;
6
6
  @use "bulma/sass/form/shared";
7
- @use "../utils/functions" as fn;
8
7
  @use "sass:list";
9
8
 
10
9
  $checkbox-active-background-color: cv.getVar('primary') !default;
@@ -22,7 +21,7 @@ $checkbox-colors: shared.$form-colors !default;
22
21
  @include cv.register-vars(
23
22
  (
24
23
  "checkbox-active-background-color": #{$checkbox-active-background-color},
25
-
24
+
26
25
  "checkbox-shadow": #{shared.$input-shadow},
27
26
 
28
27
  "checkbox-background-color": #{$checkbox-background},
@@ -31,24 +30,18 @@ $checkbox-colors: shared.$form-colors !default;
31
30
  "checkbox-border-width": #{$checkbox-border-width},
32
31
  "checkbox-checkmark-color": #{$checkbox-checkmark-color},
33
32
  "checkbox-size": #{$checkbox-size},
34
- "checkbox-checkmark-image": #{url(fn.checkmark($checkbox-checkmark-color))},
35
- "checkbox-indeterminate-image": #{url(fn.indeterminate($checkbox-checkmark-color))}
36
33
  )
37
34
  );
38
35
 
39
36
  &.checkbox input[type=checkbox] + .check {
40
37
 
41
38
  @each $name, $pair in $checkbox-colors {
42
- $color-invert: cv.getVar($name, "", "-invert");
43
-
44
39
  &.#{iv.$class-prefix}is-#{$name} {
45
40
  @include cv.register-vars(
46
41
  (
47
42
  "checkbox-active-background-color": #{cv.getVar($name)},
48
43
  "checkbox-border-color": #{cv.getVar($name)},
49
- "checkbox-checkmark-color": #{$color-invert},
50
- "checkbox-checkmark-image": #{url(fn.checkmark($color-invert))},
51
- "checkbox-indeterminate-image": #{url(fn.indeterminate($color-invert))}
44
+ "checkbox-checkmark-color": #{cv.getVar($name, "", "-100")},
52
45
  )
53
46
  );
54
47
  }
@@ -66,7 +59,7 @@ $checkbox-colors: shared.$form-colors !default;
66
59
  outline: none;
67
60
  display: inline-flex;
68
61
  align-items: center;
69
-
62
+
70
63
  &:not(.button) {
71
64
  margin-inline-end: 0.5em;
72
65
  & + .checkbox:last-child {
@@ -82,27 +75,32 @@ $checkbox-colors: shared.$form-colors !default;
82
75
  z-index: -1;
83
76
 
84
77
  + .check {
85
- // @extend %input;
86
-
87
78
  padding: 0;
88
79
  background: cv.getVar("checkbox-background-color");
89
80
  border-style: solid;
90
81
  border-width: cv.getVar('checkbox-border-width');
91
- // border-color: cv.getVar("checkbox-border-color");
92
82
  box-shadow: cv.getVar('checkbox-shadow');
83
+ position: relative;
93
84
 
94
85
  width: cv.getVar('checkbox-size');
95
86
  height: cv.getVar('checkbox-size');
96
87
  flex-shrink: 0;
97
88
  border-radius: cv.getVar('checkbox-border-radius');
98
89
  transition: background cv.getVar('speed-slow') cv.getVar('easing');
90
+
91
+ svg {
92
+ display: block;
93
+ width: 100%;
94
+ height: 100%;
95
+ color: cv.getVar('checkbox-checkmark-color');
96
+ }
99
97
  }
100
98
  &:checked + .check {
101
- background: cv.getVar('checkbox-active-background-color') cv.getVar('checkbox-checkmark-image') no-repeat center center;
99
+ background: cv.getVar('checkbox-active-background-color');
102
100
  border-color: cv.getVar("checkbox-border-color");
103
101
  }
104
102
  &:indeterminate + .check {
105
- background: cv.getVar('checkbox-active-background-color') cv.getVar('checkbox-indeterminate-image') no-repeat center center;
103
+ background: cv.getVar('checkbox-active-background-color');
106
104
  border-color: cv.getVar('checkbox-border-color');
107
105
  }
108
106
  &:focus {
@@ -74,6 +74,101 @@ export interface IconPack {
74
74
  iconPrefix?: string
75
75
  }
76
76
 
77
+ /*
78
+ * Icon alias that renders an inline SVG `<path>` element.
79
+ * Color is controlled via CSS `color` / `fill="currentColor"`.
80
+ *
81
+ * @public
82
+ */
83
+ export type SvgIconAlias = {
84
+ type: 'svg'
85
+ /* SVG path `d` attribute. */
86
+ path: string
87
+ /* SVG viewBox. Defaults to "0 0 24 24". */
88
+ viewBox?: string
89
+ }
90
+
91
+ /*
92
+ * Icon alias that delegates rendering to a Vue component (e.g. FontAwesomeIcon).
93
+ *
94
+ * @public
95
+ */
96
+ export type ComponentIconAlias = {
97
+ type: 'component'
98
+ /* The Vue component to render. */
99
+ component: string | object
100
+ /*
101
+ * Passed as the `:icon` prop to the component.
102
+ * Typed as `any` because it is forwarded verbatim to an external component
103
+ * (e.g. `['fas', 'check']` for FontAwesomeIcon), whose prop type is opaque to Buefy.
104
+ */
105
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
106
+ icon: any
107
+ }
108
+
109
+ /*
110
+ * Icon alias that uses the existing CSS-class pack approach.
111
+ *
112
+ * @public
113
+ */
114
+ export type CssIconAlias = {
115
+ type: 'css'
116
+ /* Icon pack name (e.g. "mdi", "fas"). */
117
+ pack: string
118
+ /* Icon name within the pack. */
119
+ icon: string
120
+ }
121
+
122
+ /*
123
+ * A named icon alias — one of three rendering modes.
124
+ *
125
+ * @public
126
+ */
127
+ export type IconAlias = SvgIconAlias | ComponentIconAlias | CssIconAlias
128
+
129
+ /*
130
+ * Named icon aliases used by Buefy components.
131
+ * Override any entry via the `iconAliases` config option.
132
+ *
133
+ * @public
134
+ */
135
+ export interface IconAliases {
136
+ /* Checked checkbox mark. */
137
+ checkboxOn: IconAlias
138
+ /* Indeterminate checkbox mark. */
139
+ checkboxIndeterminate: IconAlias
140
+ /* Pagination / dropdown previous/left chevron. */
141
+ chevronLeft: IconAlias
142
+ /* Pagination / dropdown next/right chevron. */
143
+ chevronRight: IconAlias
144
+ /* Downward chevron. */
145
+ chevronDown: IconAlias
146
+ /* Upward chevron. */
147
+ chevronUp: IconAlias
148
+ /* Dropdown open indicator. */
149
+ menuDown: IconAlias
150
+ /* Dropdown close indicator. */
151
+ menuUp: IconAlias
152
+ /* Success status icon. */
153
+ check: IconAlias
154
+ /* Danger / error status icon. */
155
+ alertCircle: IconAlias
156
+ /* Warning status icon. */
157
+ alert: IconAlias
158
+ /* Info status icon. */
159
+ information: IconAlias
160
+ /* Close / dismiss icon. */
161
+ close: IconAlias
162
+ /* Close circle icon. */
163
+ closeCircle: IconAlias
164
+ /* Eye / show-password icon. */
165
+ eye: IconAlias
166
+ /* Eye-off / hide-password icon. */
167
+ eyeOff: IconAlias
168
+ /* Additional user-defined aliases. */
169
+ [key: string]: IconAlias
170
+ }
171
+
77
172
  /*
78
173
  * Buefy configuration.
79
174
  *
@@ -512,7 +607,13 @@ export interface BuefyConfig {
512
607
  * Custom icon packs.
513
608
  * No custom icon packs by default.
514
609
  */
515
- customIconPacks?: Record<string, IconPack> | null
610
+ customIconPacks?: Record<string, IconPack> | null,
611
+ /*
612
+ * Named icon aliases.
613
+ * Overrides specific entries in the default alias set.
614
+ * No overrides by default.
615
+ */
616
+ iconAliases?: Partial<IconAliases> | null
516
617
  }
517
618
 
518
619
  let config: BuefyConfig = {
@@ -600,7 +701,8 @@ let config: BuefyConfig = {
600
701
  defaultBreadcrumbAlign: 'is-left',
601
702
  defaultBreadcrumbSeparator: '',
602
703
  defaultBreadcrumbSize: 'is-medium',
603
- customIconPacks: null
704
+ customIconPacks: null,
705
+ iconAliases: null
604
706
  }
605
707
 
606
708
  /*