@bitcobblers/wod-wiki-ui 0.44.2155 → 0.44.2157

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.
@@ -1016,6 +1016,143 @@ var embedPreviewField = StateField.define({
1016
1016
  var embedPreviewDecorations = [
1017
1017
  embedPreviewField
1018
1018
  ];
1019
+
1020
+ // src/extensions/frontmatter-suggestions.ts
1021
+ var POPOVER_MIN_WIDTH = 192;
1022
+ var POPOVER_MAX_WIDTH = 320;
1023
+ var POPOVER_MAX_HEIGHT = 256;
1024
+ function computeInlinePanelBox(field, host, viewportHeight) {
1025
+ const offsetLeft = Math.max(0, Math.min(field.left - host.left, Math.max(0, host.width - POPOVER_MIN_WIDTH)));
1026
+ const room = Math.max(host.width - offsetLeft, POPOVER_MIN_WIDTH);
1027
+ const width = Math.min(Math.max(field.width, POPOVER_MIN_WIDTH), POPOVER_MAX_WIDTH, room);
1028
+ const belowField = Math.max(0, viewportHeight - field.top - 64);
1029
+ return {
1030
+ width,
1031
+ offsetLeft,
1032
+ maxHeight: Math.max(96, Math.min(POPOVER_MAX_HEIGHT, belowField))
1033
+ };
1034
+ }
1035
+ var panelId = 0;
1036
+ var SuggestionPanel = class {
1037
+ element;
1038
+ inputElement;
1039
+ onPick;
1040
+ view;
1041
+ host;
1042
+ listId;
1043
+ currentChoices = [];
1044
+ currentIndex = -1;
1045
+ isOpen = false;
1046
+ constructor(input, options) {
1047
+ this.inputElement = input;
1048
+ this.onPick = options.onPick;
1049
+ this.view = options.view;
1050
+ this.host = options.host;
1051
+ this.listId = `frontmatter-suggestions-${++panelId}`;
1052
+ const list = document.createElement("div");
1053
+ list.id = this.listId;
1054
+ list.setAttribute("role", "listbox");
1055
+ list.setAttribute("aria-label", options.label);
1056
+ list.tabIndex = -1;
1057
+ list.className = "mt-1 overflow-auto rounded-md border border-border bg-popover text-popover-foreground shadow-md text-xs";
1058
+ list.hidden = true;
1059
+ this.element = list;
1060
+ this.attach();
1061
+ input.setAttribute("role", "combobox");
1062
+ input.setAttribute("aria-haspopup", "listbox");
1063
+ input.setAttribute("aria-autocomplete", "list");
1064
+ input.setAttribute("aria-controls", this.listId);
1065
+ input.setAttribute("aria-expanded", "false");
1066
+ }
1067
+ get choices() {
1068
+ return this.currentChoices;
1069
+ }
1070
+ get activeIndex() {
1071
+ return this.currentIndex;
1072
+ }
1073
+ setChoices(choices) {
1074
+ this.currentChoices = choices;
1075
+ this.currentIndex = -1;
1076
+ this.inputElement.removeAttribute("aria-activedescendant");
1077
+ this.element.replaceChildren();
1078
+ choices.forEach((choice, index) => {
1079
+ const option = document.createElement("div");
1080
+ option.id = `${this.listId}-${index}`;
1081
+ option.setAttribute("role", "option");
1082
+ option.setAttribute("aria-selected", "false");
1083
+ option.className = "cursor-pointer px-2 py-1.5 hover:bg-muted";
1084
+ option.textContent = choice.label;
1085
+ option.addEventListener("mousedown", (event) => event.preventDefault());
1086
+ option.addEventListener("click", () => this.pick(choice));
1087
+ this.element.appendChild(option);
1088
+ });
1089
+ }
1090
+ open() {
1091
+ if (this.isOpen) return;
1092
+ this.isOpen = true;
1093
+ this.element.hidden = false;
1094
+ this.attach();
1095
+ this.position();
1096
+ this.inputElement.setAttribute("aria-expanded", "true");
1097
+ this.view.requestMeasure();
1098
+ }
1099
+ close() {
1100
+ if (!this.isOpen) return;
1101
+ this.isOpen = false;
1102
+ this.element.hidden = true;
1103
+ this.currentIndex = -1;
1104
+ this.inputElement.setAttribute("aria-expanded", "false");
1105
+ this.inputElement.removeAttribute("aria-activedescendant");
1106
+ this.view.requestMeasure();
1107
+ }
1108
+ destroy() {
1109
+ this.close();
1110
+ }
1111
+ activate(index) {
1112
+ this.currentIndex = index;
1113
+ Array.from(this.element.children).forEach((option2, i) => {
1114
+ option2.setAttribute("aria-selected", String(i === index));
1115
+ option2.classList.toggle("bg-muted", i === index);
1116
+ });
1117
+ const option = this.element.children[index];
1118
+ if (!option) return;
1119
+ this.inputElement.setAttribute("aria-activedescendant", option.id);
1120
+ if (option instanceof HTMLElement) option.scrollIntoView?.({ block: "nearest" });
1121
+ }
1122
+ /** Move the highlighted option; the first/last option wraps around. */
1123
+ moveActive(delta) {
1124
+ if (this.currentChoices.length === 0) return;
1125
+ const next = this.currentIndex < 0 ? delta > 0 ? 0 : this.currentChoices.length - 1 : (this.currentIndex + delta + this.currentChoices.length) % this.currentChoices.length;
1126
+ this.activate(next);
1127
+ }
1128
+ pickActive() {
1129
+ const choice = this.currentChoices[this.currentIndex];
1130
+ if (choice) this.pick(choice);
1131
+ }
1132
+ pick(choice) {
1133
+ this.inputElement.value = choice.value;
1134
+ this.close();
1135
+ this.onPick(choice);
1136
+ }
1137
+ /** Join the DOM under its host row (idempotent). */
1138
+ attach() {
1139
+ if (this.element.parentElement) return;
1140
+ this.host.after(this.element);
1141
+ }
1142
+ /** Anchor the panel to the field inside its row. */
1143
+ position() {
1144
+ const box = computeInlinePanelBox(
1145
+ this.inputElement.getBoundingClientRect(),
1146
+ this.host.getBoundingClientRect(),
1147
+ window.innerHeight
1148
+ );
1149
+ this.element.style.width = `${box.width}px`;
1150
+ this.element.style.marginLeft = `${box.offsetLeft}px`;
1151
+ this.element.style.maxHeight = `${box.maxHeight}px`;
1152
+ }
1153
+ };
1154
+
1155
+ // src/extensions/frontmatter-preview.ts
1019
1156
  var frontmatterSuggestions = Facet.define({ combine: (providers) => providers[0] ?? null });
1020
1157
  var frontmatterReferenceIndex = Facet.define({ combine: (providers) => providers[0] ?? null });
1021
1158
  var referenceIndexReload = StateEffect.define();
@@ -1024,52 +1161,52 @@ var frontmatterVisibility = Facet.define({
1024
1161
  });
1025
1162
  var pendingFocus = /* @__PURE__ */ new WeakMap();
1026
1163
  var widgetCleanup = /* @__PURE__ */ new WeakMap();
1027
- var suggestionId = 0;
1164
+ var helperId = 0;
1028
1165
  function isTagProperty(key) {
1029
1166
  return ["tag", "tags", "category"].includes(key.trim().toLowerCase());
1030
1167
  }
1168
+ function appendFieldHelper(parent, text) {
1169
+ const helper = document.createElement("span");
1170
+ helper.id = `frontmatter-hint-${++helperId}`;
1171
+ helper.className = "sr-only";
1172
+ helper.textContent = text;
1173
+ parent.appendChild(helper);
1174
+ return helper;
1175
+ }
1176
+ function createColumnHeader() {
1177
+ const header = document.createElement("div");
1178
+ header.className = "flex items-center border-b border-border text-[11px] font-semibold uppercase tracking-wide text-muted-foreground";
1179
+ const key = document.createElement("div");
1180
+ key.dataset.frontmatterColumn = "key";
1181
+ key.className = "px-3 py-1.5 w-36 shrink-0 border-r border-border max-[479px]:w-auto max-[479px]:border-r-0 max-[479px]:border-b";
1182
+ key.textContent = "Key";
1183
+ const value = document.createElement("div");
1184
+ value.dataset.frontmatterColumn = "value";
1185
+ value.className = "px-3 py-1.5 flex-1 min-w-0";
1186
+ value.textContent = "Value";
1187
+ const actions = document.createElement("div");
1188
+ actions.className = "w-9 shrink-0";
1189
+ header.append(key, value, actions);
1190
+ return header;
1191
+ }
1192
+ function ensureColumnHeader(box, before) {
1193
+ if (box.querySelector("[data-frontmatter-column]")) return;
1194
+ box.insertBefore(createColumnHeader(), before);
1195
+ }
1031
1196
  function attachSuggestions(input, view, root, kind, key, excluded, commit, valueKind = "tags") {
1032
1197
  const provider = view.state.facet(frontmatterSuggestions);
1033
1198
  if (!provider || !input.parentElement) return;
1034
- const parent = input.parentElement;
1035
- parent.classList.add("relative");
1036
- const list = document.createElement("div");
1037
- list.id = `frontmatter-suggestions-${++suggestionId}`;
1038
- list.setAttribute("role", "listbox");
1039
- list.className = "absolute left-0 top-full z-50 max-h-48 overflow-auto rounded-md border border-border bg-background shadow-md min-w-full text-xs";
1040
- list.hidden = true;
1041
- parent.appendChild(list);
1042
- input.setAttribute("role", "combobox");
1043
- input.setAttribute("aria-autocomplete", "list");
1044
- input.setAttribute("aria-controls", list.id);
1045
- input.setAttribute("aria-expanded", "false");
1199
+ const host = input.closest("[data-frontmatter-row]") ?? input.parentElement;
1200
+ const panel = new SuggestionPanel(input, {
1201
+ label: kind === "key" ? "Suggested properties" : suggestionListLabel(valueKind),
1202
+ onPick: () => commit(),
1203
+ view,
1204
+ host
1205
+ });
1046
1206
  let generation = 0;
1047
- let choices = [];
1048
- let active = -1;
1049
1207
  const close = () => {
1050
1208
  generation++;
1051
- choices = [];
1052
- active = -1;
1053
- list.hidden = true;
1054
- input.setAttribute("aria-expanded", "false");
1055
- input.removeAttribute("aria-activedescendant");
1056
- };
1057
- const select = (choice) => {
1058
- input.value = choice.value;
1059
- close();
1060
- commit();
1061
- };
1062
- const activate = (index) => {
1063
- active = index;
1064
- Array.from(list.children).forEach((option2, i) => {
1065
- option2.setAttribute("aria-selected", String(i === active));
1066
- option2.classList.toggle("bg-muted", i === active);
1067
- });
1068
- const option = list.children[active];
1069
- if (option) {
1070
- input.setAttribute("aria-activedescendant", option.id);
1071
- if (option instanceof HTMLElement) option.scrollIntoView?.({ block: "nearest" });
1072
- }
1209
+ panel.close();
1073
1210
  };
1074
1211
  const refresh = async (showAll = false) => {
1075
1212
  close();
@@ -1092,25 +1229,11 @@ function attachSuggestions(input, view, root, kind, key, excluded, commit, value
1092
1229
  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() }));
1093
1230
  }
1094
1231
  const selected = new Set(excluded.map((label) => label.toLowerCase()));
1095
- choices = candidates.filter(
1232
+ const choices = candidates.filter(
1096
1233
  (candidate) => (query === "" || candidate.haystack.includes(query)) && !selected.has(candidate.value.toLowerCase())
1097
- );
1098
- active = -1;
1099
- input.removeAttribute("aria-activedescendant");
1100
- list.replaceChildren();
1101
- choices.forEach((choice, index) => {
1102
- const option = document.createElement("div");
1103
- option.id = `${list.id}-${index}`;
1104
- option.setAttribute("role", "option");
1105
- option.setAttribute("aria-selected", "false");
1106
- option.className = "cursor-pointer px-2 py-1.5 hover:bg-muted";
1107
- option.textContent = choice.label;
1108
- option.addEventListener("mousedown", (event) => event.preventDefault());
1109
- option.addEventListener("click", () => select(choice));
1110
- list.appendChild(option);
1111
- });
1112
- list.hidden = choices.length === 0;
1113
- input.setAttribute("aria-expanded", String(choices.length > 0));
1234
+ ).map((candidate) => ({ value: candidate.value, label: candidate.label }));
1235
+ panel.setChoices(choices);
1236
+ if (choices.length > 0) panel.open();
1114
1237
  } catch {
1115
1238
  if (request === generation) close();
1116
1239
  }
@@ -1125,16 +1248,22 @@ function attachSuggestions(input, view, root, kind, key, excluded, commit, value
1125
1248
  } else if (event.key === "Escape") {
1126
1249
  event.preventDefault();
1127
1250
  close();
1128
- } else if ((event.key === "ArrowDown" || event.key === "ArrowUp") && choices.length) {
1251
+ } else if (event.key === "ArrowDown" || event.key === "ArrowUp") {
1252
+ if (panel.choices.length === 0) return;
1129
1253
  event.preventDefault();
1130
- const direction = event.key === "ArrowDown" ? 1 : -1;
1131
- activate(active < 0 ? direction === 1 ? 0 : choices.length - 1 : (active + direction + choices.length) % choices.length);
1132
- } else if ((event.key === "Enter" || event.key === "Tab") && active >= 0) {
1254
+ panel.moveActive(event.key === "ArrowDown" ? 1 : -1);
1255
+ } else if (event.key === "Enter" || event.key === "Tab") {
1256
+ if (panel.activeIndex < 0) return;
1133
1257
  event.preventDefault();
1134
- select(choices[active]);
1258
+ panel.pickActive();
1135
1259
  }
1136
1260
  });
1137
- widgetCleanup.get(root)?.push(close);
1261
+ widgetCleanup.get(root)?.push(() => panel.destroy());
1262
+ }
1263
+ function suggestionListLabel(valueKind) {
1264
+ if (valueKind === "effort") return "Suggested efforts";
1265
+ if (valueKind === "equipment") return "Suggested equipment";
1266
+ return "Suggested tags";
1138
1267
  }
1139
1268
  function parseTagList(val) {
1140
1269
  if (Array.isArray(val)) {
@@ -1212,10 +1341,11 @@ function isReferenceKey(key, docKind) {
1212
1341
  }
1213
1342
  function createTagDraftRow(view, root, key, onCommit) {
1214
1343
  const row = document.createElement("div");
1215
- 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";
1344
+ row.className = "flex items-center min-h-[34px] border-b border-dashed border-border last:border-b-0 group hover:bg-muted/10 transition-colors max-[479px]:flex-col max-[479px]:items-stretch";
1216
1345
  row.setAttribute("data-frontmatter-tag-draft", "true");
1346
+ row.dataset.frontmatterRow = key;
1217
1347
  const keyCol = document.createElement("div");
1218
- 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";
1348
+ keyCol.className = "flex items-center gap-2 px-3 py-1.5 w-36 shrink-0 border-r border-dashed border-border text-muted-foreground max-[479px]:w-auto max-[479px]:border-r-0 max-[479px]:border-b";
1219
1349
  keyCol.appendChild(createTagIcon());
1220
1350
  const keyLabel = document.createElement("span");
1221
1351
  keyLabel.className = "truncate font-medium text-foreground/90";
@@ -1225,9 +1355,15 @@ function createTagDraftRow(view, root, key, onCommit) {
1225
1355
  const valCol = document.createElement("div");
1226
1356
  valCol.className = "flex items-center flex-wrap gap-1.5 px-3 py-1.5 flex-1 min-w-0";
1227
1357
  const input = document.createElement("input");
1228
- 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";
1358
+ input.className = "flex-none w-44 max-w-full rounded-md border border-field-border bg-background/60 px-2 py-1 text-xs text-foreground outline-none placeholder:text-field-placeholder focus:border-ring focus:ring-1 focus:ring-ring";
1229
1359
  input.placeholder = "Add tag\u2026";
1230
- input.setAttribute("aria-label", `Add tag to ${key}`);
1360
+ input.setAttribute("aria-label", `Value for ${key}`);
1361
+ input.dataset.frontmatterField = "value";
1362
+ input.dataset.frontmatterProperty = key;
1363
+ input.setAttribute(
1364
+ "aria-describedby",
1365
+ appendFieldHelper(valCol, "Press Enter to add the value.").id
1366
+ );
1231
1367
  valCol.appendChild(input);
1232
1368
  row.appendChild(valCol);
1233
1369
  let settled = false;
@@ -1306,8 +1442,9 @@ var METRIC_DRAFT_KINDS = {
1306
1442
  };
1307
1443
  function createMetricDraftRow(view, root, referenceProvider, commit) {
1308
1444
  const row = document.createElement("div");
1309
- 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";
1445
+ row.className = "flex items-center min-h-[34px] border-b border-dashed border-border last:border-b-0 group hover:bg-muted/10 transition-colors max-[479px]:flex-col max-[479px]:items-stretch";
1310
1446
  row.setAttribute("data-frontmatter-metric-draft", "true");
1447
+ row.dataset.frontmatterRow = "metric";
1311
1448
  const select = document.createElement("select");
1312
1449
  select.setAttribute("aria-label", "Metric kind");
1313
1450
  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";
@@ -1321,9 +1458,14 @@ function createMetricDraftRow(view, root, referenceProvider, commit) {
1321
1458
  const valCol = document.createElement("div");
1322
1459
  valCol.className = "flex items-center flex-wrap gap-1.5 px-3 py-1.5 flex-1 min-w-0";
1323
1460
  const input = document.createElement("input");
1324
- 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";
1461
+ input.className = "flex-none w-44 max-w-full rounded-md border border-field-border bg-background/60 px-2 py-1 text-xs text-foreground outline-none placeholder:text-field-placeholder focus:border-ring focus:ring-1 focus:ring-ring";
1325
1462
  input.placeholder = "Value\u2026";
1326
1463
  input.setAttribute("aria-label", "Metric value");
1464
+ input.dataset.frontmatterField = "value";
1465
+ input.setAttribute(
1466
+ "aria-describedby",
1467
+ appendFieldHelper(valCol, "Press Enter to apply the metric value.").id
1468
+ );
1327
1469
  valCol.appendChild(input);
1328
1470
  row.appendChild(valCol);
1329
1471
  let settled = false;
@@ -1515,6 +1657,7 @@ var DefaultFrontmatterWidget = class extends WidgetType {
1515
1657
  const docKind = detectDefinitionKind(meta);
1516
1658
  const referenceProvider = view.state.facet(frontmatterReferenceIndex)?.() ?? null;
1517
1659
  const base = docKind === "effort" ? readBaseAttributes(body) : {};
1660
+ box.appendChild(createColumnHeader());
1518
1661
  if (entries.length === 0) {
1519
1662
  const emptyRow = document.createElement("div");
1520
1663
  emptyRow.className = "px-3 py-2 text-xs text-muted-foreground/60 italic";
@@ -1527,10 +1670,12 @@ var DefaultFrontmatterWidget = class extends WidgetType {
1527
1670
  const isReferenceList = (isReferenceKey(key, docKind) || key === "aliases") && Array.isArray(value);
1528
1671
  const nested = value === "" && ownsNestedBlock(body, key);
1529
1672
  const row = document.createElement("div");
1530
- 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";
1673
+ row.className = "flex items-center min-h-[34px] border-b border-dashed border-border last:border-b-0 group hover:bg-muted/10 transition-colors max-[479px]:flex-col max-[479px]:items-stretch";
1674
+ row.dataset.frontmatterRow = key;
1531
1675
  box.appendChild(row);
1532
1676
  const keyCol = document.createElement("div");
1533
- 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";
1677
+ keyCol.className = "flex items-center gap-2 px-3 py-1.5 w-36 shrink-0 border-r border-dashed border-border text-muted-foreground max-[479px]:w-auto max-[479px]:border-r-0 max-[479px]:border-b";
1678
+ row.appendChild(keyCol);
1534
1679
  keyCol.appendChild(isTags || isReferenceList ? createTagIcon() : createListIcon());
1535
1680
  if (this.readOnly || nested) {
1536
1681
  const keyLabel = document.createElement("span");
@@ -1542,7 +1687,16 @@ var DefaultFrontmatterWidget = class extends WidgetType {
1542
1687
  keyInput.className = "w-full bg-transparent text-xs text-foreground/90 font-medium outline-none truncate hover:bg-muted/30 focus:bg-background focus:ring-1 focus:ring-ring rounded px-1 -mx-1";
1543
1688
  keyInput.value = key;
1544
1689
  keyInput.spellcheck = false;
1545
- keyInput.setAttribute("aria-label", `Property name ${key}`);
1690
+ keyInput.setAttribute("aria-label", `Property key: ${key}`);
1691
+ keyInput.dataset.frontmatterField = "key";
1692
+ keyInput.dataset.frontmatterProperty = key;
1693
+ keyInput.setAttribute(
1694
+ "aria-describedby",
1695
+ appendFieldHelper(
1696
+ keyCol,
1697
+ "Property name. Press Enter to apply. Arrow keys browse suggested property names."
1698
+ ).id
1699
+ );
1546
1700
  let currentKey = key;
1547
1701
  const commitKey = () => {
1548
1702
  const nextKey = keyInput.value.trim();
@@ -1583,9 +1737,9 @@ var DefaultFrontmatterWidget = class extends WidgetType {
1583
1737
  pendingFocus.delete(view);
1584
1738
  }
1585
1739
  }
1586
- row.appendChild(keyCol);
1587
1740
  const valCol = document.createElement("div");
1588
1741
  valCol.className = "flex items-center flex-wrap gap-1.5 px-3 py-1.5 flex-1 min-w-0";
1742
+ row.appendChild(valCol);
1589
1743
  const commitList = (next) => {
1590
1744
  meta[key] = next;
1591
1745
  patchPropertyInView(view, this.sectionId, [key], next.length > 0 ? next : "");
@@ -1631,9 +1785,18 @@ var DefaultFrontmatterWidget = class extends WidgetType {
1631
1785
  }
1632
1786
  if (!this.readOnly) {
1633
1787
  const chipInput = document.createElement("input");
1634
- 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";
1788
+ chipInput.className = "flex-none w-44 max-w-full rounded-md border border-field-border bg-background/60 px-2 py-1 text-xs text-foreground outline-none placeholder:text-field-placeholder focus:border-ring focus:ring-1 focus:ring-ring";
1635
1789
  chipInput.placeholder = chips.length === 0 ? isReferenceList ? `Add ${valueKind === "effort" ? "effort" : "equipment"}\u2026` : "Add tags\u2026" : isTags ? "Add tag\u2026" : "Add\u2026";
1636
- chipInput.setAttribute("aria-label", isTags ? `Add tag to ${key}` : `Add to ${key}`);
1790
+ chipInput.setAttribute("aria-label", `Value for ${key}`);
1791
+ chipInput.dataset.frontmatterField = "value";
1792
+ chipInput.dataset.frontmatterProperty = key;
1793
+ chipInput.setAttribute(
1794
+ "aria-describedby",
1795
+ appendFieldHelper(
1796
+ valCol,
1797
+ "Press Enter or comma to add a value. Arrow keys browse the suggestions."
1798
+ ).id
1799
+ );
1637
1800
  const commitNewChip = () => {
1638
1801
  const val = chipInput.value.trim().replace(/^,|,$/g, "");
1639
1802
  if (val && !chips.some((chip) => chip.toLowerCase() === val.toLowerCase())) {
@@ -1706,10 +1869,16 @@ var DefaultFrontmatterWidget = class extends WidgetType {
1706
1869
  valCol.appendChild(valSpan);
1707
1870
  } else {
1708
1871
  const valInput = document.createElement("input");
1709
- valInput.className = "w-full 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";
1872
+ valInput.className = "w-full rounded-md border border-field-border bg-background/60 px-2 py-1 text-xs text-foreground outline-none placeholder:text-field-placeholder focus:border-ring focus:ring-1 focus:ring-ring transition-colors";
1710
1873
  valInput.value = strVal;
1711
1874
  valInput.spellcheck = false;
1712
1875
  valInput.setAttribute("aria-label", `Value for ${key}`);
1876
+ valInput.dataset.frontmatterField = "value";
1877
+ valInput.dataset.frontmatterProperty = key;
1878
+ valInput.setAttribute(
1879
+ "aria-describedby",
1880
+ appendFieldHelper(valCol, "Property value. Press Enter to apply.").id
1881
+ );
1713
1882
  let committedVal = strVal;
1714
1883
  const commitVal = () => {
1715
1884
  const cur = valInput.value.trim();
@@ -1760,7 +1929,7 @@ var DefaultFrontmatterWidget = class extends WidgetType {
1760
1929
  openLink.appendChild(createExternalIcon());
1761
1930
  pill.appendChild(openLink);
1762
1931
  valCol.insertBefore(pill, valInput);
1763
- 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";
1932
+ valInput.className = "flex-1 min-w-[70px] rounded-md border border-field-border bg-background/60 px-2 py-1 text-xs text-foreground outline-none placeholder:text-field-placeholder focus:border-ring focus:ring-1 focus:ring-ring transition-colors";
1764
1933
  }
1765
1934
  const diag = renderEffortValueDiagnostics(
1766
1935
  referenceProvider,
@@ -1785,14 +1954,13 @@ var DefaultFrontmatterWidget = class extends WidgetType {
1785
1954
  valCol.appendChild(openLink);
1786
1955
  }
1787
1956
  }
1788
- row.appendChild(valCol);
1789
1957
  if (!this.readOnly && !nested) {
1790
1958
  const actionsCol = document.createElement("div");
1791
1959
  actionsCol.className = "flex items-center pr-2";
1792
1960
  const delBtn = document.createElement("button");
1793
1961
  delBtn.type = "button";
1794
1962
  delBtn.setAttribute("aria-label", `Remove property ${key}`);
1795
- delBtn.className = "opacity-0 group-hover:opacity-100 text-muted-foreground/40 hover:text-destructive p-1 rounded transition-opacity cursor-pointer";
1963
+ delBtn.className = "opacity-0 group-hover:opacity-100 focus-visible:opacity-100 text-muted-foreground/70 hover:text-destructive p-1 rounded transition-opacity cursor-pointer";
1796
1964
  delBtn.appendChild(createCloseIcon("md"));
1797
1965
  delBtn.addEventListener("click", (e) => {
1798
1966
  e.preventDefault();
@@ -1872,7 +2040,9 @@ var DefaultFrontmatterWidget = class extends WidgetType {
1872
2040
  e.preventDefault();
1873
2041
  e.stopPropagation();
1874
2042
  if (existingTagKey) {
1875
- const input = Array.from(root.querySelectorAll("input")).find((element) => element.getAttribute("aria-label") === `Add tag to ${existingTagKey}`);
2043
+ const input = Array.from(root.querySelectorAll(
2044
+ '[data-frontmatter-field="value"]'
2045
+ )).find((element) => element.dataset.frontmatterProperty === existingTagKey);
1876
2046
  input?.focus();
1877
2047
  return;
1878
2048
  }
@@ -2048,6 +2218,7 @@ var EmptyFrontmatterWidget = class extends WidgetType {
2048
2218
  patchPropertyInView(view, "new", ["tags"], [val]);
2049
2219
  });
2050
2220
  root.appendChild(draftRow);
2221
+ ensureColumnHeader(root, draftRow);
2051
2222
  draftRow.querySelector("input")?.focus();
2052
2223
  view.requestMeasure();
2053
2224
  });
@@ -12667,5 +12838,5 @@ function editorPreset(optionsOrDialect = "markdown") {
12667
12838
  }
12668
12839
 
12669
12840
  export { AGG_OPTIONS, CANONICAL_BLOCK_TYPES, CLAUSE_META, ComposerRegistry, DEFAULT_DIAGNOSTICS_DEBOUNCE_MS, DEFAULT_OUTPUT_FILTERS, DEFAULT_PRIMARY_FILTER, DefaultFrontmatterWidget, EditorDialog, GROUPBY_OPTIONS, GoalRings, KIND_OPTIONS, METRIC_OPTIONS, MULTI_VALUE_TYPES, MetricBadge, OUTPUT_TYPE_CLASS, OUTPUT_TYPE_DOT, OutputFilterPills, OutputStatementsTable, PLANE_OPTIONS, ProposedMetricBadge, QueryBlockView, QueryValue, ROLLUP_OPTIONS, RowsResultsChrome, RowsTable, SERIES_COLORS, SOURCE_OPTIONS, SUGGESTION_BINDINGS, StackedBar, TARGET_OPTIONS, TIME_OPTIONS, TONE_CLASS, TokenSlotPill, TopList, UNIT_OPTIONS, WHERE_AGGREGATORS, WHERE_METRICS, WidgetChart, WidgetProblemBadge, WqlBars, WqlComposer, WqlDiagnosticsStrip, WqlEmptyState, WqlQueryInspectorModal, WqlTable, WqlTimeseries, ZoneDistribution, activeCursorSection, addRuntimePanel, blockTypesFromBlocks, canonicalSuggestionItems, catalogIdsFromBlocks, cn, compactNumber, composerRegistry, configureOverlayActions, cursorFocusExtension, dateRangeSlot, dispatchAddRuntimePanel, dispatchExpandRuntimePanel, dispatchGutterHighlights, dispatchRemoveRuntimePanel, editQueryClause, editingWidgetsField, editorPreset, editorTheme, embedPreviewDecorations, expandRuntimePanel, extractBlockQueries, extractMetricsByCategory, fenceCompletion, findQueryBlockSection, findWorkoutErrors, forceSectionParse, formatClockTime, formatMMSS, formatTimestamp, frontmatterPreview, frontmatterPreviewField, frontmatterReferenceIndex, frontmatterSuggestions, frontmatterVisibility, getClauseMeta, getCursorFocusState, getOverlayActions, getSuggestionBinding, gutterHighlightsField, gutterUnified, handleFenceAutoWrap, hashCode, inlineButtonDecoration, invalidateSuggestions, lineIdsExtension, linkOpen, linkPreview, loadSuggestions, markdownSyntaxHiding, markdownTablePreview, matchFilterTypeahead, mergeSeries, mergeSuggestionItems, mergeTagSuggestions, navigationFacet, normalizeOutputFilter, patchBlockQuery, presentBadges, previewDecorations, queryBlockPreview, readSessionRpe, referenceIndexReload, registerCustomCompletionSource, registeredSectionWidgets, removeRuntimePanel, resolveQueryDraft, runtimePanelField, saveBlockQuerySource, sectionAtPos, sectionField, sectionGeometry, sectionIdentity, sectionIdentityHistory, sectionMove, sectionRestore, sectionSaved, sessionQueryInsert, sessionQueryWql, setGutterHighlights, setSuggestionBinding, smartIncrement, summarizeAggregate, summarizeFind, summarizePipeline, tagsFromStaticBlocks, toChartResult, toggleWidgetEdit, tooltipTimestamp, unregisterCustomCompletionSource, urlAtPos, useChartShape, useComposerSlots, useSuggestions, useVisualViewportRect, useWqlStageCounts, widgetBlockPreview, wodAutoWrap, wodAutocompletion, wodEditorKeymap, wodLinter, wodOverlayPanel, workoutLintSource, wqlToPills, wrapInTimeFence };
12670
- //# sourceMappingURL=chunk-K35IEZWM.mjs.map
12671
- //# sourceMappingURL=chunk-K35IEZWM.mjs.map
12841
+ //# sourceMappingURL=chunk-NQMMGF3R.mjs.map
12842
+ //# sourceMappingURL=chunk-NQMMGF3R.mjs.map