@shadow-garden/bapbong-ui 0.8.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.cjs CHANGED
@@ -25,6 +25,7 @@ __export(index_exports, {
25
25
  cmToPx: () => cmToPx,
26
26
  colorButton: () => colorButton,
27
27
  createFindDialog: () => createFindDialog,
28
+ createSectionChip: () => createSectionChip,
28
29
  defaultMenus: () => defaultMenus,
29
30
  defaultToolbarGroups: () => defaultToolbarGroups,
30
31
  marginPresetPicker: () => marginPresetPicker,
@@ -36,11 +37,15 @@ __export(index_exports, {
36
37
  openMarginsDialog: () => openMarginsDialog,
37
38
  openPageSizeDialog: () => openPageSizeDialog,
38
39
  orientationPicker: () => orientationPicker,
40
+ pageNumberPicker: () => pageNumberPicker,
39
41
  pageSizePicker: () => pageSizePicker,
40
42
  promptDialog: () => promptDialog,
41
43
  pxToCm: () => pxToCm,
44
+ sectionPaperPanel: () => sectionPaperPanel,
42
45
  showContextMenu: () => showContextMenu,
43
46
  showLinkPanel: () => showLinkPanel,
47
+ showMenu: () => showMenu,
48
+ showPopup: () => showPopup,
44
49
  tableGridPicker: () => tableGridPicker
45
50
  });
46
51
  module.exports = __toCommonJS(index_exports);
@@ -946,10 +951,185 @@ var STYLE4 = `
946
951
  .bb-menu-shortcut{flex:none;opacity:.5;font-size:12px;padding-left:24px}
947
952
  .bb-menu-arrow{flex:none;opacity:.55;padding-left:12px}
948
953
  .bb-menu-sep{height:1px;margin:4px 6px;background:var(--bb-ui-border,#e3e3e0)}
954
+ .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}
949
955
  .bb-menubar-v{flex-direction:column;align-items:stretch;gap:1px;border-bottom:none;padding:4px}
950
956
  .bb-menubar-v .bb-menubar-title{text-align:left;width:100%}
951
957
  .bb-menubar-v .bb-menu{top:auto;bottom:0;left:100%;margin-top:0;margin-left:4px}
952
958
  `;
959
+ function makeRow(label, opts) {
960
+ const item = document.createElement("button");
961
+ item.type = "button";
962
+ item.className = "bb-menu-item" + (opts.hasSub ? " bb-has-sub" : "");
963
+ item.addEventListener("mousedown", (e) => e.preventDefault());
964
+ const check = document.createElement("span");
965
+ check.className = "bb-menu-check";
966
+ const text = document.createElement("span");
967
+ text.className = "bb-menu-label";
968
+ text.textContent = label;
969
+ item.append(check, text);
970
+ if (opts.shortcut) {
971
+ const sc = document.createElement("span");
972
+ sc.className = "bb-menu-shortcut";
973
+ sc.textContent = opts.shortcut;
974
+ item.appendChild(sc);
975
+ }
976
+ if (opts.hasSub) {
977
+ const arrow = document.createElement("span");
978
+ arrow.className = "bb-menu-arrow";
979
+ arrow.textContent = "\u203A";
980
+ item.appendChild(arrow);
981
+ }
982
+ return { item, check };
983
+ }
984
+ function buildMenuEntries(entries, container, ctx) {
985
+ for (const entry of entries) {
986
+ if (entry === "separator") {
987
+ const sep = document.createElement("div");
988
+ sep.className = "bb-menu-sep";
989
+ sep.setAttribute("role", "separator");
990
+ container.appendChild(sep);
991
+ } else if ("submenu" in entry || "widget" in entry) {
992
+ const wrap = document.createElement("div");
993
+ wrap.className = "bb-menu-sub";
994
+ const { item } = makeRow(entry.label, { hasSub: true });
995
+ item.setAttribute("aria-haspopup", "true");
996
+ const flyout = document.createElement("div");
997
+ flyout.className = "bb-menu bb-submenu";
998
+ flyout.setAttribute("role", "menu");
999
+ if ("widget" in entry) {
1000
+ flyout.classList.add("bb-submenu-widget");
1001
+ const build = () => flyout.replaceChildren(entry.widget(() => ctx.close()));
1002
+ wrap.addEventListener("mouseenter", build);
1003
+ wrap.addEventListener("focusin", build);
1004
+ } else {
1005
+ buildMenuEntries(entry.submenu, flyout, ctx);
1006
+ }
1007
+ wrap.append(item, flyout);
1008
+ container.appendChild(wrap);
1009
+ } else if ("command" in entry) {
1010
+ const editor = ctx.editor;
1011
+ const cmd = editor?.commands.get(entry.command);
1012
+ if (!editor || !cmd) continue;
1013
+ const { item, check } = makeRow(
1014
+ entry.label ?? ctx.labels[entry.command] ?? entry.command,
1015
+ {}
1016
+ );
1017
+ item.setAttribute("role", "menuitemcheckbox");
1018
+ item.addEventListener("click", () => {
1019
+ const s = ctx.state();
1020
+ if (s)
1021
+ editor.commands.get(entry.command)?.run(s, (tr) => editor.dispatch(tr));
1022
+ ctx.close();
1023
+ editor.focus();
1024
+ });
1025
+ ctx.check(check, (s) => cmd.isActive?.(s) ?? false);
1026
+ if (cmd.isEnabled) ctx.enable(item, (s) => cmd.isEnabled(s));
1027
+ container.appendChild(item);
1028
+ } else {
1029
+ const { item, check } = makeRow(entry.label, {
1030
+ shortcut: entry.shortcut
1031
+ });
1032
+ item.setAttribute(
1033
+ "role",
1034
+ entry.isActive ? "menuitemcheckbox" : "menuitem"
1035
+ );
1036
+ item.addEventListener("click", () => {
1037
+ entry.run();
1038
+ ctx.close();
1039
+ });
1040
+ if (entry.isActive) ctx.check(check, () => entry.isActive());
1041
+ if (entry.isEnabled) ctx.enable(item, () => entry.isEnabled());
1042
+ container.appendChild(item);
1043
+ }
1044
+ }
1045
+ }
1046
+ var currentPopup = null;
1047
+ function closeCurrentPopup() {
1048
+ if (currentPopup) {
1049
+ const dispose = currentPopup;
1050
+ currentPopup = null;
1051
+ dispose();
1052
+ }
1053
+ }
1054
+ function showPopup(content, at, onClose) {
1055
+ injectStyle("bb-ui-menubar-styles", STYLE4);
1056
+ closeCurrentPopup();
1057
+ const el2 = document.createElement("div");
1058
+ el2.className = "bb-menu bb-popup";
1059
+ el2.setAttribute("role", "menu");
1060
+ el2.appendChild(content);
1061
+ document.body.appendChild(el2);
1062
+ const place = () => {
1063
+ const r = el2.getBoundingClientRect();
1064
+ el2.style.left = `${Math.max(4, Math.min(at.x, window.innerWidth - r.width - 4))}px`;
1065
+ el2.style.top = `${Math.max(4, Math.min(at.y, window.innerHeight - r.height - 4))}px`;
1066
+ };
1067
+ place();
1068
+ let disposed = false;
1069
+ const dispose = () => {
1070
+ if (disposed) return;
1071
+ disposed = true;
1072
+ document.removeEventListener("pointerdown", onPointer, true);
1073
+ document.removeEventListener("keydown", onKey, true);
1074
+ document.removeEventListener("scroll", onScroll, true);
1075
+ el2.remove();
1076
+ onClose?.();
1077
+ };
1078
+ const close = () => {
1079
+ if (currentPopup === dispose) currentPopup = null;
1080
+ dispose();
1081
+ };
1082
+ const onPointer = (e) => {
1083
+ if (!el2.contains(e.target)) close();
1084
+ };
1085
+ const onKey = (e) => {
1086
+ if (e.key === "Escape") {
1087
+ e.preventDefault();
1088
+ close();
1089
+ }
1090
+ };
1091
+ const onScroll = (e) => {
1092
+ if (!el2.contains(e.target)) close();
1093
+ };
1094
+ document.addEventListener("pointerdown", onPointer, true);
1095
+ document.addEventListener("keydown", onKey, true);
1096
+ document.addEventListener("scroll", onScroll, true);
1097
+ currentPopup = dispose;
1098
+ return { close, el: el2 };
1099
+ }
1100
+ function showMenu(entries, at, options = {}) {
1101
+ const labels = { ...DEFAULT_LABELS, ...options.labels ?? {} };
1102
+ const stateOf = () => {
1103
+ try {
1104
+ return options.editor?.state ?? null;
1105
+ } catch {
1106
+ return null;
1107
+ }
1108
+ };
1109
+ const container = document.createElement("div");
1110
+ let handle = null;
1111
+ const evalNow = (fn, fallback) => {
1112
+ try {
1113
+ return fn(stateOf());
1114
+ } catch {
1115
+ return fallback;
1116
+ }
1117
+ };
1118
+ buildMenuEntries(entries, container, {
1119
+ close: () => handle?.close(),
1120
+ labels,
1121
+ editor: options.editor,
1122
+ state: stateOf,
1123
+ check: (el2, active) => {
1124
+ el2.textContent = evalNow(active, false) ? "\u2713" : "";
1125
+ },
1126
+ enable: (el2, enabled) => {
1127
+ el2.disabled = !evalNow(enabled, true);
1128
+ }
1129
+ });
1130
+ handle = showPopup(container, at, options.onClose);
1131
+ return handle;
1132
+ }
953
1133
  function defaultMenus(commands) {
954
1134
  const names = [...commands].map((c) => c.name);
955
1135
  const marks = ["bold", "italic", "underline", "strike"].filter(
@@ -996,94 +1176,15 @@ function mountMenubar(host, editor, options = {}) {
996
1176
  if (focusFirst)
997
1177
  p.dropdown.querySelector(".bb-menu-item")?.focus();
998
1178
  };
999
- const makeRow = (label, opts) => {
1000
- const item = document.createElement("button");
1001
- item.type = "button";
1002
- item.className = "bb-menu-item" + (opts.hasSub ? " bb-has-sub" : "");
1003
- item.addEventListener("mousedown", (e) => e.preventDefault());
1004
- const check = document.createElement("span");
1005
- check.className = "bb-menu-check";
1006
- const text = document.createElement("span");
1007
- text.className = "bb-menu-label";
1008
- text.textContent = label;
1009
- item.append(check, text);
1010
- if (opts.shortcut) {
1011
- const sc = document.createElement("span");
1012
- sc.className = "bb-menu-shortcut";
1013
- sc.textContent = opts.shortcut;
1014
- item.appendChild(sc);
1015
- }
1016
- if (opts.hasSub) {
1017
- const arrow = document.createElement("span");
1018
- arrow.className = "bb-menu-arrow";
1019
- arrow.textContent = "\u203A";
1020
- item.appendChild(arrow);
1021
- }
1022
- return { item, check };
1023
- };
1024
- const buildEntries = (entries, container) => {
1025
- for (const entry of entries) {
1026
- if (entry === "separator") {
1027
- const sep = document.createElement("div");
1028
- sep.className = "bb-menu-sep";
1029
- sep.setAttribute("role", "separator");
1030
- container.appendChild(sep);
1031
- } else if ("submenu" in entry || "widget" in entry) {
1032
- const wrap = document.createElement("div");
1033
- wrap.className = "bb-menu-sub";
1034
- const { item } = makeRow(entry.label, { hasSub: true });
1035
- item.setAttribute("aria-haspopup", "true");
1036
- const flyout = document.createElement("div");
1037
- flyout.className = "bb-menu bb-submenu";
1038
- flyout.setAttribute("role", "menu");
1039
- if ("widget" in entry) {
1040
- flyout.classList.add("bb-submenu-widget");
1041
- const build = () => flyout.replaceChildren(entry.widget(() => close()));
1042
- wrap.addEventListener("mouseenter", build);
1043
- wrap.addEventListener("focusin", build);
1044
- } else {
1045
- buildEntries(entry.submenu, flyout);
1046
- }
1047
- wrap.append(item, flyout);
1048
- container.appendChild(wrap);
1049
- } else if ("command" in entry) {
1050
- const cmd = editor.commands.get(entry.command);
1051
- if (!cmd) continue;
1052
- const { item, check } = makeRow(
1053
- entry.label ?? labels[entry.command] ?? entry.command,
1054
- {}
1055
- );
1056
- item.setAttribute("role", "menuitemcheckbox");
1057
- item.addEventListener("click", () => {
1058
- if (latest)
1059
- editor.commands.get(entry.command)?.run(latest, (tr) => editor.dispatch(tr));
1060
- close();
1061
- editor.focus();
1062
- });
1063
- checks.push({ el: check, active: (s) => cmd.isActive?.(s) ?? false });
1064
- if (cmd.isEnabled)
1065
- enables.push({ el: item, enabled: (s) => cmd.isEnabled(s) });
1066
- container.appendChild(item);
1067
- } else {
1068
- const { item, check } = makeRow(entry.label, {
1069
- shortcut: entry.shortcut
1070
- });
1071
- item.setAttribute(
1072
- "role",
1073
- entry.isActive ? "menuitemcheckbox" : "menuitem"
1074
- );
1075
- item.addEventListener("click", () => {
1076
- entry.run();
1077
- close();
1078
- });
1079
- if (entry.isActive)
1080
- checks.push({ el: check, active: () => entry.isActive() });
1081
- if (entry.isEnabled)
1082
- enables.push({ el: item, enabled: () => entry.isEnabled() });
1083
- container.appendChild(item);
1084
- }
1085
- }
1179
+ const buildCtx = {
1180
+ close: () => close(),
1181
+ labels,
1182
+ editor,
1183
+ state: () => latest,
1184
+ check: (el2, active) => checks.push({ el: el2, active }),
1185
+ enable: (el2, enabled) => enables.push({ el: el2, enabled })
1086
1186
  };
1187
+ const buildEntries = (entries, container) => buildMenuEntries(entries, container, buildCtx);
1087
1188
  menus.forEach((menu, idx) => {
1088
1189
  const wrap = document.createElement("div");
1089
1190
  wrap.className = "bb-menubar-menu";
@@ -1856,6 +1957,7 @@ function fmtCm(cm) {
1856
1957
  }
1857
1958
  var STYLE10 = `
1858
1959
  .bb-ps{display:flex;flex-direction:column;min-width:250px;max-height:min(70vh,460px);overflow-y:auto}
1960
+ .bb-ps,.bb-ps *{box-sizing:border-box}
1859
1961
  .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}
1860
1962
  .bb-ps-row:hover,.bb-ps-row:focus{background:var(--bb-ui-hover,#f1efe8);outline:none}
1861
1963
  .bb-ps-row[aria-checked="true"]{background:var(--bb-ui-active-bg,#e6f1fb)}
@@ -1872,6 +1974,16 @@ var STYLE10 = `
1872
1974
  .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}
1873
1975
  .bb-pd-input:focus{outline:2px solid var(--bb-ui-active-border,#7fb2ec);outline-offset:-1px}
1874
1976
  .bb-pd-actions{display:flex;justify-content:flex-end;gap:8px}
1977
+ .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}
1978
+ .bb-pn-input:focus{outline:2px solid var(--bb-ui-active-border,#7fb2ec);outline-offset:-1px}
1979
+ .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}
1980
+ .bb-pn-check[data-on="true"]{background:var(--bb-ui-active-fg,#0c447c);border-color:var(--bb-ui-active-fg,#0c447c)}
1981
+ .bb-pn-body[data-disabled="true"]{opacity:.35;pointer-events:none}
1982
+ .bb-ps-group{padding:5px 10px 2px;font-size:11px;font-weight:600;letter-spacing:.4px;text-transform:uppercase;opacity:.55}
1983
+ .bb-ps-tiles{display:flex;gap:6px;padding:2px 6px 4px}
1984
+ .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}
1985
+ .bb-ps-tile:hover,.bb-ps-tile:focus{background:var(--bb-ui-hover,#f1efe8);outline:none}
1986
+ .bb-ps-tile[aria-checked="true"]{background:var(--bb-ui-active-bg,#e6f1fb)}
1875
1987
  `;
1876
1988
  var SVG_NS = "http://www.w3.org/2000/svg";
1877
1989
  function svgEl(name, attrs) {
@@ -2158,6 +2270,260 @@ function openMarginsDialog(options) {
2158
2270
  top.input.focus();
2159
2271
  top.input.select();
2160
2272
  }
2273
+ function numberPreview(sample) {
2274
+ const svg = pagePreview(0.773);
2275
+ const t = svgEl("text", {
2276
+ x: 17,
2277
+ y: 25,
2278
+ "text-anchor": "middle",
2279
+ "font-size": 11,
2280
+ fill: "var(--bb-ui-fg,#2c2c2a)",
2281
+ "fill-opacity": 0.75
2282
+ });
2283
+ t.textContent = sample;
2284
+ svg.appendChild(t);
2285
+ return svg;
2286
+ }
2287
+ var PGNUM_FORMATS = [
2288
+ [void 0, "1, 2, 3, 4\u2026", "1"],
2289
+ ["lowerRoman", "i, ii, iii, iv\u2026", "i"],
2290
+ ["upperRoman", "I, II, III, IV\u2026", "I"],
2291
+ ["lowerLetter", "a, b, c, d\u2026", "a"],
2292
+ ["upperLetter", "A, B, C, D\u2026", "A"]
2293
+ ];
2294
+ function pageNumberPicker(options) {
2295
+ injectStyle("bb-ui-pagesetup-styles", STYLE10);
2296
+ const root = document.createElement("div");
2297
+ root.className = "bb-ps";
2298
+ root.setAttribute("role", "menu");
2299
+ let body = root;
2300
+ if (options.onToggleShown) {
2301
+ const on = options.shown !== false;
2302
+ const row = document.createElement("button");
2303
+ row.type = "button";
2304
+ row.className = "bb-ps-row";
2305
+ row.setAttribute("role", "menuitemcheckbox");
2306
+ row.setAttribute("aria-checked", String(on));
2307
+ const box = document.createElement("span");
2308
+ box.className = "bb-pn-check";
2309
+ box.dataset["on"] = String(on);
2310
+ box.textContent = on ? "\u2713" : "";
2311
+ const name = document.createElement("span");
2312
+ name.className = "bb-ps-name";
2313
+ name.textContent = options.labels?.shown ?? "Show page numbers";
2314
+ row.append(box, name);
2315
+ row.addEventListener("mousedown", (e) => e.preventDefault());
2316
+ row.addEventListener("click", () => options.onToggleShown?.(!on));
2317
+ root.appendChild(row);
2318
+ const sep0 = document.createElement("div");
2319
+ sep0.className = "bb-ps-sep";
2320
+ root.appendChild(sep0);
2321
+ body = document.createElement("div");
2322
+ body.className = "bb-pn-body";
2323
+ if (!on) body.dataset["disabled"] = "true";
2324
+ root.appendChild(body);
2325
+ }
2326
+ const curFmt = options.fmt === "decimal" ? void 0 : options.fmt;
2327
+ const emit = (fmt, start) => {
2328
+ options.onPick(
2329
+ fmt == null && start == null ? null : {
2330
+ ...fmt != null ? { fmt } : {},
2331
+ ...start != null ? { start } : {}
2332
+ }
2333
+ );
2334
+ };
2335
+ for (const [key, label, sample] of PGNUM_FORMATS) {
2336
+ body.appendChild(
2337
+ presetRow(
2338
+ numberPreview(sample),
2339
+ label,
2340
+ captionLine(""),
2341
+ curFmt === key,
2342
+ () => emit(key, options.start)
2343
+ )
2344
+ );
2345
+ }
2346
+ const sep = document.createElement("div");
2347
+ sep.className = "bb-ps-sep";
2348
+ root.appendChild(sep);
2349
+ const restart = document.createElement("div");
2350
+ restart.className = "bb-ps-row";
2351
+ restart.setAttribute("role", "menuitemradio");
2352
+ restart.setAttribute("aria-checked", String(options.start != null));
2353
+ const restartName = document.createElement("span");
2354
+ restartName.className = "bb-ps-name";
2355
+ restartName.style.flex = "1 1 auto";
2356
+ restartName.textContent = options.labels?.restart ?? "Restart at";
2357
+ const input = document.createElement("input");
2358
+ input.type = "number";
2359
+ input.min = "0";
2360
+ input.step = "1";
2361
+ input.className = "bb-pn-input";
2362
+ input.value = String(options.start ?? 1);
2363
+ const readStart = () => {
2364
+ const v = Math.floor(Number(input.value));
2365
+ return Number.isFinite(v) && v >= 0 && input.value.trim() !== "" ? v : options.start ?? 1;
2366
+ };
2367
+ restart.append(restartName, input);
2368
+ restart.addEventListener("mousedown", (e) => {
2369
+ if (e.target !== input) e.preventDefault();
2370
+ });
2371
+ restart.addEventListener("click", (e) => {
2372
+ if (e.target !== input) emit(curFmt, readStart());
2373
+ });
2374
+ input.addEventListener("keydown", (e) => {
2375
+ if (e.key === "Enter") {
2376
+ e.preventDefault();
2377
+ emit(curFmt, readStart());
2378
+ }
2379
+ });
2380
+ input.addEventListener("wheel", (e) => e.preventDefault(), {
2381
+ passive: false
2382
+ });
2383
+ body.appendChild(restart);
2384
+ body.appendChild(
2385
+ presetRow(
2386
+ numberPreview("\u2192"),
2387
+ options.labels?.continueFrom ?? "Continue from previous section",
2388
+ captionLine(options.continueHint ?? ""),
2389
+ options.start == null,
2390
+ () => emit(curFmt, void 0)
2391
+ )
2392
+ );
2393
+ return root;
2394
+ }
2395
+ function sectionPaperPanel(options) {
2396
+ injectStyle("bb-ui-pagesetup-styles", STYLE10);
2397
+ const root = document.createElement("div");
2398
+ root.className = "bb-ps";
2399
+ root.setAttribute("role", "menu");
2400
+ const group = (text) => {
2401
+ const el2 = document.createElement("div");
2402
+ el2.className = "bb-ps-group";
2403
+ el2.textContent = text;
2404
+ return el2;
2405
+ };
2406
+ const sep = () => {
2407
+ const el2 = document.createElement("div");
2408
+ el2.className = "bb-ps-sep";
2409
+ return el2;
2410
+ };
2411
+ root.appendChild(group(options.labels?.orientation ?? "Orientation"));
2412
+ const tiles = document.createElement("div");
2413
+ tiles.className = "bb-ps-tiles";
2414
+ const landscapeNow = options.page.width > options.page.height;
2415
+ const short = Math.min(options.page.width, options.page.height);
2416
+ const long = Math.max(options.page.width, options.page.height);
2417
+ for (const [key, label, ratio] of [
2418
+ ["portrait", "Portrait", short / long],
2419
+ ["landscape", "Landscape", long / short]
2420
+ ]) {
2421
+ const tile = document.createElement("button");
2422
+ tile.type = "button";
2423
+ tile.className = "bb-ps-tile";
2424
+ tile.setAttribute("role", "menuitemradio");
2425
+ tile.setAttribute(
2426
+ "aria-checked",
2427
+ String(landscapeNow === (key === "landscape"))
2428
+ );
2429
+ const icon = pagePreview(ratio);
2430
+ icon.setAttribute("style", "width:26px;height:32px");
2431
+ const name = document.createElement("span");
2432
+ name.textContent = label;
2433
+ tile.append(icon, name);
2434
+ tile.addEventListener("mousedown", (e) => e.preventDefault());
2435
+ tile.addEventListener("click", () => options.onOrientation(key));
2436
+ tiles.appendChild(tile);
2437
+ }
2438
+ root.appendChild(tiles);
2439
+ root.appendChild(sep());
2440
+ root.appendChild(group(options.labels?.pageSize ?? "Page size"));
2441
+ for (const item of options.items) {
2442
+ root.appendChild(
2443
+ presetRow(
2444
+ pagePreview(item.px[0] / item.px[1]),
2445
+ item.label,
2446
+ captionLine(`${fmtCm(item.cm[0])} x ${fmtCm(item.cm[1])}`),
2447
+ !!item.active,
2448
+ () => options.onPick(item.key)
2449
+ )
2450
+ );
2451
+ }
2452
+ root.appendChild(sep());
2453
+ root.appendChild(
2454
+ customRow(
2455
+ pagePreview(0.773),
2456
+ options.labels?.custom ?? "Custom page size",
2457
+ "Define custom page size",
2458
+ options.onCustom
2459
+ )
2460
+ );
2461
+ return root;
2462
+ }
2463
+
2464
+ // packages/ui/src/lib/section-chip.ts
2465
+ var STYLE11 = `
2466
+ .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)}
2467
+ .bb-secchip *{box-sizing:border-box}
2468
+ .bb-secchip-title{padding:0 7px;font-size:11px;font-weight:600;opacity:.8}
2469
+ .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}
2470
+ .bb-secchip-seg:hover,.bb-secchip-seg[aria-expanded="true"]{background:var(--bb-ui-hover,#f1efe8)}
2471
+ .bb-secchip-caret{font-size:8px;opacity:.55}
2472
+ .bb-secchip-seg[data-muted="true"] .bb-secchip-seglabel{font-style:italic;opacity:.55}
2473
+ .bb-secchip-div{flex:none;width:1px;height:11px;margin:0 2px;background:var(--bb-ui-border,#e3e3e0)}
2474
+ .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}
2475
+ .bb-secchip-x:hover{background:var(--bb-ui-hover,#f1efe8);opacity:1}
2476
+ `;
2477
+ function createSectionChip(options) {
2478
+ injectStyle("bb-ui-section-chip-styles", STYLE11);
2479
+ const el2 = document.createElement("div");
2480
+ el2.className = "bb-secchip";
2481
+ const title = document.createElement("span");
2482
+ title.className = "bb-secchip-title";
2483
+ title.textContent = options.title;
2484
+ const divider = () => {
2485
+ const d = document.createElement("span");
2486
+ d.className = "bb-secchip-div";
2487
+ return d;
2488
+ };
2489
+ const segment = (aria, onOpen) => {
2490
+ const btn = document.createElement("button");
2491
+ btn.type = "button";
2492
+ btn.className = "bb-secchip-seg";
2493
+ btn.setAttribute("aria-haspopup", "true");
2494
+ if (aria) btn.setAttribute("aria-label", aria);
2495
+ const label = document.createElement("span");
2496
+ label.className = "bb-secchip-seglabel";
2497
+ const caret = document.createElement("span");
2498
+ caret.className = "bb-secchip-caret";
2499
+ caret.textContent = "\u25BE";
2500
+ btn.append(label, caret);
2501
+ btn.addEventListener("mousedown", (e) => e.preventDefault());
2502
+ btn.addEventListener("click", () => onOpen(btn));
2503
+ return { btn, label };
2504
+ };
2505
+ const nums = segment(options.ariaPageNumbers, options.onPageNumbers);
2506
+ const paper = segment(options.ariaPaper, options.onPaper);
2507
+ const x = document.createElement("button");
2508
+ x.type = "button";
2509
+ x.className = "bb-secchip-x";
2510
+ x.setAttribute("aria-label", options.ariaDelete ?? "Remove section break");
2511
+ 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>';
2512
+ x.addEventListener("mousedown", (e) => e.preventDefault());
2513
+ x.addEventListener("click", () => options.onDelete());
2514
+ el2.append(title, divider(), nums.btn, divider(), paper.btn, divider(), x);
2515
+ return {
2516
+ el: el2,
2517
+ update(data) {
2518
+ nums.label.textContent = data.pageNumbers;
2519
+ nums.btn.dataset["muted"] = String(!!data.pageNumbersMuted);
2520
+ paper.label.textContent = data.paper;
2521
+ },
2522
+ destroy() {
2523
+ el2.remove();
2524
+ }
2525
+ };
2526
+ }
2161
2527
 
2162
2528
  // packages/ui/src/lib/font-dialog.ts
2163
2529
  var twipsToPt = (tw) => tw / 20;
@@ -2166,7 +2532,7 @@ var halfToPt = (hp) => hp / 2;
2166
2532
  var ptToHalf = (pt) => Math.round(pt * 2);
2167
2533
  var SCALE_PRESETS = [200, 150, 100, 90, 80, 66, 50, 33];
2168
2534
  var SUPERSUB_SCALE = 0.66;
2169
- var STYLE11 = `
2535
+ var STYLE12 = `
2170
2536
  .bb-fd{display:flex;flex-direction:column;gap:15px;min-width:396px;max-width:430px;color:var(--bb-ui-fg,#2c2c2a)}
2171
2537
  .bb-fd *{box-sizing:border-box}
2172
2538
  /* A segmented control, not a "tab joined to its pane": that pattern needs the
@@ -2248,7 +2614,7 @@ function openFontDialog({
2248
2614
  sizes,
2249
2615
  onApply
2250
2616
  }) {
2251
- injectStyle("bb-font-dialog", STYLE11);
2617
+ injectStyle("bb-font-dialog", STYLE12);
2252
2618
  const dialog = new Dialog({ title: "Font", modal: true });
2253
2619
  const root = el("div", "bb-fd");
2254
2620
  const tabs = el("div", "bb-fd-tabs");
@@ -2494,6 +2860,7 @@ function openFontDialog({
2494
2860
  cmToPx,
2495
2861
  colorButton,
2496
2862
  createFindDialog,
2863
+ createSectionChip,
2497
2864
  defaultMenus,
2498
2865
  defaultToolbarGroups,
2499
2866
  marginPresetPicker,
@@ -2505,10 +2872,14 @@ function openFontDialog({
2505
2872
  openMarginsDialog,
2506
2873
  openPageSizeDialog,
2507
2874
  orientationPicker,
2875
+ pageNumberPicker,
2508
2876
  pageSizePicker,
2509
2877
  promptDialog,
2510
2878
  pxToCm,
2879
+ sectionPaperPanel,
2511
2880
  showContextMenu,
2512
2881
  showLinkPanel,
2882
+ showMenu,
2883
+ showPopup,
2513
2884
  tableGridPicker
2514
2885
  });
package/dist/index.d.ts CHANGED
@@ -8,6 +8,7 @@ export * from './lib/link-panel.js';
8
8
  export * from './lib/cell-properties.js';
9
9
  export * from './lib/table-grid.js';
10
10
  export * from './lib/page-setup.js';
11
+ export * from './lib/section-chip.js';
11
12
  export * from './lib/font-dialog.js';
12
13
  export * from './lib/color-picker.js';
13
14
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AACrE,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,eAAe,CAAC;AAC9B,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,0BAA0B,CAAC;AACzC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AACrE,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,eAAe,CAAC;AAC9B,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,0BAA0B,CAAC;AACzC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC"}