@shadow-garden/bapbong-ui 0.14.0 → 0.16.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 +491 -95
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +485 -89
- 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 +33 -0
- package/dist/lib/equation-panel.d.ts.map +1 -0
- package/dist/lib/link-panel.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,
|
|
@@ -34,6 +35,9 @@ __export(index_exports, {
|
|
|
34
35
|
createSymbolDialog: () => createSymbolDialog,
|
|
35
36
|
defaultMenus: () => defaultMenus,
|
|
36
37
|
defaultToolbarGroups: () => defaultToolbarGroups,
|
|
38
|
+
equationGallery: () => equationGallery,
|
|
39
|
+
equationPanel: () => equationPanel,
|
|
40
|
+
equationPreviewSvg: () => equationPreviewSvg,
|
|
37
41
|
installScrollbars: () => installScrollbars,
|
|
38
42
|
marginPresetPicker: () => marginPresetPicker,
|
|
39
43
|
mountMenubar: () => mountMenubar,
|
|
@@ -97,12 +101,12 @@ function placeFloating(el5, anchor) {
|
|
|
97
101
|
}
|
|
98
102
|
function rovingGrid(cells) {
|
|
99
103
|
let cur = [0, 0];
|
|
100
|
-
const at = (r,
|
|
101
|
-
const focusCell = (r,
|
|
104
|
+
const at = (r, c2) => cells[r]?.[c2];
|
|
105
|
+
const focusCell = (r, c2) => {
|
|
102
106
|
const rows = cells.length;
|
|
103
107
|
if (rows === 0) return;
|
|
104
108
|
const nr = Math.min(rows - 1, Math.max(0, r));
|
|
105
|
-
const nc = Math.min(cells[nr].length - 1, Math.max(0,
|
|
109
|
+
const nc = Math.min(cells[nr].length - 1, Math.max(0, c2));
|
|
106
110
|
const prev = at(cur[0], cur[1]);
|
|
107
111
|
if (prev) prev.tabIndex = -1;
|
|
108
112
|
const next = at(nr, nc);
|
|
@@ -112,9 +116,9 @@ function rovingGrid(cells) {
|
|
|
112
116
|
cur = [nr, nc];
|
|
113
117
|
};
|
|
114
118
|
cells.forEach(
|
|
115
|
-
(row, r) => row.forEach((cell,
|
|
119
|
+
(row, r) => row.forEach((cell, c2) => {
|
|
116
120
|
cell.setAttribute("role", "gridcell");
|
|
117
|
-
cell.tabIndex = r === 0 &&
|
|
121
|
+
cell.tabIndex = r === 0 && c2 === 0 ? 0 : -1;
|
|
118
122
|
cell.addEventListener("keydown", (e) => {
|
|
119
123
|
const delta = {
|
|
120
124
|
ArrowRight: [0, 1],
|
|
@@ -127,10 +131,10 @@ function rovingGrid(cells) {
|
|
|
127
131
|
const d = delta[e.key];
|
|
128
132
|
if (!d) return;
|
|
129
133
|
e.preventDefault();
|
|
130
|
-
focusCell(r + d[0],
|
|
134
|
+
focusCell(r + d[0], c2 + d[1]);
|
|
131
135
|
});
|
|
132
136
|
cell.addEventListener("focus", () => {
|
|
133
|
-
cur = [r,
|
|
137
|
+
cur = [r, c2];
|
|
134
138
|
});
|
|
135
139
|
})
|
|
136
140
|
);
|
|
@@ -460,9 +464,9 @@ function openColorPicker({
|
|
|
460
464
|
panel.remove();
|
|
461
465
|
anchor.focus();
|
|
462
466
|
};
|
|
463
|
-
const pick = (
|
|
464
|
-
if (
|
|
465
|
-
onPick(
|
|
467
|
+
const pick = (c2) => {
|
|
468
|
+
if (c2 && !COLOR_PALETTE.some((row) => row.includes(c2))) remember(c2);
|
|
469
|
+
onPick(c2);
|
|
466
470
|
close();
|
|
467
471
|
};
|
|
468
472
|
if (clearLabel !== void 0) {
|
|
@@ -506,15 +510,15 @@ function openColorPicker({
|
|
|
506
510
|
);
|
|
507
511
|
const customRow2 = document.createElement("div");
|
|
508
512
|
customRow2.className = "bb-cpk-row";
|
|
509
|
-
for (const
|
|
513
|
+
for (const c2 of customColors) {
|
|
510
514
|
const sw = document.createElement("button");
|
|
511
515
|
sw.type = "button";
|
|
512
516
|
sw.className = "bb-cpk-sw";
|
|
513
|
-
sw.style.background =
|
|
514
|
-
sw.title =
|
|
515
|
-
sw.setAttribute("aria-label",
|
|
516
|
-
if (
|
|
517
|
-
sw.addEventListener("click", () => pick(
|
|
517
|
+
sw.style.background = c2;
|
|
518
|
+
sw.title = c2;
|
|
519
|
+
sw.setAttribute("aria-label", c2);
|
|
520
|
+
if (c2.toUpperCase() === value?.toUpperCase()) sw.classList.add("on");
|
|
521
|
+
sw.addEventListener("click", () => pick(c2));
|
|
518
522
|
customRow2.append(sw);
|
|
519
523
|
}
|
|
520
524
|
const plus = document.createElement("button");
|
|
@@ -598,8 +602,8 @@ function colorButton(o) {
|
|
|
598
602
|
anchor: el5,
|
|
599
603
|
value: o.value(),
|
|
600
604
|
clearLabel: o.clearLabel,
|
|
601
|
-
onPick: (
|
|
602
|
-
o.onPick(
|
|
605
|
+
onPick: (c2) => {
|
|
606
|
+
o.onPick(c2);
|
|
603
607
|
sync();
|
|
604
608
|
}
|
|
605
609
|
});
|
|
@@ -710,7 +714,7 @@ var STYLE3 = `
|
|
|
710
714
|
.bb-split-bar{flex:1;height:3px;border-radius:2px;background:var(--bb-ui-border,#d9d9d4)}
|
|
711
715
|
`;
|
|
712
716
|
function defaultToolbarGroups(commands) {
|
|
713
|
-
const names = [...commands].map((
|
|
717
|
+
const names = [...commands].map((c2) => c2.name);
|
|
714
718
|
const aligns = names.filter((n) => n.startsWith("align-"));
|
|
715
719
|
const rest = names.filter((n) => !n.startsWith("align-"));
|
|
716
720
|
return [rest, aligns].filter((g2) => g2.length > 0);
|
|
@@ -960,7 +964,7 @@ function mountToolbar(host, editor, options = {}) {
|
|
|
960
964
|
el5.disabled = cmd.isEnabled ? !cmd.isEnabled(state) : false;
|
|
961
965
|
}
|
|
962
966
|
for (const { spec, el: el5 } of selects) el5.value = spec.value(state);
|
|
963
|
-
for (const
|
|
967
|
+
for (const c2 of colors) c2.sync();
|
|
964
968
|
for (const { spec, cards } of splits) {
|
|
965
969
|
const selected = spec.value(state);
|
|
966
970
|
for (const card of cards)
|
|
@@ -970,7 +974,7 @@ function mountToolbar(host, editor, options = {}) {
|
|
|
970
974
|
);
|
|
971
975
|
}
|
|
972
976
|
};
|
|
973
|
-
const off = editor.onChange((
|
|
977
|
+
const off = editor.onChange((c2) => refresh(c2.state));
|
|
974
978
|
try {
|
|
975
979
|
refresh(editor.state);
|
|
976
980
|
} catch {
|
|
@@ -1214,7 +1218,7 @@ function showMenu(entries, at, options = {}) {
|
|
|
1214
1218
|
return handle;
|
|
1215
1219
|
}
|
|
1216
1220
|
function defaultMenus(commands) {
|
|
1217
|
-
const names = [...commands].map((
|
|
1221
|
+
const names = [...commands].map((c2) => c2.name);
|
|
1218
1222
|
const marks = ["bold", "italic", "underline", "strike"].filter(
|
|
1219
1223
|
(n) => commands.has(n)
|
|
1220
1224
|
);
|
|
@@ -1328,10 +1332,10 @@ function mountMenubar(host, editor, options = {}) {
|
|
|
1328
1332
|
function refresh(state) {
|
|
1329
1333
|
latest = state;
|
|
1330
1334
|
if (openIdx < 0) return;
|
|
1331
|
-
for (const
|
|
1335
|
+
for (const c2 of checks) c2.el.textContent = c2.active(state) ? "\u2713" : "";
|
|
1332
1336
|
for (const e of enables) e.el.disabled = !e.enabled(state);
|
|
1333
1337
|
}
|
|
1334
|
-
const off = editor.onChange((
|
|
1338
|
+
const off = editor.onChange((c2) => refresh(c2.state));
|
|
1335
1339
|
try {
|
|
1336
1340
|
latest = editor.state;
|
|
1337
1341
|
} catch {
|
|
@@ -1659,13 +1663,13 @@ function showLinkPanel(opts) {
|
|
|
1659
1663
|
row.appendChild(icon);
|
|
1660
1664
|
const label = document.createElement("span");
|
|
1661
1665
|
label.className = "bb-linkpanel-href";
|
|
1662
|
-
label.textContent = internal.label ?? "
|
|
1666
|
+
label.textContent = internal.label ?? "This place is no longer in the document";
|
|
1663
1667
|
label.title = internal.label ?? existing.href;
|
|
1664
1668
|
if (!internal.label) label.classList.add("bb-linkpanel-stale");
|
|
1665
1669
|
row.appendChild(label);
|
|
1666
1670
|
if (internal.label) {
|
|
1667
1671
|
row.appendChild(
|
|
1668
|
-
iconBtn(ICONS.goTo, "
|
|
1672
|
+
iconBtn(ICONS.goTo, "Go to this place", () => {
|
|
1669
1673
|
closeCurrent2();
|
|
1670
1674
|
internal.onGo();
|
|
1671
1675
|
})
|
|
@@ -1879,8 +1883,8 @@ function openCellProperties({
|
|
|
1879
1883
|
label: "Fill",
|
|
1880
1884
|
clearLabel: "No fill",
|
|
1881
1885
|
value: () => background,
|
|
1882
|
-
onPick: (
|
|
1883
|
-
background =
|
|
1886
|
+
onPick: (c2) => {
|
|
1887
|
+
background = c2;
|
|
1884
1888
|
}
|
|
1885
1889
|
});
|
|
1886
1890
|
fill.append(fillBtn.el);
|
|
@@ -1933,8 +1937,8 @@ function openCellProperties({
|
|
|
1933
1937
|
title: "Border colour",
|
|
1934
1938
|
label: "Colour",
|
|
1935
1939
|
value: () => penColor,
|
|
1936
|
-
onPick: (
|
|
1937
|
-
if (
|
|
1940
|
+
onPick: (c2) => {
|
|
1941
|
+
if (c2) penColor = c2;
|
|
1938
1942
|
}
|
|
1939
1943
|
});
|
|
1940
1944
|
penRow.append(widthSel, styleSel, penBtn.el);
|
|
@@ -1998,8 +2002,396 @@ function openCellProperties({
|
|
|
1998
2002
|
dialog.open();
|
|
1999
2003
|
}
|
|
2000
2004
|
|
|
2001
|
-
// packages/ui/src/lib/
|
|
2005
|
+
// packages/ui/src/lib/equation-gallery.ts
|
|
2006
|
+
var import_bapbong_contracts2 = require("@shadow-garden/bapbong-contracts");
|
|
2007
|
+
var c = (s) => [...s].map((ch) => ({ t: "chr", ch }));
|
|
2008
|
+
var sup = (base, exp) => ({
|
|
2009
|
+
t: "scr",
|
|
2010
|
+
base,
|
|
2011
|
+
sub: [],
|
|
2012
|
+
sup: c(exp)
|
|
2013
|
+
});
|
|
2014
|
+
var subsup = (base, lo, hi) => ({
|
|
2015
|
+
t: "scr",
|
|
2016
|
+
base,
|
|
2017
|
+
sub: c(lo),
|
|
2018
|
+
sup: c(hi)
|
|
2019
|
+
});
|
|
2020
|
+
var BUILT_IN_EQUATIONS = [
|
|
2021
|
+
{
|
|
2022
|
+
name: "Area of a circle",
|
|
2023
|
+
ast: [...c("\u{1D434} = \u{1D70B}"), sup(c("\u{1D45F}"), "2")]
|
|
2024
|
+
},
|
|
2025
|
+
{
|
|
2026
|
+
name: "Pythagorean theorem",
|
|
2027
|
+
ast: [
|
|
2028
|
+
sup(c("\u{1D44E}"), "2"),
|
|
2029
|
+
...c(" + "),
|
|
2030
|
+
sup(c("\u{1D44F}"), "2"),
|
|
2031
|
+
...c(" = "),
|
|
2032
|
+
sup(c("\u{1D450}"), "2")
|
|
2033
|
+
]
|
|
2034
|
+
},
|
|
2035
|
+
{
|
|
2036
|
+
name: "Quadratic formula",
|
|
2037
|
+
ast: [
|
|
2038
|
+
...c("\u{1D465} = "),
|
|
2039
|
+
{
|
|
2040
|
+
t: "frac",
|
|
2041
|
+
num: [
|
|
2042
|
+
...c("\u2212\u{1D44F} \xB1 "),
|
|
2043
|
+
{
|
|
2044
|
+
t: "rad",
|
|
2045
|
+
deg: [],
|
|
2046
|
+
body: [sup(c("\u{1D44F}"), "2"), ...c(" \u2212 4\u{1D44E}\u{1D450}")]
|
|
2047
|
+
}
|
|
2048
|
+
],
|
|
2049
|
+
den: c("2\u{1D44E}")
|
|
2050
|
+
}
|
|
2051
|
+
]
|
|
2052
|
+
},
|
|
2053
|
+
{
|
|
2054
|
+
name: "Law of cosines",
|
|
2055
|
+
ast: [
|
|
2056
|
+
sup(c("\u{1D44E}"), "2"),
|
|
2057
|
+
...c(" = "),
|
|
2058
|
+
sup(c("\u{1D44F}"), "2"),
|
|
2059
|
+
...c(" + "),
|
|
2060
|
+
sup(c("\u{1D450}"), "2"),
|
|
2061
|
+
...c(" \u2212 2\u{1D44F}\u{1D450} cos \u{1D434}")
|
|
2062
|
+
]
|
|
2063
|
+
},
|
|
2064
|
+
{
|
|
2065
|
+
name: "Binomial theorem",
|
|
2066
|
+
ast: [
|
|
2067
|
+
// The exponent belongs ON the bracket: a script with an empty base
|
|
2068
|
+
// would render its own empty slot — the dotted placeholder box.
|
|
2069
|
+
{
|
|
2070
|
+
t: "scr",
|
|
2071
|
+
base: [{ t: "fence", l: "(", r: ")", body: c("\u{1D44E} + \u{1D44F}") }],
|
|
2072
|
+
sub: [],
|
|
2073
|
+
sup: c("\u{1D45B}")
|
|
2074
|
+
},
|
|
2075
|
+
...c(" = "),
|
|
2076
|
+
{
|
|
2077
|
+
t: "big",
|
|
2078
|
+
op: "\u2211",
|
|
2079
|
+
lo: c("\u{1D458} = 0"),
|
|
2080
|
+
hi: c("\u{1D45B}"),
|
|
2081
|
+
body: [
|
|
2082
|
+
subsup(c("\u{1D436}"), "\u{1D45B}", "\u{1D458}"),
|
|
2083
|
+
sup(c("\u{1D44E}"), "\u{1D458}"),
|
|
2084
|
+
{ t: "scr", base: c("\u{1D44F}"), sub: [], sup: c("\u{1D45B}\u2212\u{1D458}") }
|
|
2085
|
+
]
|
|
2086
|
+
}
|
|
2087
|
+
]
|
|
2088
|
+
}
|
|
2089
|
+
];
|
|
2090
|
+
var SVG_NS = "http://www.w3.org/2000/svg";
|
|
2091
|
+
function equationPreviewSvg(spec, opts = {}) {
|
|
2092
|
+
const svg = document.createElementNS(SVG_NS, "svg");
|
|
2093
|
+
svg.setAttribute("viewBox", `0 0 ${spec.width} ${spec.height}`);
|
|
2094
|
+
const max = opts.maxWidth ?? spec.width;
|
|
2095
|
+
const scale = Math.min(1, max / Math.max(1, spec.width));
|
|
2096
|
+
svg.setAttribute("width", String(Math.round(spec.width * scale)));
|
|
2097
|
+
svg.setAttribute("height", String(Math.round(spec.height * scale)));
|
|
2098
|
+
svg.setAttribute("aria-hidden", "true");
|
|
2099
|
+
for (const op of spec.ops) svg.append(opElement(op));
|
|
2100
|
+
return svg;
|
|
2101
|
+
}
|
|
2102
|
+
function opElement(op) {
|
|
2103
|
+
if (op.kind === "line") {
|
|
2104
|
+
const el6 = document.createElementNS(SVG_NS, "line");
|
|
2105
|
+
el6.setAttribute("x1", String(op.x1));
|
|
2106
|
+
el6.setAttribute("y1", String(op.y1));
|
|
2107
|
+
el6.setAttribute("x2", String(op.x2));
|
|
2108
|
+
el6.setAttribute("y2", String(op.y2));
|
|
2109
|
+
el6.setAttribute("stroke", op.color);
|
|
2110
|
+
el6.setAttribute("stroke-width", String(Math.max(op.width, 0.75)));
|
|
2111
|
+
return el6;
|
|
2112
|
+
}
|
|
2113
|
+
if (op.kind === "polygon") {
|
|
2114
|
+
const el6 = document.createElementNS(SVG_NS, "polygon");
|
|
2115
|
+
el6.setAttribute("points", op.points.map((p) => `${p.x},${p.y}`).join(" "));
|
|
2116
|
+
el6.setAttribute("fill", op.fill ?? "none");
|
|
2117
|
+
if (op.stroke) {
|
|
2118
|
+
el6.setAttribute("stroke", op.stroke);
|
|
2119
|
+
el6.setAttribute("stroke-width", String(op.strokeWidth ?? 1));
|
|
2120
|
+
}
|
|
2121
|
+
return el6;
|
|
2122
|
+
}
|
|
2123
|
+
const el5 = document.createElementNS(SVG_NS, "text");
|
|
2124
|
+
el5.setAttribute("x", String(op.x));
|
|
2125
|
+
el5.setAttribute("y", String(op.y));
|
|
2126
|
+
el5.setAttribute("font-size", String(op.size));
|
|
2127
|
+
el5.setAttribute("font-family", op.family);
|
|
2128
|
+
el5.setAttribute("fill", op.color);
|
|
2129
|
+
if (op.bold) el5.setAttribute("font-weight", "bold");
|
|
2130
|
+
if (op.italic) el5.setAttribute("font-style", "italic");
|
|
2131
|
+
if (op.vAlign === "top") el5.setAttribute("dominant-baseline", "hanging");
|
|
2132
|
+
if (op.dx) {
|
|
2133
|
+
let x = op.x;
|
|
2134
|
+
for (const [i, ch] of [...op.text].entries()) {
|
|
2135
|
+
const t = document.createElementNS(SVG_NS, "tspan");
|
|
2136
|
+
t.setAttribute("x", String(x));
|
|
2137
|
+
t.textContent = ch;
|
|
2138
|
+
el5.append(t);
|
|
2139
|
+
x += op.dx[i] ?? 0;
|
|
2140
|
+
}
|
|
2141
|
+
} else {
|
|
2142
|
+
el5.textContent = op.text;
|
|
2143
|
+
}
|
|
2144
|
+
return el5;
|
|
2145
|
+
}
|
|
2002
2146
|
var STYLE9 = `
|
|
2147
|
+
.bb-eqg{display:flex;flex-direction:column;min-width:236px;max-width:300px;user-select:none}
|
|
2148
|
+
.bb-eqg-head{font-size:11px;font-weight:600;opacity:.55;padding:2px 8px 6px}
|
|
2149
|
+
.bb-eqg-list{display:flex;flex-direction:column;max-height:320px;overflow-y:auto}
|
|
2150
|
+
.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}
|
|
2151
|
+
.bb-eqg-item:hover{background:var(--bb-ui-hover,#f1efe8)}
|
|
2152
|
+
.bb-eqg-name{font-size:11px;opacity:.6}
|
|
2153
|
+
/* The preview is the equation TYPESET \u2014 the same display list the canvas
|
|
2154
|
+
paints. The text form is the fallback for a host that cannot lay out. */
|
|
2155
|
+
.bb-eqg-prev{display:flex;align-items:center;min-height:22px;max-width:100%;overflow:hidden}
|
|
2156
|
+
.bb-eqg-prev svg{display:block}
|
|
2157
|
+
.bb-eqg-prev-text{font-family:"Times New Roman",Tinos,serif;font-size:15px;line-height:1.35;white-space:nowrap;text-overflow:ellipsis}
|
|
2158
|
+
.bb-eqg-foot{margin-top:4px;padding-top:5px;border-top:1px solid var(--bb-ui-border,#e3e3e0)}
|
|
2159
|
+
.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}
|
|
2160
|
+
.bb-eqg-new:hover{background:var(--bb-ui-hover,#f1efe8)}
|
|
2161
|
+
.bb-eqg-key{margin-left:auto;opacity:.5;font-size:12px}
|
|
2162
|
+
`;
|
|
2163
|
+
var PREVIEW_PT = 11;
|
|
2164
|
+
var PREVIEW_MAX_W = 264;
|
|
2165
|
+
function equationGallery(options) {
|
|
2166
|
+
injectStyle("bb-ui-eqg-styles", STYLE9);
|
|
2167
|
+
const root = document.createElement("div");
|
|
2168
|
+
root.className = "bb-eqg";
|
|
2169
|
+
const head = document.createElement("div");
|
|
2170
|
+
head.className = "bb-eqg-head";
|
|
2171
|
+
head.textContent = "Built-in";
|
|
2172
|
+
root.append(head);
|
|
2173
|
+
const list = document.createElement("div");
|
|
2174
|
+
list.className = "bb-eqg-list";
|
|
2175
|
+
for (const item of options.items ?? BUILT_IN_EQUATIONS) {
|
|
2176
|
+
const btn = document.createElement("button");
|
|
2177
|
+
btn.type = "button";
|
|
2178
|
+
btn.className = "bb-eqg-item";
|
|
2179
|
+
const prev = document.createElement("div");
|
|
2180
|
+
prev.className = "bb-eqg-prev";
|
|
2181
|
+
const spec = options.layout?.(item.ast, PREVIEW_PT) ?? null;
|
|
2182
|
+
if (spec && spec.ops.length)
|
|
2183
|
+
prev.append(equationPreviewSvg(spec, { maxWidth: PREVIEW_MAX_W }));
|
|
2184
|
+
else {
|
|
2185
|
+
prev.classList.add("bb-eqg-prev-text");
|
|
2186
|
+
prev.textContent = (0, import_bapbong_contracts2.astToLinear)(item.ast);
|
|
2187
|
+
}
|
|
2188
|
+
const name = document.createElement("div");
|
|
2189
|
+
name.className = "bb-eqg-name";
|
|
2190
|
+
name.textContent = item.name;
|
|
2191
|
+
btn.append(prev, name);
|
|
2192
|
+
btn.addEventListener("mousedown", (e) => e.preventDefault());
|
|
2193
|
+
btn.addEventListener("click", () => options.onPick(item.ast));
|
|
2194
|
+
list.append(btn);
|
|
2195
|
+
}
|
|
2196
|
+
root.append(list);
|
|
2197
|
+
const foot = document.createElement("div");
|
|
2198
|
+
foot.className = "bb-eqg-foot";
|
|
2199
|
+
const neu = document.createElement("button");
|
|
2200
|
+
neu.type = "button";
|
|
2201
|
+
neu.className = "bb-eqg-new";
|
|
2202
|
+
const label = document.createElement("span");
|
|
2203
|
+
label.textContent = "Insert new equation";
|
|
2204
|
+
neu.append(label);
|
|
2205
|
+
if (options.newShortcut) {
|
|
2206
|
+
const key = document.createElement("span");
|
|
2207
|
+
key.className = "bb-eqg-key";
|
|
2208
|
+
key.textContent = options.newShortcut;
|
|
2209
|
+
neu.append(key);
|
|
2210
|
+
}
|
|
2211
|
+
neu.addEventListener("mousedown", (e) => e.preventDefault());
|
|
2212
|
+
neu.addEventListener("click", () => options.onNew());
|
|
2213
|
+
foot.append(neu);
|
|
2214
|
+
root.append(foot);
|
|
2215
|
+
return root;
|
|
2216
|
+
}
|
|
2217
|
+
|
|
2218
|
+
// packages/ui/src/lib/equation-panel.ts
|
|
2219
|
+
var import_bapbong_contracts3 = require("@shadow-garden/bapbong-contracts");
|
|
2220
|
+
var SHORTHAND = /* @__PURE__ */ new Map();
|
|
2221
|
+
for (const [name, ch] of Object.entries(import_bapbong_contracts3.MATH_AUTOCORRECT))
|
|
2222
|
+
if (!SHORTHAND.has(ch)) SHORTHAND.set(ch, `\\${name}`);
|
|
2223
|
+
var PREVIEW_PT2 = 10;
|
|
2224
|
+
var STYLE10 = `
|
|
2225
|
+
.bb-eqp{width:352px;display:flex;flex-direction:column;background:var(--bb-ui-bg,#fff);border:0.5px solid var(--bb-ui-border,#e3e3e0);border-radius:10px;box-shadow:0 4px 16px rgba(0,0,0,.13);user-select:none;overflow:hidden}
|
|
2226
|
+
.bb-eqp-tabs{display:flex;align-items:flex-end;gap:2px;padding:5px 5px 0;border-bottom:0.5px solid var(--bb-ui-border,#e3e3e0)}
|
|
2227
|
+
.bb-eqp.is-collapsed .bb-eqp-tabs{border-bottom:0}
|
|
2228
|
+
.bb-eqp-tab{padding:6px 11px;border:0;border-radius:6px 6px 0 0;background:transparent;color:inherit;font:inherit;font-size:13px;opacity:.65;cursor:pointer}
|
|
2229
|
+
.bb-eqp-tab:hover{background:var(--bb-ui-hover,#f1efe8)}
|
|
2230
|
+
.bb-eqp-tab[aria-selected="true"]{opacity:1;background:var(--bb-ui-sel,#e6f1fb);color:var(--bb-ui-sel-fg,#0c447c)}
|
|
2231
|
+
.bb-eqp-fold{margin-left:auto;margin-bottom:5px;width:24px;height:24px;display:flex;align-items:center;justify-content:center;padding:0;border:0;border-radius:6px;background:transparent;color:inherit;opacity:.5;cursor:pointer}
|
|
2232
|
+
.bb-eqp-fold:hover{background:var(--bb-ui-hover,#f1efe8);opacity:.9}
|
|
2233
|
+
.bb-eqp-body{padding:8px}
|
|
2234
|
+
.bb-eqp.is-collapsed .bb-eqp-body{display:none}
|
|
2235
|
+
.bb-eqp-set{width:100%;height:30px;margin-bottom:7px;font:inherit;font-size:13px}
|
|
2236
|
+
.bb-eqp-grid{display:grid;grid-template-columns:repeat(10,1fr);gap:1px;max-height:190px;overflow-y:auto}
|
|
2237
|
+
.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}
|
|
2238
|
+
.bb-eqp-sym:hover{background:var(--bb-ui-hover,#f1efe8)}
|
|
2239
|
+
.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}
|
|
2240
|
+
.bb-eqp-hint-g{font-family:"Cambria Math","Times New Roman",Tinos,serif;font-size:15px}
|
|
2241
|
+
.bb-eqp-hint-k{font-family:ui-monospace,SFMono-Regular,Menlo,monospace}
|
|
2242
|
+
.bb-eqp-scroll{max-height:230px;overflow-y:auto}
|
|
2243
|
+
.bb-eqp-group{font-size:11px;font-weight:600;opacity:.5;padding:6px 2px 3px}
|
|
2244
|
+
.bb-eqp-row{display:grid;grid-template-columns:repeat(4,1fr);gap:3px}
|
|
2245
|
+
.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}
|
|
2246
|
+
.bb-eqp-st:hover{background:var(--bb-ui-hover,#f1efe8)}
|
|
2247
|
+
.bb-eqp-st-name{font-size:10px;opacity:.6;text-align:center;line-height:1.25}
|
|
2248
|
+
.bb-eqp-st svg{display:block}
|
|
2249
|
+
`;
|
|
2250
|
+
var CHEVRON_UP = '<svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M6 15l6-6 6 6"/></svg>';
|
|
2251
|
+
var CHEVRON_DOWN = '<svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M6 9l6 6 6-6"/></svg>';
|
|
2252
|
+
function equationPanel(options) {
|
|
2253
|
+
injectStyle("bb-ui-eqp-styles", STYLE10);
|
|
2254
|
+
const root = document.createElement("div");
|
|
2255
|
+
root.className = "bb-eqp";
|
|
2256
|
+
root.setAttribute("role", "group");
|
|
2257
|
+
root.setAttribute("aria-label", "Equation palette");
|
|
2258
|
+
root.addEventListener("mousedown", (e) => e.preventDefault());
|
|
2259
|
+
const tabs = document.createElement("div");
|
|
2260
|
+
tabs.className = "bb-eqp-tabs";
|
|
2261
|
+
tabs.setAttribute("role", "tablist");
|
|
2262
|
+
const body = document.createElement("div");
|
|
2263
|
+
body.className = "bb-eqp-body";
|
|
2264
|
+
let collapsed = false;
|
|
2265
|
+
let current3 = "symbols";
|
|
2266
|
+
const tabEls = {};
|
|
2267
|
+
const mkTab = (id, label) => {
|
|
2268
|
+
const b = document.createElement("button");
|
|
2269
|
+
b.type = "button";
|
|
2270
|
+
b.className = "bb-eqp-tab";
|
|
2271
|
+
b.textContent = label;
|
|
2272
|
+
b.setAttribute("role", "tab");
|
|
2273
|
+
b.addEventListener("click", () => {
|
|
2274
|
+
current3 = id;
|
|
2275
|
+
if (collapsed) setCollapsed(false);
|
|
2276
|
+
render();
|
|
2277
|
+
});
|
|
2278
|
+
tabEls[id] = b;
|
|
2279
|
+
tabs.append(b);
|
|
2280
|
+
};
|
|
2281
|
+
mkTab("symbols", "Symbols");
|
|
2282
|
+
mkTab("structures", "Structures");
|
|
2283
|
+
const fold = document.createElement("button");
|
|
2284
|
+
fold.type = "button";
|
|
2285
|
+
fold.className = "bb-eqp-fold";
|
|
2286
|
+
fold.addEventListener("click", () => setCollapsed(!collapsed));
|
|
2287
|
+
tabs.append(fold);
|
|
2288
|
+
root.append(tabs, body);
|
|
2289
|
+
function setCollapsed(next) {
|
|
2290
|
+
collapsed = next;
|
|
2291
|
+
root.classList.toggle("is-collapsed", collapsed);
|
|
2292
|
+
fold.innerHTML = collapsed ? CHEVRON_DOWN : CHEVRON_UP;
|
|
2293
|
+
fold.setAttribute(
|
|
2294
|
+
"aria-label",
|
|
2295
|
+
collapsed ? "Show palette" : "Hide palette"
|
|
2296
|
+
);
|
|
2297
|
+
fold.setAttribute("aria-expanded", String(!collapsed));
|
|
2298
|
+
}
|
|
2299
|
+
function symbolsBody() {
|
|
2300
|
+
const set = document.createElement("select");
|
|
2301
|
+
set.className = "bb-eqp-set";
|
|
2302
|
+
set.setAttribute("aria-label", "Symbol set");
|
|
2303
|
+
for (const [i, s] of import_bapbong_contracts3.MATH_SYMBOL_SETS.entries()) {
|
|
2304
|
+
const o = document.createElement("option");
|
|
2305
|
+
o.value = String(i);
|
|
2306
|
+
o.textContent = s.name;
|
|
2307
|
+
set.append(o);
|
|
2308
|
+
}
|
|
2309
|
+
set.value = String(setIndex);
|
|
2310
|
+
const grid = document.createElement("div");
|
|
2311
|
+
grid.className = "bb-eqp-grid";
|
|
2312
|
+
const hint = document.createElement("div");
|
|
2313
|
+
hint.className = "bb-eqp-hint";
|
|
2314
|
+
const hintG = document.createElement("span");
|
|
2315
|
+
hintG.className = "bb-eqp-hint-g";
|
|
2316
|
+
const hintK = document.createElement("span");
|
|
2317
|
+
hintK.className = "bb-eqp-hint-k";
|
|
2318
|
+
hint.append(hintG, hintK);
|
|
2319
|
+
const fill = () => {
|
|
2320
|
+
grid.replaceChildren();
|
|
2321
|
+
const chars = import_bapbong_contracts3.MATH_SYMBOL_SETS[setIndex]?.chars ?? "";
|
|
2322
|
+
for (const ch of chars) {
|
|
2323
|
+
const b = document.createElement("button");
|
|
2324
|
+
b.type = "button";
|
|
2325
|
+
b.className = "bb-eqp-sym";
|
|
2326
|
+
b.textContent = ch;
|
|
2327
|
+
const key = SHORTHAND.get(ch);
|
|
2328
|
+
b.title = key ? `${ch} ${key}` : ch;
|
|
2329
|
+
b.addEventListener("mouseenter", () => {
|
|
2330
|
+
hintG.textContent = ch;
|
|
2331
|
+
hintK.textContent = key ?? "";
|
|
2332
|
+
});
|
|
2333
|
+
b.addEventListener("click", () => options.onSymbol(ch));
|
|
2334
|
+
grid.append(b);
|
|
2335
|
+
}
|
|
2336
|
+
};
|
|
2337
|
+
set.addEventListener("change", () => {
|
|
2338
|
+
setIndex = Number(set.value) || 0;
|
|
2339
|
+
fill();
|
|
2340
|
+
});
|
|
2341
|
+
fill();
|
|
2342
|
+
body.replaceChildren(set, grid, hint);
|
|
2343
|
+
}
|
|
2344
|
+
function structuresBody() {
|
|
2345
|
+
const scroll = document.createElement("div");
|
|
2346
|
+
scroll.className = "bb-eqp-scroll";
|
|
2347
|
+
for (const group of (0, import_bapbong_contracts3.eqStructureGroups)()) {
|
|
2348
|
+
const h = document.createElement("div");
|
|
2349
|
+
h.className = "bb-eqp-group";
|
|
2350
|
+
h.textContent = group.name;
|
|
2351
|
+
const row = document.createElement("div");
|
|
2352
|
+
row.className = "bb-eqp-row";
|
|
2353
|
+
for (const item of group.items) {
|
|
2354
|
+
const b = document.createElement("button");
|
|
2355
|
+
b.type = "button";
|
|
2356
|
+
b.className = "bb-eqp-st";
|
|
2357
|
+
b.title = `${group.name} \u2014 ${item.name}`;
|
|
2358
|
+
const spec = options.layout?.([item.node], PREVIEW_PT2) ?? null;
|
|
2359
|
+
if (spec && spec.ops.length)
|
|
2360
|
+
b.append(equationPreviewSvg(spec, { maxWidth: 60 }));
|
|
2361
|
+
const name = document.createElement("span");
|
|
2362
|
+
name.className = "bb-eqp-st-name";
|
|
2363
|
+
name.textContent = item.name;
|
|
2364
|
+
b.append(name);
|
|
2365
|
+
b.addEventListener("click", () => options.onStructure(item));
|
|
2366
|
+
row.append(b);
|
|
2367
|
+
}
|
|
2368
|
+
scroll.append(h, row);
|
|
2369
|
+
}
|
|
2370
|
+
body.replaceChildren(scroll);
|
|
2371
|
+
}
|
|
2372
|
+
let setIndex = 0;
|
|
2373
|
+
function render() {
|
|
2374
|
+
for (const [id, el5] of Object.entries(tabEls))
|
|
2375
|
+
el5.setAttribute("aria-selected", String(id === current3));
|
|
2376
|
+
if (current3 === "symbols") symbolsBody();
|
|
2377
|
+
else structuresBody();
|
|
2378
|
+
}
|
|
2379
|
+
setCollapsed(false);
|
|
2380
|
+
render();
|
|
2381
|
+
return {
|
|
2382
|
+
el: root,
|
|
2383
|
+
setCollapsed,
|
|
2384
|
+
get collapsed() {
|
|
2385
|
+
return collapsed;
|
|
2386
|
+
},
|
|
2387
|
+
destroy() {
|
|
2388
|
+
root.remove();
|
|
2389
|
+
}
|
|
2390
|
+
};
|
|
2391
|
+
}
|
|
2392
|
+
|
|
2393
|
+
// packages/ui/src/lib/table-grid.ts
|
|
2394
|
+
var STYLE11 = `
|
|
2003
2395
|
.bb-grid{display:flex;flex-direction:column;gap:6px;user-select:none}
|
|
2004
2396
|
.bb-grid-cells{display:grid;gap:2px}
|
|
2005
2397
|
.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 +2399,7 @@ var STYLE9 = `
|
|
|
2007
2399
|
.bb-grid-label{font-size:12px;text-align:center;opacity:.7}
|
|
2008
2400
|
`;
|
|
2009
2401
|
function tableGridPicker(options) {
|
|
2010
|
-
injectStyle("bb-ui-grid-styles",
|
|
2402
|
+
injectStyle("bb-ui-grid-styles", STYLE11);
|
|
2011
2403
|
const maxRows = options.maxRows ?? 8;
|
|
2012
2404
|
const maxCols = options.maxCols ?? 10;
|
|
2013
2405
|
const root = document.createElement("div");
|
|
@@ -2019,22 +2411,22 @@ function tableGridPicker(options) {
|
|
|
2019
2411
|
label.className = "bb-grid-label";
|
|
2020
2412
|
label.textContent = "0 \xD7 0";
|
|
2021
2413
|
const cells = [];
|
|
2022
|
-
const highlight2 = (r,
|
|
2414
|
+
const highlight2 = (r, c2) => {
|
|
2023
2415
|
for (let i = 0; i < cells.length; i++) {
|
|
2024
2416
|
const row = Math.floor(i / maxCols);
|
|
2025
2417
|
const col = i % maxCols;
|
|
2026
|
-
cells[i].classList.toggle("on", row <= r && col <=
|
|
2418
|
+
cells[i].classList.toggle("on", row <= r && col <= c2);
|
|
2027
2419
|
}
|
|
2028
|
-
label.textContent = `${r + 1} \xD7 ${
|
|
2420
|
+
label.textContent = `${r + 1} \xD7 ${c2 + 1}`;
|
|
2029
2421
|
};
|
|
2030
2422
|
for (let r = 0; r < maxRows; r++) {
|
|
2031
|
-
for (let
|
|
2423
|
+
for (let c2 = 0; c2 < maxCols; c2++) {
|
|
2032
2424
|
const cell = document.createElement("button");
|
|
2033
2425
|
cell.type = "button";
|
|
2034
2426
|
cell.className = "bb-grid-cell";
|
|
2035
2427
|
cell.addEventListener("mousedown", (e) => e.preventDefault());
|
|
2036
|
-
cell.addEventListener("mouseenter", () => highlight2(r,
|
|
2037
|
-
cell.addEventListener("click", () => options.onPick(r + 1,
|
|
2428
|
+
cell.addEventListener("mouseenter", () => highlight2(r, c2));
|
|
2429
|
+
cell.addEventListener("click", () => options.onPick(r + 1, c2 + 1));
|
|
2038
2430
|
cells.push(cell);
|
|
2039
2431
|
cellsEl.appendChild(cell);
|
|
2040
2432
|
}
|
|
@@ -2050,7 +2442,7 @@ var cmToPx = (cm) => Math.round(cm * PX_PER_CM);
|
|
|
2050
2442
|
function fmtCm(cm) {
|
|
2051
2443
|
return `${Number(cm.toFixed(3))} cm`;
|
|
2052
2444
|
}
|
|
2053
|
-
var
|
|
2445
|
+
var STYLE12 = `
|
|
2054
2446
|
.bb-ps{display:flex;flex-direction:column;min-width:250px;max-height:min(70vh,460px);overflow-y:auto}
|
|
2055
2447
|
.bb-ps,.bb-ps *{box-sizing:border-box}
|
|
2056
2448
|
.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 +2472,9 @@ var STYLE10 = `
|
|
|
2080
2472
|
.bb-ps-tile:hover,.bb-ps-tile:focus{background:var(--bb-ui-hover,#f1efe8);outline:none}
|
|
2081
2473
|
.bb-ps-tile[aria-checked="true"]{background:var(--bb-ui-active-bg,#e6f1fb)}
|
|
2082
2474
|
`;
|
|
2083
|
-
var
|
|
2475
|
+
var SVG_NS2 = "http://www.w3.org/2000/svg";
|
|
2084
2476
|
function svgEl(name, attrs) {
|
|
2085
|
-
const el5 = document.createElementNS(
|
|
2477
|
+
const el5 = document.createElementNS(SVG_NS2, name);
|
|
2086
2478
|
for (const [k, v] of Object.entries(attrs)) el5.setAttribute(k, String(v));
|
|
2087
2479
|
return el5;
|
|
2088
2480
|
}
|
|
@@ -2176,7 +2568,7 @@ function customRow(icon, title, description, onPick) {
|
|
|
2176
2568
|
return presetRow(icon, title, captionLine(description), false, onPick);
|
|
2177
2569
|
}
|
|
2178
2570
|
function pageSizePicker(options) {
|
|
2179
|
-
injectStyle("bb-ui-pagesetup-styles",
|
|
2571
|
+
injectStyle("bb-ui-pagesetup-styles", STYLE12);
|
|
2180
2572
|
const root = document.createElement("div");
|
|
2181
2573
|
root.className = "bb-ps";
|
|
2182
2574
|
root.setAttribute("role", "menu");
|
|
@@ -2205,7 +2597,7 @@ function pageSizePicker(options) {
|
|
|
2205
2597
|
return root;
|
|
2206
2598
|
}
|
|
2207
2599
|
function orientationPicker(options) {
|
|
2208
|
-
injectStyle("bb-ui-pagesetup-styles",
|
|
2600
|
+
injectStyle("bb-ui-pagesetup-styles", STYLE12);
|
|
2209
2601
|
const root = document.createElement("div");
|
|
2210
2602
|
root.className = "bb-ps";
|
|
2211
2603
|
root.setAttribute("role", "menu");
|
|
@@ -2228,7 +2620,7 @@ function orientationPicker(options) {
|
|
|
2228
2620
|
return root;
|
|
2229
2621
|
}
|
|
2230
2622
|
function marginPresetPicker(options) {
|
|
2231
|
-
injectStyle("bb-ui-pagesetup-styles",
|
|
2623
|
+
injectStyle("bb-ui-pagesetup-styles", STYLE12);
|
|
2232
2624
|
const root = document.createElement("div");
|
|
2233
2625
|
root.className = "bb-ps";
|
|
2234
2626
|
root.setAttribute("role", "menu");
|
|
@@ -2303,7 +2695,7 @@ function readPx(input, fallbackPx) {
|
|
|
2303
2695
|
return Number.isFinite(n) && n > 0 ? cmToPx(n) : fallbackPx;
|
|
2304
2696
|
}
|
|
2305
2697
|
function openPageSizeDialog(options) {
|
|
2306
|
-
injectStyle("bb-ui-pagesetup-styles",
|
|
2698
|
+
injectStyle("bb-ui-pagesetup-styles", STYLE12);
|
|
2307
2699
|
const dialog = new Dialog({ title: "Paper size", modal: true });
|
|
2308
2700
|
const form = document.createElement("form");
|
|
2309
2701
|
form.className = "bb-pd";
|
|
@@ -2330,7 +2722,7 @@ function openPageSizeDialog(options) {
|
|
|
2330
2722
|
width.input.select();
|
|
2331
2723
|
}
|
|
2332
2724
|
function openMarginsDialog(options) {
|
|
2333
|
-
injectStyle("bb-ui-pagesetup-styles",
|
|
2725
|
+
injectStyle("bb-ui-pagesetup-styles", STYLE12);
|
|
2334
2726
|
const dialog = new Dialog({ title: "Margins", modal: true });
|
|
2335
2727
|
const form = document.createElement("form");
|
|
2336
2728
|
form.className = "bb-pd";
|
|
@@ -2387,7 +2779,7 @@ var PGNUM_FORMATS = [
|
|
|
2387
2779
|
["upperLetter", "A, B, C, D\u2026", "A"]
|
|
2388
2780
|
];
|
|
2389
2781
|
function pageNumberPicker(options) {
|
|
2390
|
-
injectStyle("bb-ui-pagesetup-styles",
|
|
2782
|
+
injectStyle("bb-ui-pagesetup-styles", STYLE12);
|
|
2391
2783
|
const root = document.createElement("div");
|
|
2392
2784
|
root.className = "bb-ps";
|
|
2393
2785
|
root.setAttribute("role", "menu");
|
|
@@ -2488,7 +2880,7 @@ function pageNumberPicker(options) {
|
|
|
2488
2880
|
return root;
|
|
2489
2881
|
}
|
|
2490
2882
|
function sectionPaperPanel(options) {
|
|
2491
|
-
injectStyle("bb-ui-pagesetup-styles",
|
|
2883
|
+
injectStyle("bb-ui-pagesetup-styles", STYLE12);
|
|
2492
2884
|
const root = document.createElement("div");
|
|
2493
2885
|
root.className = "bb-ps";
|
|
2494
2886
|
root.setAttribute("role", "menu");
|
|
@@ -2557,7 +2949,7 @@ function sectionPaperPanel(options) {
|
|
|
2557
2949
|
}
|
|
2558
2950
|
|
|
2559
2951
|
// packages/ui/src/lib/section-chip.ts
|
|
2560
|
-
var
|
|
2952
|
+
var STYLE13 = `
|
|
2561
2953
|
.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
2954
|
.bb-secchip *{box-sizing:border-box}
|
|
2563
2955
|
.bb-secchip-title{padding:0 7px;font-size:11px;font-weight:600;opacity:.8}
|
|
@@ -2570,7 +2962,7 @@ var STYLE11 = `
|
|
|
2570
2962
|
.bb-secchip-x:hover{background:var(--bb-ui-hover,#f1efe8);opacity:1}
|
|
2571
2963
|
`;
|
|
2572
2964
|
function createSectionChip(options) {
|
|
2573
|
-
injectStyle("bb-ui-section-chip-styles",
|
|
2965
|
+
injectStyle("bb-ui-section-chip-styles", STYLE13);
|
|
2574
2966
|
const el5 = document.createElement("div");
|
|
2575
2967
|
el5.className = "bb-secchip";
|
|
2576
2968
|
const title = document.createElement("span");
|
|
@@ -2627,7 +3019,7 @@ var halfToPt = (hp) => hp / 2;
|
|
|
2627
3019
|
var ptToHalf = (pt) => Math.round(pt * 2);
|
|
2628
3020
|
var SCALE_PRESETS = [200, 150, 100, 90, 80, 66, 50, 33];
|
|
2629
3021
|
var SUPERSUB_SCALE = 0.66;
|
|
2630
|
-
var
|
|
3022
|
+
var STYLE14 = `
|
|
2631
3023
|
.bb-fd{display:flex;flex-direction:column;gap:15px;min-width:396px;max-width:430px;color:var(--bb-ui-fg,#2c2c2a)}
|
|
2632
3024
|
.bb-fd *{box-sizing:border-box}
|
|
2633
3025
|
/* A segmented control, not a "tab joined to its pane": that pattern needs the
|
|
@@ -2709,7 +3101,7 @@ function openFontDialog({
|
|
|
2709
3101
|
sizes,
|
|
2710
3102
|
onApply
|
|
2711
3103
|
}) {
|
|
2712
|
-
injectStyle("bb-font-dialog",
|
|
3104
|
+
injectStyle("bb-font-dialog", STYLE14);
|
|
2713
3105
|
const dialog = new Dialog({ title: "Font", modal: true });
|
|
2714
3106
|
const root = el("div", "bb-fd");
|
|
2715
3107
|
const tabs = el("div", "bb-fd-tabs");
|
|
@@ -2773,8 +3165,8 @@ function openFontDialog({
|
|
|
2773
3165
|
label: "Text color",
|
|
2774
3166
|
clearLabel: "Automatic",
|
|
2775
3167
|
value: () => color,
|
|
2776
|
-
onPick: (
|
|
2777
|
-
color =
|
|
3168
|
+
onPick: (c2) => {
|
|
3169
|
+
color = c2;
|
|
2778
3170
|
paint();
|
|
2779
3171
|
}
|
|
2780
3172
|
});
|
|
@@ -2783,8 +3175,8 @@ function openFontDialog({
|
|
|
2783
3175
|
label: "Highlight",
|
|
2784
3176
|
clearLabel: "No highlight",
|
|
2785
3177
|
value: () => highlight2,
|
|
2786
|
-
onPick: (
|
|
2787
|
-
highlight2 =
|
|
3178
|
+
onPick: (c2) => {
|
|
3179
|
+
highlight2 = c2;
|
|
2788
3180
|
paint();
|
|
2789
3181
|
}
|
|
2790
3182
|
});
|
|
@@ -2909,8 +3301,8 @@ function openFontDialog({
|
|
|
2909
3301
|
s.transform = scale === 100 ? "none" : `scaleX(${scale / 100})`;
|
|
2910
3302
|
s.verticalAlign = supCb.checked ? "super" : subCb.checked ? "sub" : `${positionPt}pt`;
|
|
2911
3303
|
}
|
|
2912
|
-
for (const
|
|
2913
|
-
|
|
3304
|
+
for (const c2 of [familySel, sizeSel, scaleSel])
|
|
3305
|
+
c2.addEventListener("change", paint);
|
|
2914
3306
|
for (const i of [spacingInput, positionInput])
|
|
2915
3307
|
i.addEventListener("input", paint);
|
|
2916
3308
|
const foot = el("div", "bb-fd-foot");
|
|
@@ -2950,7 +3342,7 @@ function openFontDialog({
|
|
|
2950
3342
|
}
|
|
2951
3343
|
|
|
2952
3344
|
// packages/ui/src/lib/symbol-sets.ts
|
|
2953
|
-
var
|
|
3345
|
+
var import_bapbong_contracts4 = require("@shadow-garden/bapbong-contracts");
|
|
2954
3346
|
var g = (id, label, short, pairs) => ({
|
|
2955
3347
|
id,
|
|
2956
3348
|
label,
|
|
@@ -3286,7 +3678,7 @@ var SYMBOL_GROUPS = [
|
|
|
3286
3678
|
])
|
|
3287
3679
|
];
|
|
3288
3680
|
function autoCorrectHint(char) {
|
|
3289
|
-
return
|
|
3681
|
+
return import_bapbong_contracts4.AUTOCORRECT_RULES.find((r) => r.to === char)?.seq ?? "";
|
|
3290
3682
|
}
|
|
3291
3683
|
var SPECIAL_CHARACTERS = [
|
|
3292
3684
|
{ char: "\u2014", name: "Em dash", hint: "" },
|
|
@@ -3331,7 +3723,7 @@ function parseCodePoint(input) {
|
|
|
3331
3723
|
}
|
|
3332
3724
|
var RECENT_MAX = 16;
|
|
3333
3725
|
function pushRecent(recent, char, max = RECENT_MAX) {
|
|
3334
|
-
return [char, ...recent.filter((
|
|
3726
|
+
return [char, ...recent.filter((c2) => c2 !== char)].slice(0, max);
|
|
3335
3727
|
}
|
|
3336
3728
|
function searchSymbols(query) {
|
|
3337
3729
|
const q = query.trim().toLowerCase();
|
|
@@ -3351,7 +3743,7 @@ function searchSymbols(query) {
|
|
|
3351
3743
|
}
|
|
3352
3744
|
|
|
3353
3745
|
// packages/ui/src/lib/symbol-dialog.ts
|
|
3354
|
-
var
|
|
3746
|
+
var STYLE15 = `
|
|
3355
3747
|
.bb-sd{display:flex;flex-direction:column;gap:12px;width:412px;max-width:100%;color:var(--bb-ui-fg,#2c2c2a)}
|
|
3356
3748
|
.bb-sd *{box-sizing:border-box}
|
|
3357
3749
|
.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 +3804,7 @@ function glyphFor(char) {
|
|
|
3412
3804
|
return char;
|
|
3413
3805
|
}
|
|
3414
3806
|
function createSymbolDialog(options) {
|
|
3415
|
-
injectStyle("bb-symbol-dialog",
|
|
3807
|
+
injectStyle("bb-symbol-dialog", STYLE15);
|
|
3416
3808
|
let recent = [...options.recent ?? []].slice(0, RECENT_MAX);
|
|
3417
3809
|
let selected = null;
|
|
3418
3810
|
const root = el2("div", "bb-sd");
|
|
@@ -3601,9 +3993,9 @@ function createSymbolDialog(options) {
|
|
|
3601
3993
|
function renderRecent() {
|
|
3602
3994
|
fillGrid(
|
|
3603
3995
|
recentGrid,
|
|
3604
|
-
recent.map((
|
|
3605
|
-
char:
|
|
3606
|
-
name: SYMBOL_NAMES.get(
|
|
3996
|
+
recent.map((c2) => ({
|
|
3997
|
+
char: c2,
|
|
3998
|
+
name: SYMBOL_NAMES.get(c2) ?? "Character"
|
|
3607
3999
|
})),
|
|
3608
4000
|
RECENT_COLS,
|
|
3609
4001
|
"Nothing yet \u2014 inserted symbols appear here."
|
|
@@ -3647,7 +4039,7 @@ function createSymbolDialog(options) {
|
|
|
3647
4039
|
code.removeAttribute("aria-invalid");
|
|
3648
4040
|
const cell = Array.from(
|
|
3649
4041
|
grid.querySelectorAll(".bb-sd-cell")
|
|
3650
|
-
).find((
|
|
4042
|
+
).find((c2) => c2.textContent === glyphFor(ch));
|
|
3651
4043
|
select2(ch, cell ?? null);
|
|
3652
4044
|
} else {
|
|
3653
4045
|
code.setAttribute("aria-invalid", code.value.trim() ? "true" : "false");
|
|
@@ -3690,7 +4082,7 @@ function createSymbolDialog(options) {
|
|
|
3690
4082
|
}
|
|
3691
4083
|
|
|
3692
4084
|
// packages/ui/src/lib/symbol-popover.ts
|
|
3693
|
-
var
|
|
4085
|
+
var STYLE16 = `
|
|
3694
4086
|
.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
4087
|
.bb-spk *{box-sizing:border-box}
|
|
3696
4088
|
.bb-spk::backdrop{background:transparent}
|
|
@@ -3723,7 +4115,7 @@ function el3(tag, cls, text) {
|
|
|
3723
4115
|
return n;
|
|
3724
4116
|
}
|
|
3725
4117
|
function openSymbolPopover(options) {
|
|
3726
|
-
injectStyle("bb-ui-symbol-popover",
|
|
4118
|
+
injectStyle("bb-ui-symbol-popover", STYLE16);
|
|
3727
4119
|
const { anchor } = options;
|
|
3728
4120
|
let recent = [...options.recent ?? []].slice(0, RECENT_MAX);
|
|
3729
4121
|
let groupId = SYMBOL_GROUPS[0].id;
|
|
@@ -3754,16 +4146,16 @@ function openSymbolPopover(options) {
|
|
|
3754
4146
|
const chips = el3("div", "bb-spk-chips");
|
|
3755
4147
|
const chipEls = /* @__PURE__ */ new Map();
|
|
3756
4148
|
for (const grp of SYMBOL_GROUPS) {
|
|
3757
|
-
const
|
|
3758
|
-
|
|
3759
|
-
|
|
3760
|
-
|
|
4149
|
+
const c2 = el3("button", "bb-spk-chip", grp.short);
|
|
4150
|
+
c2.type = "button";
|
|
4151
|
+
c2.title = grp.label;
|
|
4152
|
+
c2.addEventListener("click", () => {
|
|
3761
4153
|
groupId = grp.id;
|
|
3762
4154
|
search.value = "";
|
|
3763
4155
|
render();
|
|
3764
4156
|
});
|
|
3765
|
-
chips.append(
|
|
3766
|
-
chipEls.set(grp.id,
|
|
4157
|
+
chips.append(c2);
|
|
4158
|
+
chipEls.set(grp.id, c2);
|
|
3767
4159
|
}
|
|
3768
4160
|
const grid = el3("div", "bb-spk-grid");
|
|
3769
4161
|
grid.setAttribute("role", "grid");
|
|
@@ -3834,9 +4226,9 @@ function openSymbolPopover(options) {
|
|
|
3834
4226
|
};
|
|
3835
4227
|
const renderRecent = () => fill(
|
|
3836
4228
|
recentGrid,
|
|
3837
|
-
recent.slice(0, RECENT_ROW).map((
|
|
3838
|
-
char:
|
|
3839
|
-
name: SYMBOL_NAMES.get(
|
|
4229
|
+
recent.slice(0, RECENT_ROW).map((c2) => ({
|
|
4230
|
+
char: c2,
|
|
4231
|
+
name: SYMBOL_NAMES.get(c2) ?? "Character"
|
|
3840
4232
|
})),
|
|
3841
4233
|
"Nothing yet."
|
|
3842
4234
|
);
|
|
@@ -3844,8 +4236,8 @@ function openSymbolPopover(options) {
|
|
|
3844
4236
|
const q = search.value.trim();
|
|
3845
4237
|
const byCode = q ? parseCodePoint(q) : null;
|
|
3846
4238
|
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
|
-
|
|
4239
|
+
for (const [id, c2] of chipEls)
|
|
4240
|
+
c2.setAttribute("aria-pressed", String(!q && id === groupId));
|
|
3849
4241
|
fill(grid, entries, "No match.");
|
|
3850
4242
|
const first = grid.querySelector(".bb-spk-cell");
|
|
3851
4243
|
if (q && first && entries[0]) select2(entries[0].char, first);
|
|
@@ -3884,8 +4276,8 @@ function openSymbolPopover(options) {
|
|
|
3884
4276
|
}
|
|
3885
4277
|
|
|
3886
4278
|
// packages/ui/src/lib/shortcuts-dialog.ts
|
|
3887
|
-
var
|
|
3888
|
-
var
|
|
4279
|
+
var import_bapbong_contracts5 = require("@shadow-garden/bapbong-contracts");
|
|
4280
|
+
var STYLE17 = `
|
|
3889
4281
|
.bb-ks{display:flex;flex-direction:column;gap:10px;width:600px;max-width:100%;color:var(--bb-ui-fg,#2c2c2a);font-size:12px}
|
|
3890
4282
|
.bb-ks *{box-sizing:border-box}
|
|
3891
4283
|
.bb-ks-top{display:flex;gap:8px;align-items:center}
|
|
@@ -3943,7 +4335,7 @@ function highlight(text, q) {
|
|
|
3943
4335
|
return out;
|
|
3944
4336
|
}
|
|
3945
4337
|
function openKeyboardShortcutsDialog(options) {
|
|
3946
|
-
injectStyle("bb-ui-shortcuts-dialog",
|
|
4338
|
+
injectStyle("bb-ui-shortcuts-dialog", STYLE17);
|
|
3947
4339
|
const dialog = new Dialog({
|
|
3948
4340
|
title: options.title ?? "Keyboard shortcuts",
|
|
3949
4341
|
modal: true,
|
|
@@ -3970,19 +4362,19 @@ function openKeyboardShortcutsDialog(options) {
|
|
|
3970
4362
|
let sortKey = "title";
|
|
3971
4363
|
let sortAsc = true;
|
|
3972
4364
|
const ths = /* @__PURE__ */ new Map();
|
|
3973
|
-
for (const
|
|
4365
|
+
for (const c2 of columns) {
|
|
3974
4366
|
const th = el4("th");
|
|
3975
|
-
th.append(el4("span", void 0,
|
|
4367
|
+
th.append(el4("span", void 0, c2.label));
|
|
3976
4368
|
th.addEventListener("click", () => {
|
|
3977
|
-
if (sortKey ===
|
|
4369
|
+
if (sortKey === c2.key) sortAsc = !sortAsc;
|
|
3978
4370
|
else {
|
|
3979
|
-
sortKey =
|
|
4371
|
+
sortKey = c2.key;
|
|
3980
4372
|
sortAsc = true;
|
|
3981
4373
|
}
|
|
3982
4374
|
render();
|
|
3983
4375
|
});
|
|
3984
4376
|
headRow.append(th);
|
|
3985
|
-
ths.set(
|
|
4377
|
+
ths.set(c2.key, th);
|
|
3986
4378
|
}
|
|
3987
4379
|
thead.append(headRow);
|
|
3988
4380
|
const tbody = el4("tbody");
|
|
@@ -4002,7 +4394,7 @@ function openKeyboardShortcutsDialog(options) {
|
|
|
4002
4394
|
const rows = [];
|
|
4003
4395
|
for (const src of options.sources)
|
|
4004
4396
|
rows.push(
|
|
4005
|
-
...(0,
|
|
4397
|
+
...(0, import_bapbong_contracts5.keybindingRows)(src.keybindings, (c2) => src.commands.get(c2)?.title)
|
|
4006
4398
|
);
|
|
4007
4399
|
return rows;
|
|
4008
4400
|
};
|
|
@@ -4010,13 +4402,13 @@ function openKeyboardShortcutsDialog(options) {
|
|
|
4010
4402
|
const td = el4("td");
|
|
4011
4403
|
keys.forEach((k, i) => {
|
|
4012
4404
|
if (i > 0) td.append(el4("span", "or", "or"));
|
|
4013
|
-
for (const part of (0,
|
|
4405
|
+
for (const part of (0, import_bapbong_contracts5.formatKey)(k, IS_MAC))
|
|
4014
4406
|
td.append(el4("kbd", void 0, part));
|
|
4015
4407
|
});
|
|
4016
4408
|
return td;
|
|
4017
4409
|
};
|
|
4018
4410
|
const sortRows = (rows) => {
|
|
4019
|
-
const val = (r) => sortKey === "title" ? r.title : sortKey === "keys" ? r.keys.map((k) => (0,
|
|
4411
|
+
const val = (r) => sortKey === "title" ? r.title : sortKey === "keys" ? r.keys.map((k) => (0, import_bapbong_contracts5.formatKey)(k, IS_MAC).join("")).join(" ") : sortKey === "when" ? r.when ?? "" : r.source;
|
|
4020
4412
|
const sorted = [...rows].sort(
|
|
4021
4413
|
(a, b) => val(a).localeCompare(val(b), void 0, { sensitivity: "base" })
|
|
4022
4414
|
);
|
|
@@ -4025,7 +4417,7 @@ function openKeyboardShortcutsDialog(options) {
|
|
|
4025
4417
|
const render = () => {
|
|
4026
4418
|
const q = search.value.trim().toLowerCase();
|
|
4027
4419
|
const rows = allRows();
|
|
4028
|
-
const shown = sortRows((0,
|
|
4420
|
+
const shown = sortRows((0, import_bapbong_contracts5.filterKeybindingRows)(rows, q, IS_MAC));
|
|
4029
4421
|
for (const [key, th] of ths) {
|
|
4030
4422
|
if (key === sortKey)
|
|
4031
4423
|
th.setAttribute("aria-sort", sortAsc ? "ascending" : "descending");
|
|
@@ -4059,7 +4451,7 @@ function openKeyboardShortcutsDialog(options) {
|
|
|
4059
4451
|
tbody.append(tr);
|
|
4060
4452
|
}
|
|
4061
4453
|
count.textContent = shown.length === rows.length ? `${rows.length} shortcuts` : `${shown.length} of ${rows.length}`;
|
|
4062
|
-
footL.textContent = `Sorted by ${columns.find((
|
|
4454
|
+
footL.textContent = `Sorted by ${columns.find((c2) => c2.key === sortKey)?.label.toLowerCase()} \xB7 click a header to sort`;
|
|
4063
4455
|
};
|
|
4064
4456
|
search.addEventListener("input", render);
|
|
4065
4457
|
dialog.onClose(() => dialog.destroy());
|
|
@@ -4069,7 +4461,7 @@ function openKeyboardShortcutsDialog(options) {
|
|
|
4069
4461
|
}
|
|
4070
4462
|
|
|
4071
4463
|
// packages/ui/src/lib/scrollbars.ts
|
|
4072
|
-
var
|
|
4464
|
+
var STYLE18 = `
|
|
4073
4465
|
@property --bb-scroll-thumb-now {
|
|
4074
4466
|
syntax: '<color>';
|
|
4075
4467
|
/* MUST inherit: the thumb pseudo-element never matches .bb-scrolling
|
|
@@ -4101,7 +4493,7 @@ var STYLE16 = `
|
|
|
4101
4493
|
var installed = null;
|
|
4102
4494
|
function installScrollbars(root = document) {
|
|
4103
4495
|
if (installed) return installed;
|
|
4104
|
-
injectStyle("bb-ui-scrollbars",
|
|
4496
|
+
injectStyle("bb-ui-scrollbars", STYLE18);
|
|
4105
4497
|
const quiet = /* @__PURE__ */ new WeakMap();
|
|
4106
4498
|
const onScroll = (ev) => {
|
|
4107
4499
|
const el5 = ev.target instanceof HTMLElement ? ev.target : root.documentElement;
|
|
@@ -4121,6 +4513,7 @@ function installScrollbars(root = document) {
|
|
|
4121
4513
|
}
|
|
4122
4514
|
// Annotate the CommonJS export names for ESM import in node:
|
|
4123
4515
|
0 && (module.exports = {
|
|
4516
|
+
BUILT_IN_EQUATIONS,
|
|
4124
4517
|
COLOR_PALETTE,
|
|
4125
4518
|
Dialog,
|
|
4126
4519
|
RECENT_MAX,
|
|
@@ -4135,6 +4528,9 @@ function installScrollbars(root = document) {
|
|
|
4135
4528
|
createSymbolDialog,
|
|
4136
4529
|
defaultMenus,
|
|
4137
4530
|
defaultToolbarGroups,
|
|
4531
|
+
equationGallery,
|
|
4532
|
+
equationPanel,
|
|
4533
|
+
equationPreviewSvg,
|
|
4138
4534
|
installScrollbars,
|
|
4139
4535
|
marginPresetPicker,
|
|
4140
4536
|
mountMenubar,
|