@pod-os/elements 0.31.1-rc.4c5bdf8.0 → 0.31.1-rc.85d0b38.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -16873,9 +16873,13 @@ var ExtensionManager = class {
16873
16873
  if (!addNodeView) {
16874
16874
  return [];
16875
16875
  }
16876
+ const nodeViewResult = addNodeView();
16877
+ if (!nodeViewResult) {
16878
+ return [];
16879
+ }
16876
16880
  const nodeview = (node, view, getPos, decorations, innerDecorations) => {
16877
16881
  const HTMLAttributes = getRenderedAttributes(node, extensionAttributes);
16878
- return addNodeView()({
16882
+ return nodeViewResult({
16879
16883
  // pass-through
16880
16884
  node,
16881
16885
  view,
@@ -17615,6 +17619,7 @@ var Editor = class extends EventEmitter {
17615
17619
  constructor(options = {}) {
17616
17620
  super();
17617
17621
  this.css = null;
17622
+ this.className = "tiptap";
17618
17623
  this.editorView = null;
17619
17624
  this.isFocused = false;
17620
17625
  /**
@@ -17727,7 +17732,7 @@ var Editor = class extends EventEmitter {
17727
17732
  }
17728
17733
  this.editorView = null;
17729
17734
  this.isInitialized = false;
17730
- if (this.css) {
17735
+ if (this.css && !document.querySelectorAll(`.${this.className}`).length) {
17731
17736
  try {
17732
17737
  if (typeof this.css.remove === "function") {
17733
17738
  this.css.remove();
@@ -18007,7 +18012,7 @@ var Editor = class extends EventEmitter {
18007
18012
  * Prepend class name to element.
18008
18013
  */
18009
18014
  prependClass() {
18010
- this.view.dom.className = `tiptap ${this.view.dom.className}`;
18015
+ this.view.dom.className = `${this.className} ${this.view.dom.className}`;
18011
18016
  }
18012
18017
  captureTransaction(fn) {
18013
18018
  this.isCapturingTransaction = true;
@@ -18281,6 +18286,537 @@ function wrappingInputRule(config) {
18281
18286
  undoable: config.undoable
18282
18287
  });
18283
18288
  }
18289
+
18290
+ // src/lib/ResizableNodeView.ts
18291
+ var isTouchEvent = (e) => {
18292
+ return "touches" in e;
18293
+ };
18294
+ var ResizableNodeView = class {
18295
+ /**
18296
+ * Creates a new ResizableNodeView instance.
18297
+ *
18298
+ * The constructor sets up the resize handles, applies initial sizing from
18299
+ * node attributes, and configures all resize behavior options.
18300
+ *
18301
+ * @param options - Configuration options for the resizable node view
18302
+ */
18303
+ constructor(options) {
18304
+ /** Active resize handle directions */
18305
+ this.directions = ["bottom-left", "bottom-right", "top-left", "top-right"];
18306
+ /** Minimum allowed dimensions */
18307
+ this.minSize = {
18308
+ height: 8,
18309
+ width: 8
18310
+ };
18311
+ /** Whether to always preserve aspect ratio */
18312
+ this.preserveAspectRatio = false;
18313
+ /** CSS class names for elements */
18314
+ this.classNames = {
18315
+ container: "",
18316
+ wrapper: "",
18317
+ handle: "",
18318
+ resizing: ""
18319
+ };
18320
+ /** Initial width of the element (for aspect ratio calculation) */
18321
+ this.initialWidth = 0;
18322
+ /** Initial height of the element (for aspect ratio calculation) */
18323
+ this.initialHeight = 0;
18324
+ /** Calculated aspect ratio (width / height) */
18325
+ this.aspectRatio = 1;
18326
+ /** Whether a resize operation is currently active */
18327
+ this.isResizing = false;
18328
+ /** The handle currently being dragged */
18329
+ this.activeHandle = null;
18330
+ /** Starting mouse X position when resize began */
18331
+ this.startX = 0;
18332
+ /** Starting mouse Y position when resize began */
18333
+ this.startY = 0;
18334
+ /** Element width when resize began */
18335
+ this.startWidth = 0;
18336
+ /** Element height when resize began */
18337
+ this.startHeight = 0;
18338
+ /** Whether Shift key is currently pressed (for temporary aspect ratio lock) */
18339
+ this.isShiftKeyPressed = false;
18340
+ /**
18341
+ * Handles mouse movement during an active resize.
18342
+ *
18343
+ * Calculates the delta from the starting position, computes new dimensions
18344
+ * based on the active handle direction, applies constraints and aspect ratio,
18345
+ * then updates the element's style and calls the onResize callback.
18346
+ *
18347
+ * @param event - The mouse move event
18348
+ */
18349
+ this.handleMouseMove = (event) => {
18350
+ if (!this.isResizing || !this.activeHandle) {
18351
+ return;
18352
+ }
18353
+ const deltaX = event.clientX - this.startX;
18354
+ const deltaY = event.clientY - this.startY;
18355
+ this.handleResize(deltaX, deltaY);
18356
+ };
18357
+ this.handleTouchMove = (event) => {
18358
+ if (!this.isResizing || !this.activeHandle) {
18359
+ return;
18360
+ }
18361
+ const touch = event.touches[0];
18362
+ if (!touch) {
18363
+ return;
18364
+ }
18365
+ const deltaX = touch.clientX - this.startX;
18366
+ const deltaY = touch.clientY - this.startY;
18367
+ this.handleResize(deltaX, deltaY);
18368
+ };
18369
+ /**
18370
+ * Completes the resize operation when the mouse button is released.
18371
+ *
18372
+ * Captures final dimensions, calls the onCommit callback to persist changes,
18373
+ * removes the resizing state and class, and cleans up document-level listeners.
18374
+ */
18375
+ this.handleMouseUp = () => {
18376
+ if (!this.isResizing) {
18377
+ return;
18378
+ }
18379
+ const finalWidth = this.element.offsetWidth;
18380
+ const finalHeight = this.element.offsetHeight;
18381
+ this.onCommit(finalWidth, finalHeight);
18382
+ this.isResizing = false;
18383
+ this.activeHandle = null;
18384
+ this.container.dataset.resizeState = "false";
18385
+ if (this.classNames.resizing) {
18386
+ this.container.classList.remove(this.classNames.resizing);
18387
+ }
18388
+ document.removeEventListener("mousemove", this.handleMouseMove);
18389
+ document.removeEventListener("mouseup", this.handleMouseUp);
18390
+ document.removeEventListener("keydown", this.handleKeyDown);
18391
+ document.removeEventListener("keyup", this.handleKeyUp);
18392
+ };
18393
+ /**
18394
+ * Tracks Shift key state to enable temporary aspect ratio locking.
18395
+ *
18396
+ * When Shift is pressed during resize, aspect ratio is preserved even if
18397
+ * preserveAspectRatio is false.
18398
+ *
18399
+ * @param event - The keyboard event
18400
+ */
18401
+ this.handleKeyDown = (event) => {
18402
+ if (event.key === "Shift") {
18403
+ this.isShiftKeyPressed = true;
18404
+ }
18405
+ };
18406
+ /**
18407
+ * Tracks Shift key release to disable temporary aspect ratio locking.
18408
+ *
18409
+ * @param event - The keyboard event
18410
+ */
18411
+ this.handleKeyUp = (event) => {
18412
+ if (event.key === "Shift") {
18413
+ this.isShiftKeyPressed = false;
18414
+ }
18415
+ };
18416
+ var _a, _b, _c, _d, _e;
18417
+ this.node = options.node;
18418
+ this.element = options.element;
18419
+ this.contentElement = options.contentElement;
18420
+ this.getPos = options.getPos;
18421
+ this.onResize = options.onResize;
18422
+ this.onCommit = options.onCommit;
18423
+ this.onUpdate = options.onUpdate;
18424
+ if ((_a = options.options) == null ? void 0 : _a.min) {
18425
+ this.minSize = {
18426
+ ...this.minSize,
18427
+ ...options.options.min
18428
+ };
18429
+ }
18430
+ if ((_b = options.options) == null ? void 0 : _b.max) {
18431
+ this.maxSize = options.options.max;
18432
+ }
18433
+ if ((_c = options == null ? void 0 : options.options) == null ? void 0 : _c.directions) {
18434
+ this.directions = options.options.directions;
18435
+ }
18436
+ if ((_d = options.options) == null ? void 0 : _d.preserveAspectRatio) {
18437
+ this.preserveAspectRatio = options.options.preserveAspectRatio;
18438
+ }
18439
+ if ((_e = options.options) == null ? void 0 : _e.className) {
18440
+ this.classNames = {
18441
+ container: options.options.className.container || "",
18442
+ wrapper: options.options.className.wrapper || "",
18443
+ handle: options.options.className.handle || "",
18444
+ resizing: options.options.className.resizing || ""
18445
+ };
18446
+ }
18447
+ this.wrapper = this.createWrapper();
18448
+ this.container = this.createContainer();
18449
+ this.applyInitialSize();
18450
+ this.attachHandles();
18451
+ }
18452
+ /**
18453
+ * Returns the top-level DOM node that should be placed in the editor.
18454
+ *
18455
+ * This is required by the ProseMirror NodeView interface. The container
18456
+ * includes the wrapper, handles, and the actual content element.
18457
+ *
18458
+ * @returns The container element to be inserted into the editor
18459
+ */
18460
+ get dom() {
18461
+ return this.container;
18462
+ }
18463
+ get contentDOM() {
18464
+ return this.contentElement;
18465
+ }
18466
+ /**
18467
+ * Called when the node's content or attributes change.
18468
+ *
18469
+ * Updates the internal node reference. If a custom `onUpdate` callback
18470
+ * was provided, it will be called to handle additional update logic.
18471
+ *
18472
+ * @param node - The new/updated node
18473
+ * @param decorations - Node decorations
18474
+ * @param innerDecorations - Inner decorations
18475
+ * @returns `false` if the node type has changed (requires full rebuild), otherwise the result of `onUpdate` or `true`
18476
+ */
18477
+ update(node, decorations, innerDecorations) {
18478
+ if (node.type !== this.node.type) {
18479
+ return false;
18480
+ }
18481
+ this.node = node;
18482
+ if (this.onUpdate) {
18483
+ return this.onUpdate(node, decorations, innerDecorations);
18484
+ }
18485
+ return true;
18486
+ }
18487
+ /**
18488
+ * Cleanup method called when the node view is being removed.
18489
+ *
18490
+ * Removes all event listeners to prevent memory leaks. This is required
18491
+ * by the ProseMirror NodeView interface. If a resize is active when
18492
+ * destroy is called, it will be properly cancelled.
18493
+ */
18494
+ destroy() {
18495
+ if (this.isResizing) {
18496
+ this.container.dataset.resizeState = "false";
18497
+ if (this.classNames.resizing) {
18498
+ this.container.classList.remove(this.classNames.resizing);
18499
+ }
18500
+ document.removeEventListener("mousemove", this.handleMouseMove);
18501
+ document.removeEventListener("mouseup", this.handleMouseUp);
18502
+ document.removeEventListener("keydown", this.handleKeyDown);
18503
+ document.removeEventListener("keyup", this.handleKeyUp);
18504
+ this.isResizing = false;
18505
+ this.activeHandle = null;
18506
+ }
18507
+ this.container.remove();
18508
+ }
18509
+ /**
18510
+ * Creates the outer container element.
18511
+ *
18512
+ * The container is the top-level element returned by the NodeView and
18513
+ * wraps the entire resizable node. It's set up with flexbox to handle
18514
+ * alignment and includes data attributes for styling and identification.
18515
+ *
18516
+ * @returns The container element
18517
+ */
18518
+ createContainer() {
18519
+ const element = document.createElement("div");
18520
+ element.dataset.resizeContainer = "";
18521
+ element.dataset.node = this.node.type.name;
18522
+ element.style.display = "flex";
18523
+ element.style.justifyContent = "flex-start";
18524
+ element.style.alignItems = "flex-start";
18525
+ if (this.classNames.container) {
18526
+ element.className = this.classNames.container;
18527
+ }
18528
+ element.appendChild(this.wrapper);
18529
+ return element;
18530
+ }
18531
+ /**
18532
+ * Creates the wrapper element that contains the content and handles.
18533
+ *
18534
+ * The wrapper uses relative positioning so that resize handles can be
18535
+ * positioned absolutely within it. This is the direct parent of the
18536
+ * content element being made resizable.
18537
+ *
18538
+ * @returns The wrapper element
18539
+ */
18540
+ createWrapper() {
18541
+ const element = document.createElement("div");
18542
+ element.style.position = "relative";
18543
+ element.style.display = "block";
18544
+ element.dataset.resizeWrapper = "";
18545
+ if (this.classNames.wrapper) {
18546
+ element.className = this.classNames.wrapper;
18547
+ }
18548
+ element.appendChild(this.element);
18549
+ return element;
18550
+ }
18551
+ /**
18552
+ * Creates a resize handle element for a specific direction.
18553
+ *
18554
+ * Each handle is absolutely positioned and includes a data attribute
18555
+ * identifying its direction for styling purposes.
18556
+ *
18557
+ * @param direction - The resize direction for this handle
18558
+ * @returns The handle element
18559
+ */
18560
+ createHandle(direction) {
18561
+ const handle = document.createElement("div");
18562
+ handle.dataset.resizeHandle = direction;
18563
+ handle.style.position = "absolute";
18564
+ if (this.classNames.handle) {
18565
+ handle.className = this.classNames.handle;
18566
+ }
18567
+ return handle;
18568
+ }
18569
+ /**
18570
+ * Positions a handle element according to its direction.
18571
+ *
18572
+ * Corner handles (e.g., 'top-left') are positioned at the intersection
18573
+ * of two edges. Edge handles (e.g., 'top') span the full width or height.
18574
+ *
18575
+ * @param handle - The handle element to position
18576
+ * @param direction - The direction determining the position
18577
+ */
18578
+ positionHandle(handle, direction) {
18579
+ const isTop = direction.includes("top");
18580
+ const isBottom = direction.includes("bottom");
18581
+ const isLeft = direction.includes("left");
18582
+ const isRight = direction.includes("right");
18583
+ if (isTop) {
18584
+ handle.style.top = "0";
18585
+ }
18586
+ if (isBottom) {
18587
+ handle.style.bottom = "0";
18588
+ }
18589
+ if (isLeft) {
18590
+ handle.style.left = "0";
18591
+ }
18592
+ if (isRight) {
18593
+ handle.style.right = "0";
18594
+ }
18595
+ if (direction === "top" || direction === "bottom") {
18596
+ handle.style.left = "0";
18597
+ handle.style.right = "0";
18598
+ }
18599
+ if (direction === "left" || direction === "right") {
18600
+ handle.style.top = "0";
18601
+ handle.style.bottom = "0";
18602
+ }
18603
+ }
18604
+ /**
18605
+ * Creates and attaches all resize handles to the wrapper.
18606
+ *
18607
+ * Iterates through the configured directions, creates a handle for each,
18608
+ * positions it, attaches the mousedown listener, and appends it to the DOM.
18609
+ */
18610
+ attachHandles() {
18611
+ this.directions.forEach((direction) => {
18612
+ const handle = this.createHandle(direction);
18613
+ this.positionHandle(handle, direction);
18614
+ handle.addEventListener("mousedown", (event) => this.handleResizeStart(event, direction));
18615
+ handle.addEventListener("touchstart", (event) => this.handleResizeStart(event, direction));
18616
+ this.wrapper.appendChild(handle);
18617
+ });
18618
+ }
18619
+ /**
18620
+ * Applies initial sizing from node attributes to the element.
18621
+ *
18622
+ * If width/height attributes exist on the node, they're applied to the element.
18623
+ * Otherwise, the element's natural/current dimensions are measured. The aspect
18624
+ * ratio is calculated for later use in aspect-ratio-preserving resizes.
18625
+ */
18626
+ applyInitialSize() {
18627
+ const width = this.node.attrs.width;
18628
+ const height = this.node.attrs.height;
18629
+ if (width) {
18630
+ this.element.style.width = `${width}px`;
18631
+ this.initialWidth = width;
18632
+ } else {
18633
+ this.initialWidth = this.element.offsetWidth;
18634
+ }
18635
+ if (height) {
18636
+ this.element.style.height = `${height}px`;
18637
+ this.initialHeight = height;
18638
+ } else {
18639
+ this.initialHeight = this.element.offsetHeight;
18640
+ }
18641
+ if (this.initialWidth > 0 && this.initialHeight > 0) {
18642
+ this.aspectRatio = this.initialWidth / this.initialHeight;
18643
+ }
18644
+ }
18645
+ /**
18646
+ * Initiates a resize operation when a handle is clicked.
18647
+ *
18648
+ * Captures the starting mouse position and element dimensions, sets up
18649
+ * the resize state, adds the resizing class and state attribute, and
18650
+ * attaches document-level listeners for mouse movement and keyboard input.
18651
+ *
18652
+ * @param event - The mouse down event
18653
+ * @param direction - The direction of the handle being dragged
18654
+ */
18655
+ handleResizeStart(event, direction) {
18656
+ event.preventDefault();
18657
+ event.stopPropagation();
18658
+ this.isResizing = true;
18659
+ this.activeHandle = direction;
18660
+ if (isTouchEvent(event)) {
18661
+ this.startX = event.touches[0].clientX;
18662
+ this.startY = event.touches[0].clientY;
18663
+ } else {
18664
+ this.startX = event.clientX;
18665
+ this.startY = event.clientY;
18666
+ }
18667
+ this.startWidth = this.element.offsetWidth;
18668
+ this.startHeight = this.element.offsetHeight;
18669
+ if (this.startWidth > 0 && this.startHeight > 0) {
18670
+ this.aspectRatio = this.startWidth / this.startHeight;
18671
+ }
18672
+ this.getPos();
18673
+ this.container.dataset.resizeState = "true";
18674
+ if (this.classNames.resizing) {
18675
+ this.container.classList.add(this.classNames.resizing);
18676
+ }
18677
+ document.addEventListener("mousemove", this.handleMouseMove);
18678
+ document.addEventListener("touchmove", this.handleTouchMove);
18679
+ document.addEventListener("mouseup", this.handleMouseUp);
18680
+ document.addEventListener("keydown", this.handleKeyDown);
18681
+ document.addEventListener("keyup", this.handleKeyUp);
18682
+ }
18683
+ handleResize(deltaX, deltaY) {
18684
+ if (!this.activeHandle) {
18685
+ return;
18686
+ }
18687
+ const shouldPreserveAspectRatio = this.preserveAspectRatio || this.isShiftKeyPressed;
18688
+ const { width, height } = this.calculateNewDimensions(this.activeHandle, deltaX, deltaY);
18689
+ const constrained = this.applyConstraints(width, height, shouldPreserveAspectRatio);
18690
+ this.element.style.width = `${constrained.width}px`;
18691
+ this.element.style.height = `${constrained.height}px`;
18692
+ if (this.onResize) {
18693
+ this.onResize(constrained.width, constrained.height);
18694
+ }
18695
+ }
18696
+ /**
18697
+ * Calculates new dimensions based on mouse delta and resize direction.
18698
+ *
18699
+ * Takes the starting dimensions and applies the mouse movement delta
18700
+ * according to the handle direction. For corner handles, both dimensions
18701
+ * are affected. For edge handles, only one dimension changes. If aspect
18702
+ * ratio should be preserved, delegates to applyAspectRatio.
18703
+ *
18704
+ * @param direction - The active resize handle direction
18705
+ * @param deltaX - Horizontal mouse movement since resize start
18706
+ * @param deltaY - Vertical mouse movement since resize start
18707
+ * @returns The calculated width and height
18708
+ */
18709
+ calculateNewDimensions(direction, deltaX, deltaY) {
18710
+ let newWidth = this.startWidth;
18711
+ let newHeight = this.startHeight;
18712
+ const isRight = direction.includes("right");
18713
+ const isLeft = direction.includes("left");
18714
+ const isBottom = direction.includes("bottom");
18715
+ const isTop = direction.includes("top");
18716
+ if (isRight) {
18717
+ newWidth = this.startWidth + deltaX;
18718
+ } else if (isLeft) {
18719
+ newWidth = this.startWidth - deltaX;
18720
+ }
18721
+ if (isBottom) {
18722
+ newHeight = this.startHeight + deltaY;
18723
+ } else if (isTop) {
18724
+ newHeight = this.startHeight - deltaY;
18725
+ }
18726
+ if (direction === "right" || direction === "left") {
18727
+ newWidth = this.startWidth + (isRight ? deltaX : -deltaX);
18728
+ }
18729
+ if (direction === "top" || direction === "bottom") {
18730
+ newHeight = this.startHeight + (isBottom ? deltaY : -deltaY);
18731
+ }
18732
+ const shouldPreserveAspectRatio = this.preserveAspectRatio || this.isShiftKeyPressed;
18733
+ if (shouldPreserveAspectRatio) {
18734
+ return this.applyAspectRatio(newWidth, newHeight, direction);
18735
+ }
18736
+ return { width: newWidth, height: newHeight };
18737
+ }
18738
+ /**
18739
+ * Applies min/max constraints to dimensions.
18740
+ *
18741
+ * When aspect ratio is NOT preserved, constraints are applied independently
18742
+ * to width and height. When aspect ratio IS preserved, constraints are
18743
+ * applied while maintaining the aspect ratio—if one dimension hits a limit,
18744
+ * the other is recalculated proportionally.
18745
+ *
18746
+ * This ensures that aspect ratio is never broken when constrained.
18747
+ *
18748
+ * @param width - The unconstrained width
18749
+ * @param height - The unconstrained height
18750
+ * @param preserveAspectRatio - Whether to maintain aspect ratio while constraining
18751
+ * @returns The constrained dimensions
18752
+ */
18753
+ applyConstraints(width, height, preserveAspectRatio) {
18754
+ var _a, _b, _c, _d;
18755
+ if (!preserveAspectRatio) {
18756
+ let constrainedWidth2 = Math.max(this.minSize.width, width);
18757
+ let constrainedHeight2 = Math.max(this.minSize.height, height);
18758
+ if ((_a = this.maxSize) == null ? void 0 : _a.width) {
18759
+ constrainedWidth2 = Math.min(this.maxSize.width, constrainedWidth2);
18760
+ }
18761
+ if ((_b = this.maxSize) == null ? void 0 : _b.height) {
18762
+ constrainedHeight2 = Math.min(this.maxSize.height, constrainedHeight2);
18763
+ }
18764
+ return { width: constrainedWidth2, height: constrainedHeight2 };
18765
+ }
18766
+ let constrainedWidth = width;
18767
+ let constrainedHeight = height;
18768
+ if (constrainedWidth < this.minSize.width) {
18769
+ constrainedWidth = this.minSize.width;
18770
+ constrainedHeight = constrainedWidth / this.aspectRatio;
18771
+ }
18772
+ if (constrainedHeight < this.minSize.height) {
18773
+ constrainedHeight = this.minSize.height;
18774
+ constrainedWidth = constrainedHeight * this.aspectRatio;
18775
+ }
18776
+ if (((_c = this.maxSize) == null ? void 0 : _c.width) && constrainedWidth > this.maxSize.width) {
18777
+ constrainedWidth = this.maxSize.width;
18778
+ constrainedHeight = constrainedWidth / this.aspectRatio;
18779
+ }
18780
+ if (((_d = this.maxSize) == null ? void 0 : _d.height) && constrainedHeight > this.maxSize.height) {
18781
+ constrainedHeight = this.maxSize.height;
18782
+ constrainedWidth = constrainedHeight * this.aspectRatio;
18783
+ }
18784
+ return { width: constrainedWidth, height: constrainedHeight };
18785
+ }
18786
+ /**
18787
+ * Adjusts dimensions to maintain the original aspect ratio.
18788
+ *
18789
+ * For horizontal handles (left/right), uses width as the primary dimension
18790
+ * and calculates height from it. For vertical handles (top/bottom), uses
18791
+ * height as primary and calculates width. For corner handles, uses width
18792
+ * as the primary dimension.
18793
+ *
18794
+ * @param width - The new width
18795
+ * @param height - The new height
18796
+ * @param direction - The active resize direction
18797
+ * @returns Dimensions adjusted to preserve aspect ratio
18798
+ */
18799
+ applyAspectRatio(width, height, direction) {
18800
+ const isHorizontal = direction === "left" || direction === "right";
18801
+ const isVertical = direction === "top" || direction === "bottom";
18802
+ if (isHorizontal) {
18803
+ return {
18804
+ width,
18805
+ height: width / this.aspectRatio
18806
+ };
18807
+ }
18808
+ if (isVertical) {
18809
+ return {
18810
+ width: height * this.aspectRatio,
18811
+ height
18812
+ };
18813
+ }
18814
+ return {
18815
+ width,
18816
+ height: width / this.aspectRatio
18817
+ };
18818
+ }
18819
+ };
18284
18820
  function canInsertNode(state, nodeType) {
18285
18821
  const { selection } = state;
18286
18822
  const { $from } = selection;
@@ -20256,6 +20792,7 @@ var Document = Node3.create({
20256
20792
  // src/hard-break.ts
20257
20793
  var HardBreak = Node3.create({
20258
20794
  name: "hardBreak",
20795
+ markdownTokenName: "br",
20259
20796
  addOptions() {
20260
20797
  return {
20261
20798
  keepMarks: true,
@@ -20277,6 +20814,11 @@ var HardBreak = Node3.create({
20277
20814
  },
20278
20815
  renderMarkdown: (_node, h) => h.indent(`
20279
20816
  `),
20817
+ parseMarkdown: () => {
20818
+ return {
20819
+ type: "hardBreak"
20820
+ };
20821
+ },
20280
20822
  addCommands() {
20281
20823
  return {
20282
20824
  setHardBreak: () => ({ commands, chain, state, editor }) => {
@@ -25340,7 +25882,8 @@ var Image = Node3.create({
25340
25882
  return {
25341
25883
  inline: false,
25342
25884
  allowBase64: false,
25343
- HTMLAttributes: {}
25885
+ HTMLAttributes: {},
25886
+ resize: false
25344
25887
  };
25345
25888
  },
25346
25889
  inline() {
@@ -25393,6 +25936,69 @@ var Image = Node3.create({
25393
25936
  const title = (_f = (_e = node.attrs) == null ? void 0 : _e.title) != null ? _f : "";
25394
25937
  return title ? `![${alt}](${src} "${title}")` : `![${alt}](${src})`;
25395
25938
  },
25939
+ addNodeView() {
25940
+ if (!this.options.resize || !this.options.resize.enabled || typeof document === "undefined" || !this.editor.isEditable) {
25941
+ return null;
25942
+ }
25943
+ const { directions, minWidth, minHeight, alwaysPreserveAspectRatio } = this.options.resize;
25944
+ return ({ node, getPos, HTMLAttributes }) => {
25945
+ const el = document.createElement("img");
25946
+ Object.entries(HTMLAttributes).forEach(([key, value]) => {
25947
+ if (value != null) {
25948
+ switch (key) {
25949
+ case "width":
25950
+ case "height":
25951
+ break;
25952
+ default:
25953
+ el.setAttribute(key, value);
25954
+ break;
25955
+ }
25956
+ }
25957
+ });
25958
+ el.src = HTMLAttributes.src;
25959
+ const nodeView = new ResizableNodeView({
25960
+ element: el,
25961
+ node,
25962
+ getPos,
25963
+ onResize: (width, height) => {
25964
+ el.style.width = `${width}px`;
25965
+ el.style.height = `${height}px`;
25966
+ },
25967
+ onCommit: (width, height) => {
25968
+ const pos = getPos();
25969
+ if (pos === void 0) {
25970
+ return;
25971
+ }
25972
+ this.editor.chain().setNodeSelection(pos).updateAttributes(this.name, {
25973
+ width,
25974
+ height
25975
+ }).run();
25976
+ },
25977
+ onUpdate: (updatedNode, _decorations, _innerDecorations) => {
25978
+ if (updatedNode.type !== node.type) {
25979
+ return false;
25980
+ }
25981
+ return true;
25982
+ },
25983
+ options: {
25984
+ directions,
25985
+ min: {
25986
+ width: minWidth,
25987
+ height: minHeight
25988
+ },
25989
+ preserveAspectRatio: alwaysPreserveAspectRatio === true
25990
+ }
25991
+ });
25992
+ const dom = nodeView.dom;
25993
+ dom.style.visibility = "hidden";
25994
+ dom.style.pointerEvents = "none";
25995
+ el.onload = () => {
25996
+ dom.style.visibility = "";
25997
+ dom.style.pointerEvents = "";
25998
+ };
25999
+ return nodeView;
26000
+ };
26001
+ },
25396
26002
  addCommands() {
25397
26003
  return {
25398
26004
  setImage: (options) => ({ commands }) => {