@bitcobblers/wod-wiki-ui 0.37.2137 → 0.37.2140
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/{chunk-RAM3QIP4.mjs → chunk-SNG34RG2.mjs} +450 -126
- package/dist/chunk-SNG34RG2.mjs.map +1 -0
- package/dist/extensions/index.cjs +446 -120
- package/dist/extensions/index.cjs.map +1 -1
- package/dist/extensions/index.d.cts +1 -1
- package/dist/extensions/index.d.ts +1 -1
- package/dist/extensions/index.mjs +1 -1
- package/dist/{index-WiNbi7d3.d.cts → index-D4mgqtvt.d.cts} +60 -3
- package/dist/{index-WiNbi7d3.d.ts → index-D4mgqtvt.d.ts} +60 -3
- package/dist/index.cjs +452 -126
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +9 -9
- package/dist/index.d.ts +9 -9
- package/dist/index.mjs +8 -8
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -4
- package/dist/chunk-RAM3QIP4.mjs.map +0 -1
|
@@ -1035,6 +1035,8 @@ var embedPreviewDecorations = [
|
|
|
1035
1035
|
embedPreviewField
|
|
1036
1036
|
];
|
|
1037
1037
|
var frontmatterSuggestions = state.Facet.define({ combine: (providers) => providers[0] ?? null });
|
|
1038
|
+
var frontmatterReferenceIndex = state.Facet.define({ combine: (providers) => providers[0] ?? null });
|
|
1039
|
+
var referenceIndexReload = state.StateEffect.define();
|
|
1038
1040
|
var frontmatterVisibility = state.Facet.define({
|
|
1039
1041
|
combine: (values2) => values2[0] ?? true
|
|
1040
1042
|
});
|
|
@@ -1044,7 +1046,7 @@ var suggestionId = 0;
|
|
|
1044
1046
|
function isTagProperty(key) {
|
|
1045
1047
|
return ["tag", "tags", "category"].includes(key.trim().toLowerCase());
|
|
1046
1048
|
}
|
|
1047
|
-
function attachSuggestions(input, view, root, kind, key, excluded, commit) {
|
|
1049
|
+
function attachSuggestions(input, view, root, kind, key, excluded, commit, valueKind = "tags") {
|
|
1048
1050
|
const provider = view.state.facet(frontmatterSuggestions);
|
|
1049
1051
|
if (!provider || !input.parentElement) return;
|
|
1050
1052
|
const parent = input.parentElement;
|
|
@@ -1070,8 +1072,8 @@ function attachSuggestions(input, view, root, kind, key, excluded, commit) {
|
|
|
1070
1072
|
input.setAttribute("aria-expanded", "false");
|
|
1071
1073
|
input.removeAttribute("aria-activedescendant");
|
|
1072
1074
|
};
|
|
1073
|
-
const select = (
|
|
1074
|
-
input.value =
|
|
1075
|
+
const select = (choice) => {
|
|
1076
|
+
input.value = choice.value;
|
|
1075
1077
|
close();
|
|
1076
1078
|
commit();
|
|
1077
1079
|
};
|
|
@@ -1094,21 +1096,35 @@ function attachSuggestions(input, view, root, kind, key, excluded, commit) {
|
|
|
1094
1096
|
try {
|
|
1095
1097
|
const catalog = await provider();
|
|
1096
1098
|
if (request !== generation || !input.isConnected || document.activeElement !== input) return;
|
|
1097
|
-
|
|
1099
|
+
let candidates;
|
|
1100
|
+
if (kind === "key") {
|
|
1101
|
+
candidates = catalog.types.map((name) => ({ value: name, label: name, haystack: name }));
|
|
1102
|
+
} else if (valueKind === "effort" || valueKind === "equipment") {
|
|
1103
|
+
const entries = valueKind === "effort" ? catalog.efforts ?? [] : catalog.equipment ?? [];
|
|
1104
|
+
candidates = entries.map((entry) => ({
|
|
1105
|
+
value: entry.slug,
|
|
1106
|
+
label: `${entry.label} (${entry.slug})`,
|
|
1107
|
+
haystack: [entry.label, entry.slug, ...entry.aliases].join(" ").toLowerCase()
|
|
1108
|
+
}));
|
|
1109
|
+
} else {
|
|
1110
|
+
candidates = catalog.tags.filter((tag) => isTagProperty(key) || tag.type?.toLowerCase() === key.trim().toLowerCase()).map((tag) => ({ value: tag.label, label: tag.label, haystack: tag.label.toLowerCase() }));
|
|
1111
|
+
}
|
|
1098
1112
|
const selected = new Set(excluded.map((label) => label.toLowerCase()));
|
|
1099
|
-
choices =
|
|
1113
|
+
choices = candidates.filter(
|
|
1114
|
+
(candidate) => (query === "" || candidate.haystack.includes(query)) && !selected.has(candidate.value.toLowerCase())
|
|
1115
|
+
);
|
|
1100
1116
|
active = -1;
|
|
1101
1117
|
input.removeAttribute("aria-activedescendant");
|
|
1102
1118
|
list.replaceChildren();
|
|
1103
|
-
choices.forEach((
|
|
1119
|
+
choices.forEach((choice, index) => {
|
|
1104
1120
|
const option = document.createElement("div");
|
|
1105
1121
|
option.id = `${list.id}-${index}`;
|
|
1106
1122
|
option.setAttribute("role", "option");
|
|
1107
1123
|
option.setAttribute("aria-selected", "false");
|
|
1108
1124
|
option.className = "cursor-pointer px-2 py-1.5 hover:bg-muted";
|
|
1109
|
-
option.textContent = label;
|
|
1125
|
+
option.textContent = choice.label;
|
|
1110
1126
|
option.addEventListener("mousedown", (event) => event.preventDefault());
|
|
1111
|
-
option.addEventListener("click", () => select(
|
|
1127
|
+
option.addEventListener("click", () => select(choice));
|
|
1112
1128
|
list.appendChild(option);
|
|
1113
1129
|
});
|
|
1114
1130
|
list.hidden = choices.length === 0;
|
|
@@ -1151,45 +1167,66 @@ function parseTagList(val) {
|
|
|
1151
1167
|
}
|
|
1152
1168
|
return [];
|
|
1153
1169
|
}
|
|
1154
|
-
function
|
|
1170
|
+
function patchPropertyInView(view, _sectionId, path, value) {
|
|
1155
1171
|
if (view.state.readOnly) return;
|
|
1156
|
-
const
|
|
1157
|
-
const
|
|
1158
|
-
if (
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
const
|
|
1174
|
-
if (
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1172
|
+
const wholeDoc = view.state.doc.toString();
|
|
1173
|
+
const next = wodWikiCore.patchFrontmatterProperty(wholeDoc, path, value);
|
|
1174
|
+
if (next === wholeDoc) return;
|
|
1175
|
+
view.dispatch({ changes: { from: 0, to: wholeDoc.length, insert: next } });
|
|
1176
|
+
}
|
|
1177
|
+
function renamePropertyInView(view, _sectionId, fromKey, toKey, value) {
|
|
1178
|
+
if (view.state.readOnly) return;
|
|
1179
|
+
const wholeDoc = view.state.doc.toString();
|
|
1180
|
+
const next = wodWikiCore.patchFrontmatterProperty(
|
|
1181
|
+
wodWikiCore.patchFrontmatterProperty(wholeDoc, [toKey], value),
|
|
1182
|
+
[fromKey],
|
|
1183
|
+
null
|
|
1184
|
+
);
|
|
1185
|
+
if (next === wholeDoc) return;
|
|
1186
|
+
view.dispatch({ changes: { from: 0, to: wholeDoc.length, insert: next } });
|
|
1187
|
+
}
|
|
1188
|
+
function detectDefinitionKind(meta) {
|
|
1189
|
+
const type = typeof meta.type === "string" ? meta.type.trim().toLowerCase() : "";
|
|
1190
|
+
if (type === "effort") return "effort";
|
|
1191
|
+
if (type === "equipment") return "equipment";
|
|
1192
|
+
if (meta.registrySource !== void 0 || meta.baseAttributes !== void 0) return "effort";
|
|
1193
|
+
return null;
|
|
1194
|
+
}
|
|
1195
|
+
function readBaseAttributes(body) {
|
|
1196
|
+
const out = {};
|
|
1197
|
+
let inBase = false;
|
|
1198
|
+
for (const line of body.split(/\r?\n/)) {
|
|
1199
|
+
if (/^baseAttributes:\s*(#.*)?$/.test(line)) {
|
|
1200
|
+
inBase = true;
|
|
1201
|
+
continue;
|
|
1202
|
+
}
|
|
1203
|
+
if (!inBase) continue;
|
|
1204
|
+
if (/^\S/.test(line)) break;
|
|
1205
|
+
const match = line.match(/^\s+([\w-]+):\s*(.*)$/);
|
|
1206
|
+
if (!match) continue;
|
|
1207
|
+
if (match[1] === "met" || match[1] === "discipline" || match[1] === "intensityTier") {
|
|
1208
|
+
out[match[1]] = unquoteYamlScalar(match[2].trim());
|
|
1209
|
+
}
|
|
1192
1210
|
}
|
|
1211
|
+
return out;
|
|
1212
|
+
}
|
|
1213
|
+
function unquoteYamlScalar(val) {
|
|
1214
|
+
if (val.startsWith('"') && val.endsWith('"')) return val.slice(1, -1).replace(/\\(["\\])/g, "$1");
|
|
1215
|
+
if (val.startsWith("'") && val.endsWith("'")) return val.slice(1, -1).replace(/\\'/g, "'");
|
|
1216
|
+
return val;
|
|
1217
|
+
}
|
|
1218
|
+
function referenceValueKind(key, docKind) {
|
|
1219
|
+
const normalized = key.trim().toLowerCase();
|
|
1220
|
+
if (normalized === "metrics.effort") return "effort";
|
|
1221
|
+
if (normalized === "metrics.equipment" || normalized === "equipment") return "equipment";
|
|
1222
|
+
if (normalized === "aliases" && docKind === "equipment") return "equipment";
|
|
1223
|
+
if (normalized === "aliases" && docKind === "effort") return "effort";
|
|
1224
|
+
return "tags";
|
|
1225
|
+
}
|
|
1226
|
+
function isReferenceKey(key, docKind) {
|
|
1227
|
+
const normalized = key.trim().toLowerCase();
|
|
1228
|
+
if (normalized === "metrics.effort" || normalized === "metrics.equipment") return true;
|
|
1229
|
+
return normalized === "equipment" && docKind === "effort";
|
|
1193
1230
|
}
|
|
1194
1231
|
function createTagDraftRow(view, root, key, onCommit) {
|
|
1195
1232
|
const row = document.createElement("div");
|
|
@@ -1244,6 +1281,117 @@ function createTagDraftRow(view, root, key, onCommit) {
|
|
|
1244
1281
|
}));
|
|
1245
1282
|
return row;
|
|
1246
1283
|
}
|
|
1284
|
+
function ownsNestedBlock(body, key) {
|
|
1285
|
+
const lines = body.split(/\r?\n/);
|
|
1286
|
+
for (let i = 0; i < lines.length; i++) {
|
|
1287
|
+
if (!new RegExp(`^${key.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}:\\s*$`).test(lines[i])) continue;
|
|
1288
|
+
return i + 1 < lines.length && /^\s+\S/.test(lines[i + 1]);
|
|
1289
|
+
}
|
|
1290
|
+
return false;
|
|
1291
|
+
}
|
|
1292
|
+
function renderEffortValueDiagnostics(provider, token, onPick) {
|
|
1293
|
+
const trimmed = token.trim();
|
|
1294
|
+
if (!trimmed || provider.resolveEffort(trimmed)) return null;
|
|
1295
|
+
const diagnostics = provider.resolve(trimmed).diagnostics;
|
|
1296
|
+
const box = document.createElement("div");
|
|
1297
|
+
box.setAttribute("data-testid", "editor-ref-unknown");
|
|
1298
|
+
box.className = "w-full basis-full flex flex-wrap items-center gap-2 text-[10px] text-destructive";
|
|
1299
|
+
const message = document.createElement("span");
|
|
1300
|
+
message.textContent = diagnostics[0]?.message || `Unknown effort: ${trimmed}`;
|
|
1301
|
+
box.appendChild(message);
|
|
1302
|
+
for (const candidate of diagnostics[0]?.candidates ?? []) {
|
|
1303
|
+
const pickBtn = document.createElement("button");
|
|
1304
|
+
pickBtn.type = "button";
|
|
1305
|
+
pickBtn.textContent = `Use ${candidate}`;
|
|
1306
|
+
pickBtn.className = "underline hover:text-foreground cursor-pointer";
|
|
1307
|
+
pickBtn.addEventListener("click", (e) => {
|
|
1308
|
+
e.preventDefault();
|
|
1309
|
+
onPick(candidate);
|
|
1310
|
+
});
|
|
1311
|
+
box.appendChild(pickBtn);
|
|
1312
|
+
}
|
|
1313
|
+
const createLink = document.createElement("a");
|
|
1314
|
+
createLink.href = provider.createHref("effort");
|
|
1315
|
+
createLink.textContent = "Create page";
|
|
1316
|
+
createLink.className = "underline hover:text-foreground";
|
|
1317
|
+
box.appendChild(createLink);
|
|
1318
|
+
return box;
|
|
1319
|
+
}
|
|
1320
|
+
var METRIC_DRAFT_KINDS = {
|
|
1321
|
+
effort: { label: "Effort", path: "metrics.effort", kind: "effort" },
|
|
1322
|
+
equipment: { label: "Equipment", path: "metrics.equipment", kind: "equipment" },
|
|
1323
|
+
rpe: { label: "RPE", path: "metrics.rpe", kind: "number" }
|
|
1324
|
+
};
|
|
1325
|
+
function createMetricDraftRow(view, root, referenceProvider, commit) {
|
|
1326
|
+
const row = document.createElement("div");
|
|
1327
|
+
row.className = "flex items-center min-h-[34px] border-b border-dashed border-border/60 last:border-b-0 group hover:bg-muted/10 transition-colors max-[479px]:flex-col max-[479px]:items-stretch";
|
|
1328
|
+
row.setAttribute("data-frontmatter-metric-draft", "true");
|
|
1329
|
+
const select = document.createElement("select");
|
|
1330
|
+
select.setAttribute("aria-label", "Metric kind");
|
|
1331
|
+
select.className = "mx-3 my-1.5 h-7 w-28 shrink-0 rounded-md border border-input bg-background px-1.5 text-[11px] text-muted-foreground outline-none";
|
|
1332
|
+
for (const [value, spec] of Object.entries(METRIC_DRAFT_KINDS)) {
|
|
1333
|
+
const option = document.createElement("option");
|
|
1334
|
+
option.value = value;
|
|
1335
|
+
option.textContent = spec.label;
|
|
1336
|
+
select.appendChild(option);
|
|
1337
|
+
}
|
|
1338
|
+
row.appendChild(select);
|
|
1339
|
+
const valCol = document.createElement("div");
|
|
1340
|
+
valCol.className = "flex items-center flex-wrap gap-1.5 px-3 py-1.5 flex-1 min-w-0";
|
|
1341
|
+
const input = document.createElement("input");
|
|
1342
|
+
input.className = "flex-1 min-w-[70px] bg-transparent text-xs text-foreground outline-none px-1 py-0.5 placeholder:text-muted-foreground/40";
|
|
1343
|
+
input.placeholder = "Value\u2026";
|
|
1344
|
+
input.setAttribute("aria-label", "Metric value");
|
|
1345
|
+
valCol.appendChild(input);
|
|
1346
|
+
row.appendChild(valCol);
|
|
1347
|
+
let settled = false;
|
|
1348
|
+
const settle = (doCommit) => {
|
|
1349
|
+
if (settled) return;
|
|
1350
|
+
settled = true;
|
|
1351
|
+
const spec = METRIC_DRAFT_KINDS[select.value];
|
|
1352
|
+
const raw = input.value.trim();
|
|
1353
|
+
if (doCommit && spec && raw) {
|
|
1354
|
+
if (spec.kind === "equipment") commit([spec.path], [raw]);
|
|
1355
|
+
else if (spec.kind === "number") {
|
|
1356
|
+
const num = Number(raw);
|
|
1357
|
+
if (!Number.isNaN(num)) commit([spec.path], num);
|
|
1358
|
+
} else commit([spec.path], raw);
|
|
1359
|
+
}
|
|
1360
|
+
row.remove();
|
|
1361
|
+
view.requestMeasure();
|
|
1362
|
+
};
|
|
1363
|
+
const attachFor = () => {
|
|
1364
|
+
const spec = METRIC_DRAFT_KINDS[select.value];
|
|
1365
|
+
if (spec && (spec.kind === "effort" || spec.kind === "equipment") && referenceProvider) {
|
|
1366
|
+
attachSuggestions(input, view, root, "value", spec.path, [], () => settle(true), spec.kind);
|
|
1367
|
+
}
|
|
1368
|
+
};
|
|
1369
|
+
attachFor();
|
|
1370
|
+
select.addEventListener("change", attachFor);
|
|
1371
|
+
input.addEventListener("keydown", (e) => {
|
|
1372
|
+
if (e.defaultPrevented && e.key !== "Escape") return;
|
|
1373
|
+
if (e.key === "Escape") {
|
|
1374
|
+
e.preventDefault();
|
|
1375
|
+
settle(false);
|
|
1376
|
+
return;
|
|
1377
|
+
}
|
|
1378
|
+
if (e.key === "Enter") {
|
|
1379
|
+
e.preventDefault();
|
|
1380
|
+
settle(true);
|
|
1381
|
+
}
|
|
1382
|
+
});
|
|
1383
|
+
input.addEventListener("blur", () => queueMicrotask(() => {
|
|
1384
|
+
if (!input.isConnected) return;
|
|
1385
|
+
settle(input.value.trim().length > 0);
|
|
1386
|
+
}));
|
|
1387
|
+
select.addEventListener("keydown", (e) => {
|
|
1388
|
+
if (e.key === "Escape") {
|
|
1389
|
+
e.preventDefault();
|
|
1390
|
+
settle(false);
|
|
1391
|
+
}
|
|
1392
|
+
});
|
|
1393
|
+
return row;
|
|
1394
|
+
}
|
|
1247
1395
|
function createTagIcon() {
|
|
1248
1396
|
const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
|
1249
1397
|
svg.setAttribute("viewBox", "0 0 24 24");
|
|
@@ -1356,26 +1504,11 @@ var DefaultFrontmatterWidget = class extends view.WidgetType {
|
|
|
1356
1504
|
sectionId;
|
|
1357
1505
|
rawContent;
|
|
1358
1506
|
readOnly;
|
|
1359
|
-
constructor(
|
|
1507
|
+
constructor(sectionId, rawContent, readOnly = false) {
|
|
1360
1508
|
super();
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
this.readOnly = readOnly;
|
|
1365
|
-
} else {
|
|
1366
|
-
this.sectionId = "legacy";
|
|
1367
|
-
this.rawContent = wodWikiWql.serializeFrontmatter(sectionIdOrProps);
|
|
1368
|
-
this.readOnly = readOnly;
|
|
1369
|
-
}
|
|
1370
|
-
}
|
|
1371
|
-
get props() {
|
|
1372
|
-
const body = this.rawContent.replace(/^---\r?\n?/, "").replace(/\r?\n?---\r?$/, "");
|
|
1373
|
-
const meta = wodWikiWql.parseFrontmatterBody(body);
|
|
1374
|
-
const result = {};
|
|
1375
|
-
for (const [k, v] of Object.entries(meta)) {
|
|
1376
|
-
result[k] = Array.isArray(v) ? v.join(", ") : String(v ?? "");
|
|
1377
|
-
}
|
|
1378
|
-
return result;
|
|
1509
|
+
this.sectionId = sectionId;
|
|
1510
|
+
this.rawContent = rawContent ?? "";
|
|
1511
|
+
this.readOnly = readOnly;
|
|
1379
1512
|
}
|
|
1380
1513
|
eq(other) {
|
|
1381
1514
|
return this.sectionId === other.sectionId && this.rawContent === other.rawContent && this.readOnly === other.readOnly;
|
|
@@ -1397,6 +1530,9 @@ var DefaultFrontmatterWidget = class extends view.WidgetType {
|
|
|
1397
1530
|
const body = this.rawContent.replace(/^---\r?\n?/, "").replace(/\r?\n?---\r?$/, "");
|
|
1398
1531
|
const meta = wodWikiWql.parseFrontmatterBody(body);
|
|
1399
1532
|
const entries = Object.entries(meta);
|
|
1533
|
+
const docKind = detectDefinitionKind(meta);
|
|
1534
|
+
const referenceProvider = view.state.facet(frontmatterReferenceIndex)?.() ?? null;
|
|
1535
|
+
const base = docKind === "effort" ? readBaseAttributes(body) : {};
|
|
1400
1536
|
if (entries.length === 0) {
|
|
1401
1537
|
const emptyRow = document.createElement("div");
|
|
1402
1538
|
emptyRow.className = "px-3 py-2 text-xs text-muted-foreground/60 italic";
|
|
@@ -1405,13 +1541,16 @@ var DefaultFrontmatterWidget = class extends view.WidgetType {
|
|
|
1405
1541
|
}
|
|
1406
1542
|
for (const [key, value] of entries) {
|
|
1407
1543
|
const isTags = isTagProperty(key);
|
|
1544
|
+
const valueKind = referenceValueKind(key, docKind);
|
|
1545
|
+
const isReferenceList = (isReferenceKey(key, docKind) || key === "aliases") && Array.isArray(value);
|
|
1546
|
+
const nested = value === "" && ownsNestedBlock(body, key);
|
|
1408
1547
|
const row = document.createElement("div");
|
|
1409
1548
|
row.className = "flex items-center min-h-[34px] border-b border-dashed border-border/60 last:border-b-0 group hover:bg-muted/10 transition-colors max-[479px]:flex-col max-[479px]:items-stretch";
|
|
1410
1549
|
box.appendChild(row);
|
|
1411
1550
|
const keyCol = document.createElement("div");
|
|
1412
1551
|
keyCol.className = "flex items-center gap-2 px-3 py-1.5 w-36 shrink-0 border-r border-dashed border-border/60 text-muted-foreground max-[479px]:w-auto max-[479px]:border-r-0 max-[479px]:border-b";
|
|
1413
|
-
keyCol.appendChild(isTags ? createTagIcon() : createListIcon());
|
|
1414
|
-
if (this.readOnly) {
|
|
1552
|
+
keyCol.appendChild(isTags || isReferenceList ? createTagIcon() : createListIcon());
|
|
1553
|
+
if (this.readOnly || nested) {
|
|
1415
1554
|
const keyLabel = document.createElement("span");
|
|
1416
1555
|
keyLabel.className = "truncate font-medium text-foreground/90";
|
|
1417
1556
|
keyLabel.textContent = key;
|
|
@@ -1433,15 +1572,10 @@ var DefaultFrontmatterWidget = class extends view.WidgetType {
|
|
|
1433
1572
|
keyInput.value = currentKey;
|
|
1434
1573
|
return;
|
|
1435
1574
|
}
|
|
1436
|
-
|
|
1437
|
-
for (const [k, v] of Object.entries(meta)) {
|
|
1438
|
-
if (k === currentKey) newMeta[nextKey] = v;
|
|
1439
|
-
else newMeta[k] = v;
|
|
1440
|
-
}
|
|
1575
|
+
renamePropertyInView(view, this.sectionId, currentKey, nextKey, value);
|
|
1441
1576
|
delete meta[currentKey];
|
|
1442
|
-
meta[nextKey] =
|
|
1577
|
+
meta[nextKey] = value;
|
|
1443
1578
|
currentKey = nextKey;
|
|
1444
|
-
updateFrontmatter(view, this.sectionId, newMeta);
|
|
1445
1579
|
};
|
|
1446
1580
|
const commitKeyIfAttached = () => queueMicrotask(() => {
|
|
1447
1581
|
if (keyInput.isConnected) commitKey();
|
|
@@ -1470,71 +1604,117 @@ var DefaultFrontmatterWidget = class extends view.WidgetType {
|
|
|
1470
1604
|
row.appendChild(keyCol);
|
|
1471
1605
|
const valCol = document.createElement("div");
|
|
1472
1606
|
valCol.className = "flex items-center flex-wrap gap-1.5 px-3 py-1.5 flex-1 min-w-0";
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1607
|
+
const commitList = (next) => {
|
|
1608
|
+
meta[key] = next;
|
|
1609
|
+
patchPropertyInView(view, this.sectionId, [key], next.length > 0 ? next : "");
|
|
1610
|
+
};
|
|
1611
|
+
const refMatch = (token) => {
|
|
1612
|
+
if (!referenceProvider) return null;
|
|
1613
|
+
return valueKind === "effort" ? referenceProvider.resolveEffort(token) : valueKind === "equipment" ? referenceProvider.resolveEquipment(token) : null;
|
|
1614
|
+
};
|
|
1615
|
+
if (isTags || isReferenceList) {
|
|
1616
|
+
const chips = parseTagList(value);
|
|
1617
|
+
const chipIsReference = valueKind !== "tags";
|
|
1618
|
+
for (let idx = 0; idx < chips.length; idx++) {
|
|
1619
|
+
const chip = chips[idx];
|
|
1620
|
+
const match = chipIsReference ? refMatch(chip) : null;
|
|
1477
1621
|
const pill = document.createElement("span");
|
|
1478
|
-
pill.className = "inline-flex items-center gap-1 px-2 py-0.5 rounded-md text-xs font-medium bg-amber-500/10 text-amber-800 dark:text-amber-300 border border-amber-500/20 dark:border-amber-500/30";
|
|
1479
|
-
const
|
|
1480
|
-
|
|
1481
|
-
pill.appendChild(
|
|
1622
|
+
pill.className = match ? "inline-flex items-center gap-1 px-2 py-0.5 rounded-md text-xs font-medium bg-muted/60 text-foreground border border-border/60" : chipIsReference ? "inline-flex items-center gap-1 px-2 py-0.5 rounded-md text-xs font-medium bg-destructive/10 text-destructive border border-destructive/30" : "inline-flex items-center gap-1 px-2 py-0.5 rounded-md text-xs font-medium bg-amber-500/10 text-amber-800 dark:text-amber-300 border border-amber-500/20 dark:border-amber-500/30";
|
|
1623
|
+
const pillText = document.createElement("span");
|
|
1624
|
+
pillText.textContent = match ? match.label : chip;
|
|
1625
|
+
pill.appendChild(pillText);
|
|
1626
|
+
if (match && referenceProvider) {
|
|
1627
|
+
const openLink = document.createElement("a");
|
|
1628
|
+
openLink.href = referenceProvider.openHref(valueKind, match.slug);
|
|
1629
|
+
openLink.title = `Open ${match.label} page`;
|
|
1630
|
+
openLink.setAttribute("aria-label", `Open ${match.label} page`);
|
|
1631
|
+
openLink.className = "inline-flex items-center justify-center text-muted-foreground/60 hover:text-foreground cursor-pointer";
|
|
1632
|
+
openLink.appendChild(createExternalIcon());
|
|
1633
|
+
pill.appendChild(openLink);
|
|
1634
|
+
}
|
|
1482
1635
|
if (!this.readOnly) {
|
|
1483
1636
|
const rmBtn = document.createElement("button");
|
|
1484
1637
|
rmBtn.type = "button";
|
|
1485
|
-
rmBtn.setAttribute("aria-label", `Remove tag ${
|
|
1486
|
-
rmBtn.className = "inline-flex items-center justify-center text-
|
|
1638
|
+
rmBtn.setAttribute("aria-label", isTags ? `Remove tag ${chip}` : `Remove ${chip}`);
|
|
1639
|
+
rmBtn.className = "inline-flex items-center justify-center text-muted-foreground/60 hover:text-foreground dark:hover:text-foreground cursor-pointer";
|
|
1487
1640
|
rmBtn.appendChild(createCloseIcon("sm"));
|
|
1488
1641
|
rmBtn.addEventListener("click", (e) => {
|
|
1489
1642
|
e.preventDefault();
|
|
1490
1643
|
e.stopPropagation();
|
|
1491
|
-
|
|
1492
|
-
meta[key] = nextTags;
|
|
1493
|
-
updateFrontmatter(view, this.sectionId, meta);
|
|
1644
|
+
commitList(chips.filter((_, i) => i !== idx));
|
|
1494
1645
|
});
|
|
1495
1646
|
pill.appendChild(rmBtn);
|
|
1496
1647
|
}
|
|
1497
1648
|
valCol.appendChild(pill);
|
|
1498
1649
|
}
|
|
1499
1650
|
if (!this.readOnly) {
|
|
1500
|
-
const
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
const
|
|
1505
|
-
const val =
|
|
1506
|
-
if (val && !
|
|
1507
|
-
|
|
1508
|
-
tagInput.value = "";
|
|
1651
|
+
const chipInput = document.createElement("input");
|
|
1652
|
+
chipInput.className = "flex-1 min-w-[70px] bg-transparent text-xs text-foreground outline-none px-1 py-0.5 placeholder:text-muted-foreground/40";
|
|
1653
|
+
chipInput.placeholder = chips.length === 0 ? isReferenceList ? `Add ${valueKind === "effort" ? "effort" : "equipment"}\u2026` : "Add tags\u2026" : isTags ? "Add tag\u2026" : "Add\u2026";
|
|
1654
|
+
chipInput.setAttribute("aria-label", isTags ? `Add tag to ${key}` : `Add to ${key}`);
|
|
1655
|
+
const commitNewChip = () => {
|
|
1656
|
+
const val = chipInput.value.trim().replace(/^,|,$/g, "");
|
|
1657
|
+
if (val && !chips.some((chip) => chip.toLowerCase() === val.toLowerCase())) {
|
|
1658
|
+
chipInput.value = "";
|
|
1509
1659
|
pendingFocus.set(view, { kind: "tag", key });
|
|
1510
|
-
|
|
1660
|
+
commitList([...chips, val]);
|
|
1511
1661
|
}
|
|
1512
1662
|
};
|
|
1513
|
-
valCol.appendChild(
|
|
1514
|
-
attachSuggestions(
|
|
1515
|
-
|
|
1663
|
+
valCol.appendChild(chipInput);
|
|
1664
|
+
attachSuggestions(chipInput, view, root, "value", key, chips, commitNewChip, valueKind);
|
|
1665
|
+
chipInput.addEventListener("keydown", (e) => {
|
|
1516
1666
|
if (e.defaultPrevented) return;
|
|
1517
1667
|
if (e.key === "Enter" || e.key === ",") {
|
|
1518
1668
|
e.preventDefault();
|
|
1519
|
-
|
|
1520
|
-
} else if (e.key === "Backspace" && !
|
|
1669
|
+
commitNewChip();
|
|
1670
|
+
} else if (e.key === "Backspace" && !chipInput.value && chips.length > 0) {
|
|
1521
1671
|
e.preventDefault();
|
|
1522
|
-
meta[key] = tags7.slice(0, -1);
|
|
1523
1672
|
pendingFocus.set(view, { kind: "tag", key });
|
|
1524
|
-
|
|
1673
|
+
commitList(chips.slice(0, -1));
|
|
1525
1674
|
}
|
|
1526
1675
|
});
|
|
1527
|
-
|
|
1528
|
-
if (
|
|
1676
|
+
chipInput.addEventListener("blur", () => queueMicrotask(() => {
|
|
1677
|
+
if (chipInput.isConnected && chipInput.value.trim()) commitNewChip();
|
|
1529
1678
|
}));
|
|
1530
1679
|
const focus = pendingFocus.get(view);
|
|
1531
1680
|
if (focus?.kind === "tag" && focus.key === key) {
|
|
1532
1681
|
setTimeout(() => {
|
|
1533
|
-
if (
|
|
1682
|
+
if (chipInput.isConnected) chipInput.focus();
|
|
1534
1683
|
}, 0);
|
|
1535
1684
|
pendingFocus.delete(view);
|
|
1536
1685
|
}
|
|
1686
|
+
if (chipIsReference && referenceProvider) {
|
|
1687
|
+
const unknown = chips.filter((chip) => !refMatch(chip));
|
|
1688
|
+
if (unknown.length > 0) {
|
|
1689
|
+
const diag = document.createElement("div");
|
|
1690
|
+
diag.setAttribute("data-testid", "editor-ref-unknown");
|
|
1691
|
+
diag.className = "w-full basis-full flex flex-wrap items-center gap-2 text-[10px] text-destructive";
|
|
1692
|
+
const label = document.createElement("span");
|
|
1693
|
+
label.textContent = `Unknown ${valueKind === "effort" ? "effort" : "equipment"}: ${unknown.join(", ")}`;
|
|
1694
|
+
diag.appendChild(label);
|
|
1695
|
+
const selectBtn = document.createElement("button");
|
|
1696
|
+
selectBtn.type = "button";
|
|
1697
|
+
selectBtn.textContent = "Select existing";
|
|
1698
|
+
selectBtn.className = "underline hover:text-foreground cursor-pointer";
|
|
1699
|
+
selectBtn.addEventListener("click", (e) => {
|
|
1700
|
+
e.preventDefault();
|
|
1701
|
+
chipInput.focus();
|
|
1702
|
+
});
|
|
1703
|
+
diag.appendChild(selectBtn);
|
|
1704
|
+
const createLink = document.createElement("a");
|
|
1705
|
+
createLink.href = referenceProvider.createHref(valueKind);
|
|
1706
|
+
createLink.textContent = "Create page";
|
|
1707
|
+
createLink.className = "underline hover:text-foreground";
|
|
1708
|
+
diag.appendChild(createLink);
|
|
1709
|
+
valCol.appendChild(diag);
|
|
1710
|
+
}
|
|
1711
|
+
}
|
|
1537
1712
|
}
|
|
1713
|
+
} else if (nested) {
|
|
1714
|
+
const valSpan = document.createElement("span");
|
|
1715
|
+
valSpan.className = "text-xs text-muted-foreground/60 italic py-0.5 truncate";
|
|
1716
|
+
valSpan.textContent = "Nested block \u2014 edit in YAML";
|
|
1717
|
+
valCol.appendChild(valSpan);
|
|
1538
1718
|
} else {
|
|
1539
1719
|
const strVal = Array.isArray(value) ? value.join(", ") : String(value ?? "");
|
|
1540
1720
|
if (this.readOnly) {
|
|
@@ -1554,8 +1734,9 @@ var DefaultFrontmatterWidget = class extends view.WidgetType {
|
|
|
1554
1734
|
if (cur !== committedVal) {
|
|
1555
1735
|
committedVal = cur;
|
|
1556
1736
|
const num = Number(cur);
|
|
1557
|
-
|
|
1558
|
-
|
|
1737
|
+
const next = cur !== "" && !isNaN(num) ? num : cur;
|
|
1738
|
+
meta[key] = next;
|
|
1739
|
+
patchPropertyInView(view, this.sectionId, [key], next);
|
|
1559
1740
|
}
|
|
1560
1741
|
};
|
|
1561
1742
|
const commitValIfAttached = () => queueMicrotask(() => {
|
|
@@ -1563,7 +1744,16 @@ var DefaultFrontmatterWidget = class extends view.WidgetType {
|
|
|
1563
1744
|
});
|
|
1564
1745
|
valInput.addEventListener("change", commitValIfAttached);
|
|
1565
1746
|
valCol.appendChild(valInput);
|
|
1566
|
-
attachSuggestions(
|
|
1747
|
+
attachSuggestions(
|
|
1748
|
+
valInput,
|
|
1749
|
+
view,
|
|
1750
|
+
root,
|
|
1751
|
+
"value",
|
|
1752
|
+
key,
|
|
1753
|
+
[strVal],
|
|
1754
|
+
commitVal,
|
|
1755
|
+
key.trim().toLowerCase() === "metrics.effort" ? "effort" : "tags"
|
|
1756
|
+
);
|
|
1567
1757
|
valInput.addEventListener("blur", commitValIfAttached);
|
|
1568
1758
|
valInput.addEventListener("keydown", (e) => {
|
|
1569
1759
|
if (e.defaultPrevented) return;
|
|
@@ -1572,6 +1762,34 @@ var DefaultFrontmatterWidget = class extends view.WidgetType {
|
|
|
1572
1762
|
valInput.blur();
|
|
1573
1763
|
}
|
|
1574
1764
|
});
|
|
1765
|
+
if (key.trim().toLowerCase() === "metrics.effort" && referenceProvider) {
|
|
1766
|
+
const match = referenceProvider.resolveEffort(strVal);
|
|
1767
|
+
if (match) {
|
|
1768
|
+
const pill = document.createElement("span");
|
|
1769
|
+
pill.className = "inline-flex items-center gap-1 px-2 py-0.5 rounded-md text-xs font-medium bg-muted/60 text-foreground border border-border/60 shrink-0";
|
|
1770
|
+
const pillText = document.createElement("span");
|
|
1771
|
+
pillText.textContent = match.label;
|
|
1772
|
+
pill.appendChild(pillText);
|
|
1773
|
+
const openLink = document.createElement("a");
|
|
1774
|
+
openLink.href = referenceProvider.openHref("effort", match.slug);
|
|
1775
|
+
openLink.title = `Open ${match.label} page`;
|
|
1776
|
+
openLink.setAttribute("aria-label", `Open ${match.label} page`);
|
|
1777
|
+
openLink.className = "inline-flex items-center justify-center text-muted-foreground/60 hover:text-foreground cursor-pointer";
|
|
1778
|
+
openLink.appendChild(createExternalIcon());
|
|
1779
|
+
pill.appendChild(openLink);
|
|
1780
|
+
valCol.insertBefore(pill, valInput);
|
|
1781
|
+
valInput.className = "flex-1 min-w-[70px] bg-transparent text-xs text-foreground outline-none py-0.5 hover:bg-muted/20 focus:bg-background focus:ring-1 focus:ring-ring rounded px-1 -mx-1 transition-colors";
|
|
1782
|
+
}
|
|
1783
|
+
const diag = renderEffortValueDiagnostics(
|
|
1784
|
+
referenceProvider,
|
|
1785
|
+
strVal,
|
|
1786
|
+
(slug) => {
|
|
1787
|
+
meta[key] = slug;
|
|
1788
|
+
patchPropertyInView(view, this.sectionId, [key], slug);
|
|
1789
|
+
}
|
|
1790
|
+
);
|
|
1791
|
+
if (diag) valCol.appendChild(diag);
|
|
1792
|
+
}
|
|
1575
1793
|
}
|
|
1576
1794
|
if (/^https?:\/\/\S+$/i.test(strVal)) {
|
|
1577
1795
|
const openLink = document.createElement("a");
|
|
@@ -1586,7 +1804,7 @@ var DefaultFrontmatterWidget = class extends view.WidgetType {
|
|
|
1586
1804
|
}
|
|
1587
1805
|
}
|
|
1588
1806
|
row.appendChild(valCol);
|
|
1589
|
-
if (!this.readOnly) {
|
|
1807
|
+
if (!this.readOnly && !nested) {
|
|
1590
1808
|
const actionsCol = document.createElement("div");
|
|
1591
1809
|
actionsCol.className = "flex items-center pr-2";
|
|
1592
1810
|
const delBtn = document.createElement("button");
|
|
@@ -1597,14 +1815,16 @@ var DefaultFrontmatterWidget = class extends view.WidgetType {
|
|
|
1597
1815
|
delBtn.addEventListener("click", (e) => {
|
|
1598
1816
|
e.preventDefault();
|
|
1599
1817
|
e.stopPropagation();
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
updateFrontmatter(view, this.sectionId, newMeta);
|
|
1818
|
+
delete meta[key];
|
|
1819
|
+
patchPropertyInView(view, this.sectionId, [key], null);
|
|
1603
1820
|
});
|
|
1604
1821
|
actionsCol.appendChild(delBtn);
|
|
1605
1822
|
row.appendChild(actionsCol);
|
|
1606
1823
|
}
|
|
1607
1824
|
}
|
|
1825
|
+
if (docKind === "effort" && !this.readOnly) {
|
|
1826
|
+
box.appendChild(this.buildDefinitionRows(view, base));
|
|
1827
|
+
}
|
|
1608
1828
|
if (!this.readOnly) {
|
|
1609
1829
|
const existingTagKey = entries.find(([key]) => isTagProperty(key))?.[0];
|
|
1610
1830
|
const actionsRow = document.createElement("div");
|
|
@@ -1627,10 +1847,36 @@ var DefaultFrontmatterWidget = class extends view.WidgetType {
|
|
|
1627
1847
|
newKey = `property_${count2}`;
|
|
1628
1848
|
}
|
|
1629
1849
|
pendingFocus.set(view, { kind: "key", key: newKey });
|
|
1630
|
-
|
|
1631
|
-
updateFrontmatter(view, this.sectionId, newMeta);
|
|
1850
|
+
patchPropertyInView(view, this.sectionId, [newKey], "");
|
|
1632
1851
|
});
|
|
1633
1852
|
actionsRow.appendChild(addBtn);
|
|
1853
|
+
{
|
|
1854
|
+
const addMetricBtn = document.createElement("button");
|
|
1855
|
+
addMetricBtn.type = "button";
|
|
1856
|
+
addMetricBtn.setAttribute("aria-label", "Add metric");
|
|
1857
|
+
addMetricBtn.setAttribute("data-testid", "editor-add-metric-note");
|
|
1858
|
+
addMetricBtn.className = "inline-flex items-center gap-1.5 text-xs font-medium text-muted-foreground hover:text-foreground px-1 py-1 cursor-pointer transition-colors select-none";
|
|
1859
|
+
addMetricBtn.appendChild(createPlusIcon());
|
|
1860
|
+
const addMetricLabel = document.createElement("span");
|
|
1861
|
+
addMetricLabel.textContent = "Add metric";
|
|
1862
|
+
addMetricBtn.appendChild(addMetricLabel);
|
|
1863
|
+
addMetricBtn.addEventListener("click", (e) => {
|
|
1864
|
+
e.preventDefault();
|
|
1865
|
+
e.stopPropagation();
|
|
1866
|
+
const existing = root.querySelector("[data-frontmatter-metric-draft] input");
|
|
1867
|
+
if (existing) {
|
|
1868
|
+
existing.focus();
|
|
1869
|
+
return;
|
|
1870
|
+
}
|
|
1871
|
+
const draftRow = createMetricDraftRow(view, root, referenceProvider, (path, value) => {
|
|
1872
|
+
patchPropertyInView(view, this.sectionId, path, value);
|
|
1873
|
+
});
|
|
1874
|
+
box.appendChild(draftRow);
|
|
1875
|
+
draftRow.querySelector("input")?.focus();
|
|
1876
|
+
view.requestMeasure();
|
|
1877
|
+
});
|
|
1878
|
+
actionsRow.appendChild(addMetricBtn);
|
|
1879
|
+
}
|
|
1634
1880
|
{
|
|
1635
1881
|
const addTagBtn = document.createElement("button");
|
|
1636
1882
|
addTagBtn.type = "button";
|
|
@@ -1655,7 +1901,7 @@ var DefaultFrontmatterWidget = class extends view.WidgetType {
|
|
|
1655
1901
|
}
|
|
1656
1902
|
const draftRow = createTagDraftRow(view, root, "tags", (val) => {
|
|
1657
1903
|
pendingFocus.set(view, { kind: "tag", key: "tags" });
|
|
1658
|
-
|
|
1904
|
+
patchPropertyInView(view, this.sectionId, ["tags"], [val]);
|
|
1659
1905
|
});
|
|
1660
1906
|
box.appendChild(draftRow);
|
|
1661
1907
|
draftRow.querySelector("input")?.focus();
|
|
@@ -1667,6 +1913,7 @@ var DefaultFrontmatterWidget = class extends view.WidgetType {
|
|
|
1667
1913
|
const editYamlBtn = document.createElement("button");
|
|
1668
1914
|
editYamlBtn.type = "button";
|
|
1669
1915
|
editYamlBtn.setAttribute("aria-label", "Edit YAML");
|
|
1916
|
+
editYamlBtn.setAttribute("data-testid", "editor-property-edit-yaml");
|
|
1670
1917
|
editYamlBtn.className = "inline-flex items-center gap-1.5 text-xs font-medium text-muted-foreground hover:text-foreground px-1 py-1 cursor-pointer transition-colors select-none";
|
|
1671
1918
|
const editYamlLabel = document.createElement("span");
|
|
1672
1919
|
editYamlLabel.textContent = "Edit YAML";
|
|
@@ -1686,6 +1933,82 @@ var DefaultFrontmatterWidget = class extends view.WidgetType {
|
|
|
1686
1933
|
}
|
|
1687
1934
|
return root;
|
|
1688
1935
|
}
|
|
1936
|
+
/**
|
|
1937
|
+
* Effort-definition attribute rows (MET / discipline / intensity tier).
|
|
1938
|
+
* Values live in the nested baseAttributes block; each edit patches that
|
|
1939
|
+
* one path, so unknown sibling keys and comments elsewhere survive.
|
|
1940
|
+
*/
|
|
1941
|
+
buildDefinitionRows(view, base) {
|
|
1942
|
+
const wrap = document.createElement("div");
|
|
1943
|
+
wrap.setAttribute("data-frontmatter-definition", "true");
|
|
1944
|
+
wrap.className = "border-t border-dashed border-border/60";
|
|
1945
|
+
const header = document.createElement("div");
|
|
1946
|
+
header.className = "px-3 pt-2 text-[10px] font-semibold uppercase tracking-wide text-muted-foreground";
|
|
1947
|
+
header.textContent = "Definition";
|
|
1948
|
+
wrap.appendChild(header);
|
|
1949
|
+
const commitField = (field, raw) => {
|
|
1950
|
+
if (field === "met") {
|
|
1951
|
+
const num = Number(raw);
|
|
1952
|
+
patchPropertyInView(view, this.sectionId, ["baseAttributes", "met"], raw !== "" && !Number.isNaN(num) ? num : null);
|
|
1953
|
+
return;
|
|
1954
|
+
}
|
|
1955
|
+
patchPropertyInView(view, this.sectionId, ["baseAttributes", field], raw === "" ? null : raw);
|
|
1956
|
+
};
|
|
1957
|
+
const fieldRow = (label, child) => {
|
|
1958
|
+
const row = document.createElement("label");
|
|
1959
|
+
row.className = "flex items-center gap-2 px-3 py-1.5 min-h-[34px] border-b border-dashed border-border/60 last:border-b-0 max-[479px]:flex-col max-[479px]:items-stretch";
|
|
1960
|
+
const name = document.createElement("span");
|
|
1961
|
+
name.className = "w-28 shrink-0 text-muted-foreground";
|
|
1962
|
+
name.textContent = label;
|
|
1963
|
+
row.appendChild(name);
|
|
1964
|
+
child.className = "flex-1 min-w-0 bg-transparent text-xs text-foreground outline-none py-0.5";
|
|
1965
|
+
row.appendChild(child);
|
|
1966
|
+
wrap.appendChild(row);
|
|
1967
|
+
};
|
|
1968
|
+
const met = document.createElement("input");
|
|
1969
|
+
met.type = "number";
|
|
1970
|
+
met.step = "0.1";
|
|
1971
|
+
met.inputMode = "decimal";
|
|
1972
|
+
met.value = base.met ?? "";
|
|
1973
|
+
met.setAttribute("aria-label", "MET value");
|
|
1974
|
+
met.addEventListener("change", () => queueMicrotask(() => {
|
|
1975
|
+
if (met.isConnected) commitField("met", met.value.trim());
|
|
1976
|
+
}));
|
|
1977
|
+
fieldRow("MET", met);
|
|
1978
|
+
const discipline = document.createElement("select");
|
|
1979
|
+
discipline.setAttribute("aria-label", "Discipline");
|
|
1980
|
+
discipline.className = "flex-1 min-w-0 rounded-md border border-input bg-background px-1.5 text-[11px] text-muted-foreground outline-none";
|
|
1981
|
+
const unset = document.createElement("option");
|
|
1982
|
+
unset.value = "";
|
|
1983
|
+
unset.textContent = "Unset";
|
|
1984
|
+
discipline.appendChild(unset);
|
|
1985
|
+
for (const option of wodWikiLang.EFFORT_DISCIPLINES) {
|
|
1986
|
+
const opt = document.createElement("option");
|
|
1987
|
+
opt.value = option;
|
|
1988
|
+
opt.textContent = option;
|
|
1989
|
+
discipline.appendChild(opt);
|
|
1990
|
+
}
|
|
1991
|
+
discipline.value = base.discipline ?? "";
|
|
1992
|
+
discipline.addEventListener("change", () => commitField("discipline", discipline.value));
|
|
1993
|
+
fieldRow("Discipline", discipline);
|
|
1994
|
+
const tier = document.createElement("select");
|
|
1995
|
+
tier.setAttribute("aria-label", "Intensity tier");
|
|
1996
|
+
tier.className = "flex-1 min-w-0 rounded-md border border-input bg-background px-1.5 text-[11px] text-muted-foreground outline-none";
|
|
1997
|
+
const tierUnset = document.createElement("option");
|
|
1998
|
+
tierUnset.value = "";
|
|
1999
|
+
tierUnset.textContent = "Unset";
|
|
2000
|
+
tier.appendChild(tierUnset);
|
|
2001
|
+
for (const option of ["low", "moderate", "high"]) {
|
|
2002
|
+
const opt = document.createElement("option");
|
|
2003
|
+
opt.value = option;
|
|
2004
|
+
opt.textContent = option;
|
|
2005
|
+
tier.appendChild(opt);
|
|
2006
|
+
}
|
|
2007
|
+
tier.value = base.intensityTier ?? "";
|
|
2008
|
+
tier.addEventListener("change", () => commitField("intensityTier", tier.value));
|
|
2009
|
+
fieldRow("Intensity tier", tier);
|
|
2010
|
+
return wrap;
|
|
2011
|
+
}
|
|
1689
2012
|
destroy(dom) {
|
|
1690
2013
|
widgetCleanup.get(dom)?.forEach((close) => close());
|
|
1691
2014
|
widgetCleanup.delete(dom);
|
|
@@ -1719,7 +2042,7 @@ var EmptyFrontmatterWidget = class extends view.WidgetType {
|
|
|
1719
2042
|
e.preventDefault();
|
|
1720
2043
|
e.stopPropagation();
|
|
1721
2044
|
pendingFocus.set(view, { kind: "key", key: "property" });
|
|
1722
|
-
|
|
2045
|
+
patchPropertyInView(view, "new", ["property"], "");
|
|
1723
2046
|
});
|
|
1724
2047
|
actionsRow.appendChild(addBtn);
|
|
1725
2048
|
const addTagBtn = document.createElement("button");
|
|
@@ -1740,7 +2063,7 @@ var EmptyFrontmatterWidget = class extends view.WidgetType {
|
|
|
1740
2063
|
}
|
|
1741
2064
|
const draftRow = createTagDraftRow(view, root, "tags", (val) => {
|
|
1742
2065
|
pendingFocus.set(view, { kind: "tag", key: "tags" });
|
|
1743
|
-
|
|
2066
|
+
patchPropertyInView(view, "new", ["tags"], [val]);
|
|
1744
2067
|
});
|
|
1745
2068
|
root.appendChild(draftRow);
|
|
1746
2069
|
draftRow.querySelector("input")?.focus();
|
|
@@ -1794,7 +2117,7 @@ var frontmatterPreviewField = state.StateField.define({
|
|
|
1794
2117
|
return buildFrontmatterDecos(state);
|
|
1795
2118
|
},
|
|
1796
2119
|
update(deco, tr) {
|
|
1797
|
-
if (tr.docChanged || tr.reconfigured || tr.selection) {
|
|
2120
|
+
if (tr.docChanged || tr.reconfigured || tr.selection || tr.effects.some((e) => e.is(referenceIndexReload))) {
|
|
1798
2121
|
return buildFrontmatterDecos(tr.state);
|
|
1799
2122
|
}
|
|
1800
2123
|
return deco;
|
|
@@ -4288,7 +4611,8 @@ var SOURCE_OPTIONS = wodWikiWql.WQL_SOURCE_VALUES.map((s) => ({
|
|
|
4288
4611
|
guides: "Static guide pages",
|
|
4289
4612
|
playground: "Playground scratch pages",
|
|
4290
4613
|
dashboards: "Dashboard notes",
|
|
4291
|
-
efforts: "Exercise library notes"
|
|
4614
|
+
efforts: "Exercise library notes",
|
|
4615
|
+
equipment: "Equipment library notes"
|
|
4292
4616
|
}[s]
|
|
4293
4617
|
}));
|
|
4294
4618
|
var PLANE_OPTIONS = wodWikiWql.WQL_RESULT_PLANES.map((v) => ({ value: v, label: v }));
|
|
@@ -12196,6 +12520,7 @@ exports.findWorkoutErrors = findWorkoutErrors;
|
|
|
12196
12520
|
exports.forceSectionParse = forceSectionParse;
|
|
12197
12521
|
exports.frontmatterPreview = frontmatterPreview;
|
|
12198
12522
|
exports.frontmatterPreviewField = frontmatterPreviewField;
|
|
12523
|
+
exports.frontmatterReferenceIndex = frontmatterReferenceIndex;
|
|
12199
12524
|
exports.frontmatterSuggestions = frontmatterSuggestions;
|
|
12200
12525
|
exports.frontmatterVisibility = frontmatterVisibility;
|
|
12201
12526
|
exports.getCursorFocusState = getCursorFocusState;
|
|
@@ -12212,6 +12537,7 @@ exports.markdownTablePreview = markdownTablePreview;
|
|
|
12212
12537
|
exports.navigationFacet = navigationFacet;
|
|
12213
12538
|
exports.previewDecorations = previewDecorations;
|
|
12214
12539
|
exports.queryBlockPreview = queryBlockPreview;
|
|
12540
|
+
exports.referenceIndexReload = referenceIndexReload;
|
|
12215
12541
|
exports.registerCustomCompletionSource = registerCustomCompletionSource;
|
|
12216
12542
|
exports.registeredSectionWidgets = registeredSectionWidgets;
|
|
12217
12543
|
exports.removeRuntimePanel = removeRuntimePanel;
|