@fasl-work/caos-app-shell 0.5.0 → 0.6.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/README.md CHANGED
@@ -13,7 +13,7 @@ fix lands in one place.
13
13
  ```bash
14
14
  npm i @fasl-work/caos-app-shell
15
15
  # peer deps (the app provides them):
16
- npm i react react-dom react-router-dom lucide-react katex zustand
16
+ npm i react react-dom react-router-dom lucide-react katex zustand
17
17
  ```
18
18
 
19
19
  ## Use
@@ -60,20 +60,20 @@ const config: ShellConfig = {
60
60
 
61
61
  ## Exports
62
62
 
63
- `AppShell`, `WorkbenchShell`, `ThemeToggle`, `LanguageToggle`, `useThemeStore`, `applyTheme`, `readTheme`, `useLangStore`,
63
+ `AppShell`, `WorkbenchShell`, `ThemeToggle`, `LanguageToggle`, `useThemeStore`, `applyTheme`, `readTheme`, `useLangStore`,
64
64
  `useShellLang`, `usePausedViz`, `createVizLoop`, `CaseSelector` (+ `caseModel` helpers), `Tabs`, `SubTabs`,
65
65
  `Callout`, `Equation`, `InlineMath`, `Figure`, `CitationsProvider`, `Cite`, `Refs`, `ReferenceList`, plus
66
- the `@fasl-work/caos-app-shell/styles.css` design system.
67
-
68
- ### Authenticated workbenches
69
-
70
- `WorkbenchShell` is the shared frame for products whose authenticated UI needs a desktop sidebar and
71
- mobile bottom navigation. It renders typed routes and the main landmark while the product supplies its
72
- own stateful controls through `brand`, `sidebarFooter`, `headerLead`, `headerActions`, and `overlays`.
73
- Authentication, account policy, preference persistence, chat, and modal content remain product-owned.
74
- The component uses the stable core `NavLink` contract and supports `react-router` 6, 7, and 8.
75
- Browser applications on 6/7 install the matching `react-router-dom`, which supplies the core peer;
76
- Router 8 applications provide `react-router` directly. Do not mix different core and DOM majors in
77
- one application.
66
+ the `@fasl-work/caos-app-shell/styles.css` design system.
67
+
68
+ ### Authenticated workbenches
69
+
70
+ `WorkbenchShell` is the shared frame for products whose authenticated UI needs a desktop sidebar and
71
+ mobile bottom navigation. It renders typed routes and the main landmark while the product supplies its
72
+ own stateful controls through `brand`, `sidebarFooter`, `headerLead`, `headerActions`, and `overlays`.
73
+ Authentication, account policy, preference persistence, chat, and modal content remain product-owned.
74
+ The component uses the stable core `NavLink` contract and supports `react-router` 6, 7, and 8.
75
+ Browser applications on 6/7 install the matching `react-router-dom`, which supplies the core peer;
76
+ Router 8 applications provide `react-router` directly. Do not mix different core and DOM majors in
77
+ one application.
78
78
 
79
79
  MIT · part of the Faena mining-analytics hub.
package/dist/index.d.ts CHANGED
@@ -10,7 +10,15 @@ interface ArchTab {
10
10
  /** the explanation body (paragraphs separated by a blank line). */
11
11
  body_en: string;
12
12
  body_es: string;
13
- /** an inline '<svg…>…</svg>' string OR a path under the app's public/ (fetched + inlined). */
13
+ /**
14
+ * an inline '<svg…>…</svg>' string OR a path under the app's public/ (fetched + inlined).
15
+ *
16
+ * ONE file carries BOTH languages (ADR-0058). Tag each translatable `<text>` twice at the same
17
+ * coordinates, `class="… l-en"` and `class="… l-es"`; the modal wrapper sets `data-arch-lang`
18
+ * and the shell stylesheet shows exactly one. Two files would be two things to keep in step, and
19
+ * the one that is not on screen is the one that goes stale. Anything language-neutral (a number,
20
+ * a file name, an identifier) needs no pair.
21
+ */
14
22
  svg: string;
15
23
  }
16
24
  interface ArchitectureConfig {
package/dist/index.js CHANGED
@@ -223,7 +223,7 @@ function ArchitectureModal({ config, onClose }) {
223
223
  t.id
224
224
  );
225
225
  }) }),
226
- /* @__PURE__ */ jsxs("div", { role: "tabpanel", style: { overflowY: "auto", padding: "14px 16px 18px" }, children: [
226
+ /* @__PURE__ */ jsxs("div", { role: "tabpanel", "data-arch-lang": es ? "es" : "en", style: { overflowY: "auto", padding: "14px 16px 18px" }, children: [
227
227
  body.map((p, i) => /* @__PURE__ */ jsx("p", { style: { color: "var(--color-fg)", fontSize: 13, lineHeight: 1.65, margin: i === 0 ? "0 0 10px" : "10px 0" }, children: p }, i)),
228
228
  err && /* @__PURE__ */ jsxs("div", { style: { color: "var(--color-warn, #f87171)", fontSize: 12 }, children: [
229
229
  "SVG: ",
package/package.json CHANGED
@@ -1,56 +1,56 @@
1
- {
2
- "name": "@fasl-work/caos-app-shell",
3
- "version": "0.5.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 test/workbenchShell.test.tsx",
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",
1
+ {
2
+ "name": "@fasl-work/caos-app-shell",
3
+ "version": "0.6.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/**/*.test.ts\" \"test/**/*.test.tsx\"",
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
39
  "react-router": "^6 || ^7 || ^8",
40
- "zustand": "^4 || ^5"
41
- },
40
+ "zustand": "^4 || ^5"
41
+ },
42
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",
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
50
  "react-router": "^8.3.0",
51
- "tsup": "^8.3.5",
52
- "tsx": "^4.23.0",
53
- "typescript": "^5.7.3",
51
+ "tsup": "^8.3.5",
52
+ "tsx": "^4.23.0",
53
+ "typescript": "^5.7.3",
54
54
  "zustand": "^5.0.2"
55
55
  },
56
56
  "overrides": {
package/styles.css CHANGED
@@ -254,31 +254,31 @@ code, kbd { font-family: var(--font-mono); }
254
254
  .cs-kind { font-size: 0.62rem; font-weight: 700; line-height: 1; padding: 0.12rem 0.28rem; border-radius: 4px; border: 1px solid var(--color-border); color: var(--color-fg-faint); background: var(--color-surface-2); align-self: center; }
255
255
  .cs-kind-real { color: var(--color-accent-2); border-color: color-mix(in oklab, var(--color-accent-2) 40%, transparent); }
256
256
  .cs-kind-uploaded { color: var(--color-warn); border-color: color-mix(in oklab, var(--color-warn) 40%, transparent); }
257
- .cs-modified { display: flex; align-items: center; gap: 0.5rem; }
258
- .cs-reset { border: none; background: transparent; color: var(--color-accent); font-size: 0.8rem; font-weight: 600; padding: 0.1rem 0.2rem; text-decoration: underline; text-underline-offset: 2px; }
259
-
260
- /* Authenticated workbench frame. Product styles may refine tokens and controls, but the package owns
261
- the responsive navigation/layout contract and keeps route/content landmarks consistent. */
262
- .caos-workbench-shell { min-height: 100vh; display: grid; grid-template-columns: 238px minmax(0, 1fr); }
263
- .caos-workbench-sidebar { position: fixed; inset: 0 auto 0 0; z-index: 20; width: 238px; display: flex; flex-direction: column; padding: 1.25rem 0.875rem; border-right: 1px solid var(--color-border); background: var(--color-surface); }
264
- .caos-workbench-sidebar nav { display: grid; gap: 0.25rem; }
265
- .caos-workbench-sidebar nav a { display: flex; align-items: center; gap: 0.75rem; padding: 0.625rem 0.7rem; border: 1px solid transparent; border-radius: 0.7rem; color: var(--color-fg-subtle); font-size: 0.9rem; font-weight: 650; }
266
- .caos-workbench-sidebar nav a:hover { color: var(--color-fg); background: var(--color-surface-2); text-decoration: none; }
267
- .caos-workbench-sidebar nav a.active { color: var(--color-accent); border-color: color-mix(in oklab, var(--color-accent) 24%, transparent); background: var(--color-accent-soft); }
268
- .caos-workbench-main { grid-column: 2; min-width: 0; }
269
- .caos-workbench-header { position: sticky; top: 0; z-index: 15; min-height: 64px; display: flex; align-items: center; justify-content: space-between; gap: 1rem; padding: 0 2rem; border-bottom: 1px solid var(--color-border); background: color-mix(in oklab, var(--color-bg) 88%, transparent); backdrop-filter: blur(12px); }
270
- .caos-workbench-content { width: min(1540px, 100%); margin: 0 auto; padding: 2.25rem 2rem 4rem; }
271
-
272
- @media (max-width: 760px) {
273
- .caos-workbench-shell { display: block; padding-bottom: 66px; }
274
- .caos-workbench-sidebar { inset: auto 0 0; width: auto; height: 62px; display: block; border: 0; border-top: 1px solid var(--color-border); padding: 5px 8px; }
275
- .caos-workbench-sidebar > :not(nav) { display: none; }
276
- .caos-workbench-sidebar nav { grid-template-columns: repeat(var(--caos-workbench-route-count, 5), minmax(0, 1fr)); }
277
- .caos-workbench-sidebar nav a { display: grid; justify-items: center; gap: 2px; overflow: hidden; padding: 5px; font-size: 0.7rem; text-overflow: ellipsis; white-space: nowrap; }
278
- .caos-workbench-main { min-width: 0; }
279
- .caos-workbench-header { min-height: 58px; padding: 0 1rem; }
280
- .caos-workbench-content { padding: 1.5rem 1rem 2.5rem; }
281
- }
257
+ .cs-modified { display: flex; align-items: center; gap: 0.5rem; }
258
+ .cs-reset { border: none; background: transparent; color: var(--color-accent); font-size: 0.8rem; font-weight: 600; padding: 0.1rem 0.2rem; text-decoration: underline; text-underline-offset: 2px; }
259
+
260
+ /* Authenticated workbench frame. Product styles may refine tokens and controls, but the package owns
261
+ the responsive navigation/layout contract and keeps route/content landmarks consistent. */
262
+ .caos-workbench-shell { min-height: 100vh; display: grid; grid-template-columns: 238px minmax(0, 1fr); }
263
+ .caos-workbench-sidebar { position: fixed; inset: 0 auto 0 0; z-index: 20; width: 238px; display: flex; flex-direction: column; padding: 1.25rem 0.875rem; border-right: 1px solid var(--color-border); background: var(--color-surface); }
264
+ .caos-workbench-sidebar nav { display: grid; gap: 0.25rem; }
265
+ .caos-workbench-sidebar nav a { display: flex; align-items: center; gap: 0.75rem; padding: 0.625rem 0.7rem; border: 1px solid transparent; border-radius: 0.7rem; color: var(--color-fg-subtle); font-size: 0.9rem; font-weight: 650; }
266
+ .caos-workbench-sidebar nav a:hover { color: var(--color-fg); background: var(--color-surface-2); text-decoration: none; }
267
+ .caos-workbench-sidebar nav a.active { color: var(--color-accent); border-color: color-mix(in oklab, var(--color-accent) 24%, transparent); background: var(--color-accent-soft); }
268
+ .caos-workbench-main { grid-column: 2; min-width: 0; }
269
+ .caos-workbench-header { position: sticky; top: 0; z-index: 15; min-height: 64px; display: flex; align-items: center; justify-content: space-between; gap: 1rem; padding: 0 2rem; border-bottom: 1px solid var(--color-border); background: color-mix(in oklab, var(--color-bg) 88%, transparent); backdrop-filter: blur(12px); }
270
+ .caos-workbench-content { width: min(1540px, 100%); margin: 0 auto; padding: 2.25rem 2rem 4rem; }
271
+
272
+ @media (max-width: 760px) {
273
+ .caos-workbench-shell { display: block; padding-bottom: 66px; }
274
+ .caos-workbench-sidebar { inset: auto 0 0; width: auto; height: 62px; display: block; border: 0; border-top: 1px solid var(--color-border); padding: 5px 8px; }
275
+ .caos-workbench-sidebar > :not(nav) { display: none; }
276
+ .caos-workbench-sidebar nav { grid-template-columns: repeat(var(--caos-workbench-route-count, 5), minmax(0, 1fr)); }
277
+ .caos-workbench-sidebar nav a { display: grid; justify-items: center; gap: 2px; overflow: hidden; padding: 5px; font-size: 0.7rem; text-overflow: ellipsis; white-space: nowrap; }
278
+ .caos-workbench-main { min-width: 0; }
279
+ .caos-workbench-header { min-height: 58px; padding: 0 1rem; }
280
+ .caos-workbench-content { padding: 1.5rem 1rem 2.5rem; }
281
+ }
282
282
 
283
283
  /* CONTAINED LAYOUT. A `nowrap` tab bar sizes its container to its intrinsic width unless every
284
284
  ancestor is allowed to shrink: a flex/grid item defaults to `min-width: auto`. Without this, making
@@ -301,3 +301,11 @@ html, body { overflow-x: hidden; }
301
301
  /* A viewport-filling app must not carry the prose footer margin: it becomes dead space between the
302
302
  content and the chrome. Measured on ChargeCascade as exactly 48px (3rem). */
303
303
  .app-shell.fixed .site-footer { margin-top: 0; }
304
+
305
+ /* ADR-0058 diagram i18n. A hand-authored architecture SVG carries BOTH languages inside ONE file,
306
+ and the modal wrapper picks one. Two files would be two things to keep in step, and the one not
307
+ on screen is the one that goes stale. The rules are scoped to [data-arch-lang] so the short class
308
+ names cannot collide with an app's own styles. */
309
+ [data-arch-lang] .l-es { display: none; }
310
+ [data-arch-lang="es"] .l-en { display: none; }
311
+ [data-arch-lang="es"] .l-es { display: inline; }