@bazous/ui 0.3.2

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 (40) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +150 -0
  3. package/dist/answers/AnswerPicture.d.ts +13 -0
  4. package/dist/answers/contract.d.ts +160 -0
  5. package/dist/answers/draw.d.ts +16 -0
  6. package/dist/answers/index.d.ts +6 -0
  7. package/dist/answers/messages.d.ts +3 -0
  8. package/dist/answers.js +10 -0
  9. package/dist/answers.js.map +1 -0
  10. package/dist/canvas/index.d.ts +32 -0
  11. package/dist/canvas.js +285 -0
  12. package/dist/canvas.js.map +1 -0
  13. package/dist/contract/snapshot.d.ts +173 -0
  14. package/dist/engine/scenario.d.ts +40 -0
  15. package/dist/format/index.d.ts +37 -0
  16. package/dist/i18n/index.d.ts +25 -0
  17. package/dist/i18n/shared.d.ts +3 -0
  18. package/dist/index-yeBMtDf1.js +649 -0
  19. package/dist/index-yeBMtDf1.js.map +1 -0
  20. package/dist/index.d.ts +20 -0
  21. package/dist/index.js +1258 -0
  22. package/dist/index.js.map +1 -0
  23. package/dist/modules/Question.d.ts +18 -0
  24. package/dist/modules/available-now/index.d.ts +8 -0
  25. package/dist/modules/due-before-payday/index.d.ts +9 -0
  26. package/dist/modules/low-point/index.d.ts +12 -0
  27. package/dist/modules/margin-after-payday/index.d.ts +9 -0
  28. package/dist/modules/monthly-structure/index.d.ts +24 -0
  29. package/dist/modules/next-actions/index.d.ts +13 -0
  30. package/dist/modules/pay-cycles/index.d.ts +31 -0
  31. package/dist/modules/registry.d.ts +7 -0
  32. package/dist/modules/types.d.ts +77 -0
  33. package/dist/modules/what-if/index.d.ts +6 -0
  34. package/dist/primitives/CashflowChart.d.ts +22 -0
  35. package/dist/primitives/index.d.ts +57 -0
  36. package/dist/styles.css +1 -0
  37. package/package.json +84 -0
  38. package/schema/answers.schema.json +719 -0
  39. package/schema/canvas.json +181 -0
  40. package/schema/snapshot.schema.json +821 -0
@@ -0,0 +1,649 @@
1
+ const we = [
2
+ "runway",
3
+ "valley",
4
+ "shift",
5
+ "days",
6
+ "balance",
7
+ "countdown",
8
+ "horizon",
9
+ "calendar",
10
+ "leak",
11
+ "jar",
12
+ "gauge",
13
+ "deadline"
14
+ ], H = (i) => {
15
+ if (i == null || i === "") return 0;
16
+ const t = typeof i == "number" ? i : Number(i);
17
+ return Number.isFinite(t) ? t : 0;
18
+ }, $e = "’", ke = "−";
19
+ function T(i, t = 0) {
20
+ const d = H(i), r = Math.abs(d).toFixed(t), [a = "0", s] = r.split("."), g = a.replace(/\B(?=(\d{3})+(?!\d))/g, "’"), _ = s ? `${g}.${s}` : g, k = Number(r);
21
+ return d < 0 && k !== 0 ? `−${_}` : _;
22
+ }
23
+ function se(i, t = 0) {
24
+ const d = H(i), r = T(Math.abs(d), t);
25
+ return Number(Math.abs(d).toFixed(t)) === 0 ? r : d < 0 ? `−${r}` : `+${r}`;
26
+ }
27
+ function oe(i, t, d = 2) {
28
+ return `${T(i, d)} ${t}`;
29
+ }
30
+ function j(i) {
31
+ const [t, d, r] = i.slice(0, 10).split("-").map(Number);
32
+ return new Date(t ?? 1970, (d ?? 1) - 1, r ?? 1);
33
+ }
34
+ function le(i) {
35
+ const t = (d) => String(d).padStart(2, "0");
36
+ return `${i.getFullYear()}-${t(i.getMonth() + 1)}-${t(i.getDate())}`;
37
+ }
38
+ function Me(i, t) {
39
+ const d = j(i);
40
+ return d.setDate(d.getDate() + t), le(d);
41
+ }
42
+ function De(i, t) {
43
+ return Math.round((j(t).getTime() - j(i).getTime()) / 864e5);
44
+ }
45
+ function w(i) {
46
+ if (!i) return "—";
47
+ const [, t, d] = i.slice(0, 10).split("-");
48
+ return `${d}.${t}`;
49
+ }
50
+ function ce(i, t) {
51
+ if (i === t) return w(i);
52
+ const [, d, r] = i.split("-"), [, a, s] = t.split("-");
53
+ return d === a ? `${r}–${s}` : `${r}.${d}–${s}.${a}`;
54
+ }
55
+ const B = {
56
+ fr: { short: ["dim.", "lun.", "mar.", "mer.", "jeu.", "ven.", "sam."], long: ["dimanche", "lundi", "mardi", "mercredi", "jeudi", "vendredi", "samedi"] },
57
+ de: { short: ["So", "Mo", "Di", "Mi", "Do", "Fr", "Sa"], long: ["Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag"] },
58
+ it: { short: ["dom", "lun", "mar", "mer", "gio", "ven", "sab"], long: ["domenica", "lunedì", "martedì", "mercoledì", "giovedì", "venerdì", "sabato"] },
59
+ rm: { short: ["du", "gli", "ma", "me", "gie", "ve", "so"], long: ["dumengia", "glindesdi", "mardi", "mesemna", "gievgia", "venderdi", "sonda"] },
60
+ en: { short: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], long: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"] }
61
+ }, de = {
62
+ fr: ["janvier", "février", "mars", "avril", "mai", "juin", "juillet", "août", "septembre", "octobre", "novembre", "décembre"],
63
+ de: ["Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember"],
64
+ it: ["gennaio", "febbraio", "marzo", "aprile", "maggio", "giugno", "luglio", "agosto", "settembre", "ottobre", "novembre", "dicembre"],
65
+ rm: ["schaner", "favrer", "mars", "avrigl", "matg", "zercladur", "fanadur", "avust", "settember", "october", "november", "december"],
66
+ en: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]
67
+ };
68
+ function he(i, t) {
69
+ const d = B[i].long[t.getDay()] ?? "", r = de[i][t.getMonth()] ?? "", a = t.getDate();
70
+ switch (i) {
71
+ case "fr":
72
+ return `${d} ${a === 1 ? "1er" : a} ${r}`;
73
+ case "de":
74
+ return `${d}, ${a}. ${r}`;
75
+ case "it":
76
+ return `${d} ${a} ${r}`;
77
+ case "rm":
78
+ return `${d}, ${a} ${/^[aeiou]/.test(r) ? "d’" : "da "}${r}`;
79
+ case "en":
80
+ return `${d} ${a} ${r}`;
81
+ }
82
+ }
83
+ function _e(i) {
84
+ const t = (d) => d.charAt(0).toUpperCase() + d.slice(1);
85
+ return {
86
+ locale: i,
87
+ num: T,
88
+ signed: se,
89
+ money: oe,
90
+ shortDate: w,
91
+ dateSpan: ce,
92
+ longDate: (d) => t(he(i, j(d))),
93
+ weekday: (d) => B[i].short[j(d).getDay()] ?? ""
94
+ };
95
+ }
96
+ function Se(i) {
97
+ const t = H(i);
98
+ return t < 0 ? "neg" : t > 0 ? "pos" : "flat";
99
+ }
100
+ const ve = ["fr", "de", "it", "rm", "en"], ze = {
101
+ fr: "Français",
102
+ de: "Deutsch",
103
+ it: "Italiano",
104
+ rm: "Rumantsch",
105
+ en: "English"
106
+ }, fe = {
107
+ fr: "fr-CH",
108
+ de: "de-CH",
109
+ it: "it-CH",
110
+ rm: "rm-CH",
111
+ en: "en-CH"
112
+ };
113
+ function ue(i) {
114
+ return typeof i == "string" && ve.includes(i);
115
+ }
116
+ function Ae(i, t = "fr") {
117
+ for (const d of i ?? []) {
118
+ const r = d.toLowerCase().split(/[-_]/)[0];
119
+ if (ue(r)) return r;
120
+ }
121
+ return t;
122
+ }
123
+ function Y(i, t) {
124
+ return t ? i.replace(/\{(\w+)\}/g, (d, r) => r in t ? String(t[r]) : d) : i;
125
+ }
126
+ function ye(i, ...t) {
127
+ const d = Object.assign({}, ...t.map((a) => a[i])), r = new Intl.PluralRules(fe[i]);
128
+ return (a, s) => {
129
+ if (s && typeof s.n == "number") {
130
+ const _ = `${a}.${r.select(s.n)}`, k = `${a}.other`, S = d[_] ?? d[k];
131
+ if (S !== void 0) return Y(S, s);
132
+ }
133
+ const g = d[a];
134
+ return g === void 0 ? `⟦${a}⟧` : Y(g, s);
135
+ };
136
+ }
137
+ const me = {
138
+ fr: {
139
+ "vis.today": "aujourd’hui",
140
+ "vis.payday": "salaire",
141
+ "vis.available": "dispo",
142
+ "vis.short": "manque",
143
+ "vis.left": "reste",
144
+ "vis.in": "entre",
145
+ "vis.out": "sort",
146
+ "vis.until": "jusqu’au",
147
+ "vis.dayUnit": "j",
148
+ "vis.perMonth": "/ mois",
149
+ "vis.before": "avant",
150
+ "vis.after": "après",
151
+ "vis.days": "{covered} / {target} jours",
152
+ "vis.bills.one": "{n} facture · {total}",
153
+ "vis.bills.other": "{n} factures · {total}",
154
+ "vis.fixedDays": "= {days} j de charges fixes",
155
+ "vis.inDays": "dans {days} j",
156
+ "vis.perYear": "/ an",
157
+ "vis.years.one": "{n} an",
158
+ "vis.years.other": "{n} ans",
159
+ "vis.bill": "bordereau",
160
+ "vis.perDay": "/ jour",
161
+ "vis.paid": "versé",
162
+ "vis.limit": "plafond",
163
+ "vis.letter": "lettre avant le",
164
+ "vis.ends": "fin",
165
+ "vis.renewal": "renouvellement",
166
+ "vis.more": "+{n}",
167
+ "vis.months": "12 mois"
168
+ },
169
+ de: {
170
+ "vis.today": "heute",
171
+ "vis.payday": "Lohn",
172
+ "vis.available": "verfügbar",
173
+ "vis.short": "fehlt",
174
+ "vis.left": "bleibt",
175
+ "vis.in": "rein",
176
+ "vis.out": "raus",
177
+ "vis.until": "bis",
178
+ "vis.dayUnit": "T",
179
+ "vis.perMonth": "/ Monat",
180
+ "vis.before": "vorher",
181
+ "vis.after": "nachher",
182
+ "vis.days": "{covered} / {target} Tage",
183
+ "vis.bills.one": "{n} Rechnung · {total}",
184
+ "vis.bills.other": "{n} Rechnungen · {total}",
185
+ "vis.fixedDays": "= {days} T Fixkosten",
186
+ "vis.inDays": "in {days} T",
187
+ "vis.perYear": "/ Jahr",
188
+ "vis.years.one": "{n} Jahr",
189
+ "vis.years.other": "{n} Jahre",
190
+ "vis.bill": "Steuerrechnung",
191
+ "vis.perDay": "/ Tag",
192
+ "vis.paid": "eingezahlt",
193
+ "vis.limit": "Maximum",
194
+ "vis.letter": "Brief vor dem",
195
+ "vis.ends": "Ende",
196
+ "vis.renewal": "Verlängerung",
197
+ "vis.more": "+{n}",
198
+ "vis.months": "12 Monate"
199
+ },
200
+ it: {
201
+ "vis.today": "oggi",
202
+ "vis.payday": "stipendio",
203
+ "vis.available": "disponibile",
204
+ "vis.short": "manca",
205
+ "vis.left": "resta",
206
+ "vis.in": "entra",
207
+ "vis.out": "esce",
208
+ "vis.until": "fino al",
209
+ "vis.dayUnit": "g",
210
+ "vis.perMonth": "/ mese",
211
+ "vis.before": "prima",
212
+ "vis.after": "dopo",
213
+ "vis.days": "{covered} / {target} giorni",
214
+ "vis.bills.one": "{n} fattura · {total}",
215
+ "vis.bills.other": "{n} fatture · {total}",
216
+ "vis.fixedDays": "= {days} g di spese fisse",
217
+ "vis.inDays": "tra {days} g",
218
+ "vis.perYear": "/ anno",
219
+ "vis.years.one": "{n} anno",
220
+ "vis.years.other": "{n} anni",
221
+ "vis.bill": "notifica",
222
+ "vis.perDay": "/ giorno",
223
+ "vis.paid": "versato",
224
+ "vis.limit": "massimo",
225
+ "vis.letter": "lettera prima del",
226
+ "vis.ends": "fine",
227
+ "vis.renewal": "rinnovo",
228
+ "vis.more": "+{n}",
229
+ "vis.months": "12 mesi"
230
+ },
231
+ rm: {
232
+ "vis.today": "oz",
233
+ "vis.payday": "paja",
234
+ "vis.available": "disponibel",
235
+ "vis.short": "manca",
236
+ "vis.left": "resta",
237
+ "vis.in": "entra",
238
+ "vis.out": "sorta",
239
+ "vis.until": "fin als",
240
+ "vis.dayUnit": "d",
241
+ "vis.perMonth": "/ mais",
242
+ "vis.before": "avant",
243
+ "vis.after": "suenter",
244
+ "vis.days": "{covered} / {target} dis",
245
+ "vis.bills.one": "{n} quint · {total}",
246
+ "vis.bills.other": "{n} quints · {total}",
247
+ "vis.fixedDays": "= {days} d custs fixs",
248
+ "vis.inDays": "en {days} d",
249
+ "vis.perYear": "/ onn",
250
+ "vis.years.one": "{n} onn",
251
+ "vis.years.other": "{n} onns",
252
+ "vis.bill": "quint da taglia",
253
+ "vis.perDay": "/ di",
254
+ "vis.paid": "pajà",
255
+ "vis.limit": "maximum",
256
+ "vis.letter": "brev avant ils",
257
+ "vis.ends": "fin",
258
+ "vis.renewal": "renovaziun",
259
+ "vis.more": "+{n}",
260
+ "vis.months": "12 mais"
261
+ },
262
+ en: {
263
+ "vis.today": "today",
264
+ "vis.payday": "payday",
265
+ "vis.available": "available",
266
+ "vis.short": "short",
267
+ "vis.left": "left",
268
+ "vis.in": "in",
269
+ "vis.out": "out",
270
+ "vis.until": "until",
271
+ "vis.dayUnit": "d",
272
+ "vis.perMonth": "/ month",
273
+ "vis.before": "before",
274
+ "vis.after": "after",
275
+ "vis.days": "{covered} / {target} days",
276
+ "vis.bills.one": "{n} bill · {total}",
277
+ "vis.bills.other": "{n} bills · {total}",
278
+ "vis.fixedDays": "= {days} d of fixed costs",
279
+ "vis.inDays": "in {days} d",
280
+ "vis.perYear": "/ year",
281
+ "vis.years.one": "{n} year",
282
+ "vis.years.other": "{n} years",
283
+ "vis.bill": "tax bill",
284
+ "vis.perDay": "/ day",
285
+ "vis.paid": "paid",
286
+ "vis.limit": "limit",
287
+ "vis.letter": "letter before",
288
+ "vis.ends": "ends",
289
+ "vis.renewal": "renewal",
290
+ "vis.more": "+{n}",
291
+ "vis.months": "12 months"
292
+ }
293
+ }, ge = "http://www.w3.org/2000/svg", m = 130, xe = 260, q = 320, n = {
294
+ ink: "var(--bz-text)",
295
+ muted: "var(--bz-muted)",
296
+ line: "var(--bz-control-line)",
297
+ accent: "var(--bz-accent)",
298
+ onAccent: "var(--bz-on-accent)",
299
+ negative: "var(--bz-negative)",
300
+ warning: "var(--bz-warning)",
301
+ positive: "var(--bz-positive)",
302
+ surface: "var(--bz-surface)"
303
+ }, p = (i) => Number(i ?? 0), x = (i) => T(i, 2), F = (i, t = 18) => i.length > t ? `${i.slice(0, t - 1).trimEnd()}…` : i;
304
+ function pe(i, t) {
305
+ const d = (s, g = {}, ..._) => {
306
+ const k = i.createElementNS(ge, s);
307
+ for (const [S, z] of Object.entries(g)) z != null && k.setAttribute(S, String(z));
308
+ for (const S of _.flat(1 / 0)) S && k.append(S);
309
+ return k;
310
+ };
311
+ return { sv: d, txt: (s, g, _, k = {}) => {
312
+ const S = d("text", { x: s, y: g, "font-size": 11, fill: n.muted, ...k });
313
+ return S.textContent = _, S;
314
+ }, frame: (s, ...g) => d("svg", { viewBox: `0 0 ${t} ${m}`, class: "bz-answer-visual", role: "img", "aria-label": s }, ...g) };
315
+ }
316
+ function C(i, t) {
317
+ const d = i.flat().map(([, z]) => p(z)), r = Math.min(0, ...d);
318
+ let a = Math.max(0, ...d);
319
+ r < 0 && a > -3 * r && (a = -1.6 * r);
320
+ const s = i[0].length, g = 8, _ = t - 8, k = 22, S = m - 22;
321
+ return {
322
+ n: s,
323
+ top: k,
324
+ hi: a,
325
+ x: (z) => g + z * (_ - g) / Math.max(s - 1, 1),
326
+ y: (z) => k + (a - Math.min(z, a)) * (S - k) / (a - r || 1)
327
+ };
328
+ }
329
+ const L = (i, t, d = (r) => r) => i.map(([, r], a) => `${t.x(a).toFixed(1)},${t.y(d(p(r))).toFixed(1)}`).join(" ");
330
+ function be(i, t, d, r) {
331
+ const { sv: a, txt: s, frame: g } = pe(d, r), _ = (e) => [
332
+ a("line", { x1: 8, x2: r - 8, y1: e, y2: e, stroke: n.line, "stroke-dasharray": "3 3" }),
333
+ s(r - 8, e - 4, "0", { "text-anchor": "end" })
334
+ ], k = (e, o) => {
335
+ const f = [];
336
+ return e.forEach(([, h], c) => {
337
+ const l = c ? p(e[c - 1][1]) : -1 / 0;
338
+ p(h) > o.hi && l <= o.hi && f.length < 2 && f.push(s(o.x(c), o.top - 8, `↑ ${x(h)}`, { "text-anchor": o.x(c) > r * 0.7 ? "end" : "start" }));
339
+ }), f;
340
+ }, S = (e) => [
341
+ s(8, m - 6, w(e[0][0])),
342
+ s(r - 8, m - 6, w(e[e.length - 1][0]), { "text-anchor": "end" })
343
+ ], z = (e) => {
344
+ const o = Date.parse(e.today), f = Math.max(Date.parse(e.payday) - o, 1), h = (b) => 14 + (Date.parse(b) - o) * (r - 28) / f, c = p(e.due), l = p(e.available), v = p(e.gap), u = r - 28, y = v < 0 && c > 0 ? Math.min(Math.max(l, 0) / c, 1) * u : u, M = e.bills.reduce((b, A) => b + p(A.amount), 0), $ = e.bills.length === 1 ? `${F(e.bills[0].label)} ${w(e.bills[0].date)}` : t("vis.bills", { n: e.bills.length, total: x(M) }), D = y > 110;
345
+ return g(
346
+ e.caption,
347
+ a("line", { x1: 14, x2: r - 14, y1: 30, y2: 30, stroke: n.line, "stroke-width": 2 }),
348
+ a("circle", { cx: 14, cy: 30, r: 5, fill: n.ink }),
349
+ s(8, 14, t("vis.today")),
350
+ a("circle", { cx: r - 14, cy: 30, r: 6, fill: n.positive }),
351
+ s(r - 8, 14, `${t("vis.payday")} ${w(e.payday)}`, { "text-anchor": "end", fill: n.positive }),
352
+ e.bills.map((b) => a("rect", { x: h(b.date) - 6, y: 24, width: 12, height: 12, rx: 3, fill: n.negative, stroke: n.surface, "stroke-width": 1 })),
353
+ e.bills.length > 0 && s(r / 2, 58, $, { "text-anchor": "middle", fill: n.negative }),
354
+ a("rect", { x: 14, y: 86, width: Math.max(y, 0), height: 20, rx: 3, fill: n.accent }),
355
+ v < 0 && a("rect", {
356
+ x: 14 + y,
357
+ y: 86,
358
+ width: u - y,
359
+ height: 20,
360
+ rx: 3,
361
+ fill: n.negative,
362
+ "fill-opacity": 0.16,
363
+ stroke: n.negative,
364
+ "stroke-dasharray": "4 3"
365
+ }),
366
+ s(
367
+ D ? 20 : 14,
368
+ D ? 100 : 80,
369
+ `${t("vis.available")} ${x(l)}`,
370
+ { fill: D ? n.onAccent : l < 0 ? n.negative : n.ink, "font-weight": 600 }
371
+ ),
372
+ v < 0 ? s(r - 20, 100, `${t("vis.short")} ${x(-v)}`, { "text-anchor": "end", fill: n.negative, "font-weight": 600 }) : s(r - 20, 100, `${t("vis.left")} ${x(v)}`, { "text-anchor": "end", fill: n.onAccent, "font-weight": 600 })
373
+ );
374
+ }, V = (e) => {
375
+ const o = C([e.series], r), f = o.y(0), h = Math.max(0, e.series.findIndex(([u]) => u === e.low.date)), c = o.x(h), l = o.y(p(e.low.balance)), v = c > r * 0.6;
376
+ return g(
377
+ e.caption,
378
+ a("polygon", {
379
+ points: `${o.x(0)},${f} ${L(e.series, o, (u) => Math.min(u, 0))} ${o.x(o.n - 1)},${f}`,
380
+ fill: n.negative,
381
+ "fill-opacity": 0.18
382
+ }),
383
+ _(f),
384
+ a("polyline", { points: L(e.series, o), fill: "none", stroke: n.ink, "stroke-width": 2, "stroke-linejoin": "round" }),
385
+ k(e.series, o),
386
+ a("circle", { cx: c, cy: l, r: 5, fill: n.negative }),
387
+ s(
388
+ c + (v ? -9 : 9),
389
+ Math.min(l + 4, m - 26),
390
+ `${x(e.low.balance)} · ${w(e.low.date)}`,
391
+ { "text-anchor": v ? "end" : "start", fill: n.negative, "font-weight": 600 }
392
+ ),
393
+ S(e.series)
394
+ );
395
+ }, X = (e) => {
396
+ const o = C([e.before, e.after], r), f = o.y(0), h = (ae) => {
397
+ const J = e.before.findIndex(([re]) => re === ae);
398
+ return o.x(J < 0 ? o.n - 1 : J);
399
+ }, c = h(e.move.from), l = h(e.move.to), v = F(e.move.label, 16), u = Math.min(v.length * 6 + 14, 120), y = Math.max(4, Math.min(c - u / 2, l - u - 12, r - 4 - u)), M = y + u + 8 < l - 4, $ = t("vis.before"), D = t("vis.after"), b = 14, A = 7, U = b + 4 + $.length * A + 12 + b + 4 + D.length * A, E = 26, O = 8 + U < l - E, R = r - 8 - U > l + E, N = O || !R ? 8 : r - 8 - U, ie = !O && !R, I = N + b + 4 + $.length * A + 12;
400
+ return g(
401
+ e.caption,
402
+ a("defs", {}, a(
403
+ "marker",
404
+ { id: "bz-arrowhead", viewBox: "0 0 10 10", refX: 8, refY: 5, markerWidth: 6, markerHeight: 6, orient: "auto" },
405
+ a("path", { d: "M0 0 L10 5 L0 10z", fill: n.accent })
406
+ )),
407
+ a("rect", { x: y, y: 2, width: u, height: 16, rx: 3, fill: n.negative, "fill-opacity": 0.16, stroke: n.negative, "stroke-width": 0.5 }),
408
+ s(y + u / 2, 14, v, { "text-anchor": "middle", fill: n.negative }),
409
+ M && a("line", { x1: y + u + 4, x2: l - 4, y1: 10, y2: 10, stroke: n.accent, "stroke-width": 1.5, "marker-end": "url(#bz-arrowhead)" }),
410
+ a("line", { x1: l, x2: l, y1: 16, y2: m - 20, stroke: n.accent, "stroke-dasharray": "2 3", "stroke-opacity": 0.6 }),
411
+ _(f),
412
+ a("polyline", { points: L(e.before, o), fill: "none", stroke: n.muted, "stroke-width": 1.5, "stroke-dasharray": "4 3" }),
413
+ a("polyline", { points: L(e.after, o), fill: "none", stroke: n.accent, "stroke-width": 2.5, "stroke-linejoin": "round" }),
414
+ a("line", { x1: N, x2: N + b, y1: m - 10, y2: m - 10, stroke: n.muted, "stroke-width": 1.5, "stroke-dasharray": "4 3" }),
415
+ s(N + b + 4, m - 6, $),
416
+ a("line", { x1: I, x2: I + b, y1: m - 10, y2: m - 10, stroke: n.accent, "stroke-width": 2.5 }),
417
+ s(I + b + 4, m - 6, D, { fill: n.accent, "font-weight": 600 }),
418
+ ie ? s(l + 6 < r - 40 ? l + 6 : l - 6, 30, w(e.move.to), { "text-anchor": l + 6 < r - 40 ? "start" : "end", fill: n.accent, "font-weight": 600 }) : s(Math.min(Math.max(l, 22), r - 22), m - 6, w(e.move.to), { "text-anchor": "middle", fill: n.accent, "font-weight": 600 })
419
+ );
420
+ }, G = (e) => {
421
+ const f = (r - 16) / 18, h = Math.min(e.covered, e.target), c = Math.ceil(e.target / 18), l = e.covered < e.target / 3 ? n.negative : e.covered < e.target ? n.warning : n.positive, v = Array.from({ length: e.target }, (u, y) => a("rect", {
422
+ x: 8 + y % 18 * f,
423
+ y: 6 + Math.floor(y / 18) * 19,
424
+ width: f * 0.75,
425
+ height: 15,
426
+ rx: 2,
427
+ fill: y < h ? l : "none",
428
+ stroke: y < h ? null : n.line
429
+ }));
430
+ return g(
431
+ e.caption,
432
+ v,
433
+ s(8, 6 + c * 19 + 14, t("vis.days", { covered: e.covered, target: e.target }), { fill: l, "font-weight": 600, "font-size": 12 })
434
+ );
435
+ }, K = (e) => {
436
+ const o = p(e.in), f = p(e.out), h = Math.max(o, f) || 1, c = 8, l = r - 8, v = (u) => u * (l - c) / h;
437
+ return g(
438
+ e.caption,
439
+ s(c, 20, `${t("vis.in")} ${x(o)}`),
440
+ a("rect", { x: c, y: 26, width: v(o), height: 22, rx: 3, fill: n.positive }),
441
+ s(c, 76, `${t("vis.out")} ${x(f)}`),
442
+ a("rect", { x: c, y: 82, width: v(Math.min(f, o)), height: 22, rx: 3, fill: n.negative, "fill-opacity": 0.5 }),
443
+ f > o && a("rect", { x: c + v(o), y: 82, width: v(f - o), height: 22, rx: 3, fill: n.negative }),
444
+ a("line", { x1: c + v(o), x2: c + v(o), y1: 24, y2: 106, stroke: n.ink, "stroke-dasharray": "2 2" }),
445
+ s(l, m - 6, `−${x(e.gap)}`, { "text-anchor": "end", fill: n.negative, "font-weight": 600, "font-size": 12 }),
446
+ s(c, m - 6, `${w(e.start)} → ${w(e.end)}`)
447
+ );
448
+ }, P = (e) => {
449
+ const f = 2 * Math.PI * 38, h = Math.min(e.window_days ? e.days_left / e.window_days : 1, 1), c = e.current != null && e.next != null, l = c && p(e.next) > p(e.current), v = 118, u = r - 8, y = (v + u) / 2;
450
+ return g(
451
+ e.caption,
452
+ a("circle", { cx: 56, cy: 52, r: 38, fill: "none", stroke: n.line, "stroke-width": 9 }),
453
+ a("circle", {
454
+ cx: 56,
455
+ cy: 52,
456
+ r: 38,
457
+ fill: "none",
458
+ stroke: n.accent,
459
+ "stroke-width": 9,
460
+ "stroke-linecap": "round",
461
+ "stroke-dasharray": `${(h * f).toFixed(1)} ${f.toFixed(1)}`,
462
+ transform: "rotate(-90 56 52)"
463
+ }),
464
+ s(56, 59, `${e.days_left} ${t("vis.dayUnit")}`, { "text-anchor": "middle", fill: n.ink, "font-size": 20, "font-weight": 600 }),
465
+ s(56, m - 6, `${t("vis.until")} ${w(e.deadline)}`, { "text-anchor": "middle" }),
466
+ c && [
467
+ a("polyline", {
468
+ points: `${v},${l ? 96 : 56} ${y},${l ? 96 : 56} ${y},${l ? 56 : 96} ${u},${l ? 56 : 96}`,
469
+ fill: "none",
470
+ stroke: l ? n.negative : n.positive,
471
+ "stroke-width": 2.5
472
+ }),
473
+ s(v, l ? 114 : 48, `${x(e.current)} ${t("vis.perMonth")}`),
474
+ s(u, l ? 48 : 114, x(e.next), { "text-anchor": "end", fill: l ? n.negative : n.positive, "font-weight": 600 })
475
+ ]
476
+ );
477
+ }, Q = (e) => {
478
+ const o = C([e.series], r), f = o.y(0), h = e.series.length - 1, c = o.x(h), l = o.y(p(e.end.balance)), u = p(e.end.balance) < 0 ? n.negative : n.positive;
479
+ return g(
480
+ e.caption,
481
+ _(f),
482
+ a("polyline", { points: L(e.series, o), fill: "none", stroke: n.muted, "stroke-width": 1.5, "stroke-linejoin": "round" }),
483
+ k(e.series, o),
484
+ // The finish line: from zero to where the period ends.
485
+ a("line", { x1: c, x2: c, y1: f, y2: l, stroke: u, "stroke-width": 4, "stroke-linecap": "round" }),
486
+ a("circle", { cx: c, cy: l, r: 6, fill: u }),
487
+ s(
488
+ c - 12,
489
+ Math.min(Math.max(l + 4, 26), m - 26),
490
+ `${x(e.end.balance)} · ${w(e.end.date)}`,
491
+ { "text-anchor": "end", fill: u, "font-weight": 600 }
492
+ ),
493
+ e.days_of_fixed_costs != null && s(r - 8, m - 6, t("vis.fixedDays", { days: e.days_of_fixed_costs }), { "text-anchor": "end", fill: u }),
494
+ s(8, m - 6, w(e.series[0][0]))
495
+ );
496
+ }, Z = (e) => {
497
+ const o = Date.parse(e.today), f = Math.max(Date.parse(e.until) - o, 1), h = 10, c = r - 10, l = (D) => h + (Date.parse(D) - o) * (c - h) / f, v = Math.round(f / 864e5), u = Array.from({ length: Math.floor(v / 7) + 1 }, (D, b) => a("line", { x1: h + b * 7 * (c - h) / v, x2: h + b * 7 * (c - h) / v, y1: 72, y2: 84, stroke: n.line })), y = e.items[0], M = l(y.date), $ = M > r * 0.6;
498
+ return g(
499
+ e.caption,
500
+ a("line", { x1: h, x2: c, y1: 84, y2: 84, stroke: n.line, "stroke-width": 2 }),
501
+ u,
502
+ a("circle", { cx: h, cy: 84, r: 5, fill: n.ink }),
503
+ e.items.slice(1).map((D) => a("rect", { x: l(D.date) - 4, y: 60, width: 8, height: 24, rx: 2, fill: n.warning })),
504
+ a("rect", { x: M - 6, y: 38, width: 12, height: 46, rx: 3, fill: n.accent }),
505
+ s(M + ($ ? -10 : 10), 46, `${F(y.label, 20)} · ${x(y.amount)}`, { "text-anchor": $ ? "end" : "start", fill: n.ink, "font-weight": 600 }),
506
+ s(M + ($ ? -10 : 10), 62, t("vis.inDays", { days: y.days }), { "text-anchor": $ ? "end" : "start", fill: n.accent }),
507
+ e.items.length > 1 && s(r - 8, 14, t("vis.more", { n: e.items.length - 1 }), { "text-anchor": "end" }),
508
+ s(h, m - 14, t("vis.today")),
509
+ s(c, m - 14, w(e.until), { "text-anchor": "end" })
510
+ );
511
+ }, W = (e) => {
512
+ const o = Math.max(e.years, 1), f = 6, h = 8, c = r - 8, l = (c - h - f * (o - 1)) / o, v = m - 26, u = 30, y = Array.from({ length: o }, (M, $) => {
513
+ const D = ($ + 1) / o * (v - u);
514
+ return a("rect", {
515
+ x: h + $ * (l + f),
516
+ y: v - D,
517
+ width: l,
518
+ height: D,
519
+ rx: 2,
520
+ fill: n.negative,
521
+ "fill-opacity": $ === o - 1 ? 1 : 0.25 + 0.5 * $ / o
522
+ });
523
+ });
524
+ return g(
525
+ e.caption,
526
+ y,
527
+ s(c, u - 8, x(e.total), { "text-anchor": "end", fill: n.negative, "font-weight": 600 }),
528
+ // Per year on the left, ten years on the right, both above the bars so neither crosses them.
529
+ s(h, u - 8, `${x(e.per_year)} ${t("vis.perYear")}`, { fill: n.ink }),
530
+ s(h, m - 8, t("vis.years", { n: 1 })),
531
+ s(c, m - 8, t("vis.years", { n: o }), { "text-anchor": "end" })
532
+ );
533
+ }, ee = (e) => {
534
+ const o = p(e.needed_per_month), f = p(e.set_aside_per_month), h = o > 0 ? Math.min(f / o, 1) : 1, c = 5, l = 8, v = r - 8, u = (v - l - c * 11) / 12, y = 34, M = 96, $ = Array.from({ length: 12 }, (D, b) => {
535
+ const A = l + b * (u + c);
536
+ return [
537
+ a("rect", { x: A, y, width: u, height: M - y, rx: 4, fill: "none", stroke: n.accent, "stroke-width": 1.2 }),
538
+ h > 0 && a("rect", { x: A + 1.5, y: M - h * (M - y) + 1.5, width: u - 3, height: Math.max(h * (M - y) - 3, 0), rx: 3, fill: n.accent })
539
+ ];
540
+ });
541
+ return g(
542
+ e.caption,
543
+ $,
544
+ s(l, 20, `${t("vis.bill")} ${x(e.bill)}`, { fill: n.ink, "font-weight": 600 }),
545
+ s(v, 20, `${t("vis.months")} × ${x(e.needed_per_month)}`, { "text-anchor": "end", fill: n.accent }),
546
+ s(l, m - 8, `${x(e.set_aside_per_month)} ${t("vis.perMonth")}`, { fill: h < 1 ? n.negative : n.positive }),
547
+ s(v, m - 8, `${x(e.per_day)} ${t("vis.perDay")}`, { "text-anchor": "end" })
548
+ );
549
+ }, te = (e) => {
550
+ const o = p(e.limit) || 1, f = Math.min(p(e.paid), o), h = 8, c = r - 8, l = (v) => v * (c - h) / o;
551
+ return g(
552
+ e.caption,
553
+ s(c, 24, `${t("vis.limit")} ${x(e.limit)}`, { "text-anchor": "end" }),
554
+ a("rect", { x: h, y: 36, width: c - h, height: 26, rx: 4, fill: "none", stroke: n.accent, "stroke-dasharray": "4 3" }),
555
+ f > 0 && a("rect", { x: h, y: 36, width: l(f), height: 26, rx: 4, fill: n.positive }),
556
+ s(h, 80, `${t("vis.paid")} ${x(e.paid)}`, { fill: n.positive, "font-weight": 600 }),
557
+ s(c, 80, `${t("vis.left")} ${x(e.left)}`, { "text-anchor": "end", fill: n.accent, "font-weight": 600 }),
558
+ a("line", { x1: h, x2: c, y1: 104, y2: 104, stroke: n.line, "stroke-width": 2 }),
559
+ a("circle", { cx: h, cy: 104, r: 4, fill: n.ink }),
560
+ a("circle", { cx: c, cy: 104, r: 5, fill: n.accent }),
561
+ s(h, m - 6, t("vis.today")),
562
+ s(c, m - 6, `${e.days_left} ${t("vis.dayUnit")} → ${w(e.deadline)}`, { "text-anchor": "end", fill: n.accent })
563
+ );
564
+ }, ne = (e) => {
565
+ const o = e.contracts[0], f = Date.parse(e.today), h = Date.parse(o.ends_on), c = Math.max(h - f, 1), l = 14, v = r - 52, u = (M) => l + (Date.parse(M) - f) * (v - l) / c, y = u(o.cancel_before);
566
+ return g(
567
+ e.caption,
568
+ s(8, 16, F(o.name, 26), { fill: n.ink, "font-weight": 600 }),
569
+ e.contracts.length > 1 && s(r - 8, 16, t("vis.more", { n: e.contracts.length - 1 }), { "text-anchor": "end" }),
570
+ a("line", { x1: l, x2: y, y1: 66, y2: 66, stroke: n.accent, "stroke-width": 6, "stroke-linecap": "round" }),
571
+ a("line", { x1: y, x2: v, y1: 66, y2: 66, stroke: n.line, "stroke-width": 2 }),
572
+ a("line", { x1: v, x2: r - 8, y1: 66, y2: 66, stroke: n.negative, "stroke-width": 2, "stroke-dasharray": "3 3" }),
573
+ a("circle", { cx: l, cy: 66, r: 5, fill: n.ink }),
574
+ a("rect", { x: y - 9, y: 57, width: 18, height: 18, rx: 3, fill: n.accent }),
575
+ a("circle", { cx: v, cy: 66, r: 5, fill: n.negative }),
576
+ s(Math.max(y, 40), 44, `${o.days_left} ${t("vis.dayUnit")}`, { "text-anchor": "middle", fill: n.accent, "font-size": 18, "font-weight": 600 }),
577
+ s(l - 6, 96, t("vis.today")),
578
+ s(Math.min(Math.max(y, 70), r - 110), 96, `${t("vis.letter")} ${w(o.cancel_before)}`, { "text-anchor": "middle", fill: n.accent }),
579
+ s(r - 8, 96, `${t("vis.ends")} ${w(o.ends_on)}`, { "text-anchor": "end", fill: n.negative }),
580
+ s(r - 8, m - 8, t("vis.renewal"), { "text-anchor": "end", fill: n.negative })
581
+ );
582
+ };
583
+ switch (i.kind) {
584
+ case "runway":
585
+ return z(i);
586
+ case "valley":
587
+ return V(i);
588
+ case "shift":
589
+ return X(i);
590
+ case "days":
591
+ return G(i);
592
+ case "balance":
593
+ return K(i);
594
+ case "countdown":
595
+ return P(i);
596
+ case "horizon":
597
+ return Q(i);
598
+ case "calendar":
599
+ return Z(i);
600
+ case "leak":
601
+ return W(i);
602
+ case "jar":
603
+ return ee(i);
604
+ case "gauge":
605
+ return te(i);
606
+ case "deadline":
607
+ return ne(i);
608
+ default:
609
+ return null;
610
+ }
611
+ }
612
+ function Le(i, t, d = document, r = {}) {
613
+ if (!i) return null;
614
+ const a = Math.round(Math.min(Math.max(r.width ?? q, xe), q));
615
+ try {
616
+ return be(i, ye(t, me), d, a);
617
+ } catch {
618
+ return null;
619
+ }
620
+ }
621
+ export {
622
+ ve as L,
623
+ q as M,
624
+ $e as T,
625
+ we as V,
626
+ Me as a,
627
+ Se as b,
628
+ ye as c,
629
+ De as d,
630
+ _e as e,
631
+ Le as f,
632
+ xe as g,
633
+ ze as h,
634
+ fe as i,
635
+ ke as j,
636
+ me as k,
637
+ ce as l,
638
+ ue as m,
639
+ T as n,
640
+ le as o,
641
+ oe as p,
642
+ j as q,
643
+ Ae as r,
644
+ w as s,
645
+ H as t,
646
+ F as u,
647
+ se as v
648
+ };
649
+ //# sourceMappingURL=index-yeBMtDf1.js.map