@bobbykim/manguito-theme 0.6.0 → 0.7.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.
@@ -1,9 +1,9 @@
1
1
  <script setup lang="ts">
2
- import { ref, watch, Transition } from 'vue'
3
- import type { CollapseEvent } from './index.types'
2
+ import { ref, watch, Transition, onMounted, onBeforeUnmount } from 'vue'
3
+ import { observeVisibleAttr } from '../composables'
4
+
4
5
  const props = withDefaults(
5
6
  defineProps<{
6
- collapseId: string
7
7
  accordion?: string
8
8
  className?: string
9
9
  visible?: boolean
@@ -13,12 +13,24 @@ const props = withDefaults(
13
13
  visible: false,
14
14
  }
15
15
  )
16
- const emit = defineEmits(['toggle'])
16
+ const emit = defineEmits(['open', 'close'])
17
+ const collapseRef = ref<HTMLElement | undefined>()
17
18
  const toggle = ref<boolean>(props.visible)
18
19
 
19
- const handleToggleEvent = (e: Event): void => {
20
+ const toggleCollapse = (): void => {
20
21
  toggle.value = !toggle.value
21
- emit('toggle', { ...e, visible: toggle.value } as CollapseEvent)
22
+ }
23
+ const openCollapse = (): void => {
24
+ toggle.value = true
25
+ }
26
+ const closeCollapse = (): void => {
27
+ toggle.value = false
28
+ }
29
+ const emitOpenEvent = () => {
30
+ emit('open', { visible: true })
31
+ }
32
+ const emitCloseEvent = () => {
33
+ emit('close', { visible: false })
22
34
  }
23
35
 
24
36
  /**
@@ -45,30 +57,49 @@ const onLeave = (el: any) => {
45
57
  el.style.opacity = '0'
46
58
  }
47
59
 
60
+ // set nutation observer watching `visible` attribute in element
61
+ const handleVisibility = (visible: boolean = false) => {
62
+ toggle.value = visible
63
+ }
64
+ const observer = observeVisibleAttr(handleVisibility)
65
+
48
66
  watch(
49
67
  () => props.visible,
50
68
  (newValue) => {
51
69
  toggle.value = newValue
52
70
  }
53
71
  )
72
+ watch(toggle, (newValue) => {
73
+ if (newValue === true) {
74
+ emitOpenEvent()
75
+ } else if (newValue === false) {
76
+ emitCloseEvent()
77
+ }
78
+ })
79
+ defineExpose({
80
+ toggle: toggleCollapse,
81
+ close: closeCollapse,
82
+ open: openCollapse,
83
+ })
84
+ onMounted(() => {
85
+ if (collapseRef.value) {
86
+ observer.observe(collapseRef.value, { attributes: true })
87
+ }
88
+ })
89
+ onBeforeUnmount(() => {
90
+ observer.disconnect()
91
+ })
54
92
  </script>
55
93
 
56
94
  <template>
57
- <div>
58
- <button
59
- :id="collapseId"
60
- @click="handleToggleEvent"
61
- class="hidden"
62
- :accordion="accordion"
63
- :visible="toggle"
64
- ></button>
95
+ <div :accordion="accordion" :visible="toggle" ref="collapseRef">
65
96
  <transition
66
97
  name="collapse"
67
98
  tag="div"
68
99
  @enter="onEnter"
69
100
  @after-enter="onAfterEnter"
70
101
  @leave="onLeave"
71
- class="overflow-hidden"
102
+ class="overflow-y-clip"
72
103
  >
73
104
  <div v-show="toggle">
74
105
  <div :class="[className]">
@@ -1,3 +1,3 @@
1
- export interface CollapseEvent extends Event {
1
+ export interface CollapseEvent {
2
2
  visible: boolean
3
3
  }
@@ -0,0 +1 @@
1
+ export * from './observeVisible'
@@ -0,0 +1,24 @@
1
+ export const observeVisibleAttr = (fn: (...args: any[]) => void) => {
2
+ const observer = new MutationObserver((mutations) => {
3
+ let changed = false
4
+ for (let i = 0; i < mutations.length && !changed; i++) {
5
+ const mutation = mutations[i]
6
+ const mutationType = mutation.type
7
+ const mutationAttribute = mutation.attributeName
8
+ const mutationTarget = mutation.target
9
+ if (mutationType === 'attributes') {
10
+ changed = true
11
+ } else if (mutationAttribute === 'visible') {
12
+ changed = true
13
+ }
14
+ if (changed) {
15
+ const visibleAttr =
16
+ (mutationTarget as HTMLElement).getAttribute('visible') === 'true'
17
+ ? true
18
+ : false
19
+ fn(visibleAttr)
20
+ }
21
+ }
22
+ })
23
+ return observer
24
+ }
@@ -31,7 +31,15 @@ export const vToggle: Directive = {
31
31
  } else {
32
32
  target = document.getElementById(binding.arg as string)!
33
33
  }
34
- target.click()
34
+ if (!target) {
35
+ return
36
+ }
37
+ if (target.hasAttribute('visible') === false) {
38
+ return
39
+ }
40
+ const targetAttr = target.getAttribute('visible')
41
+ const attrAfterToggle = targetAttr === 'true' ? 'false' : 'true'
42
+ target.setAttribute('visible', attrAfterToggle)
35
43
  return
36
44
  }
37
45
  el.addEventListener('click', el.__ClickToggleHandler)
@@ -43,6 +51,37 @@ export const vToggle: Directive = {
43
51
 
44
52
  export const vCollapse: Directive = {
45
53
  mounted(el, binding) {
54
+ // el.__HandleToggler = (event: Event): void => {
55
+ // const eTarget = event.target as HTMLElement
56
+ // let target: HTMLElement
57
+ // if (eTarget.tagName === 'A') {
58
+ // const targetId = eTarget.getAttribute('href')
59
+ // const formattedTargetId =
60
+ // targetId?.charAt(0) === '#' ? targetId.substring(1) : targetId
61
+ // target = document.getElementById(formattedTargetId as string)!
62
+ // } else {
63
+ // target = document.getElementById(binding.arg as string) as HTMLElement
64
+ // }
65
+ // if (!target.hasAttribute('accordion')) {
66
+ // // run when it is not accordion component case
67
+ // target.click()
68
+ // return
69
+ // }
70
+ // const accordionName = target.getAttribute('accordion')
71
+ // const accordionList: NodeListOf<HTMLElement> = document.querySelectorAll(
72
+ // `button[accordion="${accordionName}"]`
73
+ // )
74
+ // // loop through each accordion items and handle reaction for each case
75
+ // for (let i = 0; i < accordionList.length; i++) {
76
+ // const isVisible = accordionList[i].getAttribute('visible')
77
+ // if (accordionList[i].id !== target.id && isVisible === 'true') {
78
+ // accordionList[i].click()
79
+ // }
80
+ // if (accordionList[i].id === target.id) {
81
+ // accordionList[i].click()
82
+ // }
83
+ // }
84
+ // }
46
85
  el.__HandleToggler = (event: Event): void => {
47
86
  const eTarget = event.target as HTMLElement
48
87
  let target: HTMLElement
@@ -54,23 +93,36 @@ export const vCollapse: Directive = {
54
93
  } else {
55
94
  target = document.getElementById(binding.arg as string) as HTMLElement
56
95
  }
96
+ if (!target) {
97
+ return
98
+ }
99
+ if (target.hasAttribute('visible') === false) {
100
+ return
101
+ }
57
102
  if (!target.hasAttribute('accordion')) {
58
103
  // run when it is not accordion component case
59
- target.click()
104
+ const targetAttr = target.getAttribute('visible')
105
+ const attrAfterToggle = targetAttr === 'true' ? 'false' : 'true'
106
+ target.setAttribute('visible', attrAfterToggle)
107
+ // target.click()
60
108
  return
61
109
  }
62
110
  const accordionName = target.getAttribute('accordion')
63
111
  const accordionList: NodeListOf<HTMLElement> = document.querySelectorAll(
64
- `button[accordion="${accordionName}"]`
112
+ `div[accordion="${accordionName}"]`
65
113
  )
66
114
  // loop through each accordion items and handle reaction for each case
67
115
  for (let i = 0; i < accordionList.length; i++) {
68
116
  const isVisible = accordionList[i].getAttribute('visible')
69
117
  if (accordionList[i].id !== target.id && isVisible === 'true') {
70
- accordionList[i].click()
118
+ accordionList[i].setAttribute('visible', 'false')
119
+ // accordionList[i].click()
71
120
  }
72
121
  if (accordionList[i].id === target.id) {
73
- accordionList[i].click()
122
+ const targetAttr = target.getAttribute('visible')
123
+ const attrAfterToggle = targetAttr === 'true' ? 'false' : 'true'
124
+ target.setAttribute('visible', attrAfterToggle)
125
+ // accordionList[i].click()
74
126
  }
75
127
  }
76
128
  }
@@ -1,14 +1,21 @@
1
1
  <script setup lang="ts">
2
- import { ref, computed, watch, Transition } from 'vue'
2
+ import {
3
+ ref,
4
+ computed,
5
+ watch,
6
+ Transition,
7
+ onMounted,
8
+ onBeforeUnmount,
9
+ } from 'vue'
3
10
  import generateClass, {
4
11
  ColorPalette,
5
12
  vClickOutside,
6
13
  VerticalAlignment,
7
14
  } from '../../'
15
+ import { observeVisibleAttr } from '../composables'
8
16
 
9
17
  const props = withDefaults(
10
18
  defineProps<{
11
- modalId: string
12
19
  title?: string
13
20
  titleColor?: ColorPalette
14
21
  className?: string
@@ -31,23 +38,31 @@ const props = withDefaults(
31
38
  }
32
39
  )
33
40
 
34
- const emit = defineEmits(['toggle', 'close'])
41
+ const emit = defineEmits(['open', 'close'])
42
+ const modalRef = ref<HTMLElement | undefined>()
35
43
  const toggle = ref<boolean>(props.visible)
36
44
  const toggleComplete = ref<boolean>(false)
37
45
 
38
- const handleToggleEvent = (e: Event): void => {
46
+ // const handleToggleEvent = (): void => {
47
+ // toggle.value = !toggle.value
48
+ // }
49
+ const toggleModal = (): void => {
39
50
  toggle.value = !toggle.value
40
- emit('toggle', e)
41
51
  }
42
52
  const openModal = (): void => {
43
53
  toggle.value = true
44
54
  }
45
- const closeModal = (e: Event): void => {
55
+ const closeModal = (): void => {
46
56
  if (toggleComplete.value === true) {
47
57
  toggle.value = false
48
- emit('close', e)
49
58
  }
50
59
  }
60
+ const emitOpenEvent = () => {
61
+ emit('open', { visible: true })
62
+ }
63
+ const emitCloseEvent = () => {
64
+ emit('close', { visible: false })
65
+ }
51
66
  const handlePlacementVar = computed(() => {
52
67
  let placementVariable: number
53
68
  if (props.placement === 'top') {
@@ -70,22 +85,44 @@ const onAfterEnter = () => {
70
85
  const onAfterLeave = () => {
71
86
  toggleComplete.value = false
72
87
  }
88
+
89
+ // set nutation observer watching `visible` attribute in element
90
+ const handleVisibility = (visible: boolean = false) => {
91
+ toggle.value = visible
92
+ }
93
+ const observer = observeVisibleAttr(handleVisibility)
94
+
73
95
  watch(
74
96
  () => props.visible,
75
97
  (newValue) => {
76
98
  toggle.value = newValue
77
99
  }
78
100
  )
101
+ watch(toggle, (newValue) => {
102
+ if (newValue === true) {
103
+ emitOpenEvent()
104
+ } else if (newValue === false && toggleComplete.value === true) {
105
+ emitCloseEvent()
106
+ }
107
+ })
79
108
  defineExpose({
80
- toggle: handleToggleEvent,
109
+ toggle: toggleModal,
81
110
  close: closeModal,
82
111
  open: openModal,
83
112
  })
113
+ onMounted(() => {
114
+ if (modalRef.value) {
115
+ observer.observe(modalRef.value, { attributes: true })
116
+ }
117
+ })
118
+ onBeforeUnmount(() => {
119
+ observer.disconnect()
120
+ })
84
121
  </script>
85
122
 
86
123
  <template>
87
- <div :style="handlePlacementVar">
88
- <button :id="modalId" @click="handleToggleEvent" class="hidden"></button>
124
+ <div :style="handlePlacementVar" :visible="toggle" ref="modalRef">
125
+ <!-- <button :id="modalId" @click="handleToggleEvent" class="hidden"></button> -->
89
126
  <Transition name="fade" appear tag="div" v-if="!noBackdrop">
90
127
  <section
91
128
  v-if="toggle"
@@ -1,10 +1,17 @@
1
1
  <script setup lang="ts">
2
- import { ref, computed, watch, Transition } from 'vue'
2
+ import {
3
+ ref,
4
+ computed,
5
+ watch,
6
+ Transition,
7
+ onMounted,
8
+ onBeforeUnmount,
9
+ } from 'vue'
3
10
  import generateClass, { ColorPalette, vClickOutside, DirectionX } from '../../'
11
+ import { observeVisibleAttr } from '../composables'
4
12
 
5
13
  const props = withDefaults(
6
14
  defineProps<{
7
- sidebarId: string
8
15
  title?: string
9
16
  titleColor?: ColorPalette
10
17
  className?: string
@@ -29,15 +36,18 @@ const props = withDefaults(
29
36
  }
30
37
  )
31
38
 
32
- const emit = defineEmits(['toggle', 'close'])
39
+ const emit = defineEmits(['open', 'close'])
33
40
  const toggle = ref<boolean>(props.visible)
34
41
  const toggleComplete = ref<boolean>(false)
42
+ const sidebarRef = ref<HTMLElement | undefined>()
35
43
  const headerRef = ref<HTMLElement>()
36
44
  const footerRef = ref<HTMLElement>()
37
45
 
38
46
  const handleToggleEvent = (e: Event): void => {
39
47
  toggle.value = !toggle.value
40
- emit('toggle', e)
48
+ }
49
+ const toggleSidebar = (): void => {
50
+ toggle.value = !toggle.value
41
51
  }
42
52
  const openSidebar = (): void => {
43
53
  toggle.value = true
@@ -45,9 +55,14 @@ const openSidebar = (): void => {
45
55
  const closeSidebar = (e: Event): void => {
46
56
  if (toggleComplete.value === true) {
47
57
  toggle.value = false
48
- emit('close', e)
49
58
  }
50
59
  }
60
+ const emitOpenEvent = () => {
61
+ emit('open', { visible: true })
62
+ }
63
+ const emitCloseEvent = () => {
64
+ emit('close', { visible: false })
65
+ }
51
66
  const handleStyleVariables = computed(() => {
52
67
  return {
53
68
  '--sidebar-width': `${props.width}px`,
@@ -75,22 +90,44 @@ const onAfterEnter = () => {
75
90
  const onAfterLeave = () => {
76
91
  toggleComplete.value = false
77
92
  }
93
+
94
+ // set nutation observer watching `visible` attribute in element
95
+ const handleVisibility = (visible: boolean = false) => {
96
+ toggle.value = visible
97
+ }
98
+ const observer = observeVisibleAttr(handleVisibility)
99
+
78
100
  watch(
79
101
  () => props.visible,
80
102
  (newValue) => {
81
103
  toggle.value = newValue
82
104
  }
83
105
  )
106
+ watch(toggle, (newValue) => {
107
+ if (newValue === true) {
108
+ emitOpenEvent()
109
+ } else if (newValue === false && toggleComplete.value === true) {
110
+ emitCloseEvent()
111
+ }
112
+ })
84
113
  defineExpose({
85
- toggle: handleToggleEvent,
114
+ toggle: toggleSidebar,
86
115
  open: openSidebar,
87
116
  close: closeSidebar,
88
117
  })
118
+ onMounted(() => {
119
+ if (sidebarRef.value) {
120
+ observer.observe(sidebarRef.value, { attributes: true })
121
+ }
122
+ })
123
+ onBeforeUnmount(() => {
124
+ observer.disconnect()
125
+ })
89
126
  </script>
90
127
 
91
128
  <template>
92
- <div :style="handleStyleVariables">
93
- <button :id="sidebarId" @click="handleToggleEvent" class="hidden"></button>
129
+ <div :style="handleStyleVariables" :visible="toggle" ref="sidebarRef">
130
+ <!-- <button :id="sidebarId" @click="handleToggleEvent" class="hidden"></button> -->
94
131
  <Transition name="fade" appear tag="div" v-if="!noBackdrop">
95
132
  <section
96
133
  v-if="toggle"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bobbykim/manguito-theme",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
4
  "description": "main theme file for manguito components library. Other MCL components will need to import this file to run.",
5
5
  "type": "module",
6
6
  "main": "index.ts",
@@ -17,5 +17,5 @@
17
17
  "url": "https://github.com/bobbykim89/manguito-component-library.git"
18
18
  },
19
19
  "license": "MIT",
20
- "gitHead": "eb0833dd47a9dd0bb326bee28daf2bee4e421279"
20
+ "gitHead": "576d9aa7a55803b0dd7391bf81d00081848135ec"
21
21
  }
package/tsconfig.json ADDED
@@ -0,0 +1,8 @@
1
+ {
2
+ "extends": "../../../tsconfig.json",
3
+ "include": ["./**/*.vue", "./**/*.ts"],
4
+ "compilerOptions": {
5
+ "declaration": true,
6
+ "emitDeclarationOnly": true
7
+ }
8
+ }