mgv-backoffice 1.29.0 → 1.31.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 +113 -0
- package/dist/components/BaseCredentialsForm.vue.d.ts +80 -0
- package/dist/components/BaseFilterChip.vue.d.ts +31 -0
- package/dist/composables/useFieldClasses.d.ts +29 -0
- package/dist/composables/useQueryParamSync.d.ts +11 -0
- package/dist/index.d.ts +11 -2
- package/dist/types/specField.d.ts +5 -0
- package/dist/ui-lib.css +1 -1
- package/dist/ui-lib.js +933 -617
- package/dist/ui-lib.umd.cjs +1 -1
- package/dist/utils/format.d.ts +30 -0
- package/dist/utils/httpColors.d.ts +13 -0
- package/dist/utils/kvRows.d.ts +21 -0
- package/dist/utils/specForm.d.ts +20 -0
- package/package.json +1 -1
- package/src/components/BaseCredentialsForm.test.ts +108 -0
- package/src/components/BaseCredentialsForm.vue +241 -0
- package/src/components/BaseFilterChip.test.ts +44 -0
- package/src/components/BaseFilterChip.vue +67 -0
- package/src/composables/useFieldClasses.test.ts +55 -0
- package/src/composables/useFieldClasses.ts +56 -0
- package/src/composables/useQueryParamSync.test.ts +56 -0
- package/src/composables/useQueryParamSync.ts +42 -0
- package/src/index.ts +16 -0
- package/src/types/specField.ts +5 -0
- package/src/utils/format.test.ts +71 -0
- package/src/utils/format.ts +80 -0
- package/src/utils/httpColors.test.ts +38 -0
- package/src/utils/httpColors.ts +31 -0
- package/src/utils/kvRows.test.ts +47 -0
- package/src/utils/kvRows.ts +34 -0
- package/src/utils/specForm.test.ts +53 -0
- package/src/utils/specForm.ts +48 -0
package/README.md
CHANGED
|
@@ -636,8 +636,10 @@ import { getBaseColor, getBaseColorOf } from 'mgv-backoffice'
|
|
|
636
636
|
import {
|
|
637
637
|
methodBadgeSolid,
|
|
638
638
|
methodBadgeBright,
|
|
639
|
+
methodBadgeTinted,
|
|
639
640
|
statusBadgeSolid,
|
|
640
641
|
statusBadgeTinted,
|
|
642
|
+
statusBadgeSoft,
|
|
641
643
|
} from 'mgv-backoffice'
|
|
642
644
|
```
|
|
643
645
|
|
|
@@ -646,6 +648,27 @@ return saturated `bg-*-600` classes for use on neutral surfaces; `Bright` /
|
|
|
646
648
|
`Tinted` variants return softer combinations suitable for cards. `statusBadgeTinted`
|
|
647
649
|
takes `(status, isDark)` to adapt between themes.
|
|
648
650
|
|
|
651
|
+
`methodBadgeTinted(method, isDark)` gives each method its own hue on a soft
|
|
652
|
+
tinted surface (`bg-*-500/15` dark / `bg-*-100` light; GET blue, POST emerald,
|
|
653
|
+
PUT amber, DELETE red, PATCH purple, HEAD sky) — the card-chip palette used by
|
|
654
|
+
WireMate's mock/stub cards. `statusBadgeSoft(status, isDark)` is its status
|
|
655
|
+
companion keyed by status class (emerald 2xx / sky 3xx / amber 4xx / red 5xx).
|
|
656
|
+
|
|
657
|
+
### Key/value row validators
|
|
658
|
+
|
|
659
|
+
```ts
|
|
660
|
+
import { rowKeyMissing, rowValueMissing } from 'mgv-backoffice'
|
|
661
|
+
```
|
|
662
|
+
|
|
663
|
+
| Function | Signature | Returns |
|
|
664
|
+
| ----------------- | ---------------------------------------------------------------------- | ------- |
|
|
665
|
+
| `rowValueMissing` | `(row: { key?, value?, matcherType? }) => boolean` | `true` when the row has a key but no value. |
|
|
666
|
+
| `rowKeyMissing` | `(row: { key?, value?, matcherType? }) => boolean` | `true` when the row has a value but no key. |
|
|
667
|
+
|
|
668
|
+
Consistency checks for dynamic key/value grids (header lists, query params,
|
|
669
|
+
metadata rows). Rows with `matcherType: 'absent'` are exempt — an absent
|
|
670
|
+
matcher intentionally carries no value.
|
|
671
|
+
|
|
649
672
|
### HTML sanitizer
|
|
650
673
|
|
|
651
674
|
```ts
|
|
@@ -692,11 +715,31 @@ API values can be passed without pre-sanitising.
|
|
|
692
715
|
| `fmtNumber` | `(n: number \| string \| null \| undefined, digits = 4) => string` | Fixed-fraction number; em-dash for null/undefined/non-finite. Accepts numeric strings. |
|
|
693
716
|
| `fmtDate` | `(s: string \| number \| null \| undefined) => string` | Locale date-time from ISO string or epoch; em-dash on empty, raw value on parse failure. |
|
|
694
717
|
| `fmtDateTime` | `(ms: number) => string` | Compact `"Mon D, HH:MM"` label from epoch-millis (chart axes/tooltips). |
|
|
718
|
+
| `fmtDateTimeMs`| `(s: string \| number) => string` | Full 24-hour locale date-time WITH the millisecond fraction — for dense feeds where same-second rows must stay distinguishable. |
|
|
695
719
|
| `fmtDateShort` | `(ms: number) => string` | Short `"Mon D"` calendar label from epoch-millis. |
|
|
720
|
+
| `fmtCalendarDate` | `(s: string \| number \| null \| undefined) => string` | `"Mon D, YYYY"` en-US calendar label; em-dash on empty, raw value on parse failure. |
|
|
721
|
+
| `fmtCalendarDateTime` | `(s: string \| number \| null \| undefined) => string` | `"Mon D, YYYY, HH:MM"` en-US calendar label with time of day. |
|
|
722
|
+
| `fmtMsAsSeconds` | `(ms: number \| null \| undefined) => string` | `"= 1.50 s"` magnitude hint for millisecond inputs (3 decimals below 1 s); `''` for non-positive input. |
|
|
723
|
+
| `fmtBytes` | `(bytes: number \| null \| undefined) => string` | `"512 B"` / `"1.5 KB"` / `"2.0 MB"`; `''` for zero/falsy input. |
|
|
696
724
|
| `fmtPrice` | `(n: number) => string` | Price with precision that scales to magnitude (more decimals for sub-cent values). |
|
|
697
725
|
| `fmtPct` | `(n: number, digits = 2) => string` | Percentage with explicit sign, e.g. `"+2.50%"`. |
|
|
698
726
|
| `fmtUsd` | `(v: number) => string` | Signed USD amount with leading sign, e.g. `"+$5.00"`. |
|
|
699
727
|
|
|
728
|
+
### Spec-form helpers
|
|
729
|
+
|
|
730
|
+
```ts
|
|
731
|
+
import { buildSpecParams, firstInvalidNumericSpec } from 'mgv-backoffice'
|
|
732
|
+
```
|
|
733
|
+
|
|
734
|
+
Value-map helpers for spec-driven forms (the state behind `BaseSpecFields`).
|
|
735
|
+
A spec whose `default` is `null` is treated as OPTIONAL — blank means "knob
|
|
736
|
+
disabled" and passes validation.
|
|
737
|
+
|
|
738
|
+
| Function | Signature | Returns |
|
|
739
|
+
| ------------------------ | --------- | ------- |
|
|
740
|
+
| `buildSpecParams` | `(specs: SpecField[] \| undefined, existing: Record<string, SpecFieldValue>) => Record<string, SpecFieldValue>` | Value map seeded from each spec's `default`, keeping overlapping values the caller already has. |
|
|
741
|
+
| `firstInvalidNumericSpec`| `(specs: SpecField[] \| undefined, params: Record<string, SpecFieldValue>) => string \| null` | Label of the first blank / NaN numeric field, or `null` when all numerics are valid. |
|
|
742
|
+
|
|
700
743
|
### Profit & loss
|
|
701
744
|
|
|
702
745
|
```ts
|
|
@@ -1388,6 +1431,72 @@ validation can catch it.
|
|
|
1388
1431
|
@update="(key, value) => (form.params[key] = value)" />
|
|
1389
1432
|
```
|
|
1390
1433
|
|
|
1434
|
+
### BaseFilterChip
|
|
1435
|
+
|
|
1436
|
+
Colour-coded toggleable filter chip — one-click event/category filters above
|
|
1437
|
+
a data feed. Idle renders a tinted border/background in the semantic colour;
|
|
1438
|
+
active renders a solid fill with white text (`aria-pressed` reflects the
|
|
1439
|
+
state). Layout classes (`h-9 flex-1`, …) pass through the class attribute;
|
|
1440
|
+
click handlers bind natively on the component.
|
|
1441
|
+
|
|
1442
|
+
**Props:**
|
|
1443
|
+
|
|
1444
|
+
| Prop | Type | Default | Description |
|
|
1445
|
+
| ---------- | --------- | --------- | ----------- |
|
|
1446
|
+
| `label` | `String` | `''` | Chip text; the default slot overrides it. |
|
|
1447
|
+
| `color` | `'emerald' \| 'sky' \| 'amber' \| 'red' \| 'slate'` | `'slate'` | Semantic colour of the idle tint and active fill. |
|
|
1448
|
+
| `active` | `Boolean` | `false` | Whether the chip's filter is applied (solid fill). |
|
|
1449
|
+
| `disabled` | `Boolean` | `false` | Greys out + blocks the click. |
|
|
1450
|
+
| `title` | `String` | — | Native tooltip. |
|
|
1451
|
+
|
|
1452
|
+
```vue
|
|
1453
|
+
<BaseFilterChip
|
|
1454
|
+
v-for="f in filters"
|
|
1455
|
+
:key="f.key"
|
|
1456
|
+
class="h-9 flex-1"
|
|
1457
|
+
:color="f.color"
|
|
1458
|
+
:active="isActive(f)"
|
|
1459
|
+
:title="f.title"
|
|
1460
|
+
@click="toggle(f)"
|
|
1461
|
+
>{{ f.label }}</BaseFilterChip>
|
|
1462
|
+
```
|
|
1463
|
+
|
|
1464
|
+
### BaseCredentialsForm
|
|
1465
|
+
|
|
1466
|
+
One service's API-credentials card: key id + secret + base/data URLs, with
|
|
1467
|
+
the has-secret handling (placeholder dots, blank-keeps-stored-secret), the
|
|
1468
|
+
save-validation ladder and a saving spinner. Load/save results are EMITTED —
|
|
1469
|
+
the parent owns toasts / error banners. Exposes `load()` so a parent Reload
|
|
1470
|
+
button can re-pull several cards in parallel.
|
|
1471
|
+
|
|
1472
|
+
**Props:** `title` + `idPrefix` + `fetchFn: () => Promise<CredentialsView>` +
|
|
1473
|
+
`updateFn: (body: CredentialsUpdate) => Promise<CredentialsView>` +
|
|
1474
|
+
`defaults: { baseUrl, dataUrl }` (required); `subtitle`, `keyLabel`,
|
|
1475
|
+
`keyPlaceholder`, `secretLabel`, `secretPlaceholder`, `secretSetHint`,
|
|
1476
|
+
`permissionsHint`, `requiredKeyMessage`, `requiredSecretMessage`,
|
|
1477
|
+
`savedMessage`, `saveLabel` (optional copy overrides).
|
|
1478
|
+
|
|
1479
|
+
**Slots:** `no-secret-hint` — rich help while no secret is stored;
|
|
1480
|
+
`base-url-extra` (`{ form }`) — extras under the Base URL field (e.g.
|
|
1481
|
+
live/paper shortcut buttons that write into the form); `footer` — extra
|
|
1482
|
+
content at the card's bottom.
|
|
1483
|
+
|
|
1484
|
+
**Emits:** `saved(message)`, `error(message)`, `load-error(message)`.
|
|
1485
|
+
|
|
1486
|
+
```vue
|
|
1487
|
+
<BaseCredentialsForm
|
|
1488
|
+
ref="card"
|
|
1489
|
+
title="Alpaca API"
|
|
1490
|
+
id-prefix="alpaca"
|
|
1491
|
+
:fetch-fn="fetchAlpaca"
|
|
1492
|
+
:update-fn="updateAlpaca"
|
|
1493
|
+
:defaults="{ baseUrl: LIVE_BASE, dataUrl: DATA_URL }"
|
|
1494
|
+
@saved="onSaved"
|
|
1495
|
+
@error="onError"
|
|
1496
|
+
@load-error="onLoadError"
|
|
1497
|
+
/>
|
|
1498
|
+
```
|
|
1499
|
+
|
|
1391
1500
|
---
|
|
1392
1501
|
|
|
1393
1502
|
## Composables
|
|
@@ -1403,6 +1512,8 @@ import {
|
|
|
1403
1512
|
useMobileSidebar,
|
|
1404
1513
|
useSidebarCollapse,
|
|
1405
1514
|
useNotifications,
|
|
1515
|
+
useQueryParamSync,
|
|
1516
|
+
useFieldClasses,
|
|
1406
1517
|
} from 'mgv-backoffice'
|
|
1407
1518
|
```
|
|
1408
1519
|
|
|
@@ -1417,6 +1528,8 @@ import {
|
|
|
1417
1528
|
| `useMobileSidebar()` | Singleton state shared between `BaseSidebar` and `BaseAppLayout` for the off-canvas open/closed flag. |
|
|
1418
1529
|
| `useSidebarCollapse({ storageKey? })` | Singleton collapsed/expanded state for the desktop sidebar rail, shared between `BaseSidebar` and `BaseAppLayout` and persisted to localStorage (default key `'mgv-sidebar-collapsed'`). |
|
|
1419
1530
|
| `useNotifications()` | Singleton notification state shared by the sidebar bell and `BaseNotificationPanel`: `{ notifications, unreadCount, open, openPanel, closePanel, togglePanel, setNotifications, add, remove, markRead, markAllRead, clear }`. |
|
|
1531
|
+
| `useQueryParamSync()` | URL-query mirroring for filterable views: `{ qparam(name), qenum(name, allowed, fallback), replaceQuery(next) }`. Read filters from the query string once on setup, write changes back with `router.replace` (no-op when unchanged) so filtered views stay shareable without polluting history. |
|
|
1532
|
+
| `useFieldClasses()` | Shared form-field class strings for the gray/emerald form skin: `{ label, input, requiredInput(value) }`. `requiredInput` returns a red border+ring skin while the value is empty and the standard skin otherwise. |
|
|
1420
1533
|
|
|
1421
1534
|
---
|
|
1422
1535
|
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
export interface CredentialsView {
|
|
2
|
+
keyId: string | null;
|
|
3
|
+
baseUrl: string;
|
|
4
|
+
dataUrl: string;
|
|
5
|
+
hasSecret: boolean;
|
|
6
|
+
}
|
|
7
|
+
export interface CredentialsUpdate {
|
|
8
|
+
keyId: string;
|
|
9
|
+
secretKey?: string;
|
|
10
|
+
baseUrl: string;
|
|
11
|
+
dataUrl: string;
|
|
12
|
+
}
|
|
13
|
+
type __VLS_Props = {
|
|
14
|
+
title: string;
|
|
15
|
+
subtitle?: string;
|
|
16
|
+
idPrefix: string;
|
|
17
|
+
keyLabel?: string;
|
|
18
|
+
keyPlaceholder?: string;
|
|
19
|
+
secretLabel?: string;
|
|
20
|
+
secretPlaceholder?: string;
|
|
21
|
+
secretSetHint?: string;
|
|
22
|
+
permissionsHint?: string;
|
|
23
|
+
requiredKeyMessage?: string;
|
|
24
|
+
requiredSecretMessage?: string;
|
|
25
|
+
savedMessage?: string;
|
|
26
|
+
saveLabel?: string;
|
|
27
|
+
fetchFn: () => Promise<CredentialsView>;
|
|
28
|
+
updateFn: (body: CredentialsUpdate) => Promise<CredentialsView>;
|
|
29
|
+
defaults: {
|
|
30
|
+
baseUrl: string;
|
|
31
|
+
dataUrl: string;
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
declare function load(): Promise<void>;
|
|
35
|
+
declare var __VLS_23: {}, __VLS_30: {
|
|
36
|
+
form: {
|
|
37
|
+
keyId: string;
|
|
38
|
+
secretKey: string;
|
|
39
|
+
baseUrl: string;
|
|
40
|
+
dataUrl: string;
|
|
41
|
+
};
|
|
42
|
+
}, __VLS_44: {};
|
|
43
|
+
type __VLS_Slots = {} & {
|
|
44
|
+
'no-secret-hint'?: (props: typeof __VLS_23) => any;
|
|
45
|
+
} & {
|
|
46
|
+
'base-url-extra'?: (props: typeof __VLS_30) => any;
|
|
47
|
+
} & {
|
|
48
|
+
footer?: (props: typeof __VLS_44) => any;
|
|
49
|
+
};
|
|
50
|
+
declare const __VLS_base: import('vue').DefineComponent<__VLS_Props, {
|
|
51
|
+
load: typeof load;
|
|
52
|
+
}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {} & {
|
|
53
|
+
error: (message: string) => any;
|
|
54
|
+
saved: (message: string) => any;
|
|
55
|
+
"load-error": (message: string) => any;
|
|
56
|
+
}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
57
|
+
onError?: ((message: string) => any) | undefined;
|
|
58
|
+
onSaved?: ((message: string) => any) | undefined;
|
|
59
|
+
"onLoad-error"?: ((message: string) => any) | undefined;
|
|
60
|
+
}>, {
|
|
61
|
+
subtitle: string;
|
|
62
|
+
keyLabel: string;
|
|
63
|
+
keyPlaceholder: string;
|
|
64
|
+
secretLabel: string;
|
|
65
|
+
secretPlaceholder: string;
|
|
66
|
+
secretSetHint: string;
|
|
67
|
+
permissionsHint: string;
|
|
68
|
+
requiredKeyMessage: string;
|
|
69
|
+
requiredSecretMessage: string;
|
|
70
|
+
savedMessage: string;
|
|
71
|
+
saveLabel: string;
|
|
72
|
+
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
|
|
73
|
+
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
74
|
+
declare const _default: typeof __VLS_export;
|
|
75
|
+
export default _default;
|
|
76
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
77
|
+
new (): {
|
|
78
|
+
$slots: S;
|
|
79
|
+
};
|
|
80
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
type FilterChipColor = 'emerald' | 'sky' | 'amber' | 'red' | 'slate';
|
|
2
|
+
type __VLS_Props = {
|
|
3
|
+
/** Chip text; the default slot overrides it. */
|
|
4
|
+
label?: string;
|
|
5
|
+
/** Semantic colour of both the idle tint and the active solid fill. */
|
|
6
|
+
color?: FilterChipColor;
|
|
7
|
+
/** Whether the chip's filter is currently applied (solid fill). */
|
|
8
|
+
active?: boolean;
|
|
9
|
+
disabled?: boolean;
|
|
10
|
+
/** Native tooltip. */
|
|
11
|
+
title?: string;
|
|
12
|
+
};
|
|
13
|
+
declare var __VLS_1: {};
|
|
14
|
+
type __VLS_Slots = {} & {
|
|
15
|
+
default?: (props: typeof __VLS_1) => any;
|
|
16
|
+
};
|
|
17
|
+
declare const __VLS_base: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
|
|
18
|
+
title: string;
|
|
19
|
+
color: FilterChipColor;
|
|
20
|
+
label: string;
|
|
21
|
+
disabled: boolean;
|
|
22
|
+
active: boolean;
|
|
23
|
+
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
|
|
24
|
+
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
25
|
+
declare const _default: typeof __VLS_export;
|
|
26
|
+
export default _default;
|
|
27
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
28
|
+
new (): {
|
|
29
|
+
$slots: S;
|
|
30
|
+
};
|
|
31
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { ComputedRef } from 'vue';
|
|
2
|
+
/**
|
|
3
|
+
* Shared form-field class strings for the gray/emerald form skin
|
|
4
|
+
* (the WireMate mock-form family). Extracted because the exact same
|
|
5
|
+
* `labelClasses` / `inputClasses` / `requiredInputClasses` trio was
|
|
6
|
+
* copy-pasted across every form section component.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
*
|
|
10
|
+
* const f = useFieldClasses()
|
|
11
|
+
* <label :class="f.label">Name</label>
|
|
12
|
+
* <input :class="f.input" />
|
|
13
|
+
* <input :class="f.requiredInput(value)" /> // red skin while empty
|
|
14
|
+
*
|
|
15
|
+
* Vue auto-unwraps the computed refs in template bindings; `requiredInput`
|
|
16
|
+
* is a plain function and is called with the current field value.
|
|
17
|
+
*/
|
|
18
|
+
export interface FieldClasses {
|
|
19
|
+
/** Form label: gray-300 / gray-600. */
|
|
20
|
+
label: ComputedRef<string>;
|
|
21
|
+
/** Standard input skin: gray-800 dark surface / white light surface, emerald focus. */
|
|
22
|
+
input: ComputedRef<string>;
|
|
23
|
+
/**
|
|
24
|
+
* Input skin for required fields: red border + ring while the value is
|
|
25
|
+
* empty (undefined / null / blank after trim), the standard skin otherwise.
|
|
26
|
+
*/
|
|
27
|
+
requiredInput: (value: string | number | undefined | null) => string;
|
|
28
|
+
}
|
|
29
|
+
export declare function useFieldClasses(): FieldClasses;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* URL-query mirroring helpers for filterable views: read a filter's initial
|
|
3
|
+
* state from the query string once on setup, then write changes back with
|
|
4
|
+
* `replaceQuery` so a filtered view can be copied, shared and bookmarked
|
|
5
|
+
* without filter tweaks piling up in the browser history.
|
|
6
|
+
*/
|
|
7
|
+
export declare function useQueryParamSync(): {
|
|
8
|
+
qparam: (name: string) => string;
|
|
9
|
+
qenum: <T extends string>(name: string, allowed: readonly T[], fallback: T) => T;
|
|
10
|
+
replaceQuery: (next: Record<string, string>) => void;
|
|
11
|
+
};
|
package/dist/index.d.ts
CHANGED
|
@@ -38,6 +38,9 @@ export { default as BaseSegmentedControl } from './components/BaseSegmentedContr
|
|
|
38
38
|
export { default as BaseTable } from './components/BaseTable.vue';
|
|
39
39
|
export { default as BaseSpecFields } from './components/BaseSpecFields.vue';
|
|
40
40
|
export { default as BaseStatBreakdown } from './components/BaseStatBreakdown.vue';
|
|
41
|
+
export { default as BaseFilterChip } from './components/BaseFilterChip.vue';
|
|
42
|
+
export { default as BaseCredentialsForm } from './components/BaseCredentialsForm.vue';
|
|
43
|
+
export type { CredentialsView, CredentialsUpdate } from './components/BaseCredentialsForm.vue';
|
|
41
44
|
export { useTheme, initTheme } from './composables/useTheme';
|
|
42
45
|
export type { UseThemeOptions } from './composables/useTheme';
|
|
43
46
|
export { useThemeClasses } from './composables/useThemeClasses';
|
|
@@ -49,6 +52,9 @@ export { useMobileSidebar } from './composables/useMobileSidebar';
|
|
|
49
52
|
export { useSidebarCollapse } from './composables/useSidebarCollapse';
|
|
50
53
|
export type { UseSidebarCollapseOptions } from './composables/useSidebarCollapse';
|
|
51
54
|
export { useNotifications } from './composables/useNotifications';
|
|
55
|
+
export { useQueryParamSync } from './composables/useQueryParamSync';
|
|
56
|
+
export { useFieldClasses } from './composables/useFieldClasses';
|
|
57
|
+
export type { FieldClasses } from './composables/useFieldClasses';
|
|
52
58
|
export { AlertEnum } from './enums/AlertEnum';
|
|
53
59
|
export { BaseBadgeEnum } from './enums/BaseBadgeEnum';
|
|
54
60
|
export { BaseButtonEnum } from './enums/BaseButtonEnum';
|
|
@@ -70,8 +76,11 @@ export type { TableColumn } from './types/table';
|
|
|
70
76
|
export type { SpecField, SpecFieldType, SpecFieldValue } from './types/specField';
|
|
71
77
|
export type { StatBreakdownItem } from './types/statBreakdown';
|
|
72
78
|
export { getBaseColor, getBaseColorOf } from './utils/util';
|
|
73
|
-
export { methodBadgeSolid, methodBadgeBright, statusBadgeSolid, statusBadgeTinted, } from './utils/httpColors';
|
|
79
|
+
export { methodBadgeSolid, methodBadgeBright, methodBadgeTinted, statusBadgeSolid, statusBadgeTinted, statusBadgeSoft, } from './utils/httpColors';
|
|
80
|
+
export { rowKeyMissing, rowValueMissing } from './utils/kvRows';
|
|
81
|
+
export type { KeyValueRowLike } from './utils/kvRows';
|
|
74
82
|
export { sanitizeHtml, isSafeHref } from './utils/sanitizeHtml';
|
|
75
|
-
export { fmtNumber, fmtDate, fmtDateTime, fmtDateShort, fmtPrice, fmtPct, fmtUsd, fmtDuration, } from './utils/format';
|
|
83
|
+
export { fmtNumber, fmtDate, fmtDateTime, fmtDateTimeMs, fmtDateShort, fmtCalendarDate, fmtCalendarDateTime, fmtMsAsSeconds, fmtBytes, fmtPrice, fmtPct, fmtUsd, fmtDuration, } from './utils/format';
|
|
84
|
+
export { buildSpecParams, firstInvalidNumericSpec } from './utils/specForm';
|
|
76
85
|
export { computePnL } from './utils/pnl';
|
|
77
86
|
export type { PnL, PnLInputs } from './utils/pnl';
|
|
@@ -10,6 +10,11 @@ export interface SpecField {
|
|
|
10
10
|
key: string;
|
|
11
11
|
label: string;
|
|
12
12
|
type: SpecFieldType;
|
|
13
|
+
/**
|
|
14
|
+
* Default value the form seeds the field with. `null` marks the field as
|
|
15
|
+
* OPTIONAL for `firstInvalidNumericSpec` (blank = "knob disabled").
|
|
16
|
+
*/
|
|
17
|
+
default?: SpecFieldValue | null;
|
|
13
18
|
/** Choices for `type: 'select'`. */
|
|
14
19
|
options?: string[] | null;
|
|
15
20
|
/** Step for numeric inputs; defaults to 1 (integer) / 0.01 (decimal). */
|