@jackuait/blok 0.4.3-beta.4 → 0.4.3-beta.6

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.
@@ -1,4 +1,4 @@
1
- import { e as i } from "./blok-N-sAekLt.mjs";
1
+ import { e as i } from "./blok-B6xeFB1r.mjs";
2
2
  const l = async (e, r) => {
3
3
  const n = (await import("./i18next-CugVlwWp.mjs")).default.createInstance(), s = {
4
4
  lng: e,
@@ -1,4 +1,4 @@
1
- import { t as f, q as i } from "./inline-tool-convert-BBeAtLcM.mjs";
1
+ import { t as f, q as i } from "./inline-tool-convert-DqYXfC5g.mjs";
2
2
  const a = {
3
3
  wrapper: i(
4
4
  "fixed z-[2] bottom-5 left-5",
@@ -18,7 +18,7 @@ let nt = (o = 21) => {
18
18
  return t;
19
19
  };
20
20
  var ot = /* @__PURE__ */ ((o) => (o.VERBOSE = "VERBOSE", o.INFO = "INFO", o.WARN = "WARN", o.ERROR = "ERROR", o))(ot || {});
21
- const rt = () => "0.4.3-beta.4", Ct = {
21
+ const rt = () => "0.4.3-beta.6", Ct = {
22
22
  BACKSPACE: 8,
23
23
  TAB: 9,
24
24
  ENTER: 13,
@@ -1945,13 +1945,13 @@ export {
1945
1945
  Et as a8,
1946
1946
  jt as a9,
1947
1947
  ke as aa,
1948
- de as ab,
1949
- ue as ac,
1950
- pe as ad,
1951
- ge as ae,
1952
- he as af,
1953
- fe as ag,
1954
- me as ah,
1948
+ me as ab,
1949
+ de as ac,
1950
+ ue as ad,
1951
+ pe as ae,
1952
+ ge as af,
1953
+ he as ag,
1954
+ fe as ah,
1955
1955
  ve as ai,
1956
1956
  we as aj,
1957
1957
  Ce as ak,
package/dist/full.mjs CHANGED
@@ -10,10 +10,10 @@ var e = (a, l, o) => l in a ? n(a, l, { enumerable: !0, configurable: !0, writab
10
10
  d.call(l, o) && e(a, o, l[o]);
11
11
  return a;
12
12
  }, r = (a, l) => t(a, c(l));
13
- import { B as v, v as A } from "./chunks/blok-N-sAekLt.mjs";
13
+ import { B as v, v as A } from "./chunks/blok-B6xeFB1r.mjs";
14
14
  import { List as p, Header as f, Paragraph as I, Link as k, Italic as u, Bold as B } from "./tools.mjs";
15
15
  import { defaultBlockTools as H, defaultInlineTools as P } from "./tools.mjs";
16
- import { D as _ } from "./chunks/inline-tool-convert-BBeAtLcM.mjs";
16
+ import { D as _ } from "./chunks/inline-tool-convert-DqYXfC5g.mjs";
17
17
  const m = {
18
18
  paragraph: {
19
19
  class: I,
package/dist/tools.mjs CHANGED
@@ -1,17 +1,17 @@
1
- var nt = Object.defineProperty, rt = Object.defineProperties;
2
- var st = Object.getOwnPropertyDescriptors;
3
- var K = Object.getOwnPropertySymbols;
4
- var ot = Object.prototype.hasOwnProperty, it = Object.prototype.propertyIsEnumerable;
5
- var U = (f, t, e) => t in f ? nt(f, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : f[t] = e, w = (f, t) => {
1
+ var rt = Object.defineProperty, st = Object.defineProperties;
2
+ var ot = Object.getOwnPropertyDescriptors;
3
+ var q = Object.getOwnPropertySymbols;
4
+ var it = Object.prototype.hasOwnProperty, at = Object.prototype.propertyIsEnumerable;
5
+ var U = (f, t, e) => t in f ? rt(f, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : f[t] = e, w = (f, t) => {
6
6
  for (var e in t || (t = {}))
7
- ot.call(t, e) && U(f, e, t[e]);
8
- if (K)
9
- for (var e of K(t))
10
- it.call(t, e) && U(f, e, t[e]);
7
+ it.call(t, e) && U(f, e, t[e]);
8
+ if (q)
9
+ for (var e of q(t))
10
+ at.call(t, e) && U(f, e, t[e]);
11
11
  return f;
12
- }, P = (f, t) => rt(f, st(t));
13
- import { t as L, D as g, a9 as et, aa as at, ab as lt, ac as ct, ad as dt, ae as ut, af as ht, ag as ft, ah as pt, ai as G, aj as j, ak as $, f as A, al as gt, am as mt, S as H, P as Et, an as Tt, l as Ct, J as At } from "./chunks/inline-tool-convert-BBeAtLcM.mjs";
14
- import { a0 as Ot } from "./chunks/inline-tool-convert-BBeAtLcM.mjs";
12
+ }, P = (f, t) => st(f, ot(t));
13
+ import { t as L, D as g, a9 as nt, aa as lt, ab as G, ac as ct, ad as dt, ae as ut, af as ht, ag as ft, ah as pt, ai as j, aj as $, ak as X, f as A, al as gt, am as mt, S as H, P as Et, an as Tt, l as Ct, J as At } from "./chunks/inline-tool-convert-DqYXfC5g.mjs";
14
+ import { a0 as Ot } from "./chunks/inline-tool-convert-DqYXfC5g.mjs";
15
15
  const W = [
16
16
  "empty:before:pointer-events-none",
17
17
  "empty:before:text-gray-text",
@@ -41,7 +41,7 @@ const W = [
41
41
  e.selectNodeContents(f), e.collapse(!0), t.removeAllRanges(), t.addRange(e);
42
42
  }, Nt = (f) => {
43
43
  bt(f) && St(f);
44
- }, z = (f, t, e = "data-placeholder") => {
44
+ }, V = (f, t, e = "data-placeholder") => {
45
45
  f.setAttribute(e, t != null ? t : "");
46
46
  const n = () => Nt(f);
47
47
  f.addEventListener("focus", n), f.addEventListener("input", n);
@@ -101,7 +101,7 @@ const W = [
101
101
  yt
102
102
  ), t.setAttribute(g.tool, "paragraph"), t.contentEditable = "false";
103
103
  const e = this.buildInlineStyles();
104
- return Object.keys(e).length > 0 && Object.assign(t.style, e), this._data.text && (t.innerHTML = this._data.text), this.readOnly ? t.setAttribute("data-blok-placeholder-active", this.api.i18n.t(this._placeholder)) : (t.contentEditable = "true", t.addEventListener("keyup", this.onKeyUp), z(t, this.api.i18n.t(this._placeholder), "data-blok-placeholder-active")), t;
104
+ return Object.keys(e).length > 0 && Object.assign(t.style, e), this._data.text && (t.innerHTML = this._data.text), this.readOnly ? t.setAttribute("data-blok-placeholder-active", this.api.i18n.t(this._placeholder)) : (t.contentEditable = "true", t.addEventListener("keyup", this.onKeyUp), V(t, this.api.i18n.t(this._placeholder), "data-blok-placeholder-active")), t;
105
105
  }
106
106
  /**
107
107
  * Return Tool's view
@@ -142,7 +142,7 @@ const W = [
142
142
  */
143
143
  save(t) {
144
144
  return {
145
- text: et(t.innerHTML)
145
+ text: nt(t.innerHTML)
146
146
  };
147
147
  }
148
148
  /**
@@ -212,7 +212,7 @@ const W = [
212
212
  */
213
213
  static get toolbox() {
214
214
  return {
215
- icon: at,
215
+ icon: lt,
216
216
  title: "Text",
217
217
  titleKey: "text"
218
218
  };
@@ -226,8 +226,8 @@ M.WRAPPER_CLASSES = [
226
226
  "[&>p:first-of-type]:mt-0",
227
227
  "[&>p:last-of-type]:mb-0"
228
228
  ];
229
- let X = M;
230
- const I = class I {
229
+ let Y = M;
230
+ const x = class x {
231
231
  /**
232
232
  * Render plugin's main Element and fill it with saved data
233
233
  *
@@ -288,20 +288,61 @@ const I = class I {
288
288
  * @returns MenuConfig array
289
289
  */
290
290
  renderSettings() {
291
- return this.levels.map((t) => {
292
- const e = this.api.i18n.t(t.nameKey), n = e !== t.nameKey ? e : t.name;
291
+ const t = this._settings._toolboxEntries;
292
+ return t !== void 0 && t.length > 0 ? this.buildSettingsFromToolboxEntries(t) : this.levels.map((e) => {
293
+ const n = this.api.i18n.t(e.nameKey), r = n !== e.nameKey ? n : e.name;
293
294
  return {
294
- icon: t.icon,
295
- title: n,
296
- onActivate: () => this.setLevel(t.number),
295
+ icon: e.icon,
296
+ title: r,
297
+ onActivate: () => this.setLevel(e.number),
297
298
  closeOnActivate: !0,
298
- isActive: this.currentLevel.number === t.number,
299
+ isActive: this.currentLevel.number === e.number,
299
300
  dataset: {
300
- "blok-header-level": String(t.number)
301
+ "blok-header-level": String(e.number)
301
302
  }
302
303
  };
303
304
  });
304
305
  }
306
+ /**
307
+ * Build settings menu items from toolbox entries.
308
+ * This allows users to customize which levels appear in block settings
309
+ * by configuring the toolbox.
310
+ *
311
+ * @param entries - Merged toolbox entries from user config
312
+ * @returns MenuConfig array
313
+ */
314
+ buildSettingsFromToolboxEntries(t) {
315
+ return t.map((e) => {
316
+ var d, c, h, p;
317
+ const n = e.data, r = (d = n == null ? void 0 : n.level) != null ? d : this.defaultLevel.number, s = x.DEFAULT_LEVELS.find((m) => m.number === r), o = (c = s == null ? void 0 : s.name) != null ? c : `Heading ${r}`, a = this.resolveToolboxEntryTitle(e, o);
318
+ return {
319
+ icon: (p = (h = e.icon) != null ? h : s == null ? void 0 : s.icon) != null ? p : G,
320
+ title: a,
321
+ onActivate: () => this.setLevel(r),
322
+ closeOnActivate: !0,
323
+ isActive: this.currentLevel.number === r,
324
+ dataset: {
325
+ "blok-header-level": String(r)
326
+ }
327
+ };
328
+ });
329
+ }
330
+ /**
331
+ * Resolves the title for a toolbox entry.
332
+ * Priority: custom title > i18n key translation > fallback
333
+ *
334
+ * @param entry - Toolbox entry
335
+ * @param fallback - Fallback title if no custom title or translation found
336
+ * @returns Resolved title string
337
+ */
338
+ resolveToolboxEntryTitle(t, e) {
339
+ if (t.title !== void 0)
340
+ return t.title;
341
+ if (t.titleKey === void 0)
342
+ return e;
343
+ const n = `toolNames.${t.titleKey}`, r = this.api.i18n.t(n);
344
+ return r !== n ? r : e;
345
+ }
305
346
  /**
306
347
  * Callback for Block's settings buttons
307
348
  *
@@ -402,9 +443,9 @@ const I = class I {
402
443
  */
403
444
  getTag() {
404
445
  const t = document.createElement(this.currentLevel.tag);
405
- t.innerHTML = this._data.text || "", t.className = L(I.BASE_STYLES, this.currentLevel.styles, W);
446
+ t.innerHTML = this._data.text || "", t.className = L(x.BASE_STYLES, this.currentLevel.styles, W);
406
447
  const { inlineStyles: e } = this.currentLevel;
407
- return e && Object.assign(t.style, e), t.setAttribute(g.tool, "header"), t.contentEditable = this.readOnly ? "false" : "true", this.readOnly ? t.setAttribute("data-placeholder", this.api.i18n.t(this._settings.placeholder || "")) : z(t, this.api.i18n.t(this._settings.placeholder || "")), t;
448
+ return e && Object.assign(t.style, e), t.setAttribute(g.tool, "header"), t.contentEditable = this.readOnly ? "false" : "true", this.readOnly ? t.setAttribute("data-placeholder", this.api.i18n.t(this._settings.placeholder || "")) : V(t, this.api.i18n.t(this._settings.placeholder || "")), t;
408
449
  }
409
450
  /**
410
451
  * Get current level
@@ -432,7 +473,7 @@ const I = class I {
432
473
  * @returns Level array
433
474
  */
434
475
  get levels() {
435
- const t = this._settings.levelOverrides || {}, e = I.DEFAULT_LEVELS.map((n) => {
476
+ const t = this._settings.levelOverrides || {}, e = x.DEFAULT_LEVELS.map((n) => {
436
477
  var o;
437
478
  const r = t[n.number] || {}, s = {};
438
479
  return r.size && (s.fontSize = r.size), r.marginTop && (s.marginTop = r.marginTop), r.marginBottom && (s.marginBottom = r.marginBottom), {
@@ -490,21 +531,21 @@ const I = class I {
490
531
  */
491
532
  static get toolbox() {
492
533
  return {
493
- icon: pt,
534
+ icon: G,
494
535
  title: "Heading",
495
536
  titleKey: "heading"
496
537
  };
497
538
  }
498
539
  };
499
- I.BASE_STYLES = "py-[3px] px-[2px] m-0 !leading-[1.3] outline-none [&_p]:!p-0 [&_p]:!m-0 [&_div]:!p-0 [&_div]:!m-0", I.DEFAULT_LEVELS = [
500
- { number: 1, tag: "H1", nameKey: "tools.header.heading1", name: "Heading 1", icon: lt, styles: "text-4xl font-bold mt-8 mb-1" },
501
- { number: 2, tag: "H2", nameKey: "tools.header.heading2", name: "Heading 2", icon: ct, styles: "text-3xl font-semibold mt-6 mb-px" },
502
- { number: 3, tag: "H3", nameKey: "tools.header.heading3", name: "Heading 3", icon: dt, styles: "text-2xl font-semibold mt-4 mb-px" },
503
- { number: 4, tag: "H4", nameKey: "tools.header.heading4", name: "Heading 4", icon: ut, styles: "text-xl font-semibold mt-3 mb-px" },
504
- { number: 5, tag: "H5", nameKey: "tools.header.heading5", name: "Heading 5", icon: ht, styles: "text-base font-semibold mt-3 mb-px" },
505
- { number: 6, tag: "H6", nameKey: "tools.header.heading6", name: "Heading 6", icon: ft, styles: "text-sm font-semibold mt-3 mb-px" }
540
+ x.BASE_STYLES = "py-[3px] px-[2px] m-0 !leading-[1.3] outline-none [&_p]:!p-0 [&_p]:!m-0 [&_div]:!p-0 [&_div]:!m-0", x.DEFAULT_LEVELS = [
541
+ { number: 1, tag: "H1", nameKey: "tools.header.heading1", name: "Heading 1", icon: ct, styles: "text-4xl font-bold mt-8 mb-1" },
542
+ { number: 2, tag: "H2", nameKey: "tools.header.heading2", name: "Heading 2", icon: dt, styles: "text-3xl font-semibold mt-6 mb-px" },
543
+ { number: 3, tag: "H3", nameKey: "tools.header.heading3", name: "Heading 3", icon: ut, styles: "text-2xl font-semibold mt-4 mb-px" },
544
+ { number: 4, tag: "H4", nameKey: "tools.header.heading4", name: "Heading 4", icon: ht, styles: "text-xl font-semibold mt-3 mb-px" },
545
+ { number: 5, tag: "H5", nameKey: "tools.header.heading5", name: "Heading 5", icon: ft, styles: "text-base font-semibold mt-3 mb-px" },
546
+ { number: 6, tag: "H6", nameKey: "tools.header.heading6", name: "Heading 6", icon: pt, styles: "text-sm font-semibold mt-3 mb-px" }
506
547
  ];
507
- let Y = I;
548
+ let J = x;
508
549
  const u = class u {
509
550
  constructor({ data: t, config: e, api: n, readOnly: r, block: s }) {
510
551
  this._element = null, this.handleBlockChanged = (o) => {
@@ -551,7 +592,7 @@ const u = class u {
551
592
  this.itemColor && (e.color = this.itemColor), this.itemSize && (e.fontSize = this.itemSize);
552
593
  }
553
594
  setupItemPlaceholder(t) {
554
- this.readOnly || z(t, this.placeholder);
595
+ this.readOnly || V(t, this.placeholder);
555
596
  }
556
597
  render() {
557
598
  return this._element = this.createItemElement(), this._element;
@@ -1260,7 +1301,7 @@ const u = class u {
1260
1301
  save() {
1261
1302
  if (!this._element) return this._data;
1262
1303
  const t = this.getContentElement(), n = {
1263
- text: t ? et(t.innerHTML) : this._data.text,
1304
+ text: t ? nt(t.innerHTML) : this._data.text,
1264
1305
  style: this._data.style,
1265
1306
  checked: this._data.checked
1266
1307
  };
@@ -1375,21 +1416,21 @@ const u = class u {
1375
1416
  static get toolbox() {
1376
1417
  return [
1377
1418
  {
1378
- icon: G,
1419
+ icon: j,
1379
1420
  title: "Bulleted list",
1380
1421
  titleKey: "bulletedList",
1381
1422
  data: { style: "unordered" },
1382
1423
  name: "bulleted-list"
1383
1424
  },
1384
1425
  {
1385
- icon: j,
1426
+ icon: $,
1386
1427
  title: "Numbered list",
1387
1428
  titleKey: "numberedList",
1388
1429
  data: { style: "ordered" },
1389
1430
  name: "numbered-list"
1390
1431
  },
1391
1432
  {
1392
- icon: $,
1433
+ icon: X,
1393
1434
  title: "To-do list",
1394
1435
  titleKey: "todoList",
1395
1436
  data: { style: "checklist" },
@@ -1399,11 +1440,11 @@ const u = class u {
1399
1440
  }
1400
1441
  };
1401
1442
  u.BASE_STYLES = "outline-none", u.ITEM_STYLES = "outline-none py-0.5 pl-0.5 leading-[1.6em]", u.CHECKLIST_ITEM_STYLES = "flex items-start py-0.5 pl-0.5", u.CHECKBOX_STYLES = "mt-1 w-4 mr-2 h-4 cursor-pointer accent-current", u.STYLE_CONFIGS = [
1402
- { style: "unordered", name: "bulletedList", icon: G },
1403
- { style: "ordered", name: "numberedList", icon: j },
1404
- { style: "checklist", name: "todoList", icon: $ }
1443
+ { style: "unordered", name: "bulletedList", icon: j },
1444
+ { style: "ordered", name: "numberedList", icon: $ },
1445
+ { style: "checklist", name: "todoList", icon: X }
1405
1446
  ], u.pendingMarkerUpdate = !1, u.DEFAULT_PLACEHOLDER = "List", u.INDENT_PER_LEVEL = 24, u.TOOL_NAME = "list";
1406
- let J = u;
1447
+ let Z = u;
1407
1448
  const i = class i {
1408
1449
  /**
1409
1450
  * Sanitizer Rule
@@ -1470,16 +1511,16 @@ const i = class i {
1470
1511
  }
1471
1512
  const p = (n = l.textContent) != null ? n : "";
1472
1513
  p.length > 1 && p.startsWith("​") && (l.textContent = p.slice(1));
1473
- const T = window.getSelection();
1474
- i.ensureCaretAtBoundary(T, l), i.scheduleBoundaryCaretAdjustment(l);
1475
- const y = (r = l.textContent) != null ? r : "", m = y.replace(/\u200B/g, ""), C = m.match(/^\s+/), E = /\S/.test(m), N = y.startsWith("​");
1476
- C && (o.hasLeadingSpace = !0, o.leadingWhitespace = C[0]), E && (o.hasTypedContent = !0);
1477
- const B = /^\s/.test(m), x = o.hasTypedContent && !N && ((s = d.textContent) != null ? s : "").length <= c, v = o.hasLeadingSpace && o.hasTypedContent && !B;
1478
- if (x && v) {
1514
+ const m = window.getSelection();
1515
+ i.ensureCaretAtBoundary(m, l), i.scheduleBoundaryCaretAdjustment(l);
1516
+ const y = (r = l.textContent) != null ? r : "", E = y.replace(/\u200B/g, ""), C = E.match(/^\s+/), T = /\S/.test(E), N = y.startsWith("​");
1517
+ C && (o.hasLeadingSpace = !0, o.leadingWhitespace = C[0]), T && (o.hasTypedContent = !0);
1518
+ const B = /^\s/.test(E), v = o.hasTypedContent && !N && ((s = d.textContent) != null ? s : "").length <= c, R = o.hasLeadingSpace && o.hasTypedContent && !B;
1519
+ if (v && R) {
1479
1520
  const b = y.replace(/^[\u200B\s]+/, ""), S = o.leadingWhitespace || " ";
1480
- l.textContent = `${S}${b}`, i.ensureCaretAtBoundary(T, l);
1521
+ l.textContent = `${S}${b}`, i.ensureCaretAtBoundary(m, l);
1481
1522
  }
1482
- x && i.collapsedExitRecords.delete(o);
1523
+ v && i.collapsedExitRecords.delete(o);
1483
1524
  }
1484
1525
  }
1485
1526
  /**
@@ -2038,28 +2079,28 @@ const i = class i {
2038
2079
  return;
2039
2080
  const s = `strong[${i.DATA_ATTR_COLLAPSED_ACTIVE}="true"]`;
2040
2081
  r.querySelectorAll(s).forEach((l) => {
2041
- var k, R, F, V, q;
2082
+ var k, I, _, z, K;
2042
2083
  const d = l.getAttribute(i.DATA_ATTR_PREV_LENGTH), c = l.previousSibling;
2043
2084
  if (!d || !c || c.nodeType !== Node.TEXT_NODE)
2044
2085
  return;
2045
2086
  const h = Number(d);
2046
2087
  if (!Number.isFinite(h))
2047
2088
  return;
2048
- const p = c, T = (k = p.textContent) != null ? k : "";
2049
- if (T.length <= h)
2089
+ const p = c, m = (k = p.textContent) != null ? k : "";
2090
+ if (m.length <= h)
2050
2091
  return;
2051
- const y = T.slice(0, h), m = T.slice(h);
2092
+ const y = m.slice(0, h), E = m.slice(h);
2052
2093
  p.textContent = y;
2053
- const C = m.match(/^[\u00A0\s]+/);
2054
- if (C && !l.hasAttribute(i.DATA_ATTR_LEADING_WHITESPACE) && l.setAttribute(i.DATA_ATTR_LEADING_WHITESPACE, C[0]), m.length === 0)
2094
+ const C = E.match(/^[\u00A0\s]+/);
2095
+ if (C && !l.hasAttribute(i.DATA_ATTR_LEADING_WHITESPACE) && l.setAttribute(i.DATA_ATTR_LEADING_WHITESPACE, C[0]), E.length === 0)
2055
2096
  return;
2056
- const E = (R = l.textContent) != null ? R : "", N = E + m, B = (F = l.getAttribute(i.DATA_ATTR_LEADING_WHITESPACE)) != null ? F : "", v = B.length > 0 && E.length === 0 && !N.startsWith(B) ? B + N : N, b = document.createTextNode(v);
2097
+ const T = (I = l.textContent) != null ? I : "", N = T + E, B = (_ = l.getAttribute(i.DATA_ATTR_LEADING_WHITESPACE)) != null ? _ : "", R = B.length > 0 && T.length === 0 && !N.startsWith(B) ? B + N : N, b = document.createTextNode(R);
2057
2098
  for (; l.firstChild; )
2058
2099
  l.removeChild(l.firstChild);
2059
2100
  if (l.appendChild(b), !(t != null && t.isCollapsed) || !i.isNodeWithin(t.focusNode, p))
2060
2101
  return;
2061
- const S = document.createRange(), _ = (q = (V = b.textContent) == null ? void 0 : V.length) != null ? q : 0;
2062
- S.setStart(b, _), S.collapse(!0), t.removeAllRanges(), t.addRange(S);
2102
+ const S = document.createRange(), F = (K = (z = b.textContent) == null ? void 0 : z.length) != null ? K : 0;
2103
+ S.setStart(b, F), S.collapse(!0), t.removeAllRanges(), t.addRange(S);
2063
2104
  });
2064
2105
  }
2065
2106
  /**
@@ -2268,23 +2309,23 @@ const i = class i {
2268
2309
  if (!r)
2269
2310
  return;
2270
2311
  r.querySelectorAll(`strong[${i.DATA_ATTR_COLLAPSED_LENGTH}]`).forEach((a) => {
2271
- var x, v, b, S, _;
2312
+ var v, R, b, S, F;
2272
2313
  const l = a, d = l.getAttribute(i.DATA_ATTR_COLLAPSED_LENGTH);
2273
2314
  if (!d)
2274
2315
  return;
2275
- const c = Number(d), h = (x = l.textContent) != null ? x : "";
2316
+ const c = Number(d), h = (v = l.textContent) != null ? v : "";
2276
2317
  if (!Number.isFinite(c))
2277
2318
  return;
2278
- const p = h.length > c, T = p ? i.splitCollapsedBoldText(l, c, h) : null, y = l.getAttribute(i.DATA_ATTR_PREV_LENGTH), m = y ? Number(y) : NaN, C = l.previousSibling, E = (C == null ? void 0 : C.nodeType) === Node.TEXT_NODE ? C : null, N = (v = E == null ? void 0 : E.textContent) != null ? v : "", B = !!(y && Number.isFinite(m) && E && N.length > m);
2279
- if (B && E) {
2280
- const k = N.slice(0, m), R = N.slice(m);
2281
- E.textContent = k;
2282
- const F = document.createTextNode(R);
2283
- (b = l.parentNode) == null || b.insertBefore(F, l.nextSibling);
2319
+ const p = h.length > c, m = p ? i.splitCollapsedBoldText(l, c, h) : null, y = l.getAttribute(i.DATA_ATTR_PREV_LENGTH), E = y ? Number(y) : NaN, C = l.previousSibling, T = (C == null ? void 0 : C.nodeType) === Node.TEXT_NODE ? C : null, N = (R = T == null ? void 0 : T.textContent) != null ? R : "", B = !!(y && Number.isFinite(E) && T && N.length > E);
2320
+ if (B && T) {
2321
+ const k = N.slice(0, E), I = N.slice(E);
2322
+ T.textContent = k;
2323
+ const _ = document.createTextNode(I);
2324
+ (b = l.parentNode) == null || b.insertBefore(_, l.nextSibling);
2284
2325
  }
2285
- if (B && l.removeAttribute(i.DATA_ATTR_PREV_LENGTH), t != null && t.isCollapsed && T && i.isNodeWithin(t.focusNode, l)) {
2286
- const k = document.createRange(), R = (_ = (S = T.textContent) == null ? void 0 : S.length) != null ? _ : 0;
2287
- k.setStart(T, R), k.collapse(!0), t.removeAllRanges(), t.addRange(k);
2326
+ if (B && l.removeAttribute(i.DATA_ATTR_PREV_LENGTH), t != null && t.isCollapsed && m && i.isNodeWithin(t.focusNode, l)) {
2327
+ const k = document.createRange(), I = (F = (S = m.textContent) == null ? void 0 : S.length) != null ? F : 0;
2328
+ k.setStart(m, I), k.collapse(!0), t.removeAllRanges(), t.addRange(k);
2288
2329
  }
2289
2330
  p && l.removeAttribute(i.DATA_ATTR_COLLAPSED_LENGTH);
2290
2331
  });
@@ -2399,19 +2440,19 @@ const i = class i {
2399
2440
  * @param parent - Parent node that hosts the bold element
2400
2441
  */
2401
2442
  static exitCollapsedBoldWithContent(t, e, n) {
2402
- var p, T, y, m, C, E;
2403
- e.setAttribute(i.DATA_ATTR_COLLAPSED_LENGTH, ((T = (p = e.textContent) == null ? void 0 : p.length) != null ? T : 0).toString()), e.removeAttribute(i.DATA_ATTR_PREV_LENGTH), e.removeAttribute(i.DATA_ATTR_COLLAPSED_ACTIVE), e.removeAttribute(i.DATA_ATTR_LEADING_WHITESPACE);
2443
+ var p, m, y, E, C, T;
2444
+ e.setAttribute(i.DATA_ATTR_COLLAPSED_LENGTH, ((m = (p = e.textContent) == null ? void 0 : p.length) != null ? m : 0).toString()), e.removeAttribute(i.DATA_ATTR_PREV_LENGTH), e.removeAttribute(i.DATA_ATTR_COLLAPSED_ACTIVE), e.removeAttribute(i.DATA_ATTR_LEADING_WHITESPACE);
2404
2445
  const r = e.nextSibling, s = !r || r.nodeType !== Node.TEXT_NODE, o = s ? document.createTextNode("​") : null;
2405
2446
  o && n.insertBefore(o, r);
2406
2447
  const a = o != null ? o : r;
2407
2448
  !s && ((y = a.textContent) != null ? y : "").length === 0 && (a.textContent = "​");
2408
- const l = document.createRange(), c = ((m = a.textContent) != null ? m : "").startsWith("​") ? 1 : 0;
2449
+ const l = document.createRange(), c = ((E = a.textContent) != null ? E : "").startsWith("​") ? 1 : 0;
2409
2450
  l.setStart(a, c), l.collapse(!0), t.removeAllRanges(), t.addRange(l);
2410
2451
  const h = i.ensureStrongElement(e);
2411
2452
  return i.collapsedExitRecords.add({
2412
2453
  boundary: a,
2413
2454
  boldElement: h,
2414
- allowedLength: (E = (C = h.textContent) == null ? void 0 : C.length) != null ? E : 0,
2455
+ allowedLength: (T = (C = h.textContent) == null ? void 0 : C.length) != null ? T : 0,
2415
2456
  hasLeadingSpace: !1,
2416
2457
  hasTypedContent: !1,
2417
2458
  leadingWhitespace: ""
@@ -2549,7 +2590,7 @@ const i = class i {
2549
2590
  }
2550
2591
  };
2551
2592
  i.isInline = !0, i.title = "Bold", i.titleKey = "bold", i.shortcutListenerRegistered = !1, i.selectionListenerRegistered = !1, i.inputListenerRegistered = !1, i.beforeInputListenerRegistered = !1, i.globalListenersInitialized = i.initializeGlobalListeners(), i.collapsedExitRecords = /* @__PURE__ */ new Set(), i.markerSequence = 0, i.isProcessingMutation = !1, i.DATA_ATTR_COLLAPSED_LENGTH = "data-blok-bold-collapsed-length", i.DATA_ATTR_COLLAPSED_ACTIVE = "data-blok-bold-collapsed-active", i.DATA_ATTR_PREV_LENGTH = "data-blok-bold-prev-length", i.DATA_ATTR_LEADING_WHITESPACE = "data-blok-bold-leading-ws", i.instances = /* @__PURE__ */ new Set(), i.pendingBoundaryCaretAdjustments = /* @__PURE__ */ new WeakSet(), i.shortcut = "CMD+B";
2552
- let Z = i;
2593
+ let Q = i;
2553
2594
  const O = class O {
2554
2595
  /**
2555
2596
  * Sanitizer Rule
@@ -2822,7 +2863,7 @@ const O = class O {
2822
2863
  }
2823
2864
  };
2824
2865
  O.isInline = !0, O.title = "Italic", O.titleKey = "italic", O.shortcut = "CMD+I";
2825
- let Q = O;
2866
+ let tt = O;
2826
2867
  const D = class D {
2827
2868
  /**
2828
2869
  * @param api - Blok API
@@ -3050,7 +3091,7 @@ const D = class D {
3050
3091
  }
3051
3092
  };
3052
3093
  D.isInline = !0, D.title = "Link", D.titleKey = "link", D.shortcut = "CMD+K";
3053
- let tt = D;
3094
+ let et = D;
3054
3095
  const xt = {
3055
3096
  paragraph: { inlineToolbar: !0, config: { preserveBlank: !0 } },
3056
3097
  header: { inlineToolbar: !0 },
@@ -3061,13 +3102,13 @@ const xt = {
3061
3102
  link: {}
3062
3103
  };
3063
3104
  export {
3064
- Z as Bold,
3105
+ Q as Bold,
3065
3106
  Ot as Convert,
3066
- Y as Header,
3067
- Q as Italic,
3068
- tt as Link,
3069
- J as List,
3070
- X as Paragraph,
3107
+ J as Header,
3108
+ tt as Italic,
3109
+ et as Link,
3110
+ Z as List,
3111
+ Y as Paragraph,
3071
3112
  xt as defaultBlockTools,
3072
3113
  vt as defaultInlineTools
3073
3114
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jackuait/blok",
3
- "version": "0.4.3-beta.4",
3
+ "version": "0.4.3-beta.6",
4
4
  "description": "Blok — headless, highly extensible rich text editor built for developers who need to implement a block-based editing experience (similar to Notion) without building it from scratch",
5
5
  "module": "dist/blok.mjs",
6
6
  "types": "./types/index.d.ts",
@@ -25,6 +25,7 @@ export class I18nAPI extends Module {
25
25
  if (this.cachedMethods === null) {
26
26
  this.cachedMethods = {
27
27
  t: (dictKey: string): string => this.Blok.I18n.t(dictKey),
28
+ has: (dictKey: string): boolean => this.Blok.I18n.has(dictKey),
28
29
  };
29
30
  }
30
31
 
@@ -51,13 +51,22 @@ export class BlockToolAdapter extends BaseToolAdapter<ToolType.Block, IBlockTool
51
51
  * @param readOnly - True if Blok is in read-only mode
52
52
  */
53
53
  public create(data: BlockToolData, block: BlockAPI, readOnly: boolean): IBlockTool {
54
+ const toolboxEntries = this.toolbox;
55
+
56
+ /**
57
+ * Inject merged toolbox entries into config so tools can use them in renderSettings().
58
+ * This allows tools like Header to show the same options in block settings as in the toolbox.
59
+ */
60
+ const configWithToolbox = toolboxEntries !== undefined
61
+ ? { ...this.settings, _toolboxEntries: toolboxEntries }
62
+ : this.settings;
54
63
 
55
64
  return new this.constructable({
56
65
  data,
57
66
  block,
58
67
  readOnly,
59
68
  api: this.api,
60
- config: this.settings,
69
+ config: configWithToolbox,
61
70
  }) as IBlockTool;
62
71
  }
63
72
 
@@ -5,6 +5,7 @@ import { BlockTuneAdapter } from './tune';
5
5
  import { BlockToolAdapter } from './block';
6
6
  import type { API as ApiModule } from '../modules/api';
7
7
  import type { BlokConfig } from '../../../types/configs';
8
+ import type { API as ApiMethods, I18n } from '../../../types';
8
9
 
9
10
  type ToolConstructor = typeof InlineToolAdapter | typeof BlockToolAdapter | typeof BlockTuneAdapter;
10
11
 
@@ -56,18 +57,66 @@ export class ToolsFactory {
56
57
  }
57
58
 
58
59
  const Constructor = this.getConstructor(constructable);
60
+ const toolApi = this.createToolApi(name);
59
61
 
60
62
  return new Constructor({
61
63
  name,
62
64
  constructable,
63
65
  config,
64
- api: this.api.methods,
66
+ api: toolApi,
65
67
  isDefault: name === this.blokConfig.defaultBlock,
66
68
  defaultPlaceholder: this.blokConfig.placeholder,
67
69
  isInternal,
68
70
  });
69
71
  }
70
72
 
73
+ /**
74
+ * Creates a tool-specific API with namespaced i18n.
75
+ *
76
+ * EditorJS tools expect `api.i18n.t('key')` to automatically look up
77
+ * `tools.{toolName}.key`. This wrapper provides that behavior while
78
+ * falling back to direct key lookup for Blok internal tools that use
79
+ * fully-qualified keys like `tools.stub.error`.
80
+ *
81
+ * @param toolName - Name of the tool
82
+ * @returns API object with tool-namespaced i18n
83
+ */
84
+ private createToolApi(toolName: string): ApiMethods {
85
+ const baseApi = this.api.methods;
86
+ const namespace = `tools.${toolName}`;
87
+
88
+ const namespacedI18n: I18n = {
89
+ t: (dictKey: string): string => {
90
+ /**
91
+ * Try namespaced key first for EditorJS compatibility.
92
+ * External tools call t('Add row') expecting lookup of 'tools.table.Add row'.
93
+ */
94
+ const namespacedKey = `${namespace}.${dictKey}`;
95
+
96
+ if (baseApi.i18n.has(namespacedKey)) {
97
+ return baseApi.i18n.t(namespacedKey);
98
+ }
99
+
100
+ /**
101
+ * Fall back to direct key lookup for Blok internal tools.
102
+ * Internal tools use fully-qualified keys like 'tools.stub.error'.
103
+ */
104
+ return baseApi.i18n.t(dictKey);
105
+ },
106
+
107
+ has: (dictKey: string): boolean => {
108
+ const namespacedKey = `${namespace}.${dictKey}`;
109
+
110
+ return baseApi.i18n.has(namespacedKey) || baseApi.i18n.has(dictKey);
111
+ },
112
+ };
113
+
114
+ return {
115
+ ...baseApi,
116
+ i18n: namespacedI18n,
117
+ };
118
+ }
119
+
71
120
  /**
72
121
  * Find appropriate Tool object constructor for Tool constructable
73
122
  * @param constructable - Tools constructable