nuxt-ui-tools 1.25.0 → 1.26.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/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/file-preview/components/shell/file-preview-header.d.vue.ts +2 -0
- package/dist/runtime/file-preview/components/shell/file-preview-header.vue +13 -7
- package/dist/runtime/file-preview/components/shell/file-preview-header.vue.d.ts +2 -0
- package/dist/runtime/file-preview/components/shell/file-preview-shell.vue +6 -0
- package/dist/runtime/file-preview/components/shell/file-preview-stage.d.vue.ts +5 -3
- package/dist/runtime/file-preview/components/shell/file-preview-stage.vue +4 -10
- package/dist/runtime/file-preview/components/shell/file-preview-stage.vue.d.ts +5 -3
- package/dist/runtime/form/components/root/form.vue +1 -0
- package/dist/runtime/form/composables/use-field-options.js +3 -1
- package/dist/runtime/form/composables/use-form-overlay-controller.js +1 -1
- package/dist/runtime/form/composables/use-form-root.d.ts +3 -1
- package/dist/runtime/form/composables/use-form-root.js +41 -15
- package/dist/runtime/form/composables/use-form-runtime.js +14 -4
- package/dist/runtime/form/composables/use-form-validation.d.ts +5 -2
- package/dist/runtime/form/composables/use-form-validation.js +51 -5
- package/dist/runtime/form/fields/custom-component/component.vue +2 -3
- package/dist/runtime/form/fields/date-family/component.vue +7 -6
- package/dist/runtime/form/fields/date-family/utils.d.ts +5 -0
- package/dist/runtime/form/fields/date-family/utils.js +13 -0
- package/dist/runtime/form/fields/number/component.vue +11 -5
- package/dist/runtime/form/fields/phone-number/component.vue +20 -1
- package/dist/runtime/form/types/api.d.ts +9 -2
- package/dist/runtime/form/types/options.d.ts +4 -1
- package/dist/runtime/form/types/runtime.d.ts +10 -0
- package/dist/runtime/form/types/schema.d.ts +5 -1
- package/dist/runtime/form/utils/api.js +1 -0
- package/dist/runtime/i18n/locales/en.js +12 -3
- package/dist/runtime/i18n/locales/fr.js +12 -3
- package/dist/runtime/i18n/types.d.ts +16 -0
- package/dist/runtime/table/components/filters/tags/date-filter-tag.vue +4 -0
- package/dist/runtime/table/types/filters.d.ts +17 -0
- package/dist/runtime/table/utils/filters/options.js +2 -1
- package/dist/runtime/table/utils/filters/preview/option-preview.js +4 -1
- package/package.json +1 -1
package/dist/module.json
CHANGED
|
@@ -3,6 +3,7 @@ import UIcon from "@nuxt/ui/components/Icon.vue";
|
|
|
3
3
|
import { computed, defineAsyncComponent, ref, useId } from "vue";
|
|
4
4
|
import { useDisplayAppUi } from "../../composables/use-display-config";
|
|
5
5
|
import { useDisplayIcons } from "../../composables/use-display-icons";
|
|
6
|
+
import { vRevealTruncated } from "../../directives/reveal-truncated";
|
|
6
7
|
import { resolveDisplayClasses } from "../../utils/classes";
|
|
7
8
|
import DisplayRender from "../parts/display-render";
|
|
8
9
|
import DisplaySkeleton from "../parts/display-skeleton.vue";
|
|
@@ -67,7 +68,9 @@ function toggle(index) {
|
|
|
67
68
|
@click="toggle(index)"
|
|
68
69
|
>
|
|
69
70
|
<UIcon v-if="item.icon" :name="item.icon" :class="classes.icon" />
|
|
70
|
-
<span :class="classes.label"
|
|
71
|
+
<span v-reveal-truncated :class="classes.label"
|
|
72
|
+
><DisplayRender :content="item.label"
|
|
73
|
+
/></span>
|
|
71
74
|
<UIcon
|
|
72
75
|
:name="icons.chevronDown"
|
|
73
76
|
:class="[classes.chevron, open.includes(index) ? 'rotate-180' : '']"
|
|
@@ -4,6 +4,7 @@ import { computed, ref } from "vue";
|
|
|
4
4
|
import { useDisplayAppUi } from "../../composables/use-display-config";
|
|
5
5
|
import { toneIcon, useDisplayIcons } from "../../composables/use-display-icons";
|
|
6
6
|
import { useDisplayLocale } from "../../composables/use-display-locale";
|
|
7
|
+
import { vRevealTruncated } from "../../directives/reveal-truncated";
|
|
7
8
|
import { resolveDisplayClasses } from "../../utils/classes";
|
|
8
9
|
import { isDisplayContentEmpty } from "../../utils/content";
|
|
9
10
|
import { displayToneClass } from "../../utils/tone";
|
|
@@ -93,8 +94,10 @@ const classes = computed(
|
|
|
93
94
|
</span>
|
|
94
95
|
<UIcon v-else-if="resolvedIcon" :name="resolvedIcon" :class="classes.icon" />
|
|
95
96
|
<div :class="classes.body">
|
|
96
|
-
<div v-if="titled" :class="classes.title"
|
|
97
|
-
|
|
97
|
+
<div v-if="titled" v-reveal-truncated :class="classes.title">
|
|
98
|
+
<DisplayRender :content="title" />
|
|
99
|
+
</div>
|
|
100
|
+
<div v-if="!isDisplayContentEmpty(message)" v-reveal-truncated :class="classes.message">
|
|
98
101
|
<DisplayRender :content="message" />
|
|
99
102
|
</div>
|
|
100
103
|
<div v-if="items?.length" :class="classes.items">
|
|
@@ -5,6 +5,7 @@ import { computed, ref } from "vue";
|
|
|
5
5
|
import { useDisplayAppUi } from "../../composables/use-display-config";
|
|
6
6
|
import { useDisplayIcons } from "../../composables/use-display-icons";
|
|
7
7
|
import { useDisplayLocale } from "../../composables/use-display-locale";
|
|
8
|
+
import { vRevealTruncated } from "../../directives/reveal-truncated";
|
|
8
9
|
import { resolveDisplayClasses } from "../../utils/classes";
|
|
9
10
|
import { isDisplayContentEmpty } from "../../utils/content";
|
|
10
11
|
import { DISPLAY_SURFACE_CLASSES, displayToneClass } from "../../utils/tone";
|
|
@@ -100,6 +101,7 @@ function valueClass(line) {
|
|
|
100
101
|
<td
|
|
101
102
|
v-for="(cell, cellIndex) in line.values ?? []"
|
|
102
103
|
:key="cellIndex"
|
|
104
|
+
v-reveal-truncated
|
|
103
105
|
:class="['px-4 py-2 text-end', valueClass(line)]"
|
|
104
106
|
>
|
|
105
107
|
<DisplayRender :content="cell" />
|
|
@@ -122,7 +124,7 @@ function valueClass(line) {
|
|
|
122
124
|
</div>
|
|
123
125
|
<div v-else-if="mode === 'collapsible'" :class="classes.root">
|
|
124
126
|
<div :class="classes.total">
|
|
125
|
-
<span :class="classes.totalLabel">
|
|
127
|
+
<span v-reveal-truncated :class="classes.totalLabel">
|
|
126
128
|
<DisplayRender :content="total?.label ?? title" />
|
|
127
129
|
<DisplayChip v-if="total?.chip" :chip="total.chip" />
|
|
128
130
|
</span>
|
|
@@ -140,31 +142,35 @@ function valueClass(line) {
|
|
|
140
142
|
</div>
|
|
141
143
|
<div v-if="open" :class="classes.body">
|
|
142
144
|
<div v-for="(line, index) in lines" :key="index" :class="lineClass(line)">
|
|
143
|
-
<span :class="classes.label">
|
|
145
|
+
<span v-reveal-truncated :class="classes.label">
|
|
144
146
|
<DisplayRender :content="line.label" />
|
|
145
147
|
<span v-if="!isDisplayContentEmpty(line.detail)" :class="classes.detail"
|
|
146
148
|
><DisplayRender :content="line.detail"
|
|
147
149
|
/></span>
|
|
148
150
|
</span>
|
|
149
|
-
<span :class="valueClass(line)"
|
|
151
|
+
<span v-reveal-truncated :class="valueClass(line)"
|
|
152
|
+
><DisplayRender :content="line.value"
|
|
153
|
+
/></span>
|
|
150
154
|
</div>
|
|
151
155
|
</div>
|
|
152
156
|
</div>
|
|
153
157
|
<div v-else :class="classes.root">
|
|
154
|
-
<div v-if="!isDisplayContentEmpty(title)" :class="classes.title">
|
|
158
|
+
<div v-if="!isDisplayContentEmpty(title)" v-reveal-truncated :class="classes.title">
|
|
155
159
|
<DisplayRender :content="title" />
|
|
156
160
|
</div>
|
|
157
161
|
<div v-for="(line, index) in lines" :key="index" :class="lineClass(line)">
|
|
158
|
-
<span :class="classes.label">
|
|
162
|
+
<span v-reveal-truncated :class="classes.label">
|
|
159
163
|
<DisplayRender :content="line.label" />
|
|
160
164
|
<span v-if="!isDisplayContentEmpty(line.detail)" :class="classes.detail"
|
|
161
165
|
><DisplayRender :content="line.detail"
|
|
162
166
|
/></span>
|
|
163
167
|
</span>
|
|
164
|
-
<span :class="valueClass(line)"
|
|
168
|
+
<span v-reveal-truncated :class="valueClass(line)"
|
|
169
|
+
><DisplayRender :content="line.value"
|
|
170
|
+
/></span>
|
|
165
171
|
</div>
|
|
166
172
|
<div v-if="total" :class="classes.total">
|
|
167
|
-
<span :class="classes.totalLabel">
|
|
173
|
+
<span v-reveal-truncated :class="classes.totalLabel">
|
|
168
174
|
<DisplayRender :content="total.label" />
|
|
169
175
|
<DisplayChip v-if="total.chip" :chip="total.chip" />
|
|
170
176
|
</span>
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { computed } from "vue";
|
|
3
3
|
import { useDisplayAppUi } from "../../composables/use-display-config";
|
|
4
4
|
import { useDisplayNumber } from "../../composables/use-display-number";
|
|
5
|
+
import { vRevealTruncated } from "../../directives/reveal-truncated";
|
|
5
6
|
import { resolveDisplayClasses } from "../../utils/classes";
|
|
6
7
|
import { isDisplayContentEmpty, resolveDisplayText } from "../../utils/content";
|
|
7
8
|
import DisplayEmptyLine from "../parts/display-empty-line.vue";
|
|
@@ -113,7 +114,7 @@ function colorOf(datum, index) {
|
|
|
113
114
|
v-if="!isDisplayContentEmpty(title) || !isDisplayContentEmpty(aside)"
|
|
114
115
|
:class="classes.header"
|
|
115
116
|
>
|
|
116
|
-
<span :class="classes.title"><DisplayRender :content="title" /></span>
|
|
117
|
+
<span v-reveal-truncated :class="classes.title"><DisplayRender :content="title" /></span>
|
|
117
118
|
<span :class="classes.aside"><DisplayRender :content="aside" /></span>
|
|
118
119
|
</div>
|
|
119
120
|
<DisplayEmptyLine v-if="!data.length" :content="empty" :class="classes.plot" />
|
|
@@ -145,6 +146,7 @@ function colorOf(datum, index) {
|
|
|
145
146
|
<span
|
|
146
147
|
v-for="(datum, index) in data"
|
|
147
148
|
:key="index"
|
|
149
|
+
v-reveal-truncated
|
|
148
150
|
class="min-w-0 flex-1 truncate text-center"
|
|
149
151
|
>
|
|
150
152
|
{{ resolveDisplayText(datum.label) }}
|
|
@@ -220,7 +222,9 @@ function colorOf(datum, index) {
|
|
|
220
222
|
</div>
|
|
221
223
|
<div v-else-if="variant === 'funnel'" :class="[classes.plot, 'flex flex-col gap-1.5']">
|
|
222
224
|
<div v-for="(step, index) in steps" :key="index" :class="classes.step">
|
|
223
|
-
<span :class="classes.stepLabel">{{
|
|
225
|
+
<span v-reveal-truncated :class="classes.stepLabel">{{
|
|
226
|
+
resolveDisplayText(step.label)
|
|
227
|
+
}}</span>
|
|
224
228
|
<span
|
|
225
229
|
class="h-4 rounded-[3px]"
|
|
226
230
|
:style="{
|
|
@@ -6,6 +6,7 @@ import { isNumber } from "../../../shared/utils/predicate";
|
|
|
6
6
|
import { useDisplayAppUi } from "../../composables/use-display-config";
|
|
7
7
|
import { useDisplayIcons } from "../../composables/use-display-icons";
|
|
8
8
|
import { useDisplayLocale } from "../../composables/use-display-locale";
|
|
9
|
+
import { vRevealTruncated } from "../../directives/reveal-truncated";
|
|
9
10
|
import { resolveDisplayClasses } from "../../utils/classes";
|
|
10
11
|
import { resolveDisplayText } from "../../utils/content";
|
|
11
12
|
import { tokenizeJson } from "../../utils/json";
|
|
@@ -109,7 +110,7 @@ const classes = computed(
|
|
|
109
110
|
</div>
|
|
110
111
|
<div v-else :class="classes.root" data-display="code" :data-variant="variant">
|
|
111
112
|
<UIcon v-if="icon" :name="icon" :class="classes.icon" />
|
|
112
|
-
<span :class="classes.value" data-display-value>{{
|
|
113
|
+
<span v-reveal-truncated :class="classes.value" data-display-value>{{
|
|
113
114
|
variant === "secret" && !revealed ? masked : value
|
|
114
115
|
}}</span>
|
|
115
116
|
<div :class="classes.actions">
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
<script setup>
|
|
2
|
-
import UBadge from "@nuxt/ui/components/Badge.vue";
|
|
3
2
|
import UIcon from "@nuxt/ui/components/Icon.vue";
|
|
4
3
|
import { computed } from "vue";
|
|
5
4
|
import { useDisplayAppUi } from "../../composables/use-display-config";
|
|
6
5
|
import { useDisplayIcons } from "../../composables/use-display-icons";
|
|
7
6
|
import { useDisplayLocale } from "../../composables/use-display-locale";
|
|
7
|
+
import { vRevealTruncated } from "../../directives/reveal-truncated";
|
|
8
8
|
import { resolveDisplayClasses } from "../../utils/classes";
|
|
9
9
|
import { isDisplayContentEmpty, resolveDisplayText } from "../../utils/content";
|
|
10
10
|
import {
|
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
toDisplayDate
|
|
17
17
|
} from "../../utils/dates";
|
|
18
18
|
import { displayToneClass } from "../../utils/tone";
|
|
19
|
+
import DisplayChip from "../parts/display-chip.vue";
|
|
19
20
|
import DisplayRender from "../parts/display-render";
|
|
20
21
|
import DisplaySkeleton from "../parts/display-skeleton.vue";
|
|
21
22
|
const {
|
|
@@ -83,7 +84,10 @@ const countdownText = computed(() => {
|
|
|
83
84
|
return t("display.overdue", { duration: formatDayCount(-days.value, code.value) });
|
|
84
85
|
return formatRelativeDays(days.value, code.value);
|
|
85
86
|
});
|
|
86
|
-
const longDate = (date) => date ? formatDisplayDate(date, code.value,
|
|
87
|
+
const longDate = (date) => date ? formatDisplayDate(date, code.value, {
|
|
88
|
+
...time ? LONG_DATE_TIME_FORMAT : LONG_DATE_FORMAT,
|
|
89
|
+
year: date.getFullYear() === reference.value.getFullYear() ? void 0 : "numeric"
|
|
90
|
+
}) : "";
|
|
87
91
|
const duration = computed(
|
|
88
92
|
() => start.value && finish.value ? formatDayCount(calendarDaysBetween(start.value, finish.value) + 1, code.value) : void 0
|
|
89
93
|
);
|
|
@@ -124,8 +128,10 @@ const classes = computed(
|
|
|
124
128
|
<template v-if="variant === 'countdown'">
|
|
125
129
|
<UIcon :name="icon ?? (overdue ? icons.warning : 'i-lucide-clock')" :class="classes.icon" />
|
|
126
130
|
<div :class="classes.body">
|
|
127
|
-
<div :class="classes.value" data-display-countdown>
|
|
128
|
-
|
|
131
|
+
<div v-reveal-truncated :class="classes.value" data-display-countdown>
|
|
132
|
+
{{ countdownText }}
|
|
133
|
+
</div>
|
|
134
|
+
<div v-reveal-truncated :class="classes.caption">
|
|
129
135
|
<DisplayRender
|
|
130
136
|
:content="
|
|
131
137
|
description ?? (deadline ? t('display.dueOn', { date: longDate(start) }) : longDate(start))
|
|
@@ -137,21 +143,14 @@ const classes = computed(
|
|
|
137
143
|
<template v-else-if="variant === 'range'">
|
|
138
144
|
<div :class="classes.bound">
|
|
139
145
|
<span :class="classes.boundLabel">{{ t("display.from") }}</span>
|
|
140
|
-
<span :class="classes.boundValue">{{ longDate(start) }}</span>
|
|
146
|
+
<span v-reveal-truncated :class="classes.boundValue">{{ longDate(start) }}</span>
|
|
141
147
|
</div>
|
|
142
148
|
<div :class="classes.line">
|
|
143
|
-
<
|
|
144
|
-
v-if="duration"
|
|
145
|
-
color="neutral"
|
|
146
|
-
variant="soft"
|
|
147
|
-
size="sm"
|
|
148
|
-
:label="duration"
|
|
149
|
-
:class="classes.duration"
|
|
150
|
-
/>
|
|
149
|
+
<DisplayChip v-if="duration" :chip="{ label: duration }" :class="classes.duration" />
|
|
151
150
|
</div>
|
|
152
151
|
<div :class="[classes.bound, 'text-end']">
|
|
153
152
|
<span :class="classes.boundLabel">{{ t("display.to") }}</span>
|
|
154
|
-
<span :class="classes.boundValue">{{ longDate(finish) }}</span>
|
|
153
|
+
<span v-reveal-truncated :class="classes.boundValue">{{ longDate(finish) }}</span>
|
|
155
154
|
</div>
|
|
156
155
|
</template>
|
|
157
156
|
<template v-else>
|
|
@@ -161,8 +160,14 @@ const classes = computed(
|
|
|
161
160
|
<div :class="classes.weekday">{{ leaf?.weekday }}</div>
|
|
162
161
|
</div>
|
|
163
162
|
<div :class="classes.body">
|
|
164
|
-
<div :class="classes.title"
|
|
165
|
-
|
|
163
|
+
<div v-reveal-truncated :class="classes.title">
|
|
164
|
+
<DisplayRender :content="title ?? longDate(start)" />
|
|
165
|
+
</div>
|
|
166
|
+
<div
|
|
167
|
+
v-if="!isDisplayContentEmpty(description) || timeRange"
|
|
168
|
+
v-reveal-truncated
|
|
169
|
+
:class="classes.description"
|
|
170
|
+
>
|
|
166
171
|
<UIcon v-if="timeRange" :name="icon ?? 'i-lucide-clock'" class="size-3 shrink-0" />
|
|
167
172
|
<span v-if="timeRange">{{ timeRange }}</span>
|
|
168
173
|
<template v-if="timeRange && !isDisplayContentEmpty(description)"> · </template>
|
|
@@ -4,6 +4,7 @@ import { computed } from "vue";
|
|
|
4
4
|
import { useDisplayAppUi } from "../../composables/use-display-config";
|
|
5
5
|
import { useDisplayIcons } from "../../composables/use-display-icons";
|
|
6
6
|
import { useDisplayLocale } from "../../composables/use-display-locale";
|
|
7
|
+
import { vRevealTruncated } from "../../directives/reveal-truncated";
|
|
7
8
|
import { resolveDisplayClasses } from "../../utils/classes";
|
|
8
9
|
import { isDisplayContentEmpty } from "../../utils/content";
|
|
9
10
|
import DisplayChip from "../parts/display-chip.vue";
|
|
@@ -42,6 +43,7 @@ const classes = computed(
|
|
|
42
43
|
arrow: "size-3.5 shrink-0 text-dimmed",
|
|
43
44
|
before: "rounded-[4px] bg-[var(--nut-display-error-soft)] px-1.5 py-px text-[var(--nut-display-error-ink)] line-through decoration-[color-mix(in_oklab,currentColor_45%,transparent)]",
|
|
44
45
|
cell: "border-t border-muted px-3 py-2 align-middle",
|
|
46
|
+
frame: "overflow-hidden rounded-[var(--nut-display-radius)] border border-default",
|
|
45
47
|
headCell: "bg-elevated px-3 py-2 text-start text-[11px] font-bold tracking-[0.07em] text-muted uppercase",
|
|
46
48
|
item: "",
|
|
47
49
|
label: "mb-1 flex items-center gap-2 text-xs text-muted",
|
|
@@ -65,12 +67,12 @@ const classes = computed(
|
|
|
65
67
|
:count="Math.max(items.length, 2)"
|
|
66
68
|
/>
|
|
67
69
|
<div v-else :class="classes.root" data-display="diff" :data-variant="variant">
|
|
68
|
-
<div v-if="!isDisplayContentEmpty(title)" :class="classes.title">
|
|
70
|
+
<div v-if="!isDisplayContentEmpty(title)" v-reveal-truncated :class="classes.title">
|
|
69
71
|
<DisplayRender :content="title" />
|
|
70
72
|
</div>
|
|
71
73
|
<template v-if="variant === 'inline'">
|
|
72
74
|
<div v-for="(item, index) in inlineItems" :key="index" :class="classes.item">
|
|
73
|
-
<div :class="classes.label">
|
|
75
|
+
<div v-reveal-truncated :class="classes.label">
|
|
74
76
|
<DisplayRender :content="item.label" />
|
|
75
77
|
<DisplayChip v-if="item.note" :chip="item.note" :class="classes.note" />
|
|
76
78
|
</div>
|
|
@@ -82,7 +84,10 @@ const classes = computed(
|
|
|
82
84
|
<DisplayRender :content="isDisplayContentEmpty(item.after) ? item.before : item.after" />
|
|
83
85
|
</div>
|
|
84
86
|
<div v-else :class="classes.values">
|
|
85
|
-
<span
|
|
87
|
+
<span
|
|
88
|
+
v-if="!isDisplayContentEmpty(item.before)"
|
|
89
|
+
v-reveal-truncated
|
|
90
|
+
:class="classes.before"
|
|
86
91
|
><DisplayRender :content="item.before"
|
|
87
92
|
/></span>
|
|
88
93
|
<UIcon
|
|
@@ -90,13 +95,13 @@ const classes = computed(
|
|
|
90
95
|
:name="icons.arrowRight"
|
|
91
96
|
:class="classes.arrow"
|
|
92
97
|
/>
|
|
93
|
-
<span v-if="!isDisplayContentEmpty(item.after)" :class="classes.after"
|
|
98
|
+
<span v-if="!isDisplayContentEmpty(item.after)" v-reveal-truncated :class="classes.after"
|
|
94
99
|
><DisplayRender :content="item.after"
|
|
95
100
|
/></span>
|
|
96
101
|
</div>
|
|
97
102
|
</div>
|
|
98
103
|
</template>
|
|
99
|
-
<div v-else class="
|
|
104
|
+
<div v-else :class="classes.frame">
|
|
100
105
|
<table :class="classes.table">
|
|
101
106
|
<thead>
|
|
102
107
|
<tr>
|
|
@@ -104,6 +109,7 @@ const classes = computed(
|
|
|
104
109
|
v-for="(heading, index) in headings"
|
|
105
110
|
:key="index"
|
|
106
111
|
scope="col"
|
|
112
|
+
v-reveal-truncated
|
|
107
113
|
:class="classes.headCell"
|
|
108
114
|
>
|
|
109
115
|
<DisplayRender :content="heading" />
|
|
@@ -117,13 +123,19 @@ const classes = computed(
|
|
|
117
123
|
:class="item.changed === false ? 'text-dimmed' : ''"
|
|
118
124
|
:data-changed="item.changed !== false"
|
|
119
125
|
>
|
|
120
|
-
<td
|
|
126
|
+
<td
|
|
127
|
+
v-reveal-truncated
|
|
128
|
+
:class="[classes.cell, item.changed === false ? '' : 'text-toned']"
|
|
129
|
+
>
|
|
121
130
|
<span class="inline-flex flex-wrap items-center gap-1.5">
|
|
122
131
|
<DisplayRender :content="item.label" />
|
|
123
132
|
<DisplayChip v-if="item.note" :chip="item.note" :class="classes.note" />
|
|
124
133
|
</span>
|
|
125
134
|
</td>
|
|
126
|
-
<td
|
|
135
|
+
<td
|
|
136
|
+
v-reveal-truncated
|
|
137
|
+
:class="[classes.cell, item.changed === false ? '' : 'text-muted']"
|
|
138
|
+
>
|
|
127
139
|
<DisplayRender :content="item.before" />
|
|
128
140
|
</td>
|
|
129
141
|
<td
|
|
@@ -4,6 +4,7 @@ import { computed } from "vue";
|
|
|
4
4
|
import { useDisplayAppUi } from "../../composables/use-display-config";
|
|
5
5
|
import { useDisplayIcons } from "../../composables/use-display-icons";
|
|
6
6
|
import { useDisplayLocale } from "../../composables/use-display-locale";
|
|
7
|
+
import { vRevealTruncated } from "../../directives/reveal-truncated";
|
|
7
8
|
import { resolveDisplayClasses } from "../../utils/classes";
|
|
8
9
|
import { isDisplayContentEmpty } from "../../utils/content";
|
|
9
10
|
import { displayToneClass } from "../../utils/tone";
|
|
@@ -63,10 +64,10 @@ const classes = computed(
|
|
|
63
64
|
>
|
|
64
65
|
<UIcon v-if="variant === 'plain'" :name="icon ?? icons.empty" :class="classes.icon" />
|
|
65
66
|
<span v-else :class="classes.icon"><UIcon :name="icon ?? icons.empty" class="size-5" /></span>
|
|
66
|
-
<div :class="classes.title">
|
|
67
|
+
<div v-reveal-truncated :class="classes.title">
|
|
67
68
|
<DisplayRender :content="title ?? (variant === 'plain' ? void 0 : t('display.empty'))" />
|
|
68
69
|
</div>
|
|
69
|
-
<div v-if="!isDisplayContentEmpty(description)" :class="classes.description">
|
|
70
|
+
<div v-if="!isDisplayContentEmpty(description)" v-reveal-truncated :class="classes.description">
|
|
70
71
|
<DisplayRender :content="description" />
|
|
71
72
|
</div>
|
|
72
73
|
<DisplayActions v-if="actions?.length" :actions="actions" :class="classes.actions" />
|
|
@@ -3,6 +3,7 @@ import UIcon from "@nuxt/ui/components/Icon.vue";
|
|
|
3
3
|
import { twMerge } from "tailwind-merge";
|
|
4
4
|
import { computed } from "vue";
|
|
5
5
|
import { useDisplayAppUi } from "../../composables/use-display-config";
|
|
6
|
+
import { vRevealTruncated } from "../../directives/reveal-truncated";
|
|
6
7
|
import { resolveDisplayClasses } from "../../utils/classes";
|
|
7
8
|
import { isDisplayContentEmpty } from "../../utils/content";
|
|
8
9
|
import {
|
|
@@ -125,40 +126,54 @@ function valueClass(fact) {
|
|
|
125
126
|
>
|
|
126
127
|
<template v-for="(group, groupIndex) in resolvedGroups" :key="groupIndex">
|
|
127
128
|
<div v-if="!isDisplayContentEmpty(group.title)" :class="classes.groupHeader">
|
|
128
|
-
<span :class="classes.groupTitle"
|
|
129
|
-
|
|
129
|
+
<span v-reveal-truncated :class="classes.groupTitle"
|
|
130
|
+
><DisplayRender :content="group.title"
|
|
131
|
+
/></span>
|
|
132
|
+
<span
|
|
133
|
+
v-if="!isDisplayContentEmpty(group.aside)"
|
|
134
|
+
v-reveal-truncated
|
|
135
|
+
:class="classes.groupAside"
|
|
136
|
+
>
|
|
130
137
|
<DisplayRender :content="group.aside" />
|
|
131
138
|
</span>
|
|
132
139
|
</div>
|
|
133
140
|
<div v-for="(fact, index) in group.items" :key="index" :class="classes.item">
|
|
134
141
|
<div class="flex min-w-0 flex-col gap-px">
|
|
135
|
-
<span :class="classes.label">
|
|
142
|
+
<span v-reveal-truncated :class="classes.label">
|
|
136
143
|
<UIcon v-if="fact.icon" :name="fact.icon" class="size-3.5 shrink-0" />
|
|
137
144
|
<DisplayRender :content="fact.label" />
|
|
138
145
|
</span>
|
|
139
|
-
<span v-if="!isDisplayContentEmpty(fact.hint)" :class="classes.hint">
|
|
146
|
+
<span v-if="!isDisplayContentEmpty(fact.hint)" v-reveal-truncated :class="classes.hint">
|
|
140
147
|
<DisplayRender :content="fact.hint" />
|
|
141
148
|
</span>
|
|
142
149
|
</div>
|
|
143
|
-
<div :class="valueClass(fact)" data-display-value
|
|
150
|
+
<div v-reveal-truncated :class="valueClass(fact)" data-display-value>
|
|
151
|
+
<DisplayFactValue :fact="fact" />
|
|
152
|
+
</div>
|
|
144
153
|
</div>
|
|
145
154
|
</template>
|
|
146
155
|
</div>
|
|
147
156
|
<div v-else :class="classes.root" data-display="facts" :data-layout="layout">
|
|
148
157
|
<div v-for="(group, groupIndex) in resolvedGroups" :key="groupIndex">
|
|
149
158
|
<div v-if="!isDisplayContentEmpty(group.title)" :class="classes.groupHeader">
|
|
150
|
-
<span :class="classes.groupTitle"
|
|
151
|
-
|
|
159
|
+
<span v-reveal-truncated :class="classes.groupTitle"
|
|
160
|
+
><DisplayRender :content="group.title"
|
|
161
|
+
/></span>
|
|
162
|
+
<span
|
|
163
|
+
v-if="!isDisplayContentEmpty(group.aside)"
|
|
164
|
+
v-reveal-truncated
|
|
165
|
+
:class="classes.groupAside"
|
|
166
|
+
>
|
|
152
167
|
<DisplayRender :content="group.aside" />
|
|
153
168
|
</span>
|
|
154
169
|
</div>
|
|
155
170
|
<dl :class="['m-0', classes.group]" :style="groupStyle">
|
|
156
171
|
<div v-for="(fact, index) in group.items" :key="index" :class="classes.item">
|
|
157
|
-
<dt :class="classes.label">
|
|
172
|
+
<dt v-reveal-truncated :class="classes.label">
|
|
158
173
|
<UIcon v-if="fact.icon" :name="fact.icon" class="size-3.5 shrink-0" />
|
|
159
174
|
<DisplayRender :content="fact.label" />
|
|
160
175
|
</dt>
|
|
161
|
-
<dd :class="['m-0', valueClass(fact)]" data-display-value>
|
|
176
|
+
<dd v-reveal-truncated :class="['m-0', valueClass(fact)]" data-display-value>
|
|
162
177
|
<DisplayFactValue :fact="fact" />
|
|
163
178
|
</dd>
|
|
164
179
|
<dd
|
|
@@ -3,8 +3,10 @@ import UButton from "@nuxt/ui/components/Button.vue";
|
|
|
3
3
|
import UIcon from "@nuxt/ui/components/Icon.vue";
|
|
4
4
|
import { computed } from "vue";
|
|
5
5
|
import { useDisplayAppUi } from "../../composables/use-display-config";
|
|
6
|
+
import { vRevealTruncated } from "../../directives/reveal-truncated";
|
|
6
7
|
import { resolveDisplayClasses } from "../../utils/classes";
|
|
7
8
|
import { isDisplayContentEmpty, resolveDisplayText } from "../../utils/content";
|
|
9
|
+
import { isExternalLink } from "../../utils/links";
|
|
8
10
|
import { displayToneClass } from "../../utils/tone";
|
|
9
11
|
import DisplayRender from "../parts/display-render";
|
|
10
12
|
import DisplaySkeleton from "../parts/display-skeleton.vue";
|
|
@@ -64,7 +66,8 @@ const actionButton = computed(() => {
|
|
|
64
66
|
size: "sm",
|
|
65
67
|
variant: "link",
|
|
66
68
|
...rest,
|
|
67
|
-
label: resolveDisplayText(label)
|
|
69
|
+
label: resolveDisplayText(label),
|
|
70
|
+
target: rest.target === void 0 && isExternalLink(rest.to) ? "_blank" : rest.target
|
|
68
71
|
};
|
|
69
72
|
});
|
|
70
73
|
</script>
|
|
@@ -80,14 +83,18 @@ const actionButton = computed(() => {
|
|
|
80
83
|
<div v-else :class="[classes.root, displayToneClass(tone)]" data-display="heading">
|
|
81
84
|
<span v-if="tile" :class="classes.icon"><UIcon :name="icon ?? ''" class="size-5" /></span>
|
|
82
85
|
<UIcon v-else-if="icon" :name="icon" :class="classes.icon" />
|
|
83
|
-
<div :class="classes.text">
|
|
86
|
+
<div v-reveal-truncated :class="classes.text">
|
|
84
87
|
<component :is="`h${level}`" :class="classes.title">
|
|
85
88
|
<DisplayRender :content="title" />
|
|
86
89
|
<span v-if="count !== void 0" :class="classes.count">{{
|
|
87
90
|
resolveDisplayText(count)
|
|
88
91
|
}}</span>
|
|
89
92
|
</component>
|
|
90
|
-
<div
|
|
93
|
+
<div
|
|
94
|
+
v-if="!isDisplayContentEmpty(description)"
|
|
95
|
+
v-reveal-truncated
|
|
96
|
+
:class="classes.description"
|
|
97
|
+
>
|
|
91
98
|
<DisplayRender :content="description" />
|
|
92
99
|
</div>
|
|
93
100
|
</div>
|
|
@@ -10,6 +10,7 @@ import { useDisplayIcons } from "../../composables/use-display-icons";
|
|
|
10
10
|
import { useDisplayLocale } from "../../composables/use-display-locale";
|
|
11
11
|
import { useDisplayReveal } from "../../composables/use-display-reveal";
|
|
12
12
|
import { useDisplayUrlActions } from "../../composables/use-display-url";
|
|
13
|
+
import { vRevealTruncated } from "../../directives/reveal-truncated";
|
|
13
14
|
import { resolveDisplayClasses } from "../../utils/classes";
|
|
14
15
|
import { displayContentText, isDisplayContentEmpty, resolveDisplayText } from "../../utils/content";
|
|
15
16
|
import { displayToneClass } from "../../utils/tone";
|
|
@@ -160,7 +161,7 @@ function downloadFile(index) {
|
|
|
160
161
|
<template>
|
|
161
162
|
<DisplaySkeleton v-if="loading" :count="Math.min(Math.max(items.length, 2), 5)" />
|
|
162
163
|
<div v-else :class="classes.root" data-display="list" :data-variant="variant">
|
|
163
|
-
<div v-if="!isDisplayContentEmpty(title)" :class="classes.title">
|
|
164
|
+
<div v-if="!isDisplayContentEmpty(title)" v-reveal-truncated :class="classes.title">
|
|
164
165
|
<DisplayRender :content="title" />
|
|
165
166
|
</div>
|
|
166
167
|
<DisplayEmptyLine v-if="!items.length" :content="empty" :class="classes.empty" />
|
|
@@ -193,7 +194,7 @@ function downloadFile(index) {
|
|
|
193
194
|
{{ files[index]?.label }}
|
|
194
195
|
</span>
|
|
195
196
|
<div class="min-w-0 flex-1">
|
|
196
|
-
<div :class="classes.text">
|
|
197
|
+
<div v-reveal-truncated :class="classes.text">
|
|
197
198
|
<a
|
|
198
199
|
v-if="item.href"
|
|
199
200
|
:href="isString(item.href) ? item.href : '#'"
|
|
@@ -209,6 +210,7 @@ function downloadFile(index) {
|
|
|
209
210
|
</div>
|
|
210
211
|
<div
|
|
211
212
|
v-if="files[index]?.size || !isDisplayContentEmpty(item.description)"
|
|
213
|
+
v-reveal-truncated
|
|
212
214
|
:class="classes.description"
|
|
213
215
|
>
|
|
214
216
|
{{ files[index]?.size
|
|
@@ -274,11 +276,15 @@ function downloadFile(index) {
|
|
|
274
276
|
>
|
|
275
277
|
<DisplayRender :content="item.text" />
|
|
276
278
|
</div>
|
|
277
|
-
<div
|
|
279
|
+
<div
|
|
280
|
+
v-if="!isDisplayContentEmpty(item.description)"
|
|
281
|
+
v-reveal-truncated
|
|
282
|
+
:class="classes.description"
|
|
283
|
+
>
|
|
278
284
|
<DisplayRender :content="item.description" />
|
|
279
285
|
</div>
|
|
280
286
|
</div>
|
|
281
|
-
<span v-if="!isDisplayContentEmpty(item.meta)" :class="classes.meta"
|
|
287
|
+
<span v-if="!isDisplayContentEmpty(item.meta)" v-reveal-truncated :class="classes.meta"
|
|
282
288
|
><DisplayRender :content="item.meta"
|
|
283
289
|
/></span>
|
|
284
290
|
</template>
|
|
@@ -8,6 +8,7 @@ import { useDisplayAppUi } from "../../composables/use-display-config";
|
|
|
8
8
|
import { useDisplayFilePreview } from "../../composables/use-display-file-preview";
|
|
9
9
|
import { useDisplayLocale } from "../../composables/use-display-locale";
|
|
10
10
|
import { useDisplayUrlActions, useResolvedDisplayUrl } from "../../composables/use-display-url";
|
|
11
|
+
import { vRevealTruncated } from "../../directives/reveal-truncated";
|
|
11
12
|
import { resolveDisplayClasses } from "../../utils/classes";
|
|
12
13
|
import { isDisplayContentEmpty, resolveDisplayText } from "../../utils/content";
|
|
13
14
|
import { downloadDisplayUrl, openDisplayUrl } from "../../utils/urls";
|
|
@@ -181,7 +182,7 @@ function openLink() {
|
|
|
181
182
|
/>
|
|
182
183
|
<span v-else-if="shown.pending.value" class="nut-dash-shimmer absolute inset-0" />
|
|
183
184
|
</component>
|
|
184
|
-
<figcaption v-if="!isDisplayContentEmpty(caption)" :class="classes.caption">
|
|
185
|
+
<figcaption v-if="!isDisplayContentEmpty(caption)" v-reveal-truncated :class="classes.caption">
|
|
185
186
|
<DisplayRender :content="caption" />
|
|
186
187
|
</figcaption>
|
|
187
188
|
</figure>
|
|
@@ -208,7 +209,7 @@ function openLink() {
|
|
|
208
209
|
>
|
|
209
210
|
</button>
|
|
210
211
|
</div>
|
|
211
|
-
<figcaption v-if="!isDisplayContentEmpty(caption)" :class="classes.caption">
|
|
212
|
+
<figcaption v-if="!isDisplayContentEmpty(caption)" v-reveal-truncated :class="classes.caption">
|
|
212
213
|
<DisplayRender :content="caption" />
|
|
213
214
|
</figcaption>
|
|
214
215
|
</figure>
|
|
@@ -242,6 +243,7 @@ function openLink() {
|
|
|
242
243
|
/></span>
|
|
243
244
|
<span
|
|
244
245
|
v-if="!isDisplayContentEmpty(title)"
|
|
246
|
+
v-reveal-truncated
|
|
245
247
|
:class="[classes.title, 'absolute start-3 bottom-2 text-white']"
|
|
246
248
|
>
|
|
247
249
|
<DisplayRender :content="title" />
|
|
@@ -251,7 +253,7 @@ function openLink() {
|
|
|
251
253
|
}}</span>
|
|
252
254
|
</button>
|
|
253
255
|
</div>
|
|
254
|
-
<figcaption v-if="!isDisplayContentEmpty(caption)" :class="classes.caption">
|
|
256
|
+
<figcaption v-if="!isDisplayContentEmpty(caption)" v-reveal-truncated :class="classes.caption">
|
|
255
257
|
<DisplayRender :content="caption" />
|
|
256
258
|
</figcaption>
|
|
257
259
|
</figure>
|
|
@@ -277,9 +279,13 @@ function openLink() {
|
|
|
277
279
|
/>
|
|
278
280
|
</div>
|
|
279
281
|
<div :class="classes.body">
|
|
280
|
-
<div :class="classes.name">{{ fileName }}</div>
|
|
281
|
-
<div v-if="documentMeta" :class="classes.meta">{{ documentMeta }}</div>
|
|
282
|
-
<div
|
|
282
|
+
<div v-reveal-truncated :class="classes.name">{{ fileName }}</div>
|
|
283
|
+
<div v-if="documentMeta" v-reveal-truncated :class="classes.meta">{{ documentMeta }}</div>
|
|
284
|
+
<div
|
|
285
|
+
v-if="!isDisplayContentEmpty(description)"
|
|
286
|
+
v-reveal-truncated
|
|
287
|
+
:class="classes.description"
|
|
288
|
+
>
|
|
283
289
|
<DisplayRender :content="description" />
|
|
284
290
|
</div>
|
|
285
291
|
<DisplayActions
|
|
@@ -301,10 +307,10 @@ function openLink() {
|
|
|
301
307
|
@click="isString(href) ? void 0 : openLink()"
|
|
302
308
|
>
|
|
303
309
|
<div :class="[classes.body, 'px-3 py-2.5']">
|
|
304
|
-
<div v-if="domain" :class="classes.domain">
|
|
310
|
+
<div v-if="domain" v-reveal-truncated :class="classes.domain">
|
|
305
311
|
<UIcon name="i-lucide-globe" class="size-3.5 shrink-0" />{{ domain }}
|
|
306
312
|
</div>
|
|
307
|
-
<div :class="[classes.title, 'mt-0.5 flex items-center gap-1.5']">
|
|
313
|
+
<div v-reveal-truncated :class="[classes.title, 'mt-0.5 flex items-center gap-1.5']">
|
|
308
314
|
<DisplayRender :content="title ?? (isString(href) ? href : void 0)" />
|
|
309
315
|
<UIcon
|
|
310
316
|
v-if="links.pending.value === 'open'"
|
|
@@ -312,7 +318,11 @@ function openLink() {
|
|
|
312
318
|
class="size-3.5 shrink-0 animate-spin text-muted"
|
|
313
319
|
/>
|
|
314
320
|
</div>
|
|
315
|
-
<div
|
|
321
|
+
<div
|
|
322
|
+
v-if="!isDisplayContentEmpty(description)"
|
|
323
|
+
v-reveal-truncated
|
|
324
|
+
:class="classes.description"
|
|
325
|
+
>
|
|
316
326
|
<DisplayRender :content="description" />
|
|
317
327
|
</div>
|
|
318
328
|
</div>
|