pgo-uiux2 1.0.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 (180) hide show
  1. package/.env +1 -0
  2. package/.env.production +1 -0
  3. package/.prettierrc +13 -0
  4. package/.vscode/extensions.json +3 -0
  5. package/BUTTON_GUIDE.md +257 -0
  6. package/README.md +49 -0
  7. package/THEME_REFERENCE.md +310 -0
  8. package/eslint.config.ts +27 -0
  9. package/index.html +13 -0
  10. package/package.json +85 -0
  11. package/public/favicon.ico +0 -0
  12. package/src/App.vue +368 -0
  13. package/src/assets/fonts/Faruma.ttf +0 -0
  14. package/src/components/examples/AppBarExample.vue +101 -0
  15. package/src/components/examples/AvatarExample.vue +47 -0
  16. package/src/components/examples/BannerExample.vue +287 -0
  17. package/src/components/examples/BaseInputExample.vue +25 -0
  18. package/src/components/examples/BreadcrumbExample.vue +53 -0
  19. package/src/components/examples/CardExample.vue +77 -0
  20. package/src/components/examples/ChipExample.vue +225 -0
  21. package/src/components/examples/DatePickerExample.vue +31 -0
  22. package/src/components/examples/DropdownExample.vue +84 -0
  23. package/src/components/examples/EditorExample.vue +200 -0
  24. package/src/components/examples/ExpansionPanelExample.vue +42 -0
  25. package/src/components/examples/FileUploadExample.vue +40 -0
  26. package/src/components/examples/FormExample.vue +121 -0
  27. package/src/components/examples/HugeTest.vue +8 -0
  28. package/src/components/examples/LayoutContainerExample.vue +80 -0
  29. package/src/components/examples/ModalExample.vue +82 -0
  30. package/src/components/examples/NavDrawerExample.vue +170 -0
  31. package/src/components/examples/NumberFieldExample.vue +145 -0
  32. package/src/components/examples/RadioButtonExample.vue +161 -0
  33. package/src/components/examples/SearchExample.vue +322 -0
  34. package/src/components/examples/SelectExample.vue +121 -0
  35. package/src/components/examples/StackedTableViewExample.vue +53 -0
  36. package/src/components/examples/TabExample.vue +336 -0
  37. package/src/components/examples/TableExample.vue +228 -0
  38. package/src/components/examples/TextFieldExample.vue +181 -0
  39. package/src/components/examples/TextareaExample.vue +173 -0
  40. package/src/components/examples/ThemeToggle.vue +50 -0
  41. package/src/components/examples/TimelineExample.vue +66 -0
  42. package/src/components/examples/TipTapEditorExample.vue +20 -0
  43. package/src/components/examples/TooltipExample.vue +53 -0
  44. package/src/components/examples/VueDatePickerShowcase.vue +214 -0
  45. package/src/components/examples/_DatePickerExample.vue +33 -0
  46. package/src/components/examples/__FormExample.vue +77 -0
  47. package/src/components/index.ts +25 -0
  48. package/src/components/pgo/AppBar.vue +347 -0
  49. package/src/components/pgo/Avatar.vue +139 -0
  50. package/src/components/pgo/Banner.vue +300 -0
  51. package/src/components/pgo/Breadcrumb.vue +101 -0
  52. package/src/components/pgo/Button.vue +171 -0
  53. package/src/components/pgo/Card.vue +178 -0
  54. package/src/components/pgo/ConfirmationModel.vue +32 -0
  55. package/src/components/pgo/DataTable.vue +845 -0
  56. package/src/components/pgo/DatePicker/CalendarPanel.vue +43 -0
  57. package/src/components/pgo/DatePicker/__DatePicker.vue +122 -0
  58. package/src/components/pgo/DatePicker/types.ts +11 -0
  59. package/src/components/pgo/DatePicker/useCalendar.ts +39 -0
  60. package/src/components/pgo/DatePicker/useDatePicker.ts +31 -0
  61. package/src/components/pgo/Deprecated/ToastContainer.vue +51 -0
  62. package/src/components/pgo/Deprecated/ToastItem.vue +55 -0
  63. package/src/components/pgo/Dropdown.vue +296 -0
  64. package/src/components/pgo/DropdownItem.vue +40 -0
  65. package/src/components/pgo/Editor.vue +511 -0
  66. package/src/components/pgo/ExpansionPanel.vue +185 -0
  67. package/src/components/pgo/Footer.vue +39 -0
  68. package/src/components/pgo/HeroIcon.vue +124 -0
  69. package/src/components/pgo/InputSearch.vue +194 -0
  70. package/src/components/pgo/LayoutContainer.vue +104 -0
  71. package/src/components/pgo/Main.vue +37 -0
  72. package/src/components/pgo/Modal.vue +273 -0
  73. package/src/components/pgo/NavDrawer.vue +127 -0
  74. package/src/components/pgo/NavDrawerItem.vue +161 -0
  75. package/src/components/pgo/NavigationDrawer.vue +849 -0
  76. package/src/components/pgo/OLDNavDrawer.vue +661 -0
  77. package/src/components/pgo/OldAppBar.vue +223 -0
  78. package/src/components/pgo/PApp.vue +102 -0
  79. package/src/components/pgo/Pagination.vue +242 -0
  80. package/src/components/pgo/Search copy.vue +310 -0
  81. package/src/components/pgo/Search.vue +411 -0
  82. package/src/components/pgo/StackedTableView.vue +167 -0
  83. package/src/components/pgo/Tab.vue +617 -0
  84. package/src/components/pgo/TestInput.vue +395 -0
  85. package/src/components/pgo/Timeline.vue +367 -0
  86. package/src/components/pgo/TimelineItem.vue +80 -0
  87. package/src/components/pgo/TipTapEditor.vue +315 -0
  88. package/src/components/pgo/Tooltip.NOTES.md +12 -0
  89. package/src/components/pgo/Tooltip.PROPS.md +21 -0
  90. package/src/components/pgo/Tooltip.vue +281 -0
  91. package/src/components/pgo/base/Base.vue +444 -0
  92. package/src/components/pgo/buttons/Chip.vue +324 -0
  93. package/src/components/pgo/buttons/ChipGroup.vue +224 -0
  94. package/src/components/pgo/buttons/Radio.vue +424 -0
  95. package/src/components/pgo/filters/FilterSection.vue +188 -0
  96. package/src/components/pgo/filters/Searchbar.vue +216 -0
  97. package/src/components/pgo/forms/DynamicForm.vue +45 -0
  98. package/src/components/pgo/forms/Form.vue +132 -0
  99. package/src/components/pgo/index.ts +15 -0
  100. package/src/components/pgo/inputs/Checkbox.vue +320 -0
  101. package/src/components/pgo/inputs/DatePicker.vue +395 -0
  102. package/src/components/pgo/inputs/FileUpload.vue +326 -0
  103. package/src/components/pgo/inputs/NumberField.vue +243 -0
  104. package/src/components/pgo/inputs/Radio.vue +162 -0
  105. package/src/components/pgo/inputs/RadioGroup.vue +188 -0
  106. package/src/components/pgo/inputs/Select.vue +535 -0
  107. package/src/components/pgo/inputs/TextField.vue +194 -0
  108. package/src/components/pgo/inputs/Textarea.vue +181 -0
  109. package/src/main.js +12 -0
  110. package/src/pgo-components/_index.js +31 -0
  111. package/src/pgo-components/assets/fonts/Faruma.ttf +0 -0
  112. package/src/pgo-components/assets/fonts/logo.png +0 -0
  113. package/src/pgo-components/composables/useTheme.js +10 -0
  114. package/src/pgo-components/directives/tooltip-directive.ts +393 -0
  115. package/src/pgo-components/index.js +96 -0
  116. package/src/pgo-components/lib/componentConfig.js +147 -0
  117. package/src/pgo-components/lib/core/composables/_useCalendar.ts +127 -0
  118. package/src/pgo-components/lib/core/composables/useDefaults.ts +15 -0
  119. package/src/pgo-components/lib/core/composables/useLanguageSelect.js +0 -0
  120. package/src/pgo-components/lib/core/composables/useRtl.ts +12 -0
  121. package/src/pgo-components/lib/core/defaults/createDefaults.ts +5 -0
  122. package/src/pgo-components/lib/core/defaults/defaults.ts +7 -0
  123. package/src/pgo-components/lib/core/rtl/rtl.ts +3 -0
  124. package/src/pgo-components/lib/core/rtl/setRtl.ts +19 -0
  125. package/src/pgo-components/lib/drawerState.ts +3 -0
  126. package/src/pgo-components/lib/i18n/defaultLables.js +71 -0
  127. package/src/pgo-components/lib/i18n/i18nPlugin.js +52 -0
  128. package/src/pgo-components/lib/i18n/useI18n.js +35 -0
  129. package/src/pgo-components/lib/index.ts +38 -0
  130. package/src/pgo-components/pages/Component.vue +7 -0
  131. package/src/pgo-components/pages/ComponentRenderer.vue +85 -0
  132. package/src/pgo-components/pages/Home.vue +130 -0
  133. package/src/pgo-components/pages/ListView.vue +370 -0
  134. package/src/pgo-components/pages/Page1.vue +296 -0
  135. package/src/pgo-components/pages/_Page1.vue +180 -0
  136. package/src/pgo-components/plugins/SnackBar.vue +251 -0
  137. package/src/pgo-components/plugins/SnackBarContainer.vue +53 -0
  138. package/src/pgo-components/plugins/SnackBarPlugin.ts +136 -0
  139. package/src/pgo-components/plugins/theme-plugin.js +114 -0
  140. package/src/pgo-components/plugins/types.ts +46 -0
  141. package/src/pgo-components/plugins/useSnackBar.js +11 -0
  142. package/src/pgo-components/plugins/useSnackBar.ts +21 -0
  143. package/src/pgo-components/plugins/validation-plugin.js +11 -0
  144. package/src/pgo-components/services/Entry.json +813 -0
  145. package/src/pgo-components/services/axios.js +54 -0
  146. package/src/pgo-components/services/data.json +90 -0
  147. package/src/pgo-components/services/person.json +260 -0
  148. package/src/pgo-components/services/toast.ts +44 -0
  149. package/src/pgo-components/styles/global.css +234 -0
  150. package/src/pgo-components/styles/reset.css +96 -0
  151. package/src/pgo-components/styles/tokens.css +18 -0
  152. package/src/pgo-components/styles/utilities/border-radius.css +57 -0
  153. package/src/pgo-components/styles/utilities/borders.css +85 -0
  154. package/src/pgo-components/styles/utilities/colors.css +38 -0
  155. package/src/pgo-components/styles/utilities/cursor.css +19 -0
  156. package/src/pgo-components/styles/utilities/display.css +78 -0
  157. package/src/pgo-components/styles/utilities/elevation.css +33 -0
  158. package/src/pgo-components/styles/utilities/flex.css +403 -0
  159. package/src/pgo-components/styles/utilities/float.css +41 -0
  160. package/src/pgo-components/styles/utilities/hover.css +9 -0
  161. package/src/pgo-components/styles/utilities/index.css +18 -0
  162. package/src/pgo-components/styles/utilities/opacity.css +27 -0
  163. package/src/pgo-components/styles/utilities/overflow.css +26 -0
  164. package/src/pgo-components/styles/utilities/palette.css +515 -0
  165. package/src/pgo-components/styles/utilities/position.css +14 -0
  166. package/src/pgo-components/styles/utilities/sizing.css +70 -0
  167. package/src/pgo-components/styles/utilities/spacing.css +578 -0
  168. package/src/pgo-components/styles/utilities/transitions.css +58 -0
  169. package/src/pgo-components/styles/utilities/typography.css +91 -0
  170. package/src/pgo-components/styles/utilities/z-index.css +11 -0
  171. package/src/pgo-components/tokens/index.js +337 -0
  172. package/src/router/index.js +88 -0
  173. package/src/shims-vue.d.ts +14 -0
  174. package/src/validations/validationRules.js +50 -0
  175. package/tailwind.config.js +73 -0
  176. package/test.php +5 -0
  177. package/tsconfig.json +25 -0
  178. package/ui +31 -0
  179. package/ui.pgo.mv.conf +18 -0
  180. package/vite.config.js +42 -0
@@ -0,0 +1,395 @@
1
+ <template>
2
+ <div
3
+ ref="containerRef"
4
+ :class="['relative', containerClass, width]"
5
+ v-on-click-outside="handleClickOutside"
6
+ >
7
+ <Base
8
+ :model-value="localValue"
9
+ :label="label"
10
+ v-on="$attrs"
11
+ :hint="hint"
12
+ :persistent-hint="!!hint"
13
+ :disabled="disabled"
14
+ :readonly="readonly"
15
+ :required="required"
16
+ :error="!!error || errorMessages.length > 0"
17
+ :error-messages="errorMessages"
18
+ :clearable="clearable && !loading"
19
+ :size="size"
20
+ :id="inputId"
21
+ :prepend="prepend"
22
+ :append="append"
23
+ :is-open="showResults"
24
+ @click:clear="clear"
25
+ :bg="bg"
26
+ :border="border"
27
+ :text-color="textColor"
28
+ :rounded="rounded"
29
+ :dir="dir"
30
+ :width="width"
31
+ >
32
+ <template #control="{ attrs, events }">
33
+ <input
34
+ ref="inputRef"
35
+ v-bind="attrs"
36
+ type="search"
37
+ :value="localValue"
38
+ :placeholder="isFocused && !localValue ? placeholder : ''"
39
+ :class="inputClasses"
40
+ @input="handleInput"
41
+ @focus="handleFocus"
42
+ @blur="handleBlur"
43
+ @keydown.enter="handleEnter"
44
+ @keydown.esc="handleEscape"
45
+ @keydown.down="handleArrowDown"
46
+ @keydown.up="handleArrowUp"
47
+ />
48
+ </template>
49
+
50
+ <!-- Loading spinner in append slot -->
51
+ <template v-if="loading" #append>
52
+ <svg class="animate-spin h-4 w-4" fill="none" viewBox="0 0 24 24">
53
+ <circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
54
+ <path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
55
+ </svg>
56
+ </template>
57
+
58
+ <!-- Magnifying glass icon when not loading -->
59
+ <!-- <template v-else #append>
60
+ <HeroIcon name="magnifying-glass" :size="iconSizes[size]" />
61
+ </template> -->
62
+ </Base>
63
+
64
+ <!-- Results Dropdown - Styled like Select component -->
65
+ <Transition name="fade">
66
+ <div
67
+ v-if="showResults"
68
+ ref="menuRef"
69
+ :class="[
70
+ 'absolute left-0 right-0 mt-1 shadow-lg z-50',
71
+ bg,
72
+ border ? 'border ' + border : '',
73
+ rounded ? roundedMap[rounded] : '',
74
+ menuClass
75
+ ]"
76
+ :style="menuStyle"
77
+ >
78
+ <ul class="max-h-60 overflow-auto py-1">
79
+ <!-- Loading State -->
80
+ <li v-if="loading" class="px-4 py-2 text-input-text text-center text-sm">
81
+ <slot name="loading">
82
+ <div class="flex items-center gap-2 justify-center">
83
+ <svg class="animate-spin h-4 w-4" fill="none" viewBox="0 0 24 24">
84
+ <circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
85
+ <path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
86
+ </svg>
87
+ Searching...
88
+ </div>
89
+ </slot>
90
+ </li>
91
+
92
+ <!-- No Data -->
93
+ <li v-else-if="filteredItems.length === 0" class="px-4 py-2 text-input-text text-center text-sm">
94
+ <slot name="noData">No results found</slot>
95
+ </li>
96
+
97
+ <!-- Results List -->
98
+ <li
99
+ v-else
100
+ v-for="(item, index) in filteredItems"
101
+ :key="getItemValue(item)"
102
+ @click="selectItem(item)"
103
+ @mouseenter="highlightedIndex = index"
104
+ :class="[
105
+ 'px-4 py-2 cursor-pointer transition flex items-center text-sm',
106
+ highlightedIndex === index
107
+ ? 'bg-gray-100 text-gray-900'
108
+ : 'hover:bg-input-hover',
109
+ itemClass,
110
+ itemHoverClass
111
+ ]"
112
+ role="option"
113
+ :aria-selected="highlightedIndex === index"
114
+ >
115
+ <slot name="item" :item="item" :index="index">
116
+ <span class="flex-1">{{ getItemText(item) }}</span>
117
+ </slot>
118
+ </li>
119
+ </ul>
120
+ </div>
121
+ </Transition>
122
+ </div>
123
+ </template>
124
+
125
+ <script setup>
126
+ import { ref, computed, watch, onMounted, onBeforeUnmount, nextTick } from 'vue'
127
+ import Base from '../pgo/base/Base.vue'
128
+ import HeroIcon from '../pgo/HeroIcon.vue'
129
+ import { vOnClickOutside } from '@vueuse/components'
130
+ import { roundedMap, sizes, iconSizes } from '../../pgo-components/lib/componentConfig'
131
+
132
+ const props = defineProps({
133
+ modelValue: { type: [String, Number, Object], default: '' },
134
+ label: { type: [String, Object], default: '' },
135
+ placeholder: { type: String, default: 'Search...' },
136
+ hint: { type: String, default: '' },
137
+ error: { type: String, default: '' },
138
+ errorMessages: { type: Array, default: () => [] },
139
+ disabled: { type: Boolean, default: false },
140
+ readonly: { type: Boolean, default: false },
141
+ required: { type: Boolean, default: false },
142
+ clearable: { type: Boolean, default: true },
143
+ loading: { type: Boolean, default: false },
144
+ prepend: { type: String, default: '' },
145
+ append: { type: String, default: '' },
146
+
147
+ // Items & Search
148
+ items: { type: Array, default: () => [] },
149
+ itemText: { type: [String, Function], default: 'text' },
150
+ itemValue: { type: [String, Function], default: 'value' },
151
+ returnObject: { type: Boolean, default: false },
152
+
153
+ // Search behavior
154
+ searchInput: { type: String, default: '' },
155
+ filterKeys: { type: Array, default: () => [] },
156
+ customFilter: { type: Function, default: null },
157
+ minSearchLength: { type: Number, default: 0 },
158
+ debounce: { type: Number, default: 300 },
159
+
160
+ // Appearance
161
+ size: { type: String, default: 'md' },
162
+ rounded: { type: String, default: '' },
163
+ border: { type: String, default: 'border-input-border' },
164
+ textColor: { type: String, default: 'text-input-text' },
165
+ bg: { type: String, default: 'bg-input-background' },
166
+ containerClass: { type: String, default: '' },
167
+ menuClass: { type: String, default: '' },
168
+ menuStyle: { type: Object, default: () => ({}) },
169
+ itemClass: { type: String, default: '' },
170
+ itemHoverClass: { type: String, default: '' },
171
+ id: { type: String, default: '' },
172
+ width: { type: String, default: 'w-full' },
173
+
174
+ // RTL/Lang support
175
+ dir: { type: String, default: '' },
176
+ lang: { type: String, default: '' },
177
+ })
178
+
179
+ const emit = defineEmits([
180
+ 'update:modelValue',
181
+ 'update:searchInput',
182
+ 'input',
183
+ 'change',
184
+ 'focus',
185
+ 'blur',
186
+ 'select',
187
+ 'clear',
188
+ 'search'
189
+ ])
190
+
191
+ const containerRef = ref(null)
192
+ const inputRef = ref(null)
193
+ const menuRef = ref(null)
194
+ const localValue = ref('')
195
+ const isFocused = ref(false)
196
+ const showResults = ref(false)
197
+ const highlightedIndex = ref(-1)
198
+ let debounceTimeout = null
199
+
200
+ // Generate unique ID
201
+ const inputId = computed(() => props.id || `search-${Math.random().toString(36).substr(2, 9)}`)
202
+
203
+ // Initialize local value
204
+ watch(() => props.modelValue, (newVal) => {
205
+ if (props.returnObject) {
206
+ localValue.value = newVal ? getItemText(newVal) : ''
207
+ } else {
208
+ localValue.value = newVal || ''
209
+ }
210
+ }, { immediate: true })
211
+
212
+ // Watch search input
213
+ watch(() => props.searchInput, (newVal) => {
214
+ localValue.value = newVal
215
+ })
216
+
217
+ // Filter items
218
+ const filteredItems = computed(() => {
219
+ const search = localValue.value?.toString().toLowerCase() || ''
220
+
221
+ if (search.length < props.minSearchLength) {
222
+ return []
223
+ }
224
+
225
+ if (!search && props.items.length > 0) {
226
+ return props.items
227
+ }
228
+
229
+ if (props.customFilter) {
230
+ return props.customFilter(props.items, search)
231
+ }
232
+
233
+ return props.items.filter(item => {
234
+ const searchKeys = props.filterKeys.length > 0
235
+ ? props.filterKeys
236
+ : [props.itemText]
237
+
238
+ return searchKeys.some(key => {
239
+ const value = typeof key === 'function'
240
+ ? key(item)
241
+ : item[key]
242
+ return value?.toString().toLowerCase().includes(search)
243
+ })
244
+ })
245
+ })
246
+
247
+ // Get item text
248
+ const getItemText = (item) => {
249
+ if (!item) return ''
250
+ if (typeof item === 'string' || typeof item === 'number') return item.toString()
251
+ if (typeof props.itemText === 'function') return props.itemText(item)
252
+ return item[props.itemText] || ''
253
+ }
254
+
255
+ // Get item value
256
+ const getItemValue = (item) => {
257
+ if (!item) return ''
258
+ if (typeof item === 'string' || typeof item === 'number') return item
259
+ if (typeof props.itemValue === 'function') return props.itemValue(item)
260
+ return item[props.itemValue] || item
261
+ }
262
+
263
+ // Input classes
264
+ const inputClasses = computed(() => [
265
+ 'w-full bg-transparent outline-none border-none',
266
+ 'placeholder:text-gray-400',
267
+ 'focus:outline-none'
268
+ ])
269
+
270
+ // Handlers
271
+ const handleInput = (e) => {
272
+ const value = e.target.value
273
+ localValue.value = value
274
+
275
+ clearTimeout(debounceTimeout)
276
+ debounceTimeout = setTimeout(() => {
277
+ emit('update:searchInput', value)
278
+ emit('input', value)
279
+ emit('search', value)
280
+ emit('update:modelValue', value)
281
+
282
+ if (value.length >= props.minSearchLength) {
283
+ showResults.value = true
284
+ } else {
285
+ showResults.value = false
286
+ }
287
+ }, props.debounce)
288
+ }
289
+
290
+ const handleFocus = (event) => {
291
+ isFocused.value = true
292
+ emit('focus', event)
293
+
294
+ if (localValue.value.length >= props.minSearchLength) {
295
+ showResults.value = true
296
+ }
297
+ }
298
+
299
+ const handleBlur = (event) => {
300
+ // Delay to allow click on menu items
301
+ setTimeout(() => {
302
+ isFocused.value = false
303
+ emit('blur', event)
304
+ }, 200)
305
+ }
306
+
307
+ const handleClickOutside = () => {
308
+ showResults.value = false
309
+ }
310
+
311
+ const handleEnter = (event) => {
312
+ if (highlightedIndex.value >= 0 && highlightedIndex.value < filteredItems.value.length) {
313
+ event.preventDefault()
314
+ selectItem(filteredItems.value[highlightedIndex.value])
315
+ }
316
+ }
317
+
318
+ const handleEscape = () => {
319
+ showResults.value = false
320
+ inputRef.value?.blur()
321
+ }
322
+
323
+ const handleArrowDown = (event) => {
324
+ event.preventDefault()
325
+ if (highlightedIndex.value < filteredItems.value.length - 1) {
326
+ highlightedIndex.value++
327
+ }
328
+ }
329
+
330
+ const handleArrowUp = (event) => {
331
+ event.preventDefault()
332
+ if (highlightedIndex.value > 0) {
333
+ highlightedIndex.value--
334
+ }
335
+ }
336
+
337
+ const selectItem = (item) => {
338
+ const value = props.returnObject ? item : getItemValue(item)
339
+ const text = getItemText(item)
340
+
341
+ localValue.value = text
342
+ emit('update:modelValue', value)
343
+ emit('update:searchInput', text)
344
+ emit('select', item)
345
+
346
+ showResults.value = false
347
+ highlightedIndex.value = -1
348
+ }
349
+
350
+ const clear = () => {
351
+ localValue.value = ''
352
+ emit('update:modelValue', '')
353
+ emit('update:searchInput', '')
354
+ emit('clear')
355
+ inputRef.value?.focus()
356
+ }
357
+
358
+ // Focus method
359
+ const focus = () => {
360
+ inputRef.value?.focus()
361
+ }
362
+
363
+ // Lifecycle
364
+ onMounted(() => {
365
+ // No need for resize/scroll listeners with absolute positioning
366
+ })
367
+
368
+ onBeforeUnmount(() => {
369
+ clearTimeout(debounceTimeout)
370
+ })
371
+
372
+ // Expose methods
373
+ defineExpose({ focus, clear })
374
+ </script>
375
+
376
+ <style scoped>
377
+ /* Remove default search input styling */
378
+ input[type="search"]::-webkit-search-decoration,
379
+ input[type="search"]::-webkit-search-cancel-button,
380
+ input[type="search"]::-webkit-search-results-button,
381
+ input[type="search"]::-webkit-search-results-decoration {
382
+ display: none;
383
+ }
384
+
385
+ /* Transition styles matching Select component */
386
+ .fade-enter-active,
387
+ .fade-leave-active {
388
+ transition: opacity 0.2s, transform 0.2s;
389
+ }
390
+
391
+ .fade-enter-from,
392
+ .fade-leave-to {
393
+ opacity: 0;
394
+ }
395
+ </style>