@jackuait/blok 0.12.0 → 0.12.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.
Files changed (46) hide show
  1. package/dist/blok.cjs +1 -1
  2. package/dist/blok.iife.js +5 -5
  3. package/dist/blok.mjs +2 -2
  4. package/dist/chunks/{blok-Cxcy7G7v.mjs → blok-B4ebnd6l.mjs} +58 -6
  5. package/dist/chunks/{blok-qY4LDF7A.cjs → blok-k8Yo4v2F.cjs} +4 -4
  6. package/dist/chunks/{constants-Bhk7u_hm.mjs → constants-BsyOzSoJ.mjs} +1 -1
  7. package/dist/chunks/{constants-BYCpx4v_.cjs → constants-DGaNl2M0.cjs} +1 -1
  8. package/dist/chunks/tools-CPzDYrWa.cjs +115 -0
  9. package/dist/chunks/{tools-Bc4e0xmz.mjs → tools-JNr7LO1_.mjs} +888 -883
  10. package/dist/full.cjs +1 -1
  11. package/dist/full.mjs +3 -3
  12. package/dist/react.cjs +1 -1
  13. package/dist/react.mjs +2 -2
  14. package/dist/tools.cjs +1 -1
  15. package/dist/tools.mjs +2 -2
  16. package/package.json +2 -2
  17. package/src/components/block-tunes/block-tune-copy-link.ts +2 -2
  18. package/src/components/modules/paste/index.ts +154 -2
  19. package/src/styles/colors.css +57 -0
  20. package/src/styles/database.css +3 -3
  21. package/src/styles/image.css +50 -140
  22. package/src/styles/main.css +148 -6
  23. package/src/tools/callout/index.ts +0 -1
  24. package/src/tools/code/index.ts +19 -2
  25. package/src/tools/database/database-board-view.ts +1 -1
  26. package/src/tools/database/database-card-drawer.ts +3 -2
  27. package/src/tools/database/database-list-view.ts +1 -1
  28. package/src/tools/database/database-model.ts +15 -3
  29. package/src/tools/database/database-property-type-popover.ts +14 -10
  30. package/src/tools/database/database-tab-bar.ts +9 -3
  31. package/src/tools/database/database-view-popover.ts +15 -7
  32. package/src/tools/database/index.ts +0 -2
  33. package/src/tools/header/index.ts +6 -6
  34. package/src/tools/image/alt-popover.css +6 -6
  35. package/src/tools/image/crop-editor.css +34 -34
  36. package/src/tools/image/crop-modal.css +1 -1
  37. package/src/tools/image/empty-state.ts +3 -3
  38. package/src/tools/image/error-state.ts +9 -9
  39. package/src/tools/image/index.ts +2 -3
  40. package/src/tools/image/ui.ts +18 -13
  41. package/src/tools/list/style-config.ts +0 -3
  42. package/src/tools/paragraph/index.ts +0 -1
  43. package/src/tools/quote/index.ts +0 -1
  44. package/src/tools/table/index.ts +0 -1
  45. package/src/tools/toggle/index.ts +0 -1
  46. package/dist/chunks/tools-DaOdAh89.cjs +0 -115
package/dist/full.cjs CHANGED
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`}),require(`./chunks/chunk-Kud-AIAt.cjs`);const e=require(`./chunks/blok-qY4LDF7A.cjs`),t=require(`./chunks/constants-BYCpx4v_.cjs`),n=require(`./chunks/objectSpread2-iNkE6aJh.cjs`),r=require(`./chunks/tools-DaOdAh89.cjs`);var i={paragraph:{class:r.x,inlineToolbar:!0,config:{preserveBlank:!0}},header:{class:r.b,inlineToolbar:!0},list:{class:r.y,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.Pr,exports.Header=r.b,exports.Italic=r.c,exports.Link=r.s,exports.List=r.y,exports.Marker=r.o,exports.Paragraph=r.x,exports.Strikethrough=r.i,exports.Toggle=r._,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`}),require(`./chunks/chunk-Kud-AIAt.cjs`);const e=require(`./chunks/blok-k8Yo4v2F.cjs`),t=require(`./chunks/constants-DGaNl2M0.cjs`),n=require(`./chunks/objectSpread2-iNkE6aJh.cjs`),r=require(`./chunks/tools-CPzDYrWa.cjs`);var i={paragraph:{class:r.x,inlineToolbar:!0,config:{preserveBlank:!0}},header:{class:r.b,inlineToolbar:!0},list:{class:r.y,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.Pr,exports.Header=r.b,exports.Italic=r.c,exports.Link=r.s,exports.List=r.y,exports.Marker=r.o,exports.Paragraph=r.x,exports.Strikethrough=r.i,exports.Toggle=r._,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-Cxcy7G7v.mjs";
2
- import { Pr as n } from "./chunks/constants-Bhk7u_hm.mjs";
1
+ import { n as e, t } from "./chunks/blok-B4ebnd6l.mjs";
2
+ import { Pr as n } from "./chunks/constants-BsyOzSoJ.mjs";
3
3
  import { t as r } from "./chunks/objectSpread2-CWwMYL_U.mjs";
4
- import { _ as i, a, b as o, c as s, i as c, l, n as u, o as d, s as f, t as p, x as m, y as h } from "./chunks/tools-Bc4e0xmz.mjs";
4
+ import { _ as i, a, b as o, c as s, i as c, l, n as u, o as d, s as f, t as p, x as m, y as h } from "./chunks/tools-JNr7LO1_.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-Kud-AIAt.cjs`);const e=require(`./chunks/blok-qY4LDF7A.cjs`);require(`./chunks/constants-BYCpx4v_.cjs`);const 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.r(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-Kud-AIAt.cjs`);const e=require(`./chunks/blok-k8Yo4v2F.cjs`);require(`./chunks/constants-DGaNl2M0.cjs`);const 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.r(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,5 +1,5 @@
1
- import { r as e, t } from "./chunks/blok-Cxcy7G7v.mjs";
2
- import "./chunks/constants-Bhk7u_hm.mjs";
1
+ import { r as e, t } from "./chunks/blok-B4ebnd6l.mjs";
2
+ import "./chunks/constants-BsyOzSoJ.mjs";
3
3
  import { t as n } from "./chunks/objectSpread2-CWwMYL_U.mjs";
4
4
  import { forwardRef as r, useEffect as i, useMemo as a, useRef as o, useState as s } from "react";
5
5
  import { jsx as c } from "react/jsx-runtime";
package/dist/tools.cjs CHANGED
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`}),require(`./chunks/chunk-Kud-AIAt.cjs`);const e=require(`./chunks/constants-BYCpx4v_.cjs`),t=require(`./chunks/tools-DaOdAh89.cjs`);exports.Bold=t.l,exports.Callout=t.g,exports.Code=t.d,exports.Convert=e.m,exports.Database=t.h,exports.DatabaseRow=t.m,exports.Divider=t.p,exports.Header=t.b,exports.Image=t.u,exports.InlineCode=t.r,exports.Italic=t.c,exports.Link=t.s,exports.List=t.y,exports.Marker=t.o,exports.Paragraph=t.x,exports.Quote=t.f,exports.Strikethrough=t.i,exports.Table=t.v,exports.Toggle=t._,exports.Underline=t.a,exports.defaultBlockTools=t.t,exports.defaultInlineTools=t.n;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`}),require(`./chunks/chunk-Kud-AIAt.cjs`);const e=require(`./chunks/constants-DGaNl2M0.cjs`),t=require(`./chunks/tools-CPzDYrWa.cjs`);exports.Bold=t.l,exports.Callout=t.g,exports.Code=t.d,exports.Convert=e.m,exports.Database=t.h,exports.DatabaseRow=t.m,exports.Divider=t.p,exports.Header=t.b,exports.Image=t.u,exports.InlineCode=t.r,exports.Italic=t.c,exports.Link=t.s,exports.List=t.y,exports.Marker=t.o,exports.Paragraph=t.x,exports.Quote=t.f,exports.Strikethrough=t.i,exports.Table=t.v,exports.Toggle=t._,exports.Underline=t.a,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-Bhk7u_hm.mjs";
2
- import { _ as t, a as n, b as r, c as i, d as a, f as o, g as s, h as c, i as l, l as u, m as d, n as f, o as p, p as m, r as h, s as g, t as _, u as v, v as y, x as b, y as x } from "./chunks/tools-Bc4e0xmz.mjs";
1
+ import { m as e } from "./chunks/constants-BsyOzSoJ.mjs";
2
+ import { _ as t, a as n, b as r, c as i, d as a, f as o, g as s, h as c, i as l, l as u, m as d, n as f, o as p, p as m, r as h, s as g, t as _, u as v, v as y, x as b, y as x } from "./chunks/tools-JNr7LO1_.mjs";
3
3
  export { u as Bold, s as Callout, a as Code, e as Convert, c as Database, d as DatabaseRow, m as Divider, r as Header, v as Image, h as InlineCode, i as Italic, g as Link, x as List, p as Marker, b as Paragraph, o as Quote, l as Strikethrough, y as Table, t as Toggle, n as Underline, _ as defaultBlockTools, f as defaultInlineTools };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jackuait/blok",
3
- "version": "0.12.0",
3
+ "version": "0.12.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",
@@ -129,7 +129,7 @@
129
129
  "validate:spec-coverage": "node scripts/validate-spec-file-coverage.mjs",
130
130
  "ci:timing": "node scripts/ci-timing-probe.mjs",
131
131
  "release": "node scripts/release.mjs",
132
- "release:preflight": "yarn lint",
132
+ "release:preflight": "yarn lint && yarn test",
133
133
  "unused-css": "node scripts/unused-css-finder/cli.mjs"
134
134
  },
135
135
  "author": "JackUait",
@@ -74,9 +74,9 @@ export class CopyLinkTune implements BlockTune {
74
74
 
75
75
  try {
76
76
  await navigator.clipboard.writeText(url);
77
- this.api.notifier.show({ message: 'Link copied to clipboard', style: 'success', time: 2000 });
77
+ this.api.notifier.show({ message: this.api.i18n.t('blockSettings.copyLinkSuccess'), style: 'success', time: 2000 });
78
78
  } catch {
79
- this.api.notifier.show({ message: 'Could not copy link to block', style: 'error', time: 3000 });
79
+ this.api.notifier.show({ message: this.api.i18n.t('blockSettings.copyLinkError'), style: 'error', time: 3000 });
80
80
  }
81
81
  }
82
82
  }
@@ -261,14 +261,24 @@ export class Paste extends Module {
261
261
  * Set onPaste callback handler.
262
262
  */
263
263
  private setCallback(): void {
264
- this.listeners.on(this.Blok.UI.nodes.holder, 'paste', this.handlePasteEventWrapper);
264
+ const holder = this.Blok.UI.nodes.holder;
265
+
266
+ this.listeners.on(holder, 'paste', this.handlePasteEventWrapper);
267
+ this.listeners.on(holder, 'drop', this.handleDropEventWrapper);
268
+ this.listeners.on(holder, 'dragover', this.handleDragOverEventWrapper);
269
+ this.listeners.on(holder, 'dragleave', this.handleDragLeaveEventWrapper);
265
270
  }
266
271
 
267
272
  /**
268
273
  * Unset onPaste callback handler.
269
274
  */
270
275
  private unsetCallback(): void {
271
- this.listeners.off(this.Blok.UI.nodes.holder, 'paste', this.handlePasteEventWrapper);
276
+ const holder = this.Blok.UI.nodes.holder;
277
+
278
+ this.listeners.off(holder, 'paste', this.handlePasteEventWrapper);
279
+ this.listeners.off(holder, 'drop', this.handleDropEventWrapper);
280
+ this.listeners.off(holder, 'dragover', this.handleDragOverEventWrapper);
281
+ this.listeners.off(holder, 'dragleave', this.handleDragLeaveEventWrapper);
272
282
  }
273
283
 
274
284
  /**
@@ -278,6 +288,148 @@ export class Paste extends Module {
278
288
  void this.handlePasteEvent(event as ClipboardEvent);
279
289
  };
280
290
 
291
+ private handleDropEventWrapper = (event: Event): void => {
292
+ void this.handleDropEvent(event as DragEvent);
293
+ };
294
+
295
+ private handleDragOverEventWrapper = (event: Event): void => {
296
+ this.handleDragOverEvent(event as DragEvent);
297
+ };
298
+
299
+ private handleDragLeaveEventWrapper = (event: Event): void => {
300
+ this.handleDragLeaveEvent(event as DragEvent);
301
+ };
302
+
303
+ private dataTransferHasFiles(dataTransfer: DataTransfer | null | undefined): boolean {
304
+ if (!dataTransfer) {
305
+ return false;
306
+ }
307
+
308
+ const types = Array.from(dataTransfer.types ?? []);
309
+
310
+ if (types.includes('Files')) {
311
+ return true;
312
+ }
313
+
314
+ return Boolean(dataTransfer.files?.length);
315
+ }
316
+
317
+ private dropIndicatorHolder: HTMLElement | null = null;
318
+
319
+ private handleDragOverEvent = (event: DragEvent): void => {
320
+ const { dataTransfer } = event;
321
+
322
+ if (!this.dataTransferHasFiles(dataTransfer)) {
323
+ return;
324
+ }
325
+
326
+ event.preventDefault();
327
+
328
+ if (dataTransfer) {
329
+ dataTransfer.dropEffect = 'copy';
330
+ }
331
+
332
+ this.updateDropIndicator(event);
333
+ };
334
+
335
+ private updateDropIndicator(event: DragEvent): void {
336
+ const target = event.target instanceof Element ? event.target : null;
337
+ const blockHolder = target?.closest('[data-blok-element]');
338
+
339
+ if (!(blockHolder instanceof HTMLElement)) {
340
+ this.clearDropIndicator();
341
+
342
+ return;
343
+ }
344
+
345
+ const rect = blockHolder.getBoundingClientRect();
346
+ const edge = event.clientY < rect.top + rect.height / 2 ? 'top' : 'bottom';
347
+
348
+ if (this.dropIndicatorHolder && this.dropIndicatorHolder !== blockHolder) {
349
+ this.dropIndicatorHolder.removeAttribute('data-drop-indicator');
350
+ this.dropIndicatorHolder.style.removeProperty('--drop-indicator-depth');
351
+ }
352
+
353
+ blockHolder.setAttribute('data-drop-indicator', edge);
354
+ blockHolder.style.setProperty('--drop-indicator-depth', String(this.computeDropDepth(blockHolder)));
355
+ this.dropIndicatorHolder = blockHolder;
356
+ }
357
+
358
+ private computeDropDepth(blockHolder: HTMLElement): number {
359
+ const ancestorBlocks = blockHolder.parentElement?.closest('[data-blok-element]')
360
+ ? this.countAncestorBlocks(blockHolder)
361
+ : 0;
362
+
363
+ const listWrapper = blockHolder.querySelector('[data-list-depth]');
364
+ const listDepthRaw = listWrapper?.getAttribute('data-list-depth') ?? '0';
365
+ const listDepth = Number.parseInt(listDepthRaw, 10);
366
+ const listContribution = Number.isNaN(listDepth) ? 0 : listDepth;
367
+
368
+ return ancestorBlocks + listContribution;
369
+ }
370
+
371
+ private countAncestorBlocks(blockHolder: HTMLElement): number {
372
+ const parent = blockHolder.parentElement?.closest('[data-blok-element]') as HTMLElement | null;
373
+
374
+ if (!parent) {
375
+ return 0;
376
+ }
377
+
378
+ return 1 + this.countAncestorBlocks(parent);
379
+ }
380
+
381
+ private clearDropIndicator(): void {
382
+ if (this.dropIndicatorHolder) {
383
+ this.dropIndicatorHolder.removeAttribute('data-drop-indicator');
384
+ this.dropIndicatorHolder.style.removeProperty('--drop-indicator-depth');
385
+ this.dropIndicatorHolder = null;
386
+ }
387
+ }
388
+
389
+ private handleDragLeaveEvent = (event: DragEvent): void => {
390
+ const holder = this.Blok.UI.nodes.holder;
391
+ const related = event.relatedTarget as Node | null;
392
+
393
+ if (related && holder.contains(related)) {
394
+ return;
395
+ }
396
+
397
+ this.clearDropIndicator();
398
+ };
399
+
400
+ private handleDropEvent = async (event: DragEvent): Promise<void> => {
401
+ this.clearDropIndicator();
402
+
403
+ if (this.Blok.DragManager?.isDragging) {
404
+ return;
405
+ }
406
+
407
+ if (!this.dataTransferHasFiles(event.dataTransfer)) {
408
+ return;
409
+ }
410
+
411
+ event.preventDefault();
412
+
413
+ const { BlockManager, Toolbar } = this.Blok;
414
+ const currentBlock = BlockManager.setCurrentBlockByChildNode(event.target as HTMLElement);
415
+
416
+ if (!currentBlock) {
417
+ return;
418
+ }
419
+
420
+ if (this.toolRegistry.isException(currentBlock.name)) {
421
+ return;
422
+ }
423
+
424
+ if (event.dataTransfer) {
425
+ const dropTarget = event.target instanceof Element ? event.target : undefined;
426
+
427
+ await this.processDataTransfer(event.dataTransfer, dropTarget);
428
+ }
429
+
430
+ Toolbar.moveAndOpen();
431
+ };
432
+
281
433
  /**
282
434
  * Check if browser behavior suits better.
283
435
  */
@@ -265,19 +265,31 @@
265
265
  --blok-handle-fg-default: rgba(255, 255, 255, 0.85);
266
266
 
267
267
  /* Spacing scale — 4px base, aligned with Tailwind's default spacing scale. */
268
+ --blok-space-0: 0;
269
+ --blok-space-0-25: 1px;
268
270
  --blok-space-0-5: 2px;
271
+ --blok-space-0-75: 3px;
269
272
  --blok-space-1: 4px;
270
273
  --blok-space-1-25: 5px;
271
274
  --blok-space-1-5: 6px;
272
275
  --blok-space-1-75: 7px;
273
276
  --blok-space-2: 8px;
277
+ --blok-space-2-25: 9px;
274
278
  --blok-space-2-5: 10px;
279
+ --blok-space-2-75: 11px;
275
280
  --blok-space-3: 12px;
281
+ --blok-space-3-25: 13px;
282
+ --blok-space-3-5: 14px;
276
283
  --blok-space-4: 16px;
284
+ --blok-space-4-5: 18px;
277
285
  --blok-space-5: 20px;
278
286
  --blok-space-6: 24px;
279
287
  --blok-space-10: 40px;
280
288
 
289
+ /* Micro radii for the crop-editor handle notches. */
290
+ --blok-radius-hairline: 1.5px;
291
+ --blok-radius-none: 0;
292
+
281
293
  /* Icon sizing (non-scale, role-based). */
282
294
  --blok-size-icon-sm: 18px;
283
295
  --blok-size-icon-md: 22px;
@@ -335,6 +347,51 @@
335
347
  --blok-line-height-tight: 1;
336
348
  --blok-line-height-body: 1.45;
337
349
  --blok-line-height-option: 1.3;
350
+
351
+ /*
352
+ Generic surface / accent hooks consumed with a fallback by plugin-owned
353
+ CSS (image lightbox, alt popover, crop editor). Declared here so the
354
+ var-resolution audit sees them as valid tokens.
355
+ */
356
+ --blok-accent: var(--blok-color-accent);
357
+ --blok-bg-tertiary: var(--blok-bg-light);
358
+ --blok-surface-muted: rgba(255, 255, 255, 0.05);
359
+ --blok-surface-strong: #1e1e1e;
360
+
361
+ /* Image lightbox chrome (dark, independent of page theme). */
362
+ --blok-image-lightbox-backdrop: rgba(25, 25, 24, 0.92);
363
+ --blok-image-lightbox-toolbar-bg: #252525;
364
+ --blok-image-lightbox-toolbar-fg: #e2e0dc;
365
+ --blok-image-lightbox-toolbar-ring: rgba(255, 255, 255, 0.14);
366
+ --blok-image-lightbox-toolbar-shadow-main: rgba(0, 0, 0, 0.5);
367
+ --blok-image-lightbox-toolbar-shadow-ambient: rgba(0, 0, 0, 0.4);
368
+ --blok-image-lightbox-btn-hover-bg: rgba(255, 255, 255, 0.055);
369
+ --blok-image-lightbox-btn-active-bg: rgba(255, 255, 255, 0.09);
370
+ --blok-image-lightbox-divider-bg: rgba(255, 255, 255, 0.1);
371
+ --blok-image-lightbox-caption-fg: #a39e98;
372
+ --blok-image-lightbox-shortcut-fg: rgba(255, 255, 255, 0.45);
373
+
374
+ /* Image empty-state embed submit (high-contrast fg on accent). */
375
+ --blok-image-embed-submit-fg: #fff;
376
+
377
+ /* Crop editor composite-shadow leaf literals. */
378
+ --blok-crop-rect-drop-shadow: 0 8px 32px -8px rgba(0, 0, 0, 0.8);
379
+ --blok-crop-handle-edge-drop-shadow: 0 1px 4px rgba(0, 0, 0, 0.25);
380
+ --blok-crop-handle-edge-halo: 0 0 0 3px rgba(255, 255, 255, 0.18);
381
+ --blok-crop-handle-edge-drop-hover: 0 2px 6px rgba(0, 0, 0, 0.3);
382
+ --blok-crop-pill-fg: #fff;
383
+
384
+ /* Alt-popover surface composite shadow (dark surface). */
385
+ --blok-alt-popover-shadow: 0 12px 32px rgba(0, 0, 0, 0.35);
386
+
387
+ /* Image error-state inset highlight. */
388
+ --blok-image-error-inset-highlight: #fff;
389
+
390
+ /* Crop-modal button shadow. */
391
+ --blok-crop-modal-btn-shadow: rgba(0, 0, 0, 0.3);
392
+
393
+ /* Image error-state radius (slightly larger than --blok-radius-md). */
394
+ --blok-radius-md-plus: 8px;
338
395
  }
339
396
 
340
397
  /* ─── Dark theme — system preference ────────────────── */
@@ -363,7 +363,7 @@
363
363
  padding: var(--blok-space-1);
364
364
  border-radius: var(--blok-space-1);
365
365
  color: var(--blok-database-add-text);
366
- gap: -4px;
366
+ gap: calc(-1 * var(--blok-space-1));
367
367
  }
368
368
 
369
369
  [data-blok-database-drawer-close]:hover {
@@ -373,7 +373,7 @@
373
373
  [data-blok-database-drawer-close] svg {
374
374
  width: 14px;
375
375
  height: 14px;
376
- margin-left: -6px;
376
+ margin-left: calc(-1 * var(--blok-space-1-5));
377
377
  }
378
378
 
379
379
  [data-blok-database-drawer-close] svg:first-child {
@@ -699,7 +699,7 @@
699
699
  justify-content: center;
700
700
  width: 30px;
701
701
  height: 30px;
702
- border-radius: 7px;
702
+ border-radius: var(--blok-space-1-75);
703
703
  background: var(--blok-database-popover-hover);
704
704
  color: var(--blok-database-tab-text-active);
705
705
  flex-shrink: 0;