vite-uni-dev-tool 1.1.0 → 1.2.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 (135) hide show
  1. package/README.md +8 -0
  2. package/dist/const.cjs +1 -1
  3. package/dist/const.d.ts +1 -0
  4. package/dist/const.d.ts.map +1 -1
  5. package/dist/const.js +1 -1
  6. package/dist/core.d.ts.map +1 -1
  7. package/dist/core.js +2 -2
  8. package/dist/i18n/locales/en.cjs +1 -1
  9. package/dist/i18n/locales/en.d.ts +5 -0
  10. package/dist/i18n/locales/en.d.ts.map +1 -1
  11. package/dist/i18n/locales/en.js +1 -1
  12. package/dist/i18n/locales/zh-Hans.cjs +1 -1
  13. package/dist/i18n/locales/zh-Hans.d.ts +5 -0
  14. package/dist/i18n/locales/zh-Hans.d.ts.map +1 -1
  15. package/dist/i18n/locales/zh-Hans.js +1 -1
  16. package/dist/modules/devIntercept/index.cjs +9 -9
  17. package/dist/modules/devIntercept/index.d.ts +1 -1
  18. package/dist/modules/devIntercept/index.d.ts.map +1 -1
  19. package/dist/modules/devIntercept/index.js +9 -9
  20. package/dist/modules/devStore/index.cjs +1 -1
  21. package/dist/modules/devStore/index.d.ts.map +1 -1
  22. package/dist/modules/devStore/index.js +1 -1
  23. package/dist/plugins/uniDevTool/transform/transformMain.cjs +3 -3
  24. package/dist/plugins/uniDevTool/transform/transformMain.d.ts +2 -1
  25. package/dist/plugins/uniDevTool/transform/transformMain.d.ts.map +1 -1
  26. package/dist/plugins/uniDevTool/transform/transformMain.js +3 -3
  27. package/dist/plugins/uniDevTool/transform/transformVue.cjs +31 -25
  28. package/dist/plugins/uniDevTool/transform/transformVue.d.ts +2 -1
  29. package/dist/plugins/uniDevTool/transform/transformVue.d.ts.map +1 -1
  30. package/dist/plugins/uniDevTool/transform/transformVue.js +30 -24
  31. package/dist/plugins/uniDevTool/uniDevTool.cjs +3 -3
  32. package/dist/plugins/uniDevTool/uniDevTool.d.ts +3 -1
  33. package/dist/plugins/uniDevTool/uniDevTool.d.ts.map +1 -1
  34. package/dist/plugins/uniDevTool/uniDevTool.js +3 -3
  35. package/dist/type.d.ts +3 -0
  36. package/dist/type.d.ts.map +1 -1
  37. package/dist/v3/DevTool/components/BluetoothList/BluetoothItem.vue +199 -199
  38. package/dist/v3/DevTool/components/BluetoothList/BluetoothTool.vue +730 -730
  39. package/dist/v3/DevTool/components/BluetoothList/index.vue +167 -167
  40. package/dist/v3/DevTool/components/CaptureScreen/index.vue +109 -109
  41. package/dist/v3/DevTool/components/ConsoleList/ConsoleItem.vue +230 -225
  42. package/dist/v3/DevTool/components/ConsoleList/RunJSInput.vue +247 -247
  43. package/dist/v3/DevTool/components/ConsoleList/index.vue +171 -171
  44. package/dist/v3/DevTool/components/ConsoleList/staticTips.ts +1145 -1145
  45. package/dist/v3/DevTool/components/DevToolTitle/index.vue +24 -24
  46. package/dist/v3/DevTool/components/DevToolWindow/DevToolOverlay.vue +197 -197
  47. package/dist/v3/DevTool/components/DevToolWindow/hooks/dataUtils.ts +48 -48
  48. package/dist/v3/DevTool/components/DevToolWindow/hooks/useDevToolData.ts +387 -387
  49. package/dist/v3/DevTool/components/DevToolWindow/hooks/useDevToolHandlers.ts +629 -629
  50. package/dist/v3/DevTool/components/DevToolWindow/hooks/useDevToolOverlay.ts +201 -197
  51. package/dist/v3/DevTool/components/ElEvent/ElEventItem.vue +105 -105
  52. package/dist/v3/DevTool/components/ElEvent/index.vue +106 -106
  53. package/dist/v3/DevTool/components/Instance/components/InstanceTreeNode.vue +265 -265
  54. package/dist/v3/DevTool/components/Instance/flatten.ts +226 -226
  55. package/dist/v3/DevTool/components/Instance/index.vue +94 -94
  56. package/dist/v3/DevTool/components/Instance/registry.ts +49 -49
  57. package/dist/v3/DevTool/components/Instance/transformTree.ts +375 -375
  58. package/dist/v3/DevTool/components/Instance/transformTreeCtx.ts +268 -268
  59. package/dist/v3/DevTool/components/Instance/typing.d.ts +43 -43
  60. package/dist/v3/DevTool/components/InstanceDetail/index.vue +485 -485
  61. package/dist/v3/DevTool/components/JsonDetail/index.vue +70 -70
  62. package/dist/v3/DevTool/components/NFCList/NFCItem.vue +112 -112
  63. package/dist/v3/DevTool/components/NFCList/NFCTool.vue +454 -454
  64. package/dist/v3/DevTool/components/NFCList/const.ts +56 -56
  65. package/dist/v3/DevTool/components/NFCList/index.vue +94 -94
  66. package/dist/v3/DevTool/components/NetworkList/InterceptConfig.vue +624 -624
  67. package/dist/v3/DevTool/components/NetworkList/InterceptItem.vue +140 -140
  68. package/dist/v3/DevTool/components/NetworkList/NetworkDetail.vue +287 -287
  69. package/dist/v3/DevTool/components/NetworkList/NetworkIntercept.vue +88 -88
  70. package/dist/v3/DevTool/components/NetworkList/NetworkItem.vue +163 -163
  71. package/dist/v3/DevTool/components/NetworkList/NetworkSend.vue +589 -589
  72. package/dist/v3/DevTool/components/NetworkList/const.ts +4 -4
  73. package/dist/v3/DevTool/components/NetworkList/hooks/useNetworkForm.ts +86 -86
  74. package/dist/v3/DevTool/components/NetworkList/index.vue +160 -160
  75. package/dist/v3/DevTool/components/NetworkList/utils.ts +101 -101
  76. package/dist/v3/DevTool/components/Performance/index.vue +498 -498
  77. package/dist/v3/DevTool/components/Performance/modules/PerformanceMetrics.vue +153 -153
  78. package/dist/v3/DevTool/components/Performance/modules/usePerformanceChart.ts +460 -460
  79. package/dist/v3/DevTool/components/Performance/modules/usePerformanceData.ts +258 -258
  80. package/dist/v3/DevTool/components/PiniaList/index.vue +93 -93
  81. package/dist/v3/DevTool/components/RunJS/index.vue +148 -148
  82. package/dist/v3/DevTool/components/ScanCodeList/ScanCodeItem.vue +97 -97
  83. package/dist/v3/DevTool/components/ScanCodeList/index.vue +100 -100
  84. package/dist/v3/DevTool/components/SettingButton/index.vue +45 -45
  85. package/dist/v3/DevTool/components/SettingList/index.vue +218 -218
  86. package/dist/v3/DevTool/components/SettingList/modules/SettingBarrage.vue +304 -304
  87. package/dist/v3/DevTool/components/SettingList/modules/SettingDevTool.vue +212 -212
  88. package/dist/v3/DevTool/components/SettingList/modules/SettingInfo.vue +157 -157
  89. package/dist/v3/DevTool/components/SettingList/modules/SettingLanguage.vue +74 -74
  90. package/dist/v3/DevTool/components/SettingList/modules/SettingLog.vue +230 -230
  91. package/dist/v3/DevTool/components/SettingList/typing.d.ts +2 -2
  92. package/dist/v3/DevTool/components/SourceCode/Line.vue +127 -127
  93. package/dist/v3/DevTool/components/SourceCode/parseCode.ts +609 -609
  94. package/dist/v3/DevTool/components/StorageList/index.vue +174 -174
  95. package/dist/v3/DevTool/components/TransferList/TransferDetail.vue +268 -268
  96. package/dist/v3/DevTool/components/VuexList/index.vue +84 -84
  97. package/dist/v3/DevTool/index.vue +1 -0
  98. package/dist/v3/components/AppTransition/index.vue +176 -176
  99. package/dist/v3/components/AutoSizer/index.vue +192 -192
  100. package/dist/v3/components/AutoSizer/index1.vue +184 -184
  101. package/dist/v3/components/AutoSizer/utils.ts +49 -49
  102. package/dist/v3/components/Barrage/BarrageItem.vue +137 -137
  103. package/dist/v3/components/Barrage/index.vue +202 -202
  104. package/dist/v3/components/CircularButton/index.vue +84 -84
  105. package/dist/v3/components/CustomSwiper/CustomSwiperItem.vue +49 -49
  106. package/dist/v3/components/CustomSwiper/index.vue +104 -104
  107. package/dist/v3/components/DevErrorBoundary/index.vue +380 -0
  108. package/dist/v3/components/Empty/index.vue +29 -29
  109. package/dist/v3/components/FilterSelect/index.vue +179 -179
  110. package/dist/v3/components/JsonPretty/components/Brackets/index.vue +27 -27
  111. package/dist/v3/components/JsonPretty/components/Carets/index.vue +59 -59
  112. package/dist/v3/components/JsonPretty/components/CheckController/index.vue +136 -136
  113. package/dist/v3/components/JsonPretty/components/TreeNode/index.vue +387 -387
  114. package/dist/v3/components/JsonPretty/hooks/useClipboard.ts +21 -21
  115. package/dist/v3/components/JsonPretty/hooks/useError.ts +21 -21
  116. package/dist/v3/components/JsonPretty/type.ts +127 -127
  117. package/dist/v3/components/JsonPretty/utils/index.ts +169 -169
  118. package/dist/v3/components/MovableContainer/index.vue +8 -4
  119. package/dist/v3/components/Pick/index.vue +322 -322
  120. package/dist/v3/components/Tag/index.vue +113 -113
  121. package/dist/v3/components/VirtualList/AutoSize.vue +40 -40
  122. package/dist/v3/components/VirtualList/index.vue +416 -416
  123. package/dist/v3/hooks/useBluetooth/index.ts +561 -561
  124. package/dist/v3/hooks/useContainerStyle.ts +153 -153
  125. package/dist/v3/hooks/useNFC/index.ts +107 -107
  126. package/dist/v3/hooks/useNFC/typing.d.ts +396 -396
  127. package/dist/v3/hooks/useNFC/useNFCAndroid.ts +966 -966
  128. package/dist/v3/hooks/useNFC/useNFCMpWeiXin.ts +812 -812
  129. package/dist/v3/hooks/useNFC/utils.ts +754 -754
  130. package/dist/v3/hooks/useRequest/index.ts +586 -586
  131. package/dist/v3/hooks/useRequest/utils.ts +267 -267
  132. package/dist/v3/hooks/useScanCode/index.ts +206 -206
  133. package/dist/v3/hooks/useWebsocket/index.ts +253 -253
  134. package/dist/v3/styles/theme.ts +12 -12
  135. package/package.json +9 -1
@@ -51,12 +51,16 @@ watch([() => props.x, () => props.y], ([newX, newY]) => {
51
51
  });
52
52
 
53
53
  const areaStyle = computed(() => {
54
- const { _paddingBottom, paddingTop, ...rest } = (props.customStyle ||
55
- {}) as any;
54
+ const style = (props.customStyle || {}) as any;
55
+ const { paddingBottom, paddingTop, ...rest } = style;
56
+
57
+ const top = parseInt(paddingTop) || 0;
58
+ const bottom = parseInt(paddingBottom) || 0;
59
+
56
60
  return {
57
61
  ...rest,
58
- top: paddingTop || 0,
59
- height: props.contentHeight + 'px',
62
+ top: top + 'px',
63
+ height: props.contentHeight + bottom + 'px',
60
64
  position: 'fixed' as const,
61
65
  left: 0,
62
66
  width: '100vw',
@@ -1,322 +1,322 @@
1
- <template>
2
- <view class="pick-wrapper" :style="customStyle">
3
- <!-- Trigger Area -->
4
- <view
5
- :class="`pick-trigger ${!modelValue ? 'pick-trigger-placeholder' : ''}`"
6
- @click="onOpenPick">
7
- <text class="pick-trigger-text">
8
- {{ label || placeholder || '请选择' }}
9
- </text>
10
- <view class="pick-handle">
11
- <view
12
- v-if="allowClear && modelValue"
13
- class="pick-clear"
14
- @click.stop="onClear">
15
- ×
16
- </view>
17
- <view :class="['pick-arrow', isActive ? 'pick-arrow-active' : '']">
18
- >
19
- </view>
20
- </view>
21
- </view>
22
-
23
- <!-- Popup Modal -->
24
- <view class="pick-mask" v-if="isActive" @click="onClosePick">
25
- <view class="pick-modal" @click.stop>
26
- <!-- Header -->
27
- <view class="pick-header">
28
- <text class="pick-title">{{ placeholder || '请选择' }}</text>
29
- <view class="pick-close" @click="onClosePick">×</view>
30
- </view>
31
-
32
- <!-- Search -->
33
- <view class="pick-search" v-if="!readonly">
34
- <input
35
- class="pick-search-input"
36
- :value="searchText"
37
- placeholder="搜索..."
38
- @input="debounceInput"
39
- :focus="isActive" />
40
- </view>
41
-
42
- <!-- List -->
43
- <scroll-view scroll-y class="pick-list">
44
- <view
45
- v-for="item in filteredOptions"
46
- :key="item.value"
47
- :class="[
48
- 'pick-item',
49
- item.value === modelValue ? 'pick-item-active' : '',
50
- ]"
51
- @click="onSelect(item)">
52
- <text class="pick-item-text">{{ item.label }}</text>
53
- <text v-if="item.value === modelValue" class="pick-item-check">
54
-
55
- </text>
56
- </view>
57
- <view v-if="filteredOptions.length === 0" class="pick-empty">
58
- 暂无数据
59
- </view>
60
- </scroll-view>
61
- </view>
62
- </view>
63
- </view>
64
- </template>
65
-
66
- <script lang="ts" setup>
67
- import { debounce } from '../../../utils';
68
- import { ref, computed } from 'vue';
69
-
70
- const props = defineProps<{
71
- placeholder?: string;
72
- readonly?: boolean;
73
- allowClear?: boolean;
74
- options?: { label: string; value: any }[];
75
- customStyle?: Record<string, any> | string;
76
- }>();
77
-
78
- const modelValue = defineModel<string>('modelValue');
79
-
80
- const emit = defineEmits<{
81
- (e: 'search', value: string): void;
82
- (e: 'openSearch', value: boolean): void;
83
- (e: 'change', value: { label: string; value: any }): void;
84
- }>();
85
-
86
- const isActive = ref(false);
87
- const searchText = ref('');
88
-
89
- // Computed label for the trigger
90
- const label = computed(() => {
91
- return (
92
- props.options?.find((item) => item.value === modelValue.value)?.label ??
93
- modelValue.value
94
- );
95
- });
96
-
97
- const filteredOptions = computed(() => {
98
- if (!searchText.value) return props.options || [];
99
- const lowerSearch = searchText.value.toLowerCase();
100
- return (props.options || []).filter(
101
- (item) => item.label && item.label.toLowerCase().includes(lowerSearch),
102
- );
103
- });
104
-
105
- function onOpenPick() {
106
- isActive.value = true;
107
- searchText.value = '';
108
- emit('openSearch', true);
109
- }
110
-
111
- function onClosePick() {
112
- isActive.value = false;
113
- emit('openSearch', false);
114
- }
115
-
116
- function onInput(e: any) {
117
- const value = e.detail?.value ?? e.target?.value;
118
- searchText.value = value;
119
- emit('search', value);
120
- }
121
-
122
- const debounceInput = debounce(onInput, 300);
123
-
124
- function onSelect(item: { label: string; value: any }) {
125
- modelValue.value = item.value;
126
- emit('change', item);
127
- onClosePick();
128
- }
129
-
130
- function onClear() {
131
- modelValue.value = '';
132
- emit('search', '');
133
- emit('change', { label: '', value: '' });
134
- }
135
- </script>
136
-
137
- <style scoped>
138
- .pick-wrapper {
139
- position: relative;
140
- width: 100%;
141
- }
142
-
143
- .pick-trigger {
144
- display: flex;
145
- align-items: center;
146
- justify-content: space-between;
147
- width: 100%;
148
- min-width: 0;
149
- height: 24px; /* Slightly taller for easier click */
150
- padding: 0 10px;
151
- border-radius: 4px;
152
- border: 1px solid var(--dev-tool-border-color);
153
- background-color: var(--dev-tool-bg-color);
154
- transition: all 0.3s;
155
- box-sizing: border-box;
156
- cursor: pointer;
157
- }
158
-
159
- .pick-trigger:hover {
160
- border-color: var(--dev-tool-active-color, #409eff);
161
- }
162
-
163
- .pick-trigger-placeholder .pick-trigger-text {
164
- color: var(--dev-tool-text-color-placeholder, #999);
165
- }
166
-
167
- .pick-trigger-text {
168
- flex: 1;
169
- overflow: hidden;
170
- text-overflow: ellipsis;
171
- white-space: nowrap;
172
- color: var(--dev-tool-text-color);
173
- }
174
-
175
- .pick-handle {
176
- display: flex;
177
- align-items: center;
178
- }
179
-
180
- .pick-arrow {
181
- padding-left: 4px;
182
- color: #999;
183
- font-family: monospace;
184
- font-weight: bold;
185
- transform: rotate(90deg);
186
- transition: transform 0.3s;
187
- position: relative;
188
- top: -1px;
189
- }
190
-
191
- .pick-arrow-active {
192
- transform: rotate(-90deg);
193
- }
194
-
195
- .pick-clear {
196
- padding-left: 8px;
197
- font-size: 16px;
198
- color: #999;
199
- }
200
-
201
- .pick-mask {
202
- position: fixed;
203
- inset: 0;
204
- background-color: rgb(0 0 0 / 40%);
205
- z-index: 10000;
206
- display: flex;
207
- align-items: center;
208
- justify-content: center;
209
- backdrop-filter: blur(2px);
210
- }
211
-
212
- .pick-modal {
213
- width: 80%;
214
- max-width: 400px;
215
- height: 60vh;
216
- max-height: 500px;
217
- background-color: var(--dev-tool-bg-color);
218
- border-radius: 12px;
219
- box-shadow: 0 8px 24px rgb(0 0 0 / 15%);
220
- display: flex;
221
- flex-direction: column;
222
- overflow: hidden;
223
- animation: pick-pop-in 0.2s ease-out;
224
- }
225
-
226
- @keyframes pick-pop-in {
227
- from {
228
- opacity: 0;
229
- transform: scale(0.95);
230
- }
231
-
232
- to {
233
- opacity: 1;
234
- transform: scale(1);
235
- }
236
- }
237
-
238
- .pick-header {
239
- display: flex;
240
- align-items: center;
241
- justify-content: space-between;
242
- padding: 12px 16px;
243
- border-bottom: 1px solid var(--dev-tool-border-color);
244
- }
245
-
246
- .pick-title {
247
- font-weight: 600;
248
- color: var(--dev-tool-text-color);
249
- }
250
-
251
- .pick-close {
252
- font-size: 20px;
253
- color: #999;
254
- padding: 4px;
255
- cursor: pointer;
256
- }
257
-
258
- .pick-search {
259
- padding: 10px 16px;
260
- border-bottom: 1px solid var(--dev-tool-border-color);
261
- }
262
-
263
- .pick-search-input {
264
- width: 100%;
265
- height: 36px;
266
- padding: 0 12px;
267
- border-radius: 6px;
268
- background-color: var(--dev-tool-bg2-color, #f5f5f5);
269
- border: 1px solid transparent;
270
- box-sizing: border-box;
271
- color: var(--dev-tool-text-color);
272
- }
273
-
274
- .pick-search-input:focus {
275
- border-color: var(--dev-tool-active-color, #409eff);
276
- background-color: var(--dev-tool-bg-color);
277
- }
278
-
279
- .pick-list {
280
- flex: 1;
281
- overflow-y: auto;
282
- padding: 8px 0;
283
- }
284
-
285
- .pick-item {
286
- display: flex;
287
- align-items: center;
288
- justify-content: space-between;
289
- padding: 12px 16px;
290
- cursor: pointer;
291
- transition: background-color 0.2s;
292
- }
293
-
294
- .pick-item:hover,
295
- .pick-item:active {
296
- background-color: var(--dev-tool-hover-bg-color, rgb(0 0 0 / 5%));
297
- }
298
-
299
- .pick-item-active {
300
- background-color: var(--dev-tool-active-bg-color, rgb(64 158 255 / 10%));
301
- }
302
-
303
- .pick-item-active .pick-item-text {
304
- color: var(--dev-tool-active-color, #409eff);
305
- font-weight: 500;
306
- }
307
-
308
- .pick-item-text {
309
- color: var(--dev-tool-text-color);
310
- }
311
-
312
- .pick-item-check {
313
- color: var(--dev-tool-active-color, #409eff);
314
- font-weight: bold;
315
- }
316
-
317
- .pick-empty {
318
- padding: 24px;
319
- text-align: center;
320
- color: #999;
321
- }
322
- </style>
1
+ <template>
2
+ <view class="pick-wrapper" :style="customStyle">
3
+ <!-- Trigger Area -->
4
+ <view
5
+ :class="`pick-trigger ${!modelValue ? 'pick-trigger-placeholder' : ''}`"
6
+ @click="onOpenPick">
7
+ <text class="pick-trigger-text">
8
+ {{ label || placeholder || '请选择' }}
9
+ </text>
10
+ <view class="pick-handle">
11
+ <view
12
+ v-if="allowClear && modelValue"
13
+ class="pick-clear"
14
+ @click.stop="onClear">
15
+ ×
16
+ </view>
17
+ <view :class="['pick-arrow', isActive ? 'pick-arrow-active' : '']">
18
+ >
19
+ </view>
20
+ </view>
21
+ </view>
22
+
23
+ <!-- Popup Modal -->
24
+ <view class="pick-mask" v-if="isActive" @click="onClosePick">
25
+ <view class="pick-modal" @click.stop>
26
+ <!-- Header -->
27
+ <view class="pick-header">
28
+ <text class="pick-title">{{ placeholder || '请选择' }}</text>
29
+ <view class="pick-close" @click="onClosePick">×</view>
30
+ </view>
31
+
32
+ <!-- Search -->
33
+ <view class="pick-search" v-if="!readonly">
34
+ <input
35
+ class="pick-search-input"
36
+ :value="searchText"
37
+ placeholder="搜索..."
38
+ @input="debounceInput"
39
+ :focus="isActive" />
40
+ </view>
41
+
42
+ <!-- List -->
43
+ <scroll-view scroll-y class="pick-list">
44
+ <view
45
+ v-for="item in filteredOptions"
46
+ :key="item.value"
47
+ :class="[
48
+ 'pick-item',
49
+ item.value === modelValue ? 'pick-item-active' : '',
50
+ ]"
51
+ @click="onSelect(item)">
52
+ <text class="pick-item-text">{{ item.label }}</text>
53
+ <text v-if="item.value === modelValue" class="pick-item-check">
54
+
55
+ </text>
56
+ </view>
57
+ <view v-if="filteredOptions.length === 0" class="pick-empty">
58
+ 暂无数据
59
+ </view>
60
+ </scroll-view>
61
+ </view>
62
+ </view>
63
+ </view>
64
+ </template>
65
+
66
+ <script lang="ts" setup>
67
+ import { debounce } from '../../../utils';
68
+ import { ref, computed } from 'vue';
69
+
70
+ const props = defineProps<{
71
+ placeholder?: string;
72
+ readonly?: boolean;
73
+ allowClear?: boolean;
74
+ options?: { label: string; value: any }[];
75
+ customStyle?: Record<string, any> | string;
76
+ }>();
77
+
78
+ const modelValue = defineModel<string>('modelValue');
79
+
80
+ const emit = defineEmits<{
81
+ (e: 'search', value: string): void;
82
+ (e: 'openSearch', value: boolean): void;
83
+ (e: 'change', value: { label: string; value: any }): void;
84
+ }>();
85
+
86
+ const isActive = ref(false);
87
+ const searchText = ref('');
88
+
89
+ // Computed label for the trigger
90
+ const label = computed(() => {
91
+ return (
92
+ props.options?.find((item) => item.value === modelValue.value)?.label ??
93
+ modelValue.value
94
+ );
95
+ });
96
+
97
+ const filteredOptions = computed(() => {
98
+ if (!searchText.value) return props.options || [];
99
+ const lowerSearch = searchText.value.toLowerCase();
100
+ return (props.options || []).filter(
101
+ (item) => item.label && item.label.toLowerCase().includes(lowerSearch),
102
+ );
103
+ });
104
+
105
+ function onOpenPick() {
106
+ isActive.value = true;
107
+ searchText.value = '';
108
+ emit('openSearch', true);
109
+ }
110
+
111
+ function onClosePick() {
112
+ isActive.value = false;
113
+ emit('openSearch', false);
114
+ }
115
+
116
+ function onInput(e: any) {
117
+ const value = e.detail?.value ?? e.target?.value;
118
+ searchText.value = value;
119
+ emit('search', value);
120
+ }
121
+
122
+ const debounceInput = debounce(onInput, 300);
123
+
124
+ function onSelect(item: { label: string; value: any }) {
125
+ modelValue.value = item.value;
126
+ emit('change', item);
127
+ onClosePick();
128
+ }
129
+
130
+ function onClear() {
131
+ modelValue.value = '';
132
+ emit('search', '');
133
+ emit('change', { label: '', value: '' });
134
+ }
135
+ </script>
136
+
137
+ <style scoped>
138
+ .pick-wrapper {
139
+ position: relative;
140
+ width: 100%;
141
+ }
142
+
143
+ .pick-trigger {
144
+ display: flex;
145
+ align-items: center;
146
+ justify-content: space-between;
147
+ width: 100%;
148
+ min-width: 0;
149
+ height: 24px; /* Slightly taller for easier click */
150
+ padding: 0 10px;
151
+ border-radius: 4px;
152
+ border: 1px solid var(--dev-tool-border-color);
153
+ background-color: var(--dev-tool-bg-color);
154
+ transition: all 0.3s;
155
+ box-sizing: border-box;
156
+ cursor: pointer;
157
+ }
158
+
159
+ .pick-trigger:hover {
160
+ border-color: var(--dev-tool-active-color, #409eff);
161
+ }
162
+
163
+ .pick-trigger-placeholder .pick-trigger-text {
164
+ color: var(--dev-tool-text-color-placeholder, #999);
165
+ }
166
+
167
+ .pick-trigger-text {
168
+ flex: 1;
169
+ overflow: hidden;
170
+ text-overflow: ellipsis;
171
+ white-space: nowrap;
172
+ color: var(--dev-tool-text-color);
173
+ }
174
+
175
+ .pick-handle {
176
+ display: flex;
177
+ align-items: center;
178
+ }
179
+
180
+ .pick-arrow {
181
+ padding-left: 4px;
182
+ color: #999;
183
+ font-family: monospace;
184
+ font-weight: bold;
185
+ transform: rotate(90deg);
186
+ transition: transform 0.3s;
187
+ position: relative;
188
+ top: -1px;
189
+ }
190
+
191
+ .pick-arrow-active {
192
+ transform: rotate(-90deg);
193
+ }
194
+
195
+ .pick-clear {
196
+ padding-left: 8px;
197
+ font-size: 16px;
198
+ color: #999;
199
+ }
200
+
201
+ .pick-mask {
202
+ position: fixed;
203
+ inset: 0;
204
+ background-color: rgb(0 0 0 / 40%);
205
+ z-index: 10000;
206
+ display: flex;
207
+ align-items: center;
208
+ justify-content: center;
209
+ backdrop-filter: blur(2px);
210
+ }
211
+
212
+ .pick-modal {
213
+ width: 80%;
214
+ max-width: 400px;
215
+ height: 60vh;
216
+ max-height: 500px;
217
+ background-color: var(--dev-tool-bg-color);
218
+ border-radius: 12px;
219
+ box-shadow: 0 8px 24px rgb(0 0 0 / 15%);
220
+ display: flex;
221
+ flex-direction: column;
222
+ overflow: hidden;
223
+ animation: pick-pop-in 0.2s ease-out;
224
+ }
225
+
226
+ @keyframes pick-pop-in {
227
+ from {
228
+ opacity: 0;
229
+ transform: scale(0.95);
230
+ }
231
+
232
+ to {
233
+ opacity: 1;
234
+ transform: scale(1);
235
+ }
236
+ }
237
+
238
+ .pick-header {
239
+ display: flex;
240
+ align-items: center;
241
+ justify-content: space-between;
242
+ padding: 12px 16px;
243
+ border-bottom: 1px solid var(--dev-tool-border-color);
244
+ }
245
+
246
+ .pick-title {
247
+ font-weight: 600;
248
+ color: var(--dev-tool-text-color);
249
+ }
250
+
251
+ .pick-close {
252
+ font-size: 20px;
253
+ color: #999;
254
+ padding: 4px;
255
+ cursor: pointer;
256
+ }
257
+
258
+ .pick-search {
259
+ padding: 10px 16px;
260
+ border-bottom: 1px solid var(--dev-tool-border-color);
261
+ }
262
+
263
+ .pick-search-input {
264
+ width: 100%;
265
+ height: 36px;
266
+ padding: 0 12px;
267
+ border-radius: 6px;
268
+ background-color: var(--dev-tool-bg2-color, #f5f5f5);
269
+ border: 1px solid transparent;
270
+ box-sizing: border-box;
271
+ color: var(--dev-tool-text-color);
272
+ }
273
+
274
+ .pick-search-input:focus {
275
+ border-color: var(--dev-tool-active-color, #409eff);
276
+ background-color: var(--dev-tool-bg-color);
277
+ }
278
+
279
+ .pick-list {
280
+ flex: 1;
281
+ overflow-y: auto;
282
+ padding: 8px 0;
283
+ }
284
+
285
+ .pick-item {
286
+ display: flex;
287
+ align-items: center;
288
+ justify-content: space-between;
289
+ padding: 12px 16px;
290
+ cursor: pointer;
291
+ transition: background-color 0.2s;
292
+ }
293
+
294
+ .pick-item:hover,
295
+ .pick-item:active {
296
+ background-color: var(--dev-tool-hover-bg-color, rgb(0 0 0 / 5%));
297
+ }
298
+
299
+ .pick-item-active {
300
+ background-color: var(--dev-tool-active-bg-color, rgb(64 158 255 / 10%));
301
+ }
302
+
303
+ .pick-item-active .pick-item-text {
304
+ color: var(--dev-tool-active-color, #409eff);
305
+ font-weight: 500;
306
+ }
307
+
308
+ .pick-item-text {
309
+ color: var(--dev-tool-text-color);
310
+ }
311
+
312
+ .pick-item-check {
313
+ color: var(--dev-tool-active-color, #409eff);
314
+ font-weight: bold;
315
+ }
316
+
317
+ .pick-empty {
318
+ padding: 24px;
319
+ text-align: center;
320
+ color: #999;
321
+ }
322
+ </style>