@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.js
CHANGED
|
@@ -32,12 +32,12 @@ function placeFloating(el5, anchor) {
|
|
|
32
32
|
}
|
|
33
33
|
function rovingGrid(cells) {
|
|
34
34
|
let cur = [0, 0];
|
|
35
|
-
const at = (r,
|
|
36
|
-
const focusCell = (r,
|
|
35
|
+
const at = (r, c2) => cells[r]?.[c2];
|
|
36
|
+
const focusCell = (r, c2) => {
|
|
37
37
|
const rows = cells.length;
|
|
38
38
|
if (rows === 0) return;
|
|
39
39
|
const nr = Math.min(rows - 1, Math.max(0, r));
|
|
40
|
-
const nc = Math.min(cells[nr].length - 1, Math.max(0,
|
|
40
|
+
const nc = Math.min(cells[nr].length - 1, Math.max(0, c2));
|
|
41
41
|
const prev = at(cur[0], cur[1]);
|
|
42
42
|
if (prev) prev.tabIndex = -1;
|
|
43
43
|
const next = at(nr, nc);
|
|
@@ -47,9 +47,9 @@ function rovingGrid(cells) {
|
|
|
47
47
|
cur = [nr, nc];
|
|
48
48
|
};
|
|
49
49
|
cells.forEach(
|
|
50
|
-
(row, r) => row.forEach((cell,
|
|
50
|
+
(row, r) => row.forEach((cell, c2) => {
|
|
51
51
|
cell.setAttribute("role", "gridcell");
|
|
52
|
-
cell.tabIndex = r === 0 &&
|
|
52
|
+
cell.tabIndex = r === 0 && c2 === 0 ? 0 : -1;
|
|
53
53
|
cell.addEventListener("keydown", (e) => {
|
|
54
54
|
const delta = {
|
|
55
55
|
ArrowRight: [0, 1],
|
|
@@ -62,10 +62,10 @@ function rovingGrid(cells) {
|
|
|
62
62
|
const d = delta[e.key];
|
|
63
63
|
if (!d) return;
|
|
64
64
|
e.preventDefault();
|
|
65
|
-
focusCell(r + d[0],
|
|
65
|
+
focusCell(r + d[0], c2 + d[1]);
|
|
66
66
|
});
|
|
67
67
|
cell.addEventListener("focus", () => {
|
|
68
|
-
cur = [r,
|
|
68
|
+
cur = [r, c2];
|
|
69
69
|
});
|
|
70
70
|
})
|
|
71
71
|
);
|
|
@@ -395,9 +395,9 @@ function openColorPicker({
|
|
|
395
395
|
panel.remove();
|
|
396
396
|
anchor.focus();
|
|
397
397
|
};
|
|
398
|
-
const pick = (
|
|
399
|
-
if (
|
|
400
|
-
onPick(
|
|
398
|
+
const pick = (c2) => {
|
|
399
|
+
if (c2 && !COLOR_PALETTE.some((row) => row.includes(c2))) remember(c2);
|
|
400
|
+
onPick(c2);
|
|
401
401
|
close();
|
|
402
402
|
};
|
|
403
403
|
if (clearLabel !== void 0) {
|
|
@@ -441,15 +441,15 @@ function openColorPicker({
|
|
|
441
441
|
);
|
|
442
442
|
const customRow2 = document.createElement("div");
|
|
443
443
|
customRow2.className = "bb-cpk-row";
|
|
444
|
-
for (const
|
|
444
|
+
for (const c2 of customColors) {
|
|
445
445
|
const sw = document.createElement("button");
|
|
446
446
|
sw.type = "button";
|
|
447
447
|
sw.className = "bb-cpk-sw";
|
|
448
|
-
sw.style.background =
|
|
449
|
-
sw.title =
|
|
450
|
-
sw.setAttribute("aria-label",
|
|
451
|
-
if (
|
|
452
|
-
sw.addEventListener("click", () => pick(
|
|
448
|
+
sw.style.background = c2;
|
|
449
|
+
sw.title = c2;
|
|
450
|
+
sw.setAttribute("aria-label", c2);
|
|
451
|
+
if (c2.toUpperCase() === value?.toUpperCase()) sw.classList.add("on");
|
|
452
|
+
sw.addEventListener("click", () => pick(c2));
|
|
453
453
|
customRow2.append(sw);
|
|
454
454
|
}
|
|
455
455
|
const plus = document.createElement("button");
|
|
@@ -533,8 +533,8 @@ function colorButton(o) {
|
|
|
533
533
|
anchor: el5,
|
|
534
534
|
value: o.value(),
|
|
535
535
|
clearLabel: o.clearLabel,
|
|
536
|
-
onPick: (
|
|
537
|
-
o.onPick(
|
|
536
|
+
onPick: (c2) => {
|
|
537
|
+
o.onPick(c2);
|
|
538
538
|
sync();
|
|
539
539
|
}
|
|
540
540
|
});
|
|
@@ -645,7 +645,7 @@ var STYLE3 = `
|
|
|
645
645
|
.bb-split-bar{flex:1;height:3px;border-radius:2px;background:var(--bb-ui-border,#d9d9d4)}
|
|
646
646
|
`;
|
|
647
647
|
function defaultToolbarGroups(commands) {
|
|
648
|
-
const names = [...commands].map((
|
|
648
|
+
const names = [...commands].map((c2) => c2.name);
|
|
649
649
|
const aligns = names.filter((n) => n.startsWith("align-"));
|
|
650
650
|
const rest = names.filter((n) => !n.startsWith("align-"));
|
|
651
651
|
return [rest, aligns].filter((g2) => g2.length > 0);
|
|
@@ -895,7 +895,7 @@ function mountToolbar(host, editor, options = {}) {
|
|
|
895
895
|
el5.disabled = cmd.isEnabled ? !cmd.isEnabled(state) : false;
|
|
896
896
|
}
|
|
897
897
|
for (const { spec, el: el5 } of selects) el5.value = spec.value(state);
|
|
898
|
-
for (const
|
|
898
|
+
for (const c2 of colors) c2.sync();
|
|
899
899
|
for (const { spec, cards } of splits) {
|
|
900
900
|
const selected = spec.value(state);
|
|
901
901
|
for (const card of cards)
|
|
@@ -905,7 +905,7 @@ function mountToolbar(host, editor, options = {}) {
|
|
|
905
905
|
);
|
|
906
906
|
}
|
|
907
907
|
};
|
|
908
|
-
const off = editor.onChange((
|
|
908
|
+
const off = editor.onChange((c2) => refresh(c2.state));
|
|
909
909
|
try {
|
|
910
910
|
refresh(editor.state);
|
|
911
911
|
} catch {
|
|
@@ -1149,7 +1149,7 @@ function showMenu(entries, at, options = {}) {
|
|
|
1149
1149
|
return handle;
|
|
1150
1150
|
}
|
|
1151
1151
|
function defaultMenus(commands) {
|
|
1152
|
-
const names = [...commands].map((
|
|
1152
|
+
const names = [...commands].map((c2) => c2.name);
|
|
1153
1153
|
const marks = ["bold", "italic", "underline", "strike"].filter(
|
|
1154
1154
|
(n) => commands.has(n)
|
|
1155
1155
|
);
|
|
@@ -1263,10 +1263,10 @@ function mountMenubar(host, editor, options = {}) {
|
|
|
1263
1263
|
function refresh(state) {
|
|
1264
1264
|
latest = state;
|
|
1265
1265
|
if (openIdx < 0) return;
|
|
1266
|
-
for (const
|
|
1266
|
+
for (const c2 of checks) c2.el.textContent = c2.active(state) ? "\u2713" : "";
|
|
1267
1267
|
for (const e of enables) e.el.disabled = !e.enabled(state);
|
|
1268
1268
|
}
|
|
1269
|
-
const off = editor.onChange((
|
|
1269
|
+
const off = editor.onChange((c2) => refresh(c2.state));
|
|
1270
1270
|
try {
|
|
1271
1271
|
latest = editor.state;
|
|
1272
1272
|
} catch {
|
|
@@ -1594,13 +1594,13 @@ function showLinkPanel(opts) {
|
|
|
1594
1594
|
row.appendChild(icon);
|
|
1595
1595
|
const label = document.createElement("span");
|
|
1596
1596
|
label.className = "bb-linkpanel-href";
|
|
1597
|
-
label.textContent = internal.label ?? "
|
|
1597
|
+
label.textContent = internal.label ?? "This place is no longer in the document";
|
|
1598
1598
|
label.title = internal.label ?? existing.href;
|
|
1599
1599
|
if (!internal.label) label.classList.add("bb-linkpanel-stale");
|
|
1600
1600
|
row.appendChild(label);
|
|
1601
1601
|
if (internal.label) {
|
|
1602
1602
|
row.appendChild(
|
|
1603
|
-
iconBtn(ICONS.goTo, "
|
|
1603
|
+
iconBtn(ICONS.goTo, "Go to this place", () => {
|
|
1604
1604
|
closeCurrent2();
|
|
1605
1605
|
internal.onGo();
|
|
1606
1606
|
})
|
|
@@ -1814,8 +1814,8 @@ function openCellProperties({
|
|
|
1814
1814
|
label: "Fill",
|
|
1815
1815
|
clearLabel: "No fill",
|
|
1816
1816
|
value: () => background,
|
|
1817
|
-
onPick: (
|
|
1818
|
-
background =
|
|
1817
|
+
onPick: (c2) => {
|
|
1818
|
+
background = c2;
|
|
1819
1819
|
}
|
|
1820
1820
|
});
|
|
1821
1821
|
fill.append(fillBtn.el);
|
|
@@ -1868,8 +1868,8 @@ function openCellProperties({
|
|
|
1868
1868
|
title: "Border colour",
|
|
1869
1869
|
label: "Colour",
|
|
1870
1870
|
value: () => penColor,
|
|
1871
|
-
onPick: (
|
|
1872
|
-
if (
|
|
1871
|
+
onPick: (c2) => {
|
|
1872
|
+
if (c2) penColor = c2;
|
|
1873
1873
|
}
|
|
1874
1874
|
});
|
|
1875
1875
|
penRow.append(widthSel, styleSel, penBtn.el);
|
|
@@ -1933,8 +1933,400 @@ function openCellProperties({
|
|
|
1933
1933
|
dialog.open();
|
|
1934
1934
|
}
|
|
1935
1935
|
|
|
1936
|
-
// packages/ui/src/lib/
|
|
1936
|
+
// packages/ui/src/lib/equation-gallery.ts
|
|
1937
|
+
import { astToLinear } from "@shadow-garden/bapbong-contracts";
|
|
1938
|
+
var c = (s) => [...s].map((ch) => ({ t: "chr", ch }));
|
|
1939
|
+
var sup = (base, exp) => ({
|
|
1940
|
+
t: "scr",
|
|
1941
|
+
base,
|
|
1942
|
+
sub: [],
|
|
1943
|
+
sup: c(exp)
|
|
1944
|
+
});
|
|
1945
|
+
var subsup = (base, lo, hi) => ({
|
|
1946
|
+
t: "scr",
|
|
1947
|
+
base,
|
|
1948
|
+
sub: c(lo),
|
|
1949
|
+
sup: c(hi)
|
|
1950
|
+
});
|
|
1951
|
+
var BUILT_IN_EQUATIONS = [
|
|
1952
|
+
{
|
|
1953
|
+
name: "Area of a circle",
|
|
1954
|
+
ast: [...c("\u{1D434} = \u{1D70B}"), sup(c("\u{1D45F}"), "2")]
|
|
1955
|
+
},
|
|
1956
|
+
{
|
|
1957
|
+
name: "Pythagorean theorem",
|
|
1958
|
+
ast: [
|
|
1959
|
+
sup(c("\u{1D44E}"), "2"),
|
|
1960
|
+
...c(" + "),
|
|
1961
|
+
sup(c("\u{1D44F}"), "2"),
|
|
1962
|
+
...c(" = "),
|
|
1963
|
+
sup(c("\u{1D450}"), "2")
|
|
1964
|
+
]
|
|
1965
|
+
},
|
|
1966
|
+
{
|
|
1967
|
+
name: "Quadratic formula",
|
|
1968
|
+
ast: [
|
|
1969
|
+
...c("\u{1D465} = "),
|
|
1970
|
+
{
|
|
1971
|
+
t: "frac",
|
|
1972
|
+
num: [
|
|
1973
|
+
...c("\u2212\u{1D44F} \xB1 "),
|
|
1974
|
+
{
|
|
1975
|
+
t: "rad",
|
|
1976
|
+
deg: [],
|
|
1977
|
+
body: [sup(c("\u{1D44F}"), "2"), ...c(" \u2212 4\u{1D44E}\u{1D450}")]
|
|
1978
|
+
}
|
|
1979
|
+
],
|
|
1980
|
+
den: c("2\u{1D44E}")
|
|
1981
|
+
}
|
|
1982
|
+
]
|
|
1983
|
+
},
|
|
1984
|
+
{
|
|
1985
|
+
name: "Law of cosines",
|
|
1986
|
+
ast: [
|
|
1987
|
+
sup(c("\u{1D44E}"), "2"),
|
|
1988
|
+
...c(" = "),
|
|
1989
|
+
sup(c("\u{1D44F}"), "2"),
|
|
1990
|
+
...c(" + "),
|
|
1991
|
+
sup(c("\u{1D450}"), "2"),
|
|
1992
|
+
...c(" \u2212 2\u{1D44F}\u{1D450} cos \u{1D434}")
|
|
1993
|
+
]
|
|
1994
|
+
},
|
|
1995
|
+
{
|
|
1996
|
+
name: "Binomial theorem",
|
|
1997
|
+
ast: [
|
|
1998
|
+
// The exponent belongs ON the bracket: a script with an empty base
|
|
1999
|
+
// would render its own empty slot — the dotted placeholder box.
|
|
2000
|
+
{
|
|
2001
|
+
t: "scr",
|
|
2002
|
+
base: [{ t: "fence", l: "(", r: ")", body: c("\u{1D44E} + \u{1D44F}") }],
|
|
2003
|
+
sub: [],
|
|
2004
|
+
sup: c("\u{1D45B}")
|
|
2005
|
+
},
|
|
2006
|
+
...c(" = "),
|
|
2007
|
+
{
|
|
2008
|
+
t: "big",
|
|
2009
|
+
op: "\u2211",
|
|
2010
|
+
lo: c("\u{1D458} = 0"),
|
|
2011
|
+
hi: c("\u{1D45B}"),
|
|
2012
|
+
body: [
|
|
2013
|
+
subsup(c("\u{1D436}"), "\u{1D45B}", "\u{1D458}"),
|
|
2014
|
+
sup(c("\u{1D44E}"), "\u{1D458}"),
|
|
2015
|
+
{ t: "scr", base: c("\u{1D44F}"), sub: [], sup: c("\u{1D45B}\u2212\u{1D458}") }
|
|
2016
|
+
]
|
|
2017
|
+
}
|
|
2018
|
+
]
|
|
2019
|
+
}
|
|
2020
|
+
];
|
|
2021
|
+
var SVG_NS = "http://www.w3.org/2000/svg";
|
|
2022
|
+
function equationPreviewSvg(spec, opts = {}) {
|
|
2023
|
+
const svg = document.createElementNS(SVG_NS, "svg");
|
|
2024
|
+
svg.setAttribute("viewBox", `0 0 ${spec.width} ${spec.height}`);
|
|
2025
|
+
const max = opts.maxWidth ?? spec.width;
|
|
2026
|
+
const scale = Math.min(1, max / Math.max(1, spec.width));
|
|
2027
|
+
svg.setAttribute("width", String(Math.round(spec.width * scale)));
|
|
2028
|
+
svg.setAttribute("height", String(Math.round(spec.height * scale)));
|
|
2029
|
+
svg.setAttribute("aria-hidden", "true");
|
|
2030
|
+
for (const op of spec.ops) svg.append(opElement(op));
|
|
2031
|
+
return svg;
|
|
2032
|
+
}
|
|
2033
|
+
function opElement(op) {
|
|
2034
|
+
if (op.kind === "line") {
|
|
2035
|
+
const el6 = document.createElementNS(SVG_NS, "line");
|
|
2036
|
+
el6.setAttribute("x1", String(op.x1));
|
|
2037
|
+
el6.setAttribute("y1", String(op.y1));
|
|
2038
|
+
el6.setAttribute("x2", String(op.x2));
|
|
2039
|
+
el6.setAttribute("y2", String(op.y2));
|
|
2040
|
+
el6.setAttribute("stroke", op.color);
|
|
2041
|
+
el6.setAttribute("stroke-width", String(Math.max(op.width, 0.75)));
|
|
2042
|
+
return el6;
|
|
2043
|
+
}
|
|
2044
|
+
if (op.kind === "polygon") {
|
|
2045
|
+
const el6 = document.createElementNS(SVG_NS, "polygon");
|
|
2046
|
+
el6.setAttribute("points", op.points.map((p) => `${p.x},${p.y}`).join(" "));
|
|
2047
|
+
el6.setAttribute("fill", op.fill ?? "none");
|
|
2048
|
+
if (op.stroke) {
|
|
2049
|
+
el6.setAttribute("stroke", op.stroke);
|
|
2050
|
+
el6.setAttribute("stroke-width", String(op.strokeWidth ?? 1));
|
|
2051
|
+
}
|
|
2052
|
+
return el6;
|
|
2053
|
+
}
|
|
2054
|
+
const el5 = document.createElementNS(SVG_NS, "text");
|
|
2055
|
+
el5.setAttribute("x", String(op.x));
|
|
2056
|
+
el5.setAttribute("y", String(op.y));
|
|
2057
|
+
el5.setAttribute("font-size", String(op.size));
|
|
2058
|
+
el5.setAttribute("font-family", op.family);
|
|
2059
|
+
el5.setAttribute("fill", op.color);
|
|
2060
|
+
if (op.bold) el5.setAttribute("font-weight", "bold");
|
|
2061
|
+
if (op.italic) el5.setAttribute("font-style", "italic");
|
|
2062
|
+
if (op.vAlign === "top") el5.setAttribute("dominant-baseline", "hanging");
|
|
2063
|
+
if (op.dx) {
|
|
2064
|
+
let x = op.x;
|
|
2065
|
+
for (const [i, ch] of [...op.text].entries()) {
|
|
2066
|
+
const t = document.createElementNS(SVG_NS, "tspan");
|
|
2067
|
+
t.setAttribute("x", String(x));
|
|
2068
|
+
t.textContent = ch;
|
|
2069
|
+
el5.append(t);
|
|
2070
|
+
x += op.dx[i] ?? 0;
|
|
2071
|
+
}
|
|
2072
|
+
} else {
|
|
2073
|
+
el5.textContent = op.text;
|
|
2074
|
+
}
|
|
2075
|
+
return el5;
|
|
2076
|
+
}
|
|
1937
2077
|
var STYLE9 = `
|
|
2078
|
+
.bb-eqg{display:flex;flex-direction:column;min-width:236px;max-width:300px;user-select:none}
|
|
2079
|
+
.bb-eqg-head{font-size:11px;font-weight:600;opacity:.55;padding:2px 8px 6px}
|
|
2080
|
+
.bb-eqg-list{display:flex;flex-direction:column;max-height:320px;overflow-y:auto}
|
|
2081
|
+
.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}
|
|
2082
|
+
.bb-eqg-item:hover{background:var(--bb-ui-hover,#f1efe8)}
|
|
2083
|
+
.bb-eqg-name{font-size:11px;opacity:.6}
|
|
2084
|
+
/* The preview is the equation TYPESET \u2014 the same display list the canvas
|
|
2085
|
+
paints. The text form is the fallback for a host that cannot lay out. */
|
|
2086
|
+
.bb-eqg-prev{display:flex;align-items:center;min-height:22px;max-width:100%;overflow:hidden}
|
|
2087
|
+
.bb-eqg-prev svg{display:block}
|
|
2088
|
+
.bb-eqg-prev-text{font-family:"Times New Roman",Tinos,serif;font-size:15px;line-height:1.35;white-space:nowrap;text-overflow:ellipsis}
|
|
2089
|
+
.bb-eqg-foot{margin-top:4px;padding-top:5px;border-top:1px solid var(--bb-ui-border,#e3e3e0)}
|
|
2090
|
+
.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}
|
|
2091
|
+
.bb-eqg-new:hover{background:var(--bb-ui-hover,#f1efe8)}
|
|
2092
|
+
.bb-eqg-key{margin-left:auto;opacity:.5;font-size:12px}
|
|
2093
|
+
`;
|
|
2094
|
+
var PREVIEW_PT = 11;
|
|
2095
|
+
var PREVIEW_MAX_W = 264;
|
|
2096
|
+
function equationGallery(options) {
|
|
2097
|
+
injectStyle("bb-ui-eqg-styles", STYLE9);
|
|
2098
|
+
const root = document.createElement("div");
|
|
2099
|
+
root.className = "bb-eqg";
|
|
2100
|
+
const head = document.createElement("div");
|
|
2101
|
+
head.className = "bb-eqg-head";
|
|
2102
|
+
head.textContent = "Built-in";
|
|
2103
|
+
root.append(head);
|
|
2104
|
+
const list = document.createElement("div");
|
|
2105
|
+
list.className = "bb-eqg-list";
|
|
2106
|
+
for (const item of options.items ?? BUILT_IN_EQUATIONS) {
|
|
2107
|
+
const btn = document.createElement("button");
|
|
2108
|
+
btn.type = "button";
|
|
2109
|
+
btn.className = "bb-eqg-item";
|
|
2110
|
+
const prev = document.createElement("div");
|
|
2111
|
+
prev.className = "bb-eqg-prev";
|
|
2112
|
+
const spec = options.layout?.(item.ast, PREVIEW_PT) ?? null;
|
|
2113
|
+
if (spec && spec.ops.length)
|
|
2114
|
+
prev.append(equationPreviewSvg(spec, { maxWidth: PREVIEW_MAX_W }));
|
|
2115
|
+
else {
|
|
2116
|
+
prev.classList.add("bb-eqg-prev-text");
|
|
2117
|
+
prev.textContent = astToLinear(item.ast);
|
|
2118
|
+
}
|
|
2119
|
+
const name = document.createElement("div");
|
|
2120
|
+
name.className = "bb-eqg-name";
|
|
2121
|
+
name.textContent = item.name;
|
|
2122
|
+
btn.append(prev, name);
|
|
2123
|
+
btn.addEventListener("mousedown", (e) => e.preventDefault());
|
|
2124
|
+
btn.addEventListener("click", () => options.onPick(item.ast));
|
|
2125
|
+
list.append(btn);
|
|
2126
|
+
}
|
|
2127
|
+
root.append(list);
|
|
2128
|
+
const foot = document.createElement("div");
|
|
2129
|
+
foot.className = "bb-eqg-foot";
|
|
2130
|
+
const neu = document.createElement("button");
|
|
2131
|
+
neu.type = "button";
|
|
2132
|
+
neu.className = "bb-eqg-new";
|
|
2133
|
+
const label = document.createElement("span");
|
|
2134
|
+
label.textContent = "Insert new equation";
|
|
2135
|
+
neu.append(label);
|
|
2136
|
+
if (options.newShortcut) {
|
|
2137
|
+
const key = document.createElement("span");
|
|
2138
|
+
key.className = "bb-eqg-key";
|
|
2139
|
+
key.textContent = options.newShortcut;
|
|
2140
|
+
neu.append(key);
|
|
2141
|
+
}
|
|
2142
|
+
neu.addEventListener("mousedown", (e) => e.preventDefault());
|
|
2143
|
+
neu.addEventListener("click", () => options.onNew());
|
|
2144
|
+
foot.append(neu);
|
|
2145
|
+
root.append(foot);
|
|
2146
|
+
return root;
|
|
2147
|
+
}
|
|
2148
|
+
|
|
2149
|
+
// packages/ui/src/lib/equation-panel.ts
|
|
2150
|
+
import {
|
|
2151
|
+
eqStructureGroups,
|
|
2152
|
+
MATH_AUTOCORRECT,
|
|
2153
|
+
MATH_SYMBOL_SETS
|
|
2154
|
+
} from "@shadow-garden/bapbong-contracts";
|
|
2155
|
+
var SHORTHAND = /* @__PURE__ */ new Map();
|
|
2156
|
+
for (const [name, ch] of Object.entries(MATH_AUTOCORRECT))
|
|
2157
|
+
if (!SHORTHAND.has(ch)) SHORTHAND.set(ch, `\\${name}`);
|
|
2158
|
+
var PREVIEW_PT2 = 10;
|
|
2159
|
+
var STYLE10 = `
|
|
2160
|
+
.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}
|
|
2161
|
+
.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)}
|
|
2162
|
+
.bb-eqp.is-collapsed .bb-eqp-tabs{border-bottom:0}
|
|
2163
|
+
.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}
|
|
2164
|
+
.bb-eqp-tab:hover{background:var(--bb-ui-hover,#f1efe8)}
|
|
2165
|
+
.bb-eqp-tab[aria-selected="true"]{opacity:1;background:var(--bb-ui-sel,#e6f1fb);color:var(--bb-ui-sel-fg,#0c447c)}
|
|
2166
|
+
.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}
|
|
2167
|
+
.bb-eqp-fold:hover{background:var(--bb-ui-hover,#f1efe8);opacity:.9}
|
|
2168
|
+
.bb-eqp-body{padding:8px}
|
|
2169
|
+
.bb-eqp.is-collapsed .bb-eqp-body{display:none}
|
|
2170
|
+
.bb-eqp-set{width:100%;height:30px;margin-bottom:7px;font:inherit;font-size:13px}
|
|
2171
|
+
.bb-eqp-grid{display:grid;grid-template-columns:repeat(10,1fr);gap:1px;max-height:190px;overflow-y:auto}
|
|
2172
|
+
.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}
|
|
2173
|
+
.bb-eqp-sym:hover{background:var(--bb-ui-hover,#f1efe8)}
|
|
2174
|
+
.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}
|
|
2175
|
+
.bb-eqp-hint-g{font-family:"Cambria Math","Times New Roman",Tinos,serif;font-size:15px}
|
|
2176
|
+
.bb-eqp-hint-k{font-family:ui-monospace,SFMono-Regular,Menlo,monospace}
|
|
2177
|
+
.bb-eqp-scroll{max-height:230px;overflow-y:auto}
|
|
2178
|
+
.bb-eqp-group{font-size:11px;font-weight:600;opacity:.5;padding:6px 2px 3px}
|
|
2179
|
+
.bb-eqp-row{display:grid;grid-template-columns:repeat(4,1fr);gap:3px}
|
|
2180
|
+
.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}
|
|
2181
|
+
.bb-eqp-st:hover{background:var(--bb-ui-hover,#f1efe8)}
|
|
2182
|
+
.bb-eqp-st-name{font-size:10px;opacity:.6;text-align:center;line-height:1.25}
|
|
2183
|
+
.bb-eqp-st svg{display:block}
|
|
2184
|
+
`;
|
|
2185
|
+
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>';
|
|
2186
|
+
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>';
|
|
2187
|
+
function equationPanel(options) {
|
|
2188
|
+
injectStyle("bb-ui-eqp-styles", STYLE10);
|
|
2189
|
+
const root = document.createElement("div");
|
|
2190
|
+
root.className = "bb-eqp";
|
|
2191
|
+
root.setAttribute("role", "group");
|
|
2192
|
+
root.setAttribute("aria-label", "Equation palette");
|
|
2193
|
+
root.addEventListener("mousedown", (e) => e.preventDefault());
|
|
2194
|
+
const tabs = document.createElement("div");
|
|
2195
|
+
tabs.className = "bb-eqp-tabs";
|
|
2196
|
+
tabs.setAttribute("role", "tablist");
|
|
2197
|
+
const body = document.createElement("div");
|
|
2198
|
+
body.className = "bb-eqp-body";
|
|
2199
|
+
let collapsed = false;
|
|
2200
|
+
let current3 = "symbols";
|
|
2201
|
+
const tabEls = {};
|
|
2202
|
+
const mkTab = (id, label) => {
|
|
2203
|
+
const b = document.createElement("button");
|
|
2204
|
+
b.type = "button";
|
|
2205
|
+
b.className = "bb-eqp-tab";
|
|
2206
|
+
b.textContent = label;
|
|
2207
|
+
b.setAttribute("role", "tab");
|
|
2208
|
+
b.addEventListener("click", () => {
|
|
2209
|
+
current3 = id;
|
|
2210
|
+
if (collapsed) setCollapsed(false);
|
|
2211
|
+
render();
|
|
2212
|
+
});
|
|
2213
|
+
tabEls[id] = b;
|
|
2214
|
+
tabs.append(b);
|
|
2215
|
+
};
|
|
2216
|
+
mkTab("symbols", "Symbols");
|
|
2217
|
+
mkTab("structures", "Structures");
|
|
2218
|
+
const fold = document.createElement("button");
|
|
2219
|
+
fold.type = "button";
|
|
2220
|
+
fold.className = "bb-eqp-fold";
|
|
2221
|
+
fold.addEventListener("click", () => setCollapsed(!collapsed));
|
|
2222
|
+
tabs.append(fold);
|
|
2223
|
+
root.append(tabs, body);
|
|
2224
|
+
function setCollapsed(next) {
|
|
2225
|
+
collapsed = next;
|
|
2226
|
+
root.classList.toggle("is-collapsed", collapsed);
|
|
2227
|
+
fold.innerHTML = collapsed ? CHEVRON_DOWN : CHEVRON_UP;
|
|
2228
|
+
fold.setAttribute(
|
|
2229
|
+
"aria-label",
|
|
2230
|
+
collapsed ? "Show palette" : "Hide palette"
|
|
2231
|
+
);
|
|
2232
|
+
fold.setAttribute("aria-expanded", String(!collapsed));
|
|
2233
|
+
}
|
|
2234
|
+
function symbolsBody() {
|
|
2235
|
+
const set = document.createElement("select");
|
|
2236
|
+
set.className = "bb-eqp-set";
|
|
2237
|
+
set.setAttribute("aria-label", "Symbol set");
|
|
2238
|
+
for (const [i, s] of MATH_SYMBOL_SETS.entries()) {
|
|
2239
|
+
const o = document.createElement("option");
|
|
2240
|
+
o.value = String(i);
|
|
2241
|
+
o.textContent = s.name;
|
|
2242
|
+
set.append(o);
|
|
2243
|
+
}
|
|
2244
|
+
set.value = String(setIndex);
|
|
2245
|
+
const grid = document.createElement("div");
|
|
2246
|
+
grid.className = "bb-eqp-grid";
|
|
2247
|
+
const hint = document.createElement("div");
|
|
2248
|
+
hint.className = "bb-eqp-hint";
|
|
2249
|
+
const hintG = document.createElement("span");
|
|
2250
|
+
hintG.className = "bb-eqp-hint-g";
|
|
2251
|
+
const hintK = document.createElement("span");
|
|
2252
|
+
hintK.className = "bb-eqp-hint-k";
|
|
2253
|
+
hint.append(hintG, hintK);
|
|
2254
|
+
const fill = () => {
|
|
2255
|
+
grid.replaceChildren();
|
|
2256
|
+
const chars = MATH_SYMBOL_SETS[setIndex]?.chars ?? "";
|
|
2257
|
+
for (const ch of chars) {
|
|
2258
|
+
const b = document.createElement("button");
|
|
2259
|
+
b.type = "button";
|
|
2260
|
+
b.className = "bb-eqp-sym";
|
|
2261
|
+
b.textContent = ch;
|
|
2262
|
+
const key = SHORTHAND.get(ch);
|
|
2263
|
+
b.title = key ? `${ch} ${key}` : ch;
|
|
2264
|
+
b.addEventListener("mouseenter", () => {
|
|
2265
|
+
hintG.textContent = ch;
|
|
2266
|
+
hintK.textContent = key ?? "";
|
|
2267
|
+
});
|
|
2268
|
+
b.addEventListener("click", () => options.onSymbol(ch));
|
|
2269
|
+
grid.append(b);
|
|
2270
|
+
}
|
|
2271
|
+
};
|
|
2272
|
+
set.addEventListener("change", () => {
|
|
2273
|
+
setIndex = Number(set.value) || 0;
|
|
2274
|
+
fill();
|
|
2275
|
+
});
|
|
2276
|
+
fill();
|
|
2277
|
+
body.replaceChildren(set, grid, hint);
|
|
2278
|
+
}
|
|
2279
|
+
function structuresBody() {
|
|
2280
|
+
const scroll = document.createElement("div");
|
|
2281
|
+
scroll.className = "bb-eqp-scroll";
|
|
2282
|
+
for (const group of eqStructureGroups()) {
|
|
2283
|
+
const h = document.createElement("div");
|
|
2284
|
+
h.className = "bb-eqp-group";
|
|
2285
|
+
h.textContent = group.name;
|
|
2286
|
+
const row = document.createElement("div");
|
|
2287
|
+
row.className = "bb-eqp-row";
|
|
2288
|
+
for (const item of group.items) {
|
|
2289
|
+
const b = document.createElement("button");
|
|
2290
|
+
b.type = "button";
|
|
2291
|
+
b.className = "bb-eqp-st";
|
|
2292
|
+
b.title = `${group.name} \u2014 ${item.name}`;
|
|
2293
|
+
const spec = options.layout?.([item.node], PREVIEW_PT2) ?? null;
|
|
2294
|
+
if (spec && spec.ops.length)
|
|
2295
|
+
b.append(equationPreviewSvg(spec, { maxWidth: 60 }));
|
|
2296
|
+
const name = document.createElement("span");
|
|
2297
|
+
name.className = "bb-eqp-st-name";
|
|
2298
|
+
name.textContent = item.name;
|
|
2299
|
+
b.append(name);
|
|
2300
|
+
b.addEventListener("click", () => options.onStructure(item));
|
|
2301
|
+
row.append(b);
|
|
2302
|
+
}
|
|
2303
|
+
scroll.append(h, row);
|
|
2304
|
+
}
|
|
2305
|
+
body.replaceChildren(scroll);
|
|
2306
|
+
}
|
|
2307
|
+
let setIndex = 0;
|
|
2308
|
+
function render() {
|
|
2309
|
+
for (const [id, el5] of Object.entries(tabEls))
|
|
2310
|
+
el5.setAttribute("aria-selected", String(id === current3));
|
|
2311
|
+
if (current3 === "symbols") symbolsBody();
|
|
2312
|
+
else structuresBody();
|
|
2313
|
+
}
|
|
2314
|
+
setCollapsed(false);
|
|
2315
|
+
render();
|
|
2316
|
+
return {
|
|
2317
|
+
el: root,
|
|
2318
|
+
setCollapsed,
|
|
2319
|
+
get collapsed() {
|
|
2320
|
+
return collapsed;
|
|
2321
|
+
},
|
|
2322
|
+
destroy() {
|
|
2323
|
+
root.remove();
|
|
2324
|
+
}
|
|
2325
|
+
};
|
|
2326
|
+
}
|
|
2327
|
+
|
|
2328
|
+
// packages/ui/src/lib/table-grid.ts
|
|
2329
|
+
var STYLE11 = `
|
|
1938
2330
|
.bb-grid{display:flex;flex-direction:column;gap:6px;user-select:none}
|
|
1939
2331
|
.bb-grid-cells{display:grid;gap:2px}
|
|
1940
2332
|
.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}
|
|
@@ -1942,7 +2334,7 @@ var STYLE9 = `
|
|
|
1942
2334
|
.bb-grid-label{font-size:12px;text-align:center;opacity:.7}
|
|
1943
2335
|
`;
|
|
1944
2336
|
function tableGridPicker(options) {
|
|
1945
|
-
injectStyle("bb-ui-grid-styles",
|
|
2337
|
+
injectStyle("bb-ui-grid-styles", STYLE11);
|
|
1946
2338
|
const maxRows = options.maxRows ?? 8;
|
|
1947
2339
|
const maxCols = options.maxCols ?? 10;
|
|
1948
2340
|
const root = document.createElement("div");
|
|
@@ -1954,22 +2346,22 @@ function tableGridPicker(options) {
|
|
|
1954
2346
|
label.className = "bb-grid-label";
|
|
1955
2347
|
label.textContent = "0 \xD7 0";
|
|
1956
2348
|
const cells = [];
|
|
1957
|
-
const highlight2 = (r,
|
|
2349
|
+
const highlight2 = (r, c2) => {
|
|
1958
2350
|
for (let i = 0; i < cells.length; i++) {
|
|
1959
2351
|
const row = Math.floor(i / maxCols);
|
|
1960
2352
|
const col = i % maxCols;
|
|
1961
|
-
cells[i].classList.toggle("on", row <= r && col <=
|
|
2353
|
+
cells[i].classList.toggle("on", row <= r && col <= c2);
|
|
1962
2354
|
}
|
|
1963
|
-
label.textContent = `${r + 1} \xD7 ${
|
|
2355
|
+
label.textContent = `${r + 1} \xD7 ${c2 + 1}`;
|
|
1964
2356
|
};
|
|
1965
2357
|
for (let r = 0; r < maxRows; r++) {
|
|
1966
|
-
for (let
|
|
2358
|
+
for (let c2 = 0; c2 < maxCols; c2++) {
|
|
1967
2359
|
const cell = document.createElement("button");
|
|
1968
2360
|
cell.type = "button";
|
|
1969
2361
|
cell.className = "bb-grid-cell";
|
|
1970
2362
|
cell.addEventListener("mousedown", (e) => e.preventDefault());
|
|
1971
|
-
cell.addEventListener("mouseenter", () => highlight2(r,
|
|
1972
|
-
cell.addEventListener("click", () => options.onPick(r + 1,
|
|
2363
|
+
cell.addEventListener("mouseenter", () => highlight2(r, c2));
|
|
2364
|
+
cell.addEventListener("click", () => options.onPick(r + 1, c2 + 1));
|
|
1973
2365
|
cells.push(cell);
|
|
1974
2366
|
cellsEl.appendChild(cell);
|
|
1975
2367
|
}
|
|
@@ -1985,7 +2377,7 @@ var cmToPx = (cm) => Math.round(cm * PX_PER_CM);
|
|
|
1985
2377
|
function fmtCm(cm) {
|
|
1986
2378
|
return `${Number(cm.toFixed(3))} cm`;
|
|
1987
2379
|
}
|
|
1988
|
-
var
|
|
2380
|
+
var STYLE12 = `
|
|
1989
2381
|
.bb-ps{display:flex;flex-direction:column;min-width:250px;max-height:min(70vh,460px);overflow-y:auto}
|
|
1990
2382
|
.bb-ps,.bb-ps *{box-sizing:border-box}
|
|
1991
2383
|
.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}
|
|
@@ -2015,9 +2407,9 @@ var STYLE10 = `
|
|
|
2015
2407
|
.bb-ps-tile:hover,.bb-ps-tile:focus{background:var(--bb-ui-hover,#f1efe8);outline:none}
|
|
2016
2408
|
.bb-ps-tile[aria-checked="true"]{background:var(--bb-ui-active-bg,#e6f1fb)}
|
|
2017
2409
|
`;
|
|
2018
|
-
var
|
|
2410
|
+
var SVG_NS2 = "http://www.w3.org/2000/svg";
|
|
2019
2411
|
function svgEl(name, attrs) {
|
|
2020
|
-
const el5 = document.createElementNS(
|
|
2412
|
+
const el5 = document.createElementNS(SVG_NS2, name);
|
|
2021
2413
|
for (const [k, v] of Object.entries(attrs)) el5.setAttribute(k, String(v));
|
|
2022
2414
|
return el5;
|
|
2023
2415
|
}
|
|
@@ -2111,7 +2503,7 @@ function customRow(icon, title, description, onPick) {
|
|
|
2111
2503
|
return presetRow(icon, title, captionLine(description), false, onPick);
|
|
2112
2504
|
}
|
|
2113
2505
|
function pageSizePicker(options) {
|
|
2114
|
-
injectStyle("bb-ui-pagesetup-styles",
|
|
2506
|
+
injectStyle("bb-ui-pagesetup-styles", STYLE12);
|
|
2115
2507
|
const root = document.createElement("div");
|
|
2116
2508
|
root.className = "bb-ps";
|
|
2117
2509
|
root.setAttribute("role", "menu");
|
|
@@ -2140,7 +2532,7 @@ function pageSizePicker(options) {
|
|
|
2140
2532
|
return root;
|
|
2141
2533
|
}
|
|
2142
2534
|
function orientationPicker(options) {
|
|
2143
|
-
injectStyle("bb-ui-pagesetup-styles",
|
|
2535
|
+
injectStyle("bb-ui-pagesetup-styles", STYLE12);
|
|
2144
2536
|
const root = document.createElement("div");
|
|
2145
2537
|
root.className = "bb-ps";
|
|
2146
2538
|
root.setAttribute("role", "menu");
|
|
@@ -2163,7 +2555,7 @@ function orientationPicker(options) {
|
|
|
2163
2555
|
return root;
|
|
2164
2556
|
}
|
|
2165
2557
|
function marginPresetPicker(options) {
|
|
2166
|
-
injectStyle("bb-ui-pagesetup-styles",
|
|
2558
|
+
injectStyle("bb-ui-pagesetup-styles", STYLE12);
|
|
2167
2559
|
const root = document.createElement("div");
|
|
2168
2560
|
root.className = "bb-ps";
|
|
2169
2561
|
root.setAttribute("role", "menu");
|
|
@@ -2238,7 +2630,7 @@ function readPx(input, fallbackPx) {
|
|
|
2238
2630
|
return Number.isFinite(n) && n > 0 ? cmToPx(n) : fallbackPx;
|
|
2239
2631
|
}
|
|
2240
2632
|
function openPageSizeDialog(options) {
|
|
2241
|
-
injectStyle("bb-ui-pagesetup-styles",
|
|
2633
|
+
injectStyle("bb-ui-pagesetup-styles", STYLE12);
|
|
2242
2634
|
const dialog = new Dialog({ title: "Paper size", modal: true });
|
|
2243
2635
|
const form = document.createElement("form");
|
|
2244
2636
|
form.className = "bb-pd";
|
|
@@ -2265,7 +2657,7 @@ function openPageSizeDialog(options) {
|
|
|
2265
2657
|
width.input.select();
|
|
2266
2658
|
}
|
|
2267
2659
|
function openMarginsDialog(options) {
|
|
2268
|
-
injectStyle("bb-ui-pagesetup-styles",
|
|
2660
|
+
injectStyle("bb-ui-pagesetup-styles", STYLE12);
|
|
2269
2661
|
const dialog = new Dialog({ title: "Margins", modal: true });
|
|
2270
2662
|
const form = document.createElement("form");
|
|
2271
2663
|
form.className = "bb-pd";
|
|
@@ -2322,7 +2714,7 @@ var PGNUM_FORMATS = [
|
|
|
2322
2714
|
["upperLetter", "A, B, C, D\u2026", "A"]
|
|
2323
2715
|
];
|
|
2324
2716
|
function pageNumberPicker(options) {
|
|
2325
|
-
injectStyle("bb-ui-pagesetup-styles",
|
|
2717
|
+
injectStyle("bb-ui-pagesetup-styles", STYLE12);
|
|
2326
2718
|
const root = document.createElement("div");
|
|
2327
2719
|
root.className = "bb-ps";
|
|
2328
2720
|
root.setAttribute("role", "menu");
|
|
@@ -2423,7 +2815,7 @@ function pageNumberPicker(options) {
|
|
|
2423
2815
|
return root;
|
|
2424
2816
|
}
|
|
2425
2817
|
function sectionPaperPanel(options) {
|
|
2426
|
-
injectStyle("bb-ui-pagesetup-styles",
|
|
2818
|
+
injectStyle("bb-ui-pagesetup-styles", STYLE12);
|
|
2427
2819
|
const root = document.createElement("div");
|
|
2428
2820
|
root.className = "bb-ps";
|
|
2429
2821
|
root.setAttribute("role", "menu");
|
|
@@ -2492,7 +2884,7 @@ function sectionPaperPanel(options) {
|
|
|
2492
2884
|
}
|
|
2493
2885
|
|
|
2494
2886
|
// packages/ui/src/lib/section-chip.ts
|
|
2495
|
-
var
|
|
2887
|
+
var STYLE13 = `
|
|
2496
2888
|
.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)}
|
|
2497
2889
|
.bb-secchip *{box-sizing:border-box}
|
|
2498
2890
|
.bb-secchip-title{padding:0 7px;font-size:11px;font-weight:600;opacity:.8}
|
|
@@ -2505,7 +2897,7 @@ var STYLE11 = `
|
|
|
2505
2897
|
.bb-secchip-x:hover{background:var(--bb-ui-hover,#f1efe8);opacity:1}
|
|
2506
2898
|
`;
|
|
2507
2899
|
function createSectionChip(options) {
|
|
2508
|
-
injectStyle("bb-ui-section-chip-styles",
|
|
2900
|
+
injectStyle("bb-ui-section-chip-styles", STYLE13);
|
|
2509
2901
|
const el5 = document.createElement("div");
|
|
2510
2902
|
el5.className = "bb-secchip";
|
|
2511
2903
|
const title = document.createElement("span");
|
|
@@ -2562,7 +2954,7 @@ var halfToPt = (hp) => hp / 2;
|
|
|
2562
2954
|
var ptToHalf = (pt) => Math.round(pt * 2);
|
|
2563
2955
|
var SCALE_PRESETS = [200, 150, 100, 90, 80, 66, 50, 33];
|
|
2564
2956
|
var SUPERSUB_SCALE = 0.66;
|
|
2565
|
-
var
|
|
2957
|
+
var STYLE14 = `
|
|
2566
2958
|
.bb-fd{display:flex;flex-direction:column;gap:15px;min-width:396px;max-width:430px;color:var(--bb-ui-fg,#2c2c2a)}
|
|
2567
2959
|
.bb-fd *{box-sizing:border-box}
|
|
2568
2960
|
/* A segmented control, not a "tab joined to its pane": that pattern needs the
|
|
@@ -2644,7 +3036,7 @@ function openFontDialog({
|
|
|
2644
3036
|
sizes,
|
|
2645
3037
|
onApply
|
|
2646
3038
|
}) {
|
|
2647
|
-
injectStyle("bb-font-dialog",
|
|
3039
|
+
injectStyle("bb-font-dialog", STYLE14);
|
|
2648
3040
|
const dialog = new Dialog({ title: "Font", modal: true });
|
|
2649
3041
|
const root = el("div", "bb-fd");
|
|
2650
3042
|
const tabs = el("div", "bb-fd-tabs");
|
|
@@ -2708,8 +3100,8 @@ function openFontDialog({
|
|
|
2708
3100
|
label: "Text color",
|
|
2709
3101
|
clearLabel: "Automatic",
|
|
2710
3102
|
value: () => color,
|
|
2711
|
-
onPick: (
|
|
2712
|
-
color =
|
|
3103
|
+
onPick: (c2) => {
|
|
3104
|
+
color = c2;
|
|
2713
3105
|
paint();
|
|
2714
3106
|
}
|
|
2715
3107
|
});
|
|
@@ -2718,8 +3110,8 @@ function openFontDialog({
|
|
|
2718
3110
|
label: "Highlight",
|
|
2719
3111
|
clearLabel: "No highlight",
|
|
2720
3112
|
value: () => highlight2,
|
|
2721
|
-
onPick: (
|
|
2722
|
-
highlight2 =
|
|
3113
|
+
onPick: (c2) => {
|
|
3114
|
+
highlight2 = c2;
|
|
2723
3115
|
paint();
|
|
2724
3116
|
}
|
|
2725
3117
|
});
|
|
@@ -2844,8 +3236,8 @@ function openFontDialog({
|
|
|
2844
3236
|
s.transform = scale === 100 ? "none" : `scaleX(${scale / 100})`;
|
|
2845
3237
|
s.verticalAlign = supCb.checked ? "super" : subCb.checked ? "sub" : `${positionPt}pt`;
|
|
2846
3238
|
}
|
|
2847
|
-
for (const
|
|
2848
|
-
|
|
3239
|
+
for (const c2 of [familySel, sizeSel, scaleSel])
|
|
3240
|
+
c2.addEventListener("change", paint);
|
|
2849
3241
|
for (const i of [spacingInput, positionInput])
|
|
2850
3242
|
i.addEventListener("input", paint);
|
|
2851
3243
|
const foot = el("div", "bb-fd-foot");
|
|
@@ -3266,7 +3658,7 @@ function parseCodePoint(input) {
|
|
|
3266
3658
|
}
|
|
3267
3659
|
var RECENT_MAX = 16;
|
|
3268
3660
|
function pushRecent(recent, char, max = RECENT_MAX) {
|
|
3269
|
-
return [char, ...recent.filter((
|
|
3661
|
+
return [char, ...recent.filter((c2) => c2 !== char)].slice(0, max);
|
|
3270
3662
|
}
|
|
3271
3663
|
function searchSymbols(query) {
|
|
3272
3664
|
const q = query.trim().toLowerCase();
|
|
@@ -3286,7 +3678,7 @@ function searchSymbols(query) {
|
|
|
3286
3678
|
}
|
|
3287
3679
|
|
|
3288
3680
|
// packages/ui/src/lib/symbol-dialog.ts
|
|
3289
|
-
var
|
|
3681
|
+
var STYLE15 = `
|
|
3290
3682
|
.bb-sd{display:flex;flex-direction:column;gap:12px;width:412px;max-width:100%;color:var(--bb-ui-fg,#2c2c2a)}
|
|
3291
3683
|
.bb-sd *{box-sizing:border-box}
|
|
3292
3684
|
.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}
|
|
@@ -3347,7 +3739,7 @@ function glyphFor(char) {
|
|
|
3347
3739
|
return char;
|
|
3348
3740
|
}
|
|
3349
3741
|
function createSymbolDialog(options) {
|
|
3350
|
-
injectStyle("bb-symbol-dialog",
|
|
3742
|
+
injectStyle("bb-symbol-dialog", STYLE15);
|
|
3351
3743
|
let recent = [...options.recent ?? []].slice(0, RECENT_MAX);
|
|
3352
3744
|
let selected = null;
|
|
3353
3745
|
const root = el2("div", "bb-sd");
|
|
@@ -3536,9 +3928,9 @@ function createSymbolDialog(options) {
|
|
|
3536
3928
|
function renderRecent() {
|
|
3537
3929
|
fillGrid(
|
|
3538
3930
|
recentGrid,
|
|
3539
|
-
recent.map((
|
|
3540
|
-
char:
|
|
3541
|
-
name: SYMBOL_NAMES.get(
|
|
3931
|
+
recent.map((c2) => ({
|
|
3932
|
+
char: c2,
|
|
3933
|
+
name: SYMBOL_NAMES.get(c2) ?? "Character"
|
|
3542
3934
|
})),
|
|
3543
3935
|
RECENT_COLS,
|
|
3544
3936
|
"Nothing yet \u2014 inserted symbols appear here."
|
|
@@ -3582,7 +3974,7 @@ function createSymbolDialog(options) {
|
|
|
3582
3974
|
code.removeAttribute("aria-invalid");
|
|
3583
3975
|
const cell = Array.from(
|
|
3584
3976
|
grid.querySelectorAll(".bb-sd-cell")
|
|
3585
|
-
).find((
|
|
3977
|
+
).find((c2) => c2.textContent === glyphFor(ch));
|
|
3586
3978
|
select2(ch, cell ?? null);
|
|
3587
3979
|
} else {
|
|
3588
3980
|
code.setAttribute("aria-invalid", code.value.trim() ? "true" : "false");
|
|
@@ -3625,7 +4017,7 @@ function createSymbolDialog(options) {
|
|
|
3625
4017
|
}
|
|
3626
4018
|
|
|
3627
4019
|
// packages/ui/src/lib/symbol-popover.ts
|
|
3628
|
-
var
|
|
4020
|
+
var STYLE16 = `
|
|
3629
4021
|
.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}
|
|
3630
4022
|
.bb-spk *{box-sizing:border-box}
|
|
3631
4023
|
.bb-spk::backdrop{background:transparent}
|
|
@@ -3658,7 +4050,7 @@ function el3(tag, cls, text) {
|
|
|
3658
4050
|
return n;
|
|
3659
4051
|
}
|
|
3660
4052
|
function openSymbolPopover(options) {
|
|
3661
|
-
injectStyle("bb-ui-symbol-popover",
|
|
4053
|
+
injectStyle("bb-ui-symbol-popover", STYLE16);
|
|
3662
4054
|
const { anchor } = options;
|
|
3663
4055
|
let recent = [...options.recent ?? []].slice(0, RECENT_MAX);
|
|
3664
4056
|
let groupId = SYMBOL_GROUPS[0].id;
|
|
@@ -3689,16 +4081,16 @@ function openSymbolPopover(options) {
|
|
|
3689
4081
|
const chips = el3("div", "bb-spk-chips");
|
|
3690
4082
|
const chipEls = /* @__PURE__ */ new Map();
|
|
3691
4083
|
for (const grp of SYMBOL_GROUPS) {
|
|
3692
|
-
const
|
|
3693
|
-
|
|
3694
|
-
|
|
3695
|
-
|
|
4084
|
+
const c2 = el3("button", "bb-spk-chip", grp.short);
|
|
4085
|
+
c2.type = "button";
|
|
4086
|
+
c2.title = grp.label;
|
|
4087
|
+
c2.addEventListener("click", () => {
|
|
3696
4088
|
groupId = grp.id;
|
|
3697
4089
|
search.value = "";
|
|
3698
4090
|
render();
|
|
3699
4091
|
});
|
|
3700
|
-
chips.append(
|
|
3701
|
-
chipEls.set(grp.id,
|
|
4092
|
+
chips.append(c2);
|
|
4093
|
+
chipEls.set(grp.id, c2);
|
|
3702
4094
|
}
|
|
3703
4095
|
const grid = el3("div", "bb-spk-grid");
|
|
3704
4096
|
grid.setAttribute("role", "grid");
|
|
@@ -3769,9 +4161,9 @@ function openSymbolPopover(options) {
|
|
|
3769
4161
|
};
|
|
3770
4162
|
const renderRecent = () => fill(
|
|
3771
4163
|
recentGrid,
|
|
3772
|
-
recent.slice(0, RECENT_ROW).map((
|
|
3773
|
-
char:
|
|
3774
|
-
name: SYMBOL_NAMES.get(
|
|
4164
|
+
recent.slice(0, RECENT_ROW).map((c2) => ({
|
|
4165
|
+
char: c2,
|
|
4166
|
+
name: SYMBOL_NAMES.get(c2) ?? "Character"
|
|
3775
4167
|
})),
|
|
3776
4168
|
"Nothing yet."
|
|
3777
4169
|
);
|
|
@@ -3779,8 +4171,8 @@ function openSymbolPopover(options) {
|
|
|
3779
4171
|
const q = search.value.trim();
|
|
3780
4172
|
const byCode = q ? parseCodePoint(q) : null;
|
|
3781
4173
|
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 ?? [];
|
|
3782
|
-
for (const [id,
|
|
3783
|
-
|
|
4174
|
+
for (const [id, c2] of chipEls)
|
|
4175
|
+
c2.setAttribute("aria-pressed", String(!q && id === groupId));
|
|
3784
4176
|
fill(grid, entries, "No match.");
|
|
3785
4177
|
const first = grid.querySelector(".bb-spk-cell");
|
|
3786
4178
|
if (q && first && entries[0]) select2(entries[0].char, first);
|
|
@@ -3824,7 +4216,7 @@ import {
|
|
|
3824
4216
|
formatKey,
|
|
3825
4217
|
keybindingRows
|
|
3826
4218
|
} from "@shadow-garden/bapbong-contracts";
|
|
3827
|
-
var
|
|
4219
|
+
var STYLE17 = `
|
|
3828
4220
|
.bb-ks{display:flex;flex-direction:column;gap:10px;width:600px;max-width:100%;color:var(--bb-ui-fg,#2c2c2a);font-size:12px}
|
|
3829
4221
|
.bb-ks *{box-sizing:border-box}
|
|
3830
4222
|
.bb-ks-top{display:flex;gap:8px;align-items:center}
|
|
@@ -3882,7 +4274,7 @@ function highlight(text, q) {
|
|
|
3882
4274
|
return out;
|
|
3883
4275
|
}
|
|
3884
4276
|
function openKeyboardShortcutsDialog(options) {
|
|
3885
|
-
injectStyle("bb-ui-shortcuts-dialog",
|
|
4277
|
+
injectStyle("bb-ui-shortcuts-dialog", STYLE17);
|
|
3886
4278
|
const dialog = new Dialog({
|
|
3887
4279
|
title: options.title ?? "Keyboard shortcuts",
|
|
3888
4280
|
modal: true,
|
|
@@ -3909,19 +4301,19 @@ function openKeyboardShortcutsDialog(options) {
|
|
|
3909
4301
|
let sortKey = "title";
|
|
3910
4302
|
let sortAsc = true;
|
|
3911
4303
|
const ths = /* @__PURE__ */ new Map();
|
|
3912
|
-
for (const
|
|
4304
|
+
for (const c2 of columns) {
|
|
3913
4305
|
const th = el4("th");
|
|
3914
|
-
th.append(el4("span", void 0,
|
|
4306
|
+
th.append(el4("span", void 0, c2.label));
|
|
3915
4307
|
th.addEventListener("click", () => {
|
|
3916
|
-
if (sortKey ===
|
|
4308
|
+
if (sortKey === c2.key) sortAsc = !sortAsc;
|
|
3917
4309
|
else {
|
|
3918
|
-
sortKey =
|
|
4310
|
+
sortKey = c2.key;
|
|
3919
4311
|
sortAsc = true;
|
|
3920
4312
|
}
|
|
3921
4313
|
render();
|
|
3922
4314
|
});
|
|
3923
4315
|
headRow.append(th);
|
|
3924
|
-
ths.set(
|
|
4316
|
+
ths.set(c2.key, th);
|
|
3925
4317
|
}
|
|
3926
4318
|
thead.append(headRow);
|
|
3927
4319
|
const tbody = el4("tbody");
|
|
@@ -3941,7 +4333,7 @@ function openKeyboardShortcutsDialog(options) {
|
|
|
3941
4333
|
const rows = [];
|
|
3942
4334
|
for (const src of options.sources)
|
|
3943
4335
|
rows.push(
|
|
3944
|
-
...keybindingRows(src.keybindings, (
|
|
4336
|
+
...keybindingRows(src.keybindings, (c2) => src.commands.get(c2)?.title)
|
|
3945
4337
|
);
|
|
3946
4338
|
return rows;
|
|
3947
4339
|
};
|
|
@@ -3998,7 +4390,7 @@ function openKeyboardShortcutsDialog(options) {
|
|
|
3998
4390
|
tbody.append(tr);
|
|
3999
4391
|
}
|
|
4000
4392
|
count.textContent = shown.length === rows.length ? `${rows.length} shortcuts` : `${shown.length} of ${rows.length}`;
|
|
4001
|
-
footL.textContent = `Sorted by ${columns.find((
|
|
4393
|
+
footL.textContent = `Sorted by ${columns.find((c2) => c2.key === sortKey)?.label.toLowerCase()} \xB7 click a header to sort`;
|
|
4002
4394
|
};
|
|
4003
4395
|
search.addEventListener("input", render);
|
|
4004
4396
|
dialog.onClose(() => dialog.destroy());
|
|
@@ -4008,7 +4400,7 @@ function openKeyboardShortcutsDialog(options) {
|
|
|
4008
4400
|
}
|
|
4009
4401
|
|
|
4010
4402
|
// packages/ui/src/lib/scrollbars.ts
|
|
4011
|
-
var
|
|
4403
|
+
var STYLE18 = `
|
|
4012
4404
|
@property --bb-scroll-thumb-now {
|
|
4013
4405
|
syntax: '<color>';
|
|
4014
4406
|
/* MUST inherit: the thumb pseudo-element never matches .bb-scrolling
|
|
@@ -4040,7 +4432,7 @@ var STYLE16 = `
|
|
|
4040
4432
|
var installed = null;
|
|
4041
4433
|
function installScrollbars(root = document) {
|
|
4042
4434
|
if (installed) return installed;
|
|
4043
|
-
injectStyle("bb-ui-scrollbars",
|
|
4435
|
+
injectStyle("bb-ui-scrollbars", STYLE18);
|
|
4044
4436
|
const quiet = /* @__PURE__ */ new WeakMap();
|
|
4045
4437
|
const onScroll = (ev) => {
|
|
4046
4438
|
const el5 = ev.target instanceof HTMLElement ? ev.target : root.documentElement;
|
|
@@ -4059,6 +4451,7 @@ function installScrollbars(root = document) {
|
|
|
4059
4451
|
return installed;
|
|
4060
4452
|
}
|
|
4061
4453
|
export {
|
|
4454
|
+
BUILT_IN_EQUATIONS,
|
|
4062
4455
|
COLOR_PALETTE,
|
|
4063
4456
|
Dialog,
|
|
4064
4457
|
RECENT_MAX,
|
|
@@ -4073,6 +4466,9 @@ export {
|
|
|
4073
4466
|
createSymbolDialog,
|
|
4074
4467
|
defaultMenus,
|
|
4075
4468
|
defaultToolbarGroups,
|
|
4469
|
+
equationGallery,
|
|
4470
|
+
equationPanel,
|
|
4471
|
+
equationPreviewSvg,
|
|
4076
4472
|
installScrollbars,
|
|
4077
4473
|
marginPresetPicker,
|
|
4078
4474
|
mountMenubar,
|