@happyvertical/smrt-svelte 0.55.24 → 0.56.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/agents/overview-surfaces.md +16 -4
- package/dist/components/command-palette/CommandPaletteDialog.svelte +1 -1
- package/dist/components/overview/OverviewGrid.svelte +8 -4
- package/dist/components/overview/OverviewGrid.svelte.d.ts.map +1 -1
- package/dist/components/overview/WidgetOptionsForm.svelte +13 -2
- package/dist/components/overview/WidgetOptionsForm.svelte.d.ts.map +1 -1
- package/dist/components/overview/format.d.ts +3 -12
- package/dist/components/overview/format.d.ts.map +1 -1
- package/dist/components/overview/format.js +2 -45
- package/dist/components/overview/grid-types.d.ts +6 -11
- package/dist/components/overview/grid-types.d.ts.map +1 -1
- package/dist/components/overview/index.d.ts +1 -0
- package/dist/components/overview/index.d.ts.map +1 -1
- package/dist/components/overview/recipe-widgets.d.ts +6 -3
- package/dist/components/overview/recipe-widgets.d.ts.map +1 -1
- package/dist/components/overview/recipe-widgets.js +9 -0
- package/dist/components/overview/registry.d.ts +3 -0
- package/dist/components/overview/registry.d.ts.map +1 -1
- package/dist/components/overview/registry.js +25 -0
- package/dist/components/overview/server.d.ts +1 -1
- package/dist/components/overview/server.d.ts.map +1 -1
- package/dist/components/overview/server.js +1 -1
- package/dist/components/overview/types.d.ts +17 -0
- package/dist/components/overview/types.d.ts.map +1 -1
- package/dist/components/overview/widgets/ChartWidget.svelte +5 -265
- package/dist/components/overview/widgets/ChartWidget.svelte.d.ts +1 -1
- package/dist/components/overview/widgets/ChartWidget.svelte.d.ts.map +1 -1
- package/dist/components/overview/widgets/LineItemsWidget.svelte +44 -3
- package/dist/components/overview/widgets/LineItemsWidget.svelte.d.ts.map +1 -1
- package/dist/components/overview/widgets/data.d.ts +17 -0
- package/dist/components/overview/widgets/data.d.ts.map +1 -1
- package/dist/components/overview/widgets/line-totals.d.ts +35 -0
- package/dist/components/overview/widgets/line-totals.d.ts.map +1 -1
- package/dist/components/overview/widgets/line-totals.js +45 -0
- package/dist/components/overview/widgets/record-loaders.d.ts +3 -1
- package/dist/components/overview/widgets/record-loaders.d.ts.map +1 -1
- package/dist/components/overview/widgets/record-loaders.js +8 -1
- package/dist/components/screens/RecordScreen.svelte +2 -0
- package/dist/components/screens/RecordScreen.svelte.d.ts.map +1 -1
- package/dist/components/screens/types.d.ts +8 -1
- package/dist/components/screens/types.d.ts.map +1 -1
- package/dist/components/workspace/admin-shell/AdminShell.svelte +4 -4
- package/dist/components/workspace/admin-shell/ShellIconButton.svelte +2 -2
- package/dist/components/workspace/admin-shell/TenantNav.svelte +8 -8
- package/dist/components/workspace/admin-shell/WorkspaceAccountMenu.svelte +3 -3
- package/dist/i18n/strings.overview.d.ts +5 -0
- package/dist/i18n/strings.overview.d.ts.map +1 -1
- package/dist/i18n/strings.overview.js +5 -0
- package/package.json +16 -16
|
@@ -1,272 +1,12 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
|
|
3
|
-
* Chart widget (#3727, #3888): bars, a line, a plain table, a donut or a single
|
|
4
|
-
* headline value over labelled values, drawn from the loaded data. Every chart
|
|
5
|
-
* carries its numbers as text (bar values inline, a visible table for `table`,
|
|
6
|
-
* a visually hidden table for the line and the donut, the value itself for
|
|
7
|
-
* `stat`) so it is readable without sight.
|
|
8
|
-
*/
|
|
9
|
-
import { useI18n } from '@happyvertical/smrt-ui/i18n';
|
|
10
|
-
import { M } from '../../../i18n/strings.overview.js';
|
|
11
|
-
import { formatWidgetValue } from '../format.js';
|
|
2
|
+
import { Chart } from '@happyvertical/smrt-ui/charts';
|
|
12
3
|
import type { WidgetComponentProps } from '../types.js';
|
|
13
|
-
import {
|
|
4
|
+
import type { ChartWidgetData } from './data.js';
|
|
14
5
|
|
|
15
6
|
let { options, data, title, locale }: WidgetComponentProps<ChartWidgetData> =
|
|
16
7
|
$props();
|
|
17
|
-
|
|
18
|
-
const { t } = useI18n();
|
|
19
|
-
const MAX_POINTS = 60;
|
|
20
|
-
|
|
21
|
-
const chart = $derived(isRecord(data) ? data : null);
|
|
22
|
-
const points = $derived.by(() => {
|
|
23
|
-
if (!chart || !Array.isArray(chart.points)) return [];
|
|
24
|
-
const out: { label: string; value: number }[] = [];
|
|
25
|
-
for (const point of chart.points.slice(0, MAX_POINTS)) {
|
|
26
|
-
if (
|
|
27
|
-
isRecord(point) &&
|
|
28
|
-
typeof point.label === 'string' &&
|
|
29
|
-
typeof point.value === 'number' &&
|
|
30
|
-
Number.isFinite(point.value)
|
|
31
|
-
) {
|
|
32
|
-
out.push({ label: point.label, value: point.value });
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
return out;
|
|
36
|
-
});
|
|
37
|
-
const STYLES = ['bar', 'line', 'table', 'pie', 'stat'] as const;
|
|
38
|
-
const style = $derived(
|
|
39
|
-
STYLES.find((candidate) => candidate === options.style) ?? 'bar',
|
|
40
|
-
);
|
|
41
|
-
const fmt = (value: number): string =>
|
|
42
|
-
formatWidgetValue(value, {
|
|
43
|
-
format: chart?.format ?? 'integer',
|
|
44
|
-
currency: chart?.currency,
|
|
45
|
-
locale,
|
|
46
|
-
});
|
|
47
|
-
const max = $derived(Math.max(0, ...points.map((point) => point.value)));
|
|
48
|
-
const min = $derived(Math.min(0, ...points.map((point) => point.value)));
|
|
49
|
-
const span = $derived(max - min || 1);
|
|
50
|
-
const polyline = $derived(
|
|
51
|
-
points
|
|
52
|
-
.map((point, index) => {
|
|
53
|
-
const x = points.length === 1 ? 50 : (index / (points.length - 1)) * 100;
|
|
54
|
-
const y = 36 - ((point.value - min) / span) * 32;
|
|
55
|
-
return `${x.toFixed(2)},${y.toFixed(2)}`;
|
|
56
|
-
})
|
|
57
|
-
.join(' '),
|
|
58
|
-
);
|
|
59
|
-
|
|
60
|
-
// Donut: slices are percentages of the positive total on a circle whose
|
|
61
|
-
// path length is 100, so a segment's dash length is its share.
|
|
62
|
-
const total = $derived(
|
|
63
|
-
points.reduce((sum, point) => sum + Math.max(0, point.value), 0),
|
|
64
|
-
);
|
|
65
|
-
const slices = $derived.by(() => {
|
|
66
|
-
let offset = 0;
|
|
67
|
-
return points.map((point, index) => {
|
|
68
|
-
const share = total > 0 ? (Math.max(0, point.value) / total) * 100 : 0;
|
|
69
|
-
const slice = { ...point, index, share, offset };
|
|
70
|
-
offset += share;
|
|
71
|
-
return slice;
|
|
72
|
-
});
|
|
73
|
-
});
|
|
74
|
-
const percent = (share: number): string =>
|
|
75
|
-
formatWidgetValue(share / 100, { format: 'percent', locale });
|
|
76
|
-
|
|
77
|
-
// Stat: the latest value, and its change against the one before.
|
|
78
|
-
const latest = $derived(points.at(-1));
|
|
79
|
-
const delta = $derived.by((): number | null => {
|
|
80
|
-
if (
|
|
81
|
-
chart &&
|
|
82
|
-
typeof chart.delta === 'number' &&
|
|
83
|
-
Number.isFinite(chart.delta)
|
|
84
|
-
) {
|
|
85
|
-
return chart.delta;
|
|
86
|
-
}
|
|
87
|
-
const previous = points.at(-2);
|
|
88
|
-
if (!latest || !previous || previous.value === 0) return null;
|
|
89
|
-
return ((latest.value - previous.value) / Math.abs(previous.value)) * 100;
|
|
90
|
-
});
|
|
91
|
-
const deltaText = $derived(
|
|
92
|
-
delta === null || delta === 0
|
|
93
|
-
? ''
|
|
94
|
-
: t(
|
|
95
|
-
M[
|
|
96
|
-
delta > 0
|
|
97
|
-
? 'ui.overview.metric.change_up'
|
|
98
|
-
: 'ui.overview.metric.change_down'
|
|
99
|
-
],
|
|
100
|
-
{
|
|
101
|
-
value: formatWidgetValue(Math.abs(delta) / 100, {
|
|
102
|
-
format: 'percent',
|
|
103
|
-
locale,
|
|
104
|
-
}),
|
|
105
|
-
},
|
|
106
|
-
),
|
|
107
|
-
);
|
|
108
|
-
const summary = $derived(
|
|
109
|
-
`${title}. ${t(M['ui.overview.chart.summary'], { count: points.length })}`,
|
|
110
|
-
);
|
|
111
8
|
</script>
|
|
112
9
|
|
|
113
|
-
|
|
114
|
-
<
|
|
115
|
-
|
|
116
|
-
<thead>
|
|
117
|
-
<tr>
|
|
118
|
-
<th scope="col">{t(M['ui.overview.chart.label_column'])}</th>
|
|
119
|
-
<th scope="col">{t(M['ui.overview.chart.value_column'])}</th>
|
|
120
|
-
</tr>
|
|
121
|
-
</thead>
|
|
122
|
-
<tbody>
|
|
123
|
-
{#each points as point, index (index)}
|
|
124
|
-
<tr><th scope="row">{point.label}</th><td>{fmt(point.value)}</td></tr>
|
|
125
|
-
{/each}
|
|
126
|
-
</tbody>
|
|
127
|
-
</table>
|
|
128
|
-
{/snippet}
|
|
129
|
-
|
|
130
|
-
{#if points.length === 0}
|
|
131
|
-
<p class="smrt-chart__empty" data-smrt-component="ChartWidget">{t(M['ui.overview.no_data'])}</p>
|
|
132
|
-
{:else if style === 'table'}
|
|
133
|
-
<div class="smrt-chart smrt-chart--table" data-smrt-component="ChartWidget">
|
|
134
|
-
{@render dataTable(false)}
|
|
135
|
-
</div>
|
|
136
|
-
{:else if style === 'stat'}
|
|
137
|
-
{#if latest}
|
|
138
|
-
<div class="smrt-chart smrt-chart--stat" data-smrt-component="ChartWidget">
|
|
139
|
-
<p class="smrt-chart__headline">{fmt(latest.value)}</p>
|
|
140
|
-
<p class="smrt-chart__caption">{latest.label}</p>
|
|
141
|
-
{#if deltaText}
|
|
142
|
-
<p class="smrt-chart__delta" data-direction={(delta ?? 0) > 0 ? 'up' : 'down'}>
|
|
143
|
-
<span aria-hidden="true">{(delta ?? 0) > 0 ? '▲' : '▼'}</span>
|
|
144
|
-
{deltaText}
|
|
145
|
-
</p>
|
|
146
|
-
{/if}
|
|
147
|
-
</div>
|
|
148
|
-
{/if}
|
|
149
|
-
{:else if style === 'pie'}
|
|
150
|
-
{#if total > 0}
|
|
151
|
-
<div class="smrt-chart smrt-chart--pie" data-smrt-component="ChartWidget">
|
|
152
|
-
<svg class="smrt-chart__donut" viewBox="0 0 42 42" role="img" aria-label={summary}>
|
|
153
|
-
{#each slices as slice (slice.index)}
|
|
154
|
-
{#if slice.share > 0}
|
|
155
|
-
<circle
|
|
156
|
-
class="smrt-chart__slice"
|
|
157
|
-
data-slot={slice.index % 8}
|
|
158
|
-
cx="21"
|
|
159
|
-
cy="21"
|
|
160
|
-
r="15.9155"
|
|
161
|
-
fill="none"
|
|
162
|
-
stroke-width="6"
|
|
163
|
-
pathLength="100"
|
|
164
|
-
stroke-dasharray="{slice.share} {100 - slice.share}"
|
|
165
|
-
stroke-dashoffset={-slice.offset}
|
|
166
|
-
transform="rotate(-90 21 21)"
|
|
167
|
-
/>
|
|
168
|
-
{/if}
|
|
169
|
-
{/each}
|
|
170
|
-
</svg>
|
|
171
|
-
<ul class="smrt-chart__legend" aria-hidden="true">
|
|
172
|
-
{#each slices as slice (slice.index)}
|
|
173
|
-
<li class="smrt-chart__legend-item">
|
|
174
|
-
<span class="smrt-chart__swatch" data-slot={slice.index % 8}></span>
|
|
175
|
-
<span class="smrt-chart__label">{slice.label}</span>
|
|
176
|
-
<span class="smrt-chart__value">{fmt(slice.value)} · {percent(slice.share)}</span>
|
|
177
|
-
</li>
|
|
178
|
-
{/each}
|
|
179
|
-
</ul>
|
|
180
|
-
{@render dataTable(true)}
|
|
181
|
-
</div>
|
|
182
|
-
{:else}
|
|
183
|
-
<p class="smrt-chart__empty" data-smrt-component="ChartWidget">{t(M['ui.overview.no_data'])}</p>
|
|
184
|
-
{/if}
|
|
185
|
-
{:else if style === 'line'}
|
|
186
|
-
<div class="smrt-chart" data-smrt-component="ChartWidget">
|
|
187
|
-
<svg class="smrt-chart__line" viewBox="0 0 100 40" preserveAspectRatio="none" role="img" aria-label={summary}>
|
|
188
|
-
<polyline points={polyline} fill="none" stroke="currentColor" stroke-width="2" vector-effect="non-scaling-stroke" />
|
|
189
|
-
</svg>
|
|
190
|
-
<p class="smrt-chart__axis" aria-hidden="true">
|
|
191
|
-
<span>{points[0].label}</span>
|
|
192
|
-
<span>{points[points.length - 1].label}</span>
|
|
193
|
-
</p>
|
|
194
|
-
{@render dataTable(true)}
|
|
195
|
-
</div>
|
|
196
|
-
{:else}
|
|
197
|
-
<ul class="smrt-chart__bars" aria-label={summary} data-smrt-component="ChartWidget">
|
|
198
|
-
{#each points as point, index (index)}
|
|
199
|
-
<li class="smrt-chart__row">
|
|
200
|
-
<span class="smrt-chart__label">{point.label}</span>
|
|
201
|
-
<span class="smrt-chart__track" aria-hidden="true">
|
|
202
|
-
<span class="smrt-chart__bar" style:inline-size="{max > 0 ? (Math.max(0, point.value) / max) * 100 : 0}%"></span>
|
|
203
|
-
</span>
|
|
204
|
-
<span class="smrt-chart__value">{fmt(point.value)}</span>
|
|
205
|
-
</li>
|
|
206
|
-
{/each}
|
|
207
|
-
</ul>
|
|
208
|
-
{/if}
|
|
209
|
-
|
|
210
|
-
<style>
|
|
211
|
-
@layer smrt.reset, smrt.structure, smrt.theme;
|
|
212
|
-
@layer smrt.theme {
|
|
213
|
-
.smrt-chart { display: grid; gap: var(--smrt-spacing-1); color: var(--smrt-color-primary); }
|
|
214
|
-
.smrt-chart__line { inline-size: 100%; block-size: 7rem; overflow: visible; }
|
|
215
|
-
.smrt-chart__axis { display: flex; justify-content: space-between; margin: 0; color: var(--smrt-color-on-surface-variant); font-size: var(--smrt-typography-label-large-size, 0.75rem); }
|
|
216
|
-
.smrt-chart__bars { display: grid; gap: var(--smrt-spacing-2); margin: 0; padding: 0; list-style: none; }
|
|
217
|
-
.smrt-chart__row { display: grid; grid-template-columns: minmax(4rem, 30%) minmax(0, 1fr) auto; align-items: center; gap: var(--smrt-spacing-2); font-size: var(--smrt-typography-body-medium-size, 0.875rem); color: var(--smrt-color-on-surface); }
|
|
218
|
-
.smrt-chart__label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
219
|
-
.smrt-chart__track { display: block; block-size: 0.625rem; border-radius: var(--smrt-radius-full); background: var(--smrt-color-surface-container-high); overflow: hidden; }
|
|
220
|
-
.smrt-chart__bar { display: block; block-size: 100%; border-radius: inherit; background: var(--smrt-color-primary); }
|
|
221
|
-
.smrt-chart__value { font-variant-numeric: tabular-nums; color: var(--smrt-color-on-surface-variant); }
|
|
222
|
-
.smrt-chart__empty { margin: 0; color: var(--smrt-color-on-surface-variant); }
|
|
223
|
-
.smrt-chart--table { color: var(--smrt-color-on-surface); }
|
|
224
|
-
.smrt-chart__data { inline-size: 100%; border-collapse: collapse; font-size: var(--smrt-typography-body-medium-size, 0.875rem); }
|
|
225
|
-
.smrt-chart__data caption { position: absolute; inline-size: 1px; block-size: 1px; overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; }
|
|
226
|
-
.smrt-chart__data th, .smrt-chart__data td { padding: var(--smrt-spacing-1) var(--smrt-spacing-2); border-block-end: var(--smrt-hairline); text-align: start; }
|
|
227
|
-
.smrt-chart__data thead th { background: var(--smrt-surface-sunken); color: var(--smrt-color-on-surface-variant); font-weight: var(--smrt-typography-weight-medium, 500); }
|
|
228
|
-
.smrt-chart__data tbody th { font-weight: inherit; overflow-wrap: anywhere; }
|
|
229
|
-
.smrt-chart__data td, .smrt-chart__data thead th:last-child { text-align: end; font-variant-numeric: tabular-nums; }
|
|
230
|
-
.smrt-chart--stat { gap: var(--smrt-spacing-1); color: var(--smrt-color-on-surface); }
|
|
231
|
-
.smrt-chart__headline { margin: 0; font-size: var(--smrt-typography-display-small-size, 2rem); font-weight: var(--smrt-typography-weight-medium, 500); line-height: 1.1; font-variant-numeric: tabular-nums; }
|
|
232
|
-
.smrt-chart__caption { margin: 0; color: var(--smrt-color-on-surface-variant); font-size: var(--smrt-typography-body-medium-size, 0.875rem); }
|
|
233
|
-
.smrt-chart__delta { margin: 0; color: var(--smrt-color-on-surface-variant); font-size: var(--smrt-typography-label-large-size, 0.875rem); }
|
|
234
|
-
.smrt-chart--pie { grid-template-columns: minmax(6rem, 10rem) minmax(0, 1fr); align-items: center; gap: var(--smrt-spacing-4); }
|
|
235
|
-
.smrt-chart__donut { inline-size: 100%; block-size: auto; }
|
|
236
|
-
.smrt-chart__slice[data-slot='0'], .smrt-chart__swatch[data-slot='0'] { stroke: var(--smrt-color-primary); background: var(--smrt-color-primary); }
|
|
237
|
-
.smrt-chart__slice[data-slot='1'], .smrt-chart__swatch[data-slot='1'] { stroke: var(--smrt-color-secondary); background: var(--smrt-color-secondary); }
|
|
238
|
-
.smrt-chart__slice[data-slot='2'], .smrt-chart__swatch[data-slot='2'] { stroke: var(--smrt-color-tertiary); background: var(--smrt-color-tertiary); }
|
|
239
|
-
.smrt-chart__slice[data-slot='3'], .smrt-chart__swatch[data-slot='3'] { stroke: var(--smrt-color-info); background: var(--smrt-color-info); }
|
|
240
|
-
.smrt-chart__slice[data-slot='4'], .smrt-chart__swatch[data-slot='4'] { stroke: var(--smrt-color-primary-container); background: var(--smrt-color-primary-container); }
|
|
241
|
-
.smrt-chart__slice[data-slot='5'], .smrt-chart__swatch[data-slot='5'] { stroke: var(--smrt-color-secondary-container); background: var(--smrt-color-secondary-container); }
|
|
242
|
-
.smrt-chart__slice[data-slot='6'], .smrt-chart__swatch[data-slot='6'] { stroke: var(--smrt-color-tertiary-container); background: var(--smrt-color-tertiary-container); }
|
|
243
|
-
.smrt-chart__slice[data-slot='7'], .smrt-chart__swatch[data-slot='7'] { stroke: var(--smrt-color-info-container); background: var(--smrt-color-info-container); }
|
|
244
|
-
.smrt-chart__legend { display: grid; gap: var(--smrt-spacing-1); margin: 0; padding: 0; list-style: none; color: var(--smrt-color-on-surface); font-size: var(--smrt-typography-body-medium-size, 0.875rem); }
|
|
245
|
-
.smrt-chart__legend-item { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; gap: var(--smrt-spacing-2); }
|
|
246
|
-
.smrt-chart__swatch { inline-size: 0.75rem; block-size: 0.75rem; border-radius: var(--smrt-radius-small); }
|
|
247
|
-
.smrt-chart__legend .smrt-chart__label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
248
|
-
@media (prefers-reduced-motion: no-preference) {
|
|
249
|
-
.smrt-chart__slice { transition: stroke-dasharray var(--smrt-duration-normal) var(--smrt-easing-standard), stroke-dashoffset var(--smrt-duration-normal) var(--smrt-easing-standard); }
|
|
250
|
-
.smrt-chart__bar { transition: inline-size var(--smrt-duration-normal) var(--smrt-easing-standard); }
|
|
251
|
-
}
|
|
252
|
-
.smrt-chart__table { position: absolute; inline-size: 1px; block-size: 1px; overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; }
|
|
253
|
-
/* Forced colors (#3908): selected and open states keep a non-colour indicator. */
|
|
254
|
-
@media (forced-colors: active) {
|
|
255
|
-
/* Series keys: system colours cycle by slot (the user's own palette), so
|
|
256
|
-
slices and legend swatches stay distinguishable without author colours.
|
|
257
|
-
The legend always carries label, value and share as text. */
|
|
258
|
-
.smrt-chart__slice[data-slot='0'], .smrt-chart__swatch[data-slot='0'] { stroke: CanvasText; background: CanvasText; }
|
|
259
|
-
.smrt-chart__slice[data-slot='1'], .smrt-chart__swatch[data-slot='1'] { stroke: Highlight; background: Highlight; }
|
|
260
|
-
.smrt-chart__slice[data-slot='2'], .smrt-chart__swatch[data-slot='2'] { stroke: LinkText; background: LinkText; }
|
|
261
|
-
.smrt-chart__slice[data-slot='3'], .smrt-chart__swatch[data-slot='3'] { stroke: VisitedText; background: VisitedText; }
|
|
262
|
-
.smrt-chart__slice[data-slot='4'], .smrt-chart__swatch[data-slot='4'] { stroke: ActiveText; background: ActiveText; }
|
|
263
|
-
.smrt-chart__slice[data-slot='5'], .smrt-chart__swatch[data-slot='5'] { stroke: GrayText; background: GrayText; }
|
|
264
|
-
.smrt-chart__slice[data-slot='6'], .smrt-chart__swatch[data-slot='6'] { stroke: ButtonText; background: ButtonText; }
|
|
265
|
-
.smrt-chart__slice[data-slot='7'], .smrt-chart__swatch[data-slot='7'] { stroke: MarkText; background: MarkText; }
|
|
266
|
-
.smrt-chart__swatch { border: var(--smrt-hairline-strong); }
|
|
267
|
-
.smrt-chart__slice { stroke-linecap: butt; }
|
|
268
|
-
.smrt-chart__track { background: Canvas; border: var(--smrt-hairline-strong); }
|
|
269
|
-
.smrt-chart__bar { background: Highlight; }
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
</style>
|
|
10
|
+
<div data-smrt-component="ChartWidget">
|
|
11
|
+
<Chart data={data ?? null} style={String(options.style ?? 'bar')} {title} {locale} />
|
|
12
|
+
</div>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { WidgetComponentProps } from '../types.js';
|
|
2
|
-
import {
|
|
2
|
+
import type { ChartWidgetData } from './data.js';
|
|
3
3
|
declare const ChartWidget: import("svelte").Component<WidgetComponentProps<ChartWidgetData>, {}, "">;
|
|
4
4
|
type ChartWidget = ReturnType<typeof ChartWidget>;
|
|
5
5
|
export default ChartWidget;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChartWidget.svelte.d.ts","sourceRoot":"","sources":["../../../../src/components/overview/widgets/ChartWidget.svelte.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ChartWidget.svelte.d.ts","sourceRoot":"","sources":["../../../../src/components/overview/widgets/ChartWidget.svelte.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAiBjD,QAAA,MAAM,WAAW,2EAAwC,CAAC;AAC1D,KAAK,WAAW,GAAG,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC;AAClD,eAAe,WAAW,CAAC"}
|
|
@@ -12,7 +12,12 @@ import { M } from '../../../i18n/strings.overview.js';
|
|
|
12
12
|
import { safeHref } from '../markdown.js';
|
|
13
13
|
import type { WidgetComponentProps } from '../types.js';
|
|
14
14
|
import { isRecord, type LineItemsWidgetData } from './data.js';
|
|
15
|
-
import {
|
|
15
|
+
import {
|
|
16
|
+
groupStoredTaxComponents,
|
|
17
|
+
isStoredLineItemsTotals,
|
|
18
|
+
lineItemTotals,
|
|
19
|
+
sumLineAmounts,
|
|
20
|
+
} from './line-totals.js';
|
|
16
21
|
import RecordTable from './RecordTable.svelte';
|
|
17
22
|
import {
|
|
18
23
|
formatRecordCell,
|
|
@@ -70,6 +75,19 @@ const result = $derived(
|
|
|
70
75
|
lineSum,
|
|
71
76
|
),
|
|
72
77
|
);
|
|
78
|
+
const storedTotals = $derived(
|
|
79
|
+
isRecord(data) && isStoredLineItemsTotals(data.storedTotals)
|
|
80
|
+
? data.storedTotals
|
|
81
|
+
: undefined,
|
|
82
|
+
);
|
|
83
|
+
const storedTaxes = $derived(
|
|
84
|
+
storedTotals
|
|
85
|
+
? groupStoredTaxComponents(storedTotals.taxes).filter(
|
|
86
|
+
(tax) => tax.tax !== 0,
|
|
87
|
+
)
|
|
88
|
+
: [],
|
|
89
|
+
);
|
|
90
|
+
const hasStoredTax = $derived(storedTaxes.length > 0);
|
|
73
91
|
const viewAll = $derived(
|
|
74
92
|
isRecord(data) && typeof data.href === 'string' ? safeHref(data.href) : null,
|
|
75
93
|
);
|
|
@@ -101,7 +119,29 @@ const LABELS = {
|
|
|
101
119
|
{:else}
|
|
102
120
|
<p class="smrt-line-items__empty">{t(M['ui.overview.line_items.empty'])}</p>
|
|
103
121
|
{/if}
|
|
104
|
-
{#if
|
|
122
|
+
{#if storedTotals}
|
|
123
|
+
<dl class="smrt-line-items__totals" data-money-snapshot="stored">
|
|
124
|
+
{#if storedTotals.lineAmountType !== 'inclusive' || !hasStoredTax}
|
|
125
|
+
<div class="smrt-line-items__total"><dt>{t(M['ui.overview.line_items.subtotal'])}</dt><dd>{money(storedTotals.subtotal)}</dd></div>
|
|
126
|
+
{/if}
|
|
127
|
+
{#if storedTotals.discount !== 0}
|
|
128
|
+
<div class="smrt-line-items__total smrt-line-items__total--muted"><dt>{t(M['ui.overview.line_items.discount_included'])} {money(Math.abs(storedTotals.discount))}</dt></div>
|
|
129
|
+
{/if}
|
|
130
|
+
{#each storedTaxes as tax (`${tax.taxComponentId}-${tax.name}-${tax.percent}`)}
|
|
131
|
+
<div class="smrt-line-items__total smrt-line-items__total--muted">
|
|
132
|
+
<dt>{t(M[storedTotals.lineAmountType === 'inclusive' ? 'ui.overview.line_items.tax_included' : 'ui.overview.line_items.tax_on'], { name: tax.name, percent: tax.percent })} {money(storedTotals.lineAmountType === 'inclusive' ? tax.tax : tax.taxable)}</dt>
|
|
133
|
+
{#if storedTotals.lineAmountType !== 'inclusive'}<dd>{money(tax.tax)}</dd>{/if}
|
|
134
|
+
</div>
|
|
135
|
+
{/each}
|
|
136
|
+
{#if storedTotals.roundingScope === 'document'}
|
|
137
|
+
<div class="smrt-line-items__total smrt-line-items__total--muted"><dt>{t(M['ui.overview.line_items.rounded_document'])}</dt></div>
|
|
138
|
+
{/if}
|
|
139
|
+
<div class="smrt-line-items__total smrt-line-items__total--grand"><dt>{t(M['ui.overview.line_items.total'])}</dt><dd>{money(storedTotals.total)}</dd></div>
|
|
140
|
+
{#if storedTotals.lineAmountType === 'inclusive' && hasStoredTax && storedTotals.showNetSubtotal}
|
|
141
|
+
<div class="smrt-line-items__total"><dt>{t(M['ui.overview.line_items.subtotal_excluding_tax'])}</dt><dd>{money(storedTotals.subtotal)}</dd></div>
|
|
142
|
+
{/if}
|
|
143
|
+
</dl>
|
|
144
|
+
{:else if result.lines.length > 0}
|
|
105
145
|
<dl class="smrt-line-items__totals">
|
|
106
146
|
{#each result.lines as line (line.key)}
|
|
107
147
|
<div class="smrt-line-items__total" class:smrt-line-items__total--grand={line.key === 'total'}>
|
|
@@ -114,7 +154,7 @@ const LABELS = {
|
|
|
114
154
|
{/each}
|
|
115
155
|
</dl>
|
|
116
156
|
{/if}
|
|
117
|
-
{#if result.mismatch}
|
|
157
|
+
{#if !storedTotals && result.mismatch}
|
|
118
158
|
<p class="smrt-line-items__flag">
|
|
119
159
|
<strong>{t(M['ui.overview.line_items.mismatch'], { amount: money(result.mismatch.lines) })}</strong>
|
|
120
160
|
{t(M[result.mismatch.field === 'subtotal' ? 'ui.overview.line_items.mismatch_subtotal' : 'ui.overview.line_items.mismatch_total'], { amount: money(result.mismatch.recorded) })}
|
|
@@ -133,6 +173,7 @@ const LABELS = {
|
|
|
133
173
|
.smrt-line-items__totals { display: grid; justify-self: end; gap: var(--smrt-spacing-1); min-inline-size: min(100%, 18rem); margin: 0; font-variant-numeric: tabular-nums; }
|
|
134
174
|
.smrt-line-items__total { display: flex; justify-content: space-between; gap: var(--smrt-spacing-4); }
|
|
135
175
|
.smrt-line-items__total dt { color: var(--smrt-color-on-surface-variant); }
|
|
176
|
+
.smrt-line-items__total--muted { color: var(--smrt-color-on-surface-variant); font-size: var(--smrt-typography-body-small-size); }
|
|
136
177
|
.smrt-line-items__total dd { margin: 0; text-align: end; }
|
|
137
178
|
.smrt-line-items__total--grand { padding-block-start: var(--smrt-spacing-2); border-block-start: var(--smrt-hairline); font-weight: var(--smrt-typography-weight-semibold); }
|
|
138
179
|
.smrt-line-items__total--grand dt { color: var(--smrt-color-on-surface); }
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LineItemsWidget.svelte.d.ts","sourceRoot":"","sources":["../../../../src/components/overview/widgets/LineItemsWidget.svelte.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EAAY,KAAK,mBAAmB,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"LineItemsWidget.svelte.d.ts","sourceRoot":"","sources":["../../../../src/components/overview/widgets/LineItemsWidget.svelte.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EAAY,KAAK,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAgK/D,QAAA,MAAM,eAAe,+EAAwC,CAAC;AAC9D,KAAK,eAAe,GAAG,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC;AAC1D,eAAe,eAAe,CAAC"}
|
|
@@ -130,6 +130,23 @@ export interface LineItemsWidgetData {
|
|
|
130
130
|
tax?: number | null;
|
|
131
131
|
total?: number | null;
|
|
132
132
|
};
|
|
133
|
+
/** Frozen document-money snapshot supplied by a domain host. */
|
|
134
|
+
storedTotals?: {
|
|
135
|
+
subtotal: number;
|
|
136
|
+
discount: number;
|
|
137
|
+
tax: number;
|
|
138
|
+
total: number;
|
|
139
|
+
lineAmountType: 'exclusive' | 'inclusive' | 'none';
|
|
140
|
+
roundingScope: 'line' | 'document';
|
|
141
|
+
showNetSubtotal?: boolean;
|
|
142
|
+
taxes: readonly {
|
|
143
|
+
taxComponentId: string;
|
|
144
|
+
name: string;
|
|
145
|
+
percent: string;
|
|
146
|
+
taxable: number;
|
|
147
|
+
tax: number;
|
|
148
|
+
}[];
|
|
149
|
+
};
|
|
133
150
|
currency?: string;
|
|
134
151
|
/** Footer values over every line (money in minor units). */
|
|
135
152
|
summaries?: Record<string, number>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"data.d.ts","sourceRoot":"","sources":["../../../../src/components/overview/widgets/data.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"data.d.ts","sourceRoot":"","sources":["../../../../src/components/overview/widgets/data.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAGtD,oEAAoE;AACpE,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,iBAAiB,CAAC;IAC3B,iCAAiC;IACjC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iEAAiE;IACjE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,sEAAsE;IACtE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,qFAAqF;AACrF,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC3C,MAAM,CAAC,EAAE,iBAAiB,CAAC;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAED,mDAAmD;AACnD,MAAM,MAAM,gBAAgB,GACxB,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,GACT,OAAO,GACP,MAAM,CAAC;AAEX;;;;;;GAMG;AACH,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB;;;;OAIG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,iFAAiF;AACjF,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjC;AAED;;;;GAIG;AACH,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,aAAa,EAAE,CAAC;IACtB,qDAAqD;IACrD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,6BAA6B;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,2EAA2E;IAC3E,OAAO,CAAC,EAAE,gBAAgB,EAAE,CAAC;IAC7B,sDAAsD;IACtD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qFAAqF;IACrF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACpC;AAED,qEAAqE;AACrE,MAAM,WAAW,gBAAgB;IAC/B,8DAA8D;IAC9D,GAAG,EAAE,MAAM,CAAC;IACZ,4DAA4D;IAC5D,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,aAAa,EAAE,CAAC;IACtB,uEAAuE;IACvE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,gBAAgB,EAAE,CAAC;IAC5B,qCAAqC;IACrC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,uEAAuE;IACvE,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACpC;AAED,8EAA8E;AAC9E,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,gBAAgB,EAAE,CAAC;CAC1B;AAED;;;;;GAKG;AACH,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,aAAa,EAAE,CAAC;IACtB,OAAO,EAAE,gBAAgB,EAAE,CAAC;IAC5B,8DAA8D;IAC9D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,2DAA2D;IAC3D,MAAM,CAAC,EAAE;QACP,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QACzB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QACzB,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QACpB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;KACvB,CAAC;IACF,gEAAgE;IAChE,YAAY,CAAC,EAAE;QACb,QAAQ,EAAE,MAAM,CAAC;QACjB,QAAQ,EAAE,MAAM,CAAC;QACjB,GAAG,EAAE,MAAM,CAAC;QACZ,KAAK,EAAE,MAAM,CAAC;QACd,cAAc,EAAE,WAAW,GAAG,WAAW,GAAG,MAAM,CAAC;QACnD,aAAa,EAAE,MAAM,GAAG,UAAU,CAAC;QACnC,eAAe,CAAC,EAAE,OAAO,CAAC;QAC1B,KAAK,EAAE,SAAS;YACd,cAAc,EAAE,MAAM,CAAC;YACvB,IAAI,EAAE,MAAM,CAAC;YACb,OAAO,EAAE,MAAM,CAAC;YAChB,OAAO,EAAE,MAAM,CAAC;YAChB,GAAG,EAAE,MAAM,CAAC;SACb,EAAE,CAAC;KACL,CAAC;IACF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4DAA4D;IAC5D,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,0BAA0B;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,qFAAqF;AACrF,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,6CAA6C;AAC7C,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,CAAC,aAAa,GAAG;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,EAAE,CAAC;CAC3C;AAED,sEAAsE;AACtE,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,SAAS;QACd,EAAE,EAAE,MAAM,CAAC;QACX,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,CAAC,EAAE,OAAO,CAAC;QACjB,IAAI,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,IAAI,CAAC,EAAE,MAAM,CAAC;YAAC,WAAW,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;KAC7D,EAAE,CAAC;CACL;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,SAAS,kBAAkB,EAAE,EACvC,SAAS,CAAC,EAAE,MAAM,GACjB,mBAAmB,CAoBrB;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAEzE"}
|
|
@@ -16,6 +16,41 @@ export interface LineItemsTotals {
|
|
|
16
16
|
tax?: number | null;
|
|
17
17
|
total?: number | null;
|
|
18
18
|
}
|
|
19
|
+
/** A frozen per-component tax row supplied by a domain host. */
|
|
20
|
+
export interface StoredTaxComponent {
|
|
21
|
+
taxComponentId: string;
|
|
22
|
+
name: string;
|
|
23
|
+
percent: string;
|
|
24
|
+
taxable: number;
|
|
25
|
+
tax: number;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Authoritative document-money snapshot supplied by a domain host. The widget
|
|
29
|
+
* displays these persisted values only: it never derives tax or totals from
|
|
30
|
+
* the visible line page.
|
|
31
|
+
*/
|
|
32
|
+
export interface StoredLineItemsTotals extends LineItemsTotals {
|
|
33
|
+
subtotal: number;
|
|
34
|
+
discount: number;
|
|
35
|
+
tax: number;
|
|
36
|
+
total: number;
|
|
37
|
+
lineAmountType: 'exclusive' | 'inclusive' | 'none';
|
|
38
|
+
roundingScope: 'line' | 'document';
|
|
39
|
+
/** Whether an inclusive taxed document should expose its net subtotal. */
|
|
40
|
+
showNetSubtotal?: boolean;
|
|
41
|
+
taxes: readonly StoredTaxComponent[];
|
|
42
|
+
}
|
|
43
|
+
/** A persisted component can occur through more than one tax code. */
|
|
44
|
+
export interface StoredTaxComponentGroup extends StoredTaxComponent {
|
|
45
|
+
}
|
|
46
|
+
/** Whether untrusted widget data is a complete persisted money snapshot. */
|
|
47
|
+
export declare function isStoredLineItemsTotals(value: unknown): value is StoredLineItemsTotals;
|
|
48
|
+
/**
|
|
49
|
+
* Group exact persisted rows only when they identify the same component,
|
|
50
|
+
* display name, and percent. Components sharing a display label/rate remain
|
|
51
|
+
* separate; this does not calculate or reallocate tax.
|
|
52
|
+
*/
|
|
53
|
+
export declare function groupStoredTaxComponents(taxes: readonly StoredTaxComponent[]): StoredTaxComponentGroup[];
|
|
19
54
|
export type LineTotalKey = 'subtotal' | 'discount' | 'tax' | 'total';
|
|
20
55
|
export interface LineTotalLine {
|
|
21
56
|
key: LineTotalKey;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"line-totals.d.ts","sourceRoot":"","sources":["../../../../src/components/overview/widgets/line-totals.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,wFAAwF;AACxF,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAED,MAAM,MAAM,YAAY,GAAG,UAAU,GAAG,UAAU,GAAG,KAAK,GAAG,OAAO,CAAC;AAErE,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,YAAY,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,uFAAuF;IACvF,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,kBAAkB;IACjC,iDAAiD;IACjD,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC;IAC5B,0BAA0B;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,gDAAgD;IAChD,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,gBAAgB;IAC/B,6EAA6E;IAC7E,KAAK,EAAE,aAAa,EAAE,CAAC;IACvB,oEAAoE;IACpE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,QAAQ,EAAE,kBAAkB,GAAG,IAAI,CAAC;CACrC;AAQD,yFAAyF;AACzF,wBAAgB,cAAc,CAAC,OAAO,EAAE,SAAS,OAAO,EAAE,GAAG,MAAM,GAAG,IAAI,CAUzE;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,eAAe,GAAG,SAAS,EACnC,OAAO,EAAE,MAAM,GAAG,IAAI,GACrB,gBAAgB,CA2DlB"}
|
|
1
|
+
{"version":3,"file":"line-totals.d.ts","sourceRoot":"","sources":["../../../../src/components/overview/widgets/line-totals.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,wFAAwF;AACxF,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAED,gEAAgE;AAChE,MAAM,WAAW,kBAAkB;IACjC,cAAc,EAAE,MAAM,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;CACb;AAED;;;;GAIG;AACH,MAAM,WAAW,qBAAsB,SAAQ,eAAe;IAC5D,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,cAAc,EAAE,WAAW,GAAG,WAAW,GAAG,MAAM,CAAC;IACnD,aAAa,EAAE,MAAM,GAAG,UAAU,CAAC;IACnC,0EAA0E;IAC1E,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,KAAK,EAAE,SAAS,kBAAkB,EAAE,CAAC;CACtC;AAED,sEAAsE;AACtE,MAAM,WAAW,uBAAwB,SAAQ,kBAAkB;CAAG;AAEtE,4EAA4E;AAC5E,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,OAAO,GACb,KAAK,IAAI,qBAAqB,CAchC;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,SAAS,kBAAkB,EAAE,GACnC,uBAAuB,EAAE,CA0B3B;AAED,MAAM,MAAM,YAAY,GAAG,UAAU,GAAG,UAAU,GAAG,KAAK,GAAG,OAAO,CAAC;AAErE,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,YAAY,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,uFAAuF;IACvF,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,kBAAkB;IACjC,iDAAiD;IACjD,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC;IAC5B,0BAA0B;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,gDAAgD;IAChD,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,gBAAgB;IAC/B,6EAA6E;IAC7E,KAAK,EAAE,aAAa,EAAE,CAAC;IACvB,oEAAoE;IACpE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,QAAQ,EAAE,kBAAkB,GAAG,IAAI,CAAC;CACrC;AAQD,yFAAyF;AACzF,wBAAgB,cAAc,CAAC,OAAO,EAAE,SAAS,OAAO,EAAE,GAAG,MAAM,GAAG,IAAI,CAUzE;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,eAAe,GAAG,SAAS,EACnC,OAAO,EAAE,MAAM,GAAG,IAAI,GACrB,gBAAgB,CA2DlB"}
|
|
@@ -9,6 +9,51 @@
|
|
|
9
9
|
*
|
|
10
10
|
* Money is integer minor units throughout.
|
|
11
11
|
*/
|
|
12
|
+
/** Whether untrusted widget data is a complete persisted money snapshot. */
|
|
13
|
+
export function isStoredLineItemsTotals(value) {
|
|
14
|
+
if (!value || typeof value !== 'object' || Array.isArray(value))
|
|
15
|
+
return false;
|
|
16
|
+
const record = value;
|
|
17
|
+
return ((record.lineAmountType === 'exclusive' ||
|
|
18
|
+
record.lineAmountType === 'inclusive' ||
|
|
19
|
+
record.lineAmountType === 'none') &&
|
|
20
|
+
(record.roundingScope === 'line' || record.roundingScope === 'document') &&
|
|
21
|
+
Number.isSafeInteger(record.subtotal) &&
|
|
22
|
+
Number.isSafeInteger(record.discount) &&
|
|
23
|
+
Number.isSafeInteger(record.tax) &&
|
|
24
|
+
Number.isSafeInteger(record.total) &&
|
|
25
|
+
Array.isArray(record.taxes));
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Group exact persisted rows only when they identify the same component,
|
|
29
|
+
* display name, and percent. Components sharing a display label/rate remain
|
|
30
|
+
* separate; this does not calculate or reallocate tax.
|
|
31
|
+
*/
|
|
32
|
+
export function groupStoredTaxComponents(taxes) {
|
|
33
|
+
const groups = new Map();
|
|
34
|
+
for (const tax of taxes) {
|
|
35
|
+
if (!tax ||
|
|
36
|
+
typeof tax.taxComponentId !== 'string' ||
|
|
37
|
+
typeof tax.name !== 'string' ||
|
|
38
|
+
typeof tax.percent !== 'string' ||
|
|
39
|
+
!Number.isSafeInteger(tax.taxable) ||
|
|
40
|
+
!Number.isSafeInteger(tax.tax))
|
|
41
|
+
continue;
|
|
42
|
+
const key = `${tax.taxComponentId}\u0000${tax.name}\u0000${tax.percent}`;
|
|
43
|
+
const existing = groups.get(key);
|
|
44
|
+
if (!existing) {
|
|
45
|
+
groups.set(key, { ...tax });
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
const taxable = existing.taxable + tax.taxable;
|
|
49
|
+
const amount = existing.tax + tax.tax;
|
|
50
|
+
if (!Number.isSafeInteger(taxable) || !Number.isSafeInteger(amount))
|
|
51
|
+
continue;
|
|
52
|
+
existing.taxable = taxable;
|
|
53
|
+
existing.tax = amount;
|
|
54
|
+
}
|
|
55
|
+
return [...groups.values()];
|
|
56
|
+
}
|
|
12
57
|
function money(value) {
|
|
13
58
|
return typeof value === 'number' && Number.isSafeInteger(value)
|
|
14
59
|
? value
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
import type { ScreenRelation } from '../../screens/relations.js';
|
|
19
19
|
import type { OverviewOptions, WidgetLoad } from '../types.js';
|
|
20
20
|
import { type LineItemsWidgetData, type RecordListWidgetData, type RelatedWidgetData } from './data.js';
|
|
21
|
-
import type { LineItemsTotals } from './line-totals.js';
|
|
21
|
+
import type { LineItemsTotals, StoredLineItemsTotals } from './line-totals.js';
|
|
22
22
|
/** Rows per tab by default. */
|
|
23
23
|
export declare const RELATED_WIDGET_LIMIT = 5;
|
|
24
24
|
/** At most this many relations (tabs) one `related` widget lists. */
|
|
@@ -35,6 +35,8 @@ export interface RecordWidgetsOptions {
|
|
|
35
35
|
* (read when the widget loads; `RecordScreen` reads them by role).
|
|
36
36
|
*/
|
|
37
37
|
totals?: () => LineItemsTotals | undefined;
|
|
38
|
+
/** Frozen document-money snapshot. It is rendered without recalculation. */
|
|
39
|
+
storedTotals?: () => StoredLineItemsTotals | undefined;
|
|
38
40
|
/** `line-items`: the currency of the parent's amounts. */
|
|
39
41
|
currency?: () => string | undefined;
|
|
40
42
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"record-loaders.d.ts","sourceRoot":"","sources":["../../../../src/components/overview/widgets/record-loaders.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAEjE,OAAO,KAAK,EACV,eAAe,EACf,UAAU,EAEX,MAAM,aAAa,CAAC;AACrB,OAAO,EAEL,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EACzB,KAAK,iBAAiB,EAEvB,MAAM,WAAW,CAAC;AACnB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"record-loaders.d.ts","sourceRoot":"","sources":["../../../../src/components/overview/widgets/record-loaders.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAEjE,OAAO,KAAK,EACV,eAAe,EACf,UAAU,EAEX,MAAM,aAAa,CAAC;AACrB,OAAO,EAEL,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EACzB,KAAK,iBAAiB,EAEvB,MAAM,WAAW,CAAC;AACnB,OAAO,KAAK,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AAQ/E,+BAA+B;AAC/B,eAAO,MAAM,oBAAoB,IAAI,CAAC;AACtC,qEAAqE;AACrE,eAAO,MAAM,uBAAuB,KAAK,CAAC;AAE1C,MAAM,WAAW,oBAAoB;IACnC,wDAAwD;IACxD,SAAS,EAAE,SAAS,cAAc,EAAE,CAAC;IACrC,+EAA+E;IAC/E,OAAO,EAAE,UAAU,CAAC,oBAAoB,CAAC,CAAC;IAC1C,8DAA8D;IAC9D,WAAW,CAAC,EAAE,CAAC,QAAQ,EAAE,cAAc,KAAK,MAAM,GAAG,SAAS,CAAC;IAC/D;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,eAAe,GAAG,SAAS,CAAC;IAC3C,4EAA4E;IAC5E,YAAY,CAAC,EAAE,MAAM,qBAAqB,GAAG,SAAS,CAAC;IACvD,0DAA0D;IAC1D,QAAQ,CAAC,EAAE,MAAM,MAAM,GAAG,SAAS,CAAC;CACrC;AAED,kEAAkE;AAClE,eAAO,MAAM,gBAAgB,KAAK,CAAC;AAEnC,6FAA6F;AAC7F,wBAAgB,gBAAgB,CAC9B,SAAS,EAAE,SAAS,cAAc,EAAE,EACpC,IAAI,EAAE,SAAS,MAAM,EAAE,GACtB,cAAc,EAAE,CAMlB;AAED,uDAAuD;AACvD,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,cAAc,EACxB,KAAK,EAAE,MAAM,GACZ,eAAe,CAWjB;AA2CD;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,oBAAoB,GAC5B,UAAU,CAAC,iBAAiB,CAAC,CAkC/B;AAED,uFAAuF;AACvF,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,SAAS,cAAc,EAAE,EACpC,GAAG,EAAE,OAAO,GACX,cAAc,GAAG,SAAS,CAM5B;AAED,6DAA6D;AAC7D,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,cAAc,EACxB,KAAK,EAAE,MAAM,GACZ,eAAe,CAWjB;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,oBAAoB,GAC5B,UAAU,CAAC,mBAAmB,CAAC,CAoCjC"}
|
|
@@ -126,9 +126,15 @@ export function createLineItemsLoader(options) {
|
|
|
126
126
|
return async (widgetOptions, ctx) => {
|
|
127
127
|
const relation = lineItemsRelation(options.relations, widgetOptions.relation);
|
|
128
128
|
const totals = options.totals?.();
|
|
129
|
+
const storedTotals = options.storedTotals?.();
|
|
129
130
|
const currency = options.currency?.();
|
|
130
131
|
if (!relation) {
|
|
131
|
-
return {
|
|
132
|
+
return {
|
|
133
|
+
rows: [],
|
|
134
|
+
columns: [],
|
|
135
|
+
...(totals ? { totals } : {}),
|
|
136
|
+
...(storedTotals ? { storedTotals } : {}),
|
|
137
|
+
};
|
|
132
138
|
}
|
|
133
139
|
const limit = typeof widgetOptions.limit === 'number'
|
|
134
140
|
? widgetOptions.limit
|
|
@@ -140,6 +146,7 @@ export function createLineItemsLoader(options) {
|
|
|
140
146
|
columns: tab.columns,
|
|
141
147
|
...(tab.total !== undefined ? { total: tab.total } : {}),
|
|
142
148
|
...(totals ? { totals } : {}),
|
|
149
|
+
...(storedTotals ? { storedTotals } : {}),
|
|
143
150
|
...((tab.currency ?? currency)
|
|
144
151
|
? { currency: tab.currency ?? currency }
|
|
145
152
|
: {}),
|
|
@@ -74,6 +74,7 @@ let {
|
|
|
74
74
|
title,
|
|
75
75
|
fields,
|
|
76
76
|
currency,
|
|
77
|
+
lineItemStoredTotals,
|
|
77
78
|
locale,
|
|
78
79
|
backLabel,
|
|
79
80
|
deleting = false,
|
|
@@ -152,6 +153,7 @@ const widgetRegistry = untrack(() => {
|
|
|
152
153
|
records,
|
|
153
154
|
viewAllHref: (relation) => viewAllHref?.(relation),
|
|
154
155
|
totals: () => recordTotals(record, roles, viewFields),
|
|
156
|
+
storedTotals: () => lineItemStoredTotals?.(),
|
|
155
157
|
currency: () => recordCurrency,
|
|
156
158
|
});
|
|
157
159
|
for (const def of recordWidgets.list()) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RecordScreen.svelte.d.ts","sourceRoot":"","sources":["../../../src/components/screens/RecordScreen.svelte.ts"],"names":[],"mappings":"AAwDA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"RecordScreen.svelte.d.ts","sourceRoot":"","sources":["../../../src/components/screens/RecordScreen.svelte.ts"],"names":[],"mappings":"AAwDA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAoVpD,QAAA,MAAM,YAAY,uDAAwC,CAAC;AAC3D,KAAK,YAAY,GAAG,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC;AACpD,eAAe,YAAY,CAAC"}
|
|
@@ -3,6 +3,7 @@ import type { WidgetRegistry } from '../overview/registry.js';
|
|
|
3
3
|
import type { OverviewDefinition, OverviewOverride, WidgetLoadContext } from '../overview/types.js';
|
|
4
4
|
import type { CoreWidgetLoaders } from '../overview/widgets/core.js';
|
|
5
5
|
import type { RecordStatusTone } from '../overview/widgets/data.js';
|
|
6
|
+
import type { StoredLineItemsTotals } from '../overview/widgets/line-totals.js';
|
|
6
7
|
import type { ScreenRelation } from './relations.js';
|
|
7
8
|
import type { FieldRole } from './roles.js';
|
|
8
9
|
/**
|
|
@@ -317,6 +318,12 @@ export interface RecordScreenProps {
|
|
|
317
318
|
fields?: readonly string[];
|
|
318
319
|
/** ISO 4217 code used by money fields. */
|
|
319
320
|
currency?: string;
|
|
321
|
+
/**
|
|
322
|
+
* Frozen document-money snapshot for the line-items widget. The host reads
|
|
323
|
+
* its own persisted rows (including per-component tax); this screen never
|
|
324
|
+
* recalculates them from visible lines.
|
|
325
|
+
*/
|
|
326
|
+
lineItemStoredTotals?: () => StoredLineItemsTotals | undefined;
|
|
320
327
|
/** BCP-47 locale for number and date formatting. */
|
|
321
328
|
locale?: string;
|
|
322
329
|
/** Label for the back action; defaults to the pluralized class name. */
|
|
@@ -391,6 +398,6 @@ export interface RecipeScreensProps {
|
|
|
391
398
|
*/
|
|
392
399
|
definitions?: Readonly<Record<string, ScreenCollectionDefinition>>;
|
|
393
400
|
/** Passed to `RecordScreen` for the record view and edit. */
|
|
394
|
-
record?: Pick<RecordScreenProps, 'loaders' | 'registry' | 'widgetContext' | 'overview' | 'override' | 'onoverviewchange' | 'layoutEditing' | 'canCustomize' | 'hrefFor' | 'labels' | 'viewAllHref' | 'statusTones'>;
|
|
401
|
+
record?: Pick<RecordScreenProps, 'loaders' | 'registry' | 'widgetContext' | 'overview' | 'override' | 'onoverviewchange' | 'layoutEditing' | 'canCustomize' | 'hrefFor' | 'labels' | 'viewAllHref' | 'lineItemStoredTotals' | 'statusTones'>;
|
|
395
402
|
}
|
|
396
403
|
//# sourceMappingURL=types.d.ts.map
|