@jackuait/blok 0.19.0 → 0.19.1

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,5 +1,5 @@
1
1
  import { i as e, t } from "./chunk-5O_1xk2F.mjs";
2
- import { $ as n, $n as r, $r as i, $t as a, An as o, At as s, B as c, Bn as l, Bt as u, C as d, Cn as f, Cr as p, Ct as m, Dn as h, Dr as g, Dt as _, En as v, Er as y, Et as b, F as x, Fi as S, Fn as C, Ft as w, G as T, Gn as E, Gt as D, H as ee, Hn as O, Ht as k, I as A, In as j, Ir as M, It as te, J as ne, Jn as N, Jt as re, Kn as ie, Kt as ae, L as oe, Ln as se, Lr as ce, Lt as P, Mn as le, Mr as F, Mt as ue, Nn as de, Nr as fe, Nt as pe, Oi as me, On as I, Or as he, Ot as ge, P as _e, Pi as L, Pn as ve, Pt as ye, Q as be, Qn as xe, Qt as Se, R as Ce, Rn as we, Rt as Te, S as Ee, Sn as De, St as Oe, T as ke, Tn as Ae, Tr as je, Tt as Me, U as R, Un as Ne, Ut as Pe, Vn as Fe, Vt as Ie, W as Le, Wn as Re, Wt as ze, X as Be, Xn as Ve, Xt as He, Y as Ue, Yn as We, Yt as Ge, Z as Ke, Zn as qe, Zt as Je, _ as Ye, _n as Xe, _t as Ze, a as Qe, ar as $e, at as et, b as tt, bn as nt, bt as rt, c as it, ci as at, cn as ot, cr as st, ct as z, d as ct, dn as lt, dt as ut, en as dt, et as ft, f as pt, fn as mt, fr as ht, ft as gt, g as _t, gn as vt, gr as yt, gt as bt, h as xt, hn as St, ht as Ct, i as wt, in as Tt, ir as Et, it as Dt, jn as Ot, jt as kt, kn as At, kr as B, kt as jt, l as Mt, ln as Nt, lr as Pt, lt as Ft, mn as It, mr as Lt, mt as Rt, n as zt, nn as Bt, nr as Vt, nt as Ht, o as V, oi as Ut, on as Wt, or as Gt, ot as Kt, p as qt, pn as Jt, pr as Yt, pt as Xt, q as Zt, qt as Qt, r as $t, rr as en, rt as tn, s as nn, sn as rn, sr as an, st as on, t as sn, tr as cn, u as H, un as ln, ur as un, ut as dn, v as fn, vn as pn, vt as mn, wn as hn, wr as U, wt as gn, x as _n, xn as vn, xt as yn, y as bn, yn as xn, yr as Sn, yt as Cn, z as wn, zn as Tn, zt as En } from "./constants-BmCvHbkL.mjs";
2
+ import { $ as n, $n as r, $r as i, $t as a, An as o, At as s, B as c, Bn as l, Bt as u, C as d, Cn as f, Cr as p, Ct as m, Dn as h, Dr as g, Dt as _, En as v, Er as y, Et as b, F as x, Fi as S, Fn as C, Ft as w, G as T, Gn as E, Gt as D, H as ee, Hn as O, Ht as k, I as A, In as j, Ir as M, It as te, J as ne, Jn as N, Jt as re, Kn as ie, Kt as ae, L as oe, Ln as se, Lr as ce, Lt as P, Mn as le, Mr as F, Mt as ue, Nn as de, Nr as fe, Nt as pe, Oi as me, On as I, Or as he, Ot as ge, P as _e, Pi as L, Pn as ve, Pt as ye, Q as be, Qn as xe, Qt as Se, R as Ce, Rn as we, Rt as Te, S as Ee, Sn as De, St as Oe, T as ke, Tn as Ae, Tr as je, Tt as Me, U as R, Un as Ne, Ut as Pe, Vn as Fe, Vt as Ie, W as Le, Wn as Re, Wt as ze, X as Be, Xn as Ve, Xt as He, Y as Ue, Yn as We, Yt as Ge, Z as Ke, Zn as qe, Zt as Je, _ as Ye, _n as Xe, _t as Ze, a as Qe, ar as $e, at as et, b as tt, bn as nt, bt as rt, c as it, ci as at, cn as ot, cr as st, ct as z, d as ct, dn as lt, dt as ut, en as dt, et as ft, f as pt, fn as mt, fr as ht, ft as gt, g as _t, gn as vt, gr as yt, gt as bt, h as xt, hn as St, ht as Ct, i as wt, in as Tt, ir as Et, it as Dt, jn as Ot, jt as kt, kn as At, kr as B, kt as jt, l as Mt, ln as Nt, lr as Pt, lt as Ft, mn as It, mr as Lt, mt as Rt, n as zt, nn as Bt, nr as Vt, nt as Ht, o as V, oi as Ut, on as Wt, or as Gt, ot as Kt, p as qt, pn as Jt, pr as Yt, pt as Xt, q as Zt, qt as Qt, r as $t, rr as en, rt as tn, s as nn, sn as rn, sr as an, st as on, t as sn, tr as cn, u as H, un as ln, ur as un, ut as dn, v as fn, vn as pn, vt as mn, wn as hn, wr as U, wt as gn, x as _n, xn as vn, xt as yn, y as bn, yn as xn, yr as Sn, yt as Cn, z as wn, zn as Tn, zt as En } from "./constants-DzQOOvgv.mjs";
3
3
  import { t as W } from "./objectSpread2-jlBcdYeb.mjs";
4
4
  import { n as G } from "./tw-DmW6-pCY.mjs";
5
5
  import { n as Dn } from "./lightweight-i18n-DJpMke7a.mjs";
@@ -14268,8 +14268,10 @@ function lm(e, t) {
14268
14268
  function um(e) {
14269
14269
  let t = document.createElement("div");
14270
14270
  t.className = "blok-audio-caption-row", t.setAttribute("data-role", "audio-caption-row");
14271
- let n = cm("audio-caption", e.value, e.editable, e.placeholder);
14272
- return n.className = "blok-audio-caption", t.appendChild(n), t;
14271
+ let n = document.createElement("div");
14272
+ n.className = "blok-audio-caption-row__inner";
14273
+ let r = cm("audio-caption", e.value, e.editable, e.placeholder);
14274
+ return r.className = "blok-audio-caption", n.appendChild(r), t.appendChild(n), t;
14273
14275
  }
14274
14276
  //#endregion
14275
14277
  //#region src/tools/audio/controls.ts
@@ -14657,7 +14659,7 @@ var Lm = class {
14657
14659
  }, Rm = class {
14658
14660
  constructor(e) {
14659
14661
  var t, n, r;
14660
- this.root = null, this.uploadingEl = null, this.lastFileName = null, this.errorMessage = null, this.lastSource = null, this.controlsHandle = null, this.waveformHandle = null, this.destroyed = !1, this.api = e.api, this.block = e.block, this.config = (t = e.config) == null ? {} : t, this.readOnly = e.readOnly, this.data = W(W({}, e.data), {}, { url: (n = (r = e.data) == null ? void 0 : r.url) == null ? "" : n }), this.state = this.data.url ? "RENDERED" : "EMPTY", this.uploader = new Lm(this.config);
14662
+ this.root = null, this.uploadingEl = null, this.lastFileName = null, this.errorMessage = null, this.lastSource = null, this.controlsHandle = null, this.waveformHandle = null, this.destroyed = !1, this.captionExitTimer = null, this.api = e.api, this.block = e.block, this.config = (t = e.config) == null ? {} : t, this.readOnly = e.readOnly, this.data = W(W({}, e.data), {}, { url: (n = (r = e.data) == null ? void 0 : r.url) == null ? "" : n }), this.state = this.data.url ? "RENDERED" : "EMPTY", this.uploader = new Lm(this.config);
14661
14663
  }
14662
14664
  render() {
14663
14665
  let e = document.createElement("div");
@@ -14782,7 +14784,7 @@ var Lm = class {
14782
14784
  }
14783
14785
  removed() {
14784
14786
  var e, t;
14785
- this.destroyed = !0, (e = this.controlsHandle) == null || e.destroy(), this.controlsHandle = null, (t = this.waveformHandle) == null || t.destroy(), this.waveformHandle = null, this.data.url.startsWith("blob:") && URL.revokeObjectURL(this.data.url);
14787
+ this.destroyed = !0, this.captionExitTimer && (clearTimeout(this.captionExitTimer), this.captionExitTimer = null), (e = this.controlsHandle) == null || e.destroy(), this.controlsHandle = null, (t = this.waveformHandle) == null || t.destroy(), this.waveformHandle = null, this.data.url.startsWith("blob:") && URL.revokeObjectURL(this.data.url);
14786
14788
  }
14787
14789
  startUpload(e) {
14788
14790
  this.lastFileName = e.name, this.lastSource = {
@@ -14835,7 +14837,7 @@ var Lm = class {
14835
14837
  renderState() {
14836
14838
  var e, t;
14837
14839
  if (this.root) {
14838
- if ((e = this.controlsHandle) == null || e.destroy(), this.controlsHandle = null, (t = this.waveformHandle) == null || t.destroy(), this.waveformHandle = null, this.root.replaceChildren(), this.uploadingEl = null, this.syncRootAttributes(), this.state === "EMPTY") {
14840
+ if (this.captionExitTimer && (clearTimeout(this.captionExitTimer), this.captionExitTimer = null), (e = this.controlsHandle) == null || e.destroy(), this.controlsHandle = null, (t = this.waveformHandle) == null || t.destroy(), this.waveformHandle = null, this.root.replaceChildren(), this.uploadingEl = null, this.syncRootAttributes(), this.state === "EMPTY") {
14839
14841
  this.renderEmpty();
14840
14842
  return;
14841
14843
  }
@@ -14880,55 +14882,84 @@ var Lm = class {
14880
14882
  r.type = "button", r.className = "blok-audio-retry", r.setAttribute("data-action", "replace"), r.textContent = Z(this.api.i18n, "tools.audio.errorReplace", "Replace"), r.addEventListener("click", () => this.transitionToEmpty()), t.append(n, r), this.root.appendChild(t);
14881
14883
  }
14882
14884
  renderRendered() {
14883
- var e, t;
14885
+ var e;
14884
14886
  if (!this.root) return;
14885
- let n = Z(this.api.i18n, "tools.audio.titlePlaceholder", "Track title"), r = Z(this.api.i18n, "tools.audio.artistPlaceholder", "Artist"), { figure: i, audio: a, waveformMount: o, title: s, artist: c, body: l } = lm(this.data, {
14887
+ let t = Z(this.api.i18n, "tools.audio.titlePlaceholder", "Track title"), n = Z(this.api.i18n, "tools.audio.artistPlaceholder", "Artist"), { figure: r, audio: i, waveformMount: a, title: o, artist: s, body: c } = lm(this.data, {
14886
14888
  editable: !this.readOnly,
14887
- titlePlaceholder: n,
14888
- artistPlaceholder: r
14889
+ titlePlaceholder: t,
14890
+ artistPlaceholder: n
14889
14891
  });
14890
14892
  (e = this.data.peaks) != null && e.length && (this.waveformHandle = Am({
14891
- mount: o,
14892
- media: a,
14893
+ mount: a,
14894
+ media: i,
14893
14895
  peaks: this.data.peaks
14894
14896
  })), this.controlsHandle = pm({
14895
- media: a,
14896
- figure: i,
14897
+ media: i,
14898
+ figure: r,
14897
14899
  data: this.data,
14898
14900
  onLoopChange: (e) => {
14899
14901
  this.data.loop = e || void 0, this.block.dispatchChange();
14900
14902
  }
14901
- }), l.appendChild(this.controlsHandle.element);
14902
- let u = (t = this.config.captionPlaceholder) == null ? am : t;
14903
- if (this.data.captionVisible !== !1 || !this.readOnly) {
14904
- var d;
14905
- i.appendChild(um({
14906
- value: (d = this.data.caption) == null ? "" : d,
14907
- placeholder: u,
14908
- editable: !this.readOnly
14909
- }));
14910
- }
14911
- s.addEventListener("blur", () => {
14903
+ }), c.appendChild(this.controlsHandle.element), this.data.captionVisible !== !1 && r.appendChild(this.createCaptionRow()), o.addEventListener("blur", () => {
14912
14904
  var e;
14913
- let t = (e = s.textContent) == null ? "" : e;
14905
+ let t = (e = o.textContent) == null ? "" : e;
14914
14906
  t !== this.data.title && (this.data.title = t || void 0, this.block.dispatchChange());
14915
- }), c.addEventListener("blur", () => {
14907
+ }), s.addEventListener("blur", () => {
14916
14908
  var e;
14917
- let t = (e = c.textContent) == null ? "" : e;
14909
+ let t = (e = s.textContent) == null ? "" : e;
14918
14910
  t !== this.data.artist && (this.data.artist = t || void 0, this.block.dispatchChange());
14919
- });
14920
- let f = i.querySelector("[data-role=\"audio-caption\"]");
14921
- f && f.addEventListener("blur", () => {
14911
+ }), this.root.appendChild(r);
14912
+ }
14913
+ createCaptionRow() {
14914
+ var e, t;
14915
+ let n = (e = this.config.captionPlaceholder) == null ? am : e, r = um({
14916
+ value: (t = this.data.caption) == null ? "" : t,
14917
+ placeholder: n,
14918
+ editable: !this.readOnly
14919
+ }), i = r.querySelector("[data-role=\"audio-caption\"]");
14920
+ return i == null || i.addEventListener("blur", () => {
14922
14921
  var e;
14923
- let t = (e = f.textContent) == null ? "" : e;
14922
+ let t = (e = i.textContent) == null ? "" : e;
14924
14923
  t !== this.data.caption && (this.data.caption = t || void 0, this.block.dispatchChange());
14925
- }), this.root.appendChild(i);
14924
+ }), r;
14925
+ }
14926
+ prefersReducedMotion() {
14927
+ var e, t, n;
14928
+ return (e = (t = (n = globalThis).matchMedia) == null ? void 0 : t.call(n, "(prefers-reduced-motion: reduce)").matches) == null ? !1 : e;
14926
14929
  }
14927
14930
  setAlignment(e) {
14928
14931
  this.data.alignment !== e && (this.data.alignment = e, this.block.dispatchChange(), this.renderState());
14929
14932
  }
14930
14933
  toggleCaption() {
14931
- this.data.captionVisible = this.data.captionVisible === !1, this.block.dispatchChange(), this.renderState();
14934
+ var e;
14935
+ let t = this.data.captionVisible === !1;
14936
+ this.data.captionVisible = t, t || (this.data.caption = void 0), this.block.dispatchChange();
14937
+ let n = (e = this.root) == null ? void 0 : e.querySelector("[data-role=\"audio-figure\"]");
14938
+ if (!n || this.prefersReducedMotion()) {
14939
+ this.renderState();
14940
+ return;
14941
+ }
14942
+ this.syncRootAttributes(), t ? this.animateCaptionIn(n) : this.animateCaptionOut(n);
14943
+ }
14944
+ animateCaptionIn(e) {
14945
+ let t = e.querySelector("[data-role=\"audio-caption-row\"]");
14946
+ if (t) {
14947
+ this.captionExitTimer && (clearTimeout(this.captionExitTimer), this.captionExitTimer = null), t.classList.remove("is-collapsed");
14948
+ return;
14949
+ }
14950
+ let n = this.createCaptionRow();
14951
+ n.classList.add("is-collapsed"), e.appendChild(n), n.offsetHeight, n.classList.remove("is-collapsed");
14952
+ }
14953
+ animateCaptionOut(e) {
14954
+ let t = e.querySelector("[data-role=\"audio-caption-row\"]");
14955
+ if (!t) return;
14956
+ t.classList.add("is-collapsed");
14957
+ let n = () => {
14958
+ this.captionExitTimer && (clearTimeout(this.captionExitTimer), this.captionExitTimer = null), t.remove();
14959
+ };
14960
+ t.addEventListener("transitionend", (e) => {
14961
+ e.propertyName === "grid-template-rows" && n();
14962
+ }, { once: !0 }), this.captionExitTimer = setTimeout(n, 360);
14932
14963
  }
14933
14964
  toggleLoop() {
14934
14965
  this.data.loop = this.data.loop === !0 ? void 0 : !0, this.block.dispatchChange(), this.renderState();
package/dist/full.cjs CHANGED
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./chunks/blok-BosfCfPX.cjs`),t=require(`./chunks/constants-ChsAFZ8F.cjs`),n=require(`./chunks/objectSpread2-iNkE6aJh.cjs`),r=require(`./chunks/tools-DmEzyrn3.cjs`);var i={paragraph:{class:r.k,inlineToolbar:!0,config:{preserveBlank:!0}},header:{class:r.O,inlineToolbar:!0},list:{class:r.D,inlineToolbar:!0}},a=n.t(n.t({},i),{},{bold:{class:r.l},italic:{class:r.c},marker:{class:r.o},underline:{class:r.a},strikethrough:{class:r.i},link:{class:r.s}});exports.Blok=e.t,exports.Bold=r.l,exports.DATA_ATTR=t.Pi,exports.Header=r.O,exports.Italic=r.c,exports.Link=r.s,exports.List=r.D,exports.Marker=r.o,exports.Paragraph=r.k,exports.Strikethrough=r.i,exports.Toggle=r.T,exports.Underline=r.a,exports.allTools=a,exports.defaultBlockTools=r.t,exports.defaultInlineTools=r.n,exports.defaultTools=i,exports.version=e.n;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./chunks/blok-gFn3FI95.cjs`),t=require(`./chunks/constants-DmKwEMyC.cjs`),n=require(`./chunks/objectSpread2-iNkE6aJh.cjs`),r=require(`./chunks/tools-BcF1rHBg.cjs`);var i={paragraph:{class:r.k,inlineToolbar:!0,config:{preserveBlank:!0}},header:{class:r.O,inlineToolbar:!0},list:{class:r.D,inlineToolbar:!0}},a=n.t(n.t({},i),{},{bold:{class:r.l},italic:{class:r.c},marker:{class:r.o},underline:{class:r.a},strikethrough:{class:r.i},link:{class:r.s}});exports.Blok=e.t,exports.Bold=r.l,exports.DATA_ATTR=t.Pi,exports.Header=r.O,exports.Italic=r.c,exports.Link=r.s,exports.List=r.D,exports.Marker=r.o,exports.Paragraph=r.k,exports.Strikethrough=r.i,exports.Toggle=r.T,exports.Underline=r.a,exports.allTools=a,exports.defaultBlockTools=r.t,exports.defaultInlineTools=r.n,exports.defaultTools=i,exports.version=e.n;
package/dist/full.mjs CHANGED
@@ -1,7 +1,7 @@
1
- import { n as e, t } from "./chunks/blok-CXB-exXU.mjs";
2
- import { Pi as n } from "./chunks/constants-BmCvHbkL.mjs";
1
+ import { n as e, t } from "./chunks/blok-C52qeiPg.mjs";
2
+ import { Pi as n } from "./chunks/constants-DzQOOvgv.mjs";
3
3
  import { t as r } from "./chunks/objectSpread2-jlBcdYeb.mjs";
4
- import { D as i, O as a, T as o, a as s, c, i as l, k as u, l as d, n as f, o as p, s as m, t as h } from "./chunks/tools-BdoYHyV0.mjs";
4
+ import { D as i, O as a, T as o, a as s, c, i as l, k as u, l as d, n as f, o as p, s as m, t as h } from "./chunks/tools-CelSzJoA.mjs";
5
5
  //#region src/full.ts
6
6
  var g = {
7
7
  paragraph: {
package/dist/react.cjs CHANGED
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`}),require(`./chunks/chunk-BL1yB9zm.cjs`);const e=require(`./chunks/blok-BosfCfPX.cjs`),t=require(`./chunks/objectSpread2-iNkE6aJh.cjs`);let n=require(`react`),r=require(`react/jsx-runtime`);var i=new WeakMap;function a(e,t){i.set(e,t)}function o(e){return i.get(e)}function s(e){i.delete(e)}function c(r,i){let[o,c]=(0,n.useState)(null),u=(0,n.useRef)(r);u.current=r;let d=(0,n.useRef)({editor:null,holder:null,destroyTimeout:null,isDestroyed:!1,depsToken:null}),f=(0,n.useMemo)(()=>({}),i==null?[]:i);(0,n.useEffect)(()=>{if(typeof window>`u`)return;let n=d.current;if(n.destroyTimeout!==null&&(clearTimeout(n.destroyTimeout),n.destroyTimeout=null),n.editor!==null&&!n.isDestroyed&&n.depsToken===f)return c(n.editor),()=>{l(n,c)};if(n.editor!==null&&!n.isDestroyed){s(n.editor);try{n.editor.destroy()}catch(e){}n.editor=null,n.holder=null,n.isDestroyed=!0,c(null)}let r=document.createElement(`div`);n.holder=r,n.isDestroyed=!1,n.depsToken=f;let i=u.current,o=new e.t(t.t(t.t({},i),{},{holder:r,onReady:()=>{var e,t;(e=(t=u.current).onReady)==null||e.call(t)},onChange:(...e)=>{var t,n;(t=(n=u.current).onChange)==null||t.call(n,...e)}}));return n.editor=o,a(o,r),o.isReady.then(()=>{n.editor===o&&!n.isDestroyed&&c(o)}).catch(()=>{if(n.editor===o&&!n.isDestroyed){s(o);try{o.destroy()}catch(e){}n.editor=null,n.holder=null,n.isDestroyed=!0,c(null)}}),()=>{l(n,c)}},[f]);let{readOnly:p}=r;(0,n.useEffect)(()=>{o!==null&&o.readOnly.set(p==null?!1:p)},[o,p]);let{autofocus:m}=r;return(0,n.useEffect)(()=>{o===null||!m||o.focus()},[o,m]),o}function l(e,t){e.destroyTimeout=setTimeout(()=>{if(e.editor!==null){s(e.editor);try{e.editor.destroy()}catch(e){}e.editor=null,e.holder=null,e.isDestroyed=!0,e.destroyTimeout=null,t(null)}},0)}var u=[`editor`],d=(0,n.forwardRef)(function(i,a){let{editor:s}=i,c=e.i(i,u),l=(0,n.useRef)(null);return(0,n.useEffect)(()=>{if(s===null||l.current===null)return;let e=o(s);if(e!==void 0)return l.current.appendChild(e),()=>{e.remove()}},[s]),(0,r.jsx)(`div`,t.t({ref:e=>{if(l.current=e,typeof a==`function`)a(e);else if(a!=null){let t=a;t.current=e}}},c))});exports.BlokContent=d,exports.useBlok=c;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`}),require(`./chunks/chunk-BL1yB9zm.cjs`);const e=require(`./chunks/blok-gFn3FI95.cjs`),t=require(`./chunks/objectSpread2-iNkE6aJh.cjs`);let n=require(`react`),r=require(`react/jsx-runtime`);var i=new WeakMap;function a(e,t){i.set(e,t)}function o(e){return i.get(e)}function s(e){i.delete(e)}function c(r,i){let[o,c]=(0,n.useState)(null),u=(0,n.useRef)(r);u.current=r;let d=(0,n.useRef)({editor:null,holder:null,destroyTimeout:null,isDestroyed:!1,depsToken:null}),f=(0,n.useMemo)(()=>({}),i==null?[]:i);(0,n.useEffect)(()=>{if(typeof window>`u`)return;let n=d.current;if(n.destroyTimeout!==null&&(clearTimeout(n.destroyTimeout),n.destroyTimeout=null),n.editor!==null&&!n.isDestroyed&&n.depsToken===f)return c(n.editor),()=>{l(n,c)};if(n.editor!==null&&!n.isDestroyed){s(n.editor);try{n.editor.destroy()}catch(e){}n.editor=null,n.holder=null,n.isDestroyed=!0,c(null)}let r=document.createElement(`div`);n.holder=r,n.isDestroyed=!1,n.depsToken=f;let i=u.current,o=new e.t(t.t(t.t({},i),{},{holder:r,onReady:()=>{var e,t;(e=(t=u.current).onReady)==null||e.call(t)},onChange:(...e)=>{var t,n;(t=(n=u.current).onChange)==null||t.call(n,...e)}}));return n.editor=o,a(o,r),o.isReady.then(()=>{n.editor===o&&!n.isDestroyed&&c(o)}).catch(()=>{if(n.editor===o&&!n.isDestroyed){s(o);try{o.destroy()}catch(e){}n.editor=null,n.holder=null,n.isDestroyed=!0,c(null)}}),()=>{l(n,c)}},[f]);let{readOnly:p}=r;(0,n.useEffect)(()=>{o!==null&&o.readOnly.set(p==null?!1:p)},[o,p]);let{autofocus:m}=r;return(0,n.useEffect)(()=>{o===null||!m||o.focus()},[o,m]),o}function l(e,t){e.destroyTimeout=setTimeout(()=>{if(e.editor!==null){s(e.editor);try{e.editor.destroy()}catch(e){}e.editor=null,e.holder=null,e.isDestroyed=!0,e.destroyTimeout=null,t(null)}},0)}var u=[`editor`],d=(0,n.forwardRef)(function(i,a){let{editor:s}=i,c=e.i(i,u),l=(0,n.useRef)(null);return(0,n.useEffect)(()=>{if(s===null||l.current===null)return;let e=o(s);if(e!==void 0)return l.current.appendChild(e),()=>{e.remove()}},[s]),(0,r.jsx)(`div`,t.t({ref:e=>{if(l.current=e,typeof a==`function`)a(e);else if(a!=null){let t=a;t.current=e}}},c))});exports.BlokContent=d,exports.useBlok=c;
package/dist/react.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { i as e, t } from "./chunks/blok-CXB-exXU.mjs";
1
+ import { i as e, t } from "./chunks/blok-C52qeiPg.mjs";
2
2
  import { t as n } from "./chunks/objectSpread2-jlBcdYeb.mjs";
3
3
  import { forwardRef as r, useEffect as i, useMemo as a, useRef as o, useState as s } from "react";
4
4
  import { jsx as c } from "react/jsx-runtime";
package/dist/tools.cjs CHANGED
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./chunks/constants-ChsAFZ8F.cjs`),t=require(`./chunks/tools-DmEzyrn3.cjs`);exports.Audio=t.g,exports.Bold=t.l,exports.Bookmark=t.u,exports.Callout=t.w,exports.Code=t.y,exports.Column=t.p,exports.ColumnList=t.m,exports.Columns=t.f,exports.Convert=e.m,exports.Database=t.C,exports.DatabaseRow=t.S,exports.Divider=t.x,exports.Embed=t.d,exports.File=t._,exports.Header=t.O,exports.Image=t.v,exports.InlineCode=t.r,exports.Italic=t.c,exports.Link=t.s,exports.List=t.D,exports.Marker=t.o,exports.Paragraph=t.k,exports.Quote=t.b,exports.Strikethrough=t.i,exports.Table=t.E,exports.Toggle=t.T,exports.Underline=t.a,exports.Video=t.h,exports.defaultBlockTools=t.t,exports.defaultInlineTools=t.n;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./chunks/constants-DmKwEMyC.cjs`),t=require(`./chunks/tools-BcF1rHBg.cjs`);exports.Audio=t.g,exports.Bold=t.l,exports.Bookmark=t.u,exports.Callout=t.w,exports.Code=t.y,exports.Column=t.p,exports.ColumnList=t.m,exports.Columns=t.f,exports.Convert=e.m,exports.Database=t.C,exports.DatabaseRow=t.S,exports.Divider=t.x,exports.Embed=t.d,exports.File=t._,exports.Header=t.O,exports.Image=t.v,exports.InlineCode=t.r,exports.Italic=t.c,exports.Link=t.s,exports.List=t.D,exports.Marker=t.o,exports.Paragraph=t.k,exports.Quote=t.b,exports.Strikethrough=t.i,exports.Table=t.E,exports.Toggle=t.T,exports.Underline=t.a,exports.Video=t.h,exports.defaultBlockTools=t.t,exports.defaultInlineTools=t.n;
package/dist/tools.mjs CHANGED
@@ -1,3 +1,3 @@
1
- import { m as e } from "./chunks/constants-BmCvHbkL.mjs";
2
- import { C as t, D as n, E as r, O as i, S as a, T as o, _ as s, a as c, b as l, c as u, d, f, g as p, h as m, i as h, k as g, l as _, m as v, n as y, o as b, p as x, r as S, s as C, t as w, u as T, v as E, w as D, x as O, y as k } from "./chunks/tools-BdoYHyV0.mjs";
1
+ import { m as e } from "./chunks/constants-DzQOOvgv.mjs";
2
+ import { C as t, D as n, E as r, O as i, S as a, T as o, _ as s, a as c, b as l, c as u, d, f, g as p, h as m, i as h, k as g, l as _, m as v, n as y, o as b, p as x, r as S, s as C, t as w, u as T, v as E, w as D, x as O, y as k } from "./chunks/tools-CelSzJoA.mjs";
3
3
  export { p as Audio, _ as Bold, T as Bookmark, D as Callout, k as Code, x as Column, v as ColumnList, f as Columns, e as Convert, t as Database, a as DatabaseRow, O as Divider, d as Embed, s as File, i as Header, E as Image, S as InlineCode, u as Italic, C as Link, n as List, b as Marker, g as Paragraph, l as Quote, h as Strikethrough, r as Table, o as Toggle, c as Underline, m as Video, w as defaultBlockTools, y as defaultInlineTools };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jackuait/blok",
3
- "version": "0.19.0",
3
+ "version": "0.19.1",
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
  "main": "./dist/blok.cjs",
package/src/blok.ts CHANGED
@@ -36,9 +36,11 @@ class Blok {
36
36
  private readonly initialConfiguration: BlokConfig|string|undefined;
37
37
 
38
38
  /**
39
- * Promise that resolves when core modules are ready and UI is rendered on the page
39
+ * Promise that resolves when core modules are ready and UI is rendered on the page.
40
+ * Resolves with the fully-initialized Blok instance, so awaiting it narrows a
41
+ * pre-ready reference (see {@link PendingBlok}) to the complete API surface.
40
42
  */
41
- public isReady: Promise<void>;
43
+ public isReady: Promise<Blok>;
42
44
 
43
45
  /**
44
46
  * Stores destroy method implementation.
@@ -218,7 +220,7 @@ class Blok {
218
220
 
219
221
  Object.setPrototypeOf(this, null);
220
222
 
221
- return;
223
+ return this;
222
224
  }
223
225
 
224
226
  this.exportAPI(blok);
@@ -276,6 +278,8 @@ class Blok {
276
278
  * @todo pass API as an argument. It will allow to use Blok's API when blok is ready
277
279
  */
278
280
  onReady();
281
+
282
+ return this;
279
283
  });
280
284
  }
281
285
 
@@ -385,20 +385,38 @@
385
385
  color: var(--blok-text-primary);
386
386
  }
387
387
 
388
- /* ----- caption row (full-width footer) -------------------- */
388
+ /* ----- caption row (full-width footer) --------------------
389
+ The row is a single-track grid wrapper so it can collapse to zero height
390
+ (grid-template-rows 1fr → 0fr) when the caption is toggled, while the inner
391
+ element holds the actual padding/border that fade out with it. */
389
392
  [data-blok-tool="audio"] .blok-audio-caption-row {
390
393
  grid-column: 1 / -1;
391
394
  grid-row: 2;
395
+ display: grid;
396
+ grid-template-rows: 1fr;
397
+ transition:
398
+ grid-template-rows var(--blok-duration-slow) var(--blok-ease-popover),
399
+ opacity var(--blok-duration-slow) var(--blok-ease-popover);
400
+ }
401
+ [data-blok-tool="audio"] .blok-audio-caption-row.is-collapsed {
402
+ grid-template-rows: 0fr;
403
+ opacity: 0;
404
+ }
405
+ /* overflow:hidden + min-height:0 lets the grid track collapse fully to 0; the
406
+ padding/border live on the caption child below so they get clipped too. */
407
+ [data-blok-tool="audio"] .blok-audio-caption-row__inner {
408
+ min-height: 0;
409
+ overflow: hidden;
392
410
  display: flex;
393
411
  align-items: flex-start;
394
412
  gap: var(--blok-space-2);
395
- padding-top: var(--blok-space-2-5);
396
- border-top: 1px solid var(--blok-border-subtle);
397
413
  }
398
414
  [data-blok-tool="audio"] .blok-audio-caption {
399
415
  flex: 1 1 auto;
400
416
  min-width: 0;
401
417
  display: block;
418
+ padding-top: var(--blok-space-2-5);
419
+ border-top: 1px solid var(--blok-border-subtle);
402
420
  font-size: var(--blok-font-size-ui-label);
403
421
  color: var(--blok-text-secondary);
404
422
  line-height: var(--blok-line-height-body);
@@ -528,4 +546,6 @@
528
546
  }
529
547
  /* The badge still appears while playing — it just holds steady. */
530
548
  [data-blok-tool="audio"] .blok-audio-eq { transition: none; }
549
+ /* Caption appears/disappears instantly (JS also takes the instant path). */
550
+ [data-blok-tool="audio"] .blok-audio-caption-row { transition: none; }
531
551
  }
@@ -52,6 +52,8 @@ export class AudioTool implements BlockTool {
52
52
  private controlsHandle: ControlsHandle | null = null;
53
53
  private waveformHandle: WaveformHandle | null = null;
54
54
  private destroyed = false;
55
+ /** Pending fallback timer for the caption collapse-out animation. */
56
+ private captionExitTimer: ReturnType<typeof setTimeout> | null = null;
55
57
 
56
58
  constructor(options: BlockToolConstructorOptions<AudioData, AudioConfig>) {
57
59
  this.api = options.api;
@@ -199,6 +201,7 @@ export class AudioTool implements BlockTool {
199
201
 
200
202
  public removed(): void {
201
203
  this.destroyed = true;
204
+ if (this.captionExitTimer) { clearTimeout(this.captionExitTimer); this.captionExitTimer = null; }
202
205
  this.controlsHandle?.destroy();
203
206
  this.controlsHandle = null;
204
207
  this.waveformHandle?.destroy();
@@ -299,6 +302,7 @@ export class AudioTool implements BlockTool {
299
302
 
300
303
  private renderState(): void {
301
304
  if (!this.root) return;
305
+ if (this.captionExitTimer) { clearTimeout(this.captionExitTimer); this.captionExitTimer = null; }
302
306
  this.controlsHandle?.destroy();
303
307
  this.controlsHandle = null;
304
308
  this.waveformHandle?.destroy();
@@ -393,14 +397,9 @@ export class AudioTool implements BlockTool {
393
397
  body.appendChild(this.controlsHandle.element);
394
398
 
395
399
  // Caption row — outside body, below the card
396
- const placeholder = this.config.captionPlaceholder ?? DEFAULT_CAPTION_PLACEHOLDER;
397
400
  const captionVisible = this.data.captionVisible !== false;
398
- if (captionVisible || !this.readOnly) {
399
- figure.appendChild(renderCaptionRow({
400
- value: this.data.caption ?? '',
401
- placeholder,
402
- editable: !this.readOnly,
403
- }));
401
+ if (captionVisible) {
402
+ figure.appendChild(this.createCaptionRow());
404
403
  }
405
404
 
406
405
  // Wire title/artist blur handlers
@@ -419,21 +418,32 @@ export class AudioTool implements BlockTool {
419
418
  }
420
419
  });
421
420
 
422
- // Wire caption blur handler
423
- const captionEl = figure.querySelector<HTMLElement>('[data-role="audio-caption"]');
424
- if (captionEl) {
425
- captionEl.addEventListener('blur', () => {
426
- const next = captionEl.textContent ?? '';
427
- if (next !== this.data.caption) {
428
- this.data.caption = next || undefined;
429
- this.block.dispatchChange();
430
- }
431
- });
432
- }
433
-
434
421
  this.root.appendChild(figure);
435
422
  }
436
423
 
424
+ /** Build a caption row (with its blur handler wired) ready to mount. */
425
+ private createCaptionRow(): HTMLElement {
426
+ const placeholder = this.config.captionPlaceholder ?? DEFAULT_CAPTION_PLACEHOLDER;
427
+ const row = renderCaptionRow({
428
+ value: this.data.caption ?? '',
429
+ placeholder,
430
+ editable: !this.readOnly,
431
+ });
432
+ const captionEl = row.querySelector<HTMLElement>('[data-role="audio-caption"]');
433
+ captionEl?.addEventListener('blur', () => {
434
+ const next = captionEl.textContent ?? '';
435
+ if (next !== this.data.caption) {
436
+ this.data.caption = next || undefined;
437
+ this.block.dispatchChange();
438
+ }
439
+ });
440
+ return row;
441
+ }
442
+
443
+ private prefersReducedMotion(): boolean {
444
+ return globalThis.matchMedia?.('(prefers-reduced-motion: reduce)').matches ?? false;
445
+ }
446
+
437
447
  private setAlignment(next: AudioAlignment): void {
438
448
  if (this.data.alignment === next) return;
439
449
  this.data.alignment = next;
@@ -442,9 +452,54 @@ export class AudioTool implements BlockTool {
442
452
  }
443
453
 
444
454
  private toggleCaption(): void {
445
- this.data.captionVisible = this.data.captionVisible === false;
455
+ const enabling = this.data.captionVisible === false;
456
+ this.data.captionVisible = enabling;
457
+ // Removing the caption clears its text too, so re-enabling starts fresh
458
+ // rather than resurrecting the old text.
459
+ if (!enabling) this.data.caption = undefined;
446
460
  this.block.dispatchChange();
447
- this.renderState();
461
+
462
+ const figure = this.root?.querySelector<HTMLElement>('[data-role="audio-figure"]');
463
+ // No live card to animate (or motion is off) — fall back to an instant
464
+ // re-render so the caption snaps in/out.
465
+ if (!figure || this.prefersReducedMotion()) {
466
+ this.renderState();
467
+ return;
468
+ }
469
+ this.syncRootAttributes();
470
+ if (enabling) this.animateCaptionIn(figure);
471
+ else this.animateCaptionOut(figure);
472
+ }
473
+
474
+ private animateCaptionIn(figure: HTMLElement): void {
475
+ const existing = figure.querySelector<HTMLElement>('[data-role="audio-caption-row"]');
476
+ if (existing) {
477
+ // A collapse-out was mid-flight — cancel it and re-open in place.
478
+ if (this.captionExitTimer) { clearTimeout(this.captionExitTimer); this.captionExitTimer = null; }
479
+ existing.classList.remove('is-collapsed');
480
+ return;
481
+ }
482
+ const row = this.createCaptionRow();
483
+ row.classList.add('is-collapsed');
484
+ figure.appendChild(row);
485
+ // Force a reflow so the collapsed state is committed, then expand into view.
486
+ void row.offsetHeight;
487
+ row.classList.remove('is-collapsed');
488
+ }
489
+
490
+ private animateCaptionOut(figure: HTMLElement): void {
491
+ const row = figure.querySelector<HTMLElement>('[data-role="audio-caption-row"]');
492
+ if (!row) return;
493
+ row.classList.add('is-collapsed');
494
+ const finish = (): void => {
495
+ if (this.captionExitTimer) { clearTimeout(this.captionExitTimer); this.captionExitTimer = null; }
496
+ row.remove();
497
+ };
498
+ row.addEventListener('transitionend', (e) => {
499
+ if (e.propertyName === 'grid-template-rows') finish();
500
+ }, { once: true });
501
+ // Fallback in case transitionend never fires (display:none, interrupted, etc.).
502
+ this.captionExitTimer = setTimeout(finish, 360);
448
503
  }
449
504
 
450
505
  private toggleLoop(): void {
@@ -97,8 +97,13 @@ export function renderCaptionRow(opts: CaptionRowOptions): HTMLElement {
97
97
  const row = document.createElement('div');
98
98
  row.className = 'blok-audio-caption-row';
99
99
  row.setAttribute('data-role', 'audio-caption-row');
100
+ // Inner wrapper carries the visible layout (padding/border) so the row itself
101
+ // can collapse cleanly via grid-template-rows when toggled.
102
+ const inner = document.createElement('div');
103
+ inner.className = 'blok-audio-caption-row__inner';
100
104
  const cap = editableLine('audio-caption', opts.value, opts.editable, opts.placeholder);
101
105
  cap.className = 'blok-audio-caption';
102
- row.appendChild(cap);
106
+ inner.appendChild(cap);
107
+ row.appendChild(inner);
103
108
  return row;
104
109
  }
package/types/index.d.ts CHANGED
@@ -207,11 +207,37 @@ export function wrapLegacyInlineTool(
207
207
  }
208
208
  ): InlineToolConstructable;
209
209
 
210
+ /**
211
+ * The surface of a Blok instance that is guaranteed to exist synchronously,
212
+ * immediately after `new Blok()` and before `isReady` has resolved.
213
+ *
214
+ * Blok constructs its module APIs (`blocks`, `caret`, `history`, `readOnly`, …)
215
+ * asynchronously: they only become available once `isReady` resolves. Accessing
216
+ * them earlier returns `undefined` at runtime. Type a reference you hold during
217
+ * that window as `PendingBlok` so the not-yet-available members are unreachable,
218
+ * then await `isReady` to obtain the fully-initialized {@link Blok}:
219
+ *
220
+ * @example
221
+ * const pending: PendingBlok = new Blok(config);
222
+ * const editor = await pending.isReady; // editor is a ready Blok
223
+ * editor.blocks.render(data);
224
+ */
225
+ export interface PendingBlok {
226
+ /** Resolves with the fully-initialized Blok instance once core modules are ready. */
227
+ isReady: Promise<Blok>;
228
+ /** Destroy the instance. Safe to call before `isReady` resolves. */
229
+ destroy(): void;
230
+ /** Theme API, exposed immediately after construction. */
231
+ theme: Theme;
232
+ /** Width API, exposed immediately after construction. */
233
+ width: Width;
234
+ }
235
+
210
236
  /**
211
237
  * Main Blok class
212
238
  */
213
239
  export class Blok {
214
- public isReady: Promise<void>;
240
+ public isReady: Promise<Blok>;
215
241
 
216
242
  public blocks: Blocks;
217
243
  public caret: Caret;