@fasl-work/caos-app-shell 0.1.2 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +68 -59
- package/dist/index.d.ts +157 -1
- package/dist/index.js +312 -21
- package/package.json +56 -54
- package/styles.css +242 -221
package/dist/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { createContext, useState, useRef, useEffect, useId, useContext } from 'react';
|
|
1
|
+
import { createContext, useState, useRef, useEffect, useCallback, useId, useContext } from 'react';
|
|
2
2
|
import { NavLink } from 'react-router-dom';
|
|
3
3
|
import { Sun, Moon, Languages, Boxes, Github, Globe, Briefcase, Info } from 'lucide-react';
|
|
4
4
|
import { create } from 'zustand';
|
|
5
|
-
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
5
|
+
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
6
6
|
import katex from 'katex';
|
|
7
7
|
|
|
8
8
|
// src/shell/AppShell.tsx
|
|
@@ -45,7 +45,7 @@ var CHROME = {
|
|
|
45
45
|
toggleLanguage: "Switch language",
|
|
46
46
|
light: "Light",
|
|
47
47
|
dark: "Dark",
|
|
48
|
-
attribution: "
|
|
48
|
+
attribution: "Developed by Felipe Santib\xE1\xF1ez-Leal",
|
|
49
49
|
complement: "A CAOS research project",
|
|
50
50
|
license: "MIT licensed \xB7 open source",
|
|
51
51
|
version: "v"
|
|
@@ -58,7 +58,7 @@ var CHROME = {
|
|
|
58
58
|
toggleLanguage: "Cambiar idioma",
|
|
59
59
|
light: "Claro",
|
|
60
60
|
dark: "Oscuro",
|
|
61
|
-
attribution: "
|
|
61
|
+
attribution: "Desarrollado por Felipe Santib\xE1\xF1ez-Leal",
|
|
62
62
|
complement: "Un proyecto de investigaci\xF3n CAOS",
|
|
63
63
|
license: "Licencia MIT \xB7 c\xF3digo abierto",
|
|
64
64
|
version: "v"
|
|
@@ -282,28 +282,319 @@ function AppShell({ config, children }) {
|
|
|
282
282
|
] }) }),
|
|
283
283
|
config.architecture && archOpen && /* @__PURE__ */ jsx(ArchitectureModal, { config: config.architecture, onClose: () => setArchOpen(false) }),
|
|
284
284
|
/* @__PURE__ */ jsx("main", { className: "page", children }),
|
|
285
|
-
/* @__PURE__ */ jsx("footer", { className: "site-footer", children: /* @__PURE__ */
|
|
286
|
-
/* @__PURE__ */
|
|
287
|
-
|
|
285
|
+
/* @__PURE__ */ jsx("footer", { className: "site-footer", children: /* @__PURE__ */ jsx("div", { className: "footer-inner", children: /* @__PURE__ */ jsxs("div", { className: "footer-meta", children: [
|
|
286
|
+
/* @__PURE__ */ jsx("span", { children: config.product.name }),
|
|
287
|
+
/* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "\xB7" }),
|
|
288
|
+
/* @__PURE__ */ jsx("span", { children: c.complement }),
|
|
289
|
+
/* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "\xB7" }),
|
|
290
|
+
/* @__PURE__ */ jsx("span", { className: "footer-build", children: /* @__PURE__ */ jsxs("span", { children: [
|
|
291
|
+
c.version,
|
|
292
|
+
config.version
|
|
293
|
+
] }) }),
|
|
294
|
+
/* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "\xB7" }),
|
|
295
|
+
/* @__PURE__ */ jsx("span", { children: c.attribution }),
|
|
296
|
+
config.footer?.provenance && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
288
297
|
/* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "\xB7" }),
|
|
289
|
-
/* @__PURE__ */ jsx("span", { children:
|
|
298
|
+
/* @__PURE__ */ jsx("span", { children: config.footer.provenance[lang] })
|
|
290
299
|
] }),
|
|
291
|
-
/* @__PURE__ */
|
|
292
|
-
|
|
300
|
+
/* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "\xB7" }),
|
|
301
|
+
/* @__PURE__ */ jsx("a", { href: config.links.github, target: "_blank", rel: "noreferrer noopener", children: c.github }),
|
|
302
|
+
/* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "\xB7" }),
|
|
303
|
+
/* @__PURE__ */ jsx("span", { className: "faint", children: c.license }),
|
|
304
|
+
config.footer?.disclaimer && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
293
305
|
/* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "\xB7" }),
|
|
294
|
-
/* @__PURE__ */ jsx("
|
|
295
|
-
/* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "\xB7" }),
|
|
296
|
-
/* @__PURE__ */ jsx("a", { href: portfolio, target: "_blank", rel: "noreferrer noopener", children: c.portfolio }),
|
|
297
|
-
/* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "\xB7" }),
|
|
298
|
-
/* @__PURE__ */ jsx("span", { className: "faint", children: c.license }),
|
|
299
|
-
/* @__PURE__ */ jsx("span", { className: "footer-build", children: /* @__PURE__ */ jsxs("span", { children: [
|
|
300
|
-
c.version,
|
|
301
|
-
config.version
|
|
302
|
-
] }) })
|
|
306
|
+
/* @__PURE__ */ jsx("span", { className: "faint", children: config.footer.disclaimer[lang] })
|
|
303
307
|
] })
|
|
304
|
-
] }) })
|
|
308
|
+
] }) }) })
|
|
309
|
+
] });
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
// src/lib/vizLoop.ts
|
|
313
|
+
function createVizLoop(frame, options, deps) {
|
|
314
|
+
const { loop = false, durationMs, onComplete, onPlayingChange } = options;
|
|
315
|
+
const { raf, caf } = deps;
|
|
316
|
+
let handle = null;
|
|
317
|
+
let want = false;
|
|
318
|
+
let hidden = false;
|
|
319
|
+
let last = 0;
|
|
320
|
+
let baseline = true;
|
|
321
|
+
let elapsed = 0;
|
|
322
|
+
const playing = () => handle !== null;
|
|
323
|
+
const emitPlaying = (was) => {
|
|
324
|
+
if (was !== playing()) onPlayingChange?.(playing());
|
|
325
|
+
};
|
|
326
|
+
const request = () => {
|
|
327
|
+
if (handle === null) handle = raf(tick);
|
|
328
|
+
};
|
|
329
|
+
const cancel = () => {
|
|
330
|
+
if (handle !== null) {
|
|
331
|
+
caf(handle);
|
|
332
|
+
handle = null;
|
|
333
|
+
}
|
|
334
|
+
};
|
|
335
|
+
function tick(t) {
|
|
336
|
+
handle = null;
|
|
337
|
+
if (baseline) {
|
|
338
|
+
last = t;
|
|
339
|
+
baseline = false;
|
|
340
|
+
}
|
|
341
|
+
const dt = t - last;
|
|
342
|
+
last = t;
|
|
343
|
+
elapsed += dt;
|
|
344
|
+
let e = elapsed;
|
|
345
|
+
const capped = durationMs != null && e >= durationMs;
|
|
346
|
+
if (capped) e = durationMs;
|
|
347
|
+
const cont = frame(dt, e);
|
|
348
|
+
if (capped || cont === false) {
|
|
349
|
+
if (loop) {
|
|
350
|
+
elapsed = 0;
|
|
351
|
+
baseline = true;
|
|
352
|
+
request();
|
|
353
|
+
} else {
|
|
354
|
+
const was = true;
|
|
355
|
+
want = false;
|
|
356
|
+
emitPlaying(was);
|
|
357
|
+
onComplete?.();
|
|
358
|
+
}
|
|
359
|
+
return;
|
|
360
|
+
}
|
|
361
|
+
request();
|
|
362
|
+
}
|
|
363
|
+
const play = () => {
|
|
364
|
+
if (want && playing()) return;
|
|
365
|
+
const was = playing();
|
|
366
|
+
want = true;
|
|
367
|
+
baseline = true;
|
|
368
|
+
if (!hidden) request();
|
|
369
|
+
emitPlaying(was);
|
|
370
|
+
};
|
|
371
|
+
const pause = () => {
|
|
372
|
+
const was = playing();
|
|
373
|
+
want = false;
|
|
374
|
+
cancel();
|
|
375
|
+
emitPlaying(was);
|
|
376
|
+
};
|
|
377
|
+
const restart = () => {
|
|
378
|
+
const was = playing();
|
|
379
|
+
want = true;
|
|
380
|
+
elapsed = 0;
|
|
381
|
+
baseline = true;
|
|
382
|
+
cancel();
|
|
383
|
+
if (!hidden) request();
|
|
384
|
+
emitPlaying(was);
|
|
385
|
+
};
|
|
386
|
+
const setHidden = (h) => {
|
|
387
|
+
if (h === hidden) return;
|
|
388
|
+
hidden = h;
|
|
389
|
+
const was = playing();
|
|
390
|
+
if (hidden) {
|
|
391
|
+
cancel();
|
|
392
|
+
} else if (want) {
|
|
393
|
+
baseline = true;
|
|
394
|
+
request();
|
|
395
|
+
}
|
|
396
|
+
emitPlaying(was);
|
|
397
|
+
};
|
|
398
|
+
return {
|
|
399
|
+
isPlaying: playing,
|
|
400
|
+
isRunning: () => want,
|
|
401
|
+
play,
|
|
402
|
+
pause,
|
|
403
|
+
toggle: () => want ? pause() : play(),
|
|
404
|
+
restart,
|
|
405
|
+
setHidden,
|
|
406
|
+
dispose: () => {
|
|
407
|
+
want = false;
|
|
408
|
+
cancel();
|
|
409
|
+
}
|
|
410
|
+
};
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
// src/lib/usePausedViz.ts
|
|
414
|
+
function usePausedViz(frame, options = {}) {
|
|
415
|
+
const { autoStart = false, loop, durationMs, onComplete } = options;
|
|
416
|
+
const [playing, setPlaying] = useState(false);
|
|
417
|
+
const frameRef = useRef(frame);
|
|
418
|
+
frameRef.current = frame;
|
|
419
|
+
const completeRef = useRef(onComplete);
|
|
420
|
+
completeRef.current = onComplete;
|
|
421
|
+
const loopRef = useRef(null);
|
|
422
|
+
useEffect(() => {
|
|
423
|
+
if (typeof window === "undefined" || typeof requestAnimationFrame === "undefined") return;
|
|
424
|
+
const vloop = createVizLoop(
|
|
425
|
+
(dt, elapsed) => frameRef.current(dt, elapsed),
|
|
426
|
+
{
|
|
427
|
+
loop,
|
|
428
|
+
durationMs,
|
|
429
|
+
onComplete: () => completeRef.current?.(),
|
|
430
|
+
onPlayingChange: setPlaying
|
|
431
|
+
},
|
|
432
|
+
{ raf: requestAnimationFrame, caf: cancelAnimationFrame }
|
|
433
|
+
);
|
|
434
|
+
loopRef.current = vloop;
|
|
435
|
+
const onVisibility = () => vloop.setHidden(document.hidden);
|
|
436
|
+
document.addEventListener("visibilitychange", onVisibility);
|
|
437
|
+
if (autoStart && !document.hidden) vloop.play();
|
|
438
|
+
return () => {
|
|
439
|
+
document.removeEventListener("visibilitychange", onVisibility);
|
|
440
|
+
vloop.dispose();
|
|
441
|
+
loopRef.current = null;
|
|
442
|
+
};
|
|
443
|
+
}, []);
|
|
444
|
+
const play = useCallback(() => loopRef.current?.play(), []);
|
|
445
|
+
const pause = useCallback(() => loopRef.current?.pause(), []);
|
|
446
|
+
const toggle = useCallback(() => loopRef.current?.toggle(), []);
|
|
447
|
+
const restart = useCallback(() => loopRef.current?.restart(), []);
|
|
448
|
+
return { playing, play, pause, toggle, restart };
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
// src/case/caseModel.ts
|
|
452
|
+
var caseKind = (c) => c.kind ?? "synthetic";
|
|
453
|
+
var KIND_ORDER = ["synthetic", "real", "uploaded"];
|
|
454
|
+
function sourcesPresent(cases) {
|
|
455
|
+
const set = new Set(cases.map(caseKind));
|
|
456
|
+
return KIND_ORDER.filter((k) => set.has(k));
|
|
457
|
+
}
|
|
458
|
+
function groupByCategory(cases) {
|
|
459
|
+
const order = [];
|
|
460
|
+
const map = /* @__PURE__ */ new Map();
|
|
461
|
+
for (const c of cases) {
|
|
462
|
+
const cat = c.category ?? "";
|
|
463
|
+
if (!map.has(cat)) {
|
|
464
|
+
map.set(cat, []);
|
|
465
|
+
order.push(cat);
|
|
466
|
+
}
|
|
467
|
+
map.get(cat).push(c);
|
|
468
|
+
}
|
|
469
|
+
return order.map((category) => ({ category, cases: map.get(category) }));
|
|
470
|
+
}
|
|
471
|
+
function casesInSource(cases, source) {
|
|
472
|
+
if (!source) return cases;
|
|
473
|
+
return cases.filter((c) => caseKind(c) === source);
|
|
474
|
+
}
|
|
475
|
+
function caseTooltip(c) {
|
|
476
|
+
return [c.anchor, c.expectedBand].filter(Boolean).join(" \xB7 ");
|
|
477
|
+
}
|
|
478
|
+
function readCaseParam(search, param = "case") {
|
|
479
|
+
return new URLSearchParams(search).get(param);
|
|
480
|
+
}
|
|
481
|
+
function withCaseParam(search, id, param = "case") {
|
|
482
|
+
const p = new URLSearchParams(search);
|
|
483
|
+
p.set(param, id);
|
|
484
|
+
const s = p.toString();
|
|
485
|
+
return s ? `?${s}` : "";
|
|
486
|
+
}
|
|
487
|
+
var TEXT = {
|
|
488
|
+
en: {
|
|
489
|
+
source: "Source",
|
|
490
|
+
synthetic: "Synthetic",
|
|
491
|
+
real: "Real",
|
|
492
|
+
uploaded: "Uploaded",
|
|
493
|
+
lockedNote: "Scenario knobs are locked on a real sample \u2014 you pick which datum; every tool runs on it as-is.",
|
|
494
|
+
modifiedPrefix: "modified from",
|
|
495
|
+
reset: "reset"
|
|
496
|
+
},
|
|
497
|
+
es: {
|
|
498
|
+
source: "Fuente",
|
|
499
|
+
synthetic: "Sint\xE9tico",
|
|
500
|
+
real: "Real",
|
|
501
|
+
uploaded: "Subido",
|
|
502
|
+
lockedNote: "Los controles del escenario quedan bloqueados en una muestra real: eliges el dato; todas las herramientas corren sobre \xE9l tal cual.",
|
|
503
|
+
modifiedPrefix: "modificado desde",
|
|
504
|
+
reset: "restablecer"
|
|
505
|
+
}
|
|
506
|
+
};
|
|
507
|
+
var KIND_TAG = { synthetic: "S", real: "R", uploaded: "U" };
|
|
508
|
+
function CaseSelector(props) {
|
|
509
|
+
const {
|
|
510
|
+
cases,
|
|
511
|
+
selectedId,
|
|
512
|
+
onSelect,
|
|
513
|
+
source,
|
|
514
|
+
onSourceChange,
|
|
515
|
+
lockedNote,
|
|
516
|
+
modifiedFromId,
|
|
517
|
+
onResetToCanonical,
|
|
518
|
+
lang = "en",
|
|
519
|
+
text,
|
|
520
|
+
deepLink,
|
|
521
|
+
ariaLabel,
|
|
522
|
+
className
|
|
523
|
+
} = props;
|
|
524
|
+
const t = { ...TEXT[lang], ...text };
|
|
525
|
+
const baseId = useId();
|
|
526
|
+
const param = typeof deepLink === "string" ? deepLink : "case";
|
|
527
|
+
useEffect(() => {
|
|
528
|
+
if (!deepLink || typeof window === "undefined") return;
|
|
529
|
+
const fromUrl = readCaseParam(window.location.search, param);
|
|
530
|
+
if (fromUrl && fromUrl !== selectedId && cases.some((c) => c.id === fromUrl)) onSelect(fromUrl);
|
|
531
|
+
}, []);
|
|
532
|
+
useEffect(() => {
|
|
533
|
+
if (!deepLink || typeof window === "undefined") return;
|
|
534
|
+
const next = withCaseParam(window.location.search, selectedId, param);
|
|
535
|
+
if (next !== window.location.search) {
|
|
536
|
+
window.history.replaceState(null, "", `${window.location.pathname}${next}${window.location.hash}`);
|
|
537
|
+
}
|
|
538
|
+
}, [deepLink, param, selectedId]);
|
|
539
|
+
const lanes = source ? sourcesPresent(cases) : [];
|
|
540
|
+
const visible = casesInSource(cases, source);
|
|
541
|
+
const groups = groupByCategory(visible);
|
|
542
|
+
const modified = cases.find((c) => c.id === modifiedFromId) ?? null;
|
|
543
|
+
return /* @__PURE__ */ jsxs("div", { className: `cs${className ? ` ${className}` : ""}`, role: "group", "aria-label": ariaLabel ?? "Case selector", children: [
|
|
544
|
+
source && lanes.length > 1 && /* @__PURE__ */ jsxs("div", { className: "cs-source", children: [
|
|
545
|
+
/* @__PURE__ */ jsx("span", { className: "cs-source-label", children: t.source }),
|
|
546
|
+
/* @__PURE__ */ jsx("div", { className: "cs-source-tabs", role: "tablist", "aria-label": t.source, children: lanes.map((k) => /* @__PURE__ */ jsx(
|
|
547
|
+
"button",
|
|
548
|
+
{
|
|
549
|
+
type: "button",
|
|
550
|
+
role: "tab",
|
|
551
|
+
"aria-selected": source === k,
|
|
552
|
+
className: source === k ? "subtab active" : "subtab",
|
|
553
|
+
onClick: () => onSourceChange?.(k),
|
|
554
|
+
children: k === "synthetic" ? t.synthetic : k === "real" ? t.real : t.uploaded
|
|
555
|
+
},
|
|
556
|
+
k
|
|
557
|
+
)) })
|
|
558
|
+
] }),
|
|
559
|
+
source && source !== "synthetic" && /* @__PURE__ */ jsx("p", { className: "cs-locked banner", children: lockedNote ?? t.lockedNote }),
|
|
560
|
+
groups.map((g) => /* @__PURE__ */ jsxs("div", { className: "cs-group", role: "group", "aria-label": g.category || void 0, children: [
|
|
561
|
+
g.category && /* @__PURE__ */ jsx("span", { className: "cs-group-label", children: g.category }),
|
|
562
|
+
/* @__PURE__ */ jsx("div", { className: "cs-chips", children: g.cases.map((c) => {
|
|
563
|
+
const on = c.id === selectedId;
|
|
564
|
+
const tip = caseTooltip(c);
|
|
565
|
+
return /* @__PURE__ */ jsxs(
|
|
566
|
+
"button",
|
|
567
|
+
{
|
|
568
|
+
type: "button",
|
|
569
|
+
id: `${baseId}-case-${c.id}`,
|
|
570
|
+
className: `cs-chip${on ? " on" : ""}`,
|
|
571
|
+
"aria-pressed": on,
|
|
572
|
+
disabled: c.disabled,
|
|
573
|
+
title: tip || void 0,
|
|
574
|
+
onClick: () => onSelect(c.id),
|
|
575
|
+
children: [
|
|
576
|
+
/* @__PURE__ */ jsx("span", { className: "cs-chip-id", children: c.id }),
|
|
577
|
+
/* @__PURE__ */ jsx("span", { className: "cs-chip-name", children: c.name }),
|
|
578
|
+
/* @__PURE__ */ jsx("span", { className: `cs-kind cs-kind-${caseKindOf(c)}`, "aria-hidden": "true", children: KIND_TAG[caseKindOf(c)] })
|
|
579
|
+
]
|
|
580
|
+
},
|
|
581
|
+
c.id
|
|
582
|
+
);
|
|
583
|
+
}) })
|
|
584
|
+
] }, g.category || "_")),
|
|
585
|
+
modified && /* @__PURE__ */ jsxs("div", { className: "cs-modified", children: [
|
|
586
|
+
/* @__PURE__ */ jsxs("span", { className: "badge accent", children: [
|
|
587
|
+
t.modifiedPrefix,
|
|
588
|
+
" ",
|
|
589
|
+
/* @__PURE__ */ jsx("strong", { children: modified.id })
|
|
590
|
+
] }),
|
|
591
|
+
onResetToCanonical && /* @__PURE__ */ jsx("button", { type: "button", className: "cs-reset", onClick: onResetToCanonical, children: t.reset })
|
|
592
|
+
] })
|
|
305
593
|
] });
|
|
306
594
|
}
|
|
595
|
+
function caseKindOf(c) {
|
|
596
|
+
return c.kind ?? "synthetic";
|
|
597
|
+
}
|
|
307
598
|
function Tabs({ tabs, initial, ariaLabel }) {
|
|
308
599
|
const baseId = useId();
|
|
309
600
|
const first = tabs[0]?.id ?? "";
|
|
@@ -497,4 +788,4 @@ function ReferenceList({ ids, heading }) {
|
|
|
497
788
|
] });
|
|
498
789
|
}
|
|
499
790
|
|
|
500
|
-
export { AppShell, ArchitectureModal, Callout, CitationsProvider, Cite, Equation, Figure, InlineMath, LanguageToggle, ReferenceList, Refs, SubTabs, Tabs, ThemeToggle, applyTheme, readTheme, useLangStore, useShellLang, useThemeStore };
|
|
791
|
+
export { AppShell, ArchitectureModal, Callout, CaseSelector, CitationsProvider, Cite, Equation, Figure, InlineMath, LanguageToggle, ReferenceList, Refs, SubTabs, Tabs, ThemeToggle, applyTheme, caseKind, caseTooltip, casesInSource, createVizLoop, groupByCategory, readCaseParam, readTheme, sourcesPresent, useLangStore, usePausedViz, useShellLang, useThemeStore, withCaseParam };
|
package/package.json
CHANGED
|
@@ -1,54 +1,56 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@fasl-work/caos-app-shell",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Shared web-app shell + content primitives + design system for the CAOS / Faena public apps (ADR-0016).",
|
|
5
|
-
"license": "MIT",
|
|
6
|
-
"author": "Felipe Santibáñez-Leal",
|
|
7
|
-
"repository": {
|
|
8
|
-
"type": "git",
|
|
9
|
-
"url": "git+https://github.com/fsantibanezleal/CAOS_APP_SHELL.git"
|
|
10
|
-
},
|
|
11
|
-
"type": "module",
|
|
12
|
-
"publishConfig": {
|
|
13
|
-
"access": "public"
|
|
14
|
-
},
|
|
15
|
-
"sideEffects": [
|
|
16
|
-
"*.css"
|
|
17
|
-
],
|
|
18
|
-
"exports": {
|
|
19
|
-
".": {
|
|
20
|
-
"types": "./dist/index.d.ts",
|
|
21
|
-
"import": "./dist/index.js"
|
|
22
|
-
},
|
|
23
|
-
"./styles.css": "./styles.css"
|
|
24
|
-
},
|
|
25
|
-
"files": [
|
|
26
|
-
"dist",
|
|
27
|
-
"styles.css"
|
|
28
|
-
],
|
|
29
|
-
"scripts": {
|
|
30
|
-
"build": "tsup",
|
|
31
|
-
"
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
"
|
|
36
|
-
"react": "
|
|
37
|
-
"react
|
|
38
|
-
"react-
|
|
39
|
-
"
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
"@types/
|
|
44
|
-
"@types/react
|
|
45
|
-
"
|
|
46
|
-
"
|
|
47
|
-
"react": "^
|
|
48
|
-
"react
|
|
49
|
-
"react-
|
|
50
|
-
"
|
|
51
|
-
"
|
|
52
|
-
"
|
|
53
|
-
|
|
54
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "@fasl-work/caos-app-shell",
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"description": "Shared web-app shell + content primitives + design system for the CAOS / Faena public apps (ADR-0016).",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "Felipe Santibáñez-Leal",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/fsantibanezleal/CAOS_APP_SHELL.git"
|
|
10
|
+
},
|
|
11
|
+
"type": "module",
|
|
12
|
+
"publishConfig": {
|
|
13
|
+
"access": "public"
|
|
14
|
+
},
|
|
15
|
+
"sideEffects": [
|
|
16
|
+
"*.css"
|
|
17
|
+
],
|
|
18
|
+
"exports": {
|
|
19
|
+
".": {
|
|
20
|
+
"types": "./dist/index.d.ts",
|
|
21
|
+
"import": "./dist/index.js"
|
|
22
|
+
},
|
|
23
|
+
"./styles.css": "./styles.css"
|
|
24
|
+
},
|
|
25
|
+
"files": [
|
|
26
|
+
"dist",
|
|
27
|
+
"styles.css"
|
|
28
|
+
],
|
|
29
|
+
"scripts": {
|
|
30
|
+
"build": "tsup",
|
|
31
|
+
"test": "node --import tsx --test test/vizLoop.test.ts test/caseModel.test.ts",
|
|
32
|
+
"prepublishOnly": "npm run build"
|
|
33
|
+
},
|
|
34
|
+
"peerDependencies": {
|
|
35
|
+
"katex": "^0.16.0",
|
|
36
|
+
"lucide-react": ">=0.400.0",
|
|
37
|
+
"react": "^18 || ^19",
|
|
38
|
+
"react-dom": "^18 || ^19",
|
|
39
|
+
"react-router-dom": "^6 || ^7",
|
|
40
|
+
"zustand": "^4 || ^5"
|
|
41
|
+
},
|
|
42
|
+
"devDependencies": {
|
|
43
|
+
"@types/katex": "^0.16.7",
|
|
44
|
+
"@types/react": "^19.0.0",
|
|
45
|
+
"@types/react-dom": "^19.0.0",
|
|
46
|
+
"katex": "^0.16.11",
|
|
47
|
+
"lucide-react": "^0.469.0",
|
|
48
|
+
"react": "^19.0.0",
|
|
49
|
+
"react-dom": "^19.0.0",
|
|
50
|
+
"react-router-dom": "^7.1.1",
|
|
51
|
+
"tsup": "^8.3.5",
|
|
52
|
+
"tsx": "^4.23.0",
|
|
53
|
+
"typescript": "^5.7.3",
|
|
54
|
+
"zustand": "^5.0.2"
|
|
55
|
+
}
|
|
56
|
+
}
|