mycrossword
Version:
React crossword component
1,753 lines • 55.6 kB
JavaScript
import { jsx as u, jsxs as $, Fragment as te } from "react/jsx-runtime";
import * as x from "react";
import he, { useLayoutEffect as De, useEffect as le, useRef as Se, useCallback as ne, useState as ye } from "react";
function He(e) {
return e && e.__esModule && Object.prototype.hasOwnProperty.call(e, "default") ? e.default : e;
}
var ke = { exports: {} };
/*!
Copyright (c) 2018 Jed Watson.
Licensed under the MIT License (MIT), see
http://jedwatson.github.io/classnames
*/
(function(e) {
(function() {
var t = {}.hasOwnProperty;
function o() {
for (var r = "", i = 0; i < arguments.length; i++) {
var c = arguments[i];
c && (r = n(r, s(c)));
}
return r;
}
function s(r) {
if (typeof r == "string" || typeof r == "number")
return r;
if (typeof r != "object")
return "";
if (Array.isArray(r))
return o.apply(null, r);
if (r.toString !== Object.prototype.toString && !r.toString.toString().includes("[native code]"))
return r.toString();
var i = "";
for (var c in r)
t.call(r, c) && r[c] && (i = n(i, c));
return i;
}
function n(r, i) {
return i ? r ? r + " " + i : r + i : r;
}
e.exports ? (o.default = o, e.exports = o) : window.classNames = o;
})();
})(ke);
var Te = ke.exports;
const ue = /* @__PURE__ */ He(Te);
function O(e) {
return (...t) => ue(t);
}
const Be = ["b", "strong", "i", "em", "sub", "sup"], Me = /[A-Z]/;
function Ae(e, t) {
return e.length !== 1 ? !1 : e.match(t);
}
function We(e) {
return e.top >= 0 && e.left >= 0 && e.right <= (window.innerWidth || document.documentElement.clientWidth) && e.bottom <= (window.innerHeight || document.documentElement.clientHeight);
}
function Pe(e, t) {
return e.top >= t.top && e.left >= t.left && e.right <= t.right && e.bottom <= t.bottom;
}
function Ie(e, t, o = "") {
return {
value: new Array(e).fill(o).map(() => new Array(t).fill(o))
};
}
function $e(e, t, o) {
const s = Ie(e, t);
return o.forEach(({ guess: n, pos: r }) => {
s.value[r.col][r.row] = n !== void 0 ? n : "";
}), s;
}
function Oe(e, t, o, s) {
if (e.value.reduce((r, i) => r + i.length, 0) !== t * o)
return !1;
for (let r = 0; r < t; r += 1)
for (let i = 0; i < o; i += 1) {
const c = e.value[r][i];
if (c !== "" && !Ae(c, s))
return !1;
}
return !0;
}
const me = (e) => {
let t;
const o = /* @__PURE__ */ new Set(), s = (f, h) => {
const d = typeof f == "function" ? f(t) : f;
if (!Object.is(d, t)) {
const v = t;
t = h ?? (typeof d != "object" || d === null) ? d : Object.assign({}, t, d), o.forEach((C) => C(t, v));
}
}, n = () => t, c = { setState: s, getState: n, getInitialState: () => p, subscribe: (f) => (o.add(f), () => o.delete(f)) }, p = t = e(s, n, c);
return c;
}, je = (e) => e ? me(e) : me, Ue = (e) => e;
function Ve(e, t = Ue) {
const o = he.useSyncExternalStore(
e.subscribe,
() => t(e.getState()),
() => t(e.getInitialState())
);
return he.useDebugValue(o), o;
}
const ge = (e) => {
const t = je(e), o = (s) => Ve(t, s);
return Object.assign(o, t), o;
}, Re = (e) => e ? ge(e) : ge, Y = Re((e) => ({
clues: [],
setClues: (t) => {
e(() => ({ clues: t }));
},
select: (t) => {
e((o) => (typeof window < "u" && window.history.replaceState(null, "", `#${t}`), {
clues: o.clues.map((s) => ({
...s,
selected: s.id === t
}))
}));
},
answerAll: (t) => {
e((o) => ({
clues: o.clues.map((s) => ({
...s,
answered: t
}))
}));
},
answerSome: (t, o) => {
e((s) => ({
clues: s.clues.map((n) => t.includes(n.id) ? {
...n,
answered: o
} : n)
}));
}
})), V = Re((e, t) => ({
cells: [],
complete: !1,
checkComplete: () => {
if (t().complete)
return null;
const o = t().cells.every((s) => s.val === s.guess);
return e({ complete: o }), o;
},
resetComplete: () => {
e({ complete: !1 });
},
setCells: (o) => {
e(() => ({ cells: o }));
},
select: (o) => {
e((s) => ({
cells: s.cells.map((n) => ({
...n,
selected: n.pos.col === o.col && n.pos.row === o.row
}))
}));
},
answerAll: (o) => {
e((s) => ({
cells: s.cells.map((n) => ({
...n,
guess: o ? n.val : void 0
}))
}));
}
}));
function Fe({ message: e, style: t }) {
const o = O();
return /* @__PURE__ */ u("div", { className: o("GridError"), style: t, children: /* @__PURE__ */ $("div", { role: "alert", children: [
/* @__PURE__ */ u("h1", { className: o("GridError__title"), children: "Something went wrong" }),
/* @__PURE__ */ u("p", { className: o("GridError__subTitle"), children: e })
] }) });
}
function Ke({ className: e }) {
return /* @__PURE__ */ u(
"svg",
{
xmlns: "http://www.w3.org/2000/svg",
width: "16",
height: "16",
className: e,
viewBox: "0 0 16 16",
children: /* @__PURE__ */ u(
"path",
{
fillRule: "evenodd",
d: "M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z"
}
)
}
);
}
function qe({ className: e }) {
return /* @__PURE__ */ u(
"svg",
{
xmlns: "http://www.w3.org/2000/svg",
width: "16",
height: "16",
className: e,
viewBox: "0 0 16 16",
children: /* @__PURE__ */ u(
"path",
{
fillRule: "evenodd",
d: "M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z"
}
)
}
);
}
function se(e, t = {}) {
const { allowedTags: o = [] } = t;
if (!/<|>/.test(e))
return e;
let s = "", n = e;
const r = o.length > 0 ? `\\b(${o.join("|")})\\b` : "(?!)", i = new RegExp(`</?(?!${r})\\w+[^>]*>`, "gi"), c = /<(\w+)[^>]*>/gi;
for (; s !== n; )
s = n, n = n.replace(i, ""), n = n.replace(c, "<$1>");
return n;
}
const Je = {
"&": "&",
"<": "<",
">": ">",
""": '"',
"'": "'",
"'": "'",
"/": "/",
"`": "`",
"=": "=",
" ": " ",
"©": "©",
"®": "®",
"™": "™",
"€": "€",
"£": "£",
"¥": "¥",
"¢": "¢",
"'": "'",
"§": "§",
"¶": "¶",
"±": "±",
"×": "×",
"÷": "÷",
"«": "«",
"»": "»",
"“": "“",
"”": "”",
"‘": "‘",
"’": "’",
"…": "…",
"·": "·",
"•": "•",
"–": "–",
"—": "—",
"α": "α",
"β": "β",
"γ": "γ",
"δ": "δ",
"π": "π",
"σ": "σ",
"ω": "ω",
"μ": "μ",
"τ": "τ",
"φ": "φ",
"χ": "χ",
"ψ": "ψ",
"θ": "θ"
};
function re(e) {
return e.replace(/&([^;]+);/g, (t, o) => {
const s = Je[t.toLowerCase()];
if (s !== void 0)
return s;
if (o.startsWith("#")) {
let n;
if (o.startsWith("#x") || o.startsWith("#X") ? n = parseInt(o.slice(2), 16) : n = parseInt(o.slice(1), 10), !isNaN(n))
try {
return String.fromCodePoint(n);
} catch {
return t;
}
}
return t;
});
}
function Ye({
allowedTags: e,
num: t,
onMoveNext: o,
onMovePrev: s,
show: n,
text: r
}) {
const i = O();
return /* @__PURE__ */ u("div", { className: i("StickyClue", `StickyClue--${n}`), children: r !== void 0 && t !== void 0 ? /* @__PURE__ */ $(te, { children: [
/* @__PURE__ */ u(
"button",
{
"aria-label": "Previous clue",
className: i("StickyClue__button"),
onClick: s,
type: "button",
children: /* @__PURE__ */ u(Ke, {})
}
),
/* @__PURE__ */ u("div", { className: i("StickyClue__inner"), children: /* @__PURE__ */ $("span", { className: i("StickyClue__text"), children: [
/* @__PURE__ */ u("span", { className: i("StickyClue__num"), children: t }),
/* @__PURE__ */ u(
"span",
{
dangerouslySetInnerHTML: {
__html: se(re(r), { allowedTags: e })
}
}
)
] }) }),
/* @__PURE__ */ u(
"button",
{
"aria-label": "Next clue",
className: i("StickyClue__button"),
onClick: o,
type: "button",
children: /* @__PURE__ */ u(qe, {})
}
)
] }) : null });
}
const Ge = (e, t) => {
const o = 1 + (e + 1) * t.col, s = 1 + (e + 1) * t.row, n = o + 1, r = s + Math.ceil(e * 0.29), i = o + Math.ceil(e * 0.5), c = s + Math.ceil(e * 0.675);
return { xRect: o, yRect: s, xNum: n, yNum: r, xText: i, yText: c };
};
function Xe({
cellSize: e,
clueIds: t,
guess: o,
inputRef: s,
isHighlighted: n,
isSelected: r,
num: i,
onCellFocus: c,
pos: p,
selectedClueIndex: f
}) {
if (t.length !== 1 && t.length !== 2)
throw new Error(
"Crossword data error: cell does not have 1 or 2 directions"
);
const h = O(), d = Y((L) => L.select), v = V((L) => L.select), { xRect: C, yRect: l, xNum: a, yNum: G, xText: H, yText: _ } = Ge(
e,
p
), R = (L, k) => {
c !== void 0 && c({
pos: L,
clueId: k
});
}, M = () => {
var B;
let L = f === -1 ? 0 : f;
t.length === 2 && r && (L = f === 0 ? 1 : 0);
const k = t[L];
d(k), r || v(p), (!r || t.length === 2) && R(p, k), (B = s == null ? void 0 : s.current) == null || B.focus({ preventScroll: !0 });
};
return /* @__PURE__ */ $(
"g",
{
className: h(
"GridCell",
n ? "GridCell--highlighted" : null,
r ? "GridCell--selected" : null
),
onClick: M,
children: [
/* @__PURE__ */ u(
"rect",
{
className: h("GridCell__rect"),
x: C,
y: l,
width: e,
height: e
}
),
i ? /* @__PURE__ */ u(
"text",
{
className: h("GridCell__num"),
x: a,
y: G,
style: { fontSize: Math.ceil(e * 0.32) },
children: i
}
) : null,
/* @__PURE__ */ u(
"text",
{
className: h("GridCell__text"),
textAnchor: "middle",
x: H,
y: _,
style: { fontSize: Math.ceil(e * 0.55) },
children: o
}
)
]
}
);
}
const Ze = x.memo(Xe);
const Qe = x.forwardRef(
({ onChange: e, onKeyDown: t, visible: o }, s) => {
const n = O();
return /* @__PURE__ */ u(
"input",
{
autoComplete: "off",
autoCorrect: "off",
autoFocus: !1,
className: n(
"GridInput",
o ? null : "GridInput--inclusivelyHidden"
),
maxLength: 1,
onChange: e,
onKeyDown: t,
ref: s,
spellCheck: "false",
tabIndex: -1,
type: "text",
value: ""
}
);
}
), ze = Qe;
function et(e, t) {
const [o, s] = x.useState(e);
return x.useEffect(() => {
const n = setTimeout(() => {
s(e);
}, t);
return () => {
clearTimeout(n);
};
}, [e, t]), o;
}
function we(e, t) {
return e * (t + 1) + 1;
}
function tt({
char: e,
col: t,
row: o,
direction: s,
cellSize: n
}) {
const r = we(o, n), i = we(t, n), c = s === "across";
if (e === ",") {
const p = c ? 1 : n, f = c ? n : 1, h = c ? i - 2 : i, d = c ? r : r - 2;
return /* @__PURE__ */ u("rect", { width: p, height: f, x: h, y: d });
}
if (e === "-") {
const p = c ? n * 0.25 : 1, f = c ? 1 : n * 0.25, h = c ? i - 0.5 - p * 0.5 : i + n * 0.5 + p * 0.5, d = c ? r + n * 0.5 + f * 0.5 : r - 0.5 - f * 0.5;
return /* @__PURE__ */ u("rect", { width: p, height: f, x: h, y: d });
}
return /* @__PURE__ */ u(te, {});
}
function ve(e, t, o, s) {
if (t <= 0 || t >= o.length)
return null;
const n = o.position.x + (o.direction === "across" ? t : 0), r = o.position.y + (o.direction === "across" ? 0 : t);
return /* @__PURE__ */ u(
tt,
{
cellSize: s,
char: e,
direction: o.direction,
col: n,
row: r
},
[n, r, o.direction].join(",")
);
}
function ot({ clues: e, cellSize: t }) {
return /* @__PURE__ */ u("svg", { className: "GridSeparators", children: e.filter((o) => Object.keys(o.separatorLocations).length > 0).map((o) => {
const s = [], n = o.separatorLocations[","], r = o.separatorLocations["-"];
return n !== void 0 && s.push(
n.map((i) => ve(",", i, o, t))
), r !== void 0 && s.push(
r.map((i) => ve("-", i, o, t))
), s;
}) });
}
const nt = x.memo(ot);
function ce(e, t) {
return t.map((o) => o.pos.col === e.pos.col && o.pos.row === e.pos.row ? e : o);
}
function st({
cols: e,
rows: t,
entries: o,
guessGrid: s,
allowMissingSolutions: n = !1
}) {
const r = [], i = o.map((c) => c.id);
return o.forEach((c) => {
var p, f;
for (let h = 0; h < c.length; h += 1) {
const d = c.direction === "across", v = d ? c.position.x + h : c.position.x, C = d ? c.position.y : c.position.y + h;
if (v < 0 || v >= e || C < 0 || C >= t)
throw new Error("Crossword data error: out of bounds");
if (!n && c.solution !== void 0 && c.length !== c.solution.length)
throw new Error("Crossword data error: solution length mismatch");
if (!c.group.includes(c.id))
throw new Error("Crossword data error: clue id missing from group");
if (!c.group.every((a) => i.includes(a)))
throw new Error("Crossword data error: group clue id not found");
const l = r.find(
({ pos: a }) => a.col === v && a.row === C
);
if (l === void 0) {
const a = s == null ? void 0 : s.value[v][C], G = {
clueIds: [c.id],
guess: a !== "" ? a : void 0,
num: h === 0 ? c.number : void 0,
pos: { col: v, row: C },
selected: !1,
val: (p = c.solution) == null ? void 0 : p[h]
};
r.push(G);
} else {
if (d && l.clueIds.some((G) => G.endsWith("across")))
throw new Error("Crossword data error: overlapping across solutions");
if (!d && l.clueIds.some((G) => G.endsWith("down")))
throw new Error("Crossword data error: overlapping down solutions");
const a = (f = c.solution) == null ? void 0 : f[h];
if (!n && l.val !== a)
throw new Error("Crossword data error: solution character clash");
l.num = h === 0 ? c.number : l.num, l.clueIds = [...l.clueIds, c.id], n && a !== void 0 && (l.val = a);
}
}
}), r;
}
function Ce(e, t) {
return e.find(
(o) => o.pos.col === t.col && o.pos.row === t.row
);
}
function rt(e, t, o) {
const s = Ce(e, {
col: t.pos.col - (o ? 0 : 1),
row: t.pos.row - (o ? 1 : 0)
}), n = Ce(e, {
col: t.pos.col + (o ? 0 : 1),
row: t.pos.row + (o ? 1 : 0)
});
return (s == null ? void 0 : s.guess) === void 0 && (n == null ? void 0 : n.guess) === void 0;
}
function ie(e, t) {
const o = [];
return e.forEach((s) => {
const n = t.filter((r) => r.clueIds.includes(s)).sort(
(r, i) => r.pos.col - i.pos.col || r.pos.row - i.pos.row
);
o.push(...n);
}), o;
}
function it(e, t) {
const o = { ",": [], "-": [] };
let s = 0;
return e.forEach((n) => {
var i, c;
const r = t.find((p) => p.id === n);
if (r !== void 0) {
const p = (i = r.separatorLocations[","]) == null ? void 0 : i.map(
(h) => h + s
);
o[","] = [...o[","], ...p ?? []];
const f = (c = r.separatorLocations["-"]) == null ? void 0 : c.map(
(h) => h + s
);
o["-"] = [...o["-"], ...f ?? []];
}
s += r !== void 0 ? r.length : 0;
}), o;
}
function z(e, t) {
const o = ie(e.group, t), s = o.filter((n) => n.guess !== void 0);
return o.length > 0 && o.length === s.length;
}
function ct(e, t) {
const o = [];
return ie(e.group, t).forEach((n) => {
o.push(...n.clueIds);
}), Array.from(new Set(o));
}
function lt(e, t, o) {
return e.map((s) => ({
...s,
answered: z(s, t),
selected: s.id === o
})).sort(
(s, n) => s.direction.localeCompare(n.direction) || s.number - n.number
);
}
const ut = [
"ArrowUp",
"ArrowDown",
"ArrowLeft",
"ArrowRight"
];
function at(e) {
return ut.includes(e);
}
function dt(e, t) {
return t === void 0 ? !1 : e.col === t.col && e.row === t.row;
}
function ft({
cellMatcher: e,
cells: t,
cellSize: o,
clues: s,
cols: n,
guessGrid: r,
inputRef: i,
onCellChange: c,
onCellFocus: p,
onComplete: f,
rawClues: h,
rows: d,
setGuessGrid: v
}) {
const C = O(), l = t.find((m) => m.selected), a = s.find((m) => m.selected), G = n * o + n + 1, H = d * o + d + 1, [_, R] = x.useState(r), M = et(_, 1e3), L = x.useRef(null), [k, B] = x.useState(1), j = V((m) => m.select), W = V((m) => m.setCells), F = Y((m) => m.select), Z = Y((m) => m.answerSome), oe = V((m) => m.checkComplete), w = x.useCallback(() => {
if (L.current !== null) {
const m = L.current.clientWidth, b = L.current.clientHeight, y = m / G, E = b / H, I = Math.min(y, E);
B(I);
}
}, [L.current]);
x.useEffect(() => (window.addEventListener("resize", w), w(), function() {
window.removeEventListener("resize", w);
}), [w]), x.useEffect(() => {
v(M);
}, [M]);
const g = (m, b) => {
c !== void 0 && m.guess !== b && c({
pos: m.pos,
guess: b,
previousGuess: m.guess
});
}, S = (m, b) => {
p !== void 0 && p({
pos: m,
clueId: b
});
}, A = (m) => {
R($e(n, d, m));
}, U = () => {
if (a === void 0 || l === void 0)
return;
if (a.direction === "across" && l.pos.col === a.position.x || a.direction === "down" && l.pos.row === a.position.y) {
const b = a.group.indexOf(a.id);
if (b > 0) {
const y = a.group[b - 1], E = s.find((I) => I.id === y);
if (E !== void 0) {
const I = {
col: E.position.x + (E.direction === "across" ? E.length - 1 : 0),
row: E.position.y + (E.direction === "down" ? E.length - 1 : 0)
};
F(y), j(I), S(I, y);
}
}
} else {
const b = a.direction === "across" ? { col: l.pos.col - 1, row: l.pos.row } : { col: l.pos.col, row: l.pos.row - 1 };
j(b), S(b, a.id);
}
}, q = () => {
if (a === void 0 || l === void 0)
return;
if (a.direction === "across" && l.pos.col === a.position.x + a.length - 1 || a.direction === "down" && l.pos.row === a.position.y + a.length - 1) {
const b = a.group.indexOf(a.id);
if (a.group.length - 1 > b) {
const y = a.group[b + 1], E = s.find((I) => I.id === y);
if (E !== void 0) {
const I = {
col: E.position.x,
row: E.position.y
};
F(y), j(I), S(I, y);
}
}
} else {
const b = a.direction === "across" ? { col: l.pos.col + 1, row: l.pos.row } : { col: l.pos.col, row: l.pos.row + 1 };
j(b), S(b, a.id);
}
}, X = (m, b) => {
const y = (T, J, Q) => {
const ae = T + J;
return ae === -1 ? Q - 1 : ae === Q ? 0 : ae;
};
let { col: E, row: I } = l == null ? void 0 : l.pos;
for (; ; ) {
m === 1 || m === -1 ? E = y(E, m, n) : (b === 1 || b === -1) && (I = y(I, b, d));
const T = t.find(
// eslint-disable-next-line @typescript-eslint/no-loop-func
(J) => J.pos.col === E && J.pos.row === I
);
if (T !== void 0)
return T;
}
}, N = (m) => {
if (a === void 0 || l === void 0)
return;
const b = t.find(
(E) => E.pos.col === l.pos.col && E.pos.row === l.pos.row
);
if (!b)
return;
if (b.clueIds.length === 2) {
const E = m === "ArrowUp" || m === "ArrowDown", I = m === "ArrowLeft" || m === "ArrowRight";
if (E && a.direction === "across" || I && a.direction === "down") {
const T = b.clueIds.find(
(J) => J !== a.id
);
if (T !== void 0) {
F(T), S(l.pos, T);
return;
}
}
}
let y;
switch (m) {
case "ArrowUp":
y = X(0, -1);
break;
case "ArrowDown":
y = X(0, 1);
break;
case "ArrowLeft":
y = X(-1, 0);
break;
case "ArrowRight":
y = X(1, 0);
break;
default:
y = void 0;
}
if (y !== void 0)
if (j(y.pos), y.clueIds.includes(a.id))
S(y.pos, a.id);
else {
const E = y.clueIds.find(
(I) => I.endsWith(a.direction)
) ?? y.clueIds[0];
F(E), S(y.pos, E);
}
}, D = (m) => {
if (!(a === void 0 || l === void 0) && [
"ArrowUp",
"ArrowDown",
"ArrowLeft",
"ArrowRight",
"Backspace",
"Delete",
"Tab"
].includes(m.key)) {
if (m.preventDefault(), m.stopPropagation(), at(m.key))
N(m.key);
else if (["Backspace", "Delete"].includes(m.key)) {
g(l, void 0);
const b = {
...l,
guess: void 0
}, y = ce(b, t);
W(y), l.clueIds.forEach((E) => {
const I = s.find((T) => T.id === E);
if (I) {
const T = z(I, y);
Z(I.group, T);
}
}), m.key === "Backspace" && U(), A(y);
} else if (m.key === "Tab") {
const b = s.findIndex((T) => T.selected);
let y = 0;
m.shiftKey ? y = b > 0 ? b - 1 : s.length - 1 : y = b < s.length - 1 ? b + 1 : 0;
const E = s[y], I = {
col: E.position.x,
row: E.position.y
};
F(E.id), j(I), S(I, E.id);
}
}
}, K = (m) => {
if (a === void 0 || l === void 0)
return;
const b = m.target.value.toUpperCase();
if (Ae(b, e)) {
g(l, b);
const y = {
...l,
guess: b
}, E = ce(y, t);
W(E), l.clueIds.forEach((I) => {
const T = s.find((Q) => Q.id === I);
z(T, E) && Z(T.group, !0);
}), q(), f !== void 0 && oe() === !0 && f(), A(E);
} else
m.preventDefault();
}, P = l !== void 0 ? Ge(o, l.pos) : void 0;
return /* @__PURE__ */ $(
"div",
{
className: C("Grid"),
"data-testid": "grid",
style: {
minWidth: G,
minHeight: H,
width: G,
height: H,
aspectRatio: `${n} / ${d}`
},
children: [
/* @__PURE__ */ $(
"svg",
{
preserveAspectRatio: "xMinYMin",
ref: L,
viewBox: `0 0 ${G} ${H}`,
children: [
/* @__PURE__ */ u(
"rect",
{
className: C("Grid__background"),
onMouseDown: (m) => {
m.preventDefault();
const b = document.querySelector(".GridInput");
b !== null && b.blur();
},
width: G,
height: H,
x: "0",
y: "0"
}
),
t.map(({ clueIds: m, guess: b, num: y, pos: E }) => {
const I = dt(E, l == null ? void 0 : l.pos), T = m.some(
(Q) => a == null ? void 0 : a.group.includes(Q)
), J = a !== void 0 ? m.indexOf(a.id) : -1;
return /* @__PURE__ */ u(
Ze,
{
cellSize: o,
clueIds: m,
guess: b,
inputRef: i,
isHighlighted: T,
isSelected: I,
num: y,
onCellFocus: p,
pos: E,
selectedClueIndex: J
},
`${E.col},${E.row}`
);
}),
/* @__PURE__ */ u(nt, { cellSize: o, clues: h })
]
}
),
/* @__PURE__ */ u(
"div",
{
className: C("Grid__inputContainer"),
style: {
width: l !== void 0 ? o * k : void 0,
height: l !== void 0 ? o * k : void 0,
top: (P == null ? void 0 : P.yRect) !== void 0 ? P.yRect * k : void 0,
left: (P == null ? void 0 : P.xRect) !== void 0 ? P.xRect * k : void 0
},
children: /* @__PURE__ */ u(
ze,
{
onChange: K,
onKeyDown: D,
ref: i,
visible: l !== void 0
}
)
}
)
]
}
);
}
function pt({
allowedHtmlTags: e,
answered: t,
col: o,
containerRef: s,
id: n,
inputRef: r,
isHighlighted: i,
num: c,
onCellFocus: p,
row: f,
scrollTo: h,
text: d
}) {
const v = O(), C = x.useRef(null), l = V((_) => _.select), a = Y((_) => _.select), G = (_, R) => {
p !== void 0 && p({
pos: _,
clueId: R
});
}, H = x.useCallback(() => {
var R;
const _ = { col: o, row: f };
a(n), l(_), G(_, n), (R = r == null ? void 0 : r.current) == null || R.focus({ preventScroll: !0 });
}, [r]);
return x.useEffect(() => {
if (h && C.current !== null && s !== void 0 && s.current !== null) {
const _ = C.current.getBoundingClientRect(), R = s.current.getBoundingClientRect();
Pe(_, R) || C.current.scrollIntoView({
behavior: "auto",
block: "nearest",
inline: "nearest"
});
}
}, [h]), /* @__PURE__ */ $(
"div",
{
className: v(
"Clue",
t ? "Clue--answered" : null,
i ? "Clue--highlighted" : null
),
onClick: H,
onKeyDown: (_) => {
_.key === "Enter" && H();
},
role: "button",
ref: C,
tabIndex: 0,
children: [
/* @__PURE__ */ u("span", { className: v("Clue__num"), children: c }),
/* @__PURE__ */ u(
"span",
{
className: v("Clue__text"),
dangerouslySetInnerHTML: {
__html: se(re(d), {
allowedTags: e
})
},
"data-text": se(re(d))
}
)
]
}
);
}
const xe = x.memo(pt);
const ht = [
{ name: "xs", max: 576 },
{ name: "sm", max: 768 },
{ name: "md", max: 992 },
{ name: "lg", max: 1200 },
{ name: "xl", max: 1400 },
{ name: "xxl", max: 99999 }
];
function mt() {
const [e, t] = x.useState(), [o, s] = x.useState(), n = () => {
s(window.innerWidth);
};
return x.useEffect(() => {
if (window.addEventListener("resize", n), n(), o !== void 0) {
const r = ht.filter((i) => o < i.max);
r.length > 0 ? t(r[0].name) : t(void 0);
}
return function() {
window.removeEventListener("resize", n);
};
}, [o]), e;
}
function gt({
allowedHtmlTags: e,
entries: t,
gridHeight: o,
inputRef: s,
onCellFocus: n,
selectedClueId: r
}) {
const i = mt(), c = x.useRef(null), p = x.useRef(null), f = x.useRef(null), h = t.filter((l) => l.direction === "across").sort((l, a) => l.number - a.number), d = t.filter((l) => l.direction === "down").sort((l, a) => l.number - a.number), v = (l) => {
if (r === void 0)
return !1;
const a = t.find((G) => G.id === r);
return (a == null ? void 0 : a.group.includes(l.id)) ?? !1;
}, C = (l) => i !== void 0 && ["md", "lg", "xl", "xxl"].includes(i) && r !== void 0 && l.group.includes(r) && l.id === l.group[0];
return /* @__PURE__ */ $(
"div",
{
className: "Clues",
ref: c,
style: { maxHeight: o },
children: [
/* @__PURE__ */ $("div", { className: "Clues__list Clues__list--across", ref: p, children: [
/* @__PURE__ */ u("h3", { className: "Clues__listHeader", children: "Across" }),
/* @__PURE__ */ u("div", { className: "Clues__listBody", children: h.map((l) => /* @__PURE__ */ u(
xe,
{
allowedHtmlTags: e,
answered: l.answered,
col: l.position.x,
containerRef: i === "md" ? c : p,
id: l.id,
inputRef: s,
isHighlighted: v(l),
num: l.humanNumber,
onCellFocus: n,
row: l.position.y,
scrollTo: C(l),
text: l.clue
},
l.id
)) })
] }),
/* @__PURE__ */ $("div", { className: "Clues__list Clues__list--down", ref: f, children: [
/* @__PURE__ */ u("h3", { className: "Clues__listHeader", children: "Down" }),
/* @__PURE__ */ u("div", { className: "Clues__listBody", children: d.map((l) => /* @__PURE__ */ u(
xe,
{
allowedHtmlTags: e,
answered: l.answered,
col: l.position.x,
containerRef: i === "md" ? c : f,
id: l.id,
inputRef: s,
isHighlighted: v(l),
num: l.humanNumber,
onCellFocus: n,
row: l.position.y,
scrollTo: C(l),
text: l.clue
},
l.id
)) })
] })
]
}
);
}
function be(e) {
return e.normalize("NFD").replace(/[\u0300-\u036f]/g, "");
}
function wt({
allowedHtmlTags: e,
className: t,
clue: o,
onClick: s,
splitWords: n = !1
}) {
if (!n)
return /* @__PURE__ */ u(
"span",
{
dangerouslySetInnerHTML: {
__html: se(re(o), {
allowedTags: e
})
}
}
);
const i = se(re(o)).split(/\b([\p{L}\p{M}]+)\b/u);
return /* @__PURE__ */ u(te, { children: i.map((c, p) => p % 2 === 1 ? /* @__PURE__ */ u(
"span",
{
className: t,
onClick: () => s(be(c)),
onKeyDown: (f) => {
f.key === "Enter" && s(be(c));
},
role: "button",
tabIndex: 0,
children: c
},
`${c}-${p}`
) : /* @__PURE__ */ u("span", { children: c }, `${c}-${p}`)) });
}
function vt(e, t) {
if (e[","].includes(t))
return "SolutionDisplay__letter--hasSpace";
if (e["-"].includes(t))
return "SolutionDisplay__letter--hasHyphen";
}
function Ct(e, t) {
let o = e;
return t.split("").forEach((s) => {
o = o.replace(s, "");
}), o;
}
function xt({
cells: e,
letters: t,
separators: o,
shuffling: s
}) {
const n = O(), r = e.map((f) => f.guess).join(""), i = t !== void 0 ? Ct(t == null ? void 0 : t.toUpperCase(), r) : void 0;
let c = t == null ? void 0 : t.toUpperCase(), p = 0;
return /* @__PURE__ */ u("div", { className: "SolutionDisplay", children: e.map((f, h) => {
const d = f.guess !== void 0 && (c == null ? void 0 : c.includes(f.guess));
return d && (c = c == null ? void 0 : c.replace(f.guess, "")), /* @__PURE__ */ u(
"span",
{
className: n(
"SolutionDisplay__letter",
f.guess !== void 0 ? "SolutionDisplay__letter--populated" : null,
s && f.guess !== void 0 && t !== void 0 && !d ? "SolutionDisplay__letter--missing" : null,
vt(o, h + 1)
),
children: f.guess ?? (s && i !== void 0 && i[p] !== void 0 ? i[p++] : null)
},
`${f.val}-${h}`
);
}) });
}
const _e = (e) => Math.round(e * 100) / 100, bt = (e, t, o) => {
const s = t * Math.PI / 180 * o;
return {
left: `${e + _e(e * Math.sin(s))}%`,
top: `${e + _e(e * Math.cos(s))}%`
};
}, _t = (e) => ({
left: `${e - 1}%`,
top: `${e - 2}%`
}), Et = (e, t = 5) => e.length === 0 ? 0 : e.length < t ? 360 / e.length : 360 / (e.length - 1);
function Nt({
letters: e,
populatedLetters: t
}) {
const o = O(), s = Et(e), n = 40;
let r = t.toUpperCase();
return /* @__PURE__ */ u("div", { className: o("WordWheel"), children: e.toUpperCase().split("").map((i, c) => {
const p = r.includes(i);
return p && (r = r.replace(i, "")), /* @__PURE__ */ u(
"span",
{
className: o(
"WordWheel__letter",
c === 0 && (e.length === 1 || e.length > 4) ? "WordWheel__letter--central" : null,
p ? "WordWheel__letter--populated" : null
),
style: c === 0 && (e.length === 1 || e.length > 4) ? _t(n) : bt(n, s, c),
children: i
},
`${i}-${c}`
);
}) });
}
const St = x.forwardRef(
({
ariaLabel: e,
children: t,
className: o,
disabled: s,
id: n,
onClick: r,
onKeyDown: i,
variant: c = "filled"
}, p) => {
const f = O();
return /* @__PURE__ */ u(
"button",
{
"aria-label": e,
className: ue(f("Button", `Button--${c}`), o),
disabled: s,
id: n,
onClick: r,
onKeyDown: i,
ref: p,
type: "button",
children: t
}
);
}
), ee = St;
function yt({ className: e }) {
return /* @__PURE__ */ u(
"svg",
{
className: e,
xmlns: "http://www.w3.org/2000/svg",
viewBox: "0 0 28 28",
children: /* @__PURE__ */ u("path", { d: "M21 9.8l-.8-.8-5.2 4.8-5.2-4.8-.8.8 4.8 5.2-4.8 5.2.8.8 5.2-4.8 5.2 4.8.8-.8-4.8-5.2 4.8-5.2" })
}
);
}
function kt({
allowedHtmlTags: e,
clue: t,
groupCells: o,
groupSeparators: s,
onClose: n,
style: r
}) {
const i = O(), c = x.useRef(null), p = x.useRef(null), [f, h] = x.useState(""), [d, v] = x.useState(!1), C = f !== "" || d, l = o.length;
x.useEffect(() => {
var _;
d || (_ = c.current) == null || _.focus({ preventScroll: !0 });
}, [d]);
const a = () => {
h(""), v(!1);
}, G = () => {
var _;
f !== "" && (h(
(R) => R.split("").sort(() => 0.5 - Math.random()).join("")
), v(!0), (_ = p.current) == null || _.focus({ preventScroll: !0 }));
}, H = (_) => {
var R;
h((M) => (M + _).substring(0, l)), (R = c.current) == null || R.focus({ preventScroll: !0 });
};
return x.useEffect(() => {
a();
}, [t.id]), /* @__PURE__ */ $(
"div",
{
className: i(
"AnagramHelper",
d ? "AnagramHelper--shuffling" : null
),
style: r,
children: [
/* @__PURE__ */ u(
ee,
{
ariaLabel: "Close",
className: i("AnagramHelper__closeButton"),
onClick: n,
variant: "outlined",
children: /* @__PURE__ */ u(yt, { className: i("AnagramHelper__closeButtonIcon") })
}
),
/* @__PURE__ */ u("div", { className: i("AnagramHelper__top"), children: d ? /* @__PURE__ */ u(
Nt,
{
letters: f,
populatedLetters: o.map((_) => _.guess).join("")
}
) : /* @__PURE__ */ $(te, { children: [
/* @__PURE__ */ u(
"input",
{
autoComplete: "off",
className: i("AnagramHelper__input"),
maxLength: l,
onChange: (_) => h(_.target.value),
onKeyDown: (_) => {
["Enter", "NumpadEnter"].includes(_.code) ? (_.preventDefault(), G()) : _.code === "Escape" && (f === "" ? n() : a());
},
placeholder: "Enter letters...",
ref: c,
spellCheck: "false",
value: f
}
),
/* @__PURE__ */ $(
"span",
{
className: i(
"AnagramHelper__counter",
f === "" ? "AnagramHelper__counter--hidden" : null
),
children: [
f.length,
"/",
l
]
}
)
] }) }),
/* @__PURE__ */ $("div", { className: i("AnagramHelper__bottom"), children: [
/* @__PURE__ */ $("div", { className: i("AnagramHelper__buttons"), children: [
/* @__PURE__ */ u(ee, { disabled: !C, onClick: a, variant: "outlined", children: "Reset" }),
/* @__PURE__ */ u(
ee,
{
disabled: !C,
onClick: G,
onKeyDown: (_) => {
_.code === "Escape" && a();
},
ref: p,
children: "Shuffle"
}
)
] }),
/* @__PURE__ */ $("p", { className: i("AnagramHelper__clue"), children: [
/* @__PURE__ */ u(
"span",
{
className: i("AnagramHelper__clueNum"),
children: `${t.number} ${t.direction}`
}
),
/* @__PURE__ */ u(
wt,
{
allowedHtmlTags: e,
className: i("AnagramHelper__clickableWord"),
clue: t.clue,
onClick: (_) => H(_),
splitWords: !d
}
)
] }),
/* @__PURE__ */ u(
xt,
{
cells: o,
letters: f,
separators: s,
shuffling: d
}
)
] })
]
}
);
}
const Le = typeof window < "u" ? De : le;
function Ee(e) {
const t = Se(() => {
throw new Error("Cannot call an event handler while rendering.");
});
return Le(() => {
t.current = e;
}, [e]), ne((...o) => {
var s;
return (s = t.current) == null ? void 0 : s.call(t, ...o);
}, [t]);
}
function Ne(e, t, o, s) {
const n = Se(t);
Le(() => {
n.current = t;
}, [t]), le(() => {
const r = (o == null ? void 0 : o.current) ?? window;
if (!(r && r.addEventListener))
return;
const i = (c) => {
n.current(c);
};
return r.addEventListener(e, i, s), () => {
r.removeEventListener(e, i, s);
};
}, [e, o, s]);
}
const de = typeof window > "u";
function At(e, t, o = {}) {
const { initializeWithValue: s = !0 } = o, n = ne(
(v) => o.serializer ? o.serializer(v) : JSON.stringify(v),
[o]
), r = ne(
(v) => {
if (o.deserializer)
return o.deserializer(v);
if (v === "undefined")
return;
const C = t instanceof Function ? t() : t;
let l;
try {
l = JSON.parse(v);
} catch (a) {
return console.error("Error parsing JSON:", a), C;
}
return l;
},
[o, t]
), i = ne(() => {
const v = t instanceof Function ? t() : t;
if (de)
return v;
try {
const C = window.localStorage.getItem(e);
return C ? r(C) : v;
} catch (C) {
return console.warn(`Error reading localStorage key “${e}”:`, C), v;
}
}, [t, e, r]), [c, p] = ye(() => s ? i() : t instanceof Function ? t() : t), f = Ee((v) => {
de && console.warn(
`Tried setting localStorage key “${e}” even though environment is not a client`
);
try {
const C = v instanceof Function ? v(i()) : v;
window.localStorage.setItem(e, n(C)), p(C), window.dispatchEvent(new StorageEvent("local-storage", { key: e }));
} catch (C) {
console.warn(`Error setting localStorage key “${e}”:`, C);
}
}), h = Ee(() => {
de && console.warn(
`Tried removing localStorage key “${e}” even though environment is not a client`
);
const v = t instanceof Function ? t() : t;
window.localStorage.removeItem(e), p(v), window.dispatchEvent(new StorageEvent("local-storage", { key: e }));
});
le(() => {
p(i());
}, [e]);
const d = ne(
(v) => {
v.key && v.key !== e || p(i());
},
[e, i]
);
return Ne("storage", d), Ne("local-storage", d), [c, f, h];
}
const It = 10;
function fe({
buttonText: e,
onCancel: t,
onConfirm: o,
timeout: s = It
}) {
if (s <= 0)
throw new Error("Confirm should have a timeout greater than zero");
const n = O(), [r, i] = x.useState(s);
return x.useEffect(() => {
const c = setTimeout(() => {
r <= 1 ? t() : i((p) => p - 1);
}, 1e3);
return function() {
clearTimeout(c);
};
}, [r]), /* @__PURE__ */ $("div", { className: n("Confirm"), children: [
/* @__PURE__ */ $("div", { className: n("Confirm__buttonContainer"), children: [
/* @__PURE__ */ u(ee, { onClick: t, variant: "outlined", children: "Cancel" }),
/* @__PURE__ */ u(ee, { className: n("Confirm__button"), onClick: o, children: e })
] }),
/* @__PURE__ */ $("span", { className: n("Confirm__timeout"), children: [
"This will automatically cancel in ",
r
] })
] });
}
function $t({ className: e }) {
return /* @__PURE__ */ u(
"svg",
{
xmlns: "http://www.w3.org/2000/svg",
className: e,
width: "8",
height: "8",
viewBox: "0 0 292.362 292.362",
children: /* @__PURE__ */ u("path", { d: "M286.935,69.377c-3.614-3.617-7.898-5.424-12.848-5.424H18.274c-4.952,0-9.233,1.807-12.85,5.424 C1.807,72.998,0,77.279,0,82.228c0,4.948,1.807,9.229,5.424,12.847l127.907,127.907c3.621,3.617,7.902,5.428,12.85,5.428 s9.233-1.811,12.847-5.428L286.935,95.074c3.613-3.617,5.427-7.898,5.427-12.847C292.362,77.279,290.548,72.998,286.935,69.377z" })
}
);
}
function Rt({ className: e, id: t, menu: o, text: s }) {
if (o.length < 2)
throw new Error("DropdownButton should have at least 2 menu items");
const n = O(), r = x.useRef(null), i = x.useRef(null), c = x.useRef(null), [p, f] = x.useState(!1);
x.useEffect(() => {
const d = (v) => {
const C = r.current !== null && !r.current.contains(v.target);
p && C && f(!1);
};
return document.addEventListener("click", d), function() {
document.removeEventListener("click", d);
};
}, [p]);
const h = () => {
if (c.current !== null && i.current !== null && (c.current.style.marginTop = "", !p)) {
const d = c.current.getBoundingClientRect();
if (!We(d)) {
const C = d.height + i.current.clientHeight + 10;
c.current.style.marginTop = `-${C}px`;
}
}
f((d) => !d);
};
return /* @__PURE__ */ $(
"div",
{
className: ue(
n("DropdownButton", p ? "DropdownButton--expanded" : null),
e
),
ref: r,
children: [
/* @__PURE__ */ $(
"button",
{
"aria-controls": t !== void 0 ? `${t}-listbox` : void 0,
"aria-expanded": p ? "true" : "false",
"aria-haspopup": "true",
className: n("DropdownButton__button"),
id: t,
onClick: h,
ref: i,
type: "button",
children: [
/* @__PURE__ */ u("span", { children: s }),
/* @__PURE__ */ u($t, { className: n("DropdownButton__dropdownButtonIcon") })
]
}
),
/* @__PURE__ */ u(
"ul",
{
"aria-label": `${s} menu`,
className: n("DropdownButton__menu"),
id: t !== void 0 ? `${t}-listbox` : void 0,
ref: c,
role: "listbox",
children: o.map((d) => /* @__PURE__ */ u("li", { children: /* @__PURE__ */ u(
"button",
{
className: n("DropdownButton__menuItem"),
disabled: d.disabled,
onClick: () => {
d.onClick(), f(!1);
},
type: "button",
children: d.text
}
) }, d.text))
}
)
]
}
);
}
const pe = x.memo(Rt);
function Gt({
cells: e,
clues: t,
gridCols: o,
gridRows: s,
onAnagramHelperClick: n,
onCellChange: r,
onComplete: i,
setGuessGrid: c,
solutionsAvailable: p
}) {
const f = O(), h = e.find((w) => w.selected), d = t.find((w) => w.selected), [v, C] = x.useState(!1), [l, a] = x.useState(!1), [G, H] = x.useState(!1), _ = V((w) => w.answerAll), R = V((w) => w.setCells), M = V((w) => w.checkComplete), L = Y((w) => w.answerAll), k = Y((w) => w.answerSome), B = (w) => {
c($e(o, s, w));
}, j = (w, g) => {
ct(w, g).forEach((A) => {
const U = t.find((q) => q.id === A);
if (U) {
const q = z(U, g);
k(U.group, q);
}
});
}, W = (w, g) => {
r !== void 0 && w.guess !== g && r({
pos: w.pos,
guess: g,
previousGuess: w.guess
});
}, F = [
{
disabled: h === void 0,
onClick: () => {
if (h !== void 0 && h.guess !== h.val) {
W(h, void 0);
const w = ce(
{ ...h, guess: void 0 },
e
);
R(w), k(h.clueIds, !1), B(w);
}
},
text: "Check letter"
},
{
disabled: d === void 0,
onClick: () => {
if (d !== void 0) {
r !== void 0 && ie(d.group, e).forEach((S) => {
S.guess !== void 0 && S.val !== S.guess && W(S, void 0);
});
const w = e.map((g) => d.group.filter(
(A) => g.clueIds.includes(A)
).length > 0 ? {
...g,
guess: g.guess === g.val ? g.val : void 0
} : g);
R(w), j(d, w), B(w);
}
},
text: "Check word"
},
{ onClick: () => C(!0), text: "Check grid" }
], Z = [
{
disabled: h === void 0,
onClick: () => {
if (h === void 0 || h.guess === h.val)
return;
W(h, h.val);
const w = ce(
{ ...h, guess: h.val },
e
);
R(w), i !== void 0 && M() === !0 && i(), h.clueIds.forEach((g) => {
const S = t.find((U) => U.id === g);
z(S, w) && k(S.group, !0);
}), B(w);
},
text: "Reveal letter"
},
{
disabled: d === void 0,
onClick: () => {
if (d === void 0)
return;
r !== void 0 && ie(d.group, e).forEach((S) => {
S.val !== S.guess && W(S, S.val);
});
const w = e.map((g) => d.group.filter(
(A) => g.clueIds.includes(A)
).length > 0 ? {
...g,
guess: g.val
} : g);
R(w), i !== void 0 && M() === !0 && i(), j(d, w), B(w);
},
text: "Reveal word"
},
{ onClick: () => a(!0), text: "Reveal grid" }
], oe = [
{
disabled: d === void 0,
onClick: () => {
if (d !== void 0) {
const w = e.map((g) => {
const S = d.group.filter(
(A) => g.clueIds.includes(A)
);
if (S.length > 0) {
if (g.clueIds.length === 1)
return W(g, void 0), {
...g,
guess: void 0
};
const U = S[0].includes("across");
if (rt(e, g, U))
return W(g, void 0), {
...g,
guess: void 0
};
}
return g;
});
R(w), k(d.group, !1), B(w);
}
},
text: "Clear word"
},
{ onClick: () => H(!0), text: "Clear grid" }
];
return v ? /* @__PURE__ */ u("div", { className: f("Controls"), children: /* @__PURE__ */ u(
fe,
{
buttonText: "Confirm check grid",
onCancel: () => C(!1),
onConfirm: () => {
r !== void 0 && e.forEach((g) => {
g.guess !== void 0 && g.val !== g.guess && W(g, void 0);
});
const w = e.map((g) => ({
...g,
guess: g.guess === g.val ? g.val : void 0
}));
R(w), t.forEach((g) => {
const S = z(g, w);
k(g.group, S);
}), C(!1), B(w);
}
}
) }) : l ? /* @__PURE__ */ u("div", { className: f("Controls"), children: /* @__PURE__ */ u(
fe,
{
buttonText: "Confirm reveal grid",
onCancel: () => a(!1),
onConfirm: () => {
r !== void 0 && e.forEach((g) => {
g.val !== g.guess && W(g, g.val);
}), _(!0), L(!0), a(!1), i !== void 0 && M() === !0 && i();
const w = e.map((g) => ({
...g,
guess: g.val
}));
B(w);
}
}
) }) : G ? /* @__PURE__ */ u("div", { className: f("Controls"), children: /* @__PURE__ */ u(
fe,
{
buttonText: "Confirm clear grid",
onCancel: () => H(!1),
onConfirm: () => {
r !== void 0 && e.forEach((w) => {
w.guess !== void 0 && W(w, void 0);
}), _(!1), L(!1), H(!1), B([]);
}
}
) }) : /* @__PURE__ */ $("div", { className: f("Controls"), children: [
p ? /* @__PURE__ */ $(te, { children: [
/* @__PURE__ */ u(pe, { id: "check-control", menu: F, text: "Check" }),
/* @__PURE__ */ u(pe, { id: "reveal-control", menu: Z, text: "Reveal" })
] }) : null,
/* @__PURE__ */ u(pe, { id: "clear-control", menu: oe, text: "Clear" }),
/* @__PURE__ */ u("div", { className: f("Controls__buttonContainer"), children: /* @__PURE__ */ u(
ee,
{
ariaLabel: "Anagram helper",
disabled: d === void 0,
id: "anagram-control",
onClick: n,
children: /* @__PURE__ */ u("span", {})
}
) })
] });
}
function Lt() {
const [e, t] = ye(
() => typeof window < "u" ? window.location.hash : ""
);
return le(() => {
t(window.location.hash);
const s = () => {
t(window.location.hash);
};
return window.addEventListener("hashchange", s), () => window.removeEventListener("hashchange", s);
}, []), [e, (s) => {
typeof window < "u" && s !== e && (window.location.hash = s);
}];
}
function Dt({
allowedHtmlTags: e,
allowMissingSolutions: t,
cellMatcher: o,
cellSize: s,
data: n,
id: r,
loadGrid: i,
onCellChange: c,
onCellFocus: p,
onComplete: f,
saveGrid: h,
stickyClue: d
}) {
const v = O(), [C, l] = At(
`crosswords.${r}`,
Ie(n.dimensions.cols, n.dimensions.rows)
), [a] = Lt(), [G, H] = x.useState(!1), [_, R] = x.useState(null), M = x.useRef(null), L = V((N) => N.cells), k = Y((N) =>