nuxt-ui-tools 1.24.0 → 1.25.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.
Files changed (206) hide show
  1. package/dist/module.d.mts +3 -0
  2. package/dist/module.json +1 -1
  3. package/dist/module.mjs +8 -0
  4. package/dist/runtime/display/components/blocks/display-accordion.d.vue.ts +4 -0
  5. package/dist/runtime/display/components/blocks/display-accordion.vue +93 -0
  6. package/dist/runtime/display/components/blocks/display-accordion.vue.d.ts +4 -0
  7. package/dist/runtime/display/components/blocks/display-alert.d.vue.ts +4 -0
  8. package/dist/runtime/display/components/blocks/display-alert.vue +133 -0
  9. package/dist/runtime/display/components/blocks/display-alert.vue.d.ts +4 -0
  10. package/dist/runtime/display/components/blocks/display-breakdown.d.vue.ts +4 -0
  11. package/dist/runtime/display/components/blocks/display-breakdown.vue +178 -0
  12. package/dist/runtime/display/components/blocks/display-breakdown.vue.d.ts +4 -0
  13. package/dist/runtime/display/components/blocks/display-chart.d.vue.ts +4 -0
  14. package/dist/runtime/display/components/blocks/display-chart.vue +237 -0
  15. package/dist/runtime/display/components/blocks/display-chart.vue.d.ts +4 -0
  16. package/dist/runtime/display/components/blocks/display-code.d.vue.ts +4 -0
  17. package/dist/runtime/display/components/blocks/display-code.vue +143 -0
  18. package/dist/runtime/display/components/blocks/display-code.vue.d.ts +4 -0
  19. package/dist/runtime/display/components/blocks/display-date.d.vue.ts +4 -0
  20. package/dist/runtime/display/components/blocks/display-date.vue +174 -0
  21. package/dist/runtime/display/components/blocks/display-date.vue.d.ts +4 -0
  22. package/dist/runtime/display/components/blocks/display-diff.d.vue.ts +4 -0
  23. package/dist/runtime/display/components/blocks/display-diff.vue +142 -0
  24. package/dist/runtime/display/components/blocks/display-diff.vue.d.ts +4 -0
  25. package/dist/runtime/display/components/blocks/display-empty.d.vue.ts +4 -0
  26. package/dist/runtime/display/components/blocks/display-empty.vue +74 -0
  27. package/dist/runtime/display/components/blocks/display-empty.vue.d.ts +4 -0
  28. package/dist/runtime/display/components/blocks/display-facts.d.vue.ts +4 -0
  29. package/dist/runtime/display/components/blocks/display-facts.vue +180 -0
  30. package/dist/runtime/display/components/blocks/display-facts.vue.d.ts +4 -0
  31. package/dist/runtime/display/components/blocks/display-heading.d.vue.ts +4 -0
  32. package/dist/runtime/display/components/blocks/display-heading.vue +96 -0
  33. package/dist/runtime/display/components/blocks/display-heading.vue.d.ts +4 -0
  34. package/dist/runtime/display/components/blocks/display-list.d.vue.ts +4 -0
  35. package/dist/runtime/display/components/blocks/display-list.vue +295 -0
  36. package/dist/runtime/display/components/blocks/display-list.vue.d.ts +4 -0
  37. package/dist/runtime/display/components/blocks/display-media.d.vue.ts +4 -0
  38. package/dist/runtime/display/components/blocks/display-media.vue +326 -0
  39. package/dist/runtime/display/components/blocks/display-media.vue.d.ts +4 -0
  40. package/dist/runtime/display/components/blocks/display-meter.d.vue.ts +4 -0
  41. package/dist/runtime/display/components/blocks/display-meter.vue +301 -0
  42. package/dist/runtime/display/components/blocks/display-meter.vue.d.ts +4 -0
  43. package/dist/runtime/display/components/blocks/display-person.d.vue.ts +4 -0
  44. package/dist/runtime/display/components/blocks/display-person.vue +146 -0
  45. package/dist/runtime/display/components/blocks/display-person.vue.d.ts +4 -0
  46. package/dist/runtime/display/components/blocks/display-record.d.vue.ts +4 -0
  47. package/dist/runtime/display/components/blocks/display-record.vue +208 -0
  48. package/dist/runtime/display/components/blocks/display-record.vue.d.ts +4 -0
  49. package/dist/runtime/display/components/blocks/display-stat.d.vue.ts +4 -0
  50. package/dist/runtime/display/components/blocks/display-stat.vue +178 -0
  51. package/dist/runtime/display/components/blocks/display-stat.vue.d.ts +4 -0
  52. package/dist/runtime/display/components/blocks/display-table.d.vue.ts +4 -0
  53. package/dist/runtime/display/components/blocks/display-table.vue +132 -0
  54. package/dist/runtime/display/components/blocks/display-table.vue.d.ts +4 -0
  55. package/dist/runtime/display/components/blocks/display-text.d.vue.ts +4 -0
  56. package/dist/runtime/display/components/blocks/display-text.vue +135 -0
  57. package/dist/runtime/display/components/blocks/display-text.vue.d.ts +4 -0
  58. package/dist/runtime/display/components/blocks/display-timeline.d.vue.ts +4 -0
  59. package/dist/runtime/display/components/blocks/display-timeline.vue +232 -0
  60. package/dist/runtime/display/components/blocks/display-timeline.vue.d.ts +4 -0
  61. package/dist/runtime/display/components/display.d.vue.ts +24 -0
  62. package/dist/runtime/display/components/display.vue +21 -0
  63. package/dist/runtime/display/components/display.vue.d.ts +24 -0
  64. package/dist/runtime/display/components/parts/display-actions.d.vue.ts +9 -0
  65. package/dist/runtime/display/components/parts/display-actions.vue +24 -0
  66. package/dist/runtime/display/components/parts/display-actions.vue.d.ts +9 -0
  67. package/dist/runtime/display/components/parts/display-chip.d.vue.ts +11 -0
  68. package/dist/runtime/display/components/parts/display-chip.vue +45 -0
  69. package/dist/runtime/display/components/parts/display-chip.vue.d.ts +11 -0
  70. package/dist/runtime/display/components/parts/display-copy.d.vue.ts +6 -0
  71. package/dist/runtime/display/components/parts/display-copy.vue +27 -0
  72. package/dist/runtime/display/components/parts/display-copy.vue.d.ts +6 -0
  73. package/dist/runtime/display/components/parts/display-empty-line.d.vue.ts +7 -0
  74. package/dist/runtime/display/components/parts/display-empty-line.vue +21 -0
  75. package/dist/runtime/display/components/parts/display-empty-line.vue.d.ts +7 -0
  76. package/dist/runtime/display/components/parts/display-fact-value.d.vue.ts +7 -0
  77. package/dist/runtime/display/components/parts/display-fact-value.vue +35 -0
  78. package/dist/runtime/display/components/parts/display-fact-value.vue.d.ts +7 -0
  79. package/dist/runtime/display/components/parts/display-load-error.d.vue.ts +7 -0
  80. package/dist/runtime/display/components/parts/display-load-error.vue +29 -0
  81. package/dist/runtime/display/components/parts/display-load-error.vue.d.ts +7 -0
  82. package/dist/runtime/display/components/parts/display-more.d.vue.ts +10 -0
  83. package/dist/runtime/display/components/parts/display-more.vue +23 -0
  84. package/dist/runtime/display/components/parts/display-more.vue.d.ts +10 -0
  85. package/dist/runtime/display/components/parts/display-record-media.d.vue.ts +9 -0
  86. package/dist/runtime/display/components/parts/display-record-media.vue +59 -0
  87. package/dist/runtime/display/components/parts/display-record-media.vue.d.ts +9 -0
  88. package/dist/runtime/display/components/parts/display-render.d.ts +10 -0
  89. package/dist/runtime/display/components/parts/display-render.js +5 -0
  90. package/dist/runtime/display/components/parts/display-skeleton.d.vue.ts +7 -0
  91. package/dist/runtime/display/components/parts/display-skeleton.vue +67 -0
  92. package/dist/runtime/display/components/parts/display-skeleton.vue.d.ts +7 -0
  93. package/dist/runtime/display/composables/use-display-config.d.ts +6 -0
  94. package/dist/runtime/display/composables/use-display-config.js +11 -0
  95. package/dist/runtime/display/composables/use-display-file-preview.d.ts +9 -0
  96. package/dist/runtime/display/composables/use-display-file-preview.js +11 -0
  97. package/dist/runtime/display/composables/use-display-icons.d.ts +8 -0
  98. package/dist/runtime/display/composables/use-display-icons.js +62 -0
  99. package/dist/runtime/display/composables/use-display-locale.d.ts +5 -0
  100. package/dist/runtime/display/composables/use-display-locale.js +5 -0
  101. package/dist/runtime/display/composables/use-display-number.d.ts +2 -0
  102. package/dist/runtime/display/composables/use-display-number.js +7 -0
  103. package/dist/runtime/display/composables/use-display-reveal.d.ts +14 -0
  104. package/dist/runtime/display/composables/use-display-reveal.js +15 -0
  105. package/dist/runtime/display/composables/use-display-url.d.ts +26 -0
  106. package/dist/runtime/display/composables/use-display-url.js +46 -0
  107. package/dist/runtime/display/index.d.ts +4 -0
  108. package/dist/runtime/display/index.js +3 -0
  109. package/dist/runtime/display/plugins/display-tones.d.ts +3 -0
  110. package/dist/runtime/display/plugins/display-tones.js +17 -0
  111. package/dist/runtime/display/types/blocks/accordion.d.ts +18 -0
  112. package/dist/runtime/display/types/blocks/accordion.js +0 -0
  113. package/dist/runtime/display/types/blocks/alert.d.ts +31 -0
  114. package/dist/runtime/display/types/blocks/alert.js +0 -0
  115. package/dist/runtime/display/types/blocks/breakdown.d.ts +36 -0
  116. package/dist/runtime/display/types/blocks/breakdown.js +0 -0
  117. package/dist/runtime/display/types/blocks/chart.d.ts +23 -0
  118. package/dist/runtime/display/types/blocks/chart.js +0 -0
  119. package/dist/runtime/display/types/blocks/code.d.ts +21 -0
  120. package/dist/runtime/display/types/blocks/code.js +0 -0
  121. package/dist/runtime/display/types/blocks/date.d.ts +27 -0
  122. package/dist/runtime/display/types/blocks/date.js +0 -0
  123. package/dist/runtime/display/types/blocks/diff.d.ts +20 -0
  124. package/dist/runtime/display/types/blocks/diff.js +0 -0
  125. package/dist/runtime/display/types/blocks/empty.d.ts +13 -0
  126. package/dist/runtime/display/types/blocks/empty.js +0 -0
  127. package/dist/runtime/display/types/blocks/facts.d.ts +50 -0
  128. package/dist/runtime/display/types/blocks/facts.js +0 -0
  129. package/dist/runtime/display/types/blocks/heading.d.ts +19 -0
  130. package/dist/runtime/display/types/blocks/heading.js +0 -0
  131. package/dist/runtime/display/types/blocks/list.d.ts +36 -0
  132. package/dist/runtime/display/types/blocks/list.js +0 -0
  133. package/dist/runtime/display/types/blocks/media.d.ts +42 -0
  134. package/dist/runtime/display/types/blocks/media.js +0 -0
  135. package/dist/runtime/display/types/blocks/meter.d.ts +48 -0
  136. package/dist/runtime/display/types/blocks/meter.js +0 -0
  137. package/dist/runtime/display/types/blocks/person.d.ts +32 -0
  138. package/dist/runtime/display/types/blocks/person.js +0 -0
  139. package/dist/runtime/display/types/blocks/record.d.ts +42 -0
  140. package/dist/runtime/display/types/blocks/record.js +0 -0
  141. package/dist/runtime/display/types/blocks/stat.d.ts +44 -0
  142. package/dist/runtime/display/types/blocks/stat.js +0 -0
  143. package/dist/runtime/display/types/blocks/table.d.ts +28 -0
  144. package/dist/runtime/display/types/blocks/table.js +0 -0
  145. package/dist/runtime/display/types/blocks/text.d.ts +22 -0
  146. package/dist/runtime/display/types/blocks/text.js +0 -0
  147. package/dist/runtime/display/types/blocks/timeline.d.ts +37 -0
  148. package/dist/runtime/display/types/blocks/timeline.js +0 -0
  149. package/dist/runtime/display/types/config.d.ts +53 -0
  150. package/dist/runtime/display/types/config.js +0 -0
  151. package/dist/runtime/display/types/index.d.ts +22 -0
  152. package/dist/runtime/display/types/index.js +0 -0
  153. package/dist/runtime/display/types/registry.d.ts +57 -0
  154. package/dist/runtime/display/types/registry.js +0 -0
  155. package/dist/runtime/display/types/shared.d.ts +71 -0
  156. package/dist/runtime/display/types/shared.js +0 -0
  157. package/dist/runtime/display/utils/classes.d.ts +3 -0
  158. package/dist/runtime/display/utils/classes.js +7 -0
  159. package/dist/runtime/display/utils/config.d.ts +6 -0
  160. package/dist/runtime/display/utils/config.js +7 -0
  161. package/dist/runtime/display/utils/content.d.ts +7 -0
  162. package/dist/runtime/display/utils/content.js +13 -0
  163. package/dist/runtime/display/utils/dates.d.ts +16 -0
  164. package/dist/runtime/display/utils/dates.js +34 -0
  165. package/dist/runtime/display/utils/json.d.ts +7 -0
  166. package/dist/runtime/display/utils/json.js +15 -0
  167. package/dist/runtime/display/utils/meter.d.ts +7 -0
  168. package/dist/runtime/display/utils/meter.js +13 -0
  169. package/dist/runtime/display/utils/registry.d.ts +47 -0
  170. package/dist/runtime/display/utils/registry.js +64 -0
  171. package/dist/runtime/display/utils/tone-css.d.ts +7 -0
  172. package/dist/runtime/display/utils/tone-css.js +38 -0
  173. package/dist/runtime/display/utils/tone.d.ts +26 -0
  174. package/dist/runtime/display/utils/tone.js +38 -0
  175. package/dist/runtime/display/utils/urls.d.ts +10 -0
  176. package/dist/runtime/display/utils/urls.js +33 -0
  177. package/dist/runtime/file-preview/components/shell/file-preview-stage.vue +5 -3
  178. package/dist/runtime/file-preview/composables/use-file-preview-source.d.ts +7 -0
  179. package/dist/runtime/file-preview/composables/use-file-preview-source.js +7 -1
  180. package/dist/runtime/file-preview/index.d.ts +1 -0
  181. package/dist/runtime/file-preview/index.js +1 -0
  182. package/dist/runtime/file-preview/types/file.d.ts +9 -0
  183. package/dist/runtime/file-preview/utils/errors.d.ts +30 -0
  184. package/dist/runtime/file-preview/utils/errors.js +26 -0
  185. package/dist/runtime/form/components/utils/form-file-preview.vue +7 -2
  186. package/dist/runtime/form/composables/use-form-root.js +2 -0
  187. package/dist/runtime/form/composables/use-form-runtime.js +7 -2
  188. package/dist/runtime/form/fields/index.d.ts +5 -0
  189. package/dist/runtime/form/fields/info/component.vue +51 -19
  190. package/dist/runtime/form/fields/info/config.d.ts +5 -0
  191. package/dist/runtime/form/fields/info/config.js +2 -1
  192. package/dist/runtime/form/fields/info/types.d.ts +78 -4
  193. package/dist/runtime/form/fields/info/use-info-display.d.ts +20 -0
  194. package/dist/runtime/form/fields/info/use-info-display.js +82 -0
  195. package/dist/runtime/form/fields/upload/upload-item.vue +10 -2
  196. package/dist/runtime/form/types/api.d.ts +6 -0
  197. package/dist/runtime/form/types/runtime.d.ts +2 -0
  198. package/dist/runtime/form/utils/dynamic.d.ts +6 -0
  199. package/dist/runtime/form/utils/dynamic.js +7 -0
  200. package/dist/runtime/i18n/locales/en.js +27 -0
  201. package/dist/runtime/i18n/locales/fr.js +27 -0
  202. package/dist/runtime/i18n/types.d.ts +35 -0
  203. package/dist/runtime/shared/styles/tokens.css +1 -1
  204. package/dist/runtime/shared/utils/file.d.ts +1 -1
  205. package/dist/runtime/table/utils/data-list-ui.d.ts +1 -1
  206. package/package.json +16 -1
@@ -0,0 +1,237 @@
1
+ <script setup>
2
+ import { computed } from "vue";
3
+ import { useDisplayAppUi } from "../../composables/use-display-config";
4
+ import { useDisplayNumber } from "../../composables/use-display-number";
5
+ import { resolveDisplayClasses } from "../../utils/classes";
6
+ import { isDisplayContentEmpty, resolveDisplayText } from "../../utils/content";
7
+ import DisplayEmptyLine from "../parts/display-empty-line.vue";
8
+ import DisplayRender from "../parts/display-render";
9
+ import DisplaySkeleton from "../parts/display-skeleton.vue";
10
+ const {
11
+ variant = "bars",
12
+ title = void 0,
13
+ aside = void 0,
14
+ data,
15
+ format = void 0,
16
+ height = 96,
17
+ highlight = "last",
18
+ empty = void 0,
19
+ loading = false,
20
+ ui = void 0
21
+ } = defineProps({
22
+ variant: { type: String, required: false },
23
+ title: { type: [String, Number, Function, Object, Boolean, null, Array], required: false, skipCheck: true },
24
+ aside: { type: [String, Number, Function, Object, Boolean, null, Array], required: false, skipCheck: true },
25
+ data: { type: Array, required: true },
26
+ format: { type: Function, required: false },
27
+ height: { type: Number, required: false },
28
+ highlight: { type: [String, Number, Boolean], required: false },
29
+ empty: { type: [String, Number, Function, Object, Boolean, null, Array], required: false, skipCheck: true },
30
+ loading: { type: Boolean, required: false },
31
+ ui: { type: Object, required: false }
32
+ });
33
+ const SERIES = [
34
+ "var(--nut-dash-s1)",
35
+ "var(--nut-dash-s2)",
36
+ "var(--nut-dash-s3)",
37
+ "var(--nut-dash-s4)",
38
+ "var(--nut-dash-s5)",
39
+ "var(--nut-dash-s6)"
40
+ ];
41
+ const formatNumber = useDisplayNumber();
42
+ const appUi = useDisplayAppUi("chart");
43
+ const formatValue = (value) => format ? format(value) : formatNumber(value);
44
+ const maxValue = computed(() => Math.max(0, ...data.map((datum) => datum.value)));
45
+ const total = computed(() => data.reduce((sum, datum) => sum + Math.max(0, datum.value), 0));
46
+ const highlighted = computed(() => {
47
+ if (highlight === false) return -1;
48
+ if (highlight === "last") return data.length - 1;
49
+ if (highlight === "max") return data.findIndex((datum) => datum.value === maxValue.value);
50
+ return highlight;
51
+ });
52
+ const line = computed(() => {
53
+ if (data.length < 2) return void 0;
54
+ const min = Math.min(...data.map((datum) => datum.value));
55
+ const span = maxValue.value - min || 1;
56
+ const points = data.map((datum, index) => {
57
+ const x = index / (data.length - 1) * 300;
58
+ const y = 92 - (datum.value - min) / span * 80;
59
+ return `${x.toFixed(1)} ${y.toFixed(1)}`;
60
+ });
61
+ return { area: `M${points.join(" L")} L300 100 L0 100 Z`, path: `M${points.join(" L")}` };
62
+ });
63
+ const slices = computed(() => {
64
+ let offset = 25;
65
+ return data.map((datum, index) => {
66
+ const share = total.value ? Math.max(0, datum.value) / total.value * 100 : 0;
67
+ const slice = { color: colorOf(datum, index), dash: `${share} ${100 - share}`, offset, share };
68
+ offset = (offset - share + 100) % 100;
69
+ return slice;
70
+ });
71
+ });
72
+ const steps = computed(() => {
73
+ const first = data[0]?.value ?? 0;
74
+ return data.map((datum, index) => {
75
+ const previous = data[index - 1]?.value;
76
+ return {
77
+ ...datum,
78
+ rate: previous ? Math.round(datum.value / previous * 100) : void 0,
79
+ width: first ? datum.value / first * 100 : 0
80
+ };
81
+ });
82
+ });
83
+ const classes = computed(
84
+ () => resolveDisplayClasses(
85
+ {
86
+ aside: "text-xs text-dimmed",
87
+ axis: "mt-1.5 flex gap-2 text-[10.5px] text-dimmed",
88
+ bar: "relative min-h-px flex-1 rounded-t-[3px] bg-[var(--nut-dash-muted)] transition-[height] duration-300",
89
+ header: "flex items-baseline justify-between gap-3 text-sm",
90
+ legend: "flex flex-col gap-1.5 text-xs text-muted",
91
+ legendItem: "inline-flex items-center gap-1.5",
92
+ plot: "mt-3",
93
+ root: "min-w-0",
94
+ step: "grid grid-cols-[minmax(4rem,7rem)_minmax(0,1fr)_auto_2.75rem] items-center gap-2 text-xs",
95
+ stepLabel: "truncate text-muted",
96
+ stepRate: "text-end text-[11px] text-dimmed tabular-nums",
97
+ stepValue: "text-end font-semibold text-highlighted tabular-nums",
98
+ title: "font-semibold text-toned"
99
+ },
100
+ appUi.value,
101
+ ui
102
+ )
103
+ );
104
+ function colorOf(datum, index) {
105
+ return datum.tone ? `var(--nut-display-${datum.tone})` : SERIES[index % SERIES.length] ?? SERIES[0];
106
+ }
107
+ </script>
108
+
109
+ <template>
110
+ <DisplaySkeleton v-if="loading" layout="block" />
111
+ <div v-else :class="classes.root" data-display="chart" :data-variant="variant">
112
+ <div
113
+ v-if="!isDisplayContentEmpty(title) || !isDisplayContentEmpty(aside)"
114
+ :class="classes.header"
115
+ >
116
+ <span :class="classes.title"><DisplayRender :content="title" /></span>
117
+ <span :class="classes.aside"><DisplayRender :content="aside" /></span>
118
+ </div>
119
+ <DisplayEmptyLine v-if="!data.length" :content="empty" :class="classes.plot" />
120
+ <div v-else-if="variant === 'bars'" :class="classes.plot">
121
+ <div
122
+ class="flex items-end gap-2 border-b border-default pt-5"
123
+ :style="{ height: `${height + 20}px` }"
124
+ >
125
+ <div
126
+ v-for="(datum, index) in data"
127
+ :key="index"
128
+ :class="classes.bar"
129
+ :style="{
130
+ height: `${maxValue ? datum.value / maxValue * height : 0}px`,
131
+ background: index === highlighted ? 'var(--nut-dash-s1)' : datum.tone ? `var(--nut-display-${datum.tone})` : void 0
132
+ }"
133
+ :title="`${resolveDisplayText(datum.label)} : ${formatValue(datum.value)}`"
134
+ :data-highlighted="index === highlighted || void 0"
135
+ >
136
+ <span
137
+ v-if="index === highlighted"
138
+ class="absolute -top-4.5 left-1/2 -translate-x-1/2 text-[11px] font-bold whitespace-nowrap text-highlighted tabular-nums"
139
+ >
140
+ {{ formatValue(datum.value) }}
141
+ </span>
142
+ </div>
143
+ </div>
144
+ <div :class="classes.axis">
145
+ <span
146
+ v-for="(datum, index) in data"
147
+ :key="index"
148
+ class="min-w-0 flex-1 truncate text-center"
149
+ >
150
+ {{ resolveDisplayText(datum.label) }}
151
+ </span>
152
+ </div>
153
+ </div>
154
+ <div v-else-if="variant === 'line' && line" :class="classes.plot">
155
+ <svg
156
+ viewBox="0 0 300 100"
157
+ preserveAspectRatio="none"
158
+ class="w-full"
159
+ :style="{ height: `${height}px` }"
160
+ role="img"
161
+ >
162
+ <path
163
+ d="M0 25H300M0 50H300M0 75H300"
164
+ stroke="var(--nut-dash-grid)"
165
+ stroke-width="1"
166
+ vector-effect="non-scaling-stroke"
167
+ />
168
+ <path :d="line.area" fill="var(--nut-dash-s1)" fill-opacity="0.14" />
169
+ <path
170
+ :d="line.path"
171
+ fill="none"
172
+ stroke="var(--nut-dash-s1)"
173
+ stroke-width="2"
174
+ stroke-linejoin="round"
175
+ vector-effect="non-scaling-stroke"
176
+ />
177
+ </svg>
178
+ <div :class="[classes.axis, 'justify-between']">
179
+ <span
180
+ >{{ resolveDisplayText(data[0]?.label) }} · {{ formatValue(data[0]?.value ?? 0) }}</span
181
+ >
182
+ <span class="font-semibold text-toned"
183
+ >{{ resolveDisplayText(data.at(-1)?.label) }} ·
184
+ {{ formatValue(data.at(-1)?.value ?? 0) }}</span
185
+ >
186
+ </div>
187
+ </div>
188
+ <div v-else-if="variant === 'donut'" :class="[classes.plot, 'flex items-center gap-4']">
189
+ <svg width="96" height="96" viewBox="0 0 42 42" class="shrink-0" role="img">
190
+ <circle
191
+ cx="21"
192
+ cy="21"
193
+ r="15.915"
194
+ fill="none"
195
+ stroke="var(--nut-display-track)"
196
+ stroke-width="5.5"
197
+ />
198
+ <circle
199
+ v-for="(slice, index) in slices"
200
+ :key="index"
201
+ cx="21"
202
+ cy="21"
203
+ r="15.915"
204
+ fill="none"
205
+ :stroke="slice.color"
206
+ stroke-width="5.5"
207
+ :stroke-dasharray="slice.dash"
208
+ :stroke-dashoffset="slice.offset"
209
+ />
210
+ </svg>
211
+ <div :class="classes.legend">
212
+ <span v-for="(datum, index) in data" :key="index" :class="classes.legendItem">
213
+ <i class="size-2 shrink-0 rounded-[2px]" :style="{ background: slices[index]?.color }" />
214
+ {{ resolveDisplayText(datum.label) }}
215
+ <b class="font-semibold text-default tabular-nums"
216
+ >{{ Math.round(slices[index]?.share ?? 0) }} %</b
217
+ >
218
+ </span>
219
+ </div>
220
+ </div>
221
+ <div v-else-if="variant === 'funnel'" :class="[classes.plot, 'flex flex-col gap-1.5']">
222
+ <div v-for="(step, index) in steps" :key="index" :class="classes.step">
223
+ <span :class="classes.stepLabel">{{ resolveDisplayText(step.label) }}</span>
224
+ <span
225
+ class="h-4 rounded-[3px]"
226
+ :style="{
227
+ width: `${step.width}%`,
228
+ background: step.tone ? `var(--nut-display-${step.tone})` : 'var(--nut-dash-s1)',
229
+ opacity: step.tone ? 1 : 1 - index * 0.14
230
+ }"
231
+ />
232
+ <span :class="classes.stepValue">{{ formatValue(step.value) }}</span>
233
+ <span :class="classes.stepRate">{{ step.rate === void 0 ? "" : `${step.rate} %` }}</span>
234
+ </div>
235
+ </div>
236
+ </div>
237
+ </template>
@@ -0,0 +1,4 @@
1
+ import type { DisplayChartProps } from '../../types/index.js';
2
+ declare const __VLS_export: import("vue").DefineComponent<DisplayChartProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<DisplayChartProps> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
3
+ declare const _default: typeof __VLS_export;
4
+ export default _default;
@@ -0,0 +1,4 @@
1
+ import type { DisplayCodeProps } from '../../types/index.js';
2
+ declare const __VLS_export: import("vue").DefineComponent<DisplayCodeProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<DisplayCodeProps> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
3
+ declare const _default: typeof __VLS_export;
4
+ export default _default;
@@ -0,0 +1,143 @@
1
+ <script setup>
2
+ import UButton from "@nuxt/ui/components/Button.vue";
3
+ import UIcon from "@nuxt/ui/components/Icon.vue";
4
+ import { computed, ref } from "vue";
5
+ import { isNumber } from "../../../shared/utils/predicate";
6
+ import { useDisplayAppUi } from "../../composables/use-display-config";
7
+ import { useDisplayIcons } from "../../composables/use-display-icons";
8
+ import { useDisplayLocale } from "../../composables/use-display-locale";
9
+ import { resolveDisplayClasses } from "../../utils/classes";
10
+ import { resolveDisplayText } from "../../utils/content";
11
+ import { tokenizeJson } from "../../utils/json";
12
+ import DisplayCopy from "../parts/display-copy.vue";
13
+ import DisplaySkeleton from "../parts/display-skeleton.vue";
14
+ const {
15
+ variant = "block",
16
+ value,
17
+ language = void 0,
18
+ label = void 0,
19
+ icon = void 0,
20
+ href = void 0,
21
+ copy = true,
22
+ visible = 4,
23
+ maxHeight = void 0,
24
+ loading = false,
25
+ ui = void 0
26
+ } = defineProps({
27
+ variant: { type: String, required: false },
28
+ value: { type: String, required: true },
29
+ language: { type: String, required: false },
30
+ label: { type: [String, Number, Function], required: false },
31
+ icon: { type: String, required: false },
32
+ href: { type: String, required: false },
33
+ copy: { type: Boolean, required: false },
34
+ visible: { type: Number, required: false },
35
+ maxHeight: { type: [Number, String], required: false },
36
+ loading: { type: Boolean, required: false },
37
+ ui: { type: Object, required: false }
38
+ });
39
+ const TOKEN_CLASSES = {
40
+ key: "text-[var(--nut-display-code-key)]",
41
+ literal: "text-[var(--nut-display-code-literal)]",
42
+ number: "text-[var(--nut-display-code-number)]",
43
+ punctuation: "text-[var(--nut-display-code-muted)]",
44
+ space: "",
45
+ string: "text-[var(--nut-display-code-string)]"
46
+ };
47
+ const { t } = useDisplayLocale();
48
+ const icons = useDisplayIcons();
49
+ const appUi = useDisplayAppUi("code");
50
+ const revealed = ref(false);
51
+ const tokens = computed(
52
+ () => language?.toLowerCase() === "json" ? tokenizeJson(value) : void 0
53
+ );
54
+ const masked = computed(() => {
55
+ const kept = Math.max(0, Math.min(visible, value.length));
56
+ return `${"\u2022".repeat(Math.max(8, value.length - kept))}${kept ? value.slice(-kept) : ""}`;
57
+ });
58
+ const heading = computed(() => resolveDisplayText(label) ?? language);
59
+ const bodyStyle = computed(
60
+ () => maxHeight === void 0 ? void 0 : { maxHeight: isNumber(maxHeight) ? `${maxHeight}px` : maxHeight }
61
+ );
62
+ const classes = computed(
63
+ () => resolveDisplayClasses(
64
+ {
65
+ actions: "flex shrink-0 items-center",
66
+ body: "m-0 overflow-auto px-3 py-2.5 font-mono text-xs leading-relaxed whitespace-pre",
67
+ header: "flex items-center justify-between gap-2 border-b border-[var(--nut-display-code-line)] py-1 ps-3 pe-1 text-[11px] text-[var(--nut-display-code-muted)]",
68
+ icon: "me-1 size-3.5 shrink-0 text-muted",
69
+ language: "font-medium",
70
+ root: variant === "block" ? "min-w-0 overflow-hidden rounded-[var(--nut-display-radius)] bg-[var(--nut-display-code-bg)] text-[var(--nut-display-code-ink)]" : "flex h-9 min-w-0 items-center gap-1 rounded-[calc(var(--nut-display-radius)*0.75)] border border-accented bg-elevated ps-2.5 pe-1 font-mono text-[13px] text-default",
71
+ value: "min-w-0 flex-1 truncate"
72
+ },
73
+ appUi.value,
74
+ ui
75
+ )
76
+ );
77
+ </script>
78
+
79
+ <template>
80
+ <DisplaySkeleton v-if="loading" :layout="variant === 'block' ? 'block' : 'lines'" :count="1" />
81
+ <div
82
+ v-else-if="variant === 'block'"
83
+ :class="classes.root"
84
+ data-display="code"
85
+ data-variant="block"
86
+ >
87
+ <div v-if="heading || copy || href" :class="classes.header">
88
+ <span :class="classes.language">{{ heading }}</span>
89
+ <div :class="classes.actions">
90
+ <UButton
91
+ v-if="href"
92
+ :to="href"
93
+ target="_blank"
94
+ :icon="icons.external"
95
+ :aria-label="t('display.open')"
96
+ color="neutral"
97
+ variant="ghost"
98
+ size="xs"
99
+ square
100
+ class="text-[var(--nut-display-code-muted)]"
101
+ />
102
+ <DisplayCopy v-if="copy" :value="value" class="text-[var(--nut-display-code-muted)]" />
103
+ </div>
104
+ </div>
105
+ <pre
106
+ :class="classes.body"
107
+ :style="bodyStyle"
108
+ ><template v-if="tokens"><span v-for="(token, index) in tokens" :key="index" :class="TOKEN_CLASSES[token.kind]">{{ token.text }}</span></template><template v-else>{{ value }}</template></pre>
109
+ </div>
110
+ <div v-else :class="classes.root" data-display="code" :data-variant="variant">
111
+ <UIcon v-if="icon" :name="icon" :class="classes.icon" />
112
+ <span :class="classes.value" data-display-value>{{
113
+ variant === "secret" && !revealed ? masked : value
114
+ }}</span>
115
+ <div :class="classes.actions">
116
+ <UButton
117
+ v-if="variant === 'secret'"
118
+ :icon="revealed ? icons.eyeOff : icons.eye"
119
+ :aria-label="revealed ? t('display.conceal') : t('display.reveal')"
120
+ :aria-pressed="revealed"
121
+ color="neutral"
122
+ variant="ghost"
123
+ size="xs"
124
+ square
125
+ class="text-dimmed"
126
+ @click="revealed = !revealed"
127
+ />
128
+ <UButton
129
+ v-if="href"
130
+ :to="href"
131
+ target="_blank"
132
+ :icon="icons.external"
133
+ :aria-label="t('display.open')"
134
+ color="neutral"
135
+ variant="ghost"
136
+ size="xs"
137
+ square
138
+ class="text-dimmed"
139
+ />
140
+ <DisplayCopy v-if="copy" :value="value" />
141
+ </div>
142
+ </div>
143
+ </template>
@@ -0,0 +1,4 @@
1
+ import type { DisplayCodeProps } from '../../types/index.js';
2
+ declare const __VLS_export: import("vue").DefineComponent<DisplayCodeProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<DisplayCodeProps> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
3
+ declare const _default: typeof __VLS_export;
4
+ export default _default;
@@ -0,0 +1,4 @@
1
+ import type { DisplayDateProps } from '../../types/index.js';
2
+ declare const __VLS_export: import("vue").DefineComponent<DisplayDateProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<DisplayDateProps> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
3
+ declare const _default: typeof __VLS_export;
4
+ export default _default;
@@ -0,0 +1,174 @@
1
+ <script setup>
2
+ import UBadge from "@nuxt/ui/components/Badge.vue";
3
+ import UIcon from "@nuxt/ui/components/Icon.vue";
4
+ import { computed } from "vue";
5
+ import { useDisplayAppUi } from "../../composables/use-display-config";
6
+ import { useDisplayIcons } from "../../composables/use-display-icons";
7
+ import { useDisplayLocale } from "../../composables/use-display-locale";
8
+ import { resolveDisplayClasses } from "../../utils/classes";
9
+ import { isDisplayContentEmpty, resolveDisplayText } from "../../utils/content";
10
+ import {
11
+ calendarDaysBetween,
12
+ calendarLeaf,
13
+ formatDayCount,
14
+ formatDisplayDate,
15
+ formatRelativeDays,
16
+ toDisplayDate
17
+ } from "../../utils/dates";
18
+ import { displayToneClass } from "../../utils/tone";
19
+ import DisplayRender from "../parts/display-render";
20
+ import DisplaySkeleton from "../parts/display-skeleton.vue";
21
+ const {
22
+ variant = "tile",
23
+ value,
24
+ end = void 0,
25
+ title = void 0,
26
+ description = void 0,
27
+ icon = void 0,
28
+ tone = void 0,
29
+ time = false,
30
+ deadline = true,
31
+ warnWithin = 3,
32
+ now = void 0,
33
+ label = void 0,
34
+ loading = false,
35
+ ui = void 0
36
+ } = defineProps({
37
+ variant: { type: String, required: false },
38
+ value: { type: [Date, String, Number], required: true },
39
+ end: { type: [Date, String, Number], required: false },
40
+ title: { type: [String, Number, Function, Object, Boolean, null, Array], required: false, skipCheck: true },
41
+ description: { type: [String, Number, Function, Object, Boolean, null, Array], required: false, skipCheck: true },
42
+ icon: { type: String, required: false },
43
+ tone: { type: String, required: false },
44
+ time: { type: Boolean, required: false },
45
+ deadline: { type: Boolean, required: false },
46
+ warnWithin: { type: Number, required: false },
47
+ now: { type: [Date, String, Number], required: false },
48
+ label: { type: [String, Number, Function], required: false },
49
+ loading: { type: Boolean, required: false },
50
+ ui: { type: Object, required: false }
51
+ });
52
+ const TIME_FORMAT = { hour: "2-digit", minute: "2-digit" };
53
+ const LONG_DATE_FORMAT = {
54
+ day: "numeric",
55
+ month: "short",
56
+ weekday: "short"
57
+ };
58
+ const LONG_DATE_TIME_FORMAT = { ...LONG_DATE_FORMAT, ...TIME_FORMAT };
59
+ const { t, code } = useDisplayLocale();
60
+ const icons = useDisplayIcons();
61
+ const appUi = useDisplayAppUi("date");
62
+ const start = computed(() => toDisplayDate(value));
63
+ const finish = computed(() => toDisplayDate(end));
64
+ const reference = computed(() => toDisplayDate(now) ?? /* @__PURE__ */ new Date());
65
+ const days = computed(() => start.value ? calendarDaysBetween(reference.value, start.value) : 0);
66
+ const overdue = computed(() => deadline && days.value < 0);
67
+ const resolvedTone = computed(() => {
68
+ if (tone) return tone;
69
+ if (variant !== "countdown") return "primary";
70
+ if (overdue.value) return "error";
71
+ return days.value <= warnWithin ? "warning" : "neutral";
72
+ });
73
+ const leaf = computed(() => start.value ? calendarLeaf(start.value, code.value) : void 0);
74
+ const timeRange = computed(() => {
75
+ if (!time || !start.value) return void 0;
76
+ const from = formatDisplayDate(start.value, code.value, TIME_FORMAT);
77
+ return finish.value ? `${from} \u2013 ${formatDisplayDate(finish.value, code.value, TIME_FORMAT)}` : from;
78
+ });
79
+ const countdownText = computed(() => {
80
+ const text = resolveDisplayText(label);
81
+ if (text !== void 0) return text;
82
+ if (overdue.value)
83
+ return t("display.overdue", { duration: formatDayCount(-days.value, code.value) });
84
+ return formatRelativeDays(days.value, code.value);
85
+ });
86
+ const longDate = (date) => date ? formatDisplayDate(date, code.value, time ? LONG_DATE_TIME_FORMAT : LONG_DATE_FORMAT) : "";
87
+ const duration = computed(
88
+ () => start.value && finish.value ? formatDayCount(calendarDaysBetween(start.value, finish.value) + 1, code.value) : void 0
89
+ );
90
+ const classes = computed(
91
+ () => resolveDisplayClasses(
92
+ {
93
+ body: "min-w-0",
94
+ bound: "flex flex-col",
95
+ boundLabel: "text-[11px] text-muted",
96
+ boundValue: "text-[15px] font-bold text-highlighted",
97
+ caption: "text-xs text-toned",
98
+ day: "pt-1 text-xl leading-none font-extrabold text-highlighted",
99
+ description: "mt-0.5 flex items-center gap-1 text-xs text-muted",
100
+ duration: "",
101
+ icon: "size-5 shrink-0 text-[var(--nut-tone-ink)]",
102
+ line: "flex flex-1 items-center gap-2 before:h-px before:flex-1 before:bg-[var(--ui-border-accented)] after:h-px after:flex-1 after:bg-[var(--ui-border-accented)]",
103
+ month: "bg-[var(--nut-tone)] py-0.5 text-[9.5px] font-extrabold tracking-[0.1em] text-[var(--nut-tone-contrast)]",
104
+ root: variant === "countdown" ? "flex items-center gap-3 rounded-[var(--nut-display-radius)] bg-[var(--nut-tone-soft)] px-3.5 py-3" : "flex min-w-0 items-center gap-3",
105
+ tile: "w-13 shrink-0 overflow-hidden rounded-[var(--nut-display-radius)] border border-default bg-default text-center",
106
+ title: "font-semibold text-highlighted",
107
+ value: "text-lg leading-tight font-extrabold text-[var(--nut-tone-ink)]",
108
+ weekday: "pb-1 text-[10.5px] text-muted"
109
+ },
110
+ appUi.value,
111
+ ui
112
+ )
113
+ );
114
+ </script>
115
+
116
+ <template>
117
+ <DisplaySkeleton v-if="loading" layout="card" />
118
+ <div
119
+ v-else
120
+ :class="[classes.root, displayToneClass(resolvedTone)]"
121
+ data-display="date"
122
+ :data-variant="variant"
123
+ >
124
+ <template v-if="variant === 'countdown'">
125
+ <UIcon :name="icon ?? (overdue ? icons.warning : 'i-lucide-clock')" :class="classes.icon" />
126
+ <div :class="classes.body">
127
+ <div :class="classes.value" data-display-countdown>{{ countdownText }}</div>
128
+ <div :class="classes.caption">
129
+ <DisplayRender
130
+ :content="
131
+ description ?? (deadline ? t('display.dueOn', { date: longDate(start) }) : longDate(start))
132
+ "
133
+ />
134
+ </div>
135
+ </div>
136
+ </template>
137
+ <template v-else-if="variant === 'range'">
138
+ <div :class="classes.bound">
139
+ <span :class="classes.boundLabel">{{ t("display.from") }}</span>
140
+ <span :class="classes.boundValue">{{ longDate(start) }}</span>
141
+ </div>
142
+ <div :class="classes.line">
143
+ <UBadge
144
+ v-if="duration"
145
+ color="neutral"
146
+ variant="soft"
147
+ size="sm"
148
+ :label="duration"
149
+ :class="classes.duration"
150
+ />
151
+ </div>
152
+ <div :class="[classes.bound, 'text-end']">
153
+ <span :class="classes.boundLabel">{{ t("display.to") }}</span>
154
+ <span :class="classes.boundValue">{{ longDate(finish) }}</span>
155
+ </div>
156
+ </template>
157
+ <template v-else>
158
+ <div :class="classes.tile" aria-hidden="true">
159
+ <div :class="classes.month">{{ leaf?.month }}</div>
160
+ <div :class="classes.day">{{ leaf?.day }}</div>
161
+ <div :class="classes.weekday">{{ leaf?.weekday }}</div>
162
+ </div>
163
+ <div :class="classes.body">
164
+ <div :class="classes.title"><DisplayRender :content="title ?? longDate(start)" /></div>
165
+ <div v-if="!isDisplayContentEmpty(description) || timeRange" :class="classes.description">
166
+ <UIcon v-if="timeRange" :name="icon ?? 'i-lucide-clock'" class="size-3 shrink-0" />
167
+ <span v-if="timeRange">{{ timeRange }}</span>
168
+ <template v-if="timeRange && !isDisplayContentEmpty(description)"> · </template>
169
+ <DisplayRender :content="description" />
170
+ </div>
171
+ </div>
172
+ </template>
173
+ </div>
174
+ </template>
@@ -0,0 +1,4 @@
1
+ import type { DisplayDateProps } from '../../types/index.js';
2
+ declare const __VLS_export: import("vue").DefineComponent<DisplayDateProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<DisplayDateProps> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
3
+ declare const _default: typeof __VLS_export;
4
+ export default _default;
@@ -0,0 +1,4 @@
1
+ import type { DisplayDiffProps } from '../../types/index.js';
2
+ declare const __VLS_export: import("vue").DefineComponent<DisplayDiffProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<DisplayDiffProps> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
3
+ declare const _default: typeof __VLS_export;
4
+ export default _default;