@inkandswitch/patchwork-pkg-base 0.0.128 → 0.0.130

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.
Files changed (51) hide show
  1. package/module-settings-url +1 -1
  2. package/package.json +1 -1
  3. package/packages/account/dist/{AccountPicker-TCOUU4YK.js → AccountPicker-SBCGXHRS.js} +13 -44
  4. package/packages/account/dist/AccountPicker-SBCGXHRS.js.map +7 -0
  5. package/packages/account/dist/{ContactAvatar-MKDWQC6G.js → ContactAvatar-IVYTJ7M4.js} +5 -2
  6. package/packages/account/dist/ContactAvatar-IVYTJ7M4.js.map +7 -0
  7. package/packages/account/dist/{ContactCursor-4FYCATG5.js → ContactCursor-2FVKF5QA.js} +5 -2
  8. package/packages/account/dist/ContactCursor-2FVKF5QA.js.map +7 -0
  9. package/packages/account/dist/chunk-L6JWPAD3.js +52 -0
  10. package/packages/account/dist/chunk-L6JWPAD3.js.map +7 -0
  11. package/packages/account/dist/index.js +3 -3
  12. package/packages/codemirror-base/dist/{chunk-A2WBDY3J.js → chunk-REXVGJ53.js} +27 -2
  13. package/packages/codemirror-base/dist/{chunk-A2WBDY3J.js.map → chunk-REXVGJ53.js.map} +2 -2
  14. package/packages/codemirror-base/dist/lib/codemirror.js +1 -1
  15. package/packages/codemirror-base/dist/tool.js +30 -5
  16. package/packages/codemirror-base/dist/tool.js.map +2 -2
  17. package/packages/codemirror-markdown/dist/extensions/embed.js +11 -6
  18. package/packages/codemirror-markdown/dist/extensions/embed.js.map +2 -2
  19. package/packages/codemirror-markdown/dist/extensions/markdown.js +302 -43
  20. package/packages/codemirror-markdown/dist/extensions/markdown.js.map +3 -3
  21. package/packages/theming/dist/{active-theme-6H5UANUR.js → active-theme-WA6XMDTP.js} +2 -2
  22. package/packages/theming/dist/{chunk-HHCCYVOT.js → chunk-4GOF67HA.js} +2 -2
  23. package/packages/theming/dist/{chunk-VJZ4NPK4.js → chunk-T7VWPJQG.js} +26 -1
  24. package/packages/theming/dist/chunk-T7VWPJQG.js.map +7 -0
  25. package/packages/theming/dist/main.js +4 -4
  26. package/packages/theming/dist/{theme-HE7ECLIW.css → theme-HV4IDVYM.css} +44 -0
  27. package/packages/theming/dist/{theme-editor-datatype-TJ6LYT2U.js → theme-editor-datatype-DZFQK7HV.js} +2 -2
  28. package/packages/theming/dist/theme-editor.js +1 -1
  29. package/packages/theming/dist/{theme-titlebar-UX4BND5Z.js → theme-titlebar-LG6PFBKR.js} +2 -2
  30. package/packages/theming/dist/{theme-tray-B477G2WR.js → theme-tray-R3PJDYCL.js} +2 -2
  31. package/packages/theming/dist/tool.js +1 -1
  32. package/packages/threepane/dist/IsolatedDocumentArea-JJMLEL4O.js +2 -0
  33. package/packages/threepane/dist/{PatchworkFrame-22ABHJVG.js → PatchworkFrame-HMA5KZLY.js} +2 -2
  34. package/packages/threepane/dist/chunk-UOTRB26X.js +846 -0
  35. package/packages/threepane/dist/chunk-UOTRB26X.js.map +7 -0
  36. package/packages/threepane/dist/index.js +1 -1
  37. package/plugin-registry-url +1 -1
  38. package/packages/account/dist/AccountPicker-TCOUU4YK.js.map +0 -7
  39. package/packages/account/dist/ContactAvatar-MKDWQC6G.js.map +0 -7
  40. package/packages/account/dist/ContactCursor-4FYCATG5.js.map +0 -7
  41. package/packages/theming/dist/chunk-VJZ4NPK4.js.map +0 -7
  42. package/packages/threepane/dist/IsolatedDocumentArea-3HGASUGM.js +0 -2
  43. package/packages/threepane/dist/chunk-34WWZW2V.js +0 -1215
  44. package/packages/threepane/dist/chunk-34WWZW2V.js.map +0 -7
  45. /package/packages/theming/dist/{active-theme-6H5UANUR.js.map → active-theme-WA6XMDTP.js.map} +0 -0
  46. /package/packages/theming/dist/{chunk-HHCCYVOT.js.map → chunk-4GOF67HA.js.map} +0 -0
  47. /package/packages/theming/dist/{theme-editor-datatype-TJ6LYT2U.js.map → theme-editor-datatype-DZFQK7HV.js.map} +0 -0
  48. /package/packages/theming/dist/{theme-titlebar-UX4BND5Z.js.map → theme-titlebar-LG6PFBKR.js.map} +0 -0
  49. /package/packages/theming/dist/{theme-tray-B477G2WR.js.map → theme-tray-R3PJDYCL.js.map} +0 -0
  50. /package/packages/threepane/dist/{IsolatedDocumentArea-3HGASUGM.js.map → IsolatedDocumentArea-JJMLEL4O.js.map} +0 -0
  51. /package/packages/threepane/dist/{PatchworkFrame-22ABHJVG.js.map → PatchworkFrame-HMA5KZLY.js.map} +0 -0
@@ -2167,6 +2167,7 @@ var TaskWidget = class extends WidgetType {
2167
2167
  box.disabled = !view.state.facet(EditorView2.editable);
2168
2168
  box.setAttribute("aria-label", this.checked ? "Done" : "To do");
2169
2169
  box.addEventListener("mousedown", (event) => {
2170
+ if (event.button !== 0) return;
2170
2171
  event.preventDefault();
2171
2172
  if (box.disabled) return;
2172
2173
  toggle(view, view.posAtDOM(box));
@@ -2235,18 +2236,23 @@ import {
2235
2236
  WidgetType as WidgetType2
2236
2237
  } from "@codemirror/view";
2237
2238
  var hidden = Decoration3.replace({});
2238
- var taskMark = Decoration3.mark({ class: "cm-md-hang", inclusive: true });
2239
+ var taskMark = Decoration3.mark({
2240
+ class: "cm-md-hang cm-md-list-marker",
2241
+ inclusive: true
2242
+ });
2239
2243
  var HeadingLabel = class extends WidgetType2 {
2240
- constructor(level) {
2244
+ /** `shown` only on the caret's line; elsewhere it keeps its room, unseen. */
2245
+ constructor(level, shown) {
2241
2246
  super();
2242
2247
  this.level = level;
2248
+ this.shown = shown;
2243
2249
  }
2244
2250
  eq(other) {
2245
- return other.level === this.level;
2251
+ return other.level === this.level && other.shown === this.shown;
2246
2252
  }
2247
2253
  toDOM() {
2248
2254
  const span = document.createElement("span");
2249
- span.className = "cm-md-hang cm-md-heading-label";
2255
+ span.className = `cm-md-hang cm-md-heading-label${this.shown ? "" : " cm-md-heading-label-idle"}`;
2250
2256
  span.setAttribute("aria-hidden", "true");
2251
2257
  const n = document.createElement("span");
2252
2258
  n.className = "cm-md-heading-level";
@@ -2261,7 +2267,7 @@ var Bullet = class extends WidgetType2 {
2261
2267
  }
2262
2268
  toDOM() {
2263
2269
  const span = document.createElement("span");
2264
- span.className = "cm-md-hang";
2270
+ span.className = "cm-md-hang cm-md-list-marker";
2265
2271
  const dot = document.createElement("span");
2266
2272
  dot.className = "cm-bullet";
2267
2273
  span.append(dot);
@@ -2278,7 +2284,7 @@ var NumberLabel = class extends WidgetType2 {
2278
2284
  }
2279
2285
  toDOM() {
2280
2286
  const span = document.createElement("span");
2281
- span.className = "cm-md-hang cm-md-hang-number";
2287
+ span.className = "cm-md-hang cm-md-list-marker cm-md-hang-number";
2282
2288
  span.textContent = this.text;
2283
2289
  return span;
2284
2290
  }
@@ -2342,6 +2348,85 @@ function alpha(n) {
2342
2348
  }
2343
2349
  return out;
2344
2350
  }
2351
+ var codeLine = Decoration3.line({ class: "cm-md-code" });
2352
+ var calloutMarker = Decoration3.mark({ class: "cm-md-callout-marker" });
2353
+ function caretLines(state) {
2354
+ const lines = /* @__PURE__ */ new Set();
2355
+ for (const r of state.selection.ranges) {
2356
+ const last = state.doc.lineAt(r.to).number;
2357
+ for (let n = state.doc.lineAt(r.from).number; n <= last; n++) lines.add(n);
2358
+ }
2359
+ return lines;
2360
+ }
2361
+ var CALLOUTS = {
2362
+ note: "Note",
2363
+ tip: "Tip",
2364
+ important: "Important",
2365
+ warning: "Warning",
2366
+ caution: "Caution"
2367
+ };
2368
+ function calloutAt(line) {
2369
+ const m = /^((?:\s*>\s?)+)\[!(\w+)\][ \t]*(.*)$/.exec(line.text);
2370
+ if (!m) return null;
2371
+ const type = m[2].toLowerCase();
2372
+ if (!(type in CALLOUTS)) return null;
2373
+ const from = line.from + m[1].length;
2374
+ return {
2375
+ type,
2376
+ from,
2377
+ to: line.from + line.text.length - m[3].length,
2378
+ titled: m[3].trim() !== ""
2379
+ };
2380
+ }
2381
+ var ICONS = {
2382
+ note: '<circle cx="8" cy="8" r="6.25"/><path d="M8 7.25v4M8 4.75v.01"/>',
2383
+ tip: '<path d="M5.75 11.5h4.5M6.5 14h3M8 1.75a4.25 4.25 0 0 0-2.5 7.7c.5.4.75.9.75 1.55V11.5h3.5V11c0-.65.25-1.15.75-1.55A4.25 4.25 0 0 0 8 1.75z"/>',
2384
+ important: '<path d="M2.25 3.25a1.5 1.5 0 0 1 1.5-1.5h8.5a1.5 1.5 0 0 1 1.5 1.5v6.5a1.5 1.5 0 0 1-1.5 1.5H7l-3 2.5v-2.5h-.25a1.5 1.5 0 0 1-1.5-1.5z"/><path d="M8 4.5v3M8 9.5v.01"/>',
2385
+ warning: '<path d="M7.13 2.25a1 1 0 0 1 1.74 0l5.6 9.75a1 1 0 0 1-.87 1.5H2.4a1 1 0 0 1-.87-1.5z"/><path d="M8 6v3M8 11v.01"/>',
2386
+ caution: '<path d="M5.5 1.75h5l3.75 3.75v5l-3.75 3.75h-5L1.75 10.5v-5z"/><path d="M8 5v3.5M8 10.75v.01"/>'
2387
+ };
2388
+ var CalloutTitle = class extends WidgetType2 {
2389
+ constructor(type, label) {
2390
+ super();
2391
+ this.type = type;
2392
+ this.label = label;
2393
+ }
2394
+ eq(other) {
2395
+ return other.type === this.type && other.label === this.label;
2396
+ }
2397
+ toDOM() {
2398
+ const span = document.createElement("span");
2399
+ span.className = "cm-md-callout-title";
2400
+ span.innerHTML = `<svg viewBox="0 0 16 16" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">${ICONS[this.type]}</svg>`;
2401
+ if (this.label) span.append(CALLOUTS[this.type]);
2402
+ else span.setAttribute("aria-label", CALLOUTS[this.type]);
2403
+ return span;
2404
+ }
2405
+ };
2406
+ function listLines(state, from, to, decos) {
2407
+ const { doc: doc2 } = state;
2408
+ const tree = syntaxTree2(state);
2409
+ const last = doc2.lineAt(to).number;
2410
+ for (let n = doc2.lineAt(from).number; n <= last; n++) {
2411
+ const line = doc2.line(n);
2412
+ const indent = /^[ \t]*/.exec(line.text)[0].length;
2413
+ if (indent === line.length) continue;
2414
+ let depth = 0;
2415
+ let code = false;
2416
+ for (let node = tree.resolveInner(line.from + indent, 1); node; node = node.parent) {
2417
+ if (node.name === "ListItem") depth++;
2418
+ if (node.name === "FencedCode" || node.name === "CodeBlock") code = true;
2419
+ }
2420
+ if (!depth) continue;
2421
+ decos.push(
2422
+ Decoration3.line({
2423
+ class: "cm-md-list-line",
2424
+ attributes: { style: `--md-list-depth: ${depth}` }
2425
+ }).range(line.from)
2426
+ );
2427
+ if (indent && !code) decos.push(hidden.range(line.from, line.from + indent));
2428
+ }
2429
+ }
2345
2430
  function skipSpaces(state, pos) {
2346
2431
  const line = state.doc.lineAt(pos);
2347
2432
  while (pos < line.to && state.doc.sliceString(pos, pos + 1) === " ") pos++;
@@ -2350,6 +2435,7 @@ function skipSpaces(state, pos) {
2350
2435
  function build2(view) {
2351
2436
  const { state } = view;
2352
2437
  const { doc: doc2 } = state;
2438
+ const editing = caretLines(state);
2353
2439
  const decos = [];
2354
2440
  for (const { from, to } of view.visibleRanges) {
2355
2441
  syntaxTree2(state).iterate({
@@ -2361,10 +2447,14 @@ function build2(view) {
2361
2447
  if (heading) {
2362
2448
  const mark = node.node.firstChild;
2363
2449
  if (!mark || mark.name !== "HeaderMark") return;
2450
+ const line = doc2.lineAt(node.from);
2364
2451
  decos.push(
2365
2452
  Decoration3.replace({
2366
- widget: new HeadingLabel(Number(heading[1]))
2367
- }).range(doc2.lineAt(node.from).from, skipSpaces(state, mark.to))
2453
+ widget: new HeadingLabel(Number(heading[1]), editing.has(line.number))
2454
+ }).range(line.from, skipSpaces(state, mark.to)),
2455
+ // the heading's size on the whole line, for what the highlighter
2456
+ // doesn't wrap (a rendered link): see headingLines in the theme.
2457
+ Decoration3.line({ class: `cm-md-h${heading[1]}` }).range(line.from)
2368
2458
  );
2369
2459
  return;
2370
2460
  }
@@ -2394,20 +2484,43 @@ function build2(view) {
2394
2484
  }
2395
2485
  return;
2396
2486
  }
2487
+ if ((name === "BulletList" || name === "OrderedList") && node.node.parent?.name !== "ListItem") {
2488
+ listLines(state, node.from, node.to, decos);
2489
+ return;
2490
+ }
2491
+ if (name === "FencedCode" || name === "CodeBlock") {
2492
+ const first = doc2.lineAt(node.from).number;
2493
+ const last = doc2.lineAt(node.to).number;
2494
+ for (let n = first; n <= last; n++)
2495
+ decos.push(codeLine.range(doc2.line(n).from));
2496
+ return false;
2497
+ }
2397
2498
  if (name === "Blockquote") {
2398
2499
  for (let p = node.node.parent; p; p = p.parent)
2399
2500
  if (p.name === "Blockquote") return;
2400
2501
  const first = doc2.lineAt(node.from).number;
2401
2502
  const last = doc2.lineAt(node.to).number;
2503
+ const callout = calloutAt(doc2.line(first));
2402
2504
  for (let n = first; n <= last; n++) {
2403
2505
  const line = doc2.line(n);
2404
2506
  const classes = ["cm-md-quote"];
2405
2507
  if (n === first) classes.push("cm-md-quote-first");
2406
2508
  if (n === last) classes.push("cm-md-quote-last");
2509
+ if (callout) {
2510
+ classes.push("cm-md-callout", `cm-md-callout-${callout.type}`);
2511
+ if (n === first) classes.push("cm-md-callout-title-line");
2512
+ }
2407
2513
  decos.push(
2408
2514
  Decoration3.line({ class: classes.join(" ") }).range(line.from)
2409
2515
  );
2410
2516
  }
2517
+ if (callout) {
2518
+ decos.push(
2519
+ editing.has(first) ? calloutMarker.range(callout.from, callout.to) : Decoration3.replace({
2520
+ widget: new CalloutTitle(callout.type, !callout.titled)
2521
+ }).range(callout.from, callout.to)
2522
+ );
2523
+ }
2411
2524
  return;
2412
2525
  }
2413
2526
  if (name === "QuoteMark") {
@@ -2435,7 +2548,7 @@ var marginPlugin = ViewPlugin3.fromClass(
2435
2548
  this.decorations = build2(view);
2436
2549
  }
2437
2550
  update(update) {
2438
- if (update.docChanged || update.viewportChanged || syntaxTree2(update.startState) !== syntaxTree2(update.state)) {
2551
+ if (update.docChanged || update.selectionSet || update.viewportChanged || syntaxTree2(update.startState) !== syntaxTree2(update.state)) {
2439
2552
  this.decorations = build2(update.view);
2440
2553
  }
2441
2554
  }
@@ -2445,7 +2558,9 @@ var marginPlugin = ViewPlugin3.fromClass(
2445
2558
  var zoomed = (length) => `calc(${length} * var(--markdown-zoom, 1))`;
2446
2559
  var marginTheme = EditorView3.baseTheme({
2447
2560
  ".cm-content": {
2448
- "--markdown-hang": zoomed("2.5rem")
2561
+ "--markdown-hang": zoomed("2.5rem"),
2562
+ "--markdown-list-indent": zoomed("1.6rem"),
2563
+ "--markdown-quote-indent": zoomed("1.1rem")
2449
2564
  },
2450
2565
  ".cm-md-hang": {
2451
2566
  display: "inline-flex",
@@ -2478,31 +2593,137 @@ var marginTheme = EditorView3.baseTheme({
2478
2593
  fontFamily: "var(--markdown-body-family, inherit)",
2479
2594
  letterSpacing: "0.02em"
2480
2595
  },
2596
+ ".cm-md-heading-label-idle": {
2597
+ visibility: "hidden"
2598
+ },
2599
+ // a list line: padded one indent per level (CodeMirror's own 6px first)
2600
+ ".cm-md-list-line": {
2601
+ paddingLeft: "calc(6px + var(--md-list-depth, 1) * var(--markdown-list-indent))"
2602
+ },
2603
+ // its marker, in that padding: from the start of the indent, not hung right
2604
+ ".cm-md-list-marker": {
2605
+ width: "var(--markdown-list-indent)",
2606
+ marginLeft: "calc(-1 * var(--markdown-list-indent))",
2607
+ justifyContent: "flex-start",
2608
+ paddingRight: "0"
2609
+ },
2481
2610
  ".cm-md-heading-level": {
2482
2611
  fontSize: "0.75em",
2483
2612
  verticalAlign: "-0.15em"
2484
2613
  },
2485
2614
  ".cm-md-hang .cm-bullet": {
2486
2615
  display: "inline-block",
2487
- width: "0.4em",
2488
- height: "0.4em",
2616
+ width: "0.5em",
2617
+ height: "0.5em",
2618
+ // in the box's left, centred under where a number's first digit sits
2619
+ marginLeft: "0.15em",
2489
2620
  borderRadius: "50%",
2490
- background: "var(--syntax-list-marker, currentColor)",
2491
- color: "var(--text-editor-line)",
2621
+ // theming's list marker colour (the primary accent, as ink)
2622
+ background: "var(--syntax-list-marker, var(--text-editor-primary-text, currentColor))",
2492
2623
  alignSelf: "center"
2493
2624
  },
2494
2625
  ".cm-md-hang .cm-task": {
2495
2626
  margin: "0"
2496
2627
  },
2628
+ // a quote: its bar on the body's column, its text one quote indent in
2497
2629
  ".cm-md-quote": {
2498
- position: "relative"
2630
+ position: "relative",
2631
+ paddingLeft: "calc(6px + var(--markdown-quote-indent))"
2632
+ },
2633
+ ".cm-md-code": {
2634
+ fontFamily: "var(--text-editor-family-code)"
2635
+ },
2636
+ // GitHub-style callouts. Colours from theming's --studio-callout-* (the
2637
+ // accent: bar) and --text-editor-callout-*-text/-fill (title ink, box
2638
+ // tint), with fallbacks for running without the theme.
2639
+ ...Object.fromEntries(
2640
+ Object.keys(CALLOUTS).map((type) => {
2641
+ const fallback = { note: "#36e", tip: "#1a7f37", important: "#8250df", warning: "#d4a72c", caution: "#d1242f" }[type];
2642
+ return [
2643
+ `.cm-md-callout-${type}`,
2644
+ {
2645
+ "--md-callout": `var(--studio-callout-${type}, ${fallback})`,
2646
+ "--md-callout-text": `var(--text-editor-callout-${type}-text, color-mix(in oklch, var(--md-callout), currentColor 35%))`,
2647
+ "--md-callout-fill": `var(--text-editor-callout-${type}-fill, color-mix(in oklch, var(--md-callout) 9%, transparent))`
2648
+ }
2649
+ ];
2650
+ })
2651
+ ),
2652
+ ".cm-md-callout": {
2653
+ // the body reads as body text, not as a quote: the theme's quote styling
2654
+ // (italic, the punctuation grey) comes through these variables.
2655
+ "--syntax-quote": "var(--text-editor-line)",
2656
+ "--syntax-style-quote": "normal",
2657
+ "--syntax-weight-quote": "normal",
2658
+ "--syntax-fill-quote": "transparent",
2659
+ // a stacking context, so the tint drawn behind the text (z-index -1)
2660
+ // stays above the editor's own background.
2661
+ isolation: "isolate",
2662
+ paddingRight: zoomed("0.75rem")
2663
+ },
2664
+ // (doubled up to outrank the plain quote bar's rule further down)
2665
+ ".cm-md-quote.cm-md-callout::before": {
2666
+ background: "var(--md-callout)",
2667
+ opacity: "1"
2668
+ },
2669
+ ".cm-md-callout::after": {
2670
+ content: '""',
2671
+ position: "absolute",
2672
+ zIndex: "-1",
2673
+ left: "6px",
2674
+ right: "0",
2675
+ top: "0",
2676
+ bottom: "0",
2677
+ background: "var(--md-callout-fill)"
2678
+ },
2679
+ ".cm-md-callout.cm-md-quote-first": {
2680
+ paddingTop: zoomed("0.5rem")
2681
+ },
2682
+ ".cm-md-callout.cm-md-quote-last": {
2683
+ paddingBottom: zoomed("0.5rem")
2684
+ },
2685
+ ".cm-md-callout.cm-md-quote-first::before, .cm-md-callout.cm-md-quote-first::after": {
2686
+ top: "0",
2687
+ borderTopRightRadius: "6px"
2688
+ },
2689
+ ".cm-md-callout.cm-md-quote-last::before, .cm-md-callout.cm-md-quote-last::after": {
2690
+ bottom: "0",
2691
+ borderBottomRightRadius: "6px"
2692
+ },
2693
+ ".cm-md-callout.cm-md-quote-first::before": { borderTopRightRadius: "0" },
2694
+ ".cm-md-callout.cm-md-quote-last::before": { borderBottomRightRadius: "0" },
2695
+ ".cm-md-callout-title-line": {
2696
+ color: "var(--md-callout-text)",
2697
+ fontWeight: "600"
2698
+ },
2699
+ ".cm-md-callout-title": {
2700
+ display: "inline-flex",
2701
+ alignItems: "center",
2702
+ gap: "0.4em",
2703
+ color: "var(--md-callout-text)",
2704
+ fontWeight: "600",
2705
+ marginRight: "0.4em"
2706
+ },
2707
+ ".cm-md-callout-title svg": {
2708
+ width: "1em",
2709
+ height: "1em",
2710
+ flex: "none"
2711
+ },
2712
+ // the raw `[!NOTE]`, on the caret's line. it parses as a reference link,
2713
+ // so the highlighter's link colour and underline are undone inside it.
2714
+ ".cm-md-callout-marker, .cm-md-callout-marker *": {
2715
+ color: "var(--md-callout-text)",
2716
+ textDecoration: "none"
2717
+ },
2718
+ ".cm-md-callout-marker": {
2719
+ fontFamily: "var(--text-editor-family-code)",
2720
+ fontSize: "0.9em"
2499
2721
  },
2500
2722
  ".cm-md-quote::before": {
2501
2723
  content: '""',
2502
2724
  position: "absolute",
2503
- // on the bullets' column: centred on where a hung dot sits (the hang's
2504
- // right padding, then half a dot at the hang's 0.8rem).
2505
- left: `calc(-1 * (${zoomed("0.6rem")} + ${zoomed("0.16rem")}) - 1.5px)`,
2725
+ // on the body's column (past CodeMirror's own 6px line padding)
2726
+ left: "6px",
2506
2727
  top: "0",
2507
2728
  bottom: "0",
2508
2729
  width: "3px",
@@ -2690,9 +2911,6 @@ function renumber(state, list) {
2690
2911
  });
2691
2912
  return changes;
2692
2913
  }
2693
- function needsRenumber(state, list) {
2694
- return list.name === "OrderedList" && renumber(state, list).length > 0;
2695
- }
2696
2914
  function clearDone(state, list) {
2697
2915
  const all = items(list);
2698
2916
  const gone = new Set(all.flatMap((it, i) => done(state, it) ? [i] : []));
@@ -2825,16 +3043,28 @@ function menuItems(view, pos) {
2825
3043
  if (!list) return [];
2826
3044
  const apply = (changes, userEvent) => () => view.dispatch({ changes, userEvent });
2827
3045
  const out = [];
2828
- if (needsRenumber(state, list)) {
2829
- out.push({ label: "Fix numbering", run: apply(renumber(state, list), "input.renumber") });
3046
+ if (list.name === "OrderedList") {
3047
+ const changes = renumber(state, list);
3048
+ out.push({
3049
+ label: "Fix numbering",
3050
+ run: apply(changes, "input.renumber"),
3051
+ disabled: !changes.length
3052
+ });
2830
3053
  }
2831
3054
  const hasTasks = items(list).some((it) => done(state, it) !== null);
2832
3055
  if (hasTasks) {
2833
3056
  const n = countDone(state, list);
2834
- if (moveDoneDown(state, list).length)
2835
- out.push({ label: "Move done to bottom", run: apply(moveDoneDown(state, list), "input.move") });
2836
- if (n)
2837
- out.push({ label: `Clear done (${n})`, run: apply(clearDone(state, list), "delete.clear-done") });
3057
+ const moves = moveDoneDown(state, list);
3058
+ out.push({
3059
+ label: "Move done to bottom",
3060
+ run: apply(moves, "input.move"),
3061
+ disabled: !moves.length
3062
+ });
3063
+ out.push({
3064
+ label: n ? `Clear done (${n})` : "Clear done",
3065
+ run: apply(clearDone(state, list), "delete.clear-done"),
3066
+ disabled: !n
3067
+ });
2838
3068
  const hiding = isHidingDone(state);
2839
3069
  out.push({
2840
3070
  label: hiding ? "Show done" : "Hide done",
@@ -2849,12 +3079,13 @@ function openMenu(view, x, y, entries) {
2849
3079
  menu.setAttribute("role", "menu");
2850
3080
  menu.style.left = `${x}px`;
2851
3081
  menu.style.top = `${y}px`;
2852
- const buttons = entries.map(({ label, run }) => {
3082
+ const buttons = entries.map(({ label, run, disabled }) => {
2853
3083
  const b = document.createElement("button");
2854
3084
  b.type = "button";
2855
3085
  b.className = "cm-md-menu-item";
2856
3086
  b.setAttribute("role", "menuitem");
2857
3087
  b.textContent = label;
3088
+ b.disabled = !!disabled;
2858
3089
  b.addEventListener("click", () => {
2859
3090
  close();
2860
3091
  run();
@@ -2875,10 +3106,13 @@ function openMenu(view, x, y, entries) {
2875
3106
  } else if (e.key === "ArrowDown" || e.key === "ArrowUp") {
2876
3107
  e.preventDefault();
2877
3108
  const step2 = e.key === "ArrowDown" ? 1 : -1;
2878
- buttons[(i + step2 + buttons.length) % buttons.length]?.focus();
3109
+ const live = buttons.filter((b) => !b.disabled);
3110
+ const at = live.indexOf(buttons[i]);
3111
+ live[(at + step2 + live.length) % live.length]?.focus();
2879
3112
  }
2880
3113
  };
2881
3114
  function close() {
3115
+ if (menu.matches?.(":popover-open")) menu.hidePopover();
2882
3116
  menu.remove();
2883
3117
  window.removeEventListener("pointerdown", outside, true);
2884
3118
  window.removeEventListener("scroll", close, true);
@@ -2890,10 +3124,20 @@ function openMenu(view, x, y, entries) {
2890
3124
  window.addEventListener("blur", close);
2891
3125
  menu.addEventListener("keydown", keys);
2892
3126
  view.dom.appendChild(menu);
2893
- const r = menu.getBoundingClientRect();
2894
- if (r.right > window.innerWidth) menu.style.left = `${Math.max(0, x - r.width)}px`;
2895
- if (r.bottom > window.innerHeight) menu.style.top = `${Math.max(0, y - r.height)}px`;
2896
- buttons[0]?.focus();
3127
+ if (typeof menu.showPopover === "function") {
3128
+ menu.popover = "manual";
3129
+ menu.showPopover();
3130
+ }
3131
+ let r = menu.getBoundingClientRect();
3132
+ if (r.left !== x || r.top !== y) {
3133
+ menu.style.left = `${x + (x - r.left)}px`;
3134
+ menu.style.top = `${y + (y - r.top)}px`;
3135
+ r = menu.getBoundingClientRect();
3136
+ }
3137
+ const shift = (prop, by) => menu.style[prop] = `${parseFloat(menu.style[prop]) - by}px`;
3138
+ if (r.right > window.innerWidth) shift("left", r.width);
3139
+ if (r.bottom > window.innerHeight) shift("top", r.height);
3140
+ buttons.find((b) => !b.disabled)?.focus();
2897
3141
  return close;
2898
3142
  }
2899
3143
  var menuPlugin = ViewPlugin4.fromClass(
@@ -2923,6 +3167,9 @@ var menuPlugin = ViewPlugin4.fromClass(
2923
3167
  var listsTheme = EditorView4.baseTheme({
2924
3168
  ".cm-md-menu": {
2925
3169
  position: "fixed",
3170
+ // undo the popover defaults (centred, inset 0)
3171
+ inset: "auto",
3172
+ margin: "0",
2926
3173
  zIndex: "var(--studio-layer-popover, 4000)",
2927
3174
  display: "flex",
2928
3175
  flexDirection: "column",
@@ -2942,7 +3189,10 @@ var listsTheme = EditorView4.baseTheme({
2942
3189
  borderRadius: "4px",
2943
3190
  cursor: "var(--studio-cursor-default, default)"
2944
3191
  },
2945
- ".cm-md-menu-item:hover, .cm-md-menu-item:focus-visible": {
3192
+ ".cm-md-menu-item:disabled": {
3193
+ opacity: "0.45"
3194
+ },
3195
+ ".cm-md-menu-item:not(:disabled):hover, .cm-md-menu-item:focus-visible": {
2946
3196
  background: "var(--studio-fill-offset-20, #eee)"
2947
3197
  },
2948
3198
  ".cm-md-hidden-done": {
@@ -3280,6 +3530,18 @@ var baseHeadingStyles = {
3280
3530
  fontWeight: "var(--studio-heading-weight, 400)",
3281
3531
  textDecoration: "none"
3282
3532
  };
3533
+ var headingSizes = {
3534
+ 1: { fontSize: `var(--studio-heading-size-1, ${zoomed2("1.5rem")})`, lineHeight: zoomed2("2rem") },
3535
+ 2: { fontSize: `var(--studio-heading-size-2, ${zoomed2("1.5rem")})`, lineHeight: zoomed2("2rem") },
3536
+ 3: { fontSize: `var(--studio-heading-size-3, ${zoomed2("1.25rem")})`, lineHeight: zoomed2("1.75rem") },
3537
+ 4: { fontSize: `var(--studio-heading-size-4, ${zoomed2("1.1rem")})` }
3538
+ };
3539
+ var headingLines = Object.fromEntries(
3540
+ Object.entries(headingSizes).map(([level, size]) => [
3541
+ `.cm-md-h${level}`,
3542
+ { fontFamily: baseHeadingStyles.fontFamily, fontWeight: baseHeadingStyles.fontWeight, ...size }
3543
+ ])
3544
+ );
3283
3545
  var baseCodeStyles = {
3284
3546
  fontFamily: "var(--text-editor-family-code)",
3285
3547
  fontSize: "1em"
@@ -3298,31 +3560,28 @@ var markdownSyntaxHighlighting = (style) => HighlightStyle.define([
3298
3560
  {
3299
3561
  tag: tags.heading1,
3300
3562
  ...baseHeadingStyles,
3301
- fontSize: `var(--studio-heading-size-1, ${zoomed2("1.5rem")})`,
3302
- lineHeight: zoomed2("2rem"),
3563
+ ...headingSizes[1],
3303
3564
  marginBottom: zoomed2("1rem"),
3304
3565
  marginTop: zoomed2("2rem")
3305
3566
  },
3306
3567
  {
3307
3568
  tag: tags.heading2,
3308
3569
  ...baseHeadingStyles,
3309
- fontSize: `var(--studio-heading-size-2, ${zoomed2("1.5rem")})`,
3310
- lineHeight: zoomed2("2rem"),
3570
+ ...headingSizes[2],
3311
3571
  marginBottom: zoomed2("1rem"),
3312
3572
  marginTop: zoomed2("2rem")
3313
3573
  },
3314
3574
  {
3315
3575
  tag: tags.heading3,
3316
3576
  ...baseHeadingStyles,
3317
- fontSize: `var(--studio-heading-size-3, ${zoomed2("1.25rem")})`,
3318
- lineHeight: zoomed2("1.75rem"),
3577
+ ...headingSizes[3],
3319
3578
  marginBottom: zoomed2("1rem"),
3320
3579
  marginTop: zoomed2("2rem")
3321
3580
  },
3322
3581
  {
3323
3582
  tag: tags.heading4,
3324
3583
  ...baseHeadingStyles,
3325
- fontSize: `var(--studio-heading-size-4, ${zoomed2("1.1rem")})`,
3584
+ ...headingSizes[4],
3326
3585
  marginBottom: zoomed2("1rem"),
3327
3586
  marginTop: zoomed2("2rem")
3328
3587
  },
@@ -3335,7 +3594,7 @@ var markdownSyntaxHighlighting = (style) => HighlightStyle.define([
3335
3594
  color: "var(--syntax-comment, #555)",
3336
3595
  fontFamily: "var(--text-editor-family-code)"
3337
3596
  },
3338
- { tag: tags.quote, fontStyle: "var(--syntax-style-quote, italic)" },
3597
+ // quotes are set off by their bar (margin.ts), not by italics.
3339
3598
  {
3340
3599
  tag: tags.strong,
3341
3600
  fontFamily: bodyFont(style),
@@ -3397,7 +3656,7 @@ var markdownSyntaxHighlighting = (style) => HighlightStyle.define([
3397
3656
  { tag: tags.monospace, ...baseCodeStyles }
3398
3657
  ]);
3399
3658
  var theme = (style) => [
3400
- EditorView8.theme(markdownStyles(style)),
3659
+ EditorView8.theme({ ...markdownStyles(style), ...headingLines }),
3401
3660
  syntaxHighlighting(markdownSyntaxHighlighting(style))
3402
3661
  ];
3403
3662