@fasl-work/caos-app-shell 0.18.0 → 0.19.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/dist/chart.d.ts +43 -10
- package/dist/chart.js +597 -85
- package/dist/chunk-FXPSZD6X.js +686 -0
- package/dist/index.d.ts +36 -5
- package/dist/index.js +499 -66
- package/dist/{text-DyQ1A8oo.d.ts → tokens-BvU9bFPw.d.ts} +25 -22
- package/gate/inpage.mjs +169 -0
- package/gate/run.mjs +12 -0
- package/package.json +1 -1
- package/reserved-classes.json +22 -0
- package/styles.css +41 -0
- package/dist/chunk-DBCMAL2G.js +0 -289
package/dist/chunk-DBCMAL2G.js
DELETED
|
@@ -1,289 +0,0 @@
|
|
|
1
|
-
import { LANG_STORAGE_KEY, THEME_STORAGE_KEY } from './chunk-33WTUQ7Q.js';
|
|
2
|
-
import { create } from 'zustand';
|
|
3
|
-
import { useMemo, useState, useRef, useCallback, useEffect } from 'react';
|
|
4
|
-
import { jsx } from 'react/jsx-runtime';
|
|
5
|
-
|
|
6
|
-
var KEY = LANG_STORAGE_KEY;
|
|
7
|
-
function readLang() {
|
|
8
|
-
try {
|
|
9
|
-
const s = localStorage.getItem(KEY);
|
|
10
|
-
if (s === "en" || s === "es") return s;
|
|
11
|
-
} catch {
|
|
12
|
-
}
|
|
13
|
-
return "en";
|
|
14
|
-
}
|
|
15
|
-
var useLangStore = create((set, get) => ({
|
|
16
|
-
lang: readLang(),
|
|
17
|
-
setLang: (l) => {
|
|
18
|
-
try {
|
|
19
|
-
localStorage.setItem(KEY, l);
|
|
20
|
-
} catch {
|
|
21
|
-
}
|
|
22
|
-
set({ lang: l });
|
|
23
|
-
},
|
|
24
|
-
toggle: () => {
|
|
25
|
-
const next = get().lang === "en" ? "es" : "en";
|
|
26
|
-
try {
|
|
27
|
-
localStorage.setItem(KEY, next);
|
|
28
|
-
} catch {
|
|
29
|
-
}
|
|
30
|
-
set({ lang: next });
|
|
31
|
-
}
|
|
32
|
-
}));
|
|
33
|
-
var useShellLang = () => useLangStore((s) => s.lang);
|
|
34
|
-
|
|
35
|
-
// src/lib/text.ts
|
|
36
|
-
function pick(text, lang) {
|
|
37
|
-
if (text === void 0) return "";
|
|
38
|
-
if (typeof text === "string") return text;
|
|
39
|
-
return text[lang] ?? text.en;
|
|
40
|
-
}
|
|
41
|
-
var KEY2 = THEME_STORAGE_KEY;
|
|
42
|
-
function readTheme() {
|
|
43
|
-
try {
|
|
44
|
-
const s = localStorage.getItem(KEY2);
|
|
45
|
-
if (s === "light" || s === "dark") return s;
|
|
46
|
-
return window.matchMedia("(prefers-color-scheme: light)").matches ? "light" : "dark";
|
|
47
|
-
} catch {
|
|
48
|
-
return "dark";
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
function applyTheme(t) {
|
|
52
|
-
try {
|
|
53
|
-
document.documentElement.dataset.theme = t;
|
|
54
|
-
} catch {
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
var useThemeStore = create((set, get) => ({
|
|
58
|
-
theme: readTheme(),
|
|
59
|
-
toggleTheme: () => {
|
|
60
|
-
const next = get().theme === "dark" ? "light" : "dark";
|
|
61
|
-
applyTheme(next);
|
|
62
|
-
try {
|
|
63
|
-
localStorage.setItem(KEY2, next);
|
|
64
|
-
} catch {
|
|
65
|
-
}
|
|
66
|
-
set({ theme: next });
|
|
67
|
-
},
|
|
68
|
-
setTheme: (t) => {
|
|
69
|
-
applyTheme(t);
|
|
70
|
-
try {
|
|
71
|
-
localStorage.setItem(KEY2, t);
|
|
72
|
-
} catch {
|
|
73
|
-
}
|
|
74
|
-
set({ theme: t });
|
|
75
|
-
}
|
|
76
|
-
}));
|
|
77
|
-
var SHELL_TOKENS = [
|
|
78
|
-
"--color-bg",
|
|
79
|
-
"--color-surface",
|
|
80
|
-
"--color-surface-2",
|
|
81
|
-
"--color-border",
|
|
82
|
-
"--color-fg",
|
|
83
|
-
"--color-fg-subtle",
|
|
84
|
-
"--color-fg-faint",
|
|
85
|
-
"--color-accent",
|
|
86
|
-
"--color-accent-fg",
|
|
87
|
-
"--color-accent-soft",
|
|
88
|
-
"--color-accent-2",
|
|
89
|
-
"--color-magenta",
|
|
90
|
-
"--color-good",
|
|
91
|
-
"--color-warn",
|
|
92
|
-
"--color-bad",
|
|
93
|
-
"--color-shadow",
|
|
94
|
-
"--font-sans",
|
|
95
|
-
"--font-mono",
|
|
96
|
-
"--text-xs",
|
|
97
|
-
"--text-sm",
|
|
98
|
-
"--text-md",
|
|
99
|
-
"--text-base",
|
|
100
|
-
"--text-lg",
|
|
101
|
-
"--text-xl",
|
|
102
|
-
"--text-2xl",
|
|
103
|
-
"--space-1",
|
|
104
|
-
"--space-2",
|
|
105
|
-
"--space-3",
|
|
106
|
-
"--space-4",
|
|
107
|
-
"--space-5",
|
|
108
|
-
"--space-6",
|
|
109
|
-
"--radius-sm",
|
|
110
|
-
"--radius-md",
|
|
111
|
-
"--radius-lg",
|
|
112
|
-
"--radius-pill",
|
|
113
|
-
"--maxw",
|
|
114
|
-
"--maxw-wide",
|
|
115
|
-
"--measure",
|
|
116
|
-
"--measure-text",
|
|
117
|
-
"--header-h",
|
|
118
|
-
"--rail-w",
|
|
119
|
-
"--fade",
|
|
120
|
-
"--icon-sm",
|
|
121
|
-
"--icon-md",
|
|
122
|
-
"--icon-lg",
|
|
123
|
-
"--z-header",
|
|
124
|
-
"--z-focus",
|
|
125
|
-
"--z-modal"
|
|
126
|
-
];
|
|
127
|
-
function resolveToken(token, fallback = "") {
|
|
128
|
-
if (typeof document === "undefined") return fallback;
|
|
129
|
-
const v = getComputedStyle(document.documentElement).getPropertyValue(token).trim();
|
|
130
|
-
return v || fallback;
|
|
131
|
-
}
|
|
132
|
-
function useThemeTokens() {
|
|
133
|
-
const theme = useThemeStore((s) => s.theme);
|
|
134
|
-
return useMemo(() => {
|
|
135
|
-
const out = {};
|
|
136
|
-
for (const t of SHELL_TOKENS) out[t] = resolveToken(t);
|
|
137
|
-
return out;
|
|
138
|
-
}, [theme]);
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
// src/lib/format.ts
|
|
142
|
-
var LOCALE = { en: "en-US", es: "es-CL" };
|
|
143
|
-
var NBSP = "\xA0";
|
|
144
|
-
var SCIENTIFIC_BELOW = 1e-4;
|
|
145
|
-
function belowScientific(magnitude) {
|
|
146
|
-
return magnitude !== 0 && Math.abs(magnitude) < SCIENTIFIC_BELOW * (1 - 1e-12);
|
|
147
|
-
}
|
|
148
|
-
var NOT_AVAILABLE = { en: "not available", es: "no disponible" };
|
|
149
|
-
function formatNumber(value, lang, opts = {}) {
|
|
150
|
-
if (value === null || value === void 0 || !Number.isFinite(value)) return NOT_AVAILABLE[lang];
|
|
151
|
-
const v = opts.percent ? value * 100 : value;
|
|
152
|
-
const digits = opts.digits ?? 4;
|
|
153
|
-
const scientific = v !== 0 && (opts.notation === "scientific" || belowScientific(v));
|
|
154
|
-
const grouping = opts.grouping === false ? { useGrouping: false } : {};
|
|
155
|
-
const nf = opts.decimals !== void 0 ? new Intl.NumberFormat(LOCALE[lang], { minimumFractionDigits: opts.decimals, maximumFractionDigits: opts.decimals, ...grouping }) : scientific ? new Intl.NumberFormat(LOCALE[lang], { notation: "scientific", maximumSignificantDigits: digits }) : Math.abs(v) >= 10 ** (digits - 1) ? new Intl.NumberFormat(LOCALE[lang], { maximumFractionDigits: 0, ...grouping }) : new Intl.NumberFormat(LOCALE[lang], { maximumSignificantDigits: digits, ...grouping });
|
|
156
|
-
return opts.percent ? `${nf.format(v)}${NBSP}%` : nf.format(v);
|
|
157
|
-
}
|
|
158
|
-
function formatTicks(values, lang, opts = {}) {
|
|
159
|
-
let o = opts;
|
|
160
|
-
if (opts.decimals === void 0 && opts.notation === void 0) {
|
|
161
|
-
const scale = opts.percent ? 100 : 1;
|
|
162
|
-
const small = values.some((v) => v !== null && v !== void 0 && Number.isFinite(v) && belowScientific(v * scale));
|
|
163
|
-
if (small) o = { ...opts, notation: "scientific" };
|
|
164
|
-
}
|
|
165
|
-
return values.map((v) => v === null || v === void 0 ? "" : formatNumber(v, lang, o));
|
|
166
|
-
}
|
|
167
|
-
function useFormat() {
|
|
168
|
-
const lang = useShellLang();
|
|
169
|
-
return (value, opts) => formatNumber(value, lang, opts);
|
|
170
|
-
}
|
|
171
|
-
function useStageSize() {
|
|
172
|
-
const [size, setSize] = useState({ width: 0, height: 0 });
|
|
173
|
-
const roRef = useRef(null);
|
|
174
|
-
const ref = useCallback((el) => {
|
|
175
|
-
roRef.current?.disconnect();
|
|
176
|
-
roRef.current = null;
|
|
177
|
-
if (!el) return;
|
|
178
|
-
const measure = () => {
|
|
179
|
-
const r = el.getBoundingClientRect();
|
|
180
|
-
setSize((prev) => prev.width === Math.round(r.width) && prev.height === Math.round(r.height) ? prev : { width: Math.round(r.width), height: Math.round(r.height) });
|
|
181
|
-
};
|
|
182
|
-
measure();
|
|
183
|
-
if (typeof ResizeObserver !== "undefined") {
|
|
184
|
-
roRef.current = new ResizeObserver(measure);
|
|
185
|
-
roRef.current.observe(el);
|
|
186
|
-
}
|
|
187
|
-
}, []);
|
|
188
|
-
useEffect(() => () => roRef.current?.disconnect(), []);
|
|
189
|
-
return [ref, size];
|
|
190
|
-
}
|
|
191
|
-
function Stage({ label, children, className }) {
|
|
192
|
-
const lang = useShellLang();
|
|
193
|
-
const [ref, size] = useStageSize();
|
|
194
|
-
const ready = size.width > 0 && size.height > 0;
|
|
195
|
-
const name = pick(label, lang);
|
|
196
|
-
useEffect(() => {
|
|
197
|
-
if (ready) return;
|
|
198
|
-
const t = setTimeout(() => {
|
|
199
|
-
console.error(`[caos-app-shell] Stage "${name}" has no size; give its container a height (ADR-0071 rule 8)`);
|
|
200
|
-
}, 1500);
|
|
201
|
-
return () => clearTimeout(t);
|
|
202
|
-
}, [ready, name]);
|
|
203
|
-
return /* @__PURE__ */ jsx(
|
|
204
|
-
"div",
|
|
205
|
-
{
|
|
206
|
-
ref,
|
|
207
|
-
className: ["caos-stage", className].filter(Boolean).join(" "),
|
|
208
|
-
"data-stage": name,
|
|
209
|
-
"data-drawn": ready ? "1" : "0",
|
|
210
|
-
"data-width": size.width,
|
|
211
|
-
"data-height": size.height,
|
|
212
|
-
children: ready ? children(size) : null
|
|
213
|
-
}
|
|
214
|
-
);
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
// src/chart/text.ts
|
|
218
|
-
function referenceLineName(lang, n, of) {
|
|
219
|
-
const base = lang === "es" ? "L\xEDnea de referencia" : "Reference line";
|
|
220
|
-
return of > 1 ? `${base} ${n}` : base;
|
|
221
|
-
}
|
|
222
|
-
var context;
|
|
223
|
-
function fontFamily() {
|
|
224
|
-
if (typeof document === "undefined") return "sans-serif";
|
|
225
|
-
return getComputedStyle(document.documentElement).getPropertyValue("--font-sans").trim() || "sans-serif";
|
|
226
|
-
}
|
|
227
|
-
function textWidth(text, px, weight = 400) {
|
|
228
|
-
if (context === void 0) {
|
|
229
|
-
try {
|
|
230
|
-
context = typeof document === "undefined" ? null : document.createElement("canvas").getContext("2d");
|
|
231
|
-
} catch {
|
|
232
|
-
context = null;
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
if (!context) return text.length * px * 0.62;
|
|
236
|
-
context.font = `${weight} ${px}px ${fontFamily()}`;
|
|
237
|
-
return context.measureText(text).width;
|
|
238
|
-
}
|
|
239
|
-
function widestLabel(labels, px, weight = 400) {
|
|
240
|
-
return Math.max(0, ...labels.map((label) => textWidth(label, px, weight)));
|
|
241
|
-
}
|
|
242
|
-
function shorten(line, width, px) {
|
|
243
|
-
if (textWidth(line, px) <= width) return line;
|
|
244
|
-
let cut = line;
|
|
245
|
-
while (cut.length > 1 && textWidth(`${cut}\u2026`, px) > width) cut = cut.slice(0, -1);
|
|
246
|
-
return `${cut.trimEnd()}\u2026`;
|
|
247
|
-
}
|
|
248
|
-
function fitLabel(label, width, px, maxLines = 2) {
|
|
249
|
-
if (textWidth(label, px) <= width) return { lines: [label], shortened: false };
|
|
250
|
-
const words = label.split(" ");
|
|
251
|
-
if (maxLines === 2 && words.length > 1) {
|
|
252
|
-
let best = null;
|
|
253
|
-
let bestWidth = Infinity;
|
|
254
|
-
for (let k = 1; k < words.length; k += 1) {
|
|
255
|
-
const first = words.slice(0, k).join(" ");
|
|
256
|
-
const second = words.slice(k).join(" ");
|
|
257
|
-
const widest = Math.max(textWidth(first, px), textWidth(second, px));
|
|
258
|
-
if (widest < bestWidth) {
|
|
259
|
-
bestWidth = widest;
|
|
260
|
-
best = [first, second];
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
if (best && bestWidth <= width) return { lines: best, shortened: false };
|
|
264
|
-
if (best) return { lines: [shorten(best[0], width, px), shorten(best[1], width, px)], shortened: true };
|
|
265
|
-
}
|
|
266
|
-
return { lines: [shorten(label, width, px)], shortened: true };
|
|
267
|
-
}
|
|
268
|
-
function niceStep(x) {
|
|
269
|
-
if (!(x > 0) || !Number.isFinite(x)) return 1;
|
|
270
|
-
const magnitude = 10 ** Math.floor(Math.log10(x));
|
|
271
|
-
return ([1, 2, 2.5, 5, 10].find((m) => m * magnitude >= x * (1 - 1e-12)) ?? 10) * magnitude;
|
|
272
|
-
}
|
|
273
|
-
function niceTicks(lo, hi, room, labelSize, most = 6) {
|
|
274
|
-
if (!Number.isFinite(lo) || !Number.isFinite(hi)) return [0];
|
|
275
|
-
if (hi < lo) [lo, hi] = [hi, lo];
|
|
276
|
-
if (hi === lo) hi = lo === 0 ? 1 : lo + Math.abs(lo);
|
|
277
|
-
const count = Math.max(2, Math.min(most, Math.floor(room / (labelSize + 16)) + 1));
|
|
278
|
-
const step = niceStep((hi - lo) / (count - 1));
|
|
279
|
-
const first = Math.floor(lo / step + 1e-9) * step;
|
|
280
|
-
const ticks = [];
|
|
281
|
-
for (let k = 0; first + k * step <= hi + step * 1e-9 || ticks.length < 2; k += 1) {
|
|
282
|
-
ticks.push(Number((first + k * step).toPrecision(12)));
|
|
283
|
-
if (ticks.length > 50) break;
|
|
284
|
-
}
|
|
285
|
-
if (ticks[ticks.length - 1] < hi - step * 1e-9) ticks.push(Number((ticks[ticks.length - 1] + step).toPrecision(12)));
|
|
286
|
-
return ticks;
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
export { NBSP, NOT_AVAILABLE, SCIENTIFIC_BELOW, SHELL_TOKENS, Stage, applyTheme, fitLabel, fontFamily, formatNumber, formatTicks, niceStep, niceTicks, pick, readTheme, referenceLineName, resolveToken, textWidth, useFormat, useLangStore, useShellLang, useStageSize, useThemeStore, useThemeTokens, widestLabel };
|