@policystudio/policy-studio-ui-vue 1.1.90-beta.75 → 1.1.90-beta.77

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.
@@ -4013,53 +4013,15 @@ video {
4013
4013
  min-height: 27px;
4014
4014
  font-size: 0.875rem;
4015
4015
  }
4016
- .psui-el-dropdown-menu-dialog-wrapper {
4017
- position: fixed;
4018
- }
4019
4016
  .psui-el-dropdown-menu-dialog-wrapper {
4020
4017
  z-index: 50;
4021
4018
  }
4022
4019
  .psui-el-dropdown-menu-dialog-wrapper {
4023
- display: none;
4024
- }
4025
- .psui-el-dropdown-menu-dialog-wrapper {
4026
- width: auto;
4027
- }
4028
- .psui-el-dropdown-menu-dialog-wrapper {
4029
- transform-origin: top right;
4020
+ height: auto;
4030
4021
  }
4031
4022
  .psui-el-dropdown-menu-dialog-wrapper {
4032
4023
  overflow: auto;
4033
4024
  }
4034
- .psui-el-dropdown-menu-dialog-wrapper {
4035
- border-radius: 0.375rem;
4036
- }
4037
- .psui-el-dropdown-menu-dialog-wrapper {
4038
- --tw-bg-opacity: 1;
4039
- background-color: rgb(255, 255, 255, var(--tw-bg-opacity, 1));
4040
- }
4041
- .psui-el-dropdown-menu-dialog-wrapper {
4042
- opacity: 0;
4043
- }
4044
- .psui-el-dropdown-menu-dialog-wrapper {
4045
- --tw-shadow: 0px 0px 8px rgba(0, 0, 0, 0.04), 0px 5px 6px rgba(0, 0, 0, 0.1);
4046
- --tw-shadow-colored: 0px 0px 8px var(--tw-shadow-color), 0px 5px 6px var(--tw-shadow-color);
4047
- box-shadow: var(--tw-ring-offset-shadow, 0 0 rgba(0, 0, 0, 0)), var(--tw-ring-shadow, 0 0 rgba(0, 0, 0, 0)), var(--tw-shadow);
4048
- }
4049
- .psui-el-dropdown-menu-dialog-wrapper {
4050
- transition-property: opacity;
4051
- transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
4052
- transition-duration: 150ms;
4053
- }
4054
- .psui-el-dropdown-menu-dialog-wrapper {
4055
- transition-duration: 100ms;
4056
- }
4057
- .psui-el-dropdown-menu-dialog-wrapper {
4058
- transition-timing-function: cubic-bezier(0.4, 0, 1, 1);
4059
- }
4060
- .psui-el-dropdown-menu-dialog-wrapper-dialog {
4061
- width: 100%;
4062
- }
4063
4025
 
4064
4026
  .psui-el-dropdown-menu-list {
4065
4027
  margin-top: 1rem;
@@ -6359,6 +6321,10 @@ video {
6359
6321
  justify-self: center;
6360
6322
  }
6361
6323
 
6324
+ .psui-rounded {
6325
+ border-radius: 0.25rem;
6326
+ }
6327
+
6362
6328
  .psui-rounded-md {
6363
6329
  border-radius: 0.375rem;
6364
6330
  }
@@ -6403,6 +6369,11 @@ video {
6403
6369
  background-color: rgb(214, 92, 90, var(--tw-bg-opacity, 1));
6404
6370
  }
6405
6371
 
6372
+ .psui-bg-white {
6373
+ --tw-bg-opacity: 1;
6374
+ background-color: rgb(255, 255, 255, var(--tw-bg-opacity, 1));
6375
+ }
6376
+
6406
6377
  .psui-bg-yellow-20 {
6407
6378
  --tw-bg-opacity: 1;
6408
6379
  background-color: rgb(237, 171, 62, var(--tw-bg-opacity, 1));
@@ -6548,6 +6519,12 @@ video {
6548
6519
  opacity: 0.75;
6549
6520
  }
6550
6521
 
6522
+ .psui-shadow-elevation-20 {
6523
+ --tw-shadow: 0px 0px 8px rgba(0, 0, 0, 0.04), 0px 5px 6px rgba(0, 0, 0, 0.1);
6524
+ --tw-shadow-colored: 0px 0px 8px var(--tw-shadow-color), 0px 5px 6px var(--tw-shadow-color);
6525
+ box-shadow: var(--tw-ring-offset-shadow, 0 0 rgba(0, 0, 0, 0)), var(--tw-ring-shadow, 0 0 rgba(0, 0, 0, 0)), var(--tw-shadow);
6526
+ }
6527
+
6551
6528
  .psui-transition {
6552
6529
  transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, -webkit-backdrop-filter;
6553
6530
  transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@policystudio/policy-studio-ui-vue",
3
- "version": "1.1.90-beta.75",
3
+ "version": "1.1.90-beta.77",
4
4
  "description": "Policy Studio UI",
5
5
  "author": "Policy Studio Team",
6
6
  "scripts": {
@@ -15,10 +15,12 @@
15
15
  "main": "dist/index.js",
16
16
  "types": "src/types/index.d.ts",
17
17
  "dependencies": {
18
+ "@floating-ui/vue": "^1.1.9",
18
19
  "@vue/compat": "^3.4.5",
19
20
  "core-js": "^3.6.5",
20
21
  "v-tooltip": "^2.1.3",
21
- "vue": "^3.4.5"
22
+ "vue": "^3.4.5",
23
+ "vue2-teleport": "^1.1.4"
22
24
  },
23
25
  "devDependencies": {
24
26
  "@typescript-eslint/eslint-plugin": "^5.4.0",
@@ -13,11 +13,7 @@
13
13
  }
14
14
 
15
15
  &-dialog-wrapper {
16
- @apply psui-hidden psui-origin-top-right psui-bg-white psui-fixed psui-w-auto psui-rounded-md psui-z-50 psui-opacity-0 psui-shadow-elevation-20 psui-overflow-auto psui-transition-opacity psui-duration-100 psui-ease-in;
17
-
18
- &-dialog {
19
- @apply psui-w-full;
20
- }
16
+ @apply psui-z-50 psui-overflow-auto psui-h-auto;
21
17
  }
22
18
  }
23
19
  }
@@ -1,212 +1,127 @@
1
1
  <template>
2
2
  <div
3
- ref="PSDropdown"
4
3
  class="psui-el-dropdown-menu"
5
- :class="{ 'is-open': show.value }"
6
- v-click-outside="close"
7
4
  >
8
5
  <div
9
6
  ref="PSDropdownTrigger"
10
- v-if="$slots.dropdownTrigger"
11
- @click="show && !toggleWhenActive ? '' : toggle($event)"
12
- >
13
- <slot name="dropdownTrigger" />
14
- </div>
15
-
16
- <button
17
- v-else
18
- @click="show && !toggleWhenActive ? '' : toggle($event)"
19
- type="button"
20
- :id="id.value"
21
- aria-haspopup="true"
22
- aria-expanded="true"
23
- ref="PSDropdownTrigger"
7
+ @click="toggle"
24
8
  >
25
9
  <slot
26
- v-if="show.value && $slots.buttonLabelOnShow"
27
- name="buttonLabelOnShow"
10
+ v-if="$slots.dropdownTrigger"
11
+ name="dropdownTrigger"
28
12
  />
29
- <slot
13
+ <button
30
14
  v-else
31
- name="buttonLabel"
32
- />
33
- </button>
34
- <div
35
- ref="PSDropdownDialog"
36
- role="menu"
37
- class="psui-el-dropdown-menu-dialog-wrapper"
38
- aria-orientation="vertical"
39
- :aria-labelledby="id.value"
40
- :style="{ minWidth: minWidthDropDown }"
41
- >
42
- <div class="psui-el-dropdown-menu-dialog">
43
- <slot name="items" />
44
- </div>
15
+ type="button"
16
+ :aria-expanded="show"
17
+ >
18
+ <slot
19
+ v-if="show && $slots.buttonLabelOnShow"
20
+ name="buttonLabelOnShow"
21
+ />
22
+ <slot
23
+ v-else
24
+ name="buttonLabel"
25
+ />
26
+ </button>
45
27
  </div>
28
+
29
+
30
+ <Teleport to="body">
31
+ <Transition name="fade">
32
+ <div
33
+ v-if="show"
34
+ ref="PSDropdownFloating"
35
+ role="menu"
36
+ class="psui-el-dropdown-menu-dialog-wrapper"
37
+ :class="contentCss"
38
+ aria-orientation="vertical"
39
+ :style="floatingStyles"
40
+ v-click-outside="close"
41
+ >
42
+ <slot name="items" />
43
+ </div>
44
+ </Transition>
45
+ </Teleport>
46
46
  </div>
47
47
  </template>
48
48
 
49
49
  <script setup>
50
50
  // Figma - 2.3 Dropdown with category divider https://www.figma.com/file/Tto8hrNlSfuPcwd1pfqogF/%E2%9A%A1%EF%B8%8F-Design-System?node-id=1768%3A64886
51
-
52
- import { randomString, getParentScrollableEl } from '../../util/GeneralFunctions.js'
53
-
54
- import { ref, onBeforeUnmount } from 'vue'
55
-
56
- defineExpose({
57
- close:() => close(),
58
- open:() => open(),
59
- })
51
+ import {
52
+ useFloating,
53
+ autoUpdate,
54
+ offset,
55
+ flip,
56
+ shift,
57
+ size
58
+ } from '@floating-ui/vue'
59
+
60
+ import { ref, defineProps } from 'vue'
61
+ import Teleport from 'vue2-teleport'
60
62
 
61
63
  const props = defineProps({
62
- /**
63
- * It sets a minimun width for the dropdown menu.
64
- */
65
- minWidthDropDown: {
66
- type: String,
67
- default: '240px',
68
- },
69
- /**
70
- * It's a boolean responsible for showing a slot within the html tag button.
71
- */
72
- buttonLabelOnShow: {
73
- type: Boolean,
74
- default: false,
64
+ disabled: {type: Boolean, default: false},
65
+ placement: { type: String, default: 'bottom-start' },
66
+ offsetVal: { type: Number, default: 4 },
67
+ width: {
68
+ type: [Number, String],
69
+ default: null
75
70
  },
76
- /**
77
- * It's a property responsible for toggling the dropdown menu. default: true.
78
- */
79
- toggleWhenActive: {
80
- type: Boolean,
81
- default: true,
71
+ height: {
72
+ type: [Number, String],
73
+ default: 'auto'
82
74
  },
83
- /**
84
- * Disable the toogle on click. default: false.
85
- */
86
- disabled: {
87
- type: Boolean,
88
- default: false,
89
- },
90
- /**
91
- * It sets the vertical and horizontal position.
92
- */
93
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment, vue/require-default-prop
94
- position: {
75
+ contentCss: {
95
76
  type: String,
96
- validator: (value) => ['custom'].includes(value),
97
- },
77
+ default: 'psui-rounded psui-bg-white psui-shadow-elevation-20'
78
+ }
98
79
  })
99
80
 
100
81
  const emit = defineEmits(['open', 'close'])
101
82
 
102
83
  const show = ref(false)
103
- const id = ref(randomString(8))
104
- // const marginLeft = ref('-0px')
105
- const scrollableParentEl = ref(null)
106
- const PSDropdown = ref(null)
107
- const PSDropdownDialog = ref(null)
108
- const PSDropdownTrigger = ref(null)
109
-
110
- // const getMaxWidth = computed(() => {
111
- // let bounds = PSDropdown.getBoundingClientRect()
112
- // return document.documentElement.clientWidth - bounds['left'] - 30
113
- // })
114
84
 
115
- onBeforeUnmount(() => {
116
- unwatchParentScrolling()
85
+ const PSDropdownTrigger = ref(null)
86
+ const PSDropdownFloating = ref(null)
87
+
88
+ const { floatingStyles } = useFloating(PSDropdownTrigger, PSDropdownFloating, {
89
+ placement: props.placement,
90
+ whileElementsMounted: autoUpdate,
91
+ middleware: [
92
+ offset(props.offsetVal),
93
+ flip(),
94
+ shift(),
95
+ size({
96
+ apply({rects, elements}) {
97
+ const customWidth = props.width ?? rects.reference.width
98
+ Object.assign(elements.floating.style, {
99
+ width: `${customWidth}px`,
100
+ ...(typeof height == 'string' ? {maxHeight: props.height} : {maxHeight : `${props.height}px`})
101
+ })
102
+ },
103
+ })
104
+ ],
117
105
  })
118
106
 
119
- const toggle = (event) => {
120
- if (props.disabled) return
121
- if (!show.value) {
122
- open()
123
- } else {
124
- close()
125
- }
126
- event.stopPropagation()
127
- }
128
-
129
- const handleEsc = (evt) => {
130
- if (show.value && evt.keyCode === 27) close()
131
- }
132
-
133
107
  const open = () => {
134
- emit('open')
135
108
  show.value = true
136
- if (PSDropdownDialog.value) {
137
- PSDropdownDialog.value.style.opacity = 0
138
- PSDropdownDialog.value.style.display = 'block'
139
- }
140
- setTimeout(() => {
141
- updatePosition()
142
- watchParentScrolling()
143
- document.addEventListener('keyup', handleEsc)
144
- window.addEventListener('resize', updatePosition)
145
- // window.addEventListener('click', clickOutside)
146
- }, 10)
109
+ emit('open')
147
110
  }
148
111
 
149
112
  const close = () => {
150
- if (show.value == true) {
151
- emit('close')
152
- if (PSDropdownDialog.value !== null) {
153
- PSDropdownDialog.value.style.display = 'none'
154
- PSDropdownDialog.value.style.opacity = 0
155
- }
156
- show.value = false
157
- unwatchParentScrolling()
158
- }
159
- document.removeEventListener('keyup', handleEsc)
160
- document.removeEventListener('resize', updatePosition)
161
- // document.removeEventListener('click', clickOutside)
162
- }
163
-
164
- const watchParentScrolling = () => {
165
- scrollableParentEl.value = getParentScrollableEl(PSDropdown.value)
166
- if (scrollableParentEl.value) {
167
- scrollableParentEl.value.addEventListener('scroll', updatePosition)
168
- }
113
+ show.value = false
114
+ emit('close')
169
115
  }
170
116
 
171
- const unwatchParentScrolling = () => {
172
- if (scrollableParentEl.value) {
173
- scrollableParentEl.value.removeEventListener('scroll', updatePosition())
174
- }
175
- }
176
-
177
- const updatePosition = () => {
178
- if (PSDropdownDialog.value === null || PSDropdownTrigger.value === null) return
179
-
180
- const rectTrigger = PSDropdownTrigger.value.getBoundingClientRect()
181
- const rectDialog = PSDropdownDialog.value.getBoundingClientRect()
182
- const windowWidth = document.documentElement.clientWidth
183
-
184
- PSDropdownDialog.value.style.position = 'fixed'
185
- PSDropdownDialog.value.style.top = `${rectTrigger.y + rectTrigger.height}px`
186
- PSDropdownDialog.value.style.minWidth = `${rectTrigger.width}px`
187
-
188
- if (rectTrigger.x + rectDialog.width + 20 > windowWidth) {
189
- PSDropdownDialog.value.style.left = `${windowWidth - rectDialog.width - 30}px`
190
- } else {
191
- PSDropdownDialog.value.style.left = `${rectTrigger.x}px`
192
- }
193
-
194
- if (props.position == 'custom') {
195
- PSDropdownDialog.value.style.top = `${rectTrigger.y}px`
196
- PSDropdownDialog.value.style.left = `${rectTrigger.x + 100}px`
197
- }
117
+ const toggle = (event) => {
118
+ if (props.disabled) return
198
119
 
199
- if (rectTrigger.top < 10) {
200
- close()
201
- console.warn('The dropdown are too close from the top of the page')
202
- return
203
- }
120
+ if (event) event.stopPropagation()
204
121
 
205
- setTimeout(() => {
206
- if(PSDropdownDialog.value){
207
- PSDropdownDialog.value.style.opacity = 1
208
- }
209
- }, 10)
122
+ show.value ? close() : open()
123
+
210
124
  }
211
125
 
126
+ defineExpose({ open, close })
212
127
  </script>