@necrolab/dashboard 0.5.15 → 0.5.17
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 +70 -566
- 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 +61 -74
- package/src/assets/css/components/forms.scss +31 -32
- package/src/assets/css/components/headers.scss +13 -21
- package/src/assets/css/components/modals.scss +2 -2
- package/src/assets/css/components/search-groups.scss +28 -22
- 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 +295 -0
- package/src/assets/css/main.scss +55 -139
- package/src/components/Auth/LoginForm.vue +7 -86
- package/src/components/Console/ConsoleToolbar.vue +123 -0
- package/src/components/Editors/Account/Account.vue +12 -12
- package/src/components/Editors/Account/AccountView.vue +38 -111
- package/src/components/Editors/Account/CreateAccount.vue +11 -61
- package/src/components/Editors/Account/{AccountCreator.vue → CreateAccountBatch.vue} +28 -59
- package/src/components/Editors/AdminFileEditor.vue +179 -0
- package/src/components/Editors/Profile/CreateProfile.vue +77 -150
- package/src/components/Editors/Profile/Profile.vue +20 -21
- package/src/components/Editors/Profile/ProfileCountryChooser.vue +16 -60
- package/src/components/Editors/Profile/ProfileView.vue +41 -116
- package/src/components/Editors/ProxyFileEditor.vue +86 -0
- package/src/components/Editors/TagLabel.vue +16 -55
- package/src/components/Editors/TagToggle.vue +20 -8
- package/src/components/Filter/Filter.vue +66 -79
- package/src/components/Filter/FilterPreview.vue +153 -135
- package/src/components/Filter/PriceSortToggle.vue +36 -43
- package/src/components/Table/Header.vue +1 -1
- package/src/components/Table/Table.vue +45 -51
- 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 +20 -39
- package/src/components/Tasks/Task.vue +64 -270
- package/src/components/Tasks/TaskLabel.vue +9 -3
- package/src/components/Tasks/TaskView.vue +45 -64
- package/src/components/Tasks/Utilities.vue +10 -44
- 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/Wildcard.vue +2 -8
- package/src/components/icons/index.js +3 -5
- 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 +49 -49
- package/src/components/ui/IconLabel.vue +23 -0
- package/src/components/ui/InfoRow.vue +21 -54
- package/src/components/ui/Modal.vue +161 -54
- package/src/components/ui/Navbar.vue +63 -44
- 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 +29 -66
- 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 +103 -139
- package/src/components/ui/controls/atomic/MultiDropdown.vue +72 -120
- package/src/components/ui/controls/atomic/Switch.vue +21 -84
- package/src/composables/useCodeEditor.js +117 -0
- 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 +1 -4
- package/src/composables/useDynamicTableHeight.js +31 -0
- package/src/composables/useEnableDisable.js +6 -0
- package/src/composables/useFilterCSS.js +71 -0
- package/src/composables/useFormValidation.js +92 -0
- package/src/composables/useGetAllTags.js +9 -0
- package/src/composables/useIOSViewportHandling.js +76 -0
- package/src/composables/useNotchHandling.js +306 -0
- package/src/composables/useRowSelection.js +0 -3
- package/src/composables/useTableRender.js +23 -0
- package/src/composables/useTicketPricing.js +16 -0
- package/src/composables/useWindowDimensions.js +21 -0
- package/src/composables/useZoomPrevention.js +96 -0
- package/src/constants/tableLayout.js +14 -0
- package/src/libs/Filter.js +14 -20
- package/src/libs/panzoom.js +1 -5
- package/src/libs/utils/array.js +58 -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 +3 -0
- package/src/libs/utils/time.js +20 -0
- package/src/libs/utils/validation.js +64 -0
- package/src/main.js +0 -2
- package/src/stores/connection.js +1 -29
- package/src/stores/logger.js +6 -12
- package/src/stores/sampleData.js +1 -2
- package/src/stores/ui.js +80 -71
- package/src/utils/tableHelpers.js +1 -0
- package/src/views/Accounts.vue +19 -38
- package/src/views/Console.vue +74 -253
- package/src/views/Editor.vue +47 -1114
- package/src/views/FilterBuilder.vue +190 -461
- package/src/views/Login.vue +3 -28
- package/src/views/Profiles.vue +17 -32
- 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 -2438
- package/exit +0 -209
- package/run +0 -177
- package/src/assets/css/base/color-fallbacks.scss +0 -10
- package/src/assets/img/background.svg.backup +0 -11
- package/src/components/icons/SquareCheck.vue +0 -18
- package/src/components/icons/SquareUncheck.vue +0 -18
- package/src/components/ui/controls/atomic/LoadingButton.vue +0 -45
- package/switch-branch.sh +0 -41
- /package/public/{reconnect-logo.png → img/reconnect-logo.png} +0 -0
|
@@ -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: oklch(0.78 0.12 145 / 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: oklch(0.78 0.12 145 / 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-gap-1 items-center">
|
|
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-gap-1 items-center" 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-gap-1 items-center 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="icon-md" src="/img/controls/disable.svg" />
|
|
5
|
+
</button>
|
|
6
|
+
</li>
|
|
7
|
+
<li v-else>
|
|
8
|
+
<button @click="$emit('enable')">
|
|
9
|
+
<img class="icon-md" 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="
|
|
4
|
+
<label v-if="label" class="mb-2 flex items-center gap-2 text-sm font-medium text-white">
|
|
5
5
|
{{ label }}
|
|
6
|
-
<component v-if="icon" :is="icon" />
|
|
6
|
+
<component v-if="icon" :is="icon" class="h-3.5 w-3.5" />
|
|
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-gap-2 items-center 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: "icon-md 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="icon-md flex-shrink-0 text-light-300"
|
|
9
|
+
:class="{ 'flex-shrink-0': alignStart }" />
|
|
10
|
+
<span
|
|
11
|
+
v-if="iconText"
|
|
12
|
+
class="flex icon-md 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 icon-button bg-transparent text-light-500 transition-standard hover:bg-dark-550 hover:text-light-300"
|
|
30
|
+
:class="{ 'text-accent-green': showCopied }">
|
|
31
|
+
<component :is="showCopied ? CheckIcon : CopyIcon" class="icon-md" />
|
|
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>
|