@shadow-garden/bapbong-ui 0.15.0 → 0.17.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 +748 -116
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +742 -110
- package/dist/lib/equation-gallery.d.ts +44 -0
- package/dist/lib/equation-gallery.d.ts.map +1 -0
- package/dist/lib/equation-panel.d.ts +30 -0
- package/dist/lib/equation-panel.d.ts.map +1 -0
- package/dist/lib/font-dialog.d.ts.map +1 -1
- package/dist/lib/internal.d.ts +8 -0
- package/dist/lib/internal.d.ts.map +1 -1
- package/dist/lib/link-panel.d.ts.map +1 -1
- package/dist/lib/table-style-panel.d.ts +45 -0
- package/dist/lib/table-style-panel.d.ts.map +1 -0
- package/dist/lib/toolbar.d.ts +42 -1
- package/dist/lib/toolbar.d.ts.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -20,6 +20,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// packages/ui/src/index.ts
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
|
+
BUILT_IN_EQUATIONS: () => BUILT_IN_EQUATIONS,
|
|
23
24
|
COLOR_PALETTE: () => COLOR_PALETTE,
|
|
24
25
|
Dialog: () => Dialog,
|
|
25
26
|
RECENT_MAX: () => RECENT_MAX,
|
|
@@ -32,8 +33,13 @@ __export(index_exports, {
|
|
|
32
33
|
createFindDialog: () => createFindDialog,
|
|
33
34
|
createSectionChip: () => createSectionChip,
|
|
34
35
|
createSymbolDialog: () => createSymbolDialog,
|
|
36
|
+
createTableStylePanel: () => createTableStylePanel,
|
|
35
37
|
defaultMenus: () => defaultMenus,
|
|
36
38
|
defaultToolbarGroups: () => defaultToolbarGroups,
|
|
39
|
+
equationGallery: () => equationGallery,
|
|
40
|
+
equationPanel: () => equationPanel,
|
|
41
|
+
equationPreviewSvg: () => equationPreviewSvg,
|
|
42
|
+
foldPlan: () => foldPlan,
|
|
37
43
|
installScrollbars: () => installScrollbars,
|
|
38
44
|
marginPresetPicker: () => marginPresetPicker,
|
|
39
45
|
mountMenubar: () => mountMenubar,
|
|
@@ -74,6 +80,13 @@ function shortcutLabel(command, registries) {
|
|
|
74
80
|
}
|
|
75
81
|
return void 0;
|
|
76
82
|
}
|
|
83
|
+
var TABS_CSS = `
|
|
84
|
+
.bb-tabs{display:inline-flex;align-self:flex-start;border:0.5px solid var(--bb-ui-control-border,var(--bb-ui-border,#d8d6cf));border-radius:6px;overflow:hidden}
|
|
85
|
+
.bb-tab{height:30px;padding:0 18px;border:0;border-right:0.5px solid var(--bb-ui-border,#e3e3e0);background:transparent;color:inherit;opacity:.65;font:inherit;font-size:13px;cursor:pointer}
|
|
86
|
+
.bb-tab:last-child{border-right:0}
|
|
87
|
+
.bb-tab:hover{background:var(--bb-ui-hover,#f1efe8);opacity:.9}
|
|
88
|
+
.bb-tab[aria-selected="true"]{background:var(--bb-ui-active-bg,#e6f1fb);color:var(--bb-ui-active-fg,#0c447c);opacity:1}
|
|
89
|
+
`;
|
|
77
90
|
function injectStyle(id, css) {
|
|
78
91
|
if (document.getElementById(id)) return;
|
|
79
92
|
const el5 = document.createElement("style");
|
|
@@ -97,12 +110,12 @@ function placeFloating(el5, anchor) {
|
|
|
97
110
|
}
|
|
98
111
|
function rovingGrid(cells) {
|
|
99
112
|
let cur = [0, 0];
|
|
100
|
-
const at = (r,
|
|
101
|
-
const focusCell = (r,
|
|
113
|
+
const at = (r, c2) => cells[r]?.[c2];
|
|
114
|
+
const focusCell = (r, c2) => {
|
|
102
115
|
const rows = cells.length;
|
|
103
116
|
if (rows === 0) return;
|
|
104
117
|
const nr = Math.min(rows - 1, Math.max(0, r));
|
|
105
|
-
const nc = Math.min(cells[nr].length - 1, Math.max(0,
|
|
118
|
+
const nc = Math.min(cells[nr].length - 1, Math.max(0, c2));
|
|
106
119
|
const prev = at(cur[0], cur[1]);
|
|
107
120
|
if (prev) prev.tabIndex = -1;
|
|
108
121
|
const next = at(nr, nc);
|
|
@@ -112,9 +125,9 @@ function rovingGrid(cells) {
|
|
|
112
125
|
cur = [nr, nc];
|
|
113
126
|
};
|
|
114
127
|
cells.forEach(
|
|
115
|
-
(row, r) => row.forEach((cell,
|
|
128
|
+
(row, r) => row.forEach((cell, c2) => {
|
|
116
129
|
cell.setAttribute("role", "gridcell");
|
|
117
|
-
cell.tabIndex = r === 0 &&
|
|
130
|
+
cell.tabIndex = r === 0 && c2 === 0 ? 0 : -1;
|
|
118
131
|
cell.addEventListener("keydown", (e) => {
|
|
119
132
|
const delta = {
|
|
120
133
|
ArrowRight: [0, 1],
|
|
@@ -127,10 +140,10 @@ function rovingGrid(cells) {
|
|
|
127
140
|
const d = delta[e.key];
|
|
128
141
|
if (!d) return;
|
|
129
142
|
e.preventDefault();
|
|
130
|
-
focusCell(r + d[0],
|
|
143
|
+
focusCell(r + d[0], c2 + d[1]);
|
|
131
144
|
});
|
|
132
145
|
cell.addEventListener("focus", () => {
|
|
133
|
-
cur = [r,
|
|
146
|
+
cur = [r, c2];
|
|
134
147
|
});
|
|
135
148
|
})
|
|
136
149
|
);
|
|
@@ -460,9 +473,9 @@ function openColorPicker({
|
|
|
460
473
|
panel.remove();
|
|
461
474
|
anchor.focus();
|
|
462
475
|
};
|
|
463
|
-
const pick = (
|
|
464
|
-
if (
|
|
465
|
-
onPick(
|
|
476
|
+
const pick = (c2) => {
|
|
477
|
+
if (c2 && !COLOR_PALETTE.some((row) => row.includes(c2))) remember(c2);
|
|
478
|
+
onPick(c2);
|
|
466
479
|
close();
|
|
467
480
|
};
|
|
468
481
|
if (clearLabel !== void 0) {
|
|
@@ -506,15 +519,15 @@ function openColorPicker({
|
|
|
506
519
|
);
|
|
507
520
|
const customRow2 = document.createElement("div");
|
|
508
521
|
customRow2.className = "bb-cpk-row";
|
|
509
|
-
for (const
|
|
522
|
+
for (const c2 of customColors) {
|
|
510
523
|
const sw = document.createElement("button");
|
|
511
524
|
sw.type = "button";
|
|
512
525
|
sw.className = "bb-cpk-sw";
|
|
513
|
-
sw.style.background =
|
|
514
|
-
sw.title =
|
|
515
|
-
sw.setAttribute("aria-label",
|
|
516
|
-
if (
|
|
517
|
-
sw.addEventListener("click", () => pick(
|
|
526
|
+
sw.style.background = c2;
|
|
527
|
+
sw.title = c2;
|
|
528
|
+
sw.setAttribute("aria-label", c2);
|
|
529
|
+
if (c2.toUpperCase() === value?.toUpperCase()) sw.classList.add("on");
|
|
530
|
+
sw.addEventListener("click", () => pick(c2));
|
|
518
531
|
customRow2.append(sw);
|
|
519
532
|
}
|
|
520
533
|
const plus = document.createElement("button");
|
|
@@ -598,8 +611,8 @@ function colorButton(o) {
|
|
|
598
611
|
anchor: el5,
|
|
599
612
|
value: o.value(),
|
|
600
613
|
clearLabel: o.clearLabel,
|
|
601
|
-
onPick: (
|
|
602
|
-
o.onPick(
|
|
614
|
+
onPick: (c2) => {
|
|
615
|
+
o.onPick(c2);
|
|
603
616
|
sync();
|
|
604
617
|
}
|
|
605
618
|
});
|
|
@@ -683,6 +696,7 @@ var STYLE3 = `
|
|
|
683
696
|
.bb-toolbar{display:flex;gap:10px;align-items:center;flex-wrap:nowrap;overflow:hidden;padding:6px 8px;font-family:var(--bb-ui-font,system-ui,-apple-system,sans-serif);color:var(--bb-ui-fg,#2c2c2a);background:var(--bb-ui-control-bg,var(--bb-ui-bg,#fff));border-bottom:1px solid var(--bb-ui-border,#e3e3e0);box-sizing:border-box}
|
|
684
697
|
.bb-toolbar *{box-sizing:border-box}
|
|
685
698
|
.bb-toolbar-group{display:flex;gap:2px;flex:none}
|
|
699
|
+
.bb-toolbar-group[hidden]{display:none}
|
|
686
700
|
.bb-toolbar-group+.bb-toolbar-group{padding-left:10px;border-left:1px solid var(--bb-ui-border,#e3e3e0)}
|
|
687
701
|
.bb-toolbar-more{margin-left:auto;flex:none}
|
|
688
702
|
.bb-toolbar-pop{position:absolute;z-index:1200;top:100%;left:0;right:0;margin-top:4px;display:flex;flex-wrap:wrap;gap:10px;row-gap:6px;align-items:center;padding:6px 8px;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;box-shadow:0 8px 28px rgba(0,0,0,.16);font-family:var(--bb-ui-font,system-ui,-apple-system,sans-serif);color:var(--bb-ui-fg,#2c2c2a)}
|
|
@@ -691,6 +705,9 @@ var STYLE3 = `
|
|
|
691
705
|
.bb-toolbar-btn:hover{background:var(--bb-ui-hover,#f1efe8)}
|
|
692
706
|
.bb-toolbar-btn.is-active{background:var(--bb-ui-active-bg,#e6f1fb);color:var(--bb-ui-active-fg,#0c447c);border-color:var(--bb-ui-active-border,#b5d4f4)}
|
|
693
707
|
.bb-toolbar-btn:disabled{opacity:.38;cursor:default}
|
|
708
|
+
.bb-toolbar-btn.bb-btn-accent{gap:5px;padding:0 9px;font-size:12.5px;white-space:nowrap;background:var(--bb-ui-active-bg,#e6f1fb);color:var(--bb-ui-active-fg,#0c447c);border-color:var(--bb-ui-active-border,#b5d4f4)}
|
|
709
|
+
.bb-toolbar-btn.bb-btn-accent:hover{background:var(--bb-ui-active-bg,#e6f1fb);border-color:var(--bb-ui-active-fg,#0c447c)}
|
|
710
|
+
.bb-btn-caret{font-size:9px;opacity:.7;line-height:1}
|
|
694
711
|
.bb-toolbar-select{height:30px;border:1px solid var(--bb-ui-control-border,var(--bb-ui-border,#e3e3e0));border-radius:6px;background:var(--bb-ui-control-bg,var(--bb-ui-bg,#fff));color:inherit;font-family:inherit;font-size:13px;padding:0 6px;cursor:pointer}
|
|
695
712
|
.bb-toolbar-select:hover{background:var(--bb-ui-hover,#f1efe8)}
|
|
696
713
|
.bb-i-bold{font-weight:700}.bb-i-italic{font-style:italic}.bb-i-underline{text-decoration:underline}.bb-i-strike{text-decoration:line-through}
|
|
@@ -710,11 +727,30 @@ var STYLE3 = `
|
|
|
710
727
|
.bb-split-bar{flex:1;height:3px;border-radius:2px;background:var(--bb-ui-border,#d9d9d4)}
|
|
711
728
|
`;
|
|
712
729
|
function defaultToolbarGroups(commands) {
|
|
713
|
-
const names = [...commands].map((
|
|
730
|
+
const names = [...commands].map((c2) => c2.name);
|
|
714
731
|
const aligns = names.filter((n) => n.startsWith("align-"));
|
|
715
732
|
const rest = names.filter((n) => !n.startsWith("align-"));
|
|
716
733
|
return [rest, aligns].filter((g2) => g2.length > 0);
|
|
717
734
|
}
|
|
735
|
+
function foldPlan(candidates, avail, moreWidth, gap) {
|
|
736
|
+
const vis = candidates.filter((c2) => !c2.hidden);
|
|
737
|
+
const rowWidth = vis.reduce((sum, c2) => sum + c2.width, 0) + gap * Math.max(0, vis.length - 1);
|
|
738
|
+
const folded = /* @__PURE__ */ new Set();
|
|
739
|
+
if (rowWidth <= avail + 1) return folded;
|
|
740
|
+
const order = [
|
|
741
|
+
...vis.filter((c2) => !c2.sticky).reverse(),
|
|
742
|
+
...vis.filter((c2) => c2.sticky).reverse()
|
|
743
|
+
];
|
|
744
|
+
const fitsRemaining = () => {
|
|
745
|
+
const rem = vis.filter((c2) => !folded.has(c2.idx));
|
|
746
|
+
return rem.reduce((sum, c2) => sum + c2.width, 0) + gap * rem.length + moreWidth <= avail + 1;
|
|
747
|
+
};
|
|
748
|
+
for (const c2 of order) {
|
|
749
|
+
if (fitsRemaining()) break;
|
|
750
|
+
folded.add(c2.idx);
|
|
751
|
+
}
|
|
752
|
+
return folded;
|
|
753
|
+
}
|
|
718
754
|
function mountToolbar(host, editor, options = {}) {
|
|
719
755
|
injectStyle("bb-ui-toolbar-styles", STYLE3);
|
|
720
756
|
const items = { ...DEFAULT_ITEMS, ...options.items ?? {} };
|
|
@@ -725,17 +761,25 @@ function mountToolbar(host, editor, options = {}) {
|
|
|
725
761
|
root.className = "bb-toolbar";
|
|
726
762
|
root.setAttribute("role", "toolbar");
|
|
727
763
|
const buttons = [];
|
|
764
|
+
const groupList = [];
|
|
765
|
+
const conditionalGroups = [];
|
|
728
766
|
const selects = [];
|
|
729
767
|
const colors = [];
|
|
730
768
|
const splits = [];
|
|
731
769
|
let latest = null;
|
|
732
770
|
for (const group of groups) {
|
|
733
|
-
const
|
|
771
|
+
const spec = Array.isArray(group) ? { entries: group } : group;
|
|
772
|
+
const entries = spec.entries.filter(
|
|
734
773
|
(e) => typeof e !== "string" || editor.commands.has(e)
|
|
735
774
|
);
|
|
736
775
|
if (entries.length === 0) continue;
|
|
737
776
|
const groupEl = document.createElement("div");
|
|
738
777
|
groupEl.className = "bb-toolbar-group";
|
|
778
|
+
groupList.push({ el: groupEl, sticky: !!spec.sticky, lastWidth: 0 });
|
|
779
|
+
if (spec.visible) {
|
|
780
|
+
conditionalGroups.push({ el: groupEl, visible: spec.visible });
|
|
781
|
+
groupEl.hidden = true;
|
|
782
|
+
}
|
|
739
783
|
for (const entry of entries) {
|
|
740
784
|
if (typeof entry !== "string" && entry.kind === "select") {
|
|
741
785
|
const sel = document.createElement("select");
|
|
@@ -761,12 +805,24 @@ function mountToolbar(host, editor, options = {}) {
|
|
|
761
805
|
if (typeof entry !== "string" && entry.kind === "button") {
|
|
762
806
|
const btn2 = document.createElement("button");
|
|
763
807
|
btn2.type = "button";
|
|
764
|
-
btn2.className = "bb-toolbar-btn";
|
|
808
|
+
btn2.className = "bb-toolbar-btn" + (entry.accent ? " bb-btn-accent" : "");
|
|
765
809
|
btn2.title = entry.title;
|
|
766
810
|
btn2.setAttribute("aria-label", entry.title);
|
|
767
811
|
btn2.setAttribute("aria-haspopup", "dialog");
|
|
768
812
|
if (entry.svg) btn2.innerHTML = entry.svg;
|
|
769
813
|
else btn2.textContent = entry.label ?? entry.title;
|
|
814
|
+
if (entry.text) {
|
|
815
|
+
const span = document.createElement("span");
|
|
816
|
+
span.textContent = entry.text;
|
|
817
|
+
btn2.appendChild(span);
|
|
818
|
+
}
|
|
819
|
+
if (entry.caret) {
|
|
820
|
+
const caret = document.createElement("span");
|
|
821
|
+
caret.className = "bb-btn-caret";
|
|
822
|
+
caret.setAttribute("aria-hidden", "true");
|
|
823
|
+
caret.textContent = "\u25BE";
|
|
824
|
+
btn2.appendChild(caret);
|
|
825
|
+
}
|
|
770
826
|
btn2.addEventListener("mousedown", (e) => e.preventDefault());
|
|
771
827
|
btn2.addEventListener("click", () => entry.onClick(btn2));
|
|
772
828
|
groupEl.appendChild(btn2);
|
|
@@ -927,19 +983,52 @@ function mountToolbar(host, editor, options = {}) {
|
|
|
927
983
|
pop.hidden = !pop.hidden;
|
|
928
984
|
moreBtn.setAttribute("aria-expanded", String(!pop.hidden));
|
|
929
985
|
});
|
|
930
|
-
|
|
986
|
+
let gapPx = -1;
|
|
987
|
+
let moreW = -1;
|
|
988
|
+
const anchorIn = (container, idx) => {
|
|
989
|
+
for (let j = idx + 1; j < groupList.length; j++)
|
|
990
|
+
if (groupList[j].el.parentElement === container) return groupList[j].el;
|
|
991
|
+
return container === root ? moreBtn : null;
|
|
992
|
+
};
|
|
931
993
|
const layout = () => {
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
994
|
+
if (gapPx < 0)
|
|
995
|
+
gapPx = Number.parseFloat(getComputedStyle(root).columnGap) || 0;
|
|
996
|
+
if (moreW < 0) {
|
|
997
|
+
moreBtn.style.visibility = "hidden";
|
|
998
|
+
const prev = moreBtn.style.display;
|
|
999
|
+
moreBtn.style.display = "";
|
|
1000
|
+
moreW = moreBtn.offsetWidth;
|
|
1001
|
+
moreBtn.style.display = prev;
|
|
1002
|
+
moreBtn.style.visibility = "";
|
|
1003
|
+
}
|
|
1004
|
+
const avail = root.clientWidth;
|
|
1005
|
+
const candidates = groupList.map((g2, idx) => {
|
|
1006
|
+
const w = g2.el.offsetWidth;
|
|
1007
|
+
if (w > 0) g2.lastWidth = w;
|
|
1008
|
+
return {
|
|
1009
|
+
idx,
|
|
1010
|
+
width: g2.lastWidth,
|
|
1011
|
+
sticky: g2.sticky,
|
|
1012
|
+
hidden: g2.el.hidden
|
|
1013
|
+
};
|
|
1014
|
+
});
|
|
1015
|
+
const folded = foldPlan(candidates, avail, moreW, gapPx);
|
|
1016
|
+
let moved = false;
|
|
1017
|
+
groupList.forEach((g2, idx) => {
|
|
1018
|
+
const inPop = g2.el.parentElement === pop;
|
|
1019
|
+
const should = folded.has(idx);
|
|
1020
|
+
if (inPop === should) return;
|
|
1021
|
+
moved = true;
|
|
1022
|
+
if (should) pop.insertBefore(g2.el, anchorIn(pop, idx));
|
|
1023
|
+
else root.insertBefore(g2.el, anchorIn(root, idx));
|
|
1024
|
+
});
|
|
1025
|
+
const showMore = folded.size > 0;
|
|
1026
|
+
if (moreBtn.style.display !== "none" !== showMore)
|
|
1027
|
+
moreBtn.style.display = showMore ? "" : "none";
|
|
1028
|
+
if (!showMore) closePop();
|
|
1029
|
+
if (moved) {
|
|
1030
|
+
closePop();
|
|
1031
|
+
wrap.querySelectorAll(".bb-split-pop").forEach((p) => p.hidden = true);
|
|
943
1032
|
}
|
|
944
1033
|
};
|
|
945
1034
|
let ro = null;
|
|
@@ -951,6 +1040,15 @@ function mountToolbar(host, editor, options = {}) {
|
|
|
951
1040
|
layout();
|
|
952
1041
|
const refresh = (state) => {
|
|
953
1042
|
latest = state;
|
|
1043
|
+
let visibilityChanged = false;
|
|
1044
|
+
for (const g2 of conditionalGroups) {
|
|
1045
|
+
const show = g2.visible(state);
|
|
1046
|
+
if (show === g2.el.hidden) {
|
|
1047
|
+
g2.el.hidden = !show;
|
|
1048
|
+
visibilityChanged = true;
|
|
1049
|
+
}
|
|
1050
|
+
}
|
|
1051
|
+
if (visibilityChanged) layout();
|
|
954
1052
|
for (const { name, el: el5 } of buttons) {
|
|
955
1053
|
const cmd = editor.commands.get(name);
|
|
956
1054
|
if (!cmd) continue;
|
|
@@ -960,7 +1058,7 @@ function mountToolbar(host, editor, options = {}) {
|
|
|
960
1058
|
el5.disabled = cmd.isEnabled ? !cmd.isEnabled(state) : false;
|
|
961
1059
|
}
|
|
962
1060
|
for (const { spec, el: el5 } of selects) el5.value = spec.value(state);
|
|
963
|
-
for (const
|
|
1061
|
+
for (const c2 of colors) c2.sync();
|
|
964
1062
|
for (const { spec, cards } of splits) {
|
|
965
1063
|
const selected = spec.value(state);
|
|
966
1064
|
for (const card of cards)
|
|
@@ -970,7 +1068,7 @@ function mountToolbar(host, editor, options = {}) {
|
|
|
970
1068
|
);
|
|
971
1069
|
}
|
|
972
1070
|
};
|
|
973
|
-
const off = editor.onChange((
|
|
1071
|
+
const off = editor.onChange((c2) => refresh(c2.state));
|
|
974
1072
|
try {
|
|
975
1073
|
refresh(editor.state);
|
|
976
1074
|
} catch {
|
|
@@ -1214,7 +1312,7 @@ function showMenu(entries, at, options = {}) {
|
|
|
1214
1312
|
return handle;
|
|
1215
1313
|
}
|
|
1216
1314
|
function defaultMenus(commands) {
|
|
1217
|
-
const names = [...commands].map((
|
|
1315
|
+
const names = [...commands].map((c2) => c2.name);
|
|
1218
1316
|
const marks = ["bold", "italic", "underline", "strike"].filter(
|
|
1219
1317
|
(n) => commands.has(n)
|
|
1220
1318
|
);
|
|
@@ -1328,10 +1426,10 @@ function mountMenubar(host, editor, options = {}) {
|
|
|
1328
1426
|
function refresh(state) {
|
|
1329
1427
|
latest = state;
|
|
1330
1428
|
if (openIdx < 0) return;
|
|
1331
|
-
for (const
|
|
1429
|
+
for (const c2 of checks) c2.el.textContent = c2.active(state) ? "\u2713" : "";
|
|
1332
1430
|
for (const e of enables) e.el.disabled = !e.enabled(state);
|
|
1333
1431
|
}
|
|
1334
|
-
const off = editor.onChange((
|
|
1432
|
+
const off = editor.onChange((c2) => refresh(c2.state));
|
|
1335
1433
|
try {
|
|
1336
1434
|
latest = editor.state;
|
|
1337
1435
|
} catch {
|
|
@@ -1659,13 +1757,13 @@ function showLinkPanel(opts) {
|
|
|
1659
1757
|
row.appendChild(icon);
|
|
1660
1758
|
const label = document.createElement("span");
|
|
1661
1759
|
label.className = "bb-linkpanel-href";
|
|
1662
|
-
label.textContent = internal.label ?? "
|
|
1760
|
+
label.textContent = internal.label ?? "This place is no longer in the document";
|
|
1663
1761
|
label.title = internal.label ?? existing.href;
|
|
1664
1762
|
if (!internal.label) label.classList.add("bb-linkpanel-stale");
|
|
1665
1763
|
row.appendChild(label);
|
|
1666
1764
|
if (internal.label) {
|
|
1667
1765
|
row.appendChild(
|
|
1668
|
-
iconBtn(ICONS.goTo, "
|
|
1766
|
+
iconBtn(ICONS.goTo, "Go to this place", () => {
|
|
1669
1767
|
closeCurrent2();
|
|
1670
1768
|
internal.onGo();
|
|
1671
1769
|
})
|
|
@@ -1879,8 +1977,8 @@ function openCellProperties({
|
|
|
1879
1977
|
label: "Fill",
|
|
1880
1978
|
clearLabel: "No fill",
|
|
1881
1979
|
value: () => background,
|
|
1882
|
-
onPick: (
|
|
1883
|
-
background =
|
|
1980
|
+
onPick: (c2) => {
|
|
1981
|
+
background = c2;
|
|
1884
1982
|
}
|
|
1885
1983
|
});
|
|
1886
1984
|
fill.append(fillBtn.el);
|
|
@@ -1933,8 +2031,8 @@ function openCellProperties({
|
|
|
1933
2031
|
title: "Border colour",
|
|
1934
2032
|
label: "Colour",
|
|
1935
2033
|
value: () => penColor,
|
|
1936
|
-
onPick: (
|
|
1937
|
-
if (
|
|
2034
|
+
onPick: (c2) => {
|
|
2035
|
+
if (c2) penColor = c2;
|
|
1938
2036
|
}
|
|
1939
2037
|
});
|
|
1940
2038
|
penRow.append(widthSel, styleSel, penBtn.el);
|
|
@@ -1998,8 +2096,369 @@ function openCellProperties({
|
|
|
1998
2096
|
dialog.open();
|
|
1999
2097
|
}
|
|
2000
2098
|
|
|
2001
|
-
// packages/ui/src/lib/
|
|
2099
|
+
// packages/ui/src/lib/equation-gallery.ts
|
|
2100
|
+
var import_bapbong_contracts2 = require("@shadow-garden/bapbong-contracts");
|
|
2101
|
+
var c = (s) => [...s].map((ch) => ({ t: "chr", ch }));
|
|
2102
|
+
var sup = (base, exp) => ({
|
|
2103
|
+
t: "scr",
|
|
2104
|
+
base,
|
|
2105
|
+
sub: [],
|
|
2106
|
+
sup: c(exp)
|
|
2107
|
+
});
|
|
2108
|
+
var subsup = (base, lo, hi) => ({
|
|
2109
|
+
t: "scr",
|
|
2110
|
+
base,
|
|
2111
|
+
sub: c(lo),
|
|
2112
|
+
sup: c(hi)
|
|
2113
|
+
});
|
|
2114
|
+
var BUILT_IN_EQUATIONS = [
|
|
2115
|
+
{
|
|
2116
|
+
name: "Area of a circle",
|
|
2117
|
+
ast: [...c("\u{1D434} = \u{1D70B}"), sup(c("\u{1D45F}"), "2")]
|
|
2118
|
+
},
|
|
2119
|
+
{
|
|
2120
|
+
name: "Pythagorean theorem",
|
|
2121
|
+
ast: [
|
|
2122
|
+
sup(c("\u{1D44E}"), "2"),
|
|
2123
|
+
...c(" + "),
|
|
2124
|
+
sup(c("\u{1D44F}"), "2"),
|
|
2125
|
+
...c(" = "),
|
|
2126
|
+
sup(c("\u{1D450}"), "2")
|
|
2127
|
+
]
|
|
2128
|
+
},
|
|
2129
|
+
{
|
|
2130
|
+
name: "Quadratic formula",
|
|
2131
|
+
ast: [
|
|
2132
|
+
...c("\u{1D465} = "),
|
|
2133
|
+
{
|
|
2134
|
+
t: "frac",
|
|
2135
|
+
num: [
|
|
2136
|
+
...c("\u2212\u{1D44F} \xB1 "),
|
|
2137
|
+
{
|
|
2138
|
+
t: "rad",
|
|
2139
|
+
deg: [],
|
|
2140
|
+
body: [sup(c("\u{1D44F}"), "2"), ...c(" \u2212 4\u{1D44E}\u{1D450}")]
|
|
2141
|
+
}
|
|
2142
|
+
],
|
|
2143
|
+
den: c("2\u{1D44E}")
|
|
2144
|
+
}
|
|
2145
|
+
]
|
|
2146
|
+
},
|
|
2147
|
+
{
|
|
2148
|
+
name: "Law of cosines",
|
|
2149
|
+
ast: [
|
|
2150
|
+
sup(c("\u{1D44E}"), "2"),
|
|
2151
|
+
...c(" = "),
|
|
2152
|
+
sup(c("\u{1D44F}"), "2"),
|
|
2153
|
+
...c(" + "),
|
|
2154
|
+
sup(c("\u{1D450}"), "2"),
|
|
2155
|
+
...c(" \u2212 2\u{1D44F}\u{1D450} cos \u{1D434}")
|
|
2156
|
+
]
|
|
2157
|
+
},
|
|
2158
|
+
{
|
|
2159
|
+
name: "Binomial theorem",
|
|
2160
|
+
ast: [
|
|
2161
|
+
// The exponent belongs ON the bracket: a script with an empty base
|
|
2162
|
+
// would render its own empty slot — the dotted placeholder box.
|
|
2163
|
+
{
|
|
2164
|
+
t: "scr",
|
|
2165
|
+
base: [{ t: "fence", l: "(", r: ")", body: c("\u{1D44E} + \u{1D44F}") }],
|
|
2166
|
+
sub: [],
|
|
2167
|
+
sup: c("\u{1D45B}")
|
|
2168
|
+
},
|
|
2169
|
+
...c(" = "),
|
|
2170
|
+
{
|
|
2171
|
+
t: "big",
|
|
2172
|
+
op: "\u2211",
|
|
2173
|
+
lo: c("\u{1D458} = 0"),
|
|
2174
|
+
hi: c("\u{1D45B}"),
|
|
2175
|
+
body: [
|
|
2176
|
+
subsup(c("\u{1D436}"), "\u{1D45B}", "\u{1D458}"),
|
|
2177
|
+
sup(c("\u{1D44E}"), "\u{1D458}"),
|
|
2178
|
+
{ t: "scr", base: c("\u{1D44F}"), sub: [], sup: c("\u{1D45B}\u2212\u{1D458}") }
|
|
2179
|
+
]
|
|
2180
|
+
}
|
|
2181
|
+
]
|
|
2182
|
+
}
|
|
2183
|
+
];
|
|
2184
|
+
var SVG_NS = "http://www.w3.org/2000/svg";
|
|
2185
|
+
function equationPreviewSvg(spec, opts = {}) {
|
|
2186
|
+
const svg = document.createElementNS(SVG_NS, "svg");
|
|
2187
|
+
svg.setAttribute("viewBox", `0 0 ${spec.width} ${spec.height}`);
|
|
2188
|
+
const max = opts.maxWidth ?? spec.width;
|
|
2189
|
+
const scale = Math.min(1, max / Math.max(1, spec.width));
|
|
2190
|
+
svg.setAttribute("width", String(Math.round(spec.width * scale)));
|
|
2191
|
+
svg.setAttribute("height", String(Math.round(spec.height * scale)));
|
|
2192
|
+
svg.setAttribute("aria-hidden", "true");
|
|
2193
|
+
for (const op of spec.ops) svg.append(opElement(op));
|
|
2194
|
+
return svg;
|
|
2195
|
+
}
|
|
2196
|
+
function opElement(op) {
|
|
2197
|
+
if (op.kind === "line") {
|
|
2198
|
+
const el6 = document.createElementNS(SVG_NS, "line");
|
|
2199
|
+
el6.setAttribute("x1", String(op.x1));
|
|
2200
|
+
el6.setAttribute("y1", String(op.y1));
|
|
2201
|
+
el6.setAttribute("x2", String(op.x2));
|
|
2202
|
+
el6.setAttribute("y2", String(op.y2));
|
|
2203
|
+
el6.setAttribute("stroke", op.color);
|
|
2204
|
+
el6.setAttribute("stroke-width", String(Math.max(op.width, 0.75)));
|
|
2205
|
+
return el6;
|
|
2206
|
+
}
|
|
2207
|
+
if (op.kind === "polygon") {
|
|
2208
|
+
const el6 = document.createElementNS(SVG_NS, "polygon");
|
|
2209
|
+
el6.setAttribute("points", op.points.map((p) => `${p.x},${p.y}`).join(" "));
|
|
2210
|
+
el6.setAttribute("fill", op.fill ?? "none");
|
|
2211
|
+
if (op.stroke) {
|
|
2212
|
+
el6.setAttribute("stroke", op.stroke);
|
|
2213
|
+
el6.setAttribute("stroke-width", String(op.strokeWidth ?? 1));
|
|
2214
|
+
}
|
|
2215
|
+
return el6;
|
|
2216
|
+
}
|
|
2217
|
+
const el5 = document.createElementNS(SVG_NS, "text");
|
|
2218
|
+
el5.setAttribute("x", String(op.x));
|
|
2219
|
+
el5.setAttribute("y", String(op.y));
|
|
2220
|
+
el5.setAttribute("font-size", String(op.size));
|
|
2221
|
+
el5.setAttribute("font-family", op.family);
|
|
2222
|
+
el5.setAttribute("fill", op.color);
|
|
2223
|
+
if (op.bold) el5.setAttribute("font-weight", "bold");
|
|
2224
|
+
if (op.italic) el5.setAttribute("font-style", "italic");
|
|
2225
|
+
if (op.vAlign === "top") el5.setAttribute("dominant-baseline", "hanging");
|
|
2226
|
+
if (op.dx) {
|
|
2227
|
+
let x = op.x;
|
|
2228
|
+
for (const [i, ch] of [...op.text].entries()) {
|
|
2229
|
+
const t = document.createElementNS(SVG_NS, "tspan");
|
|
2230
|
+
t.setAttribute("x", String(x));
|
|
2231
|
+
t.textContent = ch;
|
|
2232
|
+
el5.append(t);
|
|
2233
|
+
x += op.dx[i] ?? 0;
|
|
2234
|
+
}
|
|
2235
|
+
} else {
|
|
2236
|
+
el5.textContent = op.text;
|
|
2237
|
+
}
|
|
2238
|
+
return el5;
|
|
2239
|
+
}
|
|
2002
2240
|
var STYLE9 = `
|
|
2241
|
+
.bb-eqg{display:flex;flex-direction:column;min-width:236px;max-width:300px;user-select:none}
|
|
2242
|
+
.bb-eqg-head{font-size:11px;font-weight:600;opacity:.55;padding:2px 8px 6px}
|
|
2243
|
+
.bb-eqg-list{display:flex;flex-direction:column;max-height:320px;overflow-y:auto}
|
|
2244
|
+
.bb-eqg-item{display:flex;flex-direction:column;gap:3px;align-items:flex-start;width:100%;padding:7px 9px;border:0;border-radius:6px;background:transparent;color:inherit;font:inherit;text-align:left;cursor:pointer}
|
|
2245
|
+
.bb-eqg-item:hover{background:var(--bb-ui-hover,#f1efe8)}
|
|
2246
|
+
.bb-eqg-name{font-size:11px;opacity:.6}
|
|
2247
|
+
/* The preview is the equation TYPESET \u2014 the same display list the canvas
|
|
2248
|
+
paints. The text form is the fallback for a host that cannot lay out. */
|
|
2249
|
+
.bb-eqg-prev{display:flex;align-items:center;min-height:22px;max-width:100%;overflow:hidden}
|
|
2250
|
+
.bb-eqg-prev svg{display:block}
|
|
2251
|
+
.bb-eqg-prev-text{font-family:"Times New Roman",Tinos,serif;font-size:15px;line-height:1.35;white-space:nowrap;text-overflow:ellipsis}
|
|
2252
|
+
.bb-eqg-foot{margin-top:4px;padding-top:5px;border-top:1px solid var(--bb-ui-border,#e3e3e0)}
|
|
2253
|
+
.bb-eqg-new{display:flex;align-items:center;gap:8px;width:100%;height:30px;padding:0 9px;border:0;border-radius:6px;background:transparent;color:inherit;font:inherit;font-size:13px;text-align:left;cursor:pointer}
|
|
2254
|
+
.bb-eqg-new:hover{background:var(--bb-ui-hover,#f1efe8)}
|
|
2255
|
+
.bb-eqg-key{margin-left:auto;opacity:.5;font-size:12px}
|
|
2256
|
+
`;
|
|
2257
|
+
var PREVIEW_PT = 11;
|
|
2258
|
+
var PREVIEW_MAX_W = 264;
|
|
2259
|
+
function equationGallery(options) {
|
|
2260
|
+
injectStyle("bb-ui-eqg-styles", STYLE9);
|
|
2261
|
+
const root = document.createElement("div");
|
|
2262
|
+
root.className = "bb-eqg";
|
|
2263
|
+
const head = document.createElement("div");
|
|
2264
|
+
head.className = "bb-eqg-head";
|
|
2265
|
+
head.textContent = "Built-in";
|
|
2266
|
+
root.append(head);
|
|
2267
|
+
const list = document.createElement("div");
|
|
2268
|
+
list.className = "bb-eqg-list";
|
|
2269
|
+
for (const item of options.items ?? BUILT_IN_EQUATIONS) {
|
|
2270
|
+
const btn = document.createElement("button");
|
|
2271
|
+
btn.type = "button";
|
|
2272
|
+
btn.className = "bb-eqg-item";
|
|
2273
|
+
const prev = document.createElement("div");
|
|
2274
|
+
prev.className = "bb-eqg-prev";
|
|
2275
|
+
const spec = options.layout?.(item.ast, PREVIEW_PT) ?? null;
|
|
2276
|
+
if (spec && spec.ops.length)
|
|
2277
|
+
prev.append(equationPreviewSvg(spec, { maxWidth: PREVIEW_MAX_W }));
|
|
2278
|
+
else {
|
|
2279
|
+
prev.classList.add("bb-eqg-prev-text");
|
|
2280
|
+
prev.textContent = (0, import_bapbong_contracts2.astToLinear)(item.ast);
|
|
2281
|
+
}
|
|
2282
|
+
const name = document.createElement("div");
|
|
2283
|
+
name.className = "bb-eqg-name";
|
|
2284
|
+
name.textContent = item.name;
|
|
2285
|
+
btn.append(prev, name);
|
|
2286
|
+
btn.addEventListener("mousedown", (e) => e.preventDefault());
|
|
2287
|
+
btn.addEventListener("click", () => options.onPick(item.ast));
|
|
2288
|
+
list.append(btn);
|
|
2289
|
+
}
|
|
2290
|
+
root.append(list);
|
|
2291
|
+
const foot = document.createElement("div");
|
|
2292
|
+
foot.className = "bb-eqg-foot";
|
|
2293
|
+
const neu = document.createElement("button");
|
|
2294
|
+
neu.type = "button";
|
|
2295
|
+
neu.className = "bb-eqg-new";
|
|
2296
|
+
const label = document.createElement("span");
|
|
2297
|
+
label.textContent = "Insert new equation";
|
|
2298
|
+
neu.append(label);
|
|
2299
|
+
if (options.newShortcut) {
|
|
2300
|
+
const key = document.createElement("span");
|
|
2301
|
+
key.className = "bb-eqg-key";
|
|
2302
|
+
key.textContent = options.newShortcut;
|
|
2303
|
+
neu.append(key);
|
|
2304
|
+
}
|
|
2305
|
+
neu.addEventListener("mousedown", (e) => e.preventDefault());
|
|
2306
|
+
neu.addEventListener("click", () => options.onNew());
|
|
2307
|
+
foot.append(neu);
|
|
2308
|
+
root.append(foot);
|
|
2309
|
+
return root;
|
|
2310
|
+
}
|
|
2311
|
+
|
|
2312
|
+
// packages/ui/src/lib/equation-panel.ts
|
|
2313
|
+
var import_bapbong_contracts3 = require("@shadow-garden/bapbong-contracts");
|
|
2314
|
+
var SHORTHAND = /* @__PURE__ */ new Map();
|
|
2315
|
+
for (const [name, ch] of Object.entries(import_bapbong_contracts3.MATH_AUTOCORRECT))
|
|
2316
|
+
if (!SHORTHAND.has(ch)) SHORTHAND.set(ch, `\\${name}`);
|
|
2317
|
+
var PREVIEW_PT2 = 10;
|
|
2318
|
+
var STYLE10 = `
|
|
2319
|
+
.bb-eqp{width:352px;display:flex;flex-direction:column;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;box-shadow:0 8px 28px rgba(0,0,0,.14);user-select:none;overflow:hidden}
|
|
2320
|
+
.bb-eqp-tabs{display:flex;padding:8px 8px 0}
|
|
2321
|
+
.bb-eqp-body{padding:8px}
|
|
2322
|
+
.bb-eqp-set{width:100%;height:30px;margin-bottom:7px;border:0.5px solid var(--bb-ui-control-border,var(--bb-ui-border,#d8d6cf));border-radius:6px;background:var(--bb-ui-control-bg,#fff);color:inherit;font:inherit;font-size:13px;padding:0 8px}
|
|
2323
|
+
.bb-eqp-grid{display:grid;grid-template-columns:repeat(10,1fr);gap:1px;max-height:190px;overflow-y:auto}
|
|
2324
|
+
.bb-eqp-sym{padding:5px 0;border:0;border-radius:5px;background:transparent;color:inherit;font-family:"Cambria Math","Times New Roman",Tinos,serif;font-size:16px;line-height:1.2;cursor:pointer}
|
|
2325
|
+
.bb-eqp-sym:hover{background:var(--bb-ui-hover,#f1efe8)}
|
|
2326
|
+
.bb-eqp-hint{display:flex;align-items:center;justify-content:space-between;gap:8px;min-height:22px;margin-top:7px;padding-top:6px;border-top:0.5px solid var(--bb-ui-border,#e3e3e0);font-size:12px;opacity:.6}
|
|
2327
|
+
.bb-eqp-hint-g{font-family:"Cambria Math","Times New Roman",Tinos,serif;font-size:15px}
|
|
2328
|
+
.bb-eqp-hint-k{font-family:ui-monospace,SFMono-Regular,Menlo,monospace}
|
|
2329
|
+
.bb-eqp-scroll{max-height:230px;overflow-y:auto}
|
|
2330
|
+
.bb-eqp-group{font-size:11px;font-weight:600;opacity:.5;padding:6px 2px 3px}
|
|
2331
|
+
.bb-eqp-row{display:grid;grid-template-columns:repeat(4,1fr);gap:3px}
|
|
2332
|
+
.bb-eqp-st{display:flex;flex-direction:column;align-items:center;justify-content:flex-end;gap:3px;min-height:52px;padding:6px 2px;border:0;border-radius:6px;background:transparent;color:inherit;font:inherit;cursor:pointer}
|
|
2333
|
+
.bb-eqp-st:hover{background:var(--bb-ui-hover,#f1efe8)}
|
|
2334
|
+
.bb-eqp-st-name{font-size:10px;opacity:.6;text-align:center;line-height:1.25}
|
|
2335
|
+
.bb-eqp-st svg{display:block}
|
|
2336
|
+
`;
|
|
2337
|
+
function equationPanel(options) {
|
|
2338
|
+
injectStyle("bb-ui-tabs", TABS_CSS);
|
|
2339
|
+
injectStyle("bb-ui-eqp-styles", STYLE10);
|
|
2340
|
+
const root = document.createElement("div");
|
|
2341
|
+
root.className = "bb-eqp";
|
|
2342
|
+
root.setAttribute("role", "group");
|
|
2343
|
+
root.setAttribute("aria-label", "Equation palette");
|
|
2344
|
+
root.addEventListener("mousedown", (e) => e.preventDefault());
|
|
2345
|
+
const strip = document.createElement("div");
|
|
2346
|
+
strip.className = "bb-eqp-tabs";
|
|
2347
|
+
const tabs = document.createElement("div");
|
|
2348
|
+
tabs.className = "bb-tabs";
|
|
2349
|
+
tabs.setAttribute("role", "tablist");
|
|
2350
|
+
strip.append(tabs);
|
|
2351
|
+
const body = document.createElement("div");
|
|
2352
|
+
body.className = "bb-eqp-body";
|
|
2353
|
+
let current3 = "symbols";
|
|
2354
|
+
const tabEls = {};
|
|
2355
|
+
const mkTab = (id, label) => {
|
|
2356
|
+
const b = document.createElement("button");
|
|
2357
|
+
b.type = "button";
|
|
2358
|
+
b.className = "bb-tab";
|
|
2359
|
+
b.textContent = label;
|
|
2360
|
+
b.setAttribute("role", "tab");
|
|
2361
|
+
b.addEventListener("click", () => {
|
|
2362
|
+
current3 = id;
|
|
2363
|
+
render();
|
|
2364
|
+
});
|
|
2365
|
+
tabEls[id] = b;
|
|
2366
|
+
tabs.append(b);
|
|
2367
|
+
};
|
|
2368
|
+
mkTab("symbols", "Symbols");
|
|
2369
|
+
mkTab("structures", "Structures");
|
|
2370
|
+
root.append(strip, body);
|
|
2371
|
+
function symbolsBody() {
|
|
2372
|
+
const set = document.createElement("select");
|
|
2373
|
+
set.className = "bb-eqp-set";
|
|
2374
|
+
set.setAttribute("aria-label", "Symbol set");
|
|
2375
|
+
for (const [i, s] of import_bapbong_contracts3.MATH_SYMBOL_SETS.entries()) {
|
|
2376
|
+
const o = document.createElement("option");
|
|
2377
|
+
o.value = String(i);
|
|
2378
|
+
o.textContent = s.name;
|
|
2379
|
+
set.append(o);
|
|
2380
|
+
}
|
|
2381
|
+
set.value = String(setIndex);
|
|
2382
|
+
const grid = document.createElement("div");
|
|
2383
|
+
grid.className = "bb-eqp-grid";
|
|
2384
|
+
const hint = document.createElement("div");
|
|
2385
|
+
hint.className = "bb-eqp-hint";
|
|
2386
|
+
const hintG = document.createElement("span");
|
|
2387
|
+
hintG.className = "bb-eqp-hint-g";
|
|
2388
|
+
const hintK = document.createElement("span");
|
|
2389
|
+
hintK.className = "bb-eqp-hint-k";
|
|
2390
|
+
hint.append(hintG, hintK);
|
|
2391
|
+
const fill = () => {
|
|
2392
|
+
grid.replaceChildren();
|
|
2393
|
+
const chars = import_bapbong_contracts3.MATH_SYMBOL_SETS[setIndex]?.chars ?? "";
|
|
2394
|
+
for (const ch of chars) {
|
|
2395
|
+
const b = document.createElement("button");
|
|
2396
|
+
b.type = "button";
|
|
2397
|
+
b.className = "bb-eqp-sym";
|
|
2398
|
+
b.textContent = ch;
|
|
2399
|
+
const key = SHORTHAND.get(ch);
|
|
2400
|
+
b.title = key ? `${ch} ${key}` : ch;
|
|
2401
|
+
b.addEventListener("mouseenter", () => {
|
|
2402
|
+
hintG.textContent = ch;
|
|
2403
|
+
hintK.textContent = key ?? "";
|
|
2404
|
+
});
|
|
2405
|
+
b.addEventListener("click", () => options.onSymbol(ch));
|
|
2406
|
+
grid.append(b);
|
|
2407
|
+
}
|
|
2408
|
+
};
|
|
2409
|
+
set.addEventListener("change", () => {
|
|
2410
|
+
setIndex = Number(set.value) || 0;
|
|
2411
|
+
fill();
|
|
2412
|
+
});
|
|
2413
|
+
fill();
|
|
2414
|
+
body.replaceChildren(set, grid, hint);
|
|
2415
|
+
}
|
|
2416
|
+
function structuresBody() {
|
|
2417
|
+
const scroll = document.createElement("div");
|
|
2418
|
+
scroll.className = "bb-eqp-scroll";
|
|
2419
|
+
for (const group of (0, import_bapbong_contracts3.eqStructureGroups)()) {
|
|
2420
|
+
const h = document.createElement("div");
|
|
2421
|
+
h.className = "bb-eqp-group";
|
|
2422
|
+
h.textContent = group.name;
|
|
2423
|
+
const row = document.createElement("div");
|
|
2424
|
+
row.className = "bb-eqp-row";
|
|
2425
|
+
for (const item of group.items) {
|
|
2426
|
+
const b = document.createElement("button");
|
|
2427
|
+
b.type = "button";
|
|
2428
|
+
b.className = "bb-eqp-st";
|
|
2429
|
+
b.title = `${group.name} \u2014 ${item.name}`;
|
|
2430
|
+
const spec = options.layout?.([item.node], PREVIEW_PT2) ?? null;
|
|
2431
|
+
if (spec && spec.ops.length)
|
|
2432
|
+
b.append(equationPreviewSvg(spec, { maxWidth: 60 }));
|
|
2433
|
+
const name = document.createElement("span");
|
|
2434
|
+
name.className = "bb-eqp-st-name";
|
|
2435
|
+
name.textContent = item.name;
|
|
2436
|
+
b.append(name);
|
|
2437
|
+
b.addEventListener("click", () => options.onStructure(item));
|
|
2438
|
+
row.append(b);
|
|
2439
|
+
}
|
|
2440
|
+
scroll.append(h, row);
|
|
2441
|
+
}
|
|
2442
|
+
body.replaceChildren(scroll);
|
|
2443
|
+
}
|
|
2444
|
+
let setIndex = 0;
|
|
2445
|
+
function render() {
|
|
2446
|
+
for (const [id, el5] of Object.entries(tabEls))
|
|
2447
|
+
el5.setAttribute("aria-selected", String(id === current3));
|
|
2448
|
+
if (current3 === "symbols") symbolsBody();
|
|
2449
|
+
else structuresBody();
|
|
2450
|
+
}
|
|
2451
|
+
render();
|
|
2452
|
+
return {
|
|
2453
|
+
el: root,
|
|
2454
|
+
destroy() {
|
|
2455
|
+
root.remove();
|
|
2456
|
+
}
|
|
2457
|
+
};
|
|
2458
|
+
}
|
|
2459
|
+
|
|
2460
|
+
// packages/ui/src/lib/table-grid.ts
|
|
2461
|
+
var STYLE11 = `
|
|
2003
2462
|
.bb-grid{display:flex;flex-direction:column;gap:6px;user-select:none}
|
|
2004
2463
|
.bb-grid-cells{display:grid;gap:2px}
|
|
2005
2464
|
.bb-grid-cell{width:15px;height:15px;border:1px solid var(--bb-ui-control-border,var(--bb-ui-border,#d8d6cf));border-radius:2px;background:var(--bb-ui-bg,#fff);cursor:pointer;padding:0}
|
|
@@ -2007,7 +2466,7 @@ var STYLE9 = `
|
|
|
2007
2466
|
.bb-grid-label{font-size:12px;text-align:center;opacity:.7}
|
|
2008
2467
|
`;
|
|
2009
2468
|
function tableGridPicker(options) {
|
|
2010
|
-
injectStyle("bb-ui-grid-styles",
|
|
2469
|
+
injectStyle("bb-ui-grid-styles", STYLE11);
|
|
2011
2470
|
const maxRows = options.maxRows ?? 8;
|
|
2012
2471
|
const maxCols = options.maxCols ?? 10;
|
|
2013
2472
|
const root = document.createElement("div");
|
|
@@ -2019,22 +2478,22 @@ function tableGridPicker(options) {
|
|
|
2019
2478
|
label.className = "bb-grid-label";
|
|
2020
2479
|
label.textContent = "0 \xD7 0";
|
|
2021
2480
|
const cells = [];
|
|
2022
|
-
const highlight2 = (r,
|
|
2481
|
+
const highlight2 = (r, c2) => {
|
|
2023
2482
|
for (let i = 0; i < cells.length; i++) {
|
|
2024
2483
|
const row = Math.floor(i / maxCols);
|
|
2025
2484
|
const col = i % maxCols;
|
|
2026
|
-
cells[i].classList.toggle("on", row <= r && col <=
|
|
2485
|
+
cells[i].classList.toggle("on", row <= r && col <= c2);
|
|
2027
2486
|
}
|
|
2028
|
-
label.textContent = `${r + 1} \xD7 ${
|
|
2487
|
+
label.textContent = `${r + 1} \xD7 ${c2 + 1}`;
|
|
2029
2488
|
};
|
|
2030
2489
|
for (let r = 0; r < maxRows; r++) {
|
|
2031
|
-
for (let
|
|
2490
|
+
for (let c2 = 0; c2 < maxCols; c2++) {
|
|
2032
2491
|
const cell = document.createElement("button");
|
|
2033
2492
|
cell.type = "button";
|
|
2034
2493
|
cell.className = "bb-grid-cell";
|
|
2035
2494
|
cell.addEventListener("mousedown", (e) => e.preventDefault());
|
|
2036
|
-
cell.addEventListener("mouseenter", () => highlight2(r,
|
|
2037
|
-
cell.addEventListener("click", () => options.onPick(r + 1,
|
|
2495
|
+
cell.addEventListener("mouseenter", () => highlight2(r, c2));
|
|
2496
|
+
cell.addEventListener("click", () => options.onPick(r + 1, c2 + 1));
|
|
2038
2497
|
cells.push(cell);
|
|
2039
2498
|
cellsEl.appendChild(cell);
|
|
2040
2499
|
}
|
|
@@ -2043,6 +2502,176 @@ function tableGridPicker(options) {
|
|
|
2043
2502
|
return root;
|
|
2044
2503
|
}
|
|
2045
2504
|
|
|
2505
|
+
// packages/ui/src/lib/table-style-panel.ts
|
|
2506
|
+
var import_bapbong_contracts4 = require("@shadow-garden/bapbong-contracts");
|
|
2507
|
+
var GATES = [
|
|
2508
|
+
{ key: "firstRow", label: "Header row" },
|
|
2509
|
+
{ key: "lastRow", label: "Total row" },
|
|
2510
|
+
{ key: "hBand", label: "Banded rows" },
|
|
2511
|
+
{ key: "firstCol", label: "First column" },
|
|
2512
|
+
{ key: "lastCol", label: "Last column" },
|
|
2513
|
+
{ key: "vBand", label: "Banded columns" }
|
|
2514
|
+
];
|
|
2515
|
+
var THUMB_ROWS = 4;
|
|
2516
|
+
var THUMB_COLS = 5;
|
|
2517
|
+
var STYLE12 = `
|
|
2518
|
+
.bb-tsp{display:flex;gap:16px;width:432px;max-width:100%;color:var(--bb-ui-fg,#2c2c2a)}
|
|
2519
|
+
.bb-tsp *{box-sizing:border-box}
|
|
2520
|
+
.bb-tsp-opts{flex:0 0 128px;display:flex;flex-direction:column;gap:2px}
|
|
2521
|
+
.bb-tsp-lbl{font-size:12px;opacity:.7;margin-bottom:4px}
|
|
2522
|
+
.bb-tsp-chk{display:flex;align-items:center;gap:7px;font-size:13px;padding:3px 0;cursor:pointer}
|
|
2523
|
+
.bb-tsp-chk input{margin:0}
|
|
2524
|
+
.bb-tsp-chk.is-disabled{opacity:.4;cursor:default}
|
|
2525
|
+
.bb-tsp-sep{height:1px;margin:6px 0;background:var(--bb-ui-border,#e3e3e0)}
|
|
2526
|
+
.bb-tsp-main{flex:1;display:flex;flex-direction:column;gap:8px;min-width:0}
|
|
2527
|
+
.bb-tsp-gallery{display:flex;flex-wrap:wrap;gap:6px}
|
|
2528
|
+
.bb-tsp-tile{padding:3px;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));cursor:pointer;line-height:0}
|
|
2529
|
+
.bb-tsp-tile:hover{border-color:var(--bb-ui-fg,#2c2c2a)}
|
|
2530
|
+
.bb-tsp-tile.is-selected{padding:2px;border:2px solid var(--bb-ui-active-fg,#0c447c)}
|
|
2531
|
+
.bb-tsp-thumb{display:grid;grid-template-columns:repeat(${THUMB_COLS},12px);grid-auto-rows:8px;gap:0}
|
|
2532
|
+
.bb-tsp-none{display:flex;align-items:center;justify-content:center;width:60px;height:32px;font-size:11px;opacity:.7;line-height:1.1}
|
|
2533
|
+
.bb-tsp-empty{font-size:13px;opacity:.65;padding:8px 0}
|
|
2534
|
+
`;
|
|
2535
|
+
function edgeCss(side) {
|
|
2536
|
+
if (!side) return "none";
|
|
2537
|
+
return `1px ${side.style === "double" ? "double" : "solid"} ${side.color}`;
|
|
2538
|
+
}
|
|
2539
|
+
function thumbnail(style, look) {
|
|
2540
|
+
const grid = document.createElement("div");
|
|
2541
|
+
grid.className = "bb-tsp-thumb";
|
|
2542
|
+
const t = style.table.borders ?? {};
|
|
2543
|
+
for (let r = 0; r < THUMB_ROWS; r++) {
|
|
2544
|
+
for (let c2 = 0; c2 < THUMB_COLS; c2++) {
|
|
2545
|
+
const layer = (0, import_bapbong_contracts4.cellStyleLayer)(style, look, {
|
|
2546
|
+
row: r,
|
|
2547
|
+
rowCount: THUMB_ROWS,
|
|
2548
|
+
col: c2,
|
|
2549
|
+
colspan: 1,
|
|
2550
|
+
colCount: THUMB_COLS,
|
|
2551
|
+
header: false
|
|
2552
|
+
});
|
|
2553
|
+
const cell = document.createElement("div");
|
|
2554
|
+
const b = layer.borders ?? {};
|
|
2555
|
+
cell.style.borderTop = edgeCss(b.top ?? (r === 0 ? t.top : t.insideH));
|
|
2556
|
+
cell.style.borderBottom = edgeCss(
|
|
2557
|
+
b.bottom ?? (r === THUMB_ROWS - 1 ? t.bottom : void 0)
|
|
2558
|
+
);
|
|
2559
|
+
cell.style.borderLeft = edgeCss(b.left ?? (c2 === 0 ? t.left : t.insideV));
|
|
2560
|
+
cell.style.borderRight = edgeCss(
|
|
2561
|
+
b.right ?? (c2 === THUMB_COLS - 1 ? t.right : void 0)
|
|
2562
|
+
);
|
|
2563
|
+
if (layer.background) cell.style.background = layer.background;
|
|
2564
|
+
grid.appendChild(cell);
|
|
2565
|
+
}
|
|
2566
|
+
}
|
|
2567
|
+
return grid;
|
|
2568
|
+
}
|
|
2569
|
+
function createTableStylePanel(options) {
|
|
2570
|
+
injectStyle("bb-table-style-panel", STYLE12);
|
|
2571
|
+
const root = document.createElement("div");
|
|
2572
|
+
root.className = "bb-tsp";
|
|
2573
|
+
const opts = document.createElement("div");
|
|
2574
|
+
opts.className = "bb-tsp-opts";
|
|
2575
|
+
const optsLbl = document.createElement("div");
|
|
2576
|
+
optsLbl.className = "bb-tsp-lbl";
|
|
2577
|
+
optsLbl.textContent = "Style options";
|
|
2578
|
+
opts.appendChild(optsLbl);
|
|
2579
|
+
const checks = /* @__PURE__ */ new Map();
|
|
2580
|
+
GATES.forEach((g2, i) => {
|
|
2581
|
+
if (i === 3) {
|
|
2582
|
+
const sep = document.createElement("div");
|
|
2583
|
+
sep.className = "bb-tsp-sep";
|
|
2584
|
+
opts.appendChild(sep);
|
|
2585
|
+
}
|
|
2586
|
+
const label = document.createElement("label");
|
|
2587
|
+
label.className = "bb-tsp-chk";
|
|
2588
|
+
const input = document.createElement("input");
|
|
2589
|
+
input.type = "checkbox";
|
|
2590
|
+
input.addEventListener(
|
|
2591
|
+
"change",
|
|
2592
|
+
() => options.onLook({ [g2.key]: input.checked })
|
|
2593
|
+
);
|
|
2594
|
+
label.append(input, document.createTextNode(g2.label));
|
|
2595
|
+
opts.appendChild(label);
|
|
2596
|
+
checks.set(g2.key, input);
|
|
2597
|
+
});
|
|
2598
|
+
const main = document.createElement("div");
|
|
2599
|
+
main.className = "bb-tsp-main";
|
|
2600
|
+
const mainLbl = document.createElement("div");
|
|
2601
|
+
mainLbl.className = "bb-tsp-lbl";
|
|
2602
|
+
mainLbl.textContent = "Table styles";
|
|
2603
|
+
const gallery = document.createElement("div");
|
|
2604
|
+
gallery.className = "bb-tsp-gallery";
|
|
2605
|
+
main.append(mainLbl, gallery);
|
|
2606
|
+
root.append(opts, main);
|
|
2607
|
+
const dialog = new Dialog({
|
|
2608
|
+
title: "Table style",
|
|
2609
|
+
modal: false,
|
|
2610
|
+
anchor: options.anchor
|
|
2611
|
+
});
|
|
2612
|
+
dialog.setContent(root);
|
|
2613
|
+
let drawnKey = "";
|
|
2614
|
+
const draw = () => {
|
|
2615
|
+
const current3 = options.current();
|
|
2616
|
+
const items = options.styles();
|
|
2617
|
+
const key = JSON.stringify([current3, items.map((i) => i.id)]);
|
|
2618
|
+
if (key === drawnKey) return;
|
|
2619
|
+
drawnKey = key;
|
|
2620
|
+
const look = current3?.look ?? null;
|
|
2621
|
+
for (const [gate, input] of checks) {
|
|
2622
|
+
input.checked = look?.[gate] ?? false;
|
|
2623
|
+
input.disabled = !current3;
|
|
2624
|
+
input.closest("label")?.classList.toggle("is-disabled", !current3);
|
|
2625
|
+
}
|
|
2626
|
+
gallery.replaceChildren();
|
|
2627
|
+
if (!current3) {
|
|
2628
|
+
const empty = document.createElement("div");
|
|
2629
|
+
empty.className = "bb-tsp-empty";
|
|
2630
|
+
empty.textContent = "Click inside a table to style it.";
|
|
2631
|
+
gallery.appendChild(empty);
|
|
2632
|
+
return;
|
|
2633
|
+
}
|
|
2634
|
+
const noneTile = document.createElement("button");
|
|
2635
|
+
noneTile.type = "button";
|
|
2636
|
+
noneTile.className = "bb-tsp-tile" + (current3.styleId === null ? " is-selected" : "");
|
|
2637
|
+
noneTile.title = "None";
|
|
2638
|
+
const noneInner = document.createElement("span");
|
|
2639
|
+
noneInner.className = "bb-tsp-none";
|
|
2640
|
+
noneInner.textContent = "None";
|
|
2641
|
+
noneTile.appendChild(noneInner);
|
|
2642
|
+
noneTile.addEventListener("click", () => options.onPick(null));
|
|
2643
|
+
gallery.appendChild(noneTile);
|
|
2644
|
+
for (const item of items) {
|
|
2645
|
+
const tile = document.createElement("button");
|
|
2646
|
+
tile.type = "button";
|
|
2647
|
+
tile.className = "bb-tsp-tile" + (current3.styleId === item.id ? " is-selected" : "");
|
|
2648
|
+
tile.title = item.name;
|
|
2649
|
+
tile.appendChild(thumbnail(item.style, current3.look));
|
|
2650
|
+
tile.addEventListener("click", () => options.onPick(item));
|
|
2651
|
+
gallery.appendChild(tile);
|
|
2652
|
+
}
|
|
2653
|
+
};
|
|
2654
|
+
return {
|
|
2655
|
+
open() {
|
|
2656
|
+
drawnKey = "";
|
|
2657
|
+
draw();
|
|
2658
|
+
dialog.open();
|
|
2659
|
+
},
|
|
2660
|
+
close() {
|
|
2661
|
+
dialog.close();
|
|
2662
|
+
},
|
|
2663
|
+
refresh() {
|
|
2664
|
+
if (dialog.isOpen) draw();
|
|
2665
|
+
},
|
|
2666
|
+
destroy() {
|
|
2667
|
+
dialog.destroy();
|
|
2668
|
+
},
|
|
2669
|
+
get isOpen() {
|
|
2670
|
+
return dialog.isOpen;
|
|
2671
|
+
}
|
|
2672
|
+
};
|
|
2673
|
+
}
|
|
2674
|
+
|
|
2046
2675
|
// packages/ui/src/lib/page-setup.ts
|
|
2047
2676
|
var PX_PER_CM = 96 / 2.54;
|
|
2048
2677
|
var pxToCm = (px) => px / PX_PER_CM;
|
|
@@ -2050,7 +2679,7 @@ var cmToPx = (cm) => Math.round(cm * PX_PER_CM);
|
|
|
2050
2679
|
function fmtCm(cm) {
|
|
2051
2680
|
return `${Number(cm.toFixed(3))} cm`;
|
|
2052
2681
|
}
|
|
2053
|
-
var
|
|
2682
|
+
var STYLE13 = `
|
|
2054
2683
|
.bb-ps{display:flex;flex-direction:column;min-width:250px;max-height:min(70vh,460px);overflow-y:auto}
|
|
2055
2684
|
.bb-ps,.bb-ps *{box-sizing:border-box}
|
|
2056
2685
|
.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}
|
|
@@ -2080,9 +2709,9 @@ var STYLE10 = `
|
|
|
2080
2709
|
.bb-ps-tile:hover,.bb-ps-tile:focus{background:var(--bb-ui-hover,#f1efe8);outline:none}
|
|
2081
2710
|
.bb-ps-tile[aria-checked="true"]{background:var(--bb-ui-active-bg,#e6f1fb)}
|
|
2082
2711
|
`;
|
|
2083
|
-
var
|
|
2712
|
+
var SVG_NS2 = "http://www.w3.org/2000/svg";
|
|
2084
2713
|
function svgEl(name, attrs) {
|
|
2085
|
-
const el5 = document.createElementNS(
|
|
2714
|
+
const el5 = document.createElementNS(SVG_NS2, name);
|
|
2086
2715
|
for (const [k, v] of Object.entries(attrs)) el5.setAttribute(k, String(v));
|
|
2087
2716
|
return el5;
|
|
2088
2717
|
}
|
|
@@ -2176,7 +2805,7 @@ function customRow(icon, title, description, onPick) {
|
|
|
2176
2805
|
return presetRow(icon, title, captionLine(description), false, onPick);
|
|
2177
2806
|
}
|
|
2178
2807
|
function pageSizePicker(options) {
|
|
2179
|
-
injectStyle("bb-ui-pagesetup-styles",
|
|
2808
|
+
injectStyle("bb-ui-pagesetup-styles", STYLE13);
|
|
2180
2809
|
const root = document.createElement("div");
|
|
2181
2810
|
root.className = "bb-ps";
|
|
2182
2811
|
root.setAttribute("role", "menu");
|
|
@@ -2205,7 +2834,7 @@ function pageSizePicker(options) {
|
|
|
2205
2834
|
return root;
|
|
2206
2835
|
}
|
|
2207
2836
|
function orientationPicker(options) {
|
|
2208
|
-
injectStyle("bb-ui-pagesetup-styles",
|
|
2837
|
+
injectStyle("bb-ui-pagesetup-styles", STYLE13);
|
|
2209
2838
|
const root = document.createElement("div");
|
|
2210
2839
|
root.className = "bb-ps";
|
|
2211
2840
|
root.setAttribute("role", "menu");
|
|
@@ -2228,7 +2857,7 @@ function orientationPicker(options) {
|
|
|
2228
2857
|
return root;
|
|
2229
2858
|
}
|
|
2230
2859
|
function marginPresetPicker(options) {
|
|
2231
|
-
injectStyle("bb-ui-pagesetup-styles",
|
|
2860
|
+
injectStyle("bb-ui-pagesetup-styles", STYLE13);
|
|
2232
2861
|
const root = document.createElement("div");
|
|
2233
2862
|
root.className = "bb-ps";
|
|
2234
2863
|
root.setAttribute("role", "menu");
|
|
@@ -2303,7 +2932,7 @@ function readPx(input, fallbackPx) {
|
|
|
2303
2932
|
return Number.isFinite(n) && n > 0 ? cmToPx(n) : fallbackPx;
|
|
2304
2933
|
}
|
|
2305
2934
|
function openPageSizeDialog(options) {
|
|
2306
|
-
injectStyle("bb-ui-pagesetup-styles",
|
|
2935
|
+
injectStyle("bb-ui-pagesetup-styles", STYLE13);
|
|
2307
2936
|
const dialog = new Dialog({ title: "Paper size", modal: true });
|
|
2308
2937
|
const form = document.createElement("form");
|
|
2309
2938
|
form.className = "bb-pd";
|
|
@@ -2330,7 +2959,7 @@ function openPageSizeDialog(options) {
|
|
|
2330
2959
|
width.input.select();
|
|
2331
2960
|
}
|
|
2332
2961
|
function openMarginsDialog(options) {
|
|
2333
|
-
injectStyle("bb-ui-pagesetup-styles",
|
|
2962
|
+
injectStyle("bb-ui-pagesetup-styles", STYLE13);
|
|
2334
2963
|
const dialog = new Dialog({ title: "Margins", modal: true });
|
|
2335
2964
|
const form = document.createElement("form");
|
|
2336
2965
|
form.className = "bb-pd";
|
|
@@ -2387,7 +3016,7 @@ var PGNUM_FORMATS = [
|
|
|
2387
3016
|
["upperLetter", "A, B, C, D\u2026", "A"]
|
|
2388
3017
|
];
|
|
2389
3018
|
function pageNumberPicker(options) {
|
|
2390
|
-
injectStyle("bb-ui-pagesetup-styles",
|
|
3019
|
+
injectStyle("bb-ui-pagesetup-styles", STYLE13);
|
|
2391
3020
|
const root = document.createElement("div");
|
|
2392
3021
|
root.className = "bb-ps";
|
|
2393
3022
|
root.setAttribute("role", "menu");
|
|
@@ -2488,7 +3117,7 @@ function pageNumberPicker(options) {
|
|
|
2488
3117
|
return root;
|
|
2489
3118
|
}
|
|
2490
3119
|
function sectionPaperPanel(options) {
|
|
2491
|
-
injectStyle("bb-ui-pagesetup-styles",
|
|
3120
|
+
injectStyle("bb-ui-pagesetup-styles", STYLE13);
|
|
2492
3121
|
const root = document.createElement("div");
|
|
2493
3122
|
root.className = "bb-ps";
|
|
2494
3123
|
root.setAttribute("role", "menu");
|
|
@@ -2557,7 +3186,7 @@ function sectionPaperPanel(options) {
|
|
|
2557
3186
|
}
|
|
2558
3187
|
|
|
2559
3188
|
// packages/ui/src/lib/section-chip.ts
|
|
2560
|
-
var
|
|
3189
|
+
var STYLE14 = `
|
|
2561
3190
|
.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)}
|
|
2562
3191
|
.bb-secchip *{box-sizing:border-box}
|
|
2563
3192
|
.bb-secchip-title{padding:0 7px;font-size:11px;font-weight:600;opacity:.8}
|
|
@@ -2570,7 +3199,7 @@ var STYLE11 = `
|
|
|
2570
3199
|
.bb-secchip-x:hover{background:var(--bb-ui-hover,#f1efe8);opacity:1}
|
|
2571
3200
|
`;
|
|
2572
3201
|
function createSectionChip(options) {
|
|
2573
|
-
injectStyle("bb-ui-section-chip-styles",
|
|
3202
|
+
injectStyle("bb-ui-section-chip-styles", STYLE14);
|
|
2574
3203
|
const el5 = document.createElement("div");
|
|
2575
3204
|
el5.className = "bb-secchip";
|
|
2576
3205
|
const title = document.createElement("span");
|
|
@@ -2627,17 +3256,13 @@ var halfToPt = (hp) => hp / 2;
|
|
|
2627
3256
|
var ptToHalf = (pt) => Math.round(pt * 2);
|
|
2628
3257
|
var SCALE_PRESETS = [200, 150, 100, 90, 80, 66, 50, 33];
|
|
2629
3258
|
var SUPERSUB_SCALE = 0.66;
|
|
2630
|
-
var
|
|
3259
|
+
var STYLE15 = `
|
|
2631
3260
|
.bb-fd{display:flex;flex-direction:column;gap:15px;min-width:396px;max-width:430px;color:var(--bb-ui-fg,#2c2c2a)}
|
|
2632
3261
|
.bb-fd *{box-sizing:border-box}
|
|
2633
3262
|
/* A segmented control, not a "tab joined to its pane": that pattern needs the
|
|
2634
3263
|
active tab's background to equal the pane's, and this dialog floats on
|
|
2635
3264
|
frosted glass whose colour the widget cannot know. Same shape cell-properties
|
|
2636
3265
|
already uses, so the two dialogs read as one product. */
|
|
2637
|
-
.bb-fd-tabs{display:inline-flex;border:0.5px solid var(--bb-ui-control-border,var(--bb-ui-border,#d8d6cf));border-radius:6px;overflow:hidden;align-self:flex-start}
|
|
2638
|
-
.bb-fd-tab{height:30px;padding:0 18px;border:0;border-right:0.5px solid var(--bb-ui-border,#e3e3e0);background:transparent;color:inherit;opacity:.65;font:inherit;font-size:13px;cursor:pointer}
|
|
2639
|
-
.bb-fd-tab:last-child{border-right:0}
|
|
2640
|
-
.bb-fd-tab[aria-selected="true"]{background:var(--bb-ui-active-bg,#e6f1fb);color:var(--bb-ui-active-fg,#0c447c);opacity:1}
|
|
2641
3266
|
.bb-fd-pane{display:flex;flex-direction:column;gap:13px}
|
|
2642
3267
|
/* A class-level display beats the UA's [hidden]{display:none}; without this
|
|
2643
3268
|
both tabs render at once. */
|
|
@@ -2709,13 +3334,14 @@ function openFontDialog({
|
|
|
2709
3334
|
sizes,
|
|
2710
3335
|
onApply
|
|
2711
3336
|
}) {
|
|
2712
|
-
injectStyle("bb-
|
|
3337
|
+
injectStyle("bb-ui-tabs", TABS_CSS);
|
|
3338
|
+
injectStyle("bb-font-dialog", STYLE15);
|
|
2713
3339
|
const dialog = new Dialog({ title: "Font", modal: true });
|
|
2714
3340
|
const root = el("div", "bb-fd");
|
|
2715
|
-
const tabs = el("div", "bb-
|
|
3341
|
+
const tabs = el("div", "bb-tabs");
|
|
2716
3342
|
tabs.setAttribute("role", "tablist");
|
|
2717
|
-
const fontTab = el("button", "bb-
|
|
2718
|
-
const advTab = el("button", "bb-
|
|
3343
|
+
const fontTab = el("button", "bb-tab", "Font");
|
|
3344
|
+
const advTab = el("button", "bb-tab", "Advanced");
|
|
2719
3345
|
for (const t of [fontTab, advTab]) {
|
|
2720
3346
|
t.type = "button";
|
|
2721
3347
|
t.setAttribute("role", "tab");
|
|
@@ -2773,8 +3399,8 @@ function openFontDialog({
|
|
|
2773
3399
|
label: "Text color",
|
|
2774
3400
|
clearLabel: "Automatic",
|
|
2775
3401
|
value: () => color,
|
|
2776
|
-
onPick: (
|
|
2777
|
-
color =
|
|
3402
|
+
onPick: (c2) => {
|
|
3403
|
+
color = c2;
|
|
2778
3404
|
paint();
|
|
2779
3405
|
}
|
|
2780
3406
|
});
|
|
@@ -2783,8 +3409,8 @@ function openFontDialog({
|
|
|
2783
3409
|
label: "Highlight",
|
|
2784
3410
|
clearLabel: "No highlight",
|
|
2785
3411
|
value: () => highlight2,
|
|
2786
|
-
onPick: (
|
|
2787
|
-
highlight2 =
|
|
3412
|
+
onPick: (c2) => {
|
|
3413
|
+
highlight2 = c2;
|
|
2788
3414
|
paint();
|
|
2789
3415
|
}
|
|
2790
3416
|
});
|
|
@@ -2909,8 +3535,8 @@ function openFontDialog({
|
|
|
2909
3535
|
s.transform = scale === 100 ? "none" : `scaleX(${scale / 100})`;
|
|
2910
3536
|
s.verticalAlign = supCb.checked ? "super" : subCb.checked ? "sub" : `${positionPt}pt`;
|
|
2911
3537
|
}
|
|
2912
|
-
for (const
|
|
2913
|
-
|
|
3538
|
+
for (const c2 of [familySel, sizeSel, scaleSel])
|
|
3539
|
+
c2.addEventListener("change", paint);
|
|
2914
3540
|
for (const i of [spacingInput, positionInput])
|
|
2915
3541
|
i.addEventListener("input", paint);
|
|
2916
3542
|
const foot = el("div", "bb-fd-foot");
|
|
@@ -2950,7 +3576,7 @@ function openFontDialog({
|
|
|
2950
3576
|
}
|
|
2951
3577
|
|
|
2952
3578
|
// packages/ui/src/lib/symbol-sets.ts
|
|
2953
|
-
var
|
|
3579
|
+
var import_bapbong_contracts5 = require("@shadow-garden/bapbong-contracts");
|
|
2954
3580
|
var g = (id, label, short, pairs) => ({
|
|
2955
3581
|
id,
|
|
2956
3582
|
label,
|
|
@@ -3286,7 +3912,7 @@ var SYMBOL_GROUPS = [
|
|
|
3286
3912
|
])
|
|
3287
3913
|
];
|
|
3288
3914
|
function autoCorrectHint(char) {
|
|
3289
|
-
return
|
|
3915
|
+
return import_bapbong_contracts5.AUTOCORRECT_RULES.find((r) => r.to === char)?.seq ?? "";
|
|
3290
3916
|
}
|
|
3291
3917
|
var SPECIAL_CHARACTERS = [
|
|
3292
3918
|
{ char: "\u2014", name: "Em dash", hint: "" },
|
|
@@ -3331,7 +3957,7 @@ function parseCodePoint(input) {
|
|
|
3331
3957
|
}
|
|
3332
3958
|
var RECENT_MAX = 16;
|
|
3333
3959
|
function pushRecent(recent, char, max = RECENT_MAX) {
|
|
3334
|
-
return [char, ...recent.filter((
|
|
3960
|
+
return [char, ...recent.filter((c2) => c2 !== char)].slice(0, max);
|
|
3335
3961
|
}
|
|
3336
3962
|
function searchSymbols(query) {
|
|
3337
3963
|
const q = query.trim().toLowerCase();
|
|
@@ -3351,7 +3977,7 @@ function searchSymbols(query) {
|
|
|
3351
3977
|
}
|
|
3352
3978
|
|
|
3353
3979
|
// packages/ui/src/lib/symbol-dialog.ts
|
|
3354
|
-
var
|
|
3980
|
+
var STYLE16 = `
|
|
3355
3981
|
.bb-sd{display:flex;flex-direction:column;gap:12px;width:412px;max-width:100%;color:var(--bb-ui-fg,#2c2c2a)}
|
|
3356
3982
|
.bb-sd *{box-sizing:border-box}
|
|
3357
3983
|
.bb-sd-tabs{display:inline-flex;border:0.5px solid var(--bb-ui-control-border,var(--bb-ui-border,#d8d6cf));border-radius:6px;overflow:hidden;align-self:flex-start}
|
|
@@ -3412,7 +4038,7 @@ function glyphFor(char) {
|
|
|
3412
4038
|
return char;
|
|
3413
4039
|
}
|
|
3414
4040
|
function createSymbolDialog(options) {
|
|
3415
|
-
injectStyle("bb-symbol-dialog",
|
|
4041
|
+
injectStyle("bb-symbol-dialog", STYLE16);
|
|
3416
4042
|
let recent = [...options.recent ?? []].slice(0, RECENT_MAX);
|
|
3417
4043
|
let selected = null;
|
|
3418
4044
|
const root = el2("div", "bb-sd");
|
|
@@ -3601,9 +4227,9 @@ function createSymbolDialog(options) {
|
|
|
3601
4227
|
function renderRecent() {
|
|
3602
4228
|
fillGrid(
|
|
3603
4229
|
recentGrid,
|
|
3604
|
-
recent.map((
|
|
3605
|
-
char:
|
|
3606
|
-
name: SYMBOL_NAMES.get(
|
|
4230
|
+
recent.map((c2) => ({
|
|
4231
|
+
char: c2,
|
|
4232
|
+
name: SYMBOL_NAMES.get(c2) ?? "Character"
|
|
3607
4233
|
})),
|
|
3608
4234
|
RECENT_COLS,
|
|
3609
4235
|
"Nothing yet \u2014 inserted symbols appear here."
|
|
@@ -3647,7 +4273,7 @@ function createSymbolDialog(options) {
|
|
|
3647
4273
|
code.removeAttribute("aria-invalid");
|
|
3648
4274
|
const cell = Array.from(
|
|
3649
4275
|
grid.querySelectorAll(".bb-sd-cell")
|
|
3650
|
-
).find((
|
|
4276
|
+
).find((c2) => c2.textContent === glyphFor(ch));
|
|
3651
4277
|
select2(ch, cell ?? null);
|
|
3652
4278
|
} else {
|
|
3653
4279
|
code.setAttribute("aria-invalid", code.value.trim() ? "true" : "false");
|
|
@@ -3690,7 +4316,7 @@ function createSymbolDialog(options) {
|
|
|
3690
4316
|
}
|
|
3691
4317
|
|
|
3692
4318
|
// packages/ui/src/lib/symbol-popover.ts
|
|
3693
|
-
var
|
|
4319
|
+
var STYLE17 = `
|
|
3694
4320
|
.bb-spk{position:fixed;margin:0;max-width:none;max-height:none;z-index:1300;width:276px;padding:10px;background:var(--bb-ui-menu-bg,#fff);-webkit-backdrop-filter:var(--bb-ui-pop-filter,none);backdrop-filter:var(--bb-ui-pop-filter,none);color:var(--bb-ui-fg,#2c2c2a);border:1px solid var(--bb-ui-pop-border,var(--bb-ui-border,#e3e3e0));border-radius:10px;box-shadow:0 8px 28px rgba(0,0,0,.16);font-family:var(--bb-ui-font,system-ui,-apple-system,sans-serif);font-size:12px;box-sizing:border-box;display:flex;flex-direction:column;gap:8px}
|
|
3695
4321
|
.bb-spk *{box-sizing:border-box}
|
|
3696
4322
|
.bb-spk::backdrop{background:transparent}
|
|
@@ -3723,7 +4349,7 @@ function el3(tag, cls, text) {
|
|
|
3723
4349
|
return n;
|
|
3724
4350
|
}
|
|
3725
4351
|
function openSymbolPopover(options) {
|
|
3726
|
-
injectStyle("bb-ui-symbol-popover",
|
|
4352
|
+
injectStyle("bb-ui-symbol-popover", STYLE17);
|
|
3727
4353
|
const { anchor } = options;
|
|
3728
4354
|
let recent = [...options.recent ?? []].slice(0, RECENT_MAX);
|
|
3729
4355
|
let groupId = SYMBOL_GROUPS[0].id;
|
|
@@ -3754,16 +4380,16 @@ function openSymbolPopover(options) {
|
|
|
3754
4380
|
const chips = el3("div", "bb-spk-chips");
|
|
3755
4381
|
const chipEls = /* @__PURE__ */ new Map();
|
|
3756
4382
|
for (const grp of SYMBOL_GROUPS) {
|
|
3757
|
-
const
|
|
3758
|
-
|
|
3759
|
-
|
|
3760
|
-
|
|
4383
|
+
const c2 = el3("button", "bb-spk-chip", grp.short);
|
|
4384
|
+
c2.type = "button";
|
|
4385
|
+
c2.title = grp.label;
|
|
4386
|
+
c2.addEventListener("click", () => {
|
|
3761
4387
|
groupId = grp.id;
|
|
3762
4388
|
search.value = "";
|
|
3763
4389
|
render();
|
|
3764
4390
|
});
|
|
3765
|
-
chips.append(
|
|
3766
|
-
chipEls.set(grp.id,
|
|
4391
|
+
chips.append(c2);
|
|
4392
|
+
chipEls.set(grp.id, c2);
|
|
3767
4393
|
}
|
|
3768
4394
|
const grid = el3("div", "bb-spk-grid");
|
|
3769
4395
|
grid.setAttribute("role", "grid");
|
|
@@ -3834,9 +4460,9 @@ function openSymbolPopover(options) {
|
|
|
3834
4460
|
};
|
|
3835
4461
|
const renderRecent = () => fill(
|
|
3836
4462
|
recentGrid,
|
|
3837
|
-
recent.slice(0, RECENT_ROW).map((
|
|
3838
|
-
char:
|
|
3839
|
-
name: SYMBOL_NAMES.get(
|
|
4463
|
+
recent.slice(0, RECENT_ROW).map((c2) => ({
|
|
4464
|
+
char: c2,
|
|
4465
|
+
name: SYMBOL_NAMES.get(c2) ?? "Character"
|
|
3840
4466
|
})),
|
|
3841
4467
|
"Nothing yet."
|
|
3842
4468
|
);
|
|
@@ -3844,8 +4470,8 @@ function openSymbolPopover(options) {
|
|
|
3844
4470
|
const q = search.value.trim();
|
|
3845
4471
|
const byCode = q ? parseCodePoint(q) : null;
|
|
3846
4472
|
const entries = q ? byCode && !searchSymbols(q).length ? [{ char: byCode, name: SYMBOL_NAMES.get(byCode) ?? "Character" }] : searchSymbols(q) : SYMBOL_GROUPS.find((g2) => g2.id === groupId)?.entries ?? [];
|
|
3847
|
-
for (const [id,
|
|
3848
|
-
|
|
4473
|
+
for (const [id, c2] of chipEls)
|
|
4474
|
+
c2.setAttribute("aria-pressed", String(!q && id === groupId));
|
|
3849
4475
|
fill(grid, entries, "No match.");
|
|
3850
4476
|
const first = grid.querySelector(".bb-spk-cell");
|
|
3851
4477
|
if (q && first && entries[0]) select2(entries[0].char, first);
|
|
@@ -3884,8 +4510,8 @@ function openSymbolPopover(options) {
|
|
|
3884
4510
|
}
|
|
3885
4511
|
|
|
3886
4512
|
// packages/ui/src/lib/shortcuts-dialog.ts
|
|
3887
|
-
var
|
|
3888
|
-
var
|
|
4513
|
+
var import_bapbong_contracts6 = require("@shadow-garden/bapbong-contracts");
|
|
4514
|
+
var STYLE18 = `
|
|
3889
4515
|
.bb-ks{display:flex;flex-direction:column;gap:10px;width:600px;max-width:100%;color:var(--bb-ui-fg,#2c2c2a);font-size:12px}
|
|
3890
4516
|
.bb-ks *{box-sizing:border-box}
|
|
3891
4517
|
.bb-ks-top{display:flex;gap:8px;align-items:center}
|
|
@@ -3943,7 +4569,7 @@ function highlight(text, q) {
|
|
|
3943
4569
|
return out;
|
|
3944
4570
|
}
|
|
3945
4571
|
function openKeyboardShortcutsDialog(options) {
|
|
3946
|
-
injectStyle("bb-ui-shortcuts-dialog",
|
|
4572
|
+
injectStyle("bb-ui-shortcuts-dialog", STYLE18);
|
|
3947
4573
|
const dialog = new Dialog({
|
|
3948
4574
|
title: options.title ?? "Keyboard shortcuts",
|
|
3949
4575
|
modal: true,
|
|
@@ -3970,19 +4596,19 @@ function openKeyboardShortcutsDialog(options) {
|
|
|
3970
4596
|
let sortKey = "title";
|
|
3971
4597
|
let sortAsc = true;
|
|
3972
4598
|
const ths = /* @__PURE__ */ new Map();
|
|
3973
|
-
for (const
|
|
4599
|
+
for (const c2 of columns) {
|
|
3974
4600
|
const th = el4("th");
|
|
3975
|
-
th.append(el4("span", void 0,
|
|
4601
|
+
th.append(el4("span", void 0, c2.label));
|
|
3976
4602
|
th.addEventListener("click", () => {
|
|
3977
|
-
if (sortKey ===
|
|
4603
|
+
if (sortKey === c2.key) sortAsc = !sortAsc;
|
|
3978
4604
|
else {
|
|
3979
|
-
sortKey =
|
|
4605
|
+
sortKey = c2.key;
|
|
3980
4606
|
sortAsc = true;
|
|
3981
4607
|
}
|
|
3982
4608
|
render();
|
|
3983
4609
|
});
|
|
3984
4610
|
headRow.append(th);
|
|
3985
|
-
ths.set(
|
|
4611
|
+
ths.set(c2.key, th);
|
|
3986
4612
|
}
|
|
3987
4613
|
thead.append(headRow);
|
|
3988
4614
|
const tbody = el4("tbody");
|
|
@@ -4002,7 +4628,7 @@ function openKeyboardShortcutsDialog(options) {
|
|
|
4002
4628
|
const rows = [];
|
|
4003
4629
|
for (const src of options.sources)
|
|
4004
4630
|
rows.push(
|
|
4005
|
-
...(0,
|
|
4631
|
+
...(0, import_bapbong_contracts6.keybindingRows)(src.keybindings, (c2) => src.commands.get(c2)?.title)
|
|
4006
4632
|
);
|
|
4007
4633
|
return rows;
|
|
4008
4634
|
};
|
|
@@ -4010,13 +4636,13 @@ function openKeyboardShortcutsDialog(options) {
|
|
|
4010
4636
|
const td = el4("td");
|
|
4011
4637
|
keys.forEach((k, i) => {
|
|
4012
4638
|
if (i > 0) td.append(el4("span", "or", "or"));
|
|
4013
|
-
for (const part of (0,
|
|
4639
|
+
for (const part of (0, import_bapbong_contracts6.formatKey)(k, IS_MAC))
|
|
4014
4640
|
td.append(el4("kbd", void 0, part));
|
|
4015
4641
|
});
|
|
4016
4642
|
return td;
|
|
4017
4643
|
};
|
|
4018
4644
|
const sortRows = (rows) => {
|
|
4019
|
-
const val = (r) => sortKey === "title" ? r.title : sortKey === "keys" ? r.keys.map((k) => (0,
|
|
4645
|
+
const val = (r) => sortKey === "title" ? r.title : sortKey === "keys" ? r.keys.map((k) => (0, import_bapbong_contracts6.formatKey)(k, IS_MAC).join("")).join(" ") : sortKey === "when" ? r.when ?? "" : r.source;
|
|
4020
4646
|
const sorted = [...rows].sort(
|
|
4021
4647
|
(a, b) => val(a).localeCompare(val(b), void 0, { sensitivity: "base" })
|
|
4022
4648
|
);
|
|
@@ -4025,7 +4651,7 @@ function openKeyboardShortcutsDialog(options) {
|
|
|
4025
4651
|
const render = () => {
|
|
4026
4652
|
const q = search.value.trim().toLowerCase();
|
|
4027
4653
|
const rows = allRows();
|
|
4028
|
-
const shown = sortRows((0,
|
|
4654
|
+
const shown = sortRows((0, import_bapbong_contracts6.filterKeybindingRows)(rows, q, IS_MAC));
|
|
4029
4655
|
for (const [key, th] of ths) {
|
|
4030
4656
|
if (key === sortKey)
|
|
4031
4657
|
th.setAttribute("aria-sort", sortAsc ? "ascending" : "descending");
|
|
@@ -4059,7 +4685,7 @@ function openKeyboardShortcutsDialog(options) {
|
|
|
4059
4685
|
tbody.append(tr);
|
|
4060
4686
|
}
|
|
4061
4687
|
count.textContent = shown.length === rows.length ? `${rows.length} shortcuts` : `${shown.length} of ${rows.length}`;
|
|
4062
|
-
footL.textContent = `Sorted by ${columns.find((
|
|
4688
|
+
footL.textContent = `Sorted by ${columns.find((c2) => c2.key === sortKey)?.label.toLowerCase()} \xB7 click a header to sort`;
|
|
4063
4689
|
};
|
|
4064
4690
|
search.addEventListener("input", render);
|
|
4065
4691
|
dialog.onClose(() => dialog.destroy());
|
|
@@ -4069,7 +4695,7 @@ function openKeyboardShortcutsDialog(options) {
|
|
|
4069
4695
|
}
|
|
4070
4696
|
|
|
4071
4697
|
// packages/ui/src/lib/scrollbars.ts
|
|
4072
|
-
var
|
|
4698
|
+
var STYLE19 = `
|
|
4073
4699
|
@property --bb-scroll-thumb-now {
|
|
4074
4700
|
syntax: '<color>';
|
|
4075
4701
|
/* MUST inherit: the thumb pseudo-element never matches .bb-scrolling
|
|
@@ -4101,7 +4727,7 @@ var STYLE16 = `
|
|
|
4101
4727
|
var installed = null;
|
|
4102
4728
|
function installScrollbars(root = document) {
|
|
4103
4729
|
if (installed) return installed;
|
|
4104
|
-
injectStyle("bb-ui-scrollbars",
|
|
4730
|
+
injectStyle("bb-ui-scrollbars", STYLE19);
|
|
4105
4731
|
const quiet = /* @__PURE__ */ new WeakMap();
|
|
4106
4732
|
const onScroll = (ev) => {
|
|
4107
4733
|
const el5 = ev.target instanceof HTMLElement ? ev.target : root.documentElement;
|
|
@@ -4121,6 +4747,7 @@ function installScrollbars(root = document) {
|
|
|
4121
4747
|
}
|
|
4122
4748
|
// Annotate the CommonJS export names for ESM import in node:
|
|
4123
4749
|
0 && (module.exports = {
|
|
4750
|
+
BUILT_IN_EQUATIONS,
|
|
4124
4751
|
COLOR_PALETTE,
|
|
4125
4752
|
Dialog,
|
|
4126
4753
|
RECENT_MAX,
|
|
@@ -4133,8 +4760,13 @@ function installScrollbars(root = document) {
|
|
|
4133
4760
|
createFindDialog,
|
|
4134
4761
|
createSectionChip,
|
|
4135
4762
|
createSymbolDialog,
|
|
4763
|
+
createTableStylePanel,
|
|
4136
4764
|
defaultMenus,
|
|
4137
4765
|
defaultToolbarGroups,
|
|
4766
|
+
equationGallery,
|
|
4767
|
+
equationPanel,
|
|
4768
|
+
equationPreviewSvg,
|
|
4769
|
+
foldPlan,
|
|
4138
4770
|
installScrollbars,
|
|
4139
4771
|
marginPresetPicker,
|
|
4140
4772
|
mountMenubar,
|