@coreui/vue-pro 4.1.4 → 4.2.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 (27) hide show
  1. package/README.md +1 -1
  2. package/dist/components/button/CButton.d.ts +29 -2
  3. package/dist/components/dropdown/CDropdown.d.ts +25 -0
  4. package/dist/components/dropdown/CDropdownToggle.d.ts +35 -1
  5. package/dist/index.es.js +198 -85
  6. package/dist/index.es.js.map +1 -1
  7. package/dist/index.js +197 -84
  8. package/dist/index.js.map +1 -1
  9. package/package.json +9 -9
  10. package/src/components/accordion/CAccordionButton.ts +1 -0
  11. package/src/components/accordion/__tests__/__snapshots__/CAccordionButton.spec.ts.snap +1 -1
  12. package/src/components/accordion/__tests__/__snapshots__/CAccordionHeader.spec.ts.snap +1 -1
  13. package/src/components/button/CButton.ts +30 -1
  14. package/src/components/button/__tests__/__snapshots__/CButton.spec.ts.snap +1 -1
  15. package/src/components/close-button/CCloseButton.ts +4 -1
  16. package/src/components/dropdown/CDropdown.ts +48 -49
  17. package/src/components/dropdown/CDropdownMenu.ts +50 -7
  18. package/src/components/dropdown/CDropdownToggle.ts +78 -29
  19. package/src/components/dropdown/__tests__/CDropdownMenu.spec.ts +7 -7
  20. package/src/components/dropdown/__tests__/CDropdownToggle.spec.ts +4 -5
  21. package/src/components/dropdown/__tests__/__snapshots__/CDropdownToggle.spec.ts.snap +2 -2
  22. package/src/components/form/CFormCheck.ts +2 -1
  23. package/src/components/form/CFormSwitch.ts +1 -7
  24. package/src/components/form/__tests__/__snapshots__/CFormCheck.spec.ts.snap +2 -8
  25. package/src/components/modal/__tests__/__snapshots__/CModal.spec.ts.snap +2 -1
  26. package/src/components/sidebar/__tests__/__snapshots__/CSidebar.spec.ts.snap +8 -2
  27. package/src/components/toast/__tests__/__snapshots__/CToastClose.spec.ts.snap +1 -1
package/README.md CHANGED
@@ -43,7 +43,7 @@
43
43
 
44
44
  Several quick start options are available:
45
45
 
46
- - [Download the latest release](https://github.com/coreui/coreui-vue-pro/archive/v4.1.4.zip)
46
+ - [Download the latest release](https://github.com/coreui/coreui-vue-pro/archive/v4.2.0.zip)
47
47
  - Clone the repo: `git clone https://github.com/coreui/coreui-vue-pro.git`
48
48
  - Install with [npm](https://www.npmjs.com/): `npm install @coreui/vue-pro`
49
49
  - Install with [yarn](https://yarnpkg.com/): `yarn add @coreui/vue-pro`
@@ -59,6 +59,18 @@ export declare const CButton: import("vue").DefineComponent<{
59
59
  required: false;
60
60
  validator: (value: string) => boolean;
61
61
  };
62
+ /**
63
+ * Specifies the type of button. Always specify the type attribute for the `<button>` element.
64
+ * Different browsers may use different default types for the `<button>` element.
65
+ *
66
+ * @values 'button', 'submit', 'reset'
67
+ */
68
+ type: {
69
+ type: StringConstructor;
70
+ default: string;
71
+ required: false;
72
+ validator: (value: string) => boolean;
73
+ };
62
74
  /**
63
75
  * Set the button variant to an outlined button or a ghost button.
64
76
  *
@@ -72,7 +84,7 @@ export declare const CButton: import("vue").DefineComponent<{
72
84
  };
73
85
  }, () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
74
86
  [key: string]: any;
75
- }>, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, Record<string, any>, string, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<{
87
+ }>, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, "click"[], "click", import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<{
76
88
  /**
77
89
  * Toggle the active state for the component.
78
90
  */
@@ -133,6 +145,18 @@ export declare const CButton: import("vue").DefineComponent<{
133
145
  required: false;
134
146
  validator: (value: string) => boolean;
135
147
  };
148
+ /**
149
+ * Specifies the type of button. Always specify the type attribute for the `<button>` element.
150
+ * Different browsers may use different default types for the `<button>` element.
151
+ *
152
+ * @values 'button', 'submit', 'reset'
153
+ */
154
+ type: {
155
+ type: StringConstructor;
156
+ default: string;
157
+ required: false;
158
+ validator: (value: string) => boolean;
159
+ };
136
160
  /**
137
161
  * Set the button variant to an outlined button or a ghost button.
138
162
  *
@@ -144,7 +168,10 @@ export declare const CButton: import("vue").DefineComponent<{
144
168
  required: false;
145
169
  validator: (value: string) => boolean;
146
170
  };
147
- }>>, {
171
+ }>> & {
172
+ onClick?: ((...args: any[]) => any) | undefined;
173
+ }, {
174
+ type: string;
148
175
  disabled: boolean;
149
176
  variant: string;
150
177
  component: string;
@@ -12,6 +12,18 @@ declare const CDropdown: import("vue").DefineComponent<{
12
12
  required: false;
13
13
  validator: (value: string | any) => boolean;
14
14
  };
15
+ /**
16
+ * Configure the auto close behavior of the dropdown:
17
+ * - `true` - the dropdown will be closed by clicking outside or inside the dropdown menu.
18
+ * - `false` - the dropdown will be closed by clicking the toggle button and manually calling hide or toggle method. (Also will not be closed by pressing esc key)
19
+ * - `'inside'` - the dropdown will be closed (only) by clicking inside the dropdown menu.
20
+ * - `'outside'` - the dropdown will be closed (only) by clicking outside the dropdown menu.
21
+ */
22
+ autoClose: {
23
+ type: (StringConstructor | BooleanConstructor)[];
24
+ default: boolean;
25
+ validator: (value: boolean | string) => boolean;
26
+ };
15
27
  /**
16
28
  * Sets a darker color scheme to match a dark navbar.
17
29
  */
@@ -97,6 +109,18 @@ declare const CDropdown: import("vue").DefineComponent<{
97
109
  required: false;
98
110
  validator: (value: string | any) => boolean;
99
111
  };
112
+ /**
113
+ * Configure the auto close behavior of the dropdown:
114
+ * - `true` - the dropdown will be closed by clicking outside or inside the dropdown menu.
115
+ * - `false` - the dropdown will be closed by clicking the toggle button and manually calling hide or toggle method. (Also will not be closed by pressing esc key)
116
+ * - `'inside'` - the dropdown will be closed (only) by clicking inside the dropdown menu.
117
+ * - `'outside'` - the dropdown will be closed (only) by clicking outside the dropdown menu.
118
+ */
119
+ autoClose: {
120
+ type: (StringConstructor | BooleanConstructor)[];
121
+ default: boolean;
122
+ validator: (value: boolean | string) => boolean;
123
+ };
100
124
  /**
101
125
  * Sets a darker color scheme to match a dark navbar.
102
126
  */
@@ -176,6 +200,7 @@ declare const CDropdown: import("vue").DefineComponent<{
176
200
  variant: string;
177
201
  direction: string;
178
202
  alignment: string | Record<string, any>;
203
+ autoClose: string | boolean;
179
204
  placement: Placement;
180
205
  popper: boolean;
181
206
  trigger: string | unknown[];
@@ -1,3 +1,5 @@
1
+ import { PropType } from 'vue';
2
+ import { Triggers } from '../Types';
1
3
  declare const CDropdownToggle: import("vue").DefineComponent<{
2
4
  /**
3
5
  * Toggle the active state for the component.
@@ -32,6 +34,10 @@ declare const CDropdownToggle: import("vue").DefineComponent<{
32
34
  default: string;
33
35
  require: boolean;
34
36
  };
37
+ /**
38
+ * Create a custom toggler which accepts any content.
39
+ */
40
+ custom: BooleanConstructor;
35
41
  /**
36
42
  * Toggle the disabled state for the component.
37
43
  */
@@ -64,6 +70,16 @@ declare const CDropdownToggle: import("vue").DefineComponent<{
64
70
  type: BooleanConstructor;
65
71
  required: false;
66
72
  };
73
+ /**
74
+ * Sets which event handlers you’d like provided to your toggle prop. You can specify one trigger or an array of them.
75
+ *
76
+ * @type 'hover' | 'focus' | 'click'
77
+ */
78
+ trigger: {
79
+ type: PropType<Triggers>;
80
+ default: string;
81
+ required: false;
82
+ };
67
83
  /**
68
84
  * Set the button variant to an outlined button or a ghost button.
69
85
  *
@@ -77,7 +93,9 @@ declare const CDropdownToggle: import("vue").DefineComponent<{
77
93
  };
78
94
  }, () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
79
95
  [key: string]: any;
80
- }>, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, Record<string, any>, string, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<{
96
+ }> | import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
97
+ [key: string]: any;
98
+ }>[] | undefined, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, Record<string, any>, string, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<{
81
99
  /**
82
100
  * Toggle the active state for the component.
83
101
  */
@@ -111,6 +129,10 @@ declare const CDropdownToggle: import("vue").DefineComponent<{
111
129
  default: string;
112
130
  require: boolean;
113
131
  };
132
+ /**
133
+ * Create a custom toggler which accepts any content.
134
+ */
135
+ custom: BooleanConstructor;
114
136
  /**
115
137
  * Toggle the disabled state for the component.
116
138
  */
@@ -143,6 +165,16 @@ declare const CDropdownToggle: import("vue").DefineComponent<{
143
165
  type: BooleanConstructor;
144
166
  required: false;
145
167
  };
168
+ /**
169
+ * Sets which event handlers you’d like provided to your toggle prop. You can specify one trigger or an array of them.
170
+ *
171
+ * @type 'hover' | 'focus' | 'click'
172
+ */
173
+ trigger: {
174
+ type: PropType<Triggers>;
175
+ default: string;
176
+ required: false;
177
+ };
146
178
  /**
147
179
  * Set the button variant to an outlined button or a ghost button.
148
180
  *
@@ -161,6 +193,8 @@ declare const CDropdownToggle: import("vue").DefineComponent<{
161
193
  component: string;
162
194
  size: string;
163
195
  active: boolean;
196
+ trigger: Triggers;
164
197
  caret: boolean;
198
+ custom: boolean;
165
199
  }>;
166
200
  export { CDropdownToggle };
package/dist/index.es.js CHANGED
@@ -1,4 +1,4 @@
1
- import { defineComponent, ref, provide, h as h$1, Transition, withDirectives, inject, watch, reactive, onBeforeMount, onMounted, onUpdated, toRefs, onUnmounted, nextTick, vShow, computed, Teleport, onBeforeUnmount } from 'vue';
1
+ import { defineComponent, ref, provide, h as h$1, Transition, withDirectives, inject, watch, reactive, onBeforeMount, onMounted, onUpdated, toRefs, onUnmounted, cloneVNode, nextTick, vShow, computed, Teleport, onBeforeUnmount } from 'vue';
2
2
 
3
3
  const CAccordion = defineComponent({
4
4
  name: 'CAccordion',
@@ -172,6 +172,7 @@ const CAccordionButton = defineComponent({
172
172
  const toggleVisibility = inject('toggleVisibility');
173
173
  const visible = inject('visible');
174
174
  return () => h$1('button', {
175
+ type: 'button',
175
176
  'aria-expanded': !visible.value,
176
177
  class: ['accordion-button', { ['collapsed']: !visible.value }],
177
178
  onClick: () => toggleVisibility(),
@@ -343,6 +344,9 @@ const CCloseButton = defineComponent({
343
344
  ],
344
345
  setup(props, { emit }) {
345
346
  const handleClick = () => {
347
+ if (props.disabled) {
348
+ return;
349
+ }
346
350
  emit('click');
347
351
  };
348
352
  return () => h$1('button', {
@@ -818,6 +822,20 @@ const CButton = defineComponent({
818
822
  return ['sm', 'lg'].includes(value);
819
823
  },
820
824
  },
825
+ /**
826
+ * Specifies the type of button. Always specify the type attribute for the `<button>` element.
827
+ * Different browsers may use different default types for the `<button>` element.
828
+ *
829
+ * @values 'button', 'submit', 'reset'
830
+ */
831
+ type: {
832
+ type: String,
833
+ default: 'button',
834
+ required: false,
835
+ validator: (value) => {
836
+ return ['button', 'submit', 'reset'].includes(value);
837
+ },
838
+ },
821
839
  /**
822
840
  * Set the button variant to an outlined button or a ghost button.
823
841
  *
@@ -832,7 +850,19 @@ const CButton = defineComponent({
832
850
  },
833
851
  },
834
852
  },
835
- setup(props, { slots }) {
853
+ emits: [
854
+ /**
855
+ * Event called when the user clicks on the button.
856
+ */
857
+ 'click',
858
+ ],
859
+ setup(props, { emit, slots }) {
860
+ const handleClick = () => {
861
+ if (props.disabled) {
862
+ return;
863
+ }
864
+ emit('click');
865
+ };
836
866
  return () => h$1(props.component, {
837
867
  class: [
838
868
  'btn',
@@ -847,6 +877,8 @@ const CButton = defineComponent({
847
877
  disabled: props.disabled && props.component !== 'a',
848
878
  ...(props.component === 'a' && props.disabled && { 'aria-disabled': true, tabIndex: -1 }),
849
879
  ...(props.component === 'a' && props.href && { href: props.href }),
880
+ ...(props.component === 'button' && { type: props.type }),
881
+ onClick: handleClick,
850
882
  }, slots.default && slots.default());
851
883
  },
852
884
  });
@@ -1805,6 +1837,10 @@ function getContainingBlock(element) {
1805
1837
 
1806
1838
  var currentNode = getParentNode(element);
1807
1839
 
1840
+ if (isShadowRoot(currentNode)) {
1841
+ currentNode = currentNode.host;
1842
+ }
1843
+
1808
1844
  while (isHTMLElement(currentNode) && ['html', 'body'].indexOf(getNodeName(currentNode)) < 0) {
1809
1845
  var css = getComputedStyle$1(currentNode); // This is non-exhaustive but covers the most common CSS properties that
1810
1846
  // create a containing block.
@@ -2037,7 +2073,7 @@ function mapToStyles(_ref2) {
2037
2073
 
2038
2074
  if (placement === top || (placement === left || placement === right) && variation === end) {
2039
2075
  sideY = bottom;
2040
- var offsetY = isFixed && win.visualViewport ? win.visualViewport.height : // $FlowFixMe[prop-missing]
2076
+ var offsetY = isFixed && offsetParent === win && win.visualViewport ? win.visualViewport.height : // $FlowFixMe[prop-missing]
2041
2077
  offsetParent[heightProp];
2042
2078
  y -= offsetY - popperRect.height;
2043
2079
  y *= gpuAcceleration ? 1 : -1;
@@ -2045,7 +2081,7 @@ function mapToStyles(_ref2) {
2045
2081
 
2046
2082
  if (placement === left || (placement === top || placement === bottom) && variation === end) {
2047
2083
  sideX = right;
2048
- var offsetX = isFixed && win.visualViewport ? win.visualViewport.width : // $FlowFixMe[prop-missing]
2084
+ var offsetX = isFixed && offsetParent === win && win.visualViewport ? win.visualViewport.width : // $FlowFixMe[prop-missing]
2049
2085
  offsetParent[widthProp];
2050
2086
  x -= offsetX - popperRect.width;
2051
2087
  x *= gpuAcceleration ? 1 : -1;
@@ -3504,6 +3540,20 @@ const CDropdown = defineComponent({
3504
3540
  }
3505
3541
  },
3506
3542
  },
3543
+ /**
3544
+ * Configure the auto close behavior of the dropdown:
3545
+ * - `true` - the dropdown will be closed by clicking outside or inside the dropdown menu.
3546
+ * - `false` - the dropdown will be closed by clicking the toggle button and manually calling hide or toggle method. (Also will not be closed by pressing esc key)
3547
+ * - `'inside'` - the dropdown will be closed (only) by clicking inside the dropdown menu.
3548
+ * - `'outside'` - the dropdown will be closed (only) by clicking outside the dropdown menu.
3549
+ */
3550
+ autoClose: {
3551
+ type: [Boolean, String],
3552
+ default: true,
3553
+ validator: (value) => {
3554
+ return typeof value === 'boolean' || ['inside', 'outside'].includes(value);
3555
+ },
3556
+ },
3507
3557
  /**
3508
3558
  * Sets a darker color scheme to match a dark navbar.
3509
3559
  */
@@ -3589,21 +3639,23 @@ const CDropdown = defineComponent({
3589
3639
  'show',
3590
3640
  ],
3591
3641
  setup(props, { slots, emit }) {
3592
- const dropdownRef = ref();
3642
+ const dropdownToggleRef = ref();
3593
3643
  const dropdownMenuRef = ref();
3594
3644
  const placement = ref(props.placement);
3595
3645
  const popper = ref();
3596
- const config = reactive({
3646
+ const visible = ref(props.visible);
3647
+ watch(() => props.visible, () => {
3648
+ visible.value = props.visible;
3649
+ });
3650
+ provide('config', {
3651
+ autoClose: props.autoClose,
3597
3652
  alignment: props.alignment,
3598
3653
  dark: props.dark,
3599
3654
  popper: props.popper,
3600
- visible: props.visible,
3601
3655
  });
3602
- const { visible } = toRefs(config);
3603
- provide('config', config);
3604
3656
  provide('variant', props.variant);
3605
3657
  provide('visible', visible);
3606
- provide('dropdownRef', dropdownRef);
3658
+ provide('dropdownToggleRef', dropdownToggleRef);
3607
3659
  provide('dropdownMenuRef', dropdownMenuRef);
3608
3660
  if (props.direction === 'dropup') {
3609
3661
  placement.value = 'top-start';
@@ -3622,8 +3674,8 @@ const CDropdown = defineComponent({
3622
3674
  if (typeof props.alignment === 'object') {
3623
3675
  return;
3624
3676
  }
3625
- if (dropdownRef.value) {
3626
- popper.value = createPopper(dropdownRef.value, dropdownMenuRef.value, {
3677
+ if (dropdownToggleRef.value) {
3678
+ popper.value = createPopper(dropdownToggleRef.value, dropdownMenuRef.value, {
3627
3679
  placement: placement.value,
3628
3680
  });
3629
3681
  }
@@ -3634,40 +3686,28 @@ const CDropdown = defineComponent({
3634
3686
  }
3635
3687
  popper.value = undefined;
3636
3688
  };
3637
- const toggleMenu = function () {
3638
- if (props.disabled === false) {
3639
- if (visible.value === true) {
3640
- visible.value = false;
3641
- }
3642
- else {
3643
- visible.value = true;
3644
- }
3689
+ const toggleMenu = (_visible) => {
3690
+ if (props.disabled) {
3691
+ return;
3645
3692
  }
3646
- };
3647
- provide('toggleMenu', toggleMenu);
3648
- const hideMenu = function () {
3649
- if (props.disabled === false) {
3650
- visible.value = false;
3693
+ if (typeof _visible == 'boolean') {
3694
+ visible.value = _visible;
3695
+ return;
3651
3696
  }
3652
- };
3653
- const handleKeyup = (event) => {
3654
- if (dropdownRef.value && !dropdownRef.value.contains(event.target)) {
3655
- hideMenu();
3697
+ if (visible.value === true) {
3698
+ visible.value = false;
3699
+ return;
3656
3700
  }
3701
+ visible.value = true;
3657
3702
  };
3658
- const handleClickOutside = (event) => {
3659
- if (dropdownRef.value && !dropdownRef.value.contains(event.target)) {
3660
- hideMenu();
3703
+ provide('toggleMenu', toggleMenu);
3704
+ const hideMenu = () => {
3705
+ if (props.disabled) {
3706
+ return;
3661
3707
  }
3708
+ visible.value = false;
3662
3709
  };
3663
- onMounted(() => {
3664
- window.addEventListener('click', handleClickOutside);
3665
- window.addEventListener('keyup', handleKeyup);
3666
- });
3667
- onUnmounted(() => {
3668
- window.removeEventListener('click', handleClickOutside);
3669
- window.removeEventListener('keyup', handleKeyup);
3670
- });
3710
+ provide('hideMenu', hideMenu);
3671
3711
  watch(visible, () => {
3672
3712
  props.popper && (visible.value ? initPopper() : destroyPopper());
3673
3713
  visible.value ? emit('show') : emit('hide');
@@ -3773,10 +3813,12 @@ const CDropdownMenu = defineComponent({
3773
3813
  },
3774
3814
  },
3775
3815
  setup(props, { slots }) {
3816
+ const dropdownToggleRef = inject('dropdownToggleRef');
3776
3817
  const dropdownMenuRef = inject('dropdownMenuRef');
3777
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
3778
- const config = inject('config');
3779
- const { alignment, dark, popper, visible } = toRefs(config);
3818
+ const config = inject('config'); // eslint-disable-line @typescript-eslint/no-explicit-any
3819
+ const hideMenu = inject('hideMenu');
3820
+ const visible = inject('visible');
3821
+ const { autoClose, alignment, dark, popper } = config;
3780
3822
  // eslint-disable-next-line @typescript-eslint/ban-types
3781
3823
  const alignmentClassNames = (alignment) => {
3782
3824
  const classNames = [];
@@ -3790,13 +3832,46 @@ const CDropdownMenu = defineComponent({
3790
3832
  }
3791
3833
  return classNames;
3792
3834
  };
3835
+ const handleKeyup = (event) => {
3836
+ if (autoClose === false) {
3837
+ return;
3838
+ }
3839
+ if (!dropdownMenuRef.value?.contains(event.target)) {
3840
+ hideMenu();
3841
+ }
3842
+ };
3843
+ const handleMouseUp = (event) => {
3844
+ if (dropdownToggleRef.value?.contains(event.target)) {
3845
+ return;
3846
+ }
3847
+ if (autoClose === true) {
3848
+ hideMenu();
3849
+ return;
3850
+ }
3851
+ if (autoClose === 'inside' && dropdownMenuRef.value?.contains(event.target)) {
3852
+ hideMenu();
3853
+ return;
3854
+ }
3855
+ if (autoClose === 'outside' &&
3856
+ !dropdownMenuRef.value?.contains(event.target)) {
3857
+ hideMenu();
3858
+ }
3859
+ };
3860
+ onUpdated(() => {
3861
+ visible.value && window.addEventListener('mouseup', handleMouseUp);
3862
+ visible.value && window.addEventListener('keyup', handleKeyup);
3863
+ });
3864
+ onUnmounted(() => {
3865
+ window.removeEventListener('mouseup', handleMouseUp);
3866
+ window.removeEventListener('keyup', handleKeyup);
3867
+ });
3793
3868
  return () => h$1(props.component, {
3794
3869
  class: [
3795
3870
  'dropdown-menu',
3796
- { 'dropdown-menu-dark': dark.value, show: visible.value },
3797
- alignmentClassNames(alignment.value),
3871
+ { 'dropdown-menu-dark': dark, show: visible.value },
3872
+ alignmentClassNames(alignment),
3798
3873
  ],
3799
- ...((typeof alignment.value === 'object' || !popper.value) && {
3874
+ ...((typeof alignment === 'object' || !popper) && {
3800
3875
  'data-coreui-popper': 'static',
3801
3876
  }),
3802
3877
  ref: dropdownMenuRef,
@@ -3839,6 +3914,10 @@ const CDropdownToggle = defineComponent({
3839
3914
  default: 'button',
3840
3915
  require: false,
3841
3916
  },
3917
+ /**
3918
+ * Create a custom toggler which accepts any content.
3919
+ */
3920
+ custom: Boolean,
3842
3921
  /**
3843
3922
  * Toggle the disabled state for the component.
3844
3923
  */
@@ -3870,6 +3949,16 @@ const CDropdownToggle = defineComponent({
3870
3949
  type: Boolean,
3871
3950
  required: false,
3872
3951
  },
3952
+ /**
3953
+ * Sets which event handlers you’d like provided to your toggle prop. You can specify one trigger or an array of them.
3954
+ *
3955
+ * @type 'hover' | 'focus' | 'click'
3956
+ */
3957
+ trigger: {
3958
+ type: String,
3959
+ default: 'click',
3960
+ required: false,
3961
+ },
3873
3962
  /**
3874
3963
  * Set the button variant to an outlined button or a ghost button.
3875
3964
  *
@@ -3885,7 +3974,8 @@ const CDropdownToggle = defineComponent({
3885
3974
  },
3886
3975
  },
3887
3976
  setup(props, { slots }) {
3888
- const dropdownRef = inject('dropdownRef');
3977
+ const togglerRef = ref();
3978
+ const dropdownToggleRef = inject('dropdownToggleRef');
3889
3979
  const dropdownVariant = inject('variant');
3890
3980
  const visible = inject('visible');
3891
3981
  const toggleMenu = inject('toggleMenu');
@@ -3893,43 +3983,70 @@ const CDropdownToggle = defineComponent({
3893
3983
  {
3894
3984
  'dropdown-toggle': props.caret,
3895
3985
  'dropdown-toggle-split': props.split,
3896
- show: visible,
3897
3986
  active: props.active,
3898
3987
  disabled: props.disabled,
3899
3988
  },
3900
3989
  ];
3901
- const buttonClassName = [
3902
- 'btn',
3903
- props.variant ? `btn-${props.variant}-${props.color}` : `btn-${props.color}`,
3904
- {
3905
- [`btn-${props.size}`]: props.size,
3906
- },
3907
- props.shape,
3908
- ];
3909
- return () => dropdownVariant === 'nav-item'
3910
- ? h$1('a', {
3911
- active: props.active,
3912
- class: ['nav-link', className],
3913
- disabled: props.disabled,
3914
- href: '#',
3915
- onClick: (event) => {
3916
- event.preventDefault();
3917
- return toggleMenu();
3918
- },
3919
- ref: dropdownRef,
3920
- }, { default: () => slots.default && slots.default() })
3921
- : h$1(
3922
- // TODO: check how to use CButton component
3923
- props.component, {
3924
- class: [...className, ...buttonClassName],
3925
- active: props.active,
3926
- disabled: props.disabled,
3990
+ const triggers = {
3991
+ ...((props.trigger === 'click' || props.trigger.includes('click')) &&
3992
+ !props.disabled && {
3927
3993
  onClick: () => toggleMenu(),
3928
- ...(props.component === 'button' && { type: 'button' }),
3929
- ref: dropdownRef,
3930
- }, props.split
3931
- ? h$1('span', { class: 'visually-hidden' }, 'Toggle Dropdown')
3932
- : slots.default && slots.default());
3994
+ }),
3995
+ ...((props.trigger === 'focus' || props.trigger.includes('focus')) &&
3996
+ !props.disabled && {
3997
+ onfocus: () => toggleMenu(true),
3998
+ onblur: () => toggleMenu(false),
3999
+ }),
4000
+ };
4001
+ onMounted(() => {
4002
+ if (togglerRef.value) {
4003
+ dropdownToggleRef.value = togglerRef.value.$el;
4004
+ }
4005
+ });
4006
+ return () => props.custom
4007
+ ? slots.default &&
4008
+ slots.default().map((slot) => cloneVNode(slot, {
4009
+ ref: (el) => {
4010
+ togglerRef.value = el;
4011
+ },
4012
+ ...triggers,
4013
+ }))
4014
+ : dropdownVariant === 'nav-item'
4015
+ ? h$1('a', {
4016
+ active: props.active,
4017
+ class: [
4018
+ 'nav-link',
4019
+ className,
4020
+ {
4021
+ show: visible.value,
4022
+ },
4023
+ ],
4024
+ disabled: props.disabled,
4025
+ href: '#',
4026
+ ref: dropdownToggleRef,
4027
+ ...triggers,
4028
+ }, { default: () => slots.default && slots.default() })
4029
+ : h$1(CButton, {
4030
+ class: [
4031
+ className,
4032
+ {
4033
+ show: visible.value,
4034
+ },
4035
+ ],
4036
+ active: props.active,
4037
+ color: props.color,
4038
+ disabled: props.disabled,
4039
+ ref: (el) => {
4040
+ togglerRef.value = el;
4041
+ },
4042
+ shape: props.shape,
4043
+ size: props.size,
4044
+ ...triggers,
4045
+ ...(props.component === 'button' && { type: 'button' }),
4046
+ variant: props.variant,
4047
+ }, () => props.split
4048
+ ? h$1('span', { class: 'visually-hidden' }, 'Toggle Dropdown')
4049
+ : slots.default && slots.default());
3933
4050
  },
3934
4051
  });
3935
4052
 
@@ -4335,6 +4452,7 @@ const CFormCheck = defineComponent({
4335
4452
  };
4336
4453
  const formControl = () => {
4337
4454
  return h$1('input', {
4455
+ ...attrs,
4338
4456
  checked: props.modelValue,
4339
4457
  class: [
4340
4458
  props.button ? 'btn-check' : 'form-check-input',
@@ -4347,7 +4465,6 @@ const CFormCheck = defineComponent({
4347
4465
  indeterminate: props.indeterminate,
4348
4466
  onChange: (event) => handleChange(event),
4349
4467
  type: props.type,
4350
- ...attrs,
4351
4468
  });
4352
4469
  };
4353
4470
  const formLabel = () => {
@@ -4380,6 +4497,7 @@ const CFormCheck = defineComponent({
4380
4497
  'is-invalid': props.invalid,
4381
4498
  'is-valid': props.valid,
4382
4499
  },
4500
+ attrs.class,
4383
4501
  ],
4384
4502
  }, [formControl(), props.label && formLabel()])
4385
4503
  : formControl();
@@ -4828,11 +4946,6 @@ const CFormSwitch = defineComponent({
4828
4946
  ],
4829
4947
  setup(props, { attrs, emit }) {
4830
4948
  const checked = ref(attrs.checked);
4831
- onMounted(() => {
4832
- if (props.modelValue && typeof props.modelValue === 'boolean') {
4833
- console.log(props.modelValue);
4834
- }
4835
- });
4836
4949
  watch(() => props.modelValue, () => {
4837
4950
  if (typeof props.modelValue === 'boolean')
4838
4951
  checked.value = props.modelValue;