@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.
@@ -1,3 +1,3 @@
1
- export { DefaultFrontmatterWidget, activeCursorSection, addRuntimePanel, blockContentId, configureOverlayActions, cursorFocusExtension, dispatchAddRuntimePanel, dispatchExpandRuntimePanel, dispatchGutterHighlights, dispatchRemoveRuntimePanel, editingWidgetsField, editorPreset, editorTheme, embedPreviewDecorations, expandRuntimePanel, fenceCompletion, findQueryBlockSection, findWorkoutErrors, forceSectionParse, frontmatterPreview, frontmatterPreviewField, frontmatterReferenceIndex, frontmatterSuggestions, frontmatterVisibility, getCursorFocusState, getOverlayActions, gutterHighlightsField, gutterUnified, handleFenceAutoWrap, inlineButtonDecoration, lineIdsExtension, linkOpen, linkPreview, markdownSyntaxHiding, markdownTablePreview, navigationFacet, previewDecorations, queryBlockPreview, referenceIndexReload, registerCustomCompletionSource, registeredSectionWidgets, removeRuntimePanel, runtimePanelField, saveBlockQuerySource, sectionAtPos, sectionField, sectionGeometry, sectionIdentity, sectionIdentityHistory, sectionMove, sectionRestore, sectionSaved, sessionQueryInsert, sessionQueryWql, setGutterHighlights, smartIncrement, toggleWidgetEdit, unregisterCustomCompletionSource, urlAtPos, widgetBlockPreview, wodAutoWrap, wodAutocompletion, wodEditorKeymap, wodLinter, wodOverlayPanel, workoutLintSource, wrapInTimeFence } from '../chunk-K35IEZWM.mjs';
1
+ export { DefaultFrontmatterWidget, activeCursorSection, addRuntimePanel, blockContentId, configureOverlayActions, cursorFocusExtension, dispatchAddRuntimePanel, dispatchExpandRuntimePanel, dispatchGutterHighlights, dispatchRemoveRuntimePanel, editingWidgetsField, editorPreset, editorTheme, embedPreviewDecorations, expandRuntimePanel, fenceCompletion, findQueryBlockSection, findWorkoutErrors, forceSectionParse, frontmatterPreview, frontmatterPreviewField, frontmatterReferenceIndex, frontmatterSuggestions, frontmatterVisibility, getCursorFocusState, getOverlayActions, gutterHighlightsField, gutterUnified, handleFenceAutoWrap, inlineButtonDecoration, lineIdsExtension, linkOpen, linkPreview, markdownSyntaxHiding, markdownTablePreview, navigationFacet, previewDecorations, queryBlockPreview, referenceIndexReload, registerCustomCompletionSource, registeredSectionWidgets, removeRuntimePanel, runtimePanelField, saveBlockQuerySource, sectionAtPos, sectionField, sectionGeometry, sectionIdentity, sectionIdentityHistory, sectionMove, sectionRestore, sectionSaved, sessionQueryInsert, sessionQueryWql, setGutterHighlights, smartIncrement, toggleWidgetEdit, unregisterCustomCompletionSource, urlAtPos, widgetBlockPreview, wodAutoWrap, wodAutocompletion, wodEditorKeymap, wodLinter, wodOverlayPanel, workoutLintSource, wrapInTimeFence } from '../chunk-NQMMGF3R.mjs';
2
2
  //# sourceMappingURL=index.mjs.map
3
3
  //# sourceMappingURL=index.mjs.map
package/dist/index.cjs CHANGED
@@ -1351,14 +1351,14 @@ function RangeSelector({ weeks: weeksProp, onWeeksChange, className }) {
1351
1351
  setInternalWeeks(w);
1352
1352
  }
1353
1353
  };
1354
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("inline-flex items-center gap-1 rounded-lg border border-border bg-card p-1", className), children: [4, 8, 16].map((w) => /* @__PURE__ */ jsxRuntime.jsxs(
1354
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("inline-flex items-center gap-1.5 rounded-lg border border-border bg-card p-1", className), children: [4, 8, 16].map((w) => /* @__PURE__ */ jsxRuntime.jsxs(
1355
1355
  "button",
1356
1356
  {
1357
1357
  type: "button",
1358
1358
  onClick: () => handleSelect(w),
1359
1359
  className: cn(
1360
- "text-xs px-2.5 py-1 rounded-md transition-colors",
1361
- currentWeeks === w ? "bg-primary text-primary-foreground font-medium" : "text-muted-foreground hover:text-foreground hover:bg-muted"
1360
+ "min-h-11 min-w-11 px-3 py-2 text-xs rounded-md transition-colors flex items-center justify-center font-medium",
1361
+ currentWeeks === w ? "bg-primary text-primary-foreground" : "text-muted-foreground hover:text-foreground hover:bg-muted"
1362
1362
  ),
1363
1363
  children: [
1364
1364
  w,
@@ -5484,6 +5484,143 @@ var embedPreviewField = state.StateField.define({
5484
5484
  var embedPreviewDecorations = [
5485
5485
  embedPreviewField
5486
5486
  ];
5487
+
5488
+ // src/extensions/frontmatter-suggestions.ts
5489
+ var POPOVER_MIN_WIDTH = 192;
5490
+ var POPOVER_MAX_WIDTH = 320;
5491
+ var POPOVER_MAX_HEIGHT = 256;
5492
+ function computeInlinePanelBox(field, host, viewportHeight) {
5493
+ const offsetLeft = Math.max(0, Math.min(field.left - host.left, Math.max(0, host.width - POPOVER_MIN_WIDTH)));
5494
+ const room = Math.max(host.width - offsetLeft, POPOVER_MIN_WIDTH);
5495
+ const width = Math.min(Math.max(field.width, POPOVER_MIN_WIDTH), POPOVER_MAX_WIDTH, room);
5496
+ const belowField = Math.max(0, viewportHeight - field.top - 64);
5497
+ return {
5498
+ width,
5499
+ offsetLeft,
5500
+ maxHeight: Math.max(96, Math.min(POPOVER_MAX_HEIGHT, belowField))
5501
+ };
5502
+ }
5503
+ var panelId = 0;
5504
+ var SuggestionPanel = class {
5505
+ element;
5506
+ inputElement;
5507
+ onPick;
5508
+ view;
5509
+ host;
5510
+ listId;
5511
+ currentChoices = [];
5512
+ currentIndex = -1;
5513
+ isOpen = false;
5514
+ constructor(input, options) {
5515
+ this.inputElement = input;
5516
+ this.onPick = options.onPick;
5517
+ this.view = options.view;
5518
+ this.host = options.host;
5519
+ this.listId = `frontmatter-suggestions-${++panelId}`;
5520
+ const list = document.createElement("div");
5521
+ list.id = this.listId;
5522
+ list.setAttribute("role", "listbox");
5523
+ list.setAttribute("aria-label", options.label);
5524
+ list.tabIndex = -1;
5525
+ list.className = "mt-1 overflow-auto rounded-md border border-border bg-popover text-popover-foreground shadow-md text-xs";
5526
+ list.hidden = true;
5527
+ this.element = list;
5528
+ this.attach();
5529
+ input.setAttribute("role", "combobox");
5530
+ input.setAttribute("aria-haspopup", "listbox");
5531
+ input.setAttribute("aria-autocomplete", "list");
5532
+ input.setAttribute("aria-controls", this.listId);
5533
+ input.setAttribute("aria-expanded", "false");
5534
+ }
5535
+ get choices() {
5536
+ return this.currentChoices;
5537
+ }
5538
+ get activeIndex() {
5539
+ return this.currentIndex;
5540
+ }
5541
+ setChoices(choices) {
5542
+ this.currentChoices = choices;
5543
+ this.currentIndex = -1;
5544
+ this.inputElement.removeAttribute("aria-activedescendant");
5545
+ this.element.replaceChildren();
5546
+ choices.forEach((choice, index) => {
5547
+ const option = document.createElement("div");
5548
+ option.id = `${this.listId}-${index}`;
5549
+ option.setAttribute("role", "option");
5550
+ option.setAttribute("aria-selected", "false");
5551
+ option.className = "cursor-pointer px-2 py-1.5 hover:bg-muted";
5552
+ option.textContent = choice.label;
5553
+ option.addEventListener("mousedown", (event) => event.preventDefault());
5554
+ option.addEventListener("click", () => this.pick(choice));
5555
+ this.element.appendChild(option);
5556
+ });
5557
+ }
5558
+ open() {
5559
+ if (this.isOpen) return;
5560
+ this.isOpen = true;
5561
+ this.element.hidden = false;
5562
+ this.attach();
5563
+ this.position();
5564
+ this.inputElement.setAttribute("aria-expanded", "true");
5565
+ this.view.requestMeasure();
5566
+ }
5567
+ close() {
5568
+ if (!this.isOpen) return;
5569
+ this.isOpen = false;
5570
+ this.element.hidden = true;
5571
+ this.currentIndex = -1;
5572
+ this.inputElement.setAttribute("aria-expanded", "false");
5573
+ this.inputElement.removeAttribute("aria-activedescendant");
5574
+ this.view.requestMeasure();
5575
+ }
5576
+ destroy() {
5577
+ this.close();
5578
+ }
5579
+ activate(index) {
5580
+ this.currentIndex = index;
5581
+ Array.from(this.element.children).forEach((option2, i) => {
5582
+ option2.setAttribute("aria-selected", String(i === index));
5583
+ option2.classList.toggle("bg-muted", i === index);
5584
+ });
5585
+ const option = this.element.children[index];
5586
+ if (!option) return;
5587
+ this.inputElement.setAttribute("aria-activedescendant", option.id);
5588
+ if (option instanceof HTMLElement) option.scrollIntoView?.({ block: "nearest" });
5589
+ }
5590
+ /** Move the highlighted option; the first/last option wraps around. */
5591
+ moveActive(delta) {
5592
+ if (this.currentChoices.length === 0) return;
5593
+ const next = this.currentIndex < 0 ? delta > 0 ? 0 : this.currentChoices.length - 1 : (this.currentIndex + delta + this.currentChoices.length) % this.currentChoices.length;
5594
+ this.activate(next);
5595
+ }
5596
+ pickActive() {
5597
+ const choice = this.currentChoices[this.currentIndex];
5598
+ if (choice) this.pick(choice);
5599
+ }
5600
+ pick(choice) {
5601
+ this.inputElement.value = choice.value;
5602
+ this.close();
5603
+ this.onPick(choice);
5604
+ }
5605
+ /** Join the DOM under its host row (idempotent). */
5606
+ attach() {
5607
+ if (this.element.parentElement) return;
5608
+ this.host.after(this.element);
5609
+ }
5610
+ /** Anchor the panel to the field inside its row. */
5611
+ position() {
5612
+ const box = computeInlinePanelBox(
5613
+ this.inputElement.getBoundingClientRect(),
5614
+ this.host.getBoundingClientRect(),
5615
+ window.innerHeight
5616
+ );
5617
+ this.element.style.width = `${box.width}px`;
5618
+ this.element.style.marginLeft = `${box.offsetLeft}px`;
5619
+ this.element.style.maxHeight = `${box.maxHeight}px`;
5620
+ }
5621
+ };
5622
+
5623
+ // src/extensions/frontmatter-preview.ts
5487
5624
  var frontmatterSuggestions = state.Facet.define({ combine: (providers) => providers[0] ?? null });
5488
5625
  var frontmatterReferenceIndex = state.Facet.define({ combine: (providers) => providers[0] ?? null });
5489
5626
  var referenceIndexReload = state.StateEffect.define();
@@ -5492,52 +5629,52 @@ var frontmatterVisibility = state.Facet.define({
5492
5629
  });
5493
5630
  var pendingFocus = /* @__PURE__ */ new WeakMap();
5494
5631
  var widgetCleanup = /* @__PURE__ */ new WeakMap();
5495
- var suggestionId = 0;
5632
+ var helperId = 0;
5496
5633
  function isTagProperty(key) {
5497
5634
  return ["tag", "tags", "category"].includes(key.trim().toLowerCase());
5498
5635
  }
5636
+ function appendFieldHelper(parent, text) {
5637
+ const helper = document.createElement("span");
5638
+ helper.id = `frontmatter-hint-${++helperId}`;
5639
+ helper.className = "sr-only";
5640
+ helper.textContent = text;
5641
+ parent.appendChild(helper);
5642
+ return helper;
5643
+ }
5644
+ function createColumnHeader() {
5645
+ const header = document.createElement("div");
5646
+ header.className = "flex items-center border-b border-border text-[11px] font-semibold uppercase tracking-wide text-muted-foreground";
5647
+ const key = document.createElement("div");
5648
+ key.dataset.frontmatterColumn = "key";
5649
+ 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";
5650
+ key.textContent = "Key";
5651
+ const value = document.createElement("div");
5652
+ value.dataset.frontmatterColumn = "value";
5653
+ value.className = "px-3 py-1.5 flex-1 min-w-0";
5654
+ value.textContent = "Value";
5655
+ const actions = document.createElement("div");
5656
+ actions.className = "w-9 shrink-0";
5657
+ header.append(key, value, actions);
5658
+ return header;
5659
+ }
5660
+ function ensureColumnHeader(box, before) {
5661
+ if (box.querySelector("[data-frontmatter-column]")) return;
5662
+ box.insertBefore(createColumnHeader(), before);
5663
+ }
5499
5664
  function attachSuggestions(input, view, root, kind, key, excluded, commit, valueKind = "tags") {
5500
5665
  const provider = view.state.facet(frontmatterSuggestions);
5501
5666
  if (!provider || !input.parentElement) return;
5502
- const parent = input.parentElement;
5503
- parent.classList.add("relative");
5504
- const list = document.createElement("div");
5505
- list.id = `frontmatter-suggestions-${++suggestionId}`;
5506
- list.setAttribute("role", "listbox");
5507
- 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";
5508
- list.hidden = true;
5509
- parent.appendChild(list);
5510
- input.setAttribute("role", "combobox");
5511
- input.setAttribute("aria-autocomplete", "list");
5512
- input.setAttribute("aria-controls", list.id);
5513
- input.setAttribute("aria-expanded", "false");
5667
+ const host = input.closest("[data-frontmatter-row]") ?? input.parentElement;
5668
+ const panel = new SuggestionPanel(input, {
5669
+ label: kind === "key" ? "Suggested properties" : suggestionListLabel(valueKind),
5670
+ onPick: () => commit(),
5671
+ view,
5672
+ host
5673
+ });
5514
5674
  let generation = 0;
5515
- let choices = [];
5516
- let active = -1;
5517
5675
  const close = () => {
5518
5676
  generation++;
5519
- choices = [];
5520
- active = -1;
5521
- list.hidden = true;
5522
- input.setAttribute("aria-expanded", "false");
5523
- input.removeAttribute("aria-activedescendant");
5524
- };
5525
- const select = (choice) => {
5526
- input.value = choice.value;
5527
- close();
5528
- commit();
5529
- };
5530
- const activate = (index) => {
5531
- active = index;
5532
- Array.from(list.children).forEach((option2, i) => {
5533
- option2.setAttribute("aria-selected", String(i === active));
5534
- option2.classList.toggle("bg-muted", i === active);
5535
- });
5536
- const option = list.children[active];
5537
- if (option) {
5538
- input.setAttribute("aria-activedescendant", option.id);
5539
- if (option instanceof HTMLElement) option.scrollIntoView?.({ block: "nearest" });
5540
- }
5677
+ panel.close();
5541
5678
  };
5542
5679
  const refresh = async (showAll = false) => {
5543
5680
  close();
@@ -5560,25 +5697,11 @@ function attachSuggestions(input, view, root, kind, key, excluded, commit, value
5560
5697
  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() }));
5561
5698
  }
5562
5699
  const selected = new Set(excluded.map((label) => label.toLowerCase()));
5563
- choices = candidates.filter(
5700
+ const choices = candidates.filter(
5564
5701
  (candidate) => (query === "" || candidate.haystack.includes(query)) && !selected.has(candidate.value.toLowerCase())
5565
- );
5566
- active = -1;
5567
- input.removeAttribute("aria-activedescendant");
5568
- list.replaceChildren();
5569
- choices.forEach((choice, index) => {
5570
- const option = document.createElement("div");
5571
- option.id = `${list.id}-${index}`;
5572
- option.setAttribute("role", "option");
5573
- option.setAttribute("aria-selected", "false");
5574
- option.className = "cursor-pointer px-2 py-1.5 hover:bg-muted";
5575
- option.textContent = choice.label;
5576
- option.addEventListener("mousedown", (event) => event.preventDefault());
5577
- option.addEventListener("click", () => select(choice));
5578
- list.appendChild(option);
5579
- });
5580
- list.hidden = choices.length === 0;
5581
- input.setAttribute("aria-expanded", String(choices.length > 0));
5702
+ ).map((candidate) => ({ value: candidate.value, label: candidate.label }));
5703
+ panel.setChoices(choices);
5704
+ if (choices.length > 0) panel.open();
5582
5705
  } catch {
5583
5706
  if (request === generation) close();
5584
5707
  }
@@ -5593,16 +5716,22 @@ function attachSuggestions(input, view, root, kind, key, excluded, commit, value
5593
5716
  } else if (event.key === "Escape") {
5594
5717
  event.preventDefault();
5595
5718
  close();
5596
- } else if ((event.key === "ArrowDown" || event.key === "ArrowUp") && choices.length) {
5719
+ } else if (event.key === "ArrowDown" || event.key === "ArrowUp") {
5720
+ if (panel.choices.length === 0) return;
5597
5721
  event.preventDefault();
5598
- const direction = event.key === "ArrowDown" ? 1 : -1;
5599
- activate(active < 0 ? direction === 1 ? 0 : choices.length - 1 : (active + direction + choices.length) % choices.length);
5600
- } else if ((event.key === "Enter" || event.key === "Tab") && active >= 0) {
5722
+ panel.moveActive(event.key === "ArrowDown" ? 1 : -1);
5723
+ } else if (event.key === "Enter" || event.key === "Tab") {
5724
+ if (panel.activeIndex < 0) return;
5601
5725
  event.preventDefault();
5602
- select(choices[active]);
5726
+ panel.pickActive();
5603
5727
  }
5604
5728
  });
5605
- widgetCleanup.get(root)?.push(close);
5729
+ widgetCleanup.get(root)?.push(() => panel.destroy());
5730
+ }
5731
+ function suggestionListLabel(valueKind) {
5732
+ if (valueKind === "effort") return "Suggested efforts";
5733
+ if (valueKind === "equipment") return "Suggested equipment";
5734
+ return "Suggested tags";
5606
5735
  }
5607
5736
  function parseTagList(val) {
5608
5737
  if (Array.isArray(val)) {
@@ -5680,10 +5809,11 @@ function isReferenceKey(key, docKind) {
5680
5809
  }
5681
5810
  function createTagDraftRow(view, root, key, onCommit) {
5682
5811
  const row = document.createElement("div");
5683
- 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";
5812
+ 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";
5684
5813
  row.setAttribute("data-frontmatter-tag-draft", "true");
5814
+ row.dataset.frontmatterRow = key;
5685
5815
  const keyCol = document.createElement("div");
5686
- 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";
5816
+ 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";
5687
5817
  keyCol.appendChild(createTagIcon());
5688
5818
  const keyLabel = document.createElement("span");
5689
5819
  keyLabel.className = "truncate font-medium text-foreground/90";
@@ -5693,9 +5823,15 @@ function createTagDraftRow(view, root, key, onCommit) {
5693
5823
  const valCol = document.createElement("div");
5694
5824
  valCol.className = "flex items-center flex-wrap gap-1.5 px-3 py-1.5 flex-1 min-w-0";
5695
5825
  const input = document.createElement("input");
5696
- 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";
5826
+ 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";
5697
5827
  input.placeholder = "Add tag\u2026";
5698
- input.setAttribute("aria-label", `Add tag to ${key}`);
5828
+ input.setAttribute("aria-label", `Value for ${key}`);
5829
+ input.dataset.frontmatterField = "value";
5830
+ input.dataset.frontmatterProperty = key;
5831
+ input.setAttribute(
5832
+ "aria-describedby",
5833
+ appendFieldHelper(valCol, "Press Enter to add the value.").id
5834
+ );
5699
5835
  valCol.appendChild(input);
5700
5836
  row.appendChild(valCol);
5701
5837
  let settled = false;
@@ -5774,8 +5910,9 @@ var METRIC_DRAFT_KINDS = {
5774
5910
  };
5775
5911
  function createMetricDraftRow(view, root, referenceProvider, commit) {
5776
5912
  const row = document.createElement("div");
5777
- 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";
5913
+ 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";
5778
5914
  row.setAttribute("data-frontmatter-metric-draft", "true");
5915
+ row.dataset.frontmatterRow = "metric";
5779
5916
  const select = document.createElement("select");
5780
5917
  select.setAttribute("aria-label", "Metric kind");
5781
5918
  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";
@@ -5789,9 +5926,14 @@ function createMetricDraftRow(view, root, referenceProvider, commit) {
5789
5926
  const valCol = document.createElement("div");
5790
5927
  valCol.className = "flex items-center flex-wrap gap-1.5 px-3 py-1.5 flex-1 min-w-0";
5791
5928
  const input = document.createElement("input");
5792
- 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";
5929
+ 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";
5793
5930
  input.placeholder = "Value\u2026";
5794
5931
  input.setAttribute("aria-label", "Metric value");
5932
+ input.dataset.frontmatterField = "value";
5933
+ input.setAttribute(
5934
+ "aria-describedby",
5935
+ appendFieldHelper(valCol, "Press Enter to apply the metric value.").id
5936
+ );
5795
5937
  valCol.appendChild(input);
5796
5938
  row.appendChild(valCol);
5797
5939
  let settled = false;
@@ -5983,6 +6125,7 @@ var DefaultFrontmatterWidget = class extends view.WidgetType {
5983
6125
  const docKind = detectDefinitionKind(meta);
5984
6126
  const referenceProvider = view.state.facet(frontmatterReferenceIndex)?.() ?? null;
5985
6127
  const base = docKind === "effort" ? readBaseAttributes(body) : {};
6128
+ box.appendChild(createColumnHeader());
5986
6129
  if (entries.length === 0) {
5987
6130
  const emptyRow = document.createElement("div");
5988
6131
  emptyRow.className = "px-3 py-2 text-xs text-muted-foreground/60 italic";
@@ -5995,10 +6138,12 @@ var DefaultFrontmatterWidget = class extends view.WidgetType {
5995
6138
  const isReferenceList = (isReferenceKey(key, docKind) || key === "aliases") && Array.isArray(value);
5996
6139
  const nested = value === "" && ownsNestedBlock(body, key);
5997
6140
  const row = document.createElement("div");
5998
- 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";
6141
+ 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";
6142
+ row.dataset.frontmatterRow = key;
5999
6143
  box.appendChild(row);
6000
6144
  const keyCol = document.createElement("div");
6001
- 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";
6145
+ 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";
6146
+ row.appendChild(keyCol);
6002
6147
  keyCol.appendChild(isTags || isReferenceList ? createTagIcon() : createListIcon());
6003
6148
  if (this.readOnly || nested) {
6004
6149
  const keyLabel = document.createElement("span");
@@ -6010,7 +6155,16 @@ var DefaultFrontmatterWidget = class extends view.WidgetType {
6010
6155
  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";
6011
6156
  keyInput.value = key;
6012
6157
  keyInput.spellcheck = false;
6013
- keyInput.setAttribute("aria-label", `Property name ${key}`);
6158
+ keyInput.setAttribute("aria-label", `Property key: ${key}`);
6159
+ keyInput.dataset.frontmatterField = "key";
6160
+ keyInput.dataset.frontmatterProperty = key;
6161
+ keyInput.setAttribute(
6162
+ "aria-describedby",
6163
+ appendFieldHelper(
6164
+ keyCol,
6165
+ "Property name. Press Enter to apply. Arrow keys browse suggested property names."
6166
+ ).id
6167
+ );
6014
6168
  let currentKey = key;
6015
6169
  const commitKey = () => {
6016
6170
  const nextKey = keyInput.value.trim();
@@ -6051,9 +6205,9 @@ var DefaultFrontmatterWidget = class extends view.WidgetType {
6051
6205
  pendingFocus.delete(view);
6052
6206
  }
6053
6207
  }
6054
- row.appendChild(keyCol);
6055
6208
  const valCol = document.createElement("div");
6056
6209
  valCol.className = "flex items-center flex-wrap gap-1.5 px-3 py-1.5 flex-1 min-w-0";
6210
+ row.appendChild(valCol);
6057
6211
  const commitList = (next) => {
6058
6212
  meta[key] = next;
6059
6213
  patchPropertyInView(view, this.sectionId, [key], next.length > 0 ? next : "");
@@ -6099,9 +6253,18 @@ var DefaultFrontmatterWidget = class extends view.WidgetType {
6099
6253
  }
6100
6254
  if (!this.readOnly) {
6101
6255
  const chipInput = document.createElement("input");
6102
- 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";
6256
+ 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";
6103
6257
  chipInput.placeholder = chips.length === 0 ? isReferenceList ? `Add ${valueKind === "effort" ? "effort" : "equipment"}\u2026` : "Add tags\u2026" : isTags ? "Add tag\u2026" : "Add\u2026";
6104
- chipInput.setAttribute("aria-label", isTags ? `Add tag to ${key}` : `Add to ${key}`);
6258
+ chipInput.setAttribute("aria-label", `Value for ${key}`);
6259
+ chipInput.dataset.frontmatterField = "value";
6260
+ chipInput.dataset.frontmatterProperty = key;
6261
+ chipInput.setAttribute(
6262
+ "aria-describedby",
6263
+ appendFieldHelper(
6264
+ valCol,
6265
+ "Press Enter or comma to add a value. Arrow keys browse the suggestions."
6266
+ ).id
6267
+ );
6105
6268
  const commitNewChip = () => {
6106
6269
  const val = chipInput.value.trim().replace(/^,|,$/g, "");
6107
6270
  if (val && !chips.some((chip) => chip.toLowerCase() === val.toLowerCase())) {
@@ -6174,10 +6337,16 @@ var DefaultFrontmatterWidget = class extends view.WidgetType {
6174
6337
  valCol.appendChild(valSpan);
6175
6338
  } else {
6176
6339
  const valInput = document.createElement("input");
6177
- 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";
6340
+ 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";
6178
6341
  valInput.value = strVal;
6179
6342
  valInput.spellcheck = false;
6180
6343
  valInput.setAttribute("aria-label", `Value for ${key}`);
6344
+ valInput.dataset.frontmatterField = "value";
6345
+ valInput.dataset.frontmatterProperty = key;
6346
+ valInput.setAttribute(
6347
+ "aria-describedby",
6348
+ appendFieldHelper(valCol, "Property value. Press Enter to apply.").id
6349
+ );
6181
6350
  let committedVal = strVal;
6182
6351
  const commitVal = () => {
6183
6352
  const cur = valInput.value.trim();
@@ -6228,7 +6397,7 @@ var DefaultFrontmatterWidget = class extends view.WidgetType {
6228
6397
  openLink.appendChild(createExternalIcon());
6229
6398
  pill.appendChild(openLink);
6230
6399
  valCol.insertBefore(pill, valInput);
6231
- 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";
6400
+ 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";
6232
6401
  }
6233
6402
  const diag = renderEffortValueDiagnostics(
6234
6403
  referenceProvider,
@@ -6253,14 +6422,13 @@ var DefaultFrontmatterWidget = class extends view.WidgetType {
6253
6422
  valCol.appendChild(openLink);
6254
6423
  }
6255
6424
  }
6256
- row.appendChild(valCol);
6257
6425
  if (!this.readOnly && !nested) {
6258
6426
  const actionsCol = document.createElement("div");
6259
6427
  actionsCol.className = "flex items-center pr-2";
6260
6428
  const delBtn = document.createElement("button");
6261
6429
  delBtn.type = "button";
6262
6430
  delBtn.setAttribute("aria-label", `Remove property ${key}`);
6263
- delBtn.className = "opacity-0 group-hover:opacity-100 text-muted-foreground/40 hover:text-destructive p-1 rounded transition-opacity cursor-pointer";
6431
+ 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";
6264
6432
  delBtn.appendChild(createCloseIcon("md"));
6265
6433
  delBtn.addEventListener("click", (e) => {
6266
6434
  e.preventDefault();
@@ -6340,7 +6508,9 @@ var DefaultFrontmatterWidget = class extends view.WidgetType {
6340
6508
  e.preventDefault();
6341
6509
  e.stopPropagation();
6342
6510
  if (existingTagKey) {
6343
- const input = Array.from(root.querySelectorAll("input")).find((element) => element.getAttribute("aria-label") === `Add tag to ${existingTagKey}`);
6511
+ const input = Array.from(root.querySelectorAll(
6512
+ '[data-frontmatter-field="value"]'
6513
+ )).find((element) => element.dataset.frontmatterProperty === existingTagKey);
6344
6514
  input?.focus();
6345
6515
  return;
6346
6516
  }
@@ -6516,6 +6686,7 @@ var EmptyFrontmatterWidget = class extends view.WidgetType {
6516
6686
  patchPropertyInView(view, "new", ["tags"], [val]);
6517
6687
  });
6518
6688
  root.appendChild(draftRow);
6689
+ ensureColumnHeader(root, draftRow);
6519
6690
  draftRow.querySelector("input")?.focus();
6520
6691
  view.requestMeasure();
6521
6692
  });
@@ -13358,13 +13529,13 @@ function editorPreset(optionsOrDialect = "markdown") {
13358
13529
  }
13359
13530
 
13360
13531
  // src/version.ts
13361
- var VERSION = "0.44.2155";
13362
- var GIT_SHA = "6807397";
13363
- var BUILD_TIME = "2026-10-24T03:58:47.392Z";
13532
+ var VERSION = "0.44.2157";
13533
+ var GIT_SHA = "2b87791";
13534
+ var BUILD_TIME = "2026-10-24T21:02:55.494Z";
13364
13535
  var SEMVER = {
13365
- version: "0.44.2155",
13366
- gitSha: "6807397",
13367
- buildTime: "2026-10-24T03:58:47.392Z"
13536
+ version: "0.44.2157",
13537
+ gitSha: "2b87791",
13538
+ buildTime: "2026-10-24T21:02:55.494Z"
13368
13539
  };
13369
13540
 
13370
13541
  Object.defineProperty(exports, "CONTENT_GROUPING_DIMENSIONS", {