@policystudio/policy-studio-ui-vue 1.1.90-rc.4 → 1.1.90-rc.5

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.
@@ -4035,57 +4035,15 @@ video {
4035
4035
  min-height: 27px;
4036
4036
  font-size: 0.875rem;
4037
4037
  }
4038
- .psui-el-dropdown-menu button:focus {
4039
- outline: none;
4040
- box-shadow: 0 0 0 3px rgba(66, 153, 225, 0.5);
4041
- }
4042
- .psui-el-dropdown-menu-dialog-wrapper {
4043
- position: fixed;
4044
- }
4045
4038
  .psui-el-dropdown-menu-dialog-wrapper {
4046
4039
  z-index: 50;
4047
4040
  }
4048
4041
  .psui-el-dropdown-menu-dialog-wrapper {
4049
- display: none;
4050
- }
4051
- .psui-el-dropdown-menu-dialog-wrapper {
4052
- width: auto;
4053
- }
4054
- .psui-el-dropdown-menu-dialog-wrapper {
4055
- transform-origin: top right;
4042
+ height: auto;
4056
4043
  }
4057
4044
  .psui-el-dropdown-menu-dialog-wrapper {
4058
4045
  overflow: auto;
4059
4046
  }
4060
- .psui-el-dropdown-menu-dialog-wrapper {
4061
- border-radius: 0.375rem;
4062
- }
4063
- .psui-el-dropdown-menu-dialog-wrapper {
4064
- --tw-bg-opacity: 1;
4065
- background-color: rgb(255, 255, 255, var(--tw-bg-opacity, 1));
4066
- }
4067
- .psui-el-dropdown-menu-dialog-wrapper {
4068
- opacity: 0;
4069
- }
4070
- .psui-el-dropdown-menu-dialog-wrapper {
4071
- --tw-shadow: 0px 0px 8px rgba(0, 0, 0, 0.04), 0px 5px 6px rgba(0, 0, 0, 0.1);
4072
- --tw-shadow-colored: 0px 0px 8px var(--tw-shadow-color), 0px 5px 6px var(--tw-shadow-color);
4073
- 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);
4074
- }
4075
- .psui-el-dropdown-menu-dialog-wrapper {
4076
- transition-property: all;
4077
- transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
4078
- transition-duration: 150ms;
4079
- }
4080
- .psui-el-dropdown-menu-dialog-wrapper {
4081
- transition-duration: 100ms;
4082
- }
4083
- .psui-el-dropdown-menu-dialog-wrapper {
4084
- transition-timing-function: cubic-bezier(0.4, 0, 1, 1);
4085
- }
4086
- .psui-el-dropdown-menu-dialog-wrapper-dialog {
4087
- width: 100%;
4088
- }
4089
4047
 
4090
4048
  .psui-el-dropdown-menu-list {
4091
4049
  margin-top: 1rem;
@@ -6385,6 +6343,10 @@ video {
6385
6343
  justify-self: center;
6386
6344
  }
6387
6345
 
6346
+ .psui-rounded {
6347
+ border-radius: 0.25rem;
6348
+ }
6349
+
6388
6350
  .psui-rounded-md {
6389
6351
  border-radius: 0.375rem;
6390
6352
  }
@@ -6429,6 +6391,11 @@ video {
6429
6391
  background-color: rgb(214, 92, 90, var(--tw-bg-opacity, 1));
6430
6392
  }
6431
6393
 
6394
+ .psui-bg-white {
6395
+ --tw-bg-opacity: 1;
6396
+ background-color: rgb(255, 255, 255, var(--tw-bg-opacity, 1));
6397
+ }
6398
+
6432
6399
  .psui-bg-yellow-20 {
6433
6400
  --tw-bg-opacity: 1;
6434
6401
  background-color: rgb(237, 171, 62, var(--tw-bg-opacity, 1));
@@ -6574,6 +6541,12 @@ video {
6574
6541
  opacity: 0.75;
6575
6542
  }
6576
6543
 
6544
+ .psui-shadow-elevation-20 {
6545
+ --tw-shadow: 0px 0px 8px rgba(0, 0, 0, 0.04), 0px 5px 6px rgba(0, 0, 0, 0.1);
6546
+ --tw-shadow-colored: 0px 0px 8px var(--tw-shadow-color), 0px 5px 6px var(--tw-shadow-color);
6547
+ 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);
6548
+ }
6549
+
6577
6550
  .psui-transition {
6578
6551
  transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, -webkit-backdrop-filter;
6579
6552
  transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter;
@@ -6582,10 +6555,6 @@ video {
6582
6555
  transition-duration: 150ms;
6583
6556
  }
6584
6557
 
6585
- .psui-duration-300 {
6586
- transition-duration: 300ms;
6587
- }
6588
-
6589
6558
  *:focus {
6590
6559
  outline: none;
6591
6560
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@policystudio/policy-studio-ui-vue",
3
- "version": "1.1.90-rc.4",
3
+ "version": "1.1.90-rc.5",
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",
@@ -10,19 +10,10 @@
10
10
  min-height: 27px;
11
11
  font-size: 0.875rem;
12
12
 
13
-
14
- &:focus {
15
- outline: none;
16
- box-shadow: 0 0 0 3px rgba(66, 153, 225, 0.5);
17
- }
18
13
  }
19
14
 
20
15
  &-dialog-wrapper {
21
- @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-transition-all psui-duration-100 psui-ease-in psui-overflow-auto;
22
-
23
- &-dialog {
24
- @apply psui-w-full;
25
- }
16
+ @apply psui-z-50 psui-overflow-auto psui-h-auto;
26
17
  }
27
18
  }
28
19
  }
@@ -1,218 +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 psui-duration-300"
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,
75
- },
76
- /**
77
- * It's a property responsible for toggling the dropdown menu. default: true.
78
- */
79
- toggleWhenActive: {
80
- type: Boolean,
81
- default: true,
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
82
70
  },
83
- /**
84
- * Disable the toogle on click. default: false.
85
- */
86
- disabled: {
87
- type: Boolean,
88
- default: false,
71
+ height: {
72
+ type: [Number, String],
73
+ default: 'auto'
89
74
  },
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
84
 
110
- // const getMaxWidth = computed(() => {
111
- // let bounds = PSDropdown.getBoundingClientRect()
112
- // return document.documentElement.clientWidth - bounds['left'] - 30
113
- // })
114
-
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
- }
169
- }
170
-
171
- const unwatchParentScrolling = () => {
172
- if (scrollableParentEl.value) {
173
- scrollableParentEl.value.removeEventListener('scroll', updatePosition())
174
- }
113
+ show.value = false
114
+ emit('close')
175
115
  }
176
116
 
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
 
212
- const clickOutside = (event) => {
213
- if (!show.value) return
214
- if (!PSDropdown.value == event.target || !PSDropdown.value?.contains(event.target)) {
215
- close()
216
- }
217
- }
126
+ defineExpose({ open, close })
218
127
  </script>
@@ -3,7 +3,10 @@
3
3
  class="psui-el-dialog"
4
4
  :class="getComponentClass"
5
5
  >
6
- <div class="psui-el-dialog-icon">
6
+ <div
7
+ v-if="hasIcon"
8
+ class="psui-el-dialog-icon"
9
+ >
7
10
  <i class="material-icons-round">{{ icon }}</i>
8
11
  </div>
9
12
  <div class="psui-el-dialog-wrapper">
@@ -71,6 +74,13 @@ const props = defineProps({
71
74
  type: String,
72
75
  default: 'info',
73
76
  },
77
+ /**
78
+ * It sets whether the icon should be displayed or not.
79
+ */
80
+ hasIcon: {
81
+ type: Boolean,
82
+ default: true,
83
+ },
74
84
  })
75
85
 
76
86
  const emit = defineEmits(['close'])