@coreui/vue-pro 4.9.0-beta.2 → 4.9.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 (34) hide show
  1. package/README.md +1 -1
  2. package/dist/components/dropdown/CDropdown.d.ts +62 -4
  3. package/dist/components/dropdown/CDropdownToggle.d.ts +1 -1
  4. package/dist/components/multi-select/CMultiSelect.d.ts +6 -6
  5. package/dist/components/popover/CPopover.d.ts +75 -6
  6. package/dist/components/toast/CToast.d.ts +1 -1
  7. package/dist/components/tooltip/CTooltip.d.ts +77 -8
  8. package/dist/composables/index.d.ts +2 -2
  9. package/dist/composables/useColorModes.d.ts +1 -1
  10. package/dist/composables/usePopper.d.ts +6 -0
  11. package/dist/index.es.js +424 -325
  12. package/dist/index.es.js.map +1 -1
  13. package/dist/index.js +423 -324
  14. package/dist/index.js.map +1 -1
  15. package/dist/types.d.ts +1 -1
  16. package/dist/utils/getRTLPlacement.d.ts +3 -0
  17. package/dist/utils/index.d.ts +2 -1
  18. package/package.json +10 -10
  19. package/src/components/date-range-picker/CDateRangePicker.ts +50 -17
  20. package/src/components/dropdown/CDropdown.ts +116 -61
  21. package/src/components/dropdown/CDropdownMenu.ts +2 -47
  22. package/src/components/dropdown/CDropdownToggle.ts +5 -5
  23. package/src/components/multi-select/CMultiSelect.ts +58 -67
  24. package/src/components/multi-select/CMultiSelectSelection.ts +10 -11
  25. package/src/components/picker/CPicker.ts +22 -7
  26. package/src/components/popover/CPopover.ts +96 -50
  27. package/src/components/time-picker/CTimePicker.ts +63 -34
  28. package/src/components/tooltip/CTooltip.ts +97 -51
  29. package/src/composables/index.ts +2 -2
  30. package/src/composables/usePopper.ts +25 -0
  31. package/src/types.ts +1 -1
  32. package/src/utils/getRTLPlacement.ts +18 -0
  33. package/src/utils/index.ts +2 -1
  34. package/src/composables/useColorModes.ts +0 -62
@@ -1,30 +1,54 @@
1
1
  import { defineComponent, h, PropType, ref, RendererElement, Teleport, Transition } from 'vue'
2
- import { createPopper, Placement } from '@popperjs/core'
2
+ import type { Placement } from '@popperjs/core'
3
3
 
4
+ import { usePopper } from '../../composables'
5
+ import type { Placements, Triggers } from '../../types'
4
6
  import { executeAfterTransition } from '../../utils/transition'
5
- import { isRTL } from '../../utils'
6
-
7
- const getPlacement = (placement: string, element: HTMLDivElement | null): Placement => {
8
- switch (placement) {
9
- case 'right': {
10
- return isRTL(element) ? 'left' : 'right'
11
- }
12
- case 'left': {
13
- return isRTL(element) ? 'right' : 'left'
14
- }
15
- default: {
16
- return placement as Placement
17
- }
18
- }
19
- }
7
+ import { getRTLPlacement } from '../../utils'
20
8
 
21
9
  const CTooltip = defineComponent({
22
10
  name: 'CTooltip',
23
11
  props: {
12
+ /**
13
+ * Apply a CSS fade transition to the tooltip.
14
+ *
15
+ * @since 4.9.0
16
+ */
17
+ animation: {
18
+ type: Boolean,
19
+ default: true,
20
+ },
24
21
  /**
25
22
  * Content for your component. If you want to pass non-string value please use dedicated slot `<template #content>...</template>`
26
23
  */
27
24
  content: String,
25
+ /**
26
+ * The delay for displaying and hiding the popover (in milliseconds). When a numerical value is provided, the delay applies to both the hide and show actions. The object structure for specifying the delay is as follows: delay: `{ 'show': 500, 'hide': 100 }`.
27
+ *
28
+ * @since 4.9.0
29
+ */
30
+ delay: {
31
+ type: [Number, Object] as PropType<number | { show: number; hide: number }>,
32
+ default: 0,
33
+ },
34
+ /**
35
+ * Specify the desired order of fallback placements by providing a list of placements as an array. The placements should be prioritized based on preference.
36
+ *
37
+ * @since 4.9.0
38
+ */
39
+ fallbackPlacements: {
40
+ type: [String, Array] as PropType<Placements | Placements[]>,
41
+ default: () => ['top', 'right', 'bottom', 'left'],
42
+ validator: (value: Placements | Placements[]) => {
43
+ if (typeof value === 'string') {
44
+ return ['top', 'right', 'bottom', 'left'].includes(value)
45
+ }
46
+ if (Array.isArray(value)) {
47
+ return value.every((e) => ['top', 'right', 'bottom', 'left'].includes(e))
48
+ }
49
+ return false
50
+ },
51
+ },
28
52
  /**
29
53
  * Offset of the tooltip relative to its target.
30
54
  */
@@ -48,9 +72,9 @@ const CTooltip = defineComponent({
48
72
  * @values 'click', 'focus', 'hover'
49
73
  */
50
74
  trigger: {
51
- type: [String, Array] as PropType<string | string[]>,
52
- default: 'hover',
53
- validator: (value: string | string[]) => {
75
+ type: [String, Array] as PropType<Triggers | Triggers[]>,
76
+ default: () => ['hover', 'focus'],
77
+ validator: (value: Triggers | Triggers[]) => {
54
78
  if (typeof value === 'string') {
55
79
  return ['click', 'focus', 'hover'].includes(value)
56
80
  }
@@ -78,12 +102,39 @@ const CTooltip = defineComponent({
78
102
  setup(props, { attrs, slots, emit }) {
79
103
  const togglerRef = ref()
80
104
  const tooltipRef = ref()
81
- const popper = ref()
82
105
  const visible = ref(props.visible)
106
+ const { initPopper, destroyPopper } = usePopper()
107
+
108
+ const delay =
109
+ typeof props.delay === 'number' ? { show: props.delay, hide: props.delay } : props.delay
110
+
111
+ const popperConfig = {
112
+ modifiers: [
113
+ {
114
+ name: 'arrow',
115
+ options: {
116
+ element: '.tooltip-arrow',
117
+ },
118
+ },
119
+ {
120
+ name: 'flip',
121
+ options: {
122
+ fallbackPlacements: props.fallbackPlacements,
123
+ },
124
+ },
125
+ {
126
+ name: 'offset',
127
+ options: {
128
+ offset: props.offset,
129
+ },
130
+ },
131
+ ],
132
+ placement: getRTLPlacement(props.placement, togglerRef.value),
133
+ }
83
134
 
84
135
  const handleEnter = (el: RendererElement, done: () => void) => {
85
136
  emit('show')
86
- initPopper()
137
+ initPopper(togglerRef.value, tooltipRef.value, popperConfig)
87
138
  el.classList.add('show')
88
139
  executeAfterTransition(() => done(), el as HTMLElement)
89
140
  }
@@ -97,32 +148,18 @@ const CTooltip = defineComponent({
97
148
  }, el as HTMLElement)
98
149
  }
99
150
 
100
- const handleToggle = (event: Event) => {
151
+ const toggleVisible = (event: Event, _visible: boolean) => {
101
152
  togglerRef.value = event.target
102
- visible.value = !visible.value
103
- }
104
-
105
- const initPopper = () => {
106
- if (togglerRef.value) {
107
- popper.value = createPopper(togglerRef.value, tooltipRef.value, {
108
- placement: getPlacement(props.placement, togglerRef.value),
109
- modifiers: [
110
- {
111
- name: 'offset',
112
- options: {
113
- offset: props.offset,
114
- },
115
- },
116
- ],
117
- })
153
+ if (_visible) {
154
+ setTimeout(() => {
155
+ visible.value = true
156
+ }, delay.show)
157
+ return
118
158
  }
119
- }
120
159
 
121
- const destroyPopper = () => {
122
- if (popper.value) {
123
- popper.value.destroy()
124
- }
125
- popper.value = undefined
160
+ setTimeout(() => {
161
+ visible.value = false
162
+ }, delay.hide)
126
163
  }
127
164
 
128
165
  return () => [
@@ -142,13 +179,19 @@ const CTooltip = defineComponent({
142
179
  h(
143
180
  'div',
144
181
  {
145
- class: 'tooltip fade bs-tooltip-auto',
182
+ class: [
183
+ 'tooltip',
184
+ 'bs-tooltip-auto',
185
+ {
186
+ fade: props.animation,
187
+ },
188
+ ],
146
189
  ref: tooltipRef,
147
190
  role: 'tooltip',
148
191
  ...attrs,
149
192
  },
150
193
  [
151
- h('div', { class: 'tooltip-arrow', 'data-popper-arrow': '' }),
194
+ h('div', { class: 'tooltip-arrow' }),
152
195
  (props.content || slots.content) &&
153
196
  h(
154
197
  'div',
@@ -164,11 +207,14 @@ const CTooltip = defineComponent({
164
207
  slots.toggler &&
165
208
  slots.toggler({
166
209
  on: {
167
- click: (event: Event) => props.trigger.includes('click') && handleToggle(event),
168
- blur: (event: Event) => props.trigger.includes('focus') && handleToggle(event),
169
- focus: (event: Event) => props.trigger.includes('focus') && handleToggle(event),
170
- mouseenter: (event: Event) => props.trigger.includes('hover') && handleToggle(event),
171
- mouseleave: (event: Event) => props.trigger.includes('hover') && handleToggle(event),
210
+ click: (event: Event) =>
211
+ props.trigger.includes('click') && toggleVisible(event, !visible.value),
212
+ blur: (event: Event) => props.trigger.includes('focus') && toggleVisible(event, false),
213
+ focus: (event: Event) => props.trigger.includes('focus') && toggleVisible(event, true),
214
+ mouseenter: (event: Event) =>
215
+ props.trigger.includes('hover') && toggleVisible(event, true),
216
+ mouseleave: (event: Event) =>
217
+ props.trigger.includes('hover') && toggleVisible(event, false),
172
218
  },
173
219
  }),
174
220
  ]
@@ -1,3 +1,3 @@
1
- import { useColorModes } from './useColorModes'
1
+ import { usePopper } from './usePopper'
2
2
 
3
- export { useColorModes }
3
+ export { usePopper }
@@ -0,0 +1,25 @@
1
+ import { ref } from 'vue'
2
+ import { createPopper } from '@popperjs/core'
3
+ import type { Instance, Options } from '@popperjs/core'
4
+
5
+ export const usePopper = () => {
6
+ const _popper = ref<Instance>()
7
+
8
+ const initPopper = (reference: HTMLElement, popper: HTMLElement, options: Partial<Options>) => {
9
+ _popper.value = createPopper(reference, popper, options)
10
+ }
11
+
12
+ const destroyPopper = () => {
13
+ if (_popper.value) {
14
+ _popper.value.destroy()
15
+ }
16
+
17
+ _popper.value = undefined
18
+ }
19
+
20
+ return {
21
+ popper: _popper.value,
22
+ initPopper,
23
+ destroyPopper,
24
+ }
25
+ }
package/src/types.ts CHANGED
@@ -35,7 +35,7 @@ export type Placements =
35
35
  | 'left-start'
36
36
  | 'left'
37
37
  | 'left-end'
38
- | undefined
38
+ | string
39
39
 
40
40
  export type Shapes =
41
41
  | 'rounded'
@@ -0,0 +1,18 @@
1
+ import { Placement } from '@popperjs/core'
2
+ import isRTL from './isRTL'
3
+
4
+ const getRTLPlacement = (placement: string, element: HTMLDivElement | null): Placement => {
5
+ switch (placement) {
6
+ case 'right': {
7
+ return isRTL(element) ? 'left' : 'right'
8
+ }
9
+ case 'left': {
10
+ return isRTL(element) ? 'right' : 'left'
11
+ }
12
+ default: {
13
+ return placement as Placement
14
+ }
15
+ }
16
+ }
17
+
18
+ export default getRTLPlacement
@@ -1,6 +1,7 @@
1
+ import getRTLPlacement from './getRTLPlacement'
1
2
  import getUID from './getUID'
2
3
  import isInViewport from './isInViewport'
3
4
  import isObjectInArray from './isObjectInArray'
4
5
  import isRTL from './isRTL'
5
6
 
6
- export { getUID, isInViewport, isObjectInArray, isRTL }
7
+ export { getRTLPlacement, getUID, isInViewport, isObjectInArray, isRTL }
@@ -1,62 +0,0 @@
1
- import { onBeforeMount, ref, watch } from 'vue'
2
-
3
- const getStoredTheme = (localStorageItemName: string) =>
4
- typeof window !== 'undefined' && localStorage.getItem(localStorageItemName)
5
- const setStoredTheme = (localStorageItemName: string, colorMode: string) =>
6
- localStorage.setItem(localStorageItemName, colorMode)
7
-
8
- const getPreferredColorScheme = (localStorageItemName: string) => {
9
- if (typeof window === 'undefined') {
10
- return
11
- }
12
-
13
- const storedTheme = getStoredTheme(localStorageItemName)
14
-
15
- if (storedTheme) {
16
- return storedTheme
17
- }
18
-
19
- return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'
20
- }
21
-
22
- const setTheme = (colorMode: string) => {
23
- document.documentElement.dataset.coreuiTheme =
24
- colorMode === 'auto' && window.matchMedia('(prefers-color-scheme: dark)').matches
25
- ? 'dark'
26
- : colorMode
27
-
28
- const event = new Event('ColorSchemeChange')
29
- document.documentElement.dispatchEvent(event)
30
- }
31
-
32
- export const useColorModes = (localStorageItemName = 'coreui-vue-color-scheme') => {
33
- const colorMode = ref(getPreferredColorScheme(localStorageItemName))
34
-
35
- watch(colorMode, () => {
36
- if (colorMode.value) {
37
- setStoredTheme(localStorageItemName, colorMode.value)
38
- setTheme(colorMode.value)
39
- }
40
- })
41
-
42
- onBeforeMount(() => {
43
- if (typeof getStoredTheme(localStorageItemName) === 'string' && colorMode.value) {
44
- setTheme(colorMode.value)
45
- }
46
-
47
- window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => {
48
- const storedTheme = getStoredTheme(localStorageItemName)
49
- if (storedTheme !== 'light' && storedTheme !== 'dark' && colorMode.value) {
50
- setTheme(colorMode.value)
51
- }
52
- })
53
- })
54
-
55
- return {
56
- getColorMode: () => colorMode.value,
57
- isColorModeSet: () => Boolean(getStoredTheme(localStorageItemName)),
58
- setColorMode: (mode: string) => {
59
- colorMode.value = mode
60
- },
61
- }
62
- }