@policystudio/policy-studio-ui-vue 1.1.90-access.1 → 1.1.90-access.12

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,218 +1,134 @@
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="hasDropdownTrigger"
11
+ name="dropdownTrigger"
12
+ :show="show"
28
13
  />
29
- <slot
14
+ <button
30
15
  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>
16
+ type="button"
17
+ :aria-expanded="show"
18
+ >
19
+ <slot
20
+ v-if="show && $slots.buttonLabelOnShow"
21
+ name="buttonLabelOnShow"
22
+ />
23
+ <slot
24
+ v-else
25
+ name="buttonLabel"
26
+ />
27
+ </button>
45
28
  </div>
29
+ <Teleport to="body">
30
+ <Transition name="fade">
31
+ <div
32
+ v-if="show"
33
+ ref="PSDropdownFloating"
34
+ role="menu"
35
+ class="psui-el-dropdown-menu-dialog-wrapper"
36
+ :class="contentCss"
37
+ aria-orientation="vertical"
38
+ :style="floatingStyles"
39
+ v-click-outside="close"
40
+ >
41
+ <slot name="items" />
42
+ </div>
43
+ </Transition>
44
+ </Teleport>
46
45
  </div>
47
46
  </template>
48
47
 
49
48
  <script setup>
50
49
  // 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
- })
50
+ import {
51
+ useFloating,
52
+ autoUpdate,
53
+ offset,
54
+ flip,
55
+ shift,
56
+ size
57
+ } from '@floating-ui/vue'
58
+
59
+ import { ref, defineProps, useSlots, computed } from 'vue'
60
+ import Teleport from 'vue2-teleport'
60
61
 
61
62
  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,
63
+ disabled: {type: Boolean, default: false},
64
+ placement: { type: String, default: 'bottom-start' },
65
+ offsetVal: { type: Number, default: 4 },
66
+ width: {
67
+ type: [Number, String],
68
+ default: null
82
69
  },
83
- /**
84
- * Disable the toogle on click. default: false.
85
- */
86
- disabled: {
87
- type: Boolean,
88
- default: false,
70
+ height: {
71
+ type: [Number, String],
72
+ default: 'auto'
89
73
  },
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: {
74
+ contentCss: {
95
75
  type: String,
96
- validator: (value) => ['custom'].includes(value),
97
- },
76
+ default: 'psui-rounded psui-bg-white psui-shadow-elevation-20'
77
+ }
98
78
  })
99
79
 
100
80
  const emit = defineEmits(['open', 'close'])
101
81
 
102
- 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
- // })
82
+ const slots = useSlots()
114
83
 
115
- onBeforeUnmount(() => {
116
- unwatchParentScrolling()
84
+ const hasDropdownTrigger = computed(() => {
85
+ return !!slots.dropdownTrigger
117
86
  })
118
87
 
119
- const toggle = (event) => {
120
- if (props.disabled) return
121
- if (!show.value) {
122
- open()
123
- } else {
124
- close()
125
- }
126
- event.stopPropagation()
127
- }
88
+ const show = ref(false)
128
89
 
129
- const handleEsc = (evt) => {
130
- if (show.value && evt.keyCode === 27) close()
131
- }
90
+ const PSDropdownTrigger = ref(null)
91
+ const PSDropdownFloating = ref(null)
92
+
93
+ const { floatingStyles } = useFloating(PSDropdownTrigger, PSDropdownFloating, {
94
+ placement: props.placement,
95
+ whileElementsMounted: autoUpdate,
96
+ middleware: [
97
+ offset(props.offsetVal),
98
+ flip(),
99
+ shift(),
100
+ size({
101
+ apply({rects, elements}) {
102
+ const customWidth = props.width ?? rects.reference.width
103
+ Object.assign(elements.floating.style, {
104
+ width: `${customWidth}px`,
105
+ ...(typeof height == 'string' ? {maxHeight: props.height} : {maxHeight : `${props.height}px`})
106
+ })
107
+ },
108
+ })
109
+ ],
110
+ })
132
111
 
133
112
  const open = () => {
134
- emit('open')
135
113
  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)
147
- }
148
-
149
- 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)
114
+ emit('open')
162
115
  }
163
116
 
164
- const watchParentScrolling = () => {
165
- scrollableParentEl.value = getParentScrollableEl(PSDropdown.value)
166
- if (scrollableParentEl.value) {
167
- scrollableParentEl.value.addEventListener('scroll', updatePosition)
168
- }
169
- }
117
+ const close = (event) => {
118
+ if(event?.target && PSDropdownTrigger.value.contains(event?.target)) return
170
119
 
171
- const unwatchParentScrolling = () => {
172
- if (scrollableParentEl.value) {
173
- scrollableParentEl.value.removeEventListener('scroll', updatePosition())
174
- }
120
+ show.value = false
121
+ emit('close')
175
122
  }
176
123
 
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
- }
124
+ const toggle = (event) => {
125
+ if (props.disabled) return
198
126
 
199
- if (rectTrigger.top < 10) {
200
- close()
201
- console.warn('The dropdown are too close from the top of the page')
202
- return
203
- }
127
+ if (event) event.stopPropagation()
204
128
 
205
- setTimeout(() => {
206
- if(PSDropdownDialog.value){
207
- PSDropdownDialog.value.style.opacity = 1
208
- }
209
- }, 10)
129
+ show.value = !show.value
130
+
210
131
  }
211
132
 
212
- const clickOutside = (event) => {
213
- if (!show.value) return
214
- if (!PSDropdown.value == event.target || !PSDropdown.value?.contains(event.target)) {
215
- close()
216
- }
217
- }
133
+ defineExpose({ open, close })
218
134
  </script>
@@ -3,7 +3,10 @@
3
3
  class="psui-el-input"
4
4
  :class="[getComponentClass, `layout-${layout}`]"
5
5
  >
6
- <label v-if="label"> {{ label }} </label>
6
+ <label
7
+ v-if="label"
8
+ :for="uniqueId"
9
+ > {{ label }} </label>
7
10
 
8
11
  <div
9
12
  class="psui-el-input-wrapper"
@@ -23,6 +26,7 @@
23
26
  >
24
27
  <template #trigger>
25
28
  <input
29
+ :id="uniqueId"
26
30
  :title="title"
27
31
  :type="type"
28
32
  :placeholder="placeholder"
@@ -69,9 +73,17 @@
69
73
  </div>
70
74
  </template>
71
75
 
76
+ <script>
77
+
78
+ export default {
79
+ name: 'PsInput',
80
+ inheritAttrs: false
81
+ }
82
+ </script>
83
+
72
84
  <script setup>
73
85
  import PsRichTooltip from '../tooltip/PsRichTooltip.vue'
74
- import { ref, computed, useAttrs } from 'vue'
86
+ import { ref, computed, useAttrs, getCurrentInstance } from 'vue'
75
87
 
76
88
  const props = defineProps({
77
89
  /**
@@ -171,7 +183,7 @@ const attrs = useAttrs()
171
183
  const getAttrs = computed(() => {
172
184
  const defaultAttrs = {
173
185
  autocapitalize: 'sentences',
174
- autocomplete: 'chrome-off',
186
+ autocomplete: 'off',
175
187
  autocorrect: 'off',
176
188
  spellcheck: 'spellcheck',
177
189
  }
@@ -190,6 +202,10 @@ const getComponentClass = computed(() => {
190
202
  }
191
203
  })
192
204
 
205
+ const instance = getCurrentInstance()
206
+ const uid = instance?.uid || Math.random().toString(36).slice(2)
207
+ const uniqueId = computed(() => `psui-input-${uid}`)
208
+
193
209
  const onInputFocus = ($event) => {
194
210
  isFocus.value = true
195
211
  emit('focus', $event)
@@ -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'])
@@ -2,6 +2,7 @@
2
2
  <div
3
3
  class="psui-el-toast"
4
4
  :class="getComponentClass"
5
+ tabindex="0"
5
6
  >
6
7
  <i class="material-icons-round psui-el-toast-icon">{{ icon }}</i>
7
8
  <p class="psui-el-toast-message">