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