nuxt-ui-tools 1.25.0 → 1.25.1
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/dist/module.json +1 -1
- package/dist/runtime/display/components/blocks/display-accordion.vue +4 -1
- package/dist/runtime/display/components/blocks/display-alert.vue +5 -2
- package/dist/runtime/display/components/blocks/display-breakdown.vue +13 -7
- package/dist/runtime/display/components/blocks/display-chart.vue +6 -2
- package/dist/runtime/display/components/blocks/display-code.vue +2 -1
- package/dist/runtime/display/components/blocks/display-date.vue +21 -16
- package/dist/runtime/display/components/blocks/display-diff.vue +19 -7
- package/dist/runtime/display/components/blocks/display-empty.vue +3 -2
- package/dist/runtime/display/components/blocks/display-facts.vue +24 -9
- package/dist/runtime/display/components/blocks/display-heading.vue +10 -3
- package/dist/runtime/display/components/blocks/display-list.vue +10 -4
- package/dist/runtime/display/components/blocks/display-media.vue +19 -9
- package/dist/runtime/display/components/blocks/display-meter.vue +12 -11
- package/dist/runtime/display/components/blocks/display-person.vue +12 -5
- package/dist/runtime/display/components/blocks/display-record.vue +78 -18
- package/dist/runtime/display/components/blocks/display-stat.vue +16 -5
- package/dist/runtime/display/components/blocks/display-table.vue +4 -0
- package/dist/runtime/display/components/blocks/display-text.vue +8 -2
- package/dist/runtime/display/components/blocks/display-timeline.vue +7 -1
- package/dist/runtime/display/components/parts/display-actions.vue +4 -1
- package/dist/runtime/display/components/parts/display-chip.vue +27 -1
- package/dist/runtime/display/components/parts/display-fact-value.vue +2 -1
- package/dist/runtime/display/components/parts/display-record-media.d.vue.ts +2 -0
- package/dist/runtime/display/components/parts/display-record-media.vue +5 -3
- package/dist/runtime/display/components/parts/display-record-media.vue.d.ts +2 -0
- package/dist/runtime/display/directives/reveal-truncated.d.ts +10 -0
- package/dist/runtime/display/directives/reveal-truncated.js +31 -0
- package/dist/runtime/display/types/blocks/diff.d.ts +1 -1
- package/dist/runtime/display/types/blocks/facts.d.ts +3 -1
- package/dist/runtime/display/types/blocks/person.d.ts +3 -1
- package/dist/runtime/display/types/blocks/record.d.ts +4 -2
- package/dist/runtime/display/types/config.d.ts +9 -2
- package/dist/runtime/display/types/shared.d.ts +9 -0
- package/dist/runtime/display/utils/config.d.ts +7 -2
- package/dist/runtime/display/utils/config.js +11 -1
- package/dist/runtime/display/utils/links.d.ts +12 -0
- package/dist/runtime/display/utils/links.js +9 -0
- package/dist/runtime/form/composables/use-form-root.js +15 -4
- package/package.json +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { DisplayAction, DisplayBlockBase, DisplayChip, DisplayContent, DisplaySurface, DisplayTone } from '../shared.js';
|
|
1
|
+
import type { DisplayAction, DisplayBlockBase, DisplayChip, DisplayContent, DisplayLinkTarget, DisplaySurface, DisplayTone } from '../shared.js';
|
|
2
2
|
export type DisplayFactsLayout = 'ledger' | 'grid' | 'inline' | 'columns' | 'tiles';
|
|
3
3
|
export type DisplayFactsSlot = 'root' | 'group' | 'groupHeader' | 'groupTitle' | 'groupAside' | 'item' | 'label' | 'hint' | 'value' | 'empty' | 'actions';
|
|
4
4
|
export interface DisplayFact {
|
|
@@ -19,6 +19,8 @@ export interface DisplayFact {
|
|
|
19
19
|
icon?: string;
|
|
20
20
|
/** Makes the value a link. */
|
|
21
21
|
to?: string;
|
|
22
|
+
/** Where `to` opens. Absolute http(s) links open in a new tab by default. */
|
|
23
|
+
target?: DisplayLinkTarget | null;
|
|
22
24
|
/** Draws a placeholder bar instead of the value, such as one figure still loading. */
|
|
23
25
|
loading?: boolean;
|
|
24
26
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { DisplayAvatar, DisplayBlockBase, DisplayChip, DisplayContent, DisplaySize, DisplayText, DisplayTone } from '../shared.js';
|
|
1
|
+
import type { DisplayAvatar, DisplayBlockBase, DisplayChip, DisplayContent, DisplayLinkTarget, DisplaySize, DisplayText, DisplayTone } from '../shared.js';
|
|
2
2
|
export type DisplayPersonSlot = 'root' | 'avatar' | 'body' | 'name' | 'description' | 'chip' | 'group' | 'label' | 'contacts' | 'contact' | 'contactIcon' | 'contactValue';
|
|
3
3
|
export interface DisplayPerson {
|
|
4
4
|
name: DisplayText;
|
|
@@ -14,6 +14,8 @@ export interface DisplayPersonContact {
|
|
|
14
14
|
value: string;
|
|
15
15
|
/** Makes the value a link, such as `mailto:` or `tel:`. */
|
|
16
16
|
href?: string;
|
|
17
|
+
/** Where `href` opens. Absolute http(s) links open in a new tab by default. */
|
|
18
|
+
target?: DisplayLinkTarget | null;
|
|
17
19
|
/** Adds a copy button. Defaults to `true`. */
|
|
18
20
|
copy?: boolean;
|
|
19
21
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { DisplayAvatar, DisplayBlockBase, DisplayChip, DisplayContent, DisplayRevealable, DisplaySurface, DisplayTone } from '../shared.js';
|
|
2
|
-
export type DisplayRecordSlot = 'root' | 'media' | 'icon' | 'body' | 'reference' | 'title' | 'meta' | 'description' | 'badges' | 'trailing' | 'trailingValue' | 'trailingCaption' | 'header' | 'list' | 'item' | 'more' | 'empty';
|
|
1
|
+
import type { DisplayAvatar, DisplayBlockBase, DisplayChip, DisplayContent, DisplayLinkTarget, DisplayRevealable, DisplaySurface, DisplayTone } from '../shared.js';
|
|
2
|
+
export type DisplayRecordSlot = 'root' | 'media' | 'avatar' | 'icon' | 'body' | 'reference' | 'title' | 'meta' | 'description' | 'badges' | 'trailing' | 'trailingValue' | 'trailingCaption' | 'header' | 'list' | 'item' | 'more' | 'empty';
|
|
3
3
|
export interface DisplayRecordItem {
|
|
4
4
|
/** Small reference over the title, such as an identifier. */
|
|
5
5
|
reference?: DisplayContent;
|
|
@@ -25,6 +25,8 @@ export interface DisplayRecordItem {
|
|
|
25
25
|
chip?: DisplayChip;
|
|
26
26
|
/** Makes the record a link. */
|
|
27
27
|
to?: string;
|
|
28
|
+
/** Where `to` opens. Absolute http(s) links open in a new tab by default. */
|
|
29
|
+
target?: DisplayLinkTarget | null;
|
|
28
30
|
onClick?: () => void;
|
|
29
31
|
}
|
|
30
32
|
export interface DisplayRecordProps extends DisplayBlockBase<DisplayRecordSlot>, Partial<DisplayRecordItem>, DisplayRevealable {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { DisplayKind, DisplayPropsMap, DisplayUiMap } from './registry.js';
|
|
2
|
-
import type { DisplayBuiltinTone, DisplayToneRegistry } from './shared.js';
|
|
2
|
+
import type { DisplayBuiltinTone, DisplayChipUi, DisplayToneRegistry } from './shared.js';
|
|
3
3
|
/**
|
|
4
4
|
* Colors of a tone, as CSS colors. Only `color` is needed for a new tone: the ink defaults to it,
|
|
5
5
|
* the soft background and the line mix it into the page background.
|
|
@@ -49,5 +49,12 @@ export interface DisplayUiConfig {
|
|
|
49
49
|
presets?: DisplayPresets;
|
|
50
50
|
/** Extra tones, and color changes to the built-in ones. Register new names in `DisplayToneRegistry`. */
|
|
51
51
|
tones?: Partial<DisplayToneDefinitions>;
|
|
52
|
-
|
|
52
|
+
/**
|
|
53
|
+
* Slot classes per kind, plus `chip`: the `UBadge` slots of every chip the blocks draw (facts
|
|
54
|
+
* chips, record badges, list chips…), so chips match the app's badge style. Tones still color
|
|
55
|
+
* them: leave colors out of these classes.
|
|
56
|
+
*/
|
|
57
|
+
ui?: Partial<DisplayUiMap> & {
|
|
58
|
+
chip?: DisplayChipUi;
|
|
59
|
+
};
|
|
53
60
|
}
|
|
@@ -38,6 +38,11 @@ export type DisplayContent = LazyRenderableValue;
|
|
|
38
38
|
* when the link is used (opened, previewed or downloaded), with the button showing its progress.
|
|
39
39
|
*/
|
|
40
40
|
export type DisplayUrl = string | (() => MaybePromise<string>);
|
|
41
|
+
/**
|
|
42
|
+
* Where a block link opens. Absolute http(s) links default to `_blank`, others to the same tab;
|
|
43
|
+
* `null` keeps an absolute link in the same tab.
|
|
44
|
+
*/
|
|
45
|
+
export type DisplayLinkTarget = '_blank' | '_self' | '_parent' | '_top' | (string & {});
|
|
41
46
|
/** Date accepted by date-aware blocks: a `Date`, an ISO string, or epoch milliseconds. */
|
|
42
47
|
export type DisplayDate = Date | string | number;
|
|
43
48
|
/** Button rendered by a block, with every `UButton` prop. */
|
|
@@ -49,6 +54,10 @@ export interface DisplayChip extends Omit<BadgeProps, 'label'> {
|
|
|
49
54
|
label: DisplayText;
|
|
50
55
|
tone?: DisplayTone;
|
|
51
56
|
}
|
|
57
|
+
/** The `UBadge` slots of a chip. */
|
|
58
|
+
export type DisplayChipSlot = 'base' | 'label' | 'leadingIcon' | 'leadingAvatar' | 'leadingAvatarSize' | 'trailingIcon';
|
|
59
|
+
/** Classes per `UBadge` slot of every chip, from `appConfig.nuxtUiTools.display.ui.chip`. */
|
|
60
|
+
export type DisplayChipUi = DisplayUiSlots<DisplayChipSlot>;
|
|
52
61
|
/** Avatar with every `UAvatar` prop. Without `src`, the initials of `alt` show. */
|
|
53
62
|
export type DisplayAvatar = AvatarProps;
|
|
54
63
|
/** Slot classes of a block: every key is optional and merged over the defaults. */
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import type { AppConfig } from 'nuxt/schema';
|
|
2
|
-
import type { DisplayKind, DisplayPropsMap, DisplayUiConfig } from '../types/index.js';
|
|
2
|
+
import type { DisplayKind, DisplayPropsMap, DisplayUiConfig, DisplayUiSlots } from '../types/index.js';
|
|
3
3
|
/** `appConfig.nuxtUiTools.display`, or an empty config. */
|
|
4
4
|
export declare function resolveAppDisplayConfig(config: Pick<AppConfig, 'nuxtUiTools'>): DisplayUiConfig;
|
|
5
|
-
/**
|
|
5
|
+
/**
|
|
6
|
+
* The props of a block over the defaults of its preset; an unknown preset changes nothing. Slot
|
|
7
|
+
* classes merge per slot, the block's over the preset's, like the other props.
|
|
8
|
+
*/
|
|
6
9
|
export declare function applyDisplayPreset<TKind extends DisplayKind>(kind: TKind, props: DisplayPropsMap[TKind], preset: string | undefined, config: DisplayUiConfig): DisplayPropsMap[TKind];
|
|
10
|
+
/** Two slot class maps merged per slot with tailwind-merge, `over` winning conflicts. */
|
|
11
|
+
export declare function mergeDisplaySlots(base: DisplayUiSlots<string> | undefined, over: DisplayUiSlots<string> | undefined): DisplayUiSlots<string> | undefined;
|
|
@@ -1,7 +1,17 @@
|
|
|
1
|
+
import { twMerge } from "tailwind-merge";
|
|
1
2
|
export function resolveAppDisplayConfig(config) {
|
|
2
3
|
return config.nuxtUiTools?.display ?? {};
|
|
3
4
|
}
|
|
4
5
|
export function applyDisplayPreset(kind, props, preset, config) {
|
|
5
6
|
const defaults = preset === void 0 ? void 0 : config.presets?.[kind]?.[preset];
|
|
6
|
-
|
|
7
|
+
if (!defaults) return props;
|
|
8
|
+
const merged = { ...defaults, ...props };
|
|
9
|
+
const ui = mergeDisplaySlots(defaults.ui, props.ui);
|
|
10
|
+
return ui ? { ...merged, ui } : merged;
|
|
11
|
+
}
|
|
12
|
+
export function mergeDisplaySlots(base, over) {
|
|
13
|
+
if (!base || !over) return base ?? over;
|
|
14
|
+
const merged = { ...base };
|
|
15
|
+
for (const [slot, classes] of Object.entries(over)) merged[slot] = twMerge(base[slot], classes);
|
|
16
|
+
return merged;
|
|
7
17
|
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { DisplayLinkTarget } from '../types/index.js';
|
|
2
|
+
/** Whether a link leaves the app: an absolute http(s) address (route objects never do). */
|
|
3
|
+
export declare function isExternalLink<TTo>(to: TTo): to is TTo & string;
|
|
4
|
+
/**
|
|
5
|
+
* Attributes of a block link: an absolute http(s) address opens in a new tab unless `target` says
|
|
6
|
+
* otherwise, and a new tab never gets access to the app (`noopener noreferrer`).
|
|
7
|
+
*/
|
|
8
|
+
export declare function displayLinkAttrs(to: string, target?: DisplayLinkTarget | null): {
|
|
9
|
+
rel: string | undefined;
|
|
10
|
+
target: DisplayLinkTarget | undefined;
|
|
11
|
+
to: string;
|
|
12
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { isString } from "../../shared/utils/predicate.js";
|
|
2
|
+
const ABSOLUTE = /^https?:\/\//iu;
|
|
3
|
+
export function isExternalLink(to) {
|
|
4
|
+
return isString(to) && ABSOLUTE.test(to);
|
|
5
|
+
}
|
|
6
|
+
export function displayLinkAttrs(to, target) {
|
|
7
|
+
const resolved = target === void 0 ? isExternalLink(to) ? "_blank" : void 0 : target ?? void 0;
|
|
8
|
+
return { rel: resolved === "_blank" ? "noopener noreferrer" : void 0, target: resolved, to };
|
|
9
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useAppConfig } from "nuxt/app";
|
|
2
|
-
import { computed, nextTick, onBeforeUnmount, onMounted, watch } from "vue";
|
|
2
|
+
import { computed, getCurrentInstance, nextTick, onBeforeUnmount, onMounted, watch } from "vue";
|
|
3
3
|
import { useRouter } from "vue-router";
|
|
4
4
|
import { useUiToolsLocale } from "../../i18n/use-locale.js";
|
|
5
5
|
import {
|
|
@@ -19,6 +19,7 @@ import { provideFormRuntime, useFormRuntime } from "./use-form-runtime.js";
|
|
|
19
19
|
import { provideFormUi } from "./use-form-ui.js";
|
|
20
20
|
export function useFormRoot(params) {
|
|
21
21
|
const router = useRouter();
|
|
22
|
+
const appContext = getCurrentInstance()?.appContext;
|
|
22
23
|
const { t } = useUiToolsLocale();
|
|
23
24
|
const appConfig = useAppConfig();
|
|
24
25
|
const schema = computed(() => params.form()?.schema.value ?? params.schema() ?? {});
|
|
@@ -122,11 +123,21 @@ export function useFormRoot(params) {
|
|
|
122
123
|
}
|
|
123
124
|
async function submit() {
|
|
124
125
|
const controller = params.form();
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
params.onSubmitted(runtime.output.value, result);
|
|
126
|
+
try {
|
|
127
|
+
const result = controller ? await controller.submitHandler() : await runtime.submitHandler();
|
|
128
|
+
if (result.success) params.onSubmitted(runtime.output.value, result);
|
|
129
|
+
} catch (error) {
|
|
130
|
+
reportSubmitError(error);
|
|
128
131
|
}
|
|
129
132
|
}
|
|
133
|
+
function reportSubmitError(error) {
|
|
134
|
+
const handler = appContext?.config.errorHandler;
|
|
135
|
+
if (handler) handler(error, null, "nuxt-ui-tools form submit");
|
|
136
|
+
else
|
|
137
|
+
queueMicrotask(() => {
|
|
138
|
+
throw error;
|
|
139
|
+
});
|
|
140
|
+
}
|
|
130
141
|
async function cancel() {
|
|
131
142
|
if (!leaveConfirmed && shouldConfirmDirtyNavigation() && !await confirmLeave()) {
|
|
132
143
|
return;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nuxt-ui-tools",
|
|
3
|
-
"version": "1.25.
|
|
3
|
+
"version": "1.25.1",
|
|
4
4
|
"description": "Nuxt module and runtime toolkit for UI-heavy Nuxt applications",
|
|
5
5
|
"homepage": "https://github.com/ChronicStone/nuxt-ui-tools#readme",
|
|
6
6
|
"bugs": "https://github.com/ChronicStone/nuxt-ui-tools/issues",
|