mgv-backoffice 1.27.0 → 1.28.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.
- package/README.md +70 -6
- package/dist/components/BaseActionButton.vue.d.ts +1 -1
- package/dist/components/BaseAlert.vue.d.ts +21 -25
- package/dist/components/BaseChipButton.vue.d.ts +25 -0
- package/dist/components/BaseRemoveButton.vue.d.ts +7 -0
- package/dist/components/BaseStatusPill.vue.d.ts +8 -0
- package/dist/components/BaseToolbarButton.vue.d.ts +1 -1
- package/dist/components/EarningsCard.vue.d.ts +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/ui-lib.css +1 -1
- package/dist/ui-lib.js +500 -429
- package/dist/ui-lib.umd.cjs +1 -1
- package/package.json +1 -1
- package/src/components/BaseAlert.vue +78 -32
- package/src/components/BaseChipButton.vue +42 -0
- package/src/components/BaseRemoveButton.vue +22 -0
- package/src/components/BaseStatusPill.vue +54 -0
- package/src/index.ts +3 -0
|
@@ -1,8 +1,31 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
<!--
|
|
3
|
+
Inline notice panel (error / warning / success / info).
|
|
4
|
+
|
|
5
|
+
v2 (1.27.0): rewritten from the legacy dynamic-class version —
|
|
6
|
+
• theme-aware via the shared `isDark` ref (same pattern as the other
|
|
7
|
+
extracted components; no runtime-composed class names, so every
|
|
8
|
+
class survives Tailwind's static scan)
|
|
9
|
+
• optional default slot for body content below the title
|
|
10
|
+
• `compact` variant for slim in-form warnings (text-xs, small icon)
|
|
11
|
+
Backward compatible: `<BaseAlert title="..." :color="AlertEnum.X" />`
|
|
12
|
+
renders the same single-line alert as before, mb-4 included.
|
|
13
|
+
-->
|
|
14
|
+
<div
|
|
15
|
+
role="alert"
|
|
16
|
+
class="flex gap-3 mb-4 rounded-lg border text-sm transition-colors"
|
|
17
|
+
:class="[compact ? 'items-start px-3 py-2 text-xs' : 'items-start p-4', palette]"
|
|
18
|
+
>
|
|
19
|
+
<component
|
|
20
|
+
:is="iconComponent"
|
|
21
|
+
class="shrink-0"
|
|
22
|
+
:class="[compact ? 'w-4 h-4 mt-px' : 'w-5 h-5 mt-0.5', iconColorClass]"
|
|
23
|
+
aria-hidden="true"
|
|
24
|
+
/>
|
|
25
|
+
<div class="min-w-0 flex-1">
|
|
26
|
+
<p v-if="title" class="font-medium">{{ title }}</p>
|
|
27
|
+
<!-- Body — caller-styled free-form content under the title. -->
|
|
28
|
+
<slot />
|
|
6
29
|
</div>
|
|
7
30
|
</div>
|
|
8
31
|
</template>
|
|
@@ -14,45 +37,68 @@ import {
|
|
|
14
37
|
ExclamationTriangleIcon,
|
|
15
38
|
InformationCircleIcon,
|
|
16
39
|
} from '@heroicons/vue/24/outline'
|
|
17
|
-
import { AlertEnum } from
|
|
18
|
-
import { computed
|
|
19
|
-
import {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
40
|
+
import { AlertEnum } from '../enums/AlertEnum'
|
|
41
|
+
import { computed } from 'vue'
|
|
42
|
+
import { useTheme } from '../composables/useTheme'
|
|
43
|
+
|
|
44
|
+
interface Props {
|
|
45
|
+
/** Bold headline. Optional when the slot carries the whole message. */
|
|
46
|
+
title?: string
|
|
47
|
+
/** Alert mode — drives palette and icon. Defaults to ERROR. */
|
|
48
|
+
color?: AlertEnum
|
|
49
|
+
/** Slim variant for in-form warnings: text-xs, smaller icon/padding. */
|
|
50
|
+
compact?: boolean
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const props = withDefaults(defineProps<Props>(), {
|
|
54
|
+
title: '',
|
|
55
|
+
color: AlertEnum.ERROR,
|
|
56
|
+
compact: false,
|
|
32
57
|
})
|
|
33
58
|
|
|
59
|
+
const { isDark } = useTheme()
|
|
60
|
+
|
|
61
|
+
// Literal palette table so Tailwind's scanner sees every class.
|
|
62
|
+
const PALETTES: Record<AlertEnum, { light: string; dark: string }> = {
|
|
63
|
+
[AlertEnum.ERROR]: {
|
|
64
|
+
light: 'bg-red-50 border-red-200 text-red-700',
|
|
65
|
+
dark: 'bg-red-500/10 border-red-500/30 text-red-300',
|
|
66
|
+
},
|
|
67
|
+
[AlertEnum.WARNING]: {
|
|
68
|
+
light: 'bg-amber-50 border-amber-200 text-amber-700',
|
|
69
|
+
dark: 'bg-amber-500/10 border-amber-500/30 text-amber-300',
|
|
70
|
+
},
|
|
71
|
+
[AlertEnum.SUCCESS]: {
|
|
72
|
+
light: 'bg-emerald-50 border-emerald-200 text-emerald-700',
|
|
73
|
+
dark: 'bg-emerald-500/10 border-emerald-500/30 text-emerald-300',
|
|
74
|
+
},
|
|
75
|
+
[AlertEnum.INFO]: {
|
|
76
|
+
light: 'bg-sky-50 border-sky-200 text-sky-700',
|
|
77
|
+
dark: 'bg-sky-500/10 border-sky-500/30 text-sky-300',
|
|
78
|
+
},
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const palette = computed(() =>
|
|
82
|
+
isDark.value ? PALETTES[props.color].dark : PALETTES[props.color].light,
|
|
83
|
+
)
|
|
84
|
+
|
|
34
85
|
// Icon + tint follow the alert mode so an error doesn't render with a
|
|
35
86
|
// neutral info glyph.
|
|
36
87
|
const iconComponent = computed(() => {
|
|
37
88
|
switch (props.color) {
|
|
38
|
-
case AlertEnum.SUCCESS: return CheckCircleIcon
|
|
39
|
-
case AlertEnum.WARNING: return ExclamationTriangleIcon
|
|
40
|
-
case AlertEnum.INFO: return InformationCircleIcon
|
|
41
|
-
default: return ExclamationCircleIcon
|
|
89
|
+
case AlertEnum.SUCCESS: return CheckCircleIcon
|
|
90
|
+
case AlertEnum.WARNING: return ExclamationTriangleIcon
|
|
91
|
+
case AlertEnum.INFO: return InformationCircleIcon
|
|
92
|
+
default: return ExclamationCircleIcon
|
|
42
93
|
}
|
|
43
94
|
})
|
|
44
95
|
|
|
45
96
|
const iconColorClass = computed(() => {
|
|
46
97
|
switch (props.color) {
|
|
47
|
-
case AlertEnum.SUCCESS: return 'text-
|
|
48
|
-
case AlertEnum.WARNING: return 'text-
|
|
49
|
-
case AlertEnum.INFO: return 'text-
|
|
50
|
-
default: return 'text-red-500'
|
|
98
|
+
case AlertEnum.SUCCESS: return 'text-emerald-500'
|
|
99
|
+
case AlertEnum.WARNING: return 'text-amber-500'
|
|
100
|
+
case AlertEnum.INFO: return 'text-sky-500'
|
|
101
|
+
default: return 'text-red-500'
|
|
51
102
|
}
|
|
52
103
|
})
|
|
53
|
-
|
|
54
|
-
function computeCss() {
|
|
55
|
-
let baseColor = getBaseColor(props.color);
|
|
56
|
-
return "flex items-center p-4 mb-4 text-sm text-" + baseColor + "-800 border border-" + baseColor + "-300 rounded-lg bg-" + baseColor + "-50 dark:bg-gray-800 dark:text-" + baseColor + "-400 dark:border-" + baseColor + "-800"
|
|
57
|
-
}
|
|
58
104
|
</script>
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<!--
|
|
3
|
+
Small tinted "chip" action button — the compact emerald "+ Add" pill
|
|
4
|
+
used above repeatable form rows (extracted from WireMate's CreateMock,
|
|
5
|
+
where the identical class string appeared seven times).
|
|
6
|
+
|
|
7
|
+
Label comes from the default slot so callers can mix text and icons.
|
|
8
|
+
-->
|
|
9
|
+
<button
|
|
10
|
+
type="button"
|
|
11
|
+
:disabled="disabled"
|
|
12
|
+
class="inline-flex items-center gap-1 font-medium rounded-md border transition-colors cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed focus:outline-none focus-visible:ring-2 focus-visible:ring-emerald-500"
|
|
13
|
+
:class="[
|
|
14
|
+
size === 'xs' ? 'text-xs px-2 py-0.5' : 'text-xs px-2.5 py-1',
|
|
15
|
+
isDark
|
|
16
|
+
? 'text-emerald-300 border-emerald-700 bg-emerald-900/30 hover:bg-emerald-800/50'
|
|
17
|
+
: 'text-emerald-700 border-emerald-200 bg-emerald-50 hover:bg-emerald-100',
|
|
18
|
+
]"
|
|
19
|
+
@click="emit('click')"
|
|
20
|
+
>
|
|
21
|
+
<slot />
|
|
22
|
+
</button>
|
|
23
|
+
</template>
|
|
24
|
+
|
|
25
|
+
<script lang="ts" setup>
|
|
26
|
+
import { useTheme } from '../composables/useTheme'
|
|
27
|
+
|
|
28
|
+
interface Props {
|
|
29
|
+
/** 'sm' = px-2.5 py-1 (default); 'xs' = px-2 py-0.5 for tight corners. */
|
|
30
|
+
size?: 'xs' | 'sm'
|
|
31
|
+
disabled?: boolean
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
withDefaults(defineProps<Props>(), {
|
|
35
|
+
size: 'sm',
|
|
36
|
+
disabled: false,
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
const emit = defineEmits<{ click: [] }>()
|
|
40
|
+
|
|
41
|
+
const { isDark } = useTheme()
|
|
42
|
+
</script>
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<!--
|
|
3
|
+
The "×" remove-row affordance used beside repeatable form rows
|
|
4
|
+
(extracted from WireMate's CreateMock, where the identical red ×
|
|
5
|
+
button appeared on every key/value, matcher, and cookie row).
|
|
6
|
+
|
|
7
|
+
Renders a multiplication sign; name it for screen readers via
|
|
8
|
+
`aria-label` (falls through as an attr, as do `title`, `disabled`,
|
|
9
|
+
and any extra classes like `pt-1` / `self-start`).
|
|
10
|
+
-->
|
|
11
|
+
<button
|
|
12
|
+
type="button"
|
|
13
|
+
class="px-2 text-lg leading-none text-red-400 hover:text-red-600 transition-colors cursor-pointer rounded focus:outline-none focus-visible:ring-2 focus-visible:ring-red-400 disabled:cursor-not-allowed disabled:text-gray-400 disabled:hover:text-gray-400"
|
|
14
|
+
@click="emit('click')"
|
|
15
|
+
>
|
|
16
|
+
×
|
|
17
|
+
</button>
|
|
18
|
+
</template>
|
|
19
|
+
|
|
20
|
+
<script lang="ts" setup>
|
|
21
|
+
const emit = defineEmits<{ click: [] }>()
|
|
22
|
+
</script>
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<!--
|
|
3
|
+
Connection/health status pill: a colored dot (pulsing while ok) next
|
|
4
|
+
to a short label, on a tinted rounded background. Extracted from
|
|
5
|
+
WireMate's sidebar WireMock health indicator.
|
|
6
|
+
|
|
7
|
+
status: 'ok' → emerald + pulse, 'error' → red, 'unknown' → gray.
|
|
8
|
+
-->
|
|
9
|
+
<div class="flex items-center gap-2 px-3 py-1.5 rounded-lg text-xs" :class="pillClass">
|
|
10
|
+
<span class="relative flex h-2 w-2">
|
|
11
|
+
<span
|
|
12
|
+
v-if="status === 'ok'"
|
|
13
|
+
class="animate-ping absolute inline-flex h-full w-full rounded-full bg-emerald-400 opacity-75"
|
|
14
|
+
aria-hidden="true"
|
|
15
|
+
></span>
|
|
16
|
+
<span class="relative inline-flex rounded-full h-2 w-2" :class="dotClass"></span>
|
|
17
|
+
</span>
|
|
18
|
+
{{ label }}
|
|
19
|
+
</div>
|
|
20
|
+
</template>
|
|
21
|
+
|
|
22
|
+
<script lang="ts" setup>
|
|
23
|
+
import { computed } from 'vue'
|
|
24
|
+
import { useTheme } from '../composables/useTheme'
|
|
25
|
+
|
|
26
|
+
interface Props {
|
|
27
|
+
status: 'ok' | 'error' | 'unknown'
|
|
28
|
+
/** Short text next to the dot, e.g. "WireMock Connected". */
|
|
29
|
+
label: string
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const props = defineProps<Props>()
|
|
33
|
+
|
|
34
|
+
const { isDark } = useTheme()
|
|
35
|
+
|
|
36
|
+
const pillClass = computed(() => {
|
|
37
|
+
switch (props.status) {
|
|
38
|
+
case 'ok':
|
|
39
|
+
return isDark.value ? 'bg-emerald-500/10 text-emerald-400' : 'bg-emerald-50 text-emerald-700'
|
|
40
|
+
case 'error':
|
|
41
|
+
return isDark.value ? 'bg-red-500/10 text-red-400' : 'bg-red-50 text-red-700'
|
|
42
|
+
default:
|
|
43
|
+
return isDark.value ? 'bg-gray-700 text-gray-400' : 'bg-gray-100 text-gray-500'
|
|
44
|
+
}
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
const dotClass = computed(() => {
|
|
48
|
+
switch (props.status) {
|
|
49
|
+
case 'ok': return 'bg-emerald-500'
|
|
50
|
+
case 'error': return 'bg-red-500'
|
|
51
|
+
default: return 'bg-gray-400'
|
|
52
|
+
}
|
|
53
|
+
})
|
|
54
|
+
</script>
|
package/src/index.ts
CHANGED
|
@@ -33,6 +33,9 @@ export { default as BaseCopyButton } from './components/BaseCopyButton.vue'
|
|
|
33
33
|
export { default as BaseGoogleSignInButton } from './components/BaseGoogleSignInButton.vue'
|
|
34
34
|
export { default as BaseLoginForm } from './components/BaseLoginForm.vue'
|
|
35
35
|
export { default as BaseNotificationPanel } from './components/BaseNotificationPanel.vue'
|
|
36
|
+
export { default as BaseChipButton } from './components/BaseChipButton.vue'
|
|
37
|
+
export { default as BaseRemoveButton } from './components/BaseRemoveButton.vue'
|
|
38
|
+
export { default as BaseStatusPill } from './components/BaseStatusPill.vue'
|
|
36
39
|
|
|
37
40
|
// Components — extracted from TradeAutomation
|
|
38
41
|
export { default as BaseInput } from './components/BaseInput.vue'
|