@necrolab/dashboard 0.5.14 → 0.5.16
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.
- package/backend/api.js +2 -3
- package/eslint.config.js +46 -0
- package/index.html +2 -1
- package/package.json +5 -2
- package/src/App.vue +140 -170
- package/src/assets/css/base/mixins.scss +72 -0
- package/src/assets/css/base/reset.scss +0 -2
- package/src/assets/css/base/scroll.scss +43 -36
- package/src/assets/css/base/typography.scss +9 -10
- package/src/assets/css/base/variables.scss +43 -0
- package/src/assets/css/components/accessibility.scss +37 -0
- package/src/assets/css/components/buttons.scss +58 -15
- package/src/assets/css/components/forms.scss +31 -32
- package/src/assets/css/components/headers.scss +119 -0
- package/src/assets/css/components/modals.scss +2 -2
- package/src/assets/css/components/search-groups.scss +28 -19
- package/src/assets/css/components/tables.scss +5 -7
- package/src/assets/css/components/toasts.scss +7 -7
- package/src/assets/css/components/utilities.scss +220 -0
- package/src/assets/css/main.scss +72 -75
- package/src/components/Auth/LoginForm.vue +5 -84
- package/src/components/Editors/Account/Account.vue +8 -10
- package/src/components/Editors/Account/AccountCreator.vue +28 -59
- package/src/components/Editors/Account/AccountView.vue +38 -86
- package/src/components/Editors/Account/CreateAccount.vue +8 -50
- package/src/components/Editors/Profile/CreateProfile.vue +74 -131
- package/src/components/Editors/Profile/Profile.vue +15 -17
- package/src/components/Editors/Profile/ProfileCountryChooser.vue +16 -60
- package/src/components/Editors/Profile/ProfileView.vue +46 -96
- package/src/components/Editors/TagLabel.vue +16 -55
- package/src/components/Editors/TagToggle.vue +20 -8
- package/src/components/Filter/Filter.vue +62 -75
- package/src/components/Filter/FilterPreview.vue +161 -135
- package/src/components/Filter/PriceSortToggle.vue +36 -43
- package/src/components/Table/Header.vue +1 -1
- package/src/components/Table/Table.vue +61 -12
- package/src/components/Tasks/CheckStock.vue +7 -16
- package/src/components/Tasks/Controls/DesktopControls.vue +15 -60
- package/src/components/Tasks/Controls/MobileControls.vue +5 -20
- package/src/components/Tasks/CreateTaskAXS.vue +20 -118
- package/src/components/Tasks/CreateTaskTM.vue +33 -189
- package/src/components/Tasks/EventDetailRow.vue +21 -0
- package/src/components/Tasks/MassEdit.vue +6 -16
- package/src/components/Tasks/QuickSettings.vue +140 -216
- package/src/components/Tasks/ScrapeVenue.vue +4 -13
- package/src/components/Tasks/Stats.vue +19 -38
- package/src/components/Tasks/Task.vue +65 -268
- package/src/components/Tasks/TaskLabel.vue +9 -3
- package/src/components/Tasks/TaskView.vue +43 -63
- package/src/components/Tasks/Utilities.vue +10 -42
- package/src/components/Tasks/ViewTask.vue +23 -107
- package/src/components/icons/Close.vue +2 -8
- package/src/components/icons/Gear.vue +8 -8
- package/src/components/icons/Hash.vue +5 -0
- package/src/components/icons/Key.vue +2 -8
- package/src/components/icons/Pencil.vue +2 -8
- package/src/components/icons/Profile.vue +2 -8
- package/src/components/icons/Sell.vue +2 -8
- package/src/components/icons/Spinner.vue +4 -7
- package/src/components/icons/SquareCheck.vue +2 -8
- package/src/components/icons/SquareUncheck.vue +2 -8
- package/src/components/icons/Wildcard.vue +2 -8
- package/src/components/icons/index.js +3 -1
- package/src/components/ui/ActionButtonGroup.vue +113 -52
- package/src/components/ui/BalanceIndicator.vue +60 -0
- package/src/components/ui/EmptyState.vue +24 -0
- package/src/components/ui/EnableDisableToggle.vue +23 -0
- package/src/components/ui/FormField.vue +48 -48
- package/src/components/ui/IconLabel.vue +23 -0
- package/src/components/ui/InfoRow.vue +21 -54
- package/src/components/ui/Modal.vue +78 -37
- package/src/components/ui/Navbar.vue +60 -41
- package/src/components/ui/ReadonlyFieldsSection.vue +31 -0
- package/src/components/ui/ReconnectIndicator.vue +111 -124
- package/src/components/ui/SectionCard.vue +6 -14
- package/src/components/ui/Splash.vue +2 -10
- package/src/components/ui/StatusBadge.vue +26 -28
- package/src/components/ui/TaskToggle.vue +54 -0
- package/src/components/ui/controls/CountryChooser.vue +27 -64
- package/src/components/ui/controls/EyeToggle.vue +1 -1
- package/src/components/ui/controls/atomic/Checkbox.vue +40 -121
- package/src/components/ui/controls/atomic/Dropdown.vue +102 -95
- package/src/components/ui/controls/atomic/MultiDropdown.vue +72 -94
- package/src/components/ui/controls/atomic/Switch.vue +21 -84
- package/src/composables/useColorMapping.js +15 -0
- package/src/composables/useCopyToClipboard.js +1 -1
- package/src/composables/useDateFormatting.js +21 -0
- package/src/composables/useDeviceDetection.js +14 -0
- package/src/composables/useDropdownPosition.js +5 -6
- package/src/composables/useDynamicTableHeight.js +31 -0
- package/src/composables/useRowSelection.js +0 -3
- package/src/composables/useTicketPricing.js +16 -0
- package/src/composables/useWindowDimensions.js +21 -0
- package/src/libs/Filter.js +14 -20
- package/src/libs/panzoom.js +1 -5
- package/src/libs/utils/array.js +60 -0
- package/src/{stores/utils.js → libs/utils/dataGeneration.js} +2 -250
- package/src/libs/utils/eventUrl.js +40 -0
- package/src/libs/utils/string.js +28 -0
- package/src/libs/utils/time.js +20 -0
- package/src/libs/utils/validation.js +88 -0
- package/src/main.js +0 -2
- package/src/stores/connection.js +1 -4
- package/src/stores/logger.js +6 -12
- package/src/stores/sampleData.js +1 -2
- package/src/stores/ui.js +59 -36
- package/src/views/Accounts.vue +17 -31
- package/src/views/Console.vue +76 -176
- package/src/views/Editor.vue +217 -383
- package/src/views/FilterBuilder.vue +190 -373
- package/src/views/Login.vue +3 -28
- package/src/views/Profiles.vue +12 -22
- package/src/views/Tasks.vue +51 -38
- package/tailwind.config.js +82 -71
- package/workbox-config.cjs +47 -5
- package/docs/plans/2026-02-08-tailwind-consolidation.md +0 -2416
- package/exit +0 -209
- package/run +0 -177
- package/switch-branch.sh +0 -41
- /package/public/{reconnect-logo.png → img/reconnect-logo.png} +0 -0
|
@@ -56,6 +56,7 @@ import CheckIcon from "./Check.vue";
|
|
|
56
56
|
import SpinnerIcon from "./Spinner.vue";
|
|
57
57
|
import EyeIcon from "./Eye.vue";
|
|
58
58
|
import CopyIcon from "./Copy.vue";
|
|
59
|
+
import HashIcon from "./Hash.vue";
|
|
59
60
|
|
|
60
61
|
export {
|
|
61
62
|
EditIcon,
|
|
@@ -111,5 +112,6 @@ export {
|
|
|
111
112
|
CheckIcon,
|
|
112
113
|
SpinnerIcon,
|
|
113
114
|
EyeIcon,
|
|
114
|
-
CopyIcon
|
|
115
|
+
CopyIcon,
|
|
116
|
+
HashIcon
|
|
115
117
|
};
|
|
@@ -1,70 +1,131 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<ul class="
|
|
3
|
-
bg-dark-400 border-2 border-dark-600 p-[3px] gap-0.5
|
|
4
|
-
md:p-0.5 md:gap-px md:rounded-md
|
|
5
|
-
lg:p-[3px] lg:gap-0.5 lg:rounded-lg lg:flex-nowrap
|
|
6
|
-
max-md:max-w-[44px] max-md:min-h-7 max-md:h-auto max-md:justify-start max-md:mx-0">
|
|
2
|
+
<ul class="action-button-group" :class="{ 'allow-wrap': allowWrap }">
|
|
7
3
|
<slot />
|
|
8
4
|
</ul>
|
|
9
5
|
</template>
|
|
10
6
|
|
|
11
7
|
<script setup>
|
|
12
|
-
|
|
8
|
+
defineProps({
|
|
9
|
+
allowWrap: {
|
|
10
|
+
type: Boolean,
|
|
11
|
+
default: false
|
|
12
|
+
}
|
|
13
|
+
});
|
|
13
14
|
</script>
|
|
14
15
|
|
|
15
|
-
<style
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
16
|
+
<style scoped>
|
|
17
|
+
.action-button-group {
|
|
18
|
+
@apply mx-auto bg-dark-400 border-2 border-dark-550 rounded;
|
|
19
|
+
display: flex;
|
|
20
|
+
flex-wrap: nowrap;
|
|
21
|
+
justify-content: center;
|
|
22
|
+
align-items: center;
|
|
23
|
+
padding: 3px;
|
|
24
|
+
gap: 2px;
|
|
25
|
+
width: fit-content;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.action-button-group.allow-wrap {
|
|
29
|
+
flex-wrap: wrap;
|
|
30
|
+
align-items: flex-start;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/* Desktop - no wrapping */
|
|
34
|
+
@media (min-width: 1024px) {
|
|
35
|
+
.action-button-group {
|
|
36
|
+
flex-wrap: nowrap;
|
|
37
|
+
padding: 3px;
|
|
38
|
+
gap: 2px;
|
|
39
|
+
border-radius: 0.5rem;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/* Tablet - max 3 per row */
|
|
44
|
+
@media (min-width: 768px) and (max-width: 1023px) {
|
|
45
|
+
.action-button-group {
|
|
46
|
+
max-width: 100px;
|
|
47
|
+
padding: 2px;
|
|
48
|
+
gap: 1px;
|
|
49
|
+
border-radius: 0.375rem;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/* Mobile - compact layout */
|
|
54
|
+
@media (max-width: 767px) {
|
|
55
|
+
.action-button-group {
|
|
56
|
+
max-width: 100%;
|
|
57
|
+
gap: 3px;
|
|
58
|
+
padding: 3px;
|
|
59
|
+
margin-left: 0;
|
|
60
|
+
margin-right: 0;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.action-button-group.allow-wrap {
|
|
64
|
+
justify-content: center;
|
|
44
65
|
}
|
|
66
|
+
}
|
|
45
67
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
68
|
+
/* Button base styling */
|
|
69
|
+
.action-button-group :deep(button) {
|
|
70
|
+
@apply relative flex items-center justify-center border-0 outline-0;
|
|
71
|
+
@apply bg-transparent text-light-300 flex-shrink-0 rounded-md;
|
|
72
|
+
@apply transition-all duration-150;
|
|
73
|
+
width: 28px !important;
|
|
74
|
+
height: 28px !important;
|
|
75
|
+
min-width: 28px !important;
|
|
76
|
+
min-height: 28px !important;
|
|
77
|
+
}
|
|
49
78
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
79
|
+
/* Hover effect */
|
|
80
|
+
.action-button-group :deep(button:hover) {
|
|
81
|
+
background-color: rgba(136, 201, 153, 0.15) !important;
|
|
82
|
+
color: white !important;
|
|
83
|
+
transform: scale(1.03) !important;
|
|
84
|
+
}
|
|
54
85
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
86
|
+
/* Active effect */
|
|
87
|
+
.action-button-group :deep(button:active) {
|
|
88
|
+
background-color: rgba(136, 201, 153, 0.25) !important;
|
|
89
|
+
transform: scale(0.98) !important;
|
|
90
|
+
}
|
|
59
91
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
92
|
+
/* Icon sizing */
|
|
93
|
+
.action-button-group :deep(svg),
|
|
94
|
+
.action-button-group :deep(img) {
|
|
95
|
+
width: 16px !important;
|
|
96
|
+
height: 16px !important;
|
|
97
|
+
flex-shrink: 0 !important;
|
|
98
|
+
display: block !important;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/* Responsive button sizing */
|
|
102
|
+
@media (min-width: 768px) and (max-width: 1023px) {
|
|
103
|
+
.action-button-group :deep(button) {
|
|
104
|
+
width: 26px !important;
|
|
105
|
+
height: 26px !important;
|
|
64
106
|
}
|
|
65
107
|
|
|
66
|
-
:deep(
|
|
67
|
-
|
|
108
|
+
.action-button-group :deep(svg),
|
|
109
|
+
.action-button-group :deep(img) {
|
|
110
|
+
width: 14px !important;
|
|
111
|
+
height: 14px !important;
|
|
68
112
|
}
|
|
69
113
|
}
|
|
114
|
+
|
|
115
|
+
@media (max-width: 767px) {
|
|
116
|
+
.action-button-group :deep(button) {
|
|
117
|
+
width: 22px !important;
|
|
118
|
+
height: 22px !important;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.action-button-group :deep(svg),
|
|
122
|
+
.action-button-group :deep(img) {
|
|
123
|
+
width: 12px !important;
|
|
124
|
+
height: 12px !important;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
.action-button-group li {
|
|
129
|
+
@apply flex m-0 p-0;
|
|
130
|
+
}
|
|
70
131
|
</style>
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="balance-indicator">
|
|
3
|
+
<div v-if="loading" class="flex items-center gap-1">
|
|
4
|
+
<svg class="animate-spin h-3 w-3 text-light-500" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
|
|
5
|
+
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
|
|
6
|
+
<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>
|
|
7
|
+
</svg>
|
|
8
|
+
</div>
|
|
9
|
+
<div v-else-if="error" class="flex items-center gap-1" title="Failed to fetch balance">
|
|
10
|
+
<svg class="h-3 w-3 text-red-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
11
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" />
|
|
12
|
+
</svg>
|
|
13
|
+
</div>
|
|
14
|
+
<div v-else-if="balance !== null && balance !== undefined" class="flex items-center gap-1 text-green-400" :title="`Balance: ${balance}`">
|
|
15
|
+
<img src="@/assets/img/sell.svg" width="9" class="opacity-60" />
|
|
16
|
+
<span class="text-2xs font-bold tabular-nums">{{ formattedBalance }}</span>
|
|
17
|
+
</div>
|
|
18
|
+
</div>
|
|
19
|
+
</template>
|
|
20
|
+
|
|
21
|
+
<script setup>
|
|
22
|
+
import { computed } from "vue";
|
|
23
|
+
|
|
24
|
+
const props = defineProps({
|
|
25
|
+
balance: {
|
|
26
|
+
type: [Number, String, null],
|
|
27
|
+
default: null
|
|
28
|
+
},
|
|
29
|
+
loading: {
|
|
30
|
+
type: Boolean,
|
|
31
|
+
default: false
|
|
32
|
+
},
|
|
33
|
+
error: {
|
|
34
|
+
type: Boolean,
|
|
35
|
+
default: false
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
const formattedBalance = computed(() => {
|
|
40
|
+
if (typeof props.balance === 'number') {
|
|
41
|
+
if (props.balance >= 1000000) {
|
|
42
|
+
return (props.balance / 1000000).toFixed(1) + 'M';
|
|
43
|
+
} else if (props.balance >= 100000) {
|
|
44
|
+
return (props.balance / 1000).toFixed(0) + 'K';
|
|
45
|
+
} else if (props.balance >= 10000) {
|
|
46
|
+
return (props.balance / 1000).toFixed(1) + 'K';
|
|
47
|
+
}
|
|
48
|
+
return props.balance.toLocaleString();
|
|
49
|
+
}
|
|
50
|
+
return String(props.balance);
|
|
51
|
+
});
|
|
52
|
+
</script>
|
|
53
|
+
|
|
54
|
+
<style scoped>
|
|
55
|
+
.balance-indicator {
|
|
56
|
+
@apply absolute right-3 top-1/2 -translate-y-1/2;
|
|
57
|
+
@apply flex items-center justify-center;
|
|
58
|
+
@apply pointer-events-none;
|
|
59
|
+
}
|
|
60
|
+
</style>
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="flex min-h-32 flex-col items-center justify-center bg-dark-400 py-8 text-center text-sm font-medium">
|
|
3
|
+
<component :is="icon" class="empty-state-icon" />
|
|
4
|
+
<p class="text-light-400">{{ message }}</p>
|
|
5
|
+
<p v-if="subtitle" class="mt-1 text-xs text-light-500">{{ subtitle }}</p>
|
|
6
|
+
</div>
|
|
7
|
+
</template>
|
|
8
|
+
|
|
9
|
+
<script setup>
|
|
10
|
+
defineProps({
|
|
11
|
+
icon: {
|
|
12
|
+
type: Object,
|
|
13
|
+
required: true
|
|
14
|
+
},
|
|
15
|
+
message: {
|
|
16
|
+
type: String,
|
|
17
|
+
required: true
|
|
18
|
+
},
|
|
19
|
+
subtitle: {
|
|
20
|
+
type: String,
|
|
21
|
+
default: ''
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
</script>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<li v-if="enabled">
|
|
3
|
+
<button @click="$emit('disable')">
|
|
4
|
+
<img class="h-4 w-4" src="/img/controls/disable.svg" />
|
|
5
|
+
</button>
|
|
6
|
+
</li>
|
|
7
|
+
<li v-else>
|
|
8
|
+
<button @click="$emit('enable')">
|
|
9
|
+
<img class="h-4 w-4" src="/img/controls/enable.svg" />
|
|
10
|
+
</button>
|
|
11
|
+
</li>
|
|
12
|
+
</template>
|
|
13
|
+
|
|
14
|
+
<script setup>
|
|
15
|
+
defineProps({
|
|
16
|
+
enabled: {
|
|
17
|
+
type: Boolean,
|
|
18
|
+
required: true
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
defineEmits(["enable", "disable"]);
|
|
23
|
+
</script>
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div
|
|
2
|
+
<div :class="[zIndex && 'relative', getZIndexClass]">
|
|
3
3
|
<slot name="label">
|
|
4
|
-
<label v-if="label" class="label-override mb-2">
|
|
4
|
+
<label v-if="label" class="label-override mb-2 flex items-center">
|
|
5
5
|
{{ label }}
|
|
6
6
|
<component v-if="icon" :is="icon" />
|
|
7
7
|
</label>
|
|
8
8
|
</slot>
|
|
9
|
-
|
|
9
|
+
<!-- For dropdowns, don't wrap in input-default -->
|
|
10
|
+
<div v-if="!noWrapper" :class="['input-default', { 'required': required, 'error border-2 border-error-300': error }]">
|
|
10
11
|
<slot />
|
|
11
12
|
<div v-if="incrementer" class="input-incrementer">
|
|
12
13
|
<button @click="$emit('increment')" type="button">
|
|
@@ -17,58 +18,57 @@
|
|
|
17
18
|
</button>
|
|
18
19
|
</div>
|
|
19
20
|
</div>
|
|
21
|
+
<!-- Direct slot for dropdowns -->
|
|
22
|
+
<slot v-else />
|
|
20
23
|
</div>
|
|
21
24
|
</template>
|
|
22
25
|
|
|
23
26
|
<script setup>
|
|
24
27
|
import { UpIcon, DownIcon } from '@/components/icons';
|
|
28
|
+
import { computed } from 'vue';
|
|
25
29
|
|
|
26
|
-
defineProps({
|
|
27
|
-
label: {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
30
|
+
const props = defineProps({
|
|
31
|
+
label: {
|
|
32
|
+
type: String,
|
|
33
|
+
default: ''
|
|
34
|
+
},
|
|
35
|
+
icon: {
|
|
36
|
+
type: Object,
|
|
37
|
+
default: null
|
|
38
|
+
},
|
|
39
|
+
required: {
|
|
40
|
+
type: Boolean,
|
|
41
|
+
default: false
|
|
42
|
+
},
|
|
43
|
+
error: {
|
|
44
|
+
type: Boolean,
|
|
45
|
+
default: false
|
|
46
|
+
},
|
|
47
|
+
incrementer: {
|
|
48
|
+
type: Boolean,
|
|
49
|
+
default: false
|
|
50
|
+
},
|
|
51
|
+
zIndex: {
|
|
52
|
+
type: String,
|
|
53
|
+
default: '',
|
|
54
|
+
validator: (value) => ['', '0', '1', '2', 'dropdown', 'tooltip'].includes(value)
|
|
55
|
+
},
|
|
56
|
+
noWrapper: {
|
|
57
|
+
type: Boolean,
|
|
58
|
+
default: false
|
|
59
|
+
}
|
|
33
60
|
});
|
|
34
61
|
|
|
35
62
|
defineEmits(['increment', 'decrement']);
|
|
36
|
-
</script>
|
|
37
|
-
|
|
38
|
-
<style lang="scss" scoped>
|
|
39
|
-
.input-wrapper {
|
|
40
|
-
label {
|
|
41
|
-
@apply flex items-center;
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
.relative-positioned {
|
|
46
|
-
@apply relative;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
.z-0 {
|
|
50
|
-
z-index: 0;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
.z-1 {
|
|
54
|
-
z-index: 1;
|
|
55
|
-
}
|
|
56
63
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
.
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
.error {
|
|
70
|
-
@apply border-2 border-error-300;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
// Incrementer styles handled by forms.scss
|
|
74
|
-
</style>
|
|
64
|
+
const getZIndexClass = computed(() => {
|
|
65
|
+
const zIndexMap = {
|
|
66
|
+
'0': 'z-0',
|
|
67
|
+
'1': 'z-1',
|
|
68
|
+
'2': 'z-2',
|
|
69
|
+
'dropdown': 'z-dropdown',
|
|
70
|
+
'tooltip': 'z-tooltip'
|
|
71
|
+
};
|
|
72
|
+
return zIndexMap[props.zIndex] || '';
|
|
73
|
+
});
|
|
74
|
+
</script>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="flex items-center gap-2 text-xs text-light-100">
|
|
3
|
+
<component :is="icon" :class="iconClass" />
|
|
4
|
+
<span>{{ label }}</span>
|
|
5
|
+
</div>
|
|
6
|
+
</template>
|
|
7
|
+
|
|
8
|
+
<script setup>
|
|
9
|
+
defineProps({
|
|
10
|
+
icon: {
|
|
11
|
+
type: Object,
|
|
12
|
+
required: true
|
|
13
|
+
},
|
|
14
|
+
label: {
|
|
15
|
+
type: String,
|
|
16
|
+
required: true
|
|
17
|
+
},
|
|
18
|
+
iconClass: {
|
|
19
|
+
type: String,
|
|
20
|
+
default: "h-4 w-4 text-light-100"
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
</script>
|
|
@@ -1,21 +1,34 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div
|
|
3
|
-
class="
|
|
3
|
+
class="flex items-center gap-3 rounded-lg bg-dark-500 border border-dark-550 px-3 py-2 min-h-10"
|
|
4
4
|
:class="{ 'items-start': alignStart, [customClass]: customClass }">
|
|
5
|
-
<component
|
|
6
|
-
|
|
5
|
+
<component
|
|
6
|
+
v-if="icon"
|
|
7
|
+
:is="icon"
|
|
8
|
+
class="h-4 w-4 flex-shrink-0 text-light-300"
|
|
9
|
+
:class="{ 'flex-shrink-0': alignStart }" />
|
|
10
|
+
<span
|
|
11
|
+
v-if="iconText"
|
|
12
|
+
class="flex h-4 w-4 flex-shrink-0 items-center justify-center text-base font-bold text-light-300"
|
|
13
|
+
:class="{ 'flex-shrink-0': alignStart }">
|
|
7
14
|
{{ iconText }}
|
|
8
15
|
</span>
|
|
9
|
-
<span
|
|
10
|
-
|
|
16
|
+
<span
|
|
17
|
+
class="min-w-25 flex-shrink-0 text-xs font-medium text-light-500 md:min-w-20 md:text-xs+"
|
|
18
|
+
:class="{ 'flex-shrink-0': alignStart }">
|
|
19
|
+
{{ label }}
|
|
20
|
+
</span>
|
|
21
|
+
<span
|
|
22
|
+
class="min-w-0 flex-1 break-words overflow-hidden text-sm text-light-300 md:text-xs+"
|
|
23
|
+
:class="valueClass">
|
|
11
24
|
<slot>{{ value }}</slot>
|
|
12
25
|
</span>
|
|
13
26
|
<button
|
|
14
27
|
v-if="copyable"
|
|
15
28
|
@click="handleCopy"
|
|
16
|
-
class="
|
|
17
|
-
:class="{ '
|
|
18
|
-
<component :is="showCopied ? CheckIcon : CopyIcon" class="
|
|
29
|
+
class="ml-2 flex h-8 w-8 flex-shrink-0 items-center justify-center rounded bg-transparent text-light-500 transition-all duration-150 hover:bg-dark-550 hover:text-light-300"
|
|
30
|
+
:class="{ 'text-accent-green': showCopied }">
|
|
31
|
+
<component :is="showCopied ? CheckIcon : CopyIcon" class="h-4 w-4" />
|
|
19
32
|
</button>
|
|
20
33
|
<slot name="action" />
|
|
21
34
|
</div>
|
|
@@ -52,49 +65,3 @@ const handleCopy = () => {
|
|
|
52
65
|
};
|
|
53
66
|
</script>
|
|
54
67
|
|
|
55
|
-
<style lang="scss" scoped>
|
|
56
|
-
.info-row {
|
|
57
|
-
@apply flex items-center gap-3 px-3 py-2 rounded-lg;
|
|
58
|
-
@apply bg-dark-500 border border-dark-600;
|
|
59
|
-
@apply min-h-10;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
.info-icon {
|
|
63
|
-
@apply w-4 h-4 flex-shrink-0 text-light-300;
|
|
64
|
-
|
|
65
|
-
svg {
|
|
66
|
-
@apply text-light-300 w-4 h-4;
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
.info-label {
|
|
71
|
-
@apply text-xs font-medium flex-shrink-0 text-light-500;
|
|
72
|
-
@apply min-w-[100px];
|
|
73
|
-
|
|
74
|
-
@media (max-width: 768px) {
|
|
75
|
-
@apply min-w-20 text-[11px];
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
.info-value {
|
|
80
|
-
@apply text-sm flex-1 text-light-300;
|
|
81
|
-
@apply break-words overflow-hidden;
|
|
82
|
-
min-width: 0; // Allow flex item to shrink below content size
|
|
83
|
-
|
|
84
|
-
@media (max-width: 768px) {
|
|
85
|
-
@apply text-[13px];
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
.copy-button {
|
|
90
|
-
@apply flex items-center justify-center;
|
|
91
|
-
@apply w-8 h-8 rounded transition-all duration-150;
|
|
92
|
-
@apply bg-transparent text-light-500 hover:text-light-300 hover:bg-dark-600;
|
|
93
|
-
@apply flex-shrink-0;
|
|
94
|
-
@apply ml-2; // Ensure spacing from value
|
|
95
|
-
|
|
96
|
-
&.copied {
|
|
97
|
-
@apply text-accent-green;
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
</style>
|