@fasl-work/caos-app-shell 0.11.1 → 0.12.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/dist/index.d.ts +90 -2
- package/dist/index.js +525 -39
- package/gate/areas.mjs +134 -6
- package/gate/inpage.mjs +87 -1
- package/package.json +4 -2
- package/reserved-classes.json +48 -0
- package/src/content/executive.schema.json +141 -0
- package/styles.css +40 -10
package/dist/index.js
CHANGED
|
@@ -123,21 +123,21 @@ function validateArchitectureConfig(config) {
|
|
|
123
123
|
const out = [];
|
|
124
124
|
if (config.tabs.length < 5) out.push(`the architecture modal has ${config.tabs.length} tabs; ADR-0058 requires at least 5`);
|
|
125
125
|
const known = new Set(SHELL_TOKENS);
|
|
126
|
-
for (const
|
|
127
|
-
if (!
|
|
128
|
-
out.push(`architecture tab "${
|
|
126
|
+
for (const t2 of config.tabs) {
|
|
127
|
+
if (!t2.en?.trim() || !t2.es?.trim() || !t2.body_en?.trim() || !t2.body_es?.trim()) {
|
|
128
|
+
out.push(`architecture tab "${t2.id}" lacks a label or a body in one language`);
|
|
129
129
|
}
|
|
130
|
-
const svg =
|
|
130
|
+
const svg = t2.svg.trim();
|
|
131
131
|
if (!svg.startsWith("<svg")) {
|
|
132
|
-
out.push(`architecture tab "${
|
|
132
|
+
out.push(`architecture tab "${t2.id}": the diagram must be an inline SVG string (import it with ?raw), not a URL`);
|
|
133
133
|
continue;
|
|
134
134
|
}
|
|
135
135
|
for (const name of new Set([...svg.matchAll(/var\((--[a-z0-9-]+)/gi)].map((x) => x[1]))) {
|
|
136
|
-
if (!known.has(name)) out.push(`architecture tab "${
|
|
136
|
+
if (!known.has(name)) out.push(`architecture tab "${t2.id}" uses ${name}, which the shell does not define`);
|
|
137
137
|
}
|
|
138
138
|
const hex = svg.replace(/url\(\s*#[^)]*\)/gi, "").replace(/href\s*=\s*["']#[^"']*["']/gi, "").match(/#[0-9a-f]{3,8}\b/gi);
|
|
139
139
|
if (hex) {
|
|
140
|
-
out.push(`architecture tab "${
|
|
140
|
+
out.push(`architecture tab "${t2.id}" uses hex colours (${[...new Set(hex)].slice(0, 3).join(", ")}); use shell tokens so it follows the theme`);
|
|
141
141
|
}
|
|
142
142
|
}
|
|
143
143
|
return out;
|
|
@@ -191,7 +191,7 @@ function ArchitectureModal({ config, onClose }) {
|
|
|
191
191
|
if (opener?.isConnected) opener.focus();
|
|
192
192
|
};
|
|
193
193
|
}, []);
|
|
194
|
-
const tab = tabs.find((
|
|
194
|
+
const tab = tabs.find((t2) => t2.id === active) ?? tabs[0];
|
|
195
195
|
useEffect(() => {
|
|
196
196
|
if (!tab) return;
|
|
197
197
|
setErr(null);
|
|
@@ -245,19 +245,19 @@ function ArchitectureModal({ config, onClose }) {
|
|
|
245
245
|
}
|
|
246
246
|
)
|
|
247
247
|
] }),
|
|
248
|
-
/* @__PURE__ */ jsx("div", { role: "tablist", "aria-label": title, style: { display: "flex", flexWrap: "wrap", gap: 4, padding: "8px 14px 0", borderBottom: "1px solid var(--color-border)" }, children: tabs.map((
|
|
249
|
-
const sel =
|
|
248
|
+
/* @__PURE__ */ jsx("div", { role: "tablist", "aria-label": title, style: { display: "flex", flexWrap: "wrap", gap: 4, padding: "8px 14px 0", borderBottom: "1px solid var(--color-border)" }, children: tabs.map((t2) => {
|
|
249
|
+
const sel = t2.id === active;
|
|
250
250
|
return /* @__PURE__ */ jsx(
|
|
251
251
|
"button",
|
|
252
252
|
{
|
|
253
|
-
id: `${id}-${
|
|
253
|
+
id: `${id}-${t2.id}`,
|
|
254
254
|
role: "tab",
|
|
255
255
|
"aria-selected": sel,
|
|
256
256
|
"aria-controls": `${id}-panel`,
|
|
257
257
|
tabIndex: sel ? 0 : -1,
|
|
258
|
-
onClick: () => setActive(
|
|
258
|
+
onClick: () => setActive(t2.id),
|
|
259
259
|
onKeyDown: (event) => {
|
|
260
|
-
const index = tabs.indexOf(
|
|
260
|
+
const index = tabs.indexOf(t2);
|
|
261
261
|
const next = event.key === "Home" ? 0 : event.key === "End" ? tabs.length - 1 : event.key === "ArrowRight" ? (index + 1) % tabs.length : event.key === "ArrowLeft" ? (index - 1 + tabs.length) % tabs.length : -1;
|
|
262
262
|
if (next < 0) return;
|
|
263
263
|
event.preventDefault();
|
|
@@ -275,9 +275,9 @@ function ArchitectureModal({ config, onClose }) {
|
|
|
275
275
|
color: sel ? "var(--color-accent-fg, #fff)" : "var(--color-fg-subtle)",
|
|
276
276
|
fontWeight: sel ? 600 : 400
|
|
277
277
|
},
|
|
278
|
-
children: es ?
|
|
278
|
+
children: es ? t2.es : t2.en
|
|
279
279
|
},
|
|
280
|
-
|
|
280
|
+
t2.id
|
|
281
281
|
);
|
|
282
282
|
}) }),
|
|
283
283
|
/* @__PURE__ */ jsxs("div", { id: `${id}-panel`, role: "tabpanel", "aria-labelledby": `${id}-${tab.id}`, "data-arch-lang": es ? "es" : "en", "data-tab": tab.id, "data-state": err ? "missing" : svg === null ? "loading" : "ready", style: { overflowY: "auto", minHeight: 0, padding: "14px 16px 18px" }, children: [
|
|
@@ -522,14 +522,14 @@ function createVizLoop(frame, options, deps) {
|
|
|
522
522
|
handle = null;
|
|
523
523
|
}
|
|
524
524
|
};
|
|
525
|
-
function tick(
|
|
525
|
+
function tick(t2) {
|
|
526
526
|
handle = null;
|
|
527
527
|
if (baseline) {
|
|
528
|
-
last =
|
|
528
|
+
last = t2;
|
|
529
529
|
baseline = false;
|
|
530
530
|
}
|
|
531
|
-
const dt =
|
|
532
|
-
last =
|
|
531
|
+
const dt = t2 - last;
|
|
532
|
+
last = t2;
|
|
533
533
|
elapsed += dt;
|
|
534
534
|
let e = elapsed;
|
|
535
535
|
const capped = durationMs != null && e >= durationMs;
|
|
@@ -712,7 +712,7 @@ function CaseSelector(props) {
|
|
|
712
712
|
className,
|
|
713
713
|
layout = "chips"
|
|
714
714
|
} = props;
|
|
715
|
-
const
|
|
715
|
+
const t2 = { ...TEXT[lang], ...text };
|
|
716
716
|
const baseId = useId();
|
|
717
717
|
const param = typeof deepLink === "string" ? deepLink : "case";
|
|
718
718
|
const linkPending = useRef(Boolean(deepLink));
|
|
@@ -735,8 +735,8 @@ function CaseSelector(props) {
|
|
|
735
735
|
const modified = cases.find((c) => c.id === modifiedFromId) ?? null;
|
|
736
736
|
return /* @__PURE__ */ jsxs("div", { className: `cs${className ? ` ${className}` : ""}`, role: "group", "aria-label": ariaLabel ?? "Case selector", children: [
|
|
737
737
|
source && lanes.length > 1 && /* @__PURE__ */ jsxs("div", { className: "cs-source", children: [
|
|
738
|
-
/* @__PURE__ */ jsx("span", { className: "cs-source-label", children:
|
|
739
|
-
/* @__PURE__ */ jsx("div", { className: "cs-source-tabs", role: "tablist", "aria-label":
|
|
738
|
+
/* @__PURE__ */ jsx("span", { className: "cs-source-label", children: t2.source }),
|
|
739
|
+
/* @__PURE__ */ jsx("div", { className: "cs-source-tabs", role: "tablist", "aria-label": t2.source, children: lanes.map((k) => /* @__PURE__ */ jsx(
|
|
740
740
|
"button",
|
|
741
741
|
{
|
|
742
742
|
type: "button",
|
|
@@ -744,12 +744,12 @@ function CaseSelector(props) {
|
|
|
744
744
|
"aria-selected": source === k,
|
|
745
745
|
className: source === k ? "subtab active" : "subtab",
|
|
746
746
|
onClick: () => onSourceChange?.(k),
|
|
747
|
-
children: k === "synthetic" ?
|
|
747
|
+
children: k === "synthetic" ? t2.synthetic : k === "real" ? t2.real : t2.uploaded
|
|
748
748
|
},
|
|
749
749
|
k
|
|
750
750
|
)) })
|
|
751
751
|
] }),
|
|
752
|
-
source && source !== "synthetic" && /* @__PURE__ */ jsx("p", { className: "cs-locked banner", children: lockedNote ??
|
|
752
|
+
source && source !== "synthetic" && /* @__PURE__ */ jsx("p", { className: "cs-locked banner", children: lockedNote ?? t2.lockedNote }),
|
|
753
753
|
layout === "select" && /* @__PURE__ */ jsx(
|
|
754
754
|
"select",
|
|
755
755
|
{
|
|
@@ -788,11 +788,11 @@ function CaseSelector(props) {
|
|
|
788
788
|
] }, g.category || "_")),
|
|
789
789
|
modified && /* @__PURE__ */ jsxs("div", { className: "cs-modified", children: [
|
|
790
790
|
/* @__PURE__ */ jsxs("span", { className: "badge accent", children: [
|
|
791
|
-
|
|
791
|
+
t2.modifiedPrefix,
|
|
792
792
|
" ",
|
|
793
793
|
/* @__PURE__ */ jsx("strong", { children: modified.name })
|
|
794
794
|
] }),
|
|
795
|
-
onResetToCanonical && /* @__PURE__ */ jsx("button", { type: "button", className: "cs-reset", onClick: onResetToCanonical, children:
|
|
795
|
+
onResetToCanonical && /* @__PURE__ */ jsx("button", { type: "button", className: "cs-reset", onClick: onResetToCanonical, children: t2.reset })
|
|
796
796
|
] })
|
|
797
797
|
] });
|
|
798
798
|
}
|
|
@@ -957,7 +957,7 @@ function Tabs({ tabs, initial, value, onChange, ariaLabel }) {
|
|
|
957
957
|
document.getElementById(`${baseId}-tab-${target.id}`)?.focus();
|
|
958
958
|
}
|
|
959
959
|
}
|
|
960
|
-
const current = tabs.find((
|
|
960
|
+
const current = tabs.find((t2) => t2.id === active) ?? tabs[0];
|
|
961
961
|
return /* @__PURE__ */ jsxs("div", { className: "tabs", children: [
|
|
962
962
|
/* @__PURE__ */ jsx("div", { className: "tablist", role: "tablist", "aria-label": ariaLabel, ref: rowRef, children: tabs.map((tab, idx) => {
|
|
963
963
|
const selected = tab.id === current?.id;
|
|
@@ -1025,7 +1025,7 @@ function SubTabs({ tabs, initial, value, onChange, ariaLabel, orientation = "hor
|
|
|
1025
1025
|
document.getElementById(`${baseId}-subtab-${target.id}`)?.focus();
|
|
1026
1026
|
}
|
|
1027
1027
|
}
|
|
1028
|
-
const current = tabs.find((
|
|
1028
|
+
const current = tabs.find((t2) => t2.id === active) ?? tabs[0];
|
|
1029
1029
|
return /* @__PURE__ */ jsxs("div", { className: vertical ? "subtabs subtabs-vertical" : "subtabs", children: [
|
|
1030
1030
|
/* @__PURE__ */ jsx(
|
|
1031
1031
|
"div",
|
|
@@ -1076,7 +1076,7 @@ function TabGroups({ groups, value, onChange, ariaLabel }) {
|
|
|
1076
1076
|
const [own, setOwn] = useState({ group: groups[0]?.id ?? "" });
|
|
1077
1077
|
const sel = value ?? own;
|
|
1078
1078
|
const group = groups.find((g) => g.id === sel.group) ?? groups[0];
|
|
1079
|
-
const tabOf = (g, wanted) => g.tabs.find((
|
|
1079
|
+
const tabOf = (g, wanted) => g.tabs.find((t2) => t2.id === wanted)?.id ?? g.tabs[0]?.id ?? "";
|
|
1080
1080
|
function set(next) {
|
|
1081
1081
|
if (value === void 0) setOwn(next);
|
|
1082
1082
|
onChange?.(next);
|
|
@@ -1137,7 +1137,7 @@ function Figure({ caption, children }) {
|
|
|
1137
1137
|
] });
|
|
1138
1138
|
}
|
|
1139
1139
|
var DOC_AREAS = {
|
|
1140
|
-
"/introduction": ["
|
|
1140
|
+
"/introduction": ["problem", "principles", "math", "pipeline", "honesty"],
|
|
1141
1141
|
"/methodology": ["method"],
|
|
1142
1142
|
"/implementation": ["architecture", "reproducibility", "engine", "lanes", "contract", "deployment"],
|
|
1143
1143
|
"/experiments": ["question", "metrics", "protocol", "datasets"],
|
|
@@ -1206,12 +1206,498 @@ function Stat({ value, unit, source }) {
|
|
|
1206
1206
|
] })
|
|
1207
1207
|
] });
|
|
1208
1208
|
}
|
|
1209
|
+
|
|
1210
|
+
// src/content/executive.schema.json
|
|
1211
|
+
var executive_schema_default = {
|
|
1212
|
+
$schema: "https://json-schema.org/draft/2020-12/schema",
|
|
1213
|
+
$id: "https://github.com/fsantibanezleal/CAOS_APP_SHELL/blob/main/src/content/executive.schema.json",
|
|
1214
|
+
title: "CAOS executive view data, version 1.0.0",
|
|
1215
|
+
description: "The one data file a CAOS product fills for the executive view of its Introduction (content/executive.json). Every text is { en, es }; nothing outside these fields is allowed. The writing limits (30 words per sentence, an answer of at most 2 sentences, one sentence for initiative, vision, statement, exec_problem and caption, no equation, no inline citation), the four_cs rule (absent until FOUR_CS names the 4 C's) and the sources-by-field rule are checked by validateExecutive in executive.ts, on top of this structure.",
|
|
1216
|
+
type: "object",
|
|
1217
|
+
additionalProperties: false,
|
|
1218
|
+
required: ["executive", "organisation", "initiative", "why_now", "vision", "outcomes", "dialogue", "illustrations", "sources"],
|
|
1219
|
+
properties: {
|
|
1220
|
+
executive: { $ref: "#/$defs/text", description: "One C-suite role, never a list." },
|
|
1221
|
+
organisation: { $ref: "#/$defs/text", description: "One industry and one context, never several regions." },
|
|
1222
|
+
initiative: { $ref: "#/$defs/text", description: "One sentence: what that executive owns and must achieve." },
|
|
1223
|
+
why_now: {
|
|
1224
|
+
type: "object",
|
|
1225
|
+
additionalProperties: false,
|
|
1226
|
+
required: ["figure", "deadline"],
|
|
1227
|
+
properties: {
|
|
1228
|
+
figure: { $ref: "#/$defs/figure" },
|
|
1229
|
+
deadline: { $ref: "#/$defs/text", description: "One date or deadline, for example 'by 1 December 2026'." }
|
|
1230
|
+
}
|
|
1231
|
+
},
|
|
1232
|
+
vision: { $ref: "#/$defs/text", description: "One sentence: what changes for the executive's business. Comes first in section 2." },
|
|
1233
|
+
outcomes: {
|
|
1234
|
+
type: "array",
|
|
1235
|
+
minItems: 3,
|
|
1236
|
+
maxItems: 5,
|
|
1237
|
+
items: {
|
|
1238
|
+
type: "object",
|
|
1239
|
+
additionalProperties: false,
|
|
1240
|
+
required: ["capability", "outcome", "proof"],
|
|
1241
|
+
properties: {
|
|
1242
|
+
capability: { $ref: "#/$defs/text", description: "What the product does, in plain words." },
|
|
1243
|
+
outcome: { $ref: "#/$defs/text", description: "The business result, non-technical." },
|
|
1244
|
+
proof: {
|
|
1245
|
+
type: "object",
|
|
1246
|
+
additionalProperties: false,
|
|
1247
|
+
required: ["value", "unit", "statement"],
|
|
1248
|
+
properties: {
|
|
1249
|
+
value: { $ref: "#/$defs/text" },
|
|
1250
|
+
unit: { $ref: "#/$defs/text" },
|
|
1251
|
+
statement: { $ref: "#/$defs/text", description: "A one-line statement of the proof point." }
|
|
1252
|
+
}
|
|
1253
|
+
}
|
|
1254
|
+
}
|
|
1255
|
+
}
|
|
1256
|
+
},
|
|
1257
|
+
four_cs: {
|
|
1258
|
+
type: "array",
|
|
1259
|
+
minItems: 4,
|
|
1260
|
+
maxItems: 4,
|
|
1261
|
+
description: "Exactly 4 rows in the owner's order. Absent while FOUR_CS is empty; required, with c equal to the name, once it holds 4 names.",
|
|
1262
|
+
items: {
|
|
1263
|
+
type: "object",
|
|
1264
|
+
additionalProperties: false,
|
|
1265
|
+
required: ["c", "exec_problem"],
|
|
1266
|
+
properties: {
|
|
1267
|
+
c: { $ref: "#/$defs/text" },
|
|
1268
|
+
exec_problem: { $ref: "#/$defs/text", description: "One sentence tying the C to this executive's problem." }
|
|
1269
|
+
}
|
|
1270
|
+
}
|
|
1271
|
+
},
|
|
1272
|
+
dialogue: {
|
|
1273
|
+
type: "array",
|
|
1274
|
+
minItems: 3,
|
|
1275
|
+
maxItems: 5,
|
|
1276
|
+
items: {
|
|
1277
|
+
type: "object",
|
|
1278
|
+
additionalProperties: false,
|
|
1279
|
+
required: ["question", "answer"],
|
|
1280
|
+
properties: {
|
|
1281
|
+
question: { $ref: "#/$defs/text", description: "A business question that executive asks." },
|
|
1282
|
+
answer: { $ref: "#/$defs/text", description: "At most 2 sentences." }
|
|
1283
|
+
}
|
|
1284
|
+
}
|
|
1285
|
+
},
|
|
1286
|
+
illustrations: {
|
|
1287
|
+
type: "object",
|
|
1288
|
+
additionalProperties: false,
|
|
1289
|
+
required: ["initiative", "problem", "solution"],
|
|
1290
|
+
properties: {
|
|
1291
|
+
initiative: { $ref: "#/$defs/illustration" },
|
|
1292
|
+
problem: { $ref: "#/$defs/illustration" },
|
|
1293
|
+
solution: { $ref: "#/$defs/illustration" }
|
|
1294
|
+
}
|
|
1295
|
+
},
|
|
1296
|
+
sources: {
|
|
1297
|
+
type: "array",
|
|
1298
|
+
minItems: 1,
|
|
1299
|
+
description: "The source of every figure (why_now.figure and each outcomes[i].proof), by field path; shown as numbered notes, never inline.",
|
|
1300
|
+
items: {
|
|
1301
|
+
type: "object",
|
|
1302
|
+
additionalProperties: false,
|
|
1303
|
+
required: ["field", "source"],
|
|
1304
|
+
properties: {
|
|
1305
|
+
field: { type: "string", minLength: 1 },
|
|
1306
|
+
source: { $ref: "#/$defs/text" }
|
|
1307
|
+
}
|
|
1308
|
+
}
|
|
1309
|
+
}
|
|
1310
|
+
},
|
|
1311
|
+
$defs: {
|
|
1312
|
+
text: {
|
|
1313
|
+
type: "object",
|
|
1314
|
+
additionalProperties: false,
|
|
1315
|
+
required: ["en", "es"],
|
|
1316
|
+
properties: {
|
|
1317
|
+
en: { type: "string", minLength: 1 },
|
|
1318
|
+
es: { type: "string", minLength: 1 }
|
|
1319
|
+
}
|
|
1320
|
+
},
|
|
1321
|
+
figure: {
|
|
1322
|
+
type: "object",
|
|
1323
|
+
additionalProperties: false,
|
|
1324
|
+
required: ["value", "unit"],
|
|
1325
|
+
properties: {
|
|
1326
|
+
value: { $ref: "#/$defs/text" },
|
|
1327
|
+
unit: { $ref: "#/$defs/text" }
|
|
1328
|
+
}
|
|
1329
|
+
},
|
|
1330
|
+
illustration: {
|
|
1331
|
+
type: "object",
|
|
1332
|
+
additionalProperties: false,
|
|
1333
|
+
required: ["file", "caption"],
|
|
1334
|
+
properties: {
|
|
1335
|
+
file: {
|
|
1336
|
+
description: "The inline SVG: one path, or one path per language.",
|
|
1337
|
+
anyOf: [
|
|
1338
|
+
{ type: "string", minLength: 1 },
|
|
1339
|
+
{
|
|
1340
|
+
type: "object",
|
|
1341
|
+
additionalProperties: false,
|
|
1342
|
+
required: ["en", "es"],
|
|
1343
|
+
properties: { en: { type: "string", minLength: 1 }, es: { type: "string", minLength: 1 } }
|
|
1344
|
+
}
|
|
1345
|
+
]
|
|
1346
|
+
},
|
|
1347
|
+
caption: { $ref: "#/$defs/text", description: "One sentence saying what the reader should take from the illustration." }
|
|
1348
|
+
}
|
|
1349
|
+
}
|
|
1350
|
+
}
|
|
1351
|
+
};
|
|
1352
|
+
|
|
1353
|
+
// src/content/executive.ts
|
|
1354
|
+
var EXECUTIVE_SCHEMA_VERSION = "1.0.0";
|
|
1355
|
+
var FOUR_CS = [];
|
|
1356
|
+
var EXEC_LIMITS = {
|
|
1357
|
+
maxWords: 30,
|
|
1358
|
+
maxAnswerSentences: 2,
|
|
1359
|
+
/** An equation or a TeX marker: a dollar sign, `\(`, `\[` or a backslash command. */
|
|
1360
|
+
equation: /\$|\\\(|\\\[|\\[a-zA-Z]+/,
|
|
1361
|
+
/** An inline citation: `(Source`, `[1]`, `(ECB`, or a parenthesised author-year such as `(Smith et al., 2019)`. */
|
|
1362
|
+
citations: [/\(\s*Source/i, /\[\d+\]/, /\(\s*ECB/, /\(\w[^()]*\d{4}\)/]};
|
|
1363
|
+
function sentencesOf(text) {
|
|
1364
|
+
return text.split(/(?<=[.?!])\s+/).map((s) => s.trim()).filter(Boolean);
|
|
1365
|
+
}
|
|
1366
|
+
function wordsIn(text) {
|
|
1367
|
+
return text.split(/\s+/).filter((w) => /[\p{L}\p{N}]/u.test(w)).length;
|
|
1368
|
+
}
|
|
1369
|
+
var ROOT = executive_schema_default;
|
|
1370
|
+
var typeOf = (v) => v === null ? "null" : Array.isArray(v) ? "array" : typeof v;
|
|
1371
|
+
var join = (base, key) => base ? `${base}.${key}` : key;
|
|
1372
|
+
function resolve(node) {
|
|
1373
|
+
if (typeof node.$ref !== "string") return node;
|
|
1374
|
+
const name = node.$ref.replace("#/$defs/", "");
|
|
1375
|
+
return { ...ROOT.$defs[name], ...node.description ? { description: node.description } : {} };
|
|
1376
|
+
}
|
|
1377
|
+
function check(value, rawNode, path, out) {
|
|
1378
|
+
const node = resolve(rawNode);
|
|
1379
|
+
if (node.anyOf) {
|
|
1380
|
+
const ok = node.anyOf.some((alt) => {
|
|
1381
|
+
const sub = [];
|
|
1382
|
+
check(value, alt, path, sub);
|
|
1383
|
+
return sub.length === 0;
|
|
1384
|
+
});
|
|
1385
|
+
if (!ok) out.push({ path, message: `matches none of the allowed forms (${node.anyOf.map((a) => resolve(a).type).join(" or ")})` });
|
|
1386
|
+
return;
|
|
1387
|
+
}
|
|
1388
|
+
const t2 = typeOf(value);
|
|
1389
|
+
if (node.type && t2 !== node.type) {
|
|
1390
|
+
out.push({ path, message: `must be ${node.type === "object" ? "an object" : node.type === "array" ? "an array" : `a ${node.type}`}, not ${t2 === "undefined" ? "missing" : t2 === "array" ? "an array" : t2 === "object" ? "an object" : `a ${t2}`}` });
|
|
1391
|
+
return;
|
|
1392
|
+
}
|
|
1393
|
+
if (node.type === "string" && typeof value === "string" && node.minLength && value.trim().length < node.minLength) {
|
|
1394
|
+
out.push({ path, message: "must not be empty" });
|
|
1395
|
+
}
|
|
1396
|
+
if (node.type === "array") {
|
|
1397
|
+
const list = value;
|
|
1398
|
+
if (node.minItems !== void 0 && list.length < node.minItems) out.push({ path, message: `needs at least ${node.minItems} item(s), has ${list.length}` });
|
|
1399
|
+
if (node.maxItems !== void 0 && list.length > node.maxItems) out.push({ path, message: `allows at most ${node.maxItems} item(s), has ${list.length}` });
|
|
1400
|
+
if (node.items) list.forEach((item, i) => check(item, node.items, `${path}[${i}]`, out));
|
|
1401
|
+
}
|
|
1402
|
+
if (node.type === "object") {
|
|
1403
|
+
const obj = value;
|
|
1404
|
+
for (const key of node.required ?? []) {
|
|
1405
|
+
if (!(key in obj) || obj[key] === void 0) out.push({ path: join(path, key), message: "is required and missing" });
|
|
1406
|
+
}
|
|
1407
|
+
const props = node.properties ?? {};
|
|
1408
|
+
for (const key of Object.keys(obj)) {
|
|
1409
|
+
if (props[key]) check(obj[key], props[key], join(path, key), out);
|
|
1410
|
+
else if (node.additionalProperties === false) out.push({ path: join(path, key), message: "is not a field of the executive view (nothing else is allowed)" });
|
|
1411
|
+
}
|
|
1412
|
+
}
|
|
1413
|
+
}
|
|
1414
|
+
function textFields(d) {
|
|
1415
|
+
const out = [
|
|
1416
|
+
{ path: "executive", text: d.executive },
|
|
1417
|
+
{ path: "organisation", text: d.organisation },
|
|
1418
|
+
{ path: "initiative", text: d.initiative, sentences: 1 },
|
|
1419
|
+
{ path: "why_now.figure.value", text: d.why_now.figure.value },
|
|
1420
|
+
{ path: "why_now.figure.unit", text: d.why_now.figure.unit },
|
|
1421
|
+
{ path: "why_now.deadline", text: d.why_now.deadline },
|
|
1422
|
+
{ path: "vision", text: d.vision, sentences: 1 }
|
|
1423
|
+
];
|
|
1424
|
+
d.outcomes.forEach((o, i) => {
|
|
1425
|
+
out.push({ path: `outcomes[${i}].capability`, text: o.capability }, { path: `outcomes[${i}].outcome`, text: o.outcome });
|
|
1426
|
+
out.push({ path: `outcomes[${i}].proof.value`, text: o.proof.value }, { path: `outcomes[${i}].proof.unit`, text: o.proof.unit }, { path: `outcomes[${i}].proof.statement`, text: o.proof.statement, sentences: 1 });
|
|
1427
|
+
});
|
|
1428
|
+
(d.four_cs ?? []).forEach((r, i) => out.push({ path: `four_cs[${i}].c`, text: r.c }, { path: `four_cs[${i}].exec_problem`, text: r.exec_problem, sentences: 1 }));
|
|
1429
|
+
d.dialogue.forEach((q, i) => out.push({ path: `dialogue[${i}].question`, text: q.question }, { path: `dialogue[${i}].answer`, text: q.answer, sentences: EXEC_LIMITS.maxAnswerSentences }));
|
|
1430
|
+
for (const name of ["initiative", "problem", "solution"]) out.push({ path: `illustrations.${name}.caption`, text: d.illustrations[name].caption, sentences: 1 });
|
|
1431
|
+
return out;
|
|
1432
|
+
}
|
|
1433
|
+
function figureFields(d) {
|
|
1434
|
+
return ["why_now.figure", ...d.outcomes.map((_, i) => `outcomes[${i}].proof`)];
|
|
1435
|
+
}
|
|
1436
|
+
function writingProblems(text, maxSentences) {
|
|
1437
|
+
const out = [];
|
|
1438
|
+
const sentences = sentencesOf(text);
|
|
1439
|
+
for (const s of sentences) {
|
|
1440
|
+
const n = wordsIn(s);
|
|
1441
|
+
if (n > EXEC_LIMITS.maxWords) out.push(`a sentence of ${n} words; the limit is ${EXEC_LIMITS.maxWords}`);
|
|
1442
|
+
}
|
|
1443
|
+
if (maxSentences !== void 0 && sentences.length > maxSentences) {
|
|
1444
|
+
out.push(maxSentences === 1 ? `must be one sentence, has ${sentences.length}` : `has ${sentences.length} sentences; the limit is ${maxSentences}`);
|
|
1445
|
+
}
|
|
1446
|
+
if (EXEC_LIMITS.equation.test(text)) out.push("holds an equation or a TeX marker; the executive view holds none");
|
|
1447
|
+
if (EXEC_LIMITS.citations.some((re) => re.test(text))) out.push('holds an inline citation; give the source in "sources"');
|
|
1448
|
+
return out;
|
|
1449
|
+
}
|
|
1450
|
+
function validateExecutive(data, opts = {}) {
|
|
1451
|
+
const fourCs = opts.fourCs ?? FOUR_CS;
|
|
1452
|
+
const out = [];
|
|
1453
|
+
const root = { ...ROOT, required: ROOT.required.filter((k) => k !== "four_cs") };
|
|
1454
|
+
check(data, root, "", out);
|
|
1455
|
+
const structural = out.length;
|
|
1456
|
+
const d = data;
|
|
1457
|
+
if (d && typeof d === "object" && !Array.isArray(d)) {
|
|
1458
|
+
if (fourCs.length === 0) {
|
|
1459
|
+
if ("four_cs" in d) out.push({ path: "four_cs", message: "is not allowed yet: the 4 C's are not named (FOUR_CS is empty), so the view shows section 3 as pending" });
|
|
1460
|
+
} else if (!("four_cs" in d)) {
|
|
1461
|
+
out.push({ path: "four_cs", message: `is required: the 4 C's are named (${fourCs.join(", ")})` });
|
|
1462
|
+
} else {
|
|
1463
|
+
const rows = Array.isArray(d.four_cs) ? d.four_cs : [];
|
|
1464
|
+
if (rows.length === 4) {
|
|
1465
|
+
rows.forEach((r, i) => {
|
|
1466
|
+
if (r?.c && r.c.en !== fourCs[i]) out.push({ path: `four_cs[${i}].c`, message: `must be "${fourCs[i]}" (the ${i + 1}${["st", "nd", "rd", "th"][i]} C, in the owner's order), not "${r.c.en}"` });
|
|
1467
|
+
});
|
|
1468
|
+
}
|
|
1469
|
+
}
|
|
1470
|
+
}
|
|
1471
|
+
if (structural > 0) return out;
|
|
1472
|
+
if (!d || typeof d !== "object") return out;
|
|
1473
|
+
const full = d;
|
|
1474
|
+
for (const f of textFields(full)) {
|
|
1475
|
+
for (const lang of ["en", "es"]) {
|
|
1476
|
+
const text = f.text?.[lang];
|
|
1477
|
+
if (typeof text !== "string") continue;
|
|
1478
|
+
for (const m of writingProblems(text, f.sentences)) out.push({ path: `${f.path}.${lang}`, message: m });
|
|
1479
|
+
}
|
|
1480
|
+
}
|
|
1481
|
+
const wanted = figureFields(full);
|
|
1482
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1483
|
+
full.sources.forEach((s, i) => {
|
|
1484
|
+
if (!wanted.includes(s.field)) out.push({ path: `sources[${i}].field`, message: `"${s.field}" is not a figure of this view (the figures are ${wanted.join(", ")})` });
|
|
1485
|
+
else if (seen.has(s.field)) out.push({ path: `sources[${i}].field`, message: `"${s.field}" already has a source` });
|
|
1486
|
+
seen.add(s.field);
|
|
1487
|
+
});
|
|
1488
|
+
const missing = wanted.filter((f) => !seen.has(f));
|
|
1489
|
+
if (missing.length > 0) out.push({ path: "sources", message: `no source for ${missing.join(", ")}` });
|
|
1490
|
+
return out;
|
|
1491
|
+
}
|
|
1492
|
+
var SECTION_TITLES = [
|
|
1493
|
+
{ en: "Industry & Exec Tailoring", es: "Industria y foco ejecutivo" },
|
|
1494
|
+
{ en: "AI Transformation Story", es: "Historia de transformaci\xF3n con IA" },
|
|
1495
|
+
{ en: "4Cs Positioning", es: "Posicionamiento 4C" },
|
|
1496
|
+
{ en: "Delivery & Credibility", es: "Entrega y credibilidad" }
|
|
1497
|
+
];
|
|
1498
|
+
var SECTION_QUESTIONS = [
|
|
1499
|
+
{ en: "Built for a C-suite exec?", es: "\xBFPensado para un ejecutivo de primer nivel?" },
|
|
1500
|
+
{ en: "Outcomes, not a feature tour", es: "Resultados, no un recorrido de funciones" },
|
|
1501
|
+
{ en: "Value story, not features dump", es: "Historia de valor, no lista de funciones" },
|
|
1502
|
+
{ en: "Trust them in front of a CxO?", es: "\xBFConfiar\xEDa en ellos frente a un ejecutivo?" }
|
|
1503
|
+
];
|
|
1504
|
+
var PENDING_FOUR_CS = {
|
|
1505
|
+
en: "Pending: the 4 C's are defined by the product owner",
|
|
1506
|
+
es: "Pendiente: las 4 C las define el responsable del producto"
|
|
1507
|
+
};
|
|
1209
1508
|
function Question({ question, answer }) {
|
|
1210
1509
|
return /* @__PURE__ */ jsxs("div", { className: "caos-qa", "data-qa": "", children: [
|
|
1211
1510
|
/* @__PURE__ */ jsx("p", { className: "caos-qa-question", "data-question": "", children: question }),
|
|
1212
1511
|
/* @__PURE__ */ jsx("div", { className: "caos-qa-answer", "data-answer": "", children: answer })
|
|
1213
1512
|
] });
|
|
1214
1513
|
}
|
|
1514
|
+
var UI = {
|
|
1515
|
+
executive: { en: "Executive", es: "Ejecutivo" },
|
|
1516
|
+
organisation: { en: "Organisation", es: "Organizaci\xF3n" },
|
|
1517
|
+
whyNow: { en: "Why now", es: "Por qu\xE9 ahora" },
|
|
1518
|
+
does: { en: "What it does", es: "Qu\xE9 hace" },
|
|
1519
|
+
result: { en: "Business result", es: "Resultado de negocio" },
|
|
1520
|
+
proof: { en: "Proof", es: "Prueba" },
|
|
1521
|
+
sources: { en: "Sources", es: "Fuentes" },
|
|
1522
|
+
source: { en: "Source", es: "Fuente" },
|
|
1523
|
+
errorTitle: { en: "The executive view data is not valid", es: "Los datos de la vista ejecutiva no son v\xE1lidos" },
|
|
1524
|
+
errorLead: {
|
|
1525
|
+
en: "Fix content/executive.json against executive.schema.json; the view shows nothing until it is valid.",
|
|
1526
|
+
es: "Corrija content/executive.json seg\xFAn executive.schema.json; la vista no muestra nada hasta que sea v\xE1lido."
|
|
1527
|
+
},
|
|
1528
|
+
loading: { en: "Loading the illustration", es: "Cargando la ilustraci\xF3n" },
|
|
1529
|
+
missing: { en: "The illustration file did not load", es: "No carg\xF3 el archivo de la ilustraci\xF3n" }
|
|
1530
|
+
};
|
|
1531
|
+
var t = (text, lang) => text[lang];
|
|
1532
|
+
function cleanSvg(text) {
|
|
1533
|
+
const doc = new DOMParser().parseFromString(text, "image/svg+xml");
|
|
1534
|
+
const root = doc.documentElement;
|
|
1535
|
+
if (!root || root.localName !== "svg" || doc.querySelector("parsererror")) return null;
|
|
1536
|
+
for (const bad of Array.from(doc.querySelectorAll("script, foreignObject"))) bad.remove();
|
|
1537
|
+
for (const el of Array.from(doc.querySelectorAll("*"))) {
|
|
1538
|
+
for (const attr of Array.from(el.attributes)) {
|
|
1539
|
+
if (/^on/i.test(attr.name) || /^(xlink:)?href$/i.test(attr.name) && /^\s*javascript:/i.test(attr.value)) el.removeAttribute(attr.name);
|
|
1540
|
+
}
|
|
1541
|
+
}
|
|
1542
|
+
root.removeAttribute("width");
|
|
1543
|
+
root.removeAttribute("height");
|
|
1544
|
+
if (!root.getAttribute("viewBox")) return null;
|
|
1545
|
+
if (!root.getAttribute("role")) root.setAttribute("role", "img");
|
|
1546
|
+
return new XMLSerializer().serializeToString(root);
|
|
1547
|
+
}
|
|
1548
|
+
function Illustration({ name, spec, base, lang }) {
|
|
1549
|
+
const file = typeof spec.file === "string" ? spec.file : spec.file[lang];
|
|
1550
|
+
const url = /^([a-z]+:)?\/\//i.test(file) || file.startsWith("/") ? file : `${base}${file}`;
|
|
1551
|
+
const [loaded, setLoaded] = useState({ status: "loading" });
|
|
1552
|
+
useEffect(() => {
|
|
1553
|
+
let live = true;
|
|
1554
|
+
setLoaded({ status: "loading" });
|
|
1555
|
+
fetch(url).then((r) => {
|
|
1556
|
+
if (!r.ok) throw new Error(`HTTP ${r.status}`);
|
|
1557
|
+
return r.text();
|
|
1558
|
+
}).then((text) => {
|
|
1559
|
+
const svg = cleanSvg(text);
|
|
1560
|
+
if (!svg) throw new Error("not an SVG document with a viewBox");
|
|
1561
|
+
if (live) setLoaded({ status: "ready", svg });
|
|
1562
|
+
}).catch((e) => {
|
|
1563
|
+
if (live) setLoaded({ status: "error", why: e.message });
|
|
1564
|
+
});
|
|
1565
|
+
return () => {
|
|
1566
|
+
live = false;
|
|
1567
|
+
};
|
|
1568
|
+
}, [url]);
|
|
1569
|
+
return /* @__PURE__ */ jsxs(
|
|
1570
|
+
"figure",
|
|
1571
|
+
{
|
|
1572
|
+
className: "figure caos-exec-fig",
|
|
1573
|
+
"data-exec-illustration": name,
|
|
1574
|
+
"data-lang": lang,
|
|
1575
|
+
"data-exec-file": file,
|
|
1576
|
+
"data-state": loaded.status === "ready" ? void 0 : loaded.status,
|
|
1577
|
+
children: [
|
|
1578
|
+
loaded.status === "ready" ? /* @__PURE__ */ jsx("div", { className: "caos-exec-art", dangerouslySetInnerHTML: { __html: loaded.svg } }) : loaded.status === "error" ? /* @__PURE__ */ jsxs("p", { className: "caos-exec-fig-error", role: "alert", children: [
|
|
1579
|
+
t(UI.missing, lang),
|
|
1580
|
+
": ",
|
|
1581
|
+
/* @__PURE__ */ jsx("code", { children: file }),
|
|
1582
|
+
" (",
|
|
1583
|
+
loaded.why,
|
|
1584
|
+
")"
|
|
1585
|
+
] }) : /* @__PURE__ */ jsx("div", { className: "caos-exec-art caos-exec-art-wait", "aria-busy": "true", "aria-label": t(UI.loading, lang) }),
|
|
1586
|
+
/* @__PURE__ */ jsx("figcaption", { className: "figure-caption", "data-exec-field": `illustrations.${name}.caption`, children: t(spec.caption, lang) })
|
|
1587
|
+
]
|
|
1588
|
+
}
|
|
1589
|
+
);
|
|
1590
|
+
}
|
|
1591
|
+
var Label = ({ children }) => /* @__PURE__ */ jsx("span", { className: "caos-exec-label", children });
|
|
1592
|
+
function Section({ n, lang, children }) {
|
|
1593
|
+
return /* @__PURE__ */ jsxs("section", { className: "caos-exec-section", "data-exec-section": n, "aria-label": t(SECTION_TITLES[n - 1], lang), children: [
|
|
1594
|
+
/* @__PURE__ */ jsx("h2", { children: t(SECTION_TITLES[n - 1], lang) }),
|
|
1595
|
+
/* @__PURE__ */ jsx("p", { className: "caos-exec-question", "data-exec-question": "", children: t(SECTION_QUESTIONS[n - 1], lang) }),
|
|
1596
|
+
children
|
|
1597
|
+
] });
|
|
1598
|
+
}
|
|
1599
|
+
function ExecutiveView({ data, base }) {
|
|
1600
|
+
return /* @__PURE__ */ jsx(ExecutiveViewBody, { data, base, fourCs: FOUR_CS });
|
|
1601
|
+
}
|
|
1602
|
+
function ExecutiveViewBody({ data, base = "/", fourCs, lang: forced }) {
|
|
1603
|
+
const stored = useShellLang();
|
|
1604
|
+
const lang = forced ?? stored;
|
|
1605
|
+
const problems = validateExecutive(data, { fourCs });
|
|
1606
|
+
if (problems.length > 0) {
|
|
1607
|
+
return /* @__PURE__ */ jsxs(
|
|
1608
|
+
"div",
|
|
1609
|
+
{
|
|
1610
|
+
className: "caos-exec caos-exec-error",
|
|
1611
|
+
"data-executive-view": "",
|
|
1612
|
+
"data-executive-schema": EXECUTIVE_SCHEMA_VERSION,
|
|
1613
|
+
"data-executive-valid": "false",
|
|
1614
|
+
"data-executive-errors": problems.map((p) => `${p.path || "(file)"}: ${p.message}`).join(" | "),
|
|
1615
|
+
"data-state": "error",
|
|
1616
|
+
role: "alert",
|
|
1617
|
+
children: [
|
|
1618
|
+
/* @__PURE__ */ jsx("h2", { children: t(UI.errorTitle, lang) }),
|
|
1619
|
+
/* @__PURE__ */ jsx("p", { children: t(UI.errorLead, lang) }),
|
|
1620
|
+
/* @__PURE__ */ jsx("ul", { children: problems.map((p, i) => /* @__PURE__ */ jsxs("li", { children: [
|
|
1621
|
+
/* @__PURE__ */ jsx("code", { children: p.path || "(file)" }),
|
|
1622
|
+
": ",
|
|
1623
|
+
p.message
|
|
1624
|
+
] }, i)) })
|
|
1625
|
+
]
|
|
1626
|
+
}
|
|
1627
|
+
);
|
|
1628
|
+
}
|
|
1629
|
+
const d = data;
|
|
1630
|
+
const figures = figureFields(d);
|
|
1631
|
+
const note = (field2) => figures.indexOf(field2) + 1;
|
|
1632
|
+
const sourceOf = (field2) => d.sources.find((s) => s.field === field2);
|
|
1633
|
+
const Cite2 = ({ field: field2 }) => /* @__PURE__ */ jsx("sup", { className: "caos-exec-cite", children: /* @__PURE__ */ jsx("a", { href: `#exec-note-${note(field2)}`, "aria-label": `${t(UI.source, lang)} ${note(field2)}`, children: note(field2) }) });
|
|
1634
|
+
const field = (path, text) => /* @__PURE__ */ jsx("span", { "data-exec-field": path, children: t(text, lang) });
|
|
1635
|
+
return /* @__PURE__ */ jsxs("div", { className: "caos-exec", "data-executive-view": "", "data-executive-schema": EXECUTIVE_SCHEMA_VERSION, "data-executive-valid": "true", children: [
|
|
1636
|
+
/* @__PURE__ */ jsxs(Section, { n: 1, lang, children: [
|
|
1637
|
+
/* @__PURE__ */ jsxs("dl", { className: "caos-exec-facts", children: [
|
|
1638
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
1639
|
+
/* @__PURE__ */ jsx("dt", { children: t(UI.executive, lang) }),
|
|
1640
|
+
/* @__PURE__ */ jsx("dd", { "data-exec-field": "executive", children: t(d.executive, lang) })
|
|
1641
|
+
] }),
|
|
1642
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
1643
|
+
/* @__PURE__ */ jsx("dt", { children: t(UI.organisation, lang) }),
|
|
1644
|
+
/* @__PURE__ */ jsx("dd", { "data-exec-field": "organisation", children: t(d.organisation, lang) })
|
|
1645
|
+
] })
|
|
1646
|
+
] }),
|
|
1647
|
+
/* @__PURE__ */ jsx("p", { className: "caos-exec-initiative", "data-exec-field": "initiative", children: t(d.initiative, lang) }),
|
|
1648
|
+
/* @__PURE__ */ jsx(Illustration, { name: "initiative", spec: d.illustrations.initiative, base, lang }),
|
|
1649
|
+
/* @__PURE__ */ jsxs("p", { className: "caos-exec-whynow", "data-exec-line": "why_now", children: [
|
|
1650
|
+
/* @__PURE__ */ jsx(Label, { children: t(UI.whyNow, lang) }),
|
|
1651
|
+
" ",
|
|
1652
|
+
/* @__PURE__ */ jsx("strong", { className: "caos-exec-value", "data-exec-field": "why_now.figure.value", children: t(d.why_now.figure.value, lang) }),
|
|
1653
|
+
" ",
|
|
1654
|
+
field("why_now.figure.unit", d.why_now.figure.unit),
|
|
1655
|
+
" ",
|
|
1656
|
+
/* @__PURE__ */ jsx("span", { className: "caos-exec-sep", children: "\xB7" }),
|
|
1657
|
+
" ",
|
|
1658
|
+
field("why_now.deadline", d.why_now.deadline),
|
|
1659
|
+
/* @__PURE__ */ jsx(Cite2, { field: "why_now.figure" })
|
|
1660
|
+
] }),
|
|
1661
|
+
/* @__PURE__ */ jsx(Illustration, { name: "problem", spec: d.illustrations.problem, base, lang })
|
|
1662
|
+
] }),
|
|
1663
|
+
/* @__PURE__ */ jsxs(Section, { n: 2, lang, children: [
|
|
1664
|
+
/* @__PURE__ */ jsx("p", { className: "caos-exec-vision", "data-exec-field": "vision", children: t(d.vision, lang) }),
|
|
1665
|
+
/* @__PURE__ */ jsx(Illustration, { name: "solution", spec: d.illustrations.solution, base, lang }),
|
|
1666
|
+
/* @__PURE__ */ jsx("ul", { className: "caos-exec-outcomes", children: d.outcomes.map((o, i) => /* @__PURE__ */ jsxs("li", { className: "caos-exec-outcome", "data-exec-outcome": i, children: [
|
|
1667
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
1668
|
+
/* @__PURE__ */ jsx(Label, { children: t(UI.does, lang) }),
|
|
1669
|
+
" ",
|
|
1670
|
+
field(`outcomes[${i}].capability`, o.capability)
|
|
1671
|
+
] }),
|
|
1672
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
1673
|
+
/* @__PURE__ */ jsx(Label, { children: t(UI.result, lang) }),
|
|
1674
|
+
" ",
|
|
1675
|
+
field(`outcomes[${i}].outcome`, o.outcome)
|
|
1676
|
+
] }),
|
|
1677
|
+
/* @__PURE__ */ jsxs("div", { className: "caos-exec-proof", children: [
|
|
1678
|
+
/* @__PURE__ */ jsx(Label, { children: t(UI.proof, lang) }),
|
|
1679
|
+
" ",
|
|
1680
|
+
/* @__PURE__ */ jsx("strong", { className: "caos-exec-value", "data-exec-field": `outcomes[${i}].proof.value`, children: t(o.proof.value, lang) }),
|
|
1681
|
+
" ",
|
|
1682
|
+
field(`outcomes[${i}].proof.unit`, o.proof.unit),
|
|
1683
|
+
". ",
|
|
1684
|
+
field(`outcomes[${i}].proof.statement`, o.proof.statement),
|
|
1685
|
+
/* @__PURE__ */ jsx(Cite2, { field: `outcomes[${i}].proof` })
|
|
1686
|
+
] })
|
|
1687
|
+
] }, i)) })
|
|
1688
|
+
] }),
|
|
1689
|
+
/* @__PURE__ */ jsx(Section, { n: 3, lang, children: fourCs.length === 0 ? /* @__PURE__ */ jsx("p", { className: "caos-exec-pending", "data-state": "unavailable", "data-exec-pending": "", children: t(PENDING_FOUR_CS, lang) }) : /* @__PURE__ */ jsx("ul", { className: "caos-exec-cs", children: d.four_cs.map((r, i) => /* @__PURE__ */ jsxs("li", { "data-exec-c": i, children: [
|
|
1690
|
+
/* @__PURE__ */ jsx("strong", { "data-exec-field": `four_cs[${i}].c`, children: t(r.c, lang) }),
|
|
1691
|
+
" ",
|
|
1692
|
+
field(`four_cs[${i}].exec_problem`, r.exec_problem)
|
|
1693
|
+
] }, i)) }) }),
|
|
1694
|
+
/* @__PURE__ */ jsx(Section, { n: 4, lang, children: d.dialogue.map((q, i) => /* @__PURE__ */ jsx(Question, { question: field(`dialogue[${i}].question`, q.question), answer: /* @__PURE__ */ jsx("p", { children: field(`dialogue[${i}].answer`, q.answer) }) }, i)) }),
|
|
1695
|
+
/* @__PURE__ */ jsxs("aside", { className: "caos-exec-notes-wrap", "aria-label": t(UI.sources, lang), children: [
|
|
1696
|
+
/* @__PURE__ */ jsx("h3", { className: "caos-exec-notes-title", children: t(UI.sources, lang) }),
|
|
1697
|
+
/* @__PURE__ */ jsx("ol", { className: "caos-exec-notes", "data-exec-notes": "", children: figures.map((f, i) => /* @__PURE__ */ jsx("li", { id: `exec-note-${i + 1}`, children: t(sourceOf(f).source, lang) }, f)) })
|
|
1698
|
+
] })
|
|
1699
|
+
] });
|
|
1700
|
+
}
|
|
1215
1701
|
function replaceQueryParam(param, value) {
|
|
1216
1702
|
if (typeof window === "undefined") return;
|
|
1217
1703
|
const next = withCaseParam(window.location.search, value, param);
|
|
@@ -1236,7 +1722,7 @@ function viewParamOf(option) {
|
|
|
1236
1722
|
}
|
|
1237
1723
|
function SurfacePage({ title, lede, actions, tabs, value, onChange, deepLinkView = true, ariaLabel, instrument, children }) {
|
|
1238
1724
|
const lang = useShellLang();
|
|
1239
|
-
const [open, select] = useUrlView((tabs ?? []).map((
|
|
1725
|
+
const [open, select] = useUrlView((tabs ?? []).map((t2) => t2.id), tabs ? viewParamOf(deepLinkView) : null, value, onChange);
|
|
1240
1726
|
const head = title !== void 0 || lede !== void 0 || actions !== void 0;
|
|
1241
1727
|
return /* @__PURE__ */ jsxs("div", { className: "page-body wide caos-surface", "data-surface": "", children: [
|
|
1242
1728
|
head && /* @__PURE__ */ jsxs("div", { className: "caos-surface-head", children: [
|
|
@@ -1388,9 +1874,9 @@ function BarChart({ title, data, axis, orientation = "horizontal", values = true
|
|
|
1388
1874
|
const barH = Math.min(rowH * 0.5, 40);
|
|
1389
1875
|
drawing = /* @__PURE__ */ jsxs("svg", { width, height: drawnHeight, role: "img", "aria-label": name, "data-chart": "", "data-chart-kind": "bars", children: [
|
|
1390
1876
|
/* @__PURE__ */ jsx("title", { children: name }),
|
|
1391
|
-
ticks.map((
|
|
1392
|
-
/* @__PURE__ */ jsx("line", { x1: sx(
|
|
1393
|
-
/* @__PURE__ */ jsx("text", { x: sx(
|
|
1877
|
+
ticks.map((t2, i) => /* @__PURE__ */ jsxs("g", { children: [
|
|
1878
|
+
/* @__PURE__ */ jsx("line", { x1: sx(t2), x2: sx(t2), y1: top, y2: plotBottom, stroke: "var(--color-border)", strokeWidth: t2 === 0 ? 1.4 : 1 }),
|
|
1879
|
+
/* @__PURE__ */ jsx("text", { x: sx(t2), y: plotBottom + 6 + LINE - 2, textAnchor: i === 0 && sx(t2) - textWidth(tickLabels[i], PX) / 2 < 0 ? "start" : i === ticks.length - 1 && sx(t2) + textWidth(tickLabels[i], PX) / 2 > width ? "end" : "middle", fontSize: PX, fill: "var(--color-fg-subtle)", style: { fontFamily: "var(--font-sans)" }, children: tickLabels[i] })
|
|
1394
1880
|
] }, `t${i}`)),
|
|
1395
1881
|
/* @__PURE__ */ jsx("text", { x: x0 + (x1 - x0) / 2, y: plotBottom + 6 + LINE + 4 + LINE - 2, textAnchor: "middle", fontSize: PX, fill: "var(--color-fg-subtle)", style: { fontFamily: "var(--font-sans)" }, children: axisTitle }),
|
|
1396
1882
|
data.map((d, i) => {
|
|
@@ -1444,9 +1930,9 @@ function BarChart({ title, data, axis, orientation = "horizontal", values = true
|
|
|
1444
1930
|
drawing = /* @__PURE__ */ jsxs("svg", { width, height: h, role: "img", "aria-label": name, "data-chart": "", "data-chart-kind": "bars", children: [
|
|
1445
1931
|
/* @__PURE__ */ jsx("title", { children: name }),
|
|
1446
1932
|
/* @__PURE__ */ jsx("text", { x: 0, y: LINE - 2, textAnchor: "start", fontSize: PX, fill: "var(--color-fg-subtle)", style: { fontFamily: "var(--font-sans)" }, children: axisTitle }),
|
|
1447
|
-
ticks.map((
|
|
1448
|
-
/* @__PURE__ */ jsx("line", { x1: left, x2: width - right, y1: sy(
|
|
1449
|
-
/* @__PURE__ */ jsx("text", { x: left - 6, y: sy(
|
|
1933
|
+
ticks.map((t2, i) => /* @__PURE__ */ jsxs("g", { children: [
|
|
1934
|
+
/* @__PURE__ */ jsx("line", { x1: left, x2: width - right, y1: sy(t2), y2: sy(t2), stroke: "var(--color-border)", strokeWidth: t2 === 0 ? 1.4 : 1 }),
|
|
1935
|
+
/* @__PURE__ */ jsx("text", { x: left - 6, y: sy(t2) + 4, textAnchor: "end", fontSize: PX, fill: "var(--color-fg-subtle)", style: { fontFamily: "var(--font-sans)" }, children: tickLabels[i] })
|
|
1450
1936
|
] }, `t${i}`)),
|
|
1451
1937
|
data.map((d, i) => {
|
|
1452
1938
|
const cx = left + band * i + band / 2;
|
|
@@ -1637,7 +2123,7 @@ function CaseWorkbench(props) {
|
|
|
1637
2123
|
`CaseWorkbench: ${tabs.length} groups; at most ${MAX_WORKBENCH_GROUPS} peers, then group by question (ADR-0071 rule 5)`
|
|
1638
2124
|
);
|
|
1639
2125
|
}
|
|
1640
|
-
const [openGroup, selectGroup] = useUrlView(tabs.map((
|
|
2126
|
+
const [openGroup, selectGroup] = useUrlView(tabs.map((t2) => t2.id), viewParamOf(deepLinkView), group, onGroupChange);
|
|
1641
2127
|
const railHead = cases || variants ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1642
2128
|
cases && /* @__PURE__ */ jsx(CaseSelector, { lang, ...cases }),
|
|
1643
2129
|
variants && /* @__PURE__ */ jsx(VariantBar, { ...variants })
|
|
@@ -1865,4 +2351,4 @@ function ViewsRow({ children, shares }) {
|
|
|
1865
2351
|
}) });
|
|
1866
2352
|
}
|
|
1867
2353
|
|
|
1868
|
-
export { AppShell, ArchitectureModal, BREAKPOINTS, BarChart, Callout, CaseSelector, CaseWorkbench, ChipGroup, CitationsProvider, Cite, DOC_AREAS, DocPage, DocReferences, DocRefsScope, DocSection, Equation, Figure, FocusShell, Gauge, Glossary, InlineMath, Knob, LaneBadge, LanguageToggle, MAX_PEER_TABS, MAX_WORKBENCH_GROUPS, PanelBoundary, PlotCard, Question, Readout, ReferenceList, Refs, Stat, SubTabs, SurfacePage, TabGroups, Tabs, ThemeToggle, VariantBar, Verdict, ViewsRow, WorkbenchLayout, WorkbenchShell, WorkbenchStateContext, caseKind, caseTooltip, casesInSource, createVizLoop, firstAppearance, fitLabel, fontFamily, groupByCategory, isStale, makeStateKey, niceStep, niceTicks, readCaseParam, replaceQueryParam, sourcesPresent, textWidth, usePausedViz, useUrlView, useWorkbenchState, validateArchitectureConfig, viewParamOf, widestLabel, withCaseParam };
|
|
2354
|
+
export { AppShell, ArchitectureModal, BREAKPOINTS, BarChart, Callout, CaseSelector, CaseWorkbench, ChipGroup, CitationsProvider, Cite, DOC_AREAS, DocPage, DocReferences, DocRefsScope, DocSection, EXECUTIVE_SCHEMA_VERSION, Equation, ExecutiveView, FOUR_CS, Figure, FocusShell, Gauge, Glossary, InlineMath, Knob, LaneBadge, LanguageToggle, MAX_PEER_TABS, MAX_WORKBENCH_GROUPS, PanelBoundary, PlotCard, Question, Readout, ReferenceList, Refs, Stat, SubTabs, SurfacePage, TabGroups, Tabs, ThemeToggle, VariantBar, Verdict, ViewsRow, WorkbenchLayout, WorkbenchShell, WorkbenchStateContext, caseKind, caseTooltip, casesInSource, createVizLoop, firstAppearance, fitLabel, fontFamily, groupByCategory, isStale, makeStateKey, niceStep, niceTicks, readCaseParam, replaceQueryParam, sourcesPresent, textWidth, usePausedViz, useUrlView, useWorkbenchState, validateArchitectureConfig, validateExecutive, viewParamOf, widestLabel, withCaseParam };
|