mgv-backoffice 1.38.0 → 1.41.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 +91 -3
- package/dist/components/BaseAuthLayout.vue.d.ts +27 -0
- package/dist/components/BaseBooleanBadge.vue.d.ts +12 -0
- package/dist/components/BaseCheckbox.vue.d.ts +28 -0
- package/dist/components/BaseDetailList.vue.d.ts +13 -0
- package/dist/components/BasePageHeader.vue.d.ts +3 -0
- package/dist/components/BaseSidebarUser.vue.d.ts +23 -0
- package/dist/components/BaseToggle.vue.d.ts +33 -0
- package/dist/index.d.ts +7 -0
- package/dist/types/detail.d.ts +10 -0
- package/dist/ui-lib.css +1 -1
- package/dist/ui-lib.js +847 -602
- package/dist/ui-lib.umd.cjs +1 -1
- package/package.json +1 -1
- package/src/components/BaseAuthLayout.test.ts +48 -0
- package/src/components/BaseAuthLayout.vue +50 -0
- package/src/components/BaseBooleanBadge.vue +32 -0
- package/src/components/BaseButton.vue +1 -1
- package/src/components/BaseCheckbox.test.ts +30 -0
- package/src/components/BaseCheckbox.vue +51 -0
- package/src/components/BaseDetailList.test.ts +36 -0
- package/src/components/BaseDetailList.vue +43 -0
- package/src/components/BasePageHeader.vue +13 -2
- package/src/components/BaseSelect.test.ts +1 -1
- package/src/components/BaseSelect.vue +3 -2
- package/src/components/BaseSidebarUser.test.ts +26 -0
- package/src/components/BaseSidebarUser.vue +75 -0
- package/src/components/BaseSpinner.vue +76 -76
- package/src/components/BaseToggle.test.ts +39 -0
- package/src/components/BaseToggle.vue +73 -0
- package/src/components/Pagination.test.ts +93 -85
- package/src/components/Pagination.vue +87 -82
- package/src/index.ts +7 -0
- package/src/style.css +58 -58
- package/src/types/detail.ts +10 -0
package/README.md
CHANGED
|
@@ -169,7 +169,7 @@ Button with color, size, loading state, and Vue Router integration.
|
|
|
169
169
|
| Prop | Type | Default | Description |
|
|
170
170
|
| ------------- | ----------------------------------- | --------------------- | ------------------------------------ |
|
|
171
171
|
| `description` | `String` | **required** | Button label text |
|
|
172
|
-
| `color` | `String` | `BaseButtonEnum.
|
|
172
|
+
| `color` | `String` | `BaseButtonEnum.GREEN` | Color variant (`BLUE`/`WHITE`/`DARK`/`GREEN`/`EMERALD`/`RED`/`YELLOW`/`PURPLE`/`SKY`/`GRAY`/`AMBER`) |
|
|
173
173
|
| `outline` | `Boolean` | `false` | Outlined/secondary style — transparent fill, coloured text + border, tinted hover (theme-aware) |
|
|
174
174
|
| `ghost` | `Boolean` | `false` | Ghost/borderless style — no border or fill, coloured text + tinted hover (theme-aware). For compact toolbar/action buttons |
|
|
175
175
|
| `to` | `String` | — | Vue Router path (renders `<router-link>`) |
|
|
@@ -348,9 +348,9 @@ Animated loading spinner — a neutral ring with a coloured leading arc.
|
|
|
348
348
|
| Prop | Type | Default | Description |
|
|
349
349
|
|---------|----------------------------------------------------------------------------|----------|-------------------------------------------------------------|
|
|
350
350
|
| `size` | `'sm' \| 'md' \| 'lg' \| 'xl'` | `'sm'` | Diameter + ring thickness — 16 / 24 / 32 / 48px. |
|
|
351
|
-
| `color` | `'blue' \| 'emerald' \| 'sky' \| 'indigo' \| 'teal' \| 'purple' \| 'red' \| 'amber'` | `'
|
|
351
|
+
| `color` | `'blue' \| 'emerald' \| 'sky' \| 'indigo' \| 'teal' \| 'purple' \| 'red' \| 'amber'` | `'emerald'` | Colour of the spinning arc. The track stays neutral gray. |
|
|
352
352
|
|
|
353
|
-
With no props it renders
|
|
353
|
+
With no props it renders a 16px emerald spinner. For page loaders use `size="xl"` centered, e.g. `<div class="flex justify-center py-12"><BaseSpinner size="xl" /></div>`.
|
|
354
354
|
|
|
355
355
|
**Example:**
|
|
356
356
|
|
|
@@ -901,6 +901,24 @@ interface NavSection {
|
|
|
901
901
|
|
|
902
902
|
---
|
|
903
903
|
|
|
904
|
+
### BaseSidebarUser
|
|
905
|
+
|
|
906
|
+
Signed-in user block for the `BaseSidebar` `footer` slot: initials avatar,
|
|
907
|
+
name and email (a link to the profile page when `to` is set) and a Logout
|
|
908
|
+
button that emits `logout`.
|
|
909
|
+
|
|
910
|
+
**Props:** `name` (required), `email`, `to` (profile route), `showLogout` (`true`),
|
|
911
|
+
`logoutLabel` (`'Logout'`), `profileLabel` (`'View profile'`, tooltip).
|
|
912
|
+
**Emits:** `logout`.
|
|
913
|
+
|
|
914
|
+
```vue
|
|
915
|
+
<BaseSidebar :sections="nav">
|
|
916
|
+
<template #footer>
|
|
917
|
+
<BaseSidebarUser :name="me.username" :email="me.email" :to="{ name: 'Profile' }" @logout="logOut" />
|
|
918
|
+
</template>
|
|
919
|
+
</BaseSidebar>
|
|
920
|
+
```
|
|
921
|
+
|
|
904
922
|
### BaseNotificationPanel
|
|
905
923
|
|
|
906
924
|
Left-anchored notification drawer (teleported to `<body>`, slides in from
|
|
@@ -1119,6 +1137,7 @@ so icon-less apps get a plain title/subtitle header.
|
|
|
1119
1137
|
| `maxWidthClass` | `String` | `'max-w-4xl'` | Tailwind max-w utility constraining header width. Pass `''` to skip the width wrapper entirely — the header then spans its container. |
|
|
1120
1138
|
| `align` | `String` | `'center'` | Vertical alignment of the title block vs the actions: `'center'` or `'end'` (actions sit on the title baseline). |
|
|
1121
1139
|
| `marginClass` | `String` | `'mb-8'` | Space under the header. Pass `''` when the parent manages vertical rhythm (`space-y-*`). |
|
|
1140
|
+
| `accent` | `Boolean` | `false` | Brand-green gauge bar in front of the title (icon-less headers). |
|
|
1122
1141
|
|
|
1123
1142
|
**Slots:**
|
|
1124
1143
|
|
|
@@ -1833,6 +1852,75 @@ title, big value) for any value — counts, labels, pre-formatted numbers.
|
|
|
1833
1852
|
</BaseStatCard>
|
|
1834
1853
|
```
|
|
1835
1854
|
|
|
1855
|
+
### BaseCheckbox
|
|
1856
|
+
|
|
1857
|
+
Rounded checkbox, emerald when checked (works with or without a forms plugin).
|
|
1858
|
+
`v-model` is the boolean; `change` fires with the new value; attrs (`id`, `name`)
|
|
1859
|
+
go to the `<input>`.
|
|
1860
|
+
|
|
1861
|
+
**Props:** `modelValue`, `label`, `disabled`. **Slots:** `default` (rich label).
|
|
1862
|
+
**Emits:** `update:modelValue(value)`, `change(value)`.
|
|
1863
|
+
|
|
1864
|
+
```vue
|
|
1865
|
+
<BaseCheckbox v-model="remember" id="remember" label="Remember me" />
|
|
1866
|
+
```
|
|
1867
|
+
|
|
1868
|
+
### BaseToggle
|
|
1869
|
+
|
|
1870
|
+
On/off switch (`role="switch"`). `v-model` is the boolean; `change` fires after
|
|
1871
|
+
every user toggle with the new value.
|
|
1872
|
+
|
|
1873
|
+
**Props:** `modelValue`, `label` (visible label, also the accessible name),
|
|
1874
|
+
`ariaLabel` (when there is no label), `color: 'emerald' | 'red' | 'sky' | 'amber'`
|
|
1875
|
+
(on state, `'emerald'`), `offTone: 'slate' | 'red'` (off track, `'slate'`), `disabled`.
|
|
1876
|
+
**Emits:** `update:modelValue(value)`, `change(value)`.
|
|
1877
|
+
|
|
1878
|
+
```vue
|
|
1879
|
+
<BaseToggle v-model="task.alive" :label="task.name" color="red" @change="save(task)" />
|
|
1880
|
+
<BaseToggle v-model="account.alive" off-tone="red" aria-label="Alive" />
|
|
1881
|
+
```
|
|
1882
|
+
|
|
1883
|
+
### BaseAuthLayout
|
|
1884
|
+
|
|
1885
|
+
Full-page, centred shell for sign-in / sign-up / password-recovery screens:
|
|
1886
|
+
logo on top (defaults to `BaseLogo`), then a bordered card with the title,
|
|
1887
|
+
content and an optional footer.
|
|
1888
|
+
|
|
1889
|
+
**Props:** `title`, `subtitle`, `wide` (max-w-3xl card for multi-column forms; default max-w-md).
|
|
1890
|
+
**Slots:** `default` (form), `logo` (replaces `BaseLogo`), `footer` ("No account? Sign up").
|
|
1891
|
+
|
|
1892
|
+
```vue
|
|
1893
|
+
<BaseAuthLayout title="Forgot password">
|
|
1894
|
+
<form>…</form>
|
|
1895
|
+
<template #footer>No account? <RouterLink to="/register">Sign up</RouterLink></template>
|
|
1896
|
+
</BaseAuthLayout>
|
|
1897
|
+
```
|
|
1898
|
+
|
|
1899
|
+
### BaseBooleanBadge
|
|
1900
|
+
|
|
1901
|
+
Yes/no pill for boolean columns: green check when true, red cross when false.
|
|
1902
|
+
|
|
1903
|
+
**Props:** `value` (`boolean | null`), `trueLabel` (`'Yes'`), `falseLabel` (`'No'`).
|
|
1904
|
+
|
|
1905
|
+
```vue
|
|
1906
|
+
<BaseBooleanBadge :value="user.hasVerifiedEmail" true-label="Verified" false-label="Not verified" />
|
|
1907
|
+
```
|
|
1908
|
+
|
|
1909
|
+
### BaseDetailList
|
|
1910
|
+
|
|
1911
|
+
Read-only label/value grid for detail pages (the "view" counterpart of a form).
|
|
1912
|
+
Empty values show `emptyText`; `href` renders the value as an external link;
|
|
1913
|
+
`mono` uses the monospace face.
|
|
1914
|
+
|
|
1915
|
+
**Props:** `items: DetailItem[]` (`{ label, value?, href?, mono? }`, required),
|
|
1916
|
+
`columns: 1 | 2 | 3` (`2`, from `sm` up), `emptyText` (`'—'`).
|
|
1917
|
+
|
|
1918
|
+
```vue
|
|
1919
|
+
<BaseCard title="Details">
|
|
1920
|
+
<BaseDetailList :items="[{ label: 'Status', value: post.status }, { label: 'Link', value: post.link, href: post.link }]" />
|
|
1921
|
+
</BaseCard>
|
|
1922
|
+
```
|
|
1923
|
+
|
|
1836
1924
|
## Composables
|
|
1837
1925
|
|
|
1838
1926
|
```ts
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
interface Props {
|
|
2
|
+
title?: string;
|
|
3
|
+
subtitle?: string;
|
|
4
|
+
/** max-w-3xl card instead of max-w-md (multi-column forms). */
|
|
5
|
+
wide?: boolean;
|
|
6
|
+
}
|
|
7
|
+
declare var __VLS_1: {}, __VLS_8: {}, __VLS_10: {};
|
|
8
|
+
type __VLS_Slots = {} & {
|
|
9
|
+
logo?: (props: typeof __VLS_1) => any;
|
|
10
|
+
} & {
|
|
11
|
+
default?: (props: typeof __VLS_8) => any;
|
|
12
|
+
} & {
|
|
13
|
+
footer?: (props: typeof __VLS_10) => any;
|
|
14
|
+
};
|
|
15
|
+
declare const __VLS_base: import('vue').DefineComponent<Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<Props> & Readonly<{}>, {
|
|
16
|
+
title: string;
|
|
17
|
+
subtitle: string;
|
|
18
|
+
wide: boolean;
|
|
19
|
+
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
|
|
20
|
+
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
21
|
+
declare const _default: typeof __VLS_export;
|
|
22
|
+
export default _default;
|
|
23
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
24
|
+
new (): {
|
|
25
|
+
$slots: S;
|
|
26
|
+
};
|
|
27
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
interface Props {
|
|
2
|
+
value?: boolean | null;
|
|
3
|
+
trueLabel?: string;
|
|
4
|
+
falseLabel?: string;
|
|
5
|
+
}
|
|
6
|
+
declare const __VLS_export: import('vue').DefineComponent<Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<Props> & Readonly<{}>, {
|
|
7
|
+
value: boolean | null;
|
|
8
|
+
trueLabel: string;
|
|
9
|
+
falseLabel: string;
|
|
10
|
+
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
|
|
11
|
+
declare const _default: typeof __VLS_export;
|
|
12
|
+
export default _default;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
interface Props {
|
|
2
|
+
modelValue?: boolean;
|
|
3
|
+
label?: string;
|
|
4
|
+
disabled?: boolean;
|
|
5
|
+
}
|
|
6
|
+
declare var __VLS_1: {};
|
|
7
|
+
type __VLS_Slots = {} & {
|
|
8
|
+
default?: (props: typeof __VLS_1) => any;
|
|
9
|
+
};
|
|
10
|
+
declare const __VLS_base: import('vue').DefineComponent<Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {} & {
|
|
11
|
+
change: (value: boolean) => any;
|
|
12
|
+
"update:modelValue": (value: boolean) => any;
|
|
13
|
+
}, string, import('vue').PublicProps, Readonly<Props> & Readonly<{
|
|
14
|
+
onChange?: ((value: boolean) => any) | undefined;
|
|
15
|
+
"onUpdate:modelValue"?: ((value: boolean) => any) | undefined;
|
|
16
|
+
}>, {
|
|
17
|
+
label: string;
|
|
18
|
+
disabled: boolean;
|
|
19
|
+
modelValue: boolean;
|
|
20
|
+
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
|
|
21
|
+
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
22
|
+
declare const _default: typeof __VLS_export;
|
|
23
|
+
export default _default;
|
|
24
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
25
|
+
new (): {
|
|
26
|
+
$slots: S;
|
|
27
|
+
};
|
|
28
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { DetailItem } from '../types/detail';
|
|
2
|
+
interface Props {
|
|
3
|
+
items: readonly DetailItem[];
|
|
4
|
+
/** Columns from `sm` up (1 column on phones). */
|
|
5
|
+
columns?: 1 | 2 | 3;
|
|
6
|
+
emptyText?: string;
|
|
7
|
+
}
|
|
8
|
+
declare const __VLS_export: import('vue').DefineComponent<Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<Props> & Readonly<{}>, {
|
|
9
|
+
emptyText: string;
|
|
10
|
+
columns: 1 | 2 | 3;
|
|
11
|
+
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
|
|
12
|
+
declare const _default: typeof __VLS_export;
|
|
13
|
+
export default _default;
|
|
@@ -6,6 +6,8 @@ type __VLS_Props = {
|
|
|
6
6
|
maxWidthClass?: string;
|
|
7
7
|
align?: 'center' | 'end';
|
|
8
8
|
marginClass?: string;
|
|
9
|
+
/** Brand-green gauge bar in front of the title (icon-less headers). */
|
|
10
|
+
accent?: boolean;
|
|
9
11
|
};
|
|
10
12
|
declare var __VLS_1: {
|
|
11
13
|
iconClass: string;
|
|
@@ -19,6 +21,7 @@ type __VLS_Slots = {} & {
|
|
|
19
21
|
};
|
|
20
22
|
declare const __VLS_base: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
|
|
21
23
|
subtitle: string;
|
|
24
|
+
accent: boolean;
|
|
22
25
|
maxWidthClass: string;
|
|
23
26
|
iconColor: IconColor;
|
|
24
27
|
align: "center" | "end";
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { RouteLocationRaw } from 'vue-router';
|
|
2
|
+
interface Props {
|
|
3
|
+
name: string;
|
|
4
|
+
email?: string;
|
|
5
|
+
/** Profile route; makes the name/email block a link. */
|
|
6
|
+
to?: RouteLocationRaw;
|
|
7
|
+
showLogout?: boolean;
|
|
8
|
+
logoutLabel?: string;
|
|
9
|
+
profileLabel?: string;
|
|
10
|
+
}
|
|
11
|
+
declare const __VLS_export: import('vue').DefineComponent<Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {} & {
|
|
12
|
+
logout: () => any;
|
|
13
|
+
}, string, import('vue').PublicProps, Readonly<Props> & Readonly<{
|
|
14
|
+
onLogout?: (() => any) | undefined;
|
|
15
|
+
}>, {
|
|
16
|
+
email: string;
|
|
17
|
+
to: RouteLocationRaw;
|
|
18
|
+
showLogout: boolean;
|
|
19
|
+
logoutLabel: string;
|
|
20
|
+
profileLabel: string;
|
|
21
|
+
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
|
|
22
|
+
declare const _default: typeof __VLS_export;
|
|
23
|
+
export default _default;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* On/off switch (role="switch"). `v-model` is the boolean; `change` fires
|
|
3
|
+
* after every user toggle with the new value, so callers can persist it.
|
|
4
|
+
* `color` tints the on state; `offTone="red"` shows a red track while off
|
|
5
|
+
* (e.g. "account is down" states).
|
|
6
|
+
*/
|
|
7
|
+
type Color = 'emerald' | 'red' | 'sky' | 'amber';
|
|
8
|
+
interface Props {
|
|
9
|
+
modelValue?: boolean;
|
|
10
|
+
/** Visible label beside the switch (also its accessible name). */
|
|
11
|
+
label?: string;
|
|
12
|
+
/** Accessible name when there is no visible label. */
|
|
13
|
+
ariaLabel?: string;
|
|
14
|
+
color?: Color;
|
|
15
|
+
offTone?: 'slate' | 'red';
|
|
16
|
+
disabled?: boolean;
|
|
17
|
+
}
|
|
18
|
+
declare const __VLS_export: import('vue').DefineComponent<Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {} & {
|
|
19
|
+
change: (value: boolean) => any;
|
|
20
|
+
"update:modelValue": (value: boolean) => any;
|
|
21
|
+
}, string, import('vue').PublicProps, Readonly<Props> & Readonly<{
|
|
22
|
+
onChange?: ((value: boolean) => any) | undefined;
|
|
23
|
+
"onUpdate:modelValue"?: ((value: boolean) => any) | undefined;
|
|
24
|
+
}>, {
|
|
25
|
+
color: Color;
|
|
26
|
+
label: string;
|
|
27
|
+
disabled: boolean;
|
|
28
|
+
ariaLabel: string;
|
|
29
|
+
modelValue: boolean;
|
|
30
|
+
offTone: "slate" | "red";
|
|
31
|
+
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
|
|
32
|
+
declare const _default: typeof __VLS_export;
|
|
33
|
+
export default _default;
|
package/dist/index.d.ts
CHANGED
|
@@ -51,6 +51,13 @@ export { default as BaseSearchSelect } from './components/BaseSearchSelect.vue';
|
|
|
51
51
|
export { default as BaseCard } from './components/BaseCard.vue';
|
|
52
52
|
export { default as BaseField } from './components/BaseField.vue';
|
|
53
53
|
export { default as BaseStatCard } from './components/BaseStatCard.vue';
|
|
54
|
+
export { default as BaseToggle } from './components/BaseToggle.vue';
|
|
55
|
+
export { default as BaseCheckbox } from './components/BaseCheckbox.vue';
|
|
56
|
+
export { default as BaseSidebarUser } from './components/BaseSidebarUser.vue';
|
|
57
|
+
export { default as BaseAuthLayout } from './components/BaseAuthLayout.vue';
|
|
58
|
+
export { default as BaseBooleanBadge } from './components/BaseBooleanBadge.vue';
|
|
59
|
+
export { default as BaseDetailList } from './components/BaseDetailList.vue';
|
|
60
|
+
export type { DetailItem } from './types/detail';
|
|
54
61
|
export { useTheme, initTheme } from './composables/useTheme';
|
|
55
62
|
export type { UseThemeOptions } from './composables/useTheme';
|
|
56
63
|
export { useThemeClasses } from './composables/useThemeClasses';
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One row of a BaseDetailList. `href` renders the value as an external link;
|
|
3
|
+
* `mono` sets it in the monospace face.
|
|
4
|
+
*/
|
|
5
|
+
export interface DetailItem {
|
|
6
|
+
label: string;
|
|
7
|
+
value?: string | number | boolean | null;
|
|
8
|
+
href?: string;
|
|
9
|
+
mono?: boolean;
|
|
10
|
+
}
|