mgv-backoffice 1.20.0 → 1.22.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 +145 -2
- package/dist/components/BaseInput.vue.d.ts +21 -0
- package/dist/components/BaseSegmentedControl.vue.d.ts +25 -0
- package/dist/components/BaseSelect.vue.d.ts +28 -0
- package/dist/components/BaseSpecFields.vue.d.ts +23 -0
- package/dist/components/BaseTable.vue.d.ts +26 -0
- package/dist/components/EarningsCard.vue.d.ts +17 -6
- package/dist/index.d.ts +8 -0
- package/dist/types/segmented.d.ts +11 -0
- package/dist/types/specField.d.ts +23 -0
- package/dist/types/table.d.ts +8 -0
- package/dist/ui-lib.css +1 -1
- package/dist/ui-lib.js +442 -270
- package/dist/ui-lib.umd.cjs +1 -1
- package/package.json +1 -1
- package/src/components/BaseInput.test.ts +40 -0
- package/src/components/BaseInput.vue +46 -0
- package/src/components/BaseSegmentedControl.test.ts +78 -0
- package/src/components/BaseSegmentedControl.vue +98 -0
- package/src/components/BaseSelect.test.ts +37 -0
- package/src/components/BaseSelect.vue +46 -0
- package/src/components/BaseSpecFields.test.ts +78 -0
- package/src/components/BaseSpecFields.vue +83 -0
- package/src/components/BaseTable.test.ts +55 -0
- package/src/components/BaseTable.vue +50 -0
- package/src/components/EarningsCard.test.ts +57 -0
- package/src/components/EarningsCard.vue +55 -18
- package/src/index.ts +10 -0
- package/src/types/segmented.ts +11 -0
- package/src/types/specField.ts +25 -0
- package/src/types/table.ts +8 -0
package/README.md
CHANGED
|
@@ -414,29 +414,43 @@ import { ColoredSquares, ColorsEnums } from 'mgv-backoffice'
|
|
|
414
414
|
|
|
415
415
|
### EarningsCard
|
|
416
416
|
|
|
417
|
-
Earnings summary card with formatted currency display.
|
|
417
|
+
Earnings summary card with formatted currency display. Supports a signed P&L
|
|
418
|
+
mode that renders a red loss theme (and a downward trend glyph) for negative
|
|
419
|
+
amounts.
|
|
418
420
|
|
|
419
421
|
**Props:**
|
|
420
422
|
|
|
421
423
|
| Prop | Type | Default | Description |
|
|
422
424
|
| ---------- | -------- |-------------------------|----------------------|
|
|
423
425
|
| `title` | `String` | `'TOTAL EARNINGS'` | Card heading |
|
|
424
|
-
| `amount` | `Number` | `0` | Monetary value
|
|
426
|
+
| `amount` | `Number` | `0` | Monetary value (a stringified number is coerced) |
|
|
425
427
|
| `subtitle` | `String` | `'Lifetime commission'` | Subheading text |
|
|
426
428
|
| `badge` | `String` | `''` | Optional badge label |
|
|
427
429
|
| `currency` | `String` | `'$'` | Currency symbol |
|
|
428
430
|
| `decimals` | `Number` | `2` | Fraction digits shown for the amount |
|
|
431
|
+
| `accent` | `'orange' \| 'emerald' \| 'red'` | `'orange'` | Card theme. `emerald` tints it green; `red` is the loss theme. |
|
|
432
|
+
| `signed` | `Boolean` | `false` | Treat `amount` as a signed P&L figure: a negative value automatically switches to the `red` loss theme and flips the trend glyph to point **down**; a non-negative value keeps the chosen `accent` and the upward glyph. |
|
|
429
433
|
|
|
430
434
|
**Example:**
|
|
431
435
|
|
|
432
436
|
```vue
|
|
433
437
|
<template>
|
|
438
|
+
<!-- Always-positive total: original behaviour. -->
|
|
434
439
|
<EarningsCard
|
|
435
440
|
title="Monthly Revenue"
|
|
436
441
|
:amount="12500"
|
|
437
442
|
subtitle="April 2026"
|
|
438
443
|
currency="€"
|
|
439
444
|
/>
|
|
445
|
+
|
|
446
|
+
<!-- Signed P&L: renders red + a down arrow when the amount is negative. -->
|
|
447
|
+
<EarningsCard
|
|
448
|
+
title="TOTAL P&L"
|
|
449
|
+
:amount="-128.4"
|
|
450
|
+
subtitle="Realised + unrealised"
|
|
451
|
+
accent="emerald"
|
|
452
|
+
signed
|
|
453
|
+
/>
|
|
440
454
|
</template>
|
|
441
455
|
|
|
442
456
|
<script setup lang="ts">
|
|
@@ -1150,6 +1164,135 @@ import { BaseCopyButton, BaseToastEnum } from 'mgv-backoffice'
|
|
|
1150
1164
|
|
|
1151
1165
|
---
|
|
1152
1166
|
|
|
1167
|
+
## Forms & tables
|
|
1168
|
+
|
|
1169
|
+
These components use `dark:` Tailwind variants, so the consuming app must map
|
|
1170
|
+
the `dark` variant to the `.dark` class that `useTheme()` toggles (see
|
|
1171
|
+
[Tailwind setup for consumers](#tailwind-setup-for-consumers)).
|
|
1172
|
+
|
|
1173
|
+
### BaseInput
|
|
1174
|
+
|
|
1175
|
+
Themed text/number input carrying the shared field skin (slate border,
|
|
1176
|
+
`bg-slate-50` / dark `bg-slate-900` surface). Everything else — `placeholder`,
|
|
1177
|
+
`id`, `disabled`, `step`/`min`, extra classes like `font-mono` or
|
|
1178
|
+
`placeholder:*` — falls through via attrs and Vue class merging.
|
|
1179
|
+
|
|
1180
|
+
**Props:**
|
|
1181
|
+
|
|
1182
|
+
| Prop | Type | Default | Description |
|
|
1183
|
+
| ------------ | ------------------ | -------- | ----------- |
|
|
1184
|
+
| `modelValue` | `String \| Number` | `''` | `v-model` value. |
|
|
1185
|
+
| `type` | `String` | `'text'` | Native input type. |
|
|
1186
|
+
| `size` | `String` | `'md'` | `'md'` = `px-3 py-2`, `'sm'` = `px-2 py-1.5`. |
|
|
1187
|
+
| `block` | `Boolean` | `true` | Full-width (`w-full`); set `false` for inline fields. |
|
|
1188
|
+
|
|
1189
|
+
**Emits:** `update:modelValue(value: string)` — always the raw string; parse
|
|
1190
|
+
numbers in the owner.
|
|
1191
|
+
|
|
1192
|
+
```vue
|
|
1193
|
+
<BaseInput v-model="query" placeholder="e.g. AMD or BTC" class="font-mono" />
|
|
1194
|
+
```
|
|
1195
|
+
|
|
1196
|
+
### BaseSelect
|
|
1197
|
+
|
|
1198
|
+
Themed `<select>` sharing BaseInput's field skin. Options come from the
|
|
1199
|
+
default slot so callers keep full control of `<option>` rendering.
|
|
1200
|
+
|
|
1201
|
+
**Props:**
|
|
1202
|
+
|
|
1203
|
+
| Prop | Type | Default | Description |
|
|
1204
|
+
| ------------ | ------------------ | ------- | ----------- |
|
|
1205
|
+
| `modelValue` | `String \| Number` | `''` | `v-model` value. |
|
|
1206
|
+
| `size` | `String` | `'sm'` | `'sm'` = `px-2 py-1.5`, `'md'` = `px-3 py-2`. |
|
|
1207
|
+
| `block` | `Boolean` | `true` | Full-width; set `false` for inline selects. |
|
|
1208
|
+
|
|
1209
|
+
**Slots:** `default` — the `<option>` elements.
|
|
1210
|
+
**Emits:** `update:modelValue(value: string)`.
|
|
1211
|
+
|
|
1212
|
+
```vue
|
|
1213
|
+
<BaseSelect v-model="strategyType">
|
|
1214
|
+
<option v-for="e in catalog" :key="e.type" :value="e.type" :title="e.description">
|
|
1215
|
+
{{ e.label }}
|
|
1216
|
+
</option>
|
|
1217
|
+
</BaseSelect>
|
|
1218
|
+
```
|
|
1219
|
+
|
|
1220
|
+
### BaseSegmentedControl
|
|
1221
|
+
|
|
1222
|
+
Segmented button group ("All | Stock | Crypto"). One button per option; the
|
|
1223
|
+
selected one gets the filled treatment and `aria-pressed="true"`.
|
|
1224
|
+
|
|
1225
|
+
**Props:**
|
|
1226
|
+
|
|
1227
|
+
| Prop | Type | Default | Description |
|
|
1228
|
+
| ------------- | ------------------- | -------- | ----------- |
|
|
1229
|
+
| `options` | `SegmentedOption[]` | **required** | `{ value, label, title? }` per button. |
|
|
1230
|
+
| `modelValue` | `String \| Number` | **required** | Selected option's `value` (`v-model`). |
|
|
1231
|
+
| `variant` | `String` | `'base'` | `'base'` (`px-3 py-2`, emerald-500 fill), `'wide'` (`px-4 py-2`, emerald-600 fill), `'toolbar'` (`h-9` uppercase `text-xs` with focus-visible rings). |
|
|
1232
|
+
| `ariaLabel` | `String` | `''` | When set, the wrapper renders `role="group"` + `aria-label`. |
|
|
1233
|
+
| `optionClass` | `Function` | — | `(option, active) => string` override for per-button fill classes (e.g. severity colours); layout stays owned by the variant. |
|
|
1234
|
+
|
|
1235
|
+
**Emits:** `update:modelValue(value)`.
|
|
1236
|
+
|
|
1237
|
+
```vue
|
|
1238
|
+
<BaseSegmentedControl v-model="assetFilter" :options="ASSET_FILTERS" />
|
|
1239
|
+
<BaseSegmentedControl v-model="exchange" :options="EXCHANGES" variant="wide" aria-label="Exchange" />
|
|
1240
|
+
```
|
|
1241
|
+
|
|
1242
|
+
### BaseTable
|
|
1243
|
+
|
|
1244
|
+
Styling shell for data tables — **not** a data grid. Owns the table skin
|
|
1245
|
+
(slate header band, `px-4 py-3` header cells, empty-state row); body rows are
|
|
1246
|
+
the caller's own `<tr>` markup via the default slot. Wrap it yourself for
|
|
1247
|
+
scrolling/card chrome (e.g. a `BaseRow` with `overflow-x-auto`).
|
|
1248
|
+
|
|
1249
|
+
**Props:**
|
|
1250
|
+
|
|
1251
|
+
| Prop | Type | Default | Description |
|
|
1252
|
+
| ----------- | --------------- | ------------ | ----------- |
|
|
1253
|
+
| `columns` | `TableColumn[]` | **required** | `{ label, align? }`; `align: 'right'` right-aligns the header cell. |
|
|
1254
|
+
| `empty` | `Boolean` | `false` | True renders the empty-state row spanning every column. |
|
|
1255
|
+
| `emptyText` | `String` | `'No rows.'` | Fallback empty-state text. |
|
|
1256
|
+
|
|
1257
|
+
**Slots:** `default` — the `<tr>` rows; `empty` — custom empty-state content.
|
|
1258
|
+
|
|
1259
|
+
```vue
|
|
1260
|
+
<BaseTable :columns="COLUMNS" :empty="rows.length === 0">
|
|
1261
|
+
<template #empty>No trades match your filters.</template>
|
|
1262
|
+
<tr v-for="row in rows" :key="row.id" class="border-t border-slate-200 dark:border-slate-700">
|
|
1263
|
+
…
|
|
1264
|
+
</tr>
|
|
1265
|
+
</BaseTable>
|
|
1266
|
+
```
|
|
1267
|
+
|
|
1268
|
+
### BaseSpecFields
|
|
1269
|
+
|
|
1270
|
+
Spec-driven form fields: renders a select / checkbox / number input per
|
|
1271
|
+
`SpecField`, with labels and help text, in a responsive two-column grid. Feed
|
|
1272
|
+
it a backend-described catalogue and every form editing those values stays in
|
|
1273
|
+
lockstep. Never mutates `params` — every edit is emitted as `(key, value)`
|
|
1274
|
+
and the owner writes it back into its own state.
|
|
1275
|
+
|
|
1276
|
+
**Props:**
|
|
1277
|
+
|
|
1278
|
+
| Prop | Type | Default | Description |
|
|
1279
|
+
| -------- | -------------------------------- | ------------ | ----------- |
|
|
1280
|
+
| `specs` | `SpecField[]` | **required** | `{ key, label, type: 'decimal' \| 'integer' \| 'boolean' \| 'select', options?, step?, min?, help? }`. |
|
|
1281
|
+
| `params` | `Record<string, SpecFieldValue>` | **required** | Current values keyed by `spec.key`. |
|
|
1282
|
+
|
|
1283
|
+
**Slots:** `after` (`{ spec }`) — extra content under each field (e.g. a live
|
|
1284
|
+
preview attached to one key).
|
|
1285
|
+
**Emits:** `update(key: string, value: SpecFieldValue)` — numbers are parsed
|
|
1286
|
+
(`parseFloat`); unparseable input passes through raw so the owner's
|
|
1287
|
+
validation can catch it.
|
|
1288
|
+
|
|
1289
|
+
```vue
|
|
1290
|
+
<BaseSpecFields :specs="entry.params" :params="form.params"
|
|
1291
|
+
@update="(key, value) => (form.params[key] = value)" />
|
|
1292
|
+
```
|
|
1293
|
+
|
|
1294
|
+
---
|
|
1295
|
+
|
|
1153
1296
|
## Composables
|
|
1154
1297
|
|
|
1155
1298
|
```ts
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
interface Props {
|
|
2
|
+
modelValue?: string | number | null;
|
|
3
|
+
/** Native input type ('text', 'number', 'password', …). */
|
|
4
|
+
type?: string;
|
|
5
|
+
/** 'md' = px-3 py-2 (default); 'sm' = px-2 py-1.5 compact. */
|
|
6
|
+
size?: 'sm' | 'md';
|
|
7
|
+
/** Full-width (w-full). Set false for inline fields. */
|
|
8
|
+
block?: boolean;
|
|
9
|
+
}
|
|
10
|
+
declare const __VLS_export: import('vue').DefineComponent<Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {} & {
|
|
11
|
+
"update:modelValue": (value: string) => any;
|
|
12
|
+
}, string, import('vue').PublicProps, Readonly<Props> & Readonly<{
|
|
13
|
+
"onUpdate:modelValue"?: ((value: string) => any) | undefined;
|
|
14
|
+
}>, {
|
|
15
|
+
type: string;
|
|
16
|
+
size: "sm" | "md";
|
|
17
|
+
block: boolean;
|
|
18
|
+
modelValue: string | number | null;
|
|
19
|
+
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
|
|
20
|
+
declare const _default: typeof __VLS_export;
|
|
21
|
+
export default _default;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { SegmentedOption } from '../types/segmented';
|
|
2
|
+
interface Props {
|
|
3
|
+
options: readonly SegmentedOption[];
|
|
4
|
+
modelValue: string | number;
|
|
5
|
+
variant?: 'base' | 'wide' | 'toolbar';
|
|
6
|
+
/** When set, the wrapper announces itself as a labelled group. */
|
|
7
|
+
ariaLabel?: string;
|
|
8
|
+
/**
|
|
9
|
+
* Override the fill (colour) classes per button — receives the option and
|
|
10
|
+
* whether it is the selected one. Defaults to the variant's emerald/slate
|
|
11
|
+
* treatment.
|
|
12
|
+
*/
|
|
13
|
+
optionClass?: (option: SegmentedOption, active: boolean) => string;
|
|
14
|
+
}
|
|
15
|
+
declare const __VLS_export: import('vue').DefineComponent<Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {} & {
|
|
16
|
+
"update:modelValue": (value: any) => any;
|
|
17
|
+
}, string, import('vue').PublicProps, Readonly<Props> & Readonly<{
|
|
18
|
+
"onUpdate:modelValue"?: ((value: any) => any) | undefined;
|
|
19
|
+
}>, {
|
|
20
|
+
variant: "base" | "wide" | "toolbar";
|
|
21
|
+
ariaLabel: string;
|
|
22
|
+
optionClass: (option: SegmentedOption, active: boolean) => string;
|
|
23
|
+
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
|
|
24
|
+
declare const _default: typeof __VLS_export;
|
|
25
|
+
export default _default;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
interface Props {
|
|
2
|
+
modelValue?: string | null;
|
|
3
|
+
/** 'sm' = px-2 py-1.5 (default, the usual select height); 'md' = px-3 py-2. */
|
|
4
|
+
size?: 'sm' | 'md';
|
|
5
|
+
/** Full-width (w-full). Set false for inline selects. */
|
|
6
|
+
block?: boolean;
|
|
7
|
+
}
|
|
8
|
+
declare var __VLS_1: {};
|
|
9
|
+
type __VLS_Slots = {} & {
|
|
10
|
+
default?: (props: typeof __VLS_1) => any;
|
|
11
|
+
};
|
|
12
|
+
declare const __VLS_base: import('vue').DefineComponent<Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {} & {
|
|
13
|
+
"update:modelValue": (value: any) => any;
|
|
14
|
+
}, string, import('vue').PublicProps, Readonly<Props> & Readonly<{
|
|
15
|
+
"onUpdate:modelValue"?: ((value: any) => any) | undefined;
|
|
16
|
+
}>, {
|
|
17
|
+
size: "sm" | "md";
|
|
18
|
+
block: boolean;
|
|
19
|
+
modelValue: string | null;
|
|
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,23 @@
|
|
|
1
|
+
import { SpecField, SpecFieldValue } from '../types/specField';
|
|
2
|
+
type __VLS_Props = {
|
|
3
|
+
specs: SpecField[];
|
|
4
|
+
params: Record<string, SpecFieldValue>;
|
|
5
|
+
};
|
|
6
|
+
type __VLS_Slots = {
|
|
7
|
+
after?: (props: {
|
|
8
|
+
spec: SpecField;
|
|
9
|
+
}) => unknown;
|
|
10
|
+
};
|
|
11
|
+
declare const __VLS_base: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {} & {
|
|
12
|
+
update: (key: string, value: SpecFieldValue) => any;
|
|
13
|
+
}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
14
|
+
onUpdate?: ((key: string, value: SpecFieldValue) => any) | undefined;
|
|
15
|
+
}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
|
|
16
|
+
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
17
|
+
declare const _default: typeof __VLS_export;
|
|
18
|
+
export default _default;
|
|
19
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
20
|
+
new (): {
|
|
21
|
+
$slots: S;
|
|
22
|
+
};
|
|
23
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { TableColumn } from '../types/table';
|
|
2
|
+
interface Props {
|
|
3
|
+
columns: TableColumn[];
|
|
4
|
+
/** True when there are no rows — renders the empty-state row. */
|
|
5
|
+
empty?: boolean;
|
|
6
|
+
/** Fallback empty-state text; the `empty` slot overrides it. */
|
|
7
|
+
emptyText?: string;
|
|
8
|
+
}
|
|
9
|
+
declare var __VLS_1: {}, __VLS_3: {};
|
|
10
|
+
type __VLS_Slots = {} & {
|
|
11
|
+
empty?: (props: typeof __VLS_1) => any;
|
|
12
|
+
} & {
|
|
13
|
+
default?: (props: typeof __VLS_3) => 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
|
+
emptyText: string;
|
|
17
|
+
empty: boolean;
|
|
18
|
+
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
|
|
19
|
+
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
20
|
+
declare const _default: typeof __VLS_export;
|
|
21
|
+
export default _default;
|
|
22
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
23
|
+
new (): {
|
|
24
|
+
$slots: S;
|
|
25
|
+
};
|
|
26
|
+
};
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Accent colour of the card. Defaults to `orange` so existing consumers are
|
|
3
|
-
* unaffected; `emerald` lets a host app tint the card to a green-themed brand
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
3
|
+
* unaffected; `emerald` lets a host app tint the card to a green-themed brand,
|
|
4
|
+
* and `red` renders a loss/negative theme (also selected automatically by
|
|
5
|
+
* `signed`, see below). Each accent carries the full literal Tailwind class
|
|
6
|
+
* strings (rather than a single interpolated hue) so the classes are statically
|
|
7
|
+
* detectable and the themes can differ in more than hue — e.g. orange renders
|
|
8
|
+
* the amount in neutral grey while emerald/red render it in the accent itself.
|
|
8
9
|
*/
|
|
9
|
-
type Accent = 'orange' | 'emerald';
|
|
10
|
+
type Accent = 'orange' | 'emerald' | 'red';
|
|
10
11
|
interface Props {
|
|
11
12
|
title?: string;
|
|
12
13
|
amount?: number;
|
|
@@ -15,6 +16,15 @@ interface Props {
|
|
|
15
16
|
currency?: string;
|
|
16
17
|
decimals?: number;
|
|
17
18
|
accent?: Accent;
|
|
19
|
+
/**
|
|
20
|
+
* Treat the card as a signed P&L figure. When `true` and the amount is
|
|
21
|
+
* negative, the card renders the loss theme automatically: the `red` accent
|
|
22
|
+
* (border / amount / subtitle / icon-box recoloured) AND the trend glyph
|
|
23
|
+
* flipped to point DOWN. A non-negative amount keeps the chosen `accent` and
|
|
24
|
+
* the upward glyph. Defaults to `false` so existing consumers — which use the
|
|
25
|
+
* card for always-positive totals like lifetime earnings — are unaffected.
|
|
26
|
+
*/
|
|
27
|
+
signed?: boolean;
|
|
18
28
|
}
|
|
19
29
|
declare const __VLS_export: import('vue').DefineComponent<Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<Props> & Readonly<{}>, {
|
|
20
30
|
title: string;
|
|
@@ -24,6 +34,7 @@ declare const __VLS_export: import('vue').DefineComponent<Props, {}, {}, {}, {},
|
|
|
24
34
|
currency: string;
|
|
25
35
|
decimals: number;
|
|
26
36
|
accent: Accent;
|
|
37
|
+
signed: boolean;
|
|
27
38
|
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
|
|
28
39
|
declare const _default: typeof __VLS_export;
|
|
29
40
|
export default _default;
|
package/dist/index.d.ts
CHANGED
|
@@ -28,6 +28,11 @@ export { default as BaseCopyButton } from './components/BaseCopyButton.vue';
|
|
|
28
28
|
export { default as BaseGoogleSignInButton } from './components/BaseGoogleSignInButton.vue';
|
|
29
29
|
export { default as BaseLoginForm } from './components/BaseLoginForm.vue';
|
|
30
30
|
export { default as BaseNotificationPanel } from './components/BaseNotificationPanel.vue';
|
|
31
|
+
export { default as BaseInput } from './components/BaseInput.vue';
|
|
32
|
+
export { default as BaseSelect } from './components/BaseSelect.vue';
|
|
33
|
+
export { default as BaseSegmentedControl } from './components/BaseSegmentedControl.vue';
|
|
34
|
+
export { default as BaseTable } from './components/BaseTable.vue';
|
|
35
|
+
export { default as BaseSpecFields } from './components/BaseSpecFields.vue';
|
|
31
36
|
export { useTheme, initTheme } from './composables/useTheme';
|
|
32
37
|
export type { UseThemeOptions } from './composables/useTheme';
|
|
33
38
|
export { useThemeClasses } from './composables/useThemeClasses';
|
|
@@ -54,6 +59,9 @@ export type { NavItem, NavSection } from './types/sidebar';
|
|
|
54
59
|
export type { EntityPickerItem } from './types/entityPicker';
|
|
55
60
|
export type { LoginCredentials } from './types/auth';
|
|
56
61
|
export type { NotificationItem } from './types/notification';
|
|
62
|
+
export type { SegmentedOption } from './types/segmented';
|
|
63
|
+
export type { TableColumn } from './types/table';
|
|
64
|
+
export type { SpecField, SpecFieldType, SpecFieldValue } from './types/specField';
|
|
57
65
|
export { getBaseColor, getBaseColorOf } from './utils/util';
|
|
58
66
|
export { methodBadgeSolid, methodBadgeBright, statusBadgeSolid, statusBadgeTinted, } from './utils/httpColors';
|
|
59
67
|
export { sanitizeHtml, isSafeHref } from './utils/sanitizeHtml';
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One choice in a BaseSegmentedControl. `value` is what the control emits,
|
|
3
|
+
* `label` what the button shows; `title` becomes the button's tooltip.
|
|
4
|
+
* Generic so callers with union-typed values ('all' | 'STOCK' | …) keep
|
|
5
|
+
* full type-safety through v-model.
|
|
6
|
+
*/
|
|
7
|
+
export interface SegmentedOption<T extends string | number = string | number> {
|
|
8
|
+
value: T;
|
|
9
|
+
label: string;
|
|
10
|
+
title?: string;
|
|
11
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/** Which input a BaseSpecFields entry renders. */
|
|
2
|
+
export type SpecFieldType = 'decimal' | 'integer' | 'boolean' | 'select';
|
|
3
|
+
/**
|
|
4
|
+
* One field of a spec-driven form: the field's key in the value map, its
|
|
5
|
+
* label, which input to render, and optional validation/rendering hints.
|
|
6
|
+
* Members are loose (`| null` allowed) so backend-described catalogues can be
|
|
7
|
+
* passed straight through without mapping.
|
|
8
|
+
*/
|
|
9
|
+
export interface SpecField {
|
|
10
|
+
key: string;
|
|
11
|
+
label: string;
|
|
12
|
+
type: SpecFieldType;
|
|
13
|
+
/** Choices for `type: 'select'`. */
|
|
14
|
+
options?: string[] | null;
|
|
15
|
+
/** Step for numeric inputs; defaults to 1 (integer) / 0.01 (decimal). */
|
|
16
|
+
step?: number | null;
|
|
17
|
+
/** Minimum for numeric inputs. */
|
|
18
|
+
min?: number | null;
|
|
19
|
+
/** Help text rendered under the field. */
|
|
20
|
+
help?: string | null;
|
|
21
|
+
}
|
|
22
|
+
/** A field's current value in the owner's form state. */
|
|
23
|
+
export type SpecFieldValue = number | boolean | string;
|