@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/dist/index.js CHANGED
@@ -176,6 +176,7 @@ const CAccordionButton = vue.defineComponent({
176
176
  const toggleVisibility = vue.inject('toggleVisibility');
177
177
  const visible = vue.inject('visible');
178
178
  return () => vue.h('button', {
179
+ type: 'button',
179
180
  'aria-expanded': !visible.value,
180
181
  class: ['accordion-button', { ['collapsed']: !visible.value }],
181
182
  onClick: () => toggleVisibility(),
@@ -347,6 +348,9 @@ const CCloseButton = vue.defineComponent({
347
348
  ],
348
349
  setup(props, { emit }) {
349
350
  const handleClick = () => {
351
+ if (props.disabled) {
352
+ return;
353
+ }
350
354
  emit('click');
351
355
  };
352
356
  return () => vue.h('button', {
@@ -822,6 +826,20 @@ const CButton = vue.defineComponent({
822
826
  return ['sm', 'lg'].includes(value);
823
827
  },
824
828
  },
829
+ /**
830
+ * Specifies the type of button. Always specify the type attribute for the `<button>` element.
831
+ * Different browsers may use different default types for the `<button>` element.
832
+ *
833
+ * @values 'button', 'submit', 'reset'
834
+ */
835
+ type: {
836
+ type: String,
837
+ default: 'button',
838
+ required: false,
839
+ validator: (value) => {
840
+ return ['button', 'submit', 'reset'].includes(value);
841
+ },
842
+ },
825
843
  /**
826
844
  * Set the button variant to an outlined button or a ghost button.
827
845
  *
@@ -836,7 +854,19 @@ const CButton = vue.defineComponent({
836
854
  },
837
855
  },
838
856
  },
839
- setup(props, { slots }) {
857
+ emits: [
858
+ /**
859
+ * Event called when the user clicks on the button.
860
+ */
861
+ 'click',
862
+ ],
863
+ setup(props, { emit, slots }) {
864
+ const handleClick = () => {
865
+ if (props.disabled) {
866
+ return;
867
+ }
868
+ emit('click');
869
+ };
840
870
  return () => vue.h(props.component, {
841
871
  class: [
842
872
  'btn',
@@ -851,6 +881,8 @@ const CButton = vue.defineComponent({
851
881
  disabled: props.disabled && props.component !== 'a',
852
882
  ...(props.component === 'a' && props.disabled && { 'aria-disabled': true, tabIndex: -1 }),
853
883
  ...(props.component === 'a' && props.href && { href: props.href }),
884
+ ...(props.component === 'button' && { type: props.type }),
885
+ onClick: handleClick,
854
886
  }, slots.default && slots.default());
855
887
  },
856
888
  });
@@ -1809,6 +1841,10 @@ function getContainingBlock(element) {
1809
1841
 
1810
1842
  var currentNode = getParentNode(element);
1811
1843
 
1844
+ if (isShadowRoot(currentNode)) {
1845
+ currentNode = currentNode.host;
1846
+ }
1847
+
1812
1848
  while (isHTMLElement(currentNode) && ['html', 'body'].indexOf(getNodeName(currentNode)) < 0) {
1813
1849
  var css = getComputedStyle$1(currentNode); // This is non-exhaustive but covers the most common CSS properties that
1814
1850
  // create a containing block.
@@ -2041,7 +2077,7 @@ function mapToStyles(_ref2) {
2041
2077
 
2042
2078
  if (placement === top || (placement === left || placement === right) && variation === end) {
2043
2079
  sideY = bottom;
2044
- var offsetY = isFixed && win.visualViewport ? win.visualViewport.height : // $FlowFixMe[prop-missing]
2080
+ var offsetY = isFixed && offsetParent === win && win.visualViewport ? win.visualViewport.height : // $FlowFixMe[prop-missing]
2045
2081
  offsetParent[heightProp];
2046
2082
  y -= offsetY - popperRect.height;
2047
2083
  y *= gpuAcceleration ? 1 : -1;
@@ -2049,7 +2085,7 @@ function mapToStyles(_ref2) {
2049
2085
 
2050
2086
  if (placement === left || (placement === top || placement === bottom) && variation === end) {
2051
2087
  sideX = right;
2052
- var offsetX = isFixed && win.visualViewport ? win.visualViewport.width : // $FlowFixMe[prop-missing]
2088
+ var offsetX = isFixed && offsetParent === win && win.visualViewport ? win.visualViewport.width : // $FlowFixMe[prop-missing]
2053
2089
  offsetParent[widthProp];
2054
2090
  x -= offsetX - popperRect.width;
2055
2091
  x *= gpuAcceleration ? 1 : -1;
@@ -3508,6 +3544,20 @@ const CDropdown = vue.defineComponent({
3508
3544
  }
3509
3545
  },
3510
3546
  },
3547
+ /**
3548
+ * Configure the auto close behavior of the dropdown:
3549
+ * - `true` - the dropdown will be closed by clicking outside or inside the dropdown menu.
3550
+ * - `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)
3551
+ * - `'inside'` - the dropdown will be closed (only) by clicking inside the dropdown menu.
3552
+ * - `'outside'` - the dropdown will be closed (only) by clicking outside the dropdown menu.
3553
+ */
3554
+ autoClose: {
3555
+ type: [Boolean, String],
3556
+ default: true,
3557
+ validator: (value) => {
3558
+ return typeof value === 'boolean' || ['inside', 'outside'].includes(value);
3559
+ },
3560
+ },
3511
3561
  /**
3512
3562
  * Sets a darker color scheme to match a dark navbar.
3513
3563
  */
@@ -3593,21 +3643,23 @@ const CDropdown = vue.defineComponent({
3593
3643
  'show',
3594
3644
  ],
3595
3645
  setup(props, { slots, emit }) {
3596
- const dropdownRef = vue.ref();
3646
+ const dropdownToggleRef = vue.ref();
3597
3647
  const dropdownMenuRef = vue.ref();
3598
3648
  const placement = vue.ref(props.placement);
3599
3649
  const popper = vue.ref();
3600
- const config = vue.reactive({
3650
+ const visible = vue.ref(props.visible);
3651
+ vue.watch(() => props.visible, () => {
3652
+ visible.value = props.visible;
3653
+ });
3654
+ vue.provide('config', {
3655
+ autoClose: props.autoClose,
3601
3656
  alignment: props.alignment,
3602
3657
  dark: props.dark,
3603
3658
  popper: props.popper,
3604
- visible: props.visible,
3605
3659
  });
3606
- const { visible } = vue.toRefs(config);
3607
- vue.provide('config', config);
3608
3660
  vue.provide('variant', props.variant);
3609
3661
  vue.provide('visible', visible);
3610
- vue.provide('dropdownRef', dropdownRef);
3662
+ vue.provide('dropdownToggleRef', dropdownToggleRef);
3611
3663
  vue.provide('dropdownMenuRef', dropdownMenuRef);
3612
3664
  if (props.direction === 'dropup') {
3613
3665
  placement.value = 'top-start';
@@ -3626,8 +3678,8 @@ const CDropdown = vue.defineComponent({
3626
3678
  if (typeof props.alignment === 'object') {
3627
3679
  return;
3628
3680
  }
3629
- if (dropdownRef.value) {
3630
- popper.value = createPopper(dropdownRef.value, dropdownMenuRef.value, {
3681
+ if (dropdownToggleRef.value) {
3682
+ popper.value = createPopper(dropdownToggleRef.value, dropdownMenuRef.value, {
3631
3683
  placement: placement.value,
3632
3684
  });
3633
3685
  }
@@ -3638,40 +3690,28 @@ const CDropdown = vue.defineComponent({
3638
3690
  }
3639
3691
  popper.value = undefined;
3640
3692
  };
3641
- const toggleMenu = function () {
3642
- if (props.disabled === false) {
3643
- if (visible.value === true) {
3644
- visible.value = false;
3645
- }
3646
- else {
3647
- visible.value = true;
3648
- }
3693
+ const toggleMenu = (_visible) => {
3694
+ if (props.disabled) {
3695
+ return;
3649
3696
  }
3650
- };
3651
- vue.provide('toggleMenu', toggleMenu);
3652
- const hideMenu = function () {
3653
- if (props.disabled === false) {
3654
- visible.value = false;
3697
+ if (typeof _visible == 'boolean') {
3698
+ visible.value = _visible;
3699
+ return;
3655
3700
  }
3656
- };
3657
- const handleKeyup = (event) => {
3658
- if (dropdownRef.value && !dropdownRef.value.contains(event.target)) {
3659
- hideMenu();
3701
+ if (visible.value === true) {
3702
+ visible.value = false;
3703
+ return;
3660
3704
  }
3705
+ visible.value = true;
3661
3706
  };
3662
- const handleClickOutside = (event) => {
3663
- if (dropdownRef.value && !dropdownRef.value.contains(event.target)) {
3664
- hideMenu();
3707
+ vue.provide('toggleMenu', toggleMenu);
3708
+ const hideMenu = () => {
3709
+ if (props.disabled) {
3710
+ return;
3665
3711
  }
3712
+ visible.value = false;
3666
3713
  };
3667
- vue.onMounted(() => {
3668
- window.addEventListener('click', handleClickOutside);
3669
- window.addEventListener('keyup', handleKeyup);
3670
- });
3671
- vue.onUnmounted(() => {
3672
- window.removeEventListener('click', handleClickOutside);
3673
- window.removeEventListener('keyup', handleKeyup);
3674
- });
3714
+ vue.provide('hideMenu', hideMenu);
3675
3715
  vue.watch(visible, () => {
3676
3716
  props.popper && (visible.value ? initPopper() : destroyPopper());
3677
3717
  visible.value ? emit('show') : emit('hide');
@@ -3777,10 +3817,12 @@ const CDropdownMenu = vue.defineComponent({
3777
3817
  },
3778
3818
  },
3779
3819
  setup(props, { slots }) {
3820
+ const dropdownToggleRef = vue.inject('dropdownToggleRef');
3780
3821
  const dropdownMenuRef = vue.inject('dropdownMenuRef');
3781
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
3782
- const config = vue.inject('config');
3783
- const { alignment, dark, popper, visible } = vue.toRefs(config);
3822
+ const config = vue.inject('config'); // eslint-disable-line @typescript-eslint/no-explicit-any
3823
+ const hideMenu = vue.inject('hideMenu');
3824
+ const visible = vue.inject('visible');
3825
+ const { autoClose, alignment, dark, popper } = config;
3784
3826
  // eslint-disable-next-line @typescript-eslint/ban-types
3785
3827
  const alignmentClassNames = (alignment) => {
3786
3828
  const classNames = [];
@@ -3794,13 +3836,46 @@ const CDropdownMenu = vue.defineComponent({
3794
3836
  }
3795
3837
  return classNames;
3796
3838
  };
3839
+ const handleKeyup = (event) => {
3840
+ if (autoClose === false) {
3841
+ return;
3842
+ }
3843
+ if (!dropdownMenuRef.value?.contains(event.target)) {
3844
+ hideMenu();
3845
+ }
3846
+ };
3847
+ const handleMouseUp = (event) => {
3848
+ if (dropdownToggleRef.value?.contains(event.target)) {
3849
+ return;
3850
+ }
3851
+ if (autoClose === true) {
3852
+ hideMenu();
3853
+ return;
3854
+ }
3855
+ if (autoClose === 'inside' && dropdownMenuRef.value?.contains(event.target)) {
3856
+ hideMenu();
3857
+ return;
3858
+ }
3859
+ if (autoClose === 'outside' &&
3860
+ !dropdownMenuRef.value?.contains(event.target)) {
3861
+ hideMenu();
3862
+ }
3863
+ };
3864
+ vue.onUpdated(() => {
3865
+ visible.value && window.addEventListener('mouseup', handleMouseUp);
3866
+ visible.value && window.addEventListener('keyup', handleKeyup);
3867
+ });
3868
+ vue.onUnmounted(() => {
3869
+ window.removeEventListener('mouseup', handleMouseUp);
3870
+ window.removeEventListener('keyup', handleKeyup);
3871
+ });
3797
3872
  return () => vue.h(props.component, {
3798
3873
  class: [
3799
3874
  'dropdown-menu',
3800
- { 'dropdown-menu-dark': dark.value, show: visible.value },
3801
- alignmentClassNames(alignment.value),
3875
+ { 'dropdown-menu-dark': dark, show: visible.value },
3876
+ alignmentClassNames(alignment),
3802
3877
  ],
3803
- ...((typeof alignment.value === 'object' || !popper.value) && {
3878
+ ...((typeof alignment === 'object' || !popper) && {
3804
3879
  'data-coreui-popper': 'static',
3805
3880
  }),
3806
3881
  ref: dropdownMenuRef,
@@ -3843,6 +3918,10 @@ const CDropdownToggle = vue.defineComponent({
3843
3918
  default: 'button',
3844
3919
  require: false,
3845
3920
  },
3921
+ /**
3922
+ * Create a custom toggler which accepts any content.
3923
+ */
3924
+ custom: Boolean,
3846
3925
  /**
3847
3926
  * Toggle the disabled state for the component.
3848
3927
  */
@@ -3874,6 +3953,16 @@ const CDropdownToggle = vue.defineComponent({
3874
3953
  type: Boolean,
3875
3954
  required: false,
3876
3955
  },
3956
+ /**
3957
+ * Sets which event handlers you’d like provided to your toggle prop. You can specify one trigger or an array of them.
3958
+ *
3959
+ * @type 'hover' | 'focus' | 'click'
3960
+ */
3961
+ trigger: {
3962
+ type: String,
3963
+ default: 'click',
3964
+ required: false,
3965
+ },
3877
3966
  /**
3878
3967
  * Set the button variant to an outlined button or a ghost button.
3879
3968
  *
@@ -3889,7 +3978,8 @@ const CDropdownToggle = vue.defineComponent({
3889
3978
  },
3890
3979
  },
3891
3980
  setup(props, { slots }) {
3892
- const dropdownRef = vue.inject('dropdownRef');
3981
+ const togglerRef = vue.ref();
3982
+ const dropdownToggleRef = vue.inject('dropdownToggleRef');
3893
3983
  const dropdownVariant = vue.inject('variant');
3894
3984
  const visible = vue.inject('visible');
3895
3985
  const toggleMenu = vue.inject('toggleMenu');
@@ -3897,43 +3987,70 @@ const CDropdownToggle = vue.defineComponent({
3897
3987
  {
3898
3988
  'dropdown-toggle': props.caret,
3899
3989
  'dropdown-toggle-split': props.split,
3900
- show: visible,
3901
3990
  active: props.active,
3902
3991
  disabled: props.disabled,
3903
3992
  },
3904
3993
  ];
3905
- const buttonClassName = [
3906
- 'btn',
3907
- props.variant ? `btn-${props.variant}-${props.color}` : `btn-${props.color}`,
3908
- {
3909
- [`btn-${props.size}`]: props.size,
3910
- },
3911
- props.shape,
3912
- ];
3913
- return () => dropdownVariant === 'nav-item'
3914
- ? vue.h('a', {
3915
- active: props.active,
3916
- class: ['nav-link', className],
3917
- disabled: props.disabled,
3918
- href: '#',
3919
- onClick: (event) => {
3920
- event.preventDefault();
3921
- return toggleMenu();
3922
- },
3923
- ref: dropdownRef,
3924
- }, { default: () => slots.default && slots.default() })
3925
- : vue.h(
3926
- // TODO: check how to use CButton component
3927
- props.component, {
3928
- class: [...className, ...buttonClassName],
3929
- active: props.active,
3930
- disabled: props.disabled,
3994
+ const triggers = {
3995
+ ...((props.trigger === 'click' || props.trigger.includes('click')) &&
3996
+ !props.disabled && {
3931
3997
  onClick: () => toggleMenu(),
3932
- ...(props.component === 'button' && { type: 'button' }),
3933
- ref: dropdownRef,
3934
- }, props.split
3935
- ? vue.h('span', { class: 'visually-hidden' }, 'Toggle Dropdown')
3936
- : slots.default && slots.default());
3998
+ }),
3999
+ ...((props.trigger === 'focus' || props.trigger.includes('focus')) &&
4000
+ !props.disabled && {
4001
+ onfocus: () => toggleMenu(true),
4002
+ onblur: () => toggleMenu(false),
4003
+ }),
4004
+ };
4005
+ vue.onMounted(() => {
4006
+ if (togglerRef.value) {
4007
+ dropdownToggleRef.value = togglerRef.value.$el;
4008
+ }
4009
+ });
4010
+ return () => props.custom
4011
+ ? slots.default &&
4012
+ slots.default().map((slot) => vue.cloneVNode(slot, {
4013
+ ref: (el) => {
4014
+ togglerRef.value = el;
4015
+ },
4016
+ ...triggers,
4017
+ }))
4018
+ : dropdownVariant === 'nav-item'
4019
+ ? vue.h('a', {
4020
+ active: props.active,
4021
+ class: [
4022
+ 'nav-link',
4023
+ className,
4024
+ {
4025
+ show: visible.value,
4026
+ },
4027
+ ],
4028
+ disabled: props.disabled,
4029
+ href: '#',
4030
+ ref: dropdownToggleRef,
4031
+ ...triggers,
4032
+ }, { default: () => slots.default && slots.default() })
4033
+ : vue.h(CButton, {
4034
+ class: [
4035
+ className,
4036
+ {
4037
+ show: visible.value,
4038
+ },
4039
+ ],
4040
+ active: props.active,
4041
+ color: props.color,
4042
+ disabled: props.disabled,
4043
+ ref: (el) => {
4044
+ togglerRef.value = el;
4045
+ },
4046
+ shape: props.shape,
4047
+ size: props.size,
4048
+ ...triggers,
4049
+ ...(props.component === 'button' && { type: 'button' }),
4050
+ variant: props.variant,
4051
+ }, () => props.split
4052
+ ? vue.h('span', { class: 'visually-hidden' }, 'Toggle Dropdown')
4053
+ : slots.default && slots.default());
3937
4054
  },
3938
4055
  });
3939
4056
 
@@ -4339,6 +4456,7 @@ const CFormCheck = vue.defineComponent({
4339
4456
  };
4340
4457
  const formControl = () => {
4341
4458
  return vue.h('input', {
4459
+ ...attrs,
4342
4460
  checked: props.modelValue,
4343
4461
  class: [
4344
4462
  props.button ? 'btn-check' : 'form-check-input',
@@ -4351,7 +4469,6 @@ const CFormCheck = vue.defineComponent({
4351
4469
  indeterminate: props.indeterminate,
4352
4470
  onChange: (event) => handleChange(event),
4353
4471
  type: props.type,
4354
- ...attrs,
4355
4472
  });
4356
4473
  };
4357
4474
  const formLabel = () => {
@@ -4384,6 +4501,7 @@ const CFormCheck = vue.defineComponent({
4384
4501
  'is-invalid': props.invalid,
4385
4502
  'is-valid': props.valid,
4386
4503
  },
4504
+ attrs.class,
4387
4505
  ],
4388
4506
  }, [formControl(), props.label && formLabel()])
4389
4507
  : formControl();
@@ -4832,11 +4950,6 @@ const CFormSwitch = vue.defineComponent({
4832
4950
  ],
4833
4951
  setup(props, { attrs, emit }) {
4834
4952
  const checked = vue.ref(attrs.checked);
4835
- vue.onMounted(() => {
4836
- if (props.modelValue && typeof props.modelValue === 'boolean') {
4837
- console.log(props.modelValue);
4838
- }
4839
- });
4840
4953
  vue.watch(() => props.modelValue, () => {
4841
4954
  if (typeof props.modelValue === 'boolean')
4842
4955
  checked.value = props.modelValue;