@shadow-garden/bapbong-ui 0.9.0 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -899,10 +899,185 @@ var STYLE4 = `
899
899
  .bb-menu-shortcut{flex:none;opacity:.5;font-size:12px;padding-left:24px}
900
900
  .bb-menu-arrow{flex:none;opacity:.55;padding-left:12px}
901
901
  .bb-menu-sep{height:1px;margin:4px 6px;background:var(--bb-ui-border,#e3e3e0)}
902
+ .bb-popup{position:fixed;top:auto;left:auto;margin-top:0;z-index:1200;font-family:var(--bb-ui-font,system-ui,-apple-system,sans-serif);color:var(--bb-ui-fg,#2c2c2a);font-size:13px}
902
903
  .bb-menubar-v{flex-direction:column;align-items:stretch;gap:1px;border-bottom:none;padding:4px}
903
904
  .bb-menubar-v .bb-menubar-title{text-align:left;width:100%}
904
905
  .bb-menubar-v .bb-menu{top:auto;bottom:0;left:100%;margin-top:0;margin-left:4px}
905
906
  `;
907
+ function makeRow(label, opts) {
908
+ const item = document.createElement("button");
909
+ item.type = "button";
910
+ item.className = "bb-menu-item" + (opts.hasSub ? " bb-has-sub" : "");
911
+ item.addEventListener("mousedown", (e) => e.preventDefault());
912
+ const check = document.createElement("span");
913
+ check.className = "bb-menu-check";
914
+ const text = document.createElement("span");
915
+ text.className = "bb-menu-label";
916
+ text.textContent = label;
917
+ item.append(check, text);
918
+ if (opts.shortcut) {
919
+ const sc = document.createElement("span");
920
+ sc.className = "bb-menu-shortcut";
921
+ sc.textContent = opts.shortcut;
922
+ item.appendChild(sc);
923
+ }
924
+ if (opts.hasSub) {
925
+ const arrow = document.createElement("span");
926
+ arrow.className = "bb-menu-arrow";
927
+ arrow.textContent = "\u203A";
928
+ item.appendChild(arrow);
929
+ }
930
+ return { item, check };
931
+ }
932
+ function buildMenuEntries(entries, container, ctx) {
933
+ for (const entry of entries) {
934
+ if (entry === "separator") {
935
+ const sep = document.createElement("div");
936
+ sep.className = "bb-menu-sep";
937
+ sep.setAttribute("role", "separator");
938
+ container.appendChild(sep);
939
+ } else if ("submenu" in entry || "widget" in entry) {
940
+ const wrap = document.createElement("div");
941
+ wrap.className = "bb-menu-sub";
942
+ const { item } = makeRow(entry.label, { hasSub: true });
943
+ item.setAttribute("aria-haspopup", "true");
944
+ const flyout = document.createElement("div");
945
+ flyout.className = "bb-menu bb-submenu";
946
+ flyout.setAttribute("role", "menu");
947
+ if ("widget" in entry) {
948
+ flyout.classList.add("bb-submenu-widget");
949
+ const build = () => flyout.replaceChildren(entry.widget(() => ctx.close()));
950
+ wrap.addEventListener("mouseenter", build);
951
+ wrap.addEventListener("focusin", build);
952
+ } else {
953
+ buildMenuEntries(entry.submenu, flyout, ctx);
954
+ }
955
+ wrap.append(item, flyout);
956
+ container.appendChild(wrap);
957
+ } else if ("command" in entry) {
958
+ const editor = ctx.editor;
959
+ const cmd = editor?.commands.get(entry.command);
960
+ if (!editor || !cmd) continue;
961
+ const { item, check } = makeRow(
962
+ entry.label ?? ctx.labels[entry.command] ?? entry.command,
963
+ {}
964
+ );
965
+ item.setAttribute("role", "menuitemcheckbox");
966
+ item.addEventListener("click", () => {
967
+ const s = ctx.state();
968
+ if (s)
969
+ editor.commands.get(entry.command)?.run(s, (tr) => editor.dispatch(tr));
970
+ ctx.close();
971
+ editor.focus();
972
+ });
973
+ ctx.check(check, (s) => cmd.isActive?.(s) ?? false);
974
+ if (cmd.isEnabled) ctx.enable(item, (s) => cmd.isEnabled(s));
975
+ container.appendChild(item);
976
+ } else {
977
+ const { item, check } = makeRow(entry.label, {
978
+ shortcut: entry.shortcut
979
+ });
980
+ item.setAttribute(
981
+ "role",
982
+ entry.isActive ? "menuitemcheckbox" : "menuitem"
983
+ );
984
+ item.addEventListener("click", () => {
985
+ entry.run();
986
+ ctx.close();
987
+ });
988
+ if (entry.isActive) ctx.check(check, () => entry.isActive());
989
+ if (entry.isEnabled) ctx.enable(item, () => entry.isEnabled());
990
+ container.appendChild(item);
991
+ }
992
+ }
993
+ }
994
+ var currentPopup = null;
995
+ function closeCurrentPopup() {
996
+ if (currentPopup) {
997
+ const dispose = currentPopup;
998
+ currentPopup = null;
999
+ dispose();
1000
+ }
1001
+ }
1002
+ function showPopup(content, at, onClose) {
1003
+ injectStyle("bb-ui-menubar-styles", STYLE4);
1004
+ closeCurrentPopup();
1005
+ const el2 = document.createElement("div");
1006
+ el2.className = "bb-menu bb-popup";
1007
+ el2.setAttribute("role", "menu");
1008
+ el2.appendChild(content);
1009
+ document.body.appendChild(el2);
1010
+ const place = () => {
1011
+ const r = el2.getBoundingClientRect();
1012
+ el2.style.left = `${Math.max(4, Math.min(at.x, window.innerWidth - r.width - 4))}px`;
1013
+ el2.style.top = `${Math.max(4, Math.min(at.y, window.innerHeight - r.height - 4))}px`;
1014
+ };
1015
+ place();
1016
+ let disposed = false;
1017
+ const dispose = () => {
1018
+ if (disposed) return;
1019
+ disposed = true;
1020
+ document.removeEventListener("pointerdown", onPointer, true);
1021
+ document.removeEventListener("keydown", onKey, true);
1022
+ document.removeEventListener("scroll", onScroll, true);
1023
+ el2.remove();
1024
+ onClose?.();
1025
+ };
1026
+ const close = () => {
1027
+ if (currentPopup === dispose) currentPopup = null;
1028
+ dispose();
1029
+ };
1030
+ const onPointer = (e) => {
1031
+ if (!el2.contains(e.target)) close();
1032
+ };
1033
+ const onKey = (e) => {
1034
+ if (e.key === "Escape") {
1035
+ e.preventDefault();
1036
+ close();
1037
+ }
1038
+ };
1039
+ const onScroll = (e) => {
1040
+ if (!el2.contains(e.target)) close();
1041
+ };
1042
+ document.addEventListener("pointerdown", onPointer, true);
1043
+ document.addEventListener("keydown", onKey, true);
1044
+ document.addEventListener("scroll", onScroll, true);
1045
+ currentPopup = dispose;
1046
+ return { close, el: el2 };
1047
+ }
1048
+ function showMenu(entries, at, options = {}) {
1049
+ const labels = { ...DEFAULT_LABELS, ...options.labels ?? {} };
1050
+ const stateOf = () => {
1051
+ try {
1052
+ return options.editor?.state ?? null;
1053
+ } catch {
1054
+ return null;
1055
+ }
1056
+ };
1057
+ const container = document.createElement("div");
1058
+ let handle = null;
1059
+ const evalNow = (fn, fallback) => {
1060
+ try {
1061
+ return fn(stateOf());
1062
+ } catch {
1063
+ return fallback;
1064
+ }
1065
+ };
1066
+ buildMenuEntries(entries, container, {
1067
+ close: () => handle?.close(),
1068
+ labels,
1069
+ editor: options.editor,
1070
+ state: stateOf,
1071
+ check: (el2, active) => {
1072
+ el2.textContent = evalNow(active, false) ? "\u2713" : "";
1073
+ },
1074
+ enable: (el2, enabled) => {
1075
+ el2.disabled = !evalNow(enabled, true);
1076
+ }
1077
+ });
1078
+ handle = showPopup(container, at, options.onClose);
1079
+ return handle;
1080
+ }
906
1081
  function defaultMenus(commands) {
907
1082
  const names = [...commands].map((c) => c.name);
908
1083
  const marks = ["bold", "italic", "underline", "strike"].filter(
@@ -949,94 +1124,15 @@ function mountMenubar(host, editor, options = {}) {
949
1124
  if (focusFirst)
950
1125
  p.dropdown.querySelector(".bb-menu-item")?.focus();
951
1126
  };
952
- const makeRow = (label, opts) => {
953
- const item = document.createElement("button");
954
- item.type = "button";
955
- item.className = "bb-menu-item" + (opts.hasSub ? " bb-has-sub" : "");
956
- item.addEventListener("mousedown", (e) => e.preventDefault());
957
- const check = document.createElement("span");
958
- check.className = "bb-menu-check";
959
- const text = document.createElement("span");
960
- text.className = "bb-menu-label";
961
- text.textContent = label;
962
- item.append(check, text);
963
- if (opts.shortcut) {
964
- const sc = document.createElement("span");
965
- sc.className = "bb-menu-shortcut";
966
- sc.textContent = opts.shortcut;
967
- item.appendChild(sc);
968
- }
969
- if (opts.hasSub) {
970
- const arrow = document.createElement("span");
971
- arrow.className = "bb-menu-arrow";
972
- arrow.textContent = "\u203A";
973
- item.appendChild(arrow);
974
- }
975
- return { item, check };
976
- };
977
- const buildEntries = (entries, container) => {
978
- for (const entry of entries) {
979
- if (entry === "separator") {
980
- const sep = document.createElement("div");
981
- sep.className = "bb-menu-sep";
982
- sep.setAttribute("role", "separator");
983
- container.appendChild(sep);
984
- } else if ("submenu" in entry || "widget" in entry) {
985
- const wrap = document.createElement("div");
986
- wrap.className = "bb-menu-sub";
987
- const { item } = makeRow(entry.label, { hasSub: true });
988
- item.setAttribute("aria-haspopup", "true");
989
- const flyout = document.createElement("div");
990
- flyout.className = "bb-menu bb-submenu";
991
- flyout.setAttribute("role", "menu");
992
- if ("widget" in entry) {
993
- flyout.classList.add("bb-submenu-widget");
994
- const build = () => flyout.replaceChildren(entry.widget(() => close()));
995
- wrap.addEventListener("mouseenter", build);
996
- wrap.addEventListener("focusin", build);
997
- } else {
998
- buildEntries(entry.submenu, flyout);
999
- }
1000
- wrap.append(item, flyout);
1001
- container.appendChild(wrap);
1002
- } else if ("command" in entry) {
1003
- const cmd = editor.commands.get(entry.command);
1004
- if (!cmd) continue;
1005
- const { item, check } = makeRow(
1006
- entry.label ?? labels[entry.command] ?? entry.command,
1007
- {}
1008
- );
1009
- item.setAttribute("role", "menuitemcheckbox");
1010
- item.addEventListener("click", () => {
1011
- if (latest)
1012
- editor.commands.get(entry.command)?.run(latest, (tr) => editor.dispatch(tr));
1013
- close();
1014
- editor.focus();
1015
- });
1016
- checks.push({ el: check, active: (s) => cmd.isActive?.(s) ?? false });
1017
- if (cmd.isEnabled)
1018
- enables.push({ el: item, enabled: (s) => cmd.isEnabled(s) });
1019
- container.appendChild(item);
1020
- } else {
1021
- const { item, check } = makeRow(entry.label, {
1022
- shortcut: entry.shortcut
1023
- });
1024
- item.setAttribute(
1025
- "role",
1026
- entry.isActive ? "menuitemcheckbox" : "menuitem"
1027
- );
1028
- item.addEventListener("click", () => {
1029
- entry.run();
1030
- close();
1031
- });
1032
- if (entry.isActive)
1033
- checks.push({ el: check, active: () => entry.isActive() });
1034
- if (entry.isEnabled)
1035
- enables.push({ el: item, enabled: () => entry.isEnabled() });
1036
- container.appendChild(item);
1037
- }
1038
- }
1127
+ const buildCtx = {
1128
+ close: () => close(),
1129
+ labels,
1130
+ editor,
1131
+ state: () => latest,
1132
+ check: (el2, active) => checks.push({ el: el2, active }),
1133
+ enable: (el2, enabled) => enables.push({ el: el2, enabled })
1039
1134
  };
1135
+ const buildEntries = (entries, container) => buildMenuEntries(entries, container, buildCtx);
1040
1136
  menus.forEach((menu, idx) => {
1041
1137
  const wrap = document.createElement("div");
1042
1138
  wrap.className = "bb-menubar-menu";
@@ -1809,6 +1905,7 @@ function fmtCm(cm) {
1809
1905
  }
1810
1906
  var STYLE10 = `
1811
1907
  .bb-ps{display:flex;flex-direction:column;min-width:250px;max-height:min(70vh,460px);overflow-y:auto}
1908
+ .bb-ps,.bb-ps *{box-sizing:border-box}
1812
1909
  .bb-ps-row{display:flex;align-items:center;gap:11px;width:100%;padding:7px 10px;border:0;border-radius:6px;background:transparent;color:inherit;font:inherit;text-align:left;cursor:pointer}
1813
1910
  .bb-ps-row:hover,.bb-ps-row:focus{background:var(--bb-ui-hover,#f1efe8);outline:none}
1814
1911
  .bb-ps-row[aria-checked="true"]{background:var(--bb-ui-active-bg,#e6f1fb)}
@@ -1825,6 +1922,16 @@ var STYLE10 = `
1825
1922
  .bb-pd-input{flex:1 1 auto;min-width:0;width:100%;height:30px;padding:0 8px;border:1px solid var(--bb-ui-control-border,var(--bb-ui-border,#d8d6cf));border-radius:6px;background:var(--bb-ui-control-bg,var(--bb-ui-bg,#fff));color:inherit;font:inherit;font-size:13px}
1826
1923
  .bb-pd-input:focus{outline:2px solid var(--bb-ui-active-border,#7fb2ec);outline-offset:-1px}
1827
1924
  .bb-pd-actions{display:flex;justify-content:flex-end;gap:8px}
1925
+ .bb-pn-input{width:66px;height:24px;padding:0 6px;border:1px solid var(--bb-ui-control-border,var(--bb-ui-border,#d8d6cf));border-radius:5px;background:var(--bb-ui-control-bg,var(--bb-ui-bg,#fff));color:inherit;font:inherit;font-size:12px}
1926
+ .bb-pn-input:focus{outline:2px solid var(--bb-ui-active-border,#7fb2ec);outline-offset:-1px}
1927
+ .bb-pn-check{flex:none;width:15px;height:15px;display:inline-flex;align-items:center;justify-content:center;border:1.5px solid var(--bb-ui-border,#b4b2a9);border-radius:4px;background:var(--bb-ui-bg,#fff);color:#fff;font-size:10px;line-height:1}
1928
+ .bb-pn-check[data-on="true"]{background:var(--bb-ui-active-fg,#0c447c);border-color:var(--bb-ui-active-fg,#0c447c)}
1929
+ .bb-pn-body[data-disabled="true"]{opacity:.35;pointer-events:none}
1930
+ .bb-ps-group{padding:5px 10px 2px;font-size:11px;font-weight:600;letter-spacing:.4px;text-transform:uppercase;opacity:.55}
1931
+ .bb-ps-tiles{display:flex;gap:6px;padding:2px 6px 4px}
1932
+ .bb-ps-tile{flex:1;display:flex;flex-direction:column;align-items:center;gap:2px;padding:7px 0 5px;border:0;border-radius:6px;background:transparent;color:inherit;font:inherit;font-size:12px;font-weight:600;cursor:pointer}
1933
+ .bb-ps-tile:hover,.bb-ps-tile:focus{background:var(--bb-ui-hover,#f1efe8);outline:none}
1934
+ .bb-ps-tile[aria-checked="true"]{background:var(--bb-ui-active-bg,#e6f1fb)}
1828
1935
  `;
1829
1936
  var SVG_NS = "http://www.w3.org/2000/svg";
1830
1937
  function svgEl(name, attrs) {
@@ -2111,6 +2218,260 @@ function openMarginsDialog(options) {
2111
2218
  top.input.focus();
2112
2219
  top.input.select();
2113
2220
  }
2221
+ function numberPreview(sample) {
2222
+ const svg = pagePreview(0.773);
2223
+ const t = svgEl("text", {
2224
+ x: 17,
2225
+ y: 25,
2226
+ "text-anchor": "middle",
2227
+ "font-size": 11,
2228
+ fill: "var(--bb-ui-fg,#2c2c2a)",
2229
+ "fill-opacity": 0.75
2230
+ });
2231
+ t.textContent = sample;
2232
+ svg.appendChild(t);
2233
+ return svg;
2234
+ }
2235
+ var PGNUM_FORMATS = [
2236
+ [void 0, "1, 2, 3, 4\u2026", "1"],
2237
+ ["lowerRoman", "i, ii, iii, iv\u2026", "i"],
2238
+ ["upperRoman", "I, II, III, IV\u2026", "I"],
2239
+ ["lowerLetter", "a, b, c, d\u2026", "a"],
2240
+ ["upperLetter", "A, B, C, D\u2026", "A"]
2241
+ ];
2242
+ function pageNumberPicker(options) {
2243
+ injectStyle("bb-ui-pagesetup-styles", STYLE10);
2244
+ const root = document.createElement("div");
2245
+ root.className = "bb-ps";
2246
+ root.setAttribute("role", "menu");
2247
+ let body = root;
2248
+ if (options.onToggleShown) {
2249
+ const on = options.shown !== false;
2250
+ const row = document.createElement("button");
2251
+ row.type = "button";
2252
+ row.className = "bb-ps-row";
2253
+ row.setAttribute("role", "menuitemcheckbox");
2254
+ row.setAttribute("aria-checked", String(on));
2255
+ const box = document.createElement("span");
2256
+ box.className = "bb-pn-check";
2257
+ box.dataset["on"] = String(on);
2258
+ box.textContent = on ? "\u2713" : "";
2259
+ const name = document.createElement("span");
2260
+ name.className = "bb-ps-name";
2261
+ name.textContent = options.labels?.shown ?? "Show page numbers";
2262
+ row.append(box, name);
2263
+ row.addEventListener("mousedown", (e) => e.preventDefault());
2264
+ row.addEventListener("click", () => options.onToggleShown?.(!on));
2265
+ root.appendChild(row);
2266
+ const sep0 = document.createElement("div");
2267
+ sep0.className = "bb-ps-sep";
2268
+ root.appendChild(sep0);
2269
+ body = document.createElement("div");
2270
+ body.className = "bb-pn-body";
2271
+ if (!on) body.dataset["disabled"] = "true";
2272
+ root.appendChild(body);
2273
+ }
2274
+ const curFmt = options.fmt === "decimal" ? void 0 : options.fmt;
2275
+ const emit = (fmt, start) => {
2276
+ options.onPick(
2277
+ fmt == null && start == null ? null : {
2278
+ ...fmt != null ? { fmt } : {},
2279
+ ...start != null ? { start } : {}
2280
+ }
2281
+ );
2282
+ };
2283
+ for (const [key, label, sample] of PGNUM_FORMATS) {
2284
+ body.appendChild(
2285
+ presetRow(
2286
+ numberPreview(sample),
2287
+ label,
2288
+ captionLine(""),
2289
+ curFmt === key,
2290
+ () => emit(key, options.start)
2291
+ )
2292
+ );
2293
+ }
2294
+ const sep = document.createElement("div");
2295
+ sep.className = "bb-ps-sep";
2296
+ root.appendChild(sep);
2297
+ const restart = document.createElement("div");
2298
+ restart.className = "bb-ps-row";
2299
+ restart.setAttribute("role", "menuitemradio");
2300
+ restart.setAttribute("aria-checked", String(options.start != null));
2301
+ const restartName = document.createElement("span");
2302
+ restartName.className = "bb-ps-name";
2303
+ restartName.style.flex = "1 1 auto";
2304
+ restartName.textContent = options.labels?.restart ?? "Restart at";
2305
+ const input = document.createElement("input");
2306
+ input.type = "number";
2307
+ input.min = "0";
2308
+ input.step = "1";
2309
+ input.className = "bb-pn-input";
2310
+ input.value = String(options.start ?? 1);
2311
+ const readStart = () => {
2312
+ const v = Math.floor(Number(input.value));
2313
+ return Number.isFinite(v) && v >= 0 && input.value.trim() !== "" ? v : options.start ?? 1;
2314
+ };
2315
+ restart.append(restartName, input);
2316
+ restart.addEventListener("mousedown", (e) => {
2317
+ if (e.target !== input) e.preventDefault();
2318
+ });
2319
+ restart.addEventListener("click", (e) => {
2320
+ if (e.target !== input) emit(curFmt, readStart());
2321
+ });
2322
+ input.addEventListener("keydown", (e) => {
2323
+ if (e.key === "Enter") {
2324
+ e.preventDefault();
2325
+ emit(curFmt, readStart());
2326
+ }
2327
+ });
2328
+ input.addEventListener("wheel", (e) => e.preventDefault(), {
2329
+ passive: false
2330
+ });
2331
+ body.appendChild(restart);
2332
+ body.appendChild(
2333
+ presetRow(
2334
+ numberPreview("\u2192"),
2335
+ options.labels?.continueFrom ?? "Continue from previous section",
2336
+ captionLine(options.continueHint ?? ""),
2337
+ options.start == null,
2338
+ () => emit(curFmt, void 0)
2339
+ )
2340
+ );
2341
+ return root;
2342
+ }
2343
+ function sectionPaperPanel(options) {
2344
+ injectStyle("bb-ui-pagesetup-styles", STYLE10);
2345
+ const root = document.createElement("div");
2346
+ root.className = "bb-ps";
2347
+ root.setAttribute("role", "menu");
2348
+ const group = (text) => {
2349
+ const el2 = document.createElement("div");
2350
+ el2.className = "bb-ps-group";
2351
+ el2.textContent = text;
2352
+ return el2;
2353
+ };
2354
+ const sep = () => {
2355
+ const el2 = document.createElement("div");
2356
+ el2.className = "bb-ps-sep";
2357
+ return el2;
2358
+ };
2359
+ root.appendChild(group(options.labels?.orientation ?? "Orientation"));
2360
+ const tiles = document.createElement("div");
2361
+ tiles.className = "bb-ps-tiles";
2362
+ const landscapeNow = options.page.width > options.page.height;
2363
+ const short = Math.min(options.page.width, options.page.height);
2364
+ const long = Math.max(options.page.width, options.page.height);
2365
+ for (const [key, label, ratio] of [
2366
+ ["portrait", "Portrait", short / long],
2367
+ ["landscape", "Landscape", long / short]
2368
+ ]) {
2369
+ const tile = document.createElement("button");
2370
+ tile.type = "button";
2371
+ tile.className = "bb-ps-tile";
2372
+ tile.setAttribute("role", "menuitemradio");
2373
+ tile.setAttribute(
2374
+ "aria-checked",
2375
+ String(landscapeNow === (key === "landscape"))
2376
+ );
2377
+ const icon = pagePreview(ratio);
2378
+ icon.setAttribute("style", "width:26px;height:32px");
2379
+ const name = document.createElement("span");
2380
+ name.textContent = label;
2381
+ tile.append(icon, name);
2382
+ tile.addEventListener("mousedown", (e) => e.preventDefault());
2383
+ tile.addEventListener("click", () => options.onOrientation(key));
2384
+ tiles.appendChild(tile);
2385
+ }
2386
+ root.appendChild(tiles);
2387
+ root.appendChild(sep());
2388
+ root.appendChild(group(options.labels?.pageSize ?? "Page size"));
2389
+ for (const item of options.items) {
2390
+ root.appendChild(
2391
+ presetRow(
2392
+ pagePreview(item.px[0] / item.px[1]),
2393
+ item.label,
2394
+ captionLine(`${fmtCm(item.cm[0])} x ${fmtCm(item.cm[1])}`),
2395
+ !!item.active,
2396
+ () => options.onPick(item.key)
2397
+ )
2398
+ );
2399
+ }
2400
+ root.appendChild(sep());
2401
+ root.appendChild(
2402
+ customRow(
2403
+ pagePreview(0.773),
2404
+ options.labels?.custom ?? "Custom page size",
2405
+ "Define custom page size",
2406
+ options.onCustom
2407
+ )
2408
+ );
2409
+ return root;
2410
+ }
2411
+
2412
+ // packages/ui/src/lib/section-chip.ts
2413
+ var STYLE11 = `
2414
+ .bb-secchip{position:absolute;z-index:8;display:inline-flex;align-items:center;transform:translate(-50%,-50%);white-space:nowrap;background:var(--bb-ui-menu-bg,#fff);-webkit-backdrop-filter:var(--bb-ui-pop-filter,none);backdrop-filter:var(--bb-ui-pop-filter,none);border:1px solid var(--bb-ui-pop-border,var(--bb-ui-border,#e3e3e0));border-radius:10px;padding:1px 2px;box-shadow:0 2px 10px rgba(0,0,0,.12);font-family:var(--bb-ui-font,system-ui,-apple-system,sans-serif);font-size:11px;color:var(--bb-ui-fg,#2c2c2a)}
2415
+ .bb-secchip *{box-sizing:border-box}
2416
+ .bb-secchip-title{padding:0 7px;font-size:11px;font-weight:600;opacity:.8}
2417
+ .bb-secchip-seg{display:inline-flex;align-items:center;gap:4px;height:16px;padding:0 7px;border:0;border-radius:6px;background:transparent;color:inherit;font:inherit;font-size:11px;cursor:pointer}
2418
+ .bb-secchip-seg:hover,.bb-secchip-seg[aria-expanded="true"]{background:var(--bb-ui-hover,#f1efe8)}
2419
+ .bb-secchip-caret{font-size:8px;opacity:.55}
2420
+ .bb-secchip-seg[data-muted="true"] .bb-secchip-seglabel{font-style:italic;opacity:.55}
2421
+ .bb-secchip-div{flex:none;width:1px;height:11px;margin:0 2px;background:var(--bb-ui-border,#e3e3e0)}
2422
+ .bb-secchip-x{display:inline-flex;align-items:center;justify-content:center;width:20px;height:16px;padding:0;border:0;border-radius:6px;background:transparent;color:inherit;font:inherit;opacity:.65;cursor:pointer}
2423
+ .bb-secchip-x:hover{background:var(--bb-ui-hover,#f1efe8);opacity:1}
2424
+ `;
2425
+ function createSectionChip(options) {
2426
+ injectStyle("bb-ui-section-chip-styles", STYLE11);
2427
+ const el2 = document.createElement("div");
2428
+ el2.className = "bb-secchip";
2429
+ const title = document.createElement("span");
2430
+ title.className = "bb-secchip-title";
2431
+ title.textContent = options.title;
2432
+ const divider = () => {
2433
+ const d = document.createElement("span");
2434
+ d.className = "bb-secchip-div";
2435
+ return d;
2436
+ };
2437
+ const segment = (aria, onOpen) => {
2438
+ const btn = document.createElement("button");
2439
+ btn.type = "button";
2440
+ btn.className = "bb-secchip-seg";
2441
+ btn.setAttribute("aria-haspopup", "true");
2442
+ if (aria) btn.setAttribute("aria-label", aria);
2443
+ const label = document.createElement("span");
2444
+ label.className = "bb-secchip-seglabel";
2445
+ const caret = document.createElement("span");
2446
+ caret.className = "bb-secchip-caret";
2447
+ caret.textContent = "\u25BE";
2448
+ btn.append(label, caret);
2449
+ btn.addEventListener("mousedown", (e) => e.preventDefault());
2450
+ btn.addEventListener("click", () => onOpen(btn));
2451
+ return { btn, label };
2452
+ };
2453
+ const nums = segment(options.ariaPageNumbers, options.onPageNumbers);
2454
+ const paper = segment(options.ariaPaper, options.onPaper);
2455
+ const x = document.createElement("button");
2456
+ x.type = "button";
2457
+ x.className = "bb-secchip-x";
2458
+ x.setAttribute("aria-label", options.ariaDelete ?? "Remove section break");
2459
+ x.innerHTML = '<svg viewBox="0 0 16 16" width="9" height="9" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"><path d="M3 3l10 10M13 3 3 13"/></svg>';
2460
+ x.addEventListener("mousedown", (e) => e.preventDefault());
2461
+ x.addEventListener("click", () => options.onDelete());
2462
+ el2.append(title, divider(), nums.btn, divider(), paper.btn, divider(), x);
2463
+ return {
2464
+ el: el2,
2465
+ update(data) {
2466
+ nums.label.textContent = data.pageNumbers;
2467
+ nums.btn.dataset["muted"] = String(!!data.pageNumbersMuted);
2468
+ paper.label.textContent = data.paper;
2469
+ },
2470
+ destroy() {
2471
+ el2.remove();
2472
+ }
2473
+ };
2474
+ }
2114
2475
 
2115
2476
  // packages/ui/src/lib/font-dialog.ts
2116
2477
  var twipsToPt = (tw) => tw / 20;
@@ -2119,7 +2480,7 @@ var halfToPt = (hp) => hp / 2;
2119
2480
  var ptToHalf = (pt) => Math.round(pt * 2);
2120
2481
  var SCALE_PRESETS = [200, 150, 100, 90, 80, 66, 50, 33];
2121
2482
  var SUPERSUB_SCALE = 0.66;
2122
- var STYLE11 = `
2483
+ var STYLE12 = `
2123
2484
  .bb-fd{display:flex;flex-direction:column;gap:15px;min-width:396px;max-width:430px;color:var(--bb-ui-fg,#2c2c2a)}
2124
2485
  .bb-fd *{box-sizing:border-box}
2125
2486
  /* A segmented control, not a "tab joined to its pane": that pattern needs the
@@ -2201,7 +2562,7 @@ function openFontDialog({
2201
2562
  sizes,
2202
2563
  onApply
2203
2564
  }) {
2204
- injectStyle("bb-font-dialog", STYLE11);
2565
+ injectStyle("bb-font-dialog", STYLE12);
2205
2566
  const dialog = new Dialog({ title: "Font", modal: true });
2206
2567
  const root = el("div", "bb-fd");
2207
2568
  const tabs = el("div", "bb-fd-tabs");
@@ -2446,6 +2807,7 @@ export {
2446
2807
  cmToPx,
2447
2808
  colorButton,
2448
2809
  createFindDialog,
2810
+ createSectionChip,
2449
2811
  defaultMenus,
2450
2812
  defaultToolbarGroups,
2451
2813
  marginPresetPicker,
@@ -2457,10 +2819,14 @@ export {
2457
2819
  openMarginsDialog,
2458
2820
  openPageSizeDialog,
2459
2821
  orientationPicker,
2822
+ pageNumberPicker,
2460
2823
  pageSizePicker,
2461
2824
  promptDialog,
2462
2825
  pxToCm,
2826
+ sectionPaperPanel,
2463
2827
  showContextMenu,
2464
2828
  showLinkPanel,
2829
+ showMenu,
2830
+ showPopup,
2465
2831
  tableGridPicker
2466
2832
  };
@@ -42,6 +42,32 @@ export interface MenubarOptions {
42
42
  export interface MenubarHandle {
43
43
  destroy(): void;
44
44
  }
45
+ export interface PopupHandle {
46
+ close(): void;
47
+ /** The popup root, for a host that needs to reposition or inspect it. */
48
+ el: HTMLElement;
49
+ }
50
+ /** Mount `el` as a fixed one-shot popup at viewport point `at` (clamped to
51
+ * the viewport), closing on outside pointerdown, Escape, or scroll. Only one
52
+ * popup is open at a time. */
53
+ export declare function showPopup(content: HTMLElement, at: {
54
+ x: number;
55
+ y: number;
56
+ }, onClose?: () => void): PopupHandle;
57
+ export interface ShowMenuOptions {
58
+ /** Resolves CommandEntry rows (state, dispatch, focus). Without it they are
59
+ * skipped; Action/Submenu/Widget entries need nothing. */
60
+ editor?: EditorHandle;
61
+ labels?: Record<string, string>;
62
+ onClose?: () => void;
63
+ }
64
+ /** A one-shot dropdown at viewport point `at`, rendered by the SAME builder as
65
+ * the menubar's menus — identical rows, checkmarks, submenu and widget
66
+ * flyouts. Check/enabled state is evaluated once, when the menu opens. */
67
+ export declare function showMenu(entries: MenuEntry[], at: {
68
+ x: number;
69
+ y: number;
70
+ }, options?: ShowMenuOptions): PopupHandle;
45
71
  /** Default menus: a "Format" menu of marks, a separator, then alignments —
46
72
  * only the commands the registry actually has. */
47
73
  export declare function defaultMenus(commands: Collection<Command>): Menu[];
@@ -1 +1 @@
1
- {"version":3,"file":"menubar.d.ts","sourceRoot":"","sources":["../../src/lib/menubar.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,kCAAkC,CAAC;AAC5E,OAAO,EACL,KAAK,YAAY,EAGlB,MAAM,eAAe,CAAC;AAEvB,kEAAkE;AAClE,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AACD,4EAA4E;AAC5E,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,IAAI,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,OAAO,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,OAAO,CAAC;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AACD,yBAAyB;AACzB,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,SAAS,EAAE,CAAC;CACtB;AACD,kFAAkF;AAClF,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,IAAI,KAAK,WAAW,CAAC;CAC5C;AACD,MAAM,MAAM,SAAS,GACjB,WAAW,GACX,YAAY,GACZ,WAAW,GACX,YAAY,GACZ,WAAW,CAAC;AAEhB,uDAAuD;AACvD,MAAM,WAAW,IAAI;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,SAAS,EAAE,CAAC;CACtB;AAED,MAAM,WAAW,cAAc;IAC7B,kFAAkF;IAClF,KAAK,CAAC,EAAE,IAAI,EAAE,CAAC;IACf,0EAA0E;IAC1E,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC;;+EAE2E;IAC3E,WAAW,CAAC,EAAE,YAAY,GAAG,UAAU,CAAC;CACzC;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,IAAI,IAAI,CAAC;CACjB;AAqDD;mDACmD;AACnD,wBAAgB,YAAY,CAAC,QAAQ,EAAE,UAAU,CAAC,OAAO,CAAC,GAAG,IAAI,EAAE,CAYlE;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,WAAW,EACjB,MAAM,EAAE,YAAY,EACpB,OAAO,GAAE,cAAmB,GAC3B,aAAa,CAiOf"}
1
+ {"version":3,"file":"menubar.d.ts","sourceRoot":"","sources":["../../src/lib/menubar.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,kCAAkC,CAAC;AAC5E,OAAO,EACL,KAAK,YAAY,EAGlB,MAAM,eAAe,CAAC;AAEvB,kEAAkE;AAClE,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AACD,4EAA4E;AAC5E,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,IAAI,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,OAAO,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,OAAO,CAAC;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AACD,yBAAyB;AACzB,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,SAAS,EAAE,CAAC;CACtB;AACD,kFAAkF;AAClF,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,IAAI,KAAK,WAAW,CAAC;CAC5C;AACD,MAAM,MAAM,SAAS,GACjB,WAAW,GACX,YAAY,GACZ,WAAW,GACX,YAAY,GACZ,WAAW,CAAC;AAEhB,uDAAuD;AACvD,MAAM,WAAW,IAAI;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,SAAS,EAAE,CAAC;CACtB;AAED,MAAM,WAAW,cAAc;IAC7B,kFAAkF;IAClF,KAAK,CAAC,EAAE,IAAI,EAAE,CAAC;IACf,0EAA0E;IAC1E,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC;;+EAE2E;IAC3E,WAAW,CAAC,EAAE,YAAY,GAAG,UAAU,CAAC;CACzC;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,IAAI,IAAI,CAAC;CACjB;AAgLD,MAAM,WAAW,WAAW;IAC1B,KAAK,IAAI,IAAI,CAAC;IACd,yEAAyE;IACzE,EAAE,EAAE,WAAW,CAAC;CACjB;AAWD;;+BAE+B;AAC/B,wBAAgB,SAAS,CACvB,OAAO,EAAE,WAAW,EACpB,EAAE,EAAE;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,EAC5B,OAAO,CAAC,EAAE,MAAM,IAAI,GACnB,WAAW,CAkDb;AAED,MAAM,WAAW,eAAe;IAC9B;+DAC2D;IAC3D,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB;AAED;;2EAE2E;AAC3E,wBAAgB,QAAQ,CACtB,OAAO,EAAE,SAAS,EAAE,EACpB,EAAE,EAAE;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,EAC5B,OAAO,GAAE,eAAoB,GAC5B,WAAW,CAgCb;AAED;mDACmD;AACnD,wBAAgB,YAAY,CAAC,QAAQ,EAAE,UAAU,CAAC,OAAO,CAAC,GAAG,IAAI,EAAE,CAYlE;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,WAAW,EACjB,MAAM,EAAE,YAAY,EACpB,OAAO,GAAE,cAAmB,GAC3B,aAAa,CAsIf"}