vite-uni-dev-tool 0.0.1

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 (69) hide show
  1. package/README.md +120 -0
  2. package/dev/components/Button/index.vue +34 -0
  3. package/dev/components/Checkbox/index.vue +40 -0
  4. package/dev/components/CloseButton/index.vue +25 -0
  5. package/dev/components/Connection/index.vue +98 -0
  6. package/dev/components/ConsoleList/ConsoleItem.vue +89 -0
  7. package/dev/components/ConsoleList/index.vue +98 -0
  8. package/dev/components/DevTool/index.vue +165 -0
  9. package/dev/components/DevToolButton/index.vue +213 -0
  10. package/dev/components/DevToolWindow/index.vue +847 -0
  11. package/dev/components/DeviceInfo/index.vue +32 -0
  12. package/dev/components/Empty/empty.png +0 -0
  13. package/dev/components/Empty/index.vue +28 -0
  14. package/dev/components/FilterInput/index.vue +86 -0
  15. package/dev/components/JsonPretty/components/Brackets/index.vue +23 -0
  16. package/dev/components/JsonPretty/components/Carets/index.vue +63 -0
  17. package/dev/components/JsonPretty/components/CheckController/index.vue +108 -0
  18. package/dev/components/JsonPretty/components/TreeNode/index.vue +348 -0
  19. package/dev/components/JsonPretty/hooks/useClipboard.ts +21 -0
  20. package/dev/components/JsonPretty/hooks/useError.ts +21 -0
  21. package/dev/components/JsonPretty/index.vue +463 -0
  22. package/dev/components/JsonPretty/type.ts +123 -0
  23. package/dev/components/JsonPretty/utils/index.ts +172 -0
  24. package/dev/components/NetworkList/NetworkDetail.vue +197 -0
  25. package/dev/components/NetworkList/NetworkItem.vue +106 -0
  26. package/dev/components/NetworkList/index.vue +108 -0
  27. package/dev/components/PiniaList/index.vue +64 -0
  28. package/dev/components/RouteList/index.vue +98 -0
  29. package/dev/components/SettingList/index.vue +235 -0
  30. package/dev/components/StorageList/index.vue +170 -0
  31. package/dev/components/SystemInfo/index.vue +34 -0
  32. package/dev/components/Tabs/index.vue +110 -0
  33. package/dev/components/Tag/index.vue +89 -0
  34. package/dev/components/UploadList/UploadDetail.vue +208 -0
  35. package/dev/components/UploadList/UploadItem.vue +111 -0
  36. package/dev/components/UploadList/index.vue +94 -0
  37. package/dev/components/VuexList/index.vue +54 -0
  38. package/dev/components/WebSocket/WebSocketItem.vue +98 -0
  39. package/dev/components/WebSocket/WebSocketList.vue +176 -0
  40. package/dev/components/WebSocket/index.vue +99 -0
  41. package/dev/components/WindowInfo/index.vue +33 -0
  42. package/dev/const.ts +95 -0
  43. package/dev/core.ts +103 -0
  44. package/dev/devConsole/index.ts +334 -0
  45. package/dev/devEvent/index.ts +665 -0
  46. package/dev/devIntercept/index.ts +629 -0
  47. package/dev/devStore/index.ts +581 -0
  48. package/dev/index.d.ts +6 -0
  49. package/dev/index.d.ts.map +1 -0
  50. package/dev/index.js +1 -0
  51. package/dev/plugins/uniDevTool/uniDevTool.d.ts +66 -0
  52. package/dev/plugins/uniDevTool/uniDevTool.d.ts.map +1 -0
  53. package/dev/plugins/uniDevTool/uniDevTool.js +13 -0
  54. package/dev/plugins/uniGlobalComponents/uniGlobalComponents.d.ts +28 -0
  55. package/dev/plugins/uniGlobalComponents/uniGlobalComponents.d.ts.map +1 -0
  56. package/dev/plugins/uniGlobalComponents/uniGlobalComponents.js +5 -0
  57. package/dev/shims-uni.d.ts +43 -0
  58. package/dev/type.ts +188 -0
  59. package/dev/utils/date.ts +75 -0
  60. package/dev/utils/file.ts +121 -0
  61. package/dev/utils/function.ts +192 -0
  62. package/dev/utils/index.ts +25 -0
  63. package/dev/utils/ip.ts +79 -0
  64. package/dev/utils/language.ts +19 -0
  65. package/dev/utils/object.ts +235 -0
  66. package/dev/utils/page.ts +13 -0
  67. package/dev/utils/string.ts +23 -0
  68. package/dev/utils/utils.ts +198 -0
  69. package/package.json +34 -0
@@ -0,0 +1,89 @@
1
+ <template>
2
+ <view
3
+ :class="`tag tag-${mode} ${active ? 'tag-active' : ''}`"
4
+ @click="onClick"
5
+ >
6
+ <slot></slot>
7
+ </view>
8
+ </template>
9
+ <script setup lang="ts">
10
+ defineProps<{
11
+ mode:
12
+ | 'primary'
13
+ | 'warn'
14
+ | 'success'
15
+ | 'error'
16
+ | 'info'
17
+ | 'log'
18
+ | 'main'
19
+ | 'clear'
20
+ | string;
21
+ active?: boolean;
22
+ }>();
23
+ const emit = defineEmits<{ (e: 'click', event: MouseEvent): void }>();
24
+ function onClick(event: MouseEvent) {
25
+ emit('click', event);
26
+ }
27
+ </script>
28
+ <style scoped>
29
+ .tag {
30
+ display: flex;
31
+ align-items: center;
32
+ padding: 0 4px;
33
+ width: min-content;
34
+ height: 24px;
35
+ color: #fff;
36
+ border-radius: 4px;
37
+ white-space: nowrap;
38
+ box-sizing: border-box;
39
+ font-size: var(--dev-tool-tag-font-size);
40
+ cursor: pointer;
41
+ transition: all 0.3s;
42
+ }
43
+ .tag-log {
44
+ color: #000;
45
+ background-color: var(--dev-tool-border-color);
46
+ border: 1px solid var(--dev-tool-border-color);
47
+ }
48
+ .tag-info {
49
+ color: #000;
50
+ background-color: var(--dev-tool-normal-bg-color);
51
+ border: 1px solid var(--dev-tool-normal-bg-color);
52
+ }
53
+ .tag-warn {
54
+ background-color: var(--dev-tool-warn-color);
55
+ border: 1px solid var(--dev-tool-warn-color);
56
+ }
57
+ .tag-success {
58
+ background-color: var(--dev-tool-success-color);
59
+ border: 1px solid var(--dev-tool-success-color);
60
+ }
61
+ .tag-error {
62
+ background-color: var(--dev-tool-error-color);
63
+ border: 1px solid var(--dev-tool-error-color);
64
+ }
65
+ .tag-main {
66
+ background-color: var(--dev-tool-main-color);
67
+ color: #fff;
68
+ border: 1px solid var(--dev-tool-main-color);
69
+ }
70
+
71
+ .tag-primary {
72
+ color: #fff;
73
+ background-color: #0958d9;
74
+ border: 1px solid #0958d9;
75
+ }
76
+ .tag-clear {
77
+ color: #0958d9;
78
+ border: 1px solid #0958d9;
79
+ }
80
+ .tag-all {
81
+ color: #000;
82
+ border: 1px solid #000;
83
+ }
84
+
85
+ .tag-active {
86
+ border-color: var(--dev-tool-main-color);
87
+ color: var(--dev-tool-main-color);
88
+ }
89
+ </style>
@@ -0,0 +1,208 @@
1
+ <template>
2
+ <view class="upload-detail">
3
+ <view class="upload-detail-control">
4
+ <Tag
5
+ v-for="item in selectItems"
6
+ :active="currentSelect === item.value"
7
+ :mode="item.mode"
8
+ :key="item.value"
9
+ @click="onSelect(item)"
10
+ >
11
+ {{ item.label }}
12
+ </Tag>
13
+
14
+ <CloseButton style="margin-left: auto" @click="onClose" />
15
+ </view>
16
+
17
+ <view class="upload-detail-header" v-if="currentSelect === 'header'">
18
+ <view class="upload-detail-title">常规</view>
19
+ <view class="net-detail-item">
20
+ <view>请求url:</view>
21
+ <view>{{ upload.url }}</view>
22
+ </view>
23
+ <view class="net-detail-item">
24
+ <view>请求方法:</view>
25
+ <Tag mode="info">{{ upload.method ?? 'POST' }}</Tag>
26
+ </view>
27
+ <view class="net-detail-item">
28
+ <view>状态代码:</view>
29
+ <Tag mode="info">{{ upload.status }}</Tag>
30
+ </view>
31
+ <view class="upload-detail-title">请求头</view>
32
+ <view
33
+ class="net-detail-item"
34
+ v-for="item in upload?.headers?.requestHeader"
35
+ :key="item.key"
36
+ >
37
+ <view>{{ item.key }}:</view>
38
+ {{ item.value }}
39
+ </view>
40
+ <!-- <view class="upload-detail-title">响应头</view>
41
+ <view
42
+ class="net-detail-item"
43
+ v-for="item in upload?.headers?.responseHeader"
44
+ :key="item.key"
45
+ >
46
+ <view>{{ item.key }}:</view>
47
+ {{ item.value }}
48
+ </view> -->
49
+ </view>
50
+
51
+ <template v-if="currentSelect === 'formdata'">
52
+ <template v-if="formData?.type === 'object'">
53
+ <JsonPretty :data="formData.value" />
54
+ </template>
55
+ <view
56
+ v-else-if="formData?.type === 'string'"
57
+ class="upload-detail-payload"
58
+ >
59
+ {{ formData.value }}
60
+ </view>
61
+ <Empty v-else />
62
+ </template>
63
+
64
+ <template v-if="currentSelect === 'response'">
65
+ <template v-if="response?.type === 'object'">
66
+ <JsonPretty :data="response.value" virtual />
67
+ </template>
68
+ <view
69
+ v-else-if="response?.type === 'string'"
70
+ class="upload-detail-payload"
71
+ >
72
+ {{ response.value }}
73
+ </view>
74
+ <Empty v-else />
75
+ </template>
76
+ </view>
77
+ </template>
78
+ <script lang="ts" setup>
79
+ import { ref, computed } from 'vue';
80
+ import JsonPretty from '../JsonPretty/index.vue';
81
+ import Tag from '../Tag/index.vue';
82
+ import Empty from '../Empty/index.vue';
83
+ import CloseButton from '../CloseButton/index.vue';
84
+ import type { DevTool } from '../../type';
85
+ const props = defineProps<{ upload: DevTool.UploadItem }>();
86
+ const emit = defineEmits<{ (e: 'close'): void }>();
87
+ const selectItems = [
88
+ {
89
+ label: 'header',
90
+ value: 'header',
91
+ mode: 'info',
92
+ },
93
+ {
94
+ label: 'formdata',
95
+ value: 'formdata',
96
+ mode: 'info',
97
+ },
98
+ {
99
+ label: 'response',
100
+ value: 'response',
101
+ mode: 'info',
102
+ },
103
+ ];
104
+ const currentSelect = ref('header');
105
+
106
+ const formData = computed(() => {
107
+ try {
108
+ if (props.upload.formData) {
109
+ return {
110
+ value: JSON.parse(JSON.stringify(props.upload.formData)),
111
+ type: 'object',
112
+ };
113
+ }
114
+ return {
115
+ value: {},
116
+ type: 'empty',
117
+ };
118
+ } catch (error) {
119
+ return {
120
+ value: JSON.parse(JSON.stringify(props.upload.formData)),
121
+ type: 'object',
122
+ };
123
+ }
124
+ });
125
+
126
+ const response = computed(() => {
127
+ try {
128
+ if (props.upload.response) {
129
+ return {
130
+ value: JSON.parse(JSON.stringify(props.upload.response)),
131
+ type: 'object',
132
+ };
133
+ }
134
+ return {
135
+ value: {},
136
+ type: 'empty',
137
+ };
138
+ } catch (error) {
139
+ return {
140
+ value: props.upload.response,
141
+ type: props.upload.response ? 'string' : 'empty',
142
+ };
143
+ }
144
+ });
145
+
146
+ function onSelect(item: { label: string; value: string }) {
147
+ currentSelect.value = item.value;
148
+ }
149
+
150
+ function onClose() {
151
+ emit('close');
152
+ }
153
+ </script>
154
+ <style>
155
+ .upload-detail {
156
+ position: fixed;
157
+ width: 100vw;
158
+ height: 100vh;
159
+ z-index: 10000;
160
+ top: 0;
161
+ left: 0;
162
+ padding: 0 16px;
163
+ /* #ifdef H5 */
164
+ padding: 50px 16px;
165
+ /* #endif */
166
+
167
+ background-color: rgba(255, 255, 255, 0.95);
168
+ box-sizing: border-box;
169
+ }
170
+ .upload-detail .upload-detail-control {
171
+ display: flex;
172
+ align-items: center;
173
+ margin-bottom: 4px;
174
+ gap: 12px;
175
+ height: 32px;
176
+ border-bottom: 1px solid transparent;
177
+ box-sizing: border-box;
178
+ }
179
+
180
+ .upload-detail .upload-detail-close {
181
+ flex-shrink: 0;
182
+ display: flex;
183
+ align-items: center;
184
+ justify-content: center;
185
+ width: 24px;
186
+ height: 24px;
187
+ margin-left: auto;
188
+ border-radius: 50%;
189
+ border: 1px solid #000;
190
+ box-sizing: border-box;
191
+ }
192
+
193
+ .upload-detail .upload-detail-header .net-detail-item {
194
+ display: flex;
195
+ align-items: center;
196
+ min-height: 28px;
197
+ word-break: break-all;
198
+ }
199
+ .upload-detail .upload-detail-header .net-detail-item > view:first-child {
200
+ white-space: nowrap;
201
+ margin-right: 8px;
202
+ color: #616161;
203
+ }
204
+ .upload-detail .upload-detail-payload {
205
+ word-break: break-all;
206
+ max-width: 100%;
207
+ }
208
+ </style>
@@ -0,0 +1,111 @@
1
+ <template>
2
+ <view class="upload-item">
3
+ <view class="upload-url-row">
4
+ <Tag mode="info">POST</Tag>
5
+ <view class="upload-url" v-html="upload.url" />
6
+ <Tag
7
+ mode="main"
8
+ class="upload-detail-icon"
9
+ @click="showDetail = !showDetail"
10
+ >详情</Tag
11
+ >
12
+ </view>
13
+ <view class="upload-info">
14
+ <view>
15
+ <Tag v-if="upload.status === 'pending'" mode="info">
16
+ {{ upload.status }}
17
+ </Tag>
18
+ <Tag v-if="upload.status === 'uploading'" mode="warn">
19
+ {{ upload.status }}
20
+ </Tag>
21
+ <Tag v-if="upload.status === 'success'" mode="success">
22
+ {{ upload.status }}
23
+ </Tag>
24
+ <Tag v-if="upload.status === 'error'" mode="error">
25
+ {{ upload.status }}
26
+ </Tag>
27
+ </view>
28
+ <view>进度: {{ upload.progress }}%</view>
29
+ <view>
30
+ 开始:
31
+ {{ upload.startTime ? formatDate(upload.startTime, ' HH:mm:ss') : '-' }}
32
+ </view>
33
+ <view>
34
+ 结束:
35
+ {{ upload.endTime ? formatDate(upload.endTime, ' HH:mm:ss') : '-' }}
36
+ </view>
37
+ </view>
38
+ </view>
39
+ <!-- <Transition name="slide-fade"> -->
40
+ <UploadDetail v-if="showDetail" :upload="upload" @close="onClose" />
41
+ <!-- </Transition> -->
42
+ </template>
43
+
44
+ <script lang="ts" setup>
45
+ import { ref } from 'vue';
46
+ import Tag from '../Tag/index.vue';
47
+ import UploadDetail from './UploadDetail.vue';
48
+ import { formatDate } from '../../utils';
49
+ import type { DevTool } from '../../type';
50
+ defineProps<{
51
+ upload: DevTool.UploadItem;
52
+ }>();
53
+ const showDetail = ref(false);
54
+
55
+ function onClose() {
56
+ showDetail.value = false;
57
+ }
58
+ </script>
59
+ <style scoped>
60
+ .upload-item {
61
+ padding: 16px;
62
+ border-bottom: 1px solid var(--dev-tool-border-color);
63
+ font-size: var(--dev-tool-base-font-size);
64
+ }
65
+ .upload-item .upload-url-row {
66
+ display: flex;
67
+ align-items: center;
68
+ word-break: break-all;
69
+ }
70
+ .websocket-item .websocket-url-row .websocket-url {
71
+ margin-left: 4px;
72
+ flex: 1;
73
+ white-space: nowrap;
74
+ overflow: hidden;
75
+ text-overflow: ellipsis;
76
+ }
77
+
78
+ .upload-item .upload-url-row .upload-detail-icon {
79
+ flex-shrink: 0;
80
+ margin-left: auto;
81
+ }
82
+ .upload-url {
83
+ margin-left: 4px;
84
+ flex: 1;
85
+ white-space: nowrap;
86
+ overflow: hidden;
87
+ text-overflow: ellipsis;
88
+ }
89
+ .upload-item .upload-url-row .upload-detail-active {
90
+ transform: rotate(135deg);
91
+ }
92
+ .upload-item .upload-info {
93
+ display: flex;
94
+ align-items: center;
95
+ justify-content: space-between;
96
+ margin-top: 4px;
97
+ color: #616161;
98
+ }
99
+
100
+ .slide-fade-enter-active {
101
+ transition: all 0.8s ease-out;
102
+ }
103
+ .slide-fade-leave-active {
104
+ transition: all 0.8s cubic-bezier(1, 0.5, 0.8, 1);
105
+ }
106
+ .slide-fade-enter-from,
107
+ .slide-fade-leave-to {
108
+ transform: translateY(20px);
109
+ opacity: 0;
110
+ }
111
+ </style>
@@ -0,0 +1,94 @@
1
+ <template>
2
+ <view class="upload-content">
3
+ <view class="upload-control">
4
+ <FilterInput
5
+ :modelValue="modelValue"
6
+ placeholder="查询url"
7
+ @search="emit('search', $event)"
8
+ @update:modelValue="emit('update:modelValue', $event)"
9
+ />
10
+ <Tag
11
+ v-for="item in uploadFilterItems"
12
+ :mode="item.mode"
13
+ :key="item.value"
14
+ :active="item.value === currentUploadType"
15
+ @click="onChoose(item.value)"
16
+ >
17
+ {{ item.label }}
18
+ </Tag>
19
+ </view>
20
+ <view class="upload-list">
21
+ <UploadItem v-for="item in uploadList" :upload="item" :key="item.index" />
22
+ <Empty v-if="!uploadList || uploadList.length === 0" />
23
+ </view>
24
+ </view>
25
+ </template>
26
+ <script lang="ts" setup>
27
+ import Tag from '../Tag/index.vue';
28
+ import UploadItem from './UploadItem.vue';
29
+ import Empty from '../Empty/index.vue';
30
+ import FilterInput from '../FilterInput/index.vue';
31
+ import type { DevTool } from '../../type';
32
+ defineProps<{
33
+ currentUploadType: string;
34
+ uploadList: DevTool.UploadItem[];
35
+ modelValue: string;
36
+ }>();
37
+
38
+ const emit = defineEmits<{
39
+ (e: 'choose', type: string): void;
40
+ (e: 'update:modelValue', value: string): void;
41
+ (e: 'search', value: string): void;
42
+ }>();
43
+ const uploadFilterItems = [
44
+ {
45
+ label: '全部',
46
+ value: 'all',
47
+ mode: 'all',
48
+ },
49
+ {
50
+ label: 'pending',
51
+ value: 'pending',
52
+ mode: 'info',
53
+ },
54
+ {
55
+ label: 'success',
56
+ value: 'success',
57
+ mode: 'success',
58
+ },
59
+ {
60
+ label: 'error',
61
+ value: 'error',
62
+ mode: 'error',
63
+ },
64
+ {
65
+ label: '清除',
66
+ value: 'clear',
67
+ mode: 'clear',
68
+ },
69
+ ];
70
+
71
+ function onChoose(type: string) {
72
+ emit('choose', type);
73
+ }
74
+ </script>
75
+ <style scoped>
76
+ .upload-content {
77
+ height: 100%;
78
+ font-size: var(--dev-tool-base-font-size);
79
+ }
80
+ .upload-list {
81
+ height: calc(100% - 32px);
82
+ overflow: auto;
83
+ }
84
+ .upload-control {
85
+ display: flex;
86
+ align-items: center;
87
+ justify-content: space-between;
88
+ gap: 8px;
89
+ padding: 0 16px;
90
+ height: 32px;
91
+ border-bottom: 1px solid var(--dev-tool-border-color);
92
+ box-sizing: border-box;
93
+ }
94
+ </style>
@@ -0,0 +1,54 @@
1
+ <template>
2
+ <view class="vuex-content">
3
+ <JsonPretty
4
+ :data="vuexList"
5
+ showLength
6
+ editable
7
+ v-if="showJson"
8
+ @update:data="onUpdateData"
9
+ @nodeClick="onNodeClick"
10
+ />
11
+ <Empty v-else />
12
+ </view>
13
+ </template>
14
+ <script lang="ts" setup>
15
+ import { computed, ref } from 'vue';
16
+ import JsonPretty from '../JsonPretty/index.vue';
17
+ import Empty from '../Empty/index.vue';
18
+ const props = defineProps<{
19
+ vuexList: Record<string, any>;
20
+ }>();
21
+ const emit = defineEmits<{
22
+ (e: 'update:vuexList', data: Record<string, any>): void;
23
+ (e: 'diffValue', value: any): void;
24
+ }>();
25
+ const showJson = computed(() => {
26
+ try {
27
+ const str = JSON.stringify(props.vuexList);
28
+ if (typeof props.vuexList === 'object' && (str === '' || str === '{}')) {
29
+ return false;
30
+ }
31
+ return true;
32
+ } catch (error) {
33
+ return false;
34
+ }
35
+ });
36
+
37
+ let currentSelect: any;
38
+ function onUpdateData(data: Record<string, any>) {
39
+ const firstKey = currentSelect?.path.split('.')?.slice(1)?.[0];
40
+ emit('update:vuexList', data);
41
+ emit('diffValue', {
42
+ [firstKey]: data[firstKey]
43
+ });
44
+ }
45
+ function onNodeClick(node: any) {
46
+ currentSelect = node;
47
+ }
48
+ </script>
49
+ <style scoped>
50
+ .vuex-content {
51
+ padding: 16px;
52
+ font-size: var(--dev-tool-base-font-size);
53
+ }
54
+ </style>
@@ -0,0 +1,98 @@
1
+ <template>
2
+ <view class="websocket-item">
3
+ <view class="websocket-url-row">
4
+ <Tag mode="info" v-if="ws.readyState === 'connection'">con</Tag>
5
+ <Tag mode="success" v-if="ws.readyState === 'open'">open</Tag>
6
+ <Tag
7
+ mode="warn"
8
+ v-if="ws.readyState === 'closing' || ws.readyState === 'closed'"
9
+ >
10
+ close
11
+ </Tag>
12
+
13
+ <Tag mode="error" v-if="ws.readyState === 'error'">error</Tag>
14
+
15
+ <view class="websocket-url" v-html="ws.url" />
16
+
17
+ <Tag
18
+ mode="main"
19
+ class="websocket-detail-icon"
20
+ @click="showDetail = !showDetail"
21
+ >
22
+ 详情
23
+ </Tag>
24
+ </view>
25
+ <view class="websocket-info">
26
+ <view class="websocket-info-last">
27
+ {{ ws?.message?.[ws.message.length - 1]?.data }}
28
+ </view>
29
+
30
+ <view>{{
31
+ ws?.message?.[ws.message.length - 1].time
32
+ ? formatDate(ws?.message?.[ws.message.length - 1].time, 'HH:mm:ss')
33
+ : '-'
34
+ }}</view>
35
+ </view>
36
+
37
+ <WebSocketList v-if="showDetail" :ws="ws" @close="onClose" />
38
+ </view>
39
+ </template>
40
+ <script lang="ts" setup>
41
+ import { ref } from 'vue';
42
+
43
+ import Tag from '../Tag/index.vue';
44
+ import WebSocketList from './WebSocketList.vue';
45
+ import { formatDate } from '../../utils';
46
+ import type { DevTool } from '../../type';
47
+
48
+ defineProps<{ ws: DevTool.WS }>();
49
+ const showDetail = ref(false);
50
+
51
+ function onClose() {
52
+ showDetail.value = false;
53
+ }
54
+ </script>
55
+ <style scoped>
56
+ .websocket-item {
57
+ padding: 16px;
58
+
59
+ box-sizing: border-box;
60
+ border-bottom: 1px solid var(--dev-tool-border-color);
61
+ font-size: var(--dev-tool-base-font-size);
62
+ }
63
+ .websocket-item .websocket-url-row {
64
+ display: flex;
65
+ align-items: center;
66
+ word-break: break-all;
67
+ }
68
+
69
+ .websocket-item .websocket-url-row .websocket-url {
70
+ margin-left: 4px;
71
+ flex: 1;
72
+ white-space: nowrap;
73
+ overflow: hidden;
74
+ text-overflow: ellipsis;
75
+ }
76
+
77
+ .websocket-item .websocket-url-row .websocket-detail-icon {
78
+ flex-shrink: 0;
79
+ margin-left: auto;
80
+ }
81
+ .websocket-item .websocket-url-row .websocket-detail-active {
82
+ transform: rotate(135deg);
83
+ }
84
+ .websocket-item .websocket-info {
85
+ display: flex;
86
+ align-items: center;
87
+ justify-content: space-between;
88
+ margin-top: 4px;
89
+ color: #616161;
90
+ }
91
+
92
+ .websocket-item .websocket-info .websocket-info-last {
93
+ white-space: nowrap;
94
+ flex: 1;
95
+ overflow: hidden;
96
+ text-overflow: ellipsis;
97
+ }
98
+ </style>