```
class RectRegionShapeFactory {
  /**
   * Constructor to initialize default options and mount on a container.
   * @param {HTMLElement} container - The DOM element to mount the rectangles.
   * @param {Object} defaultOptions - Default customization options.
   */
  constructor(container, defaultOptions = {}) {
    if (!(container instanceof HTMLElement)) {
      throw new Error('Container must be a valid DOM element.');
    }

    // Create a shadow root on the container
    this.shadow = container.attachShadow({ mode: 'open' });

    // Initialize a container inside the shadow DOM to hold rectangles
    this.rectContainer = document.createElement('div');
    this.rectContainer.style.position = 'relative'; // Ensures absolute children are positioned correctly
    this.shadow.appendChild(this.rectContainer);

    // Merge user-provided default options with inherent defaults
    this.defaultOptions = {
      vertexSize: '25px',       // Size of the corner squares
      vertexColor: '#3498db',   // Color of the corner squares
      borderColor: '#000',      // Color of the rectangle border
      borderSize: '2px',       // Width of the rectangle border
      ...defaultOptions
    };

    // Inject CSS into the shadow DOM
    this.injectCSS();
  }

  /**
   * Injects necessary CSS styles into the shadow DOM.
   */
  injectCSS() {
    const style = document.createElement('style');
    style.type = 'text/css';
    style.textContent = `
      .rect-region {
        /* CSS Variables */
        --vertex-size: 25px;
        --vertex-color: #3498db;
        --border-size: 2px;
        --border-color: #000;
        --width: 100px;
        --height: 100px;

        position: absolute; /* Positioned relative to the shadow container */
        width: var(--width);
        height: var(--height);
        border: var(--border-size) solid var(--border-color);
        box-sizing: border-box;
      }

      .rect-region::before {
        content: '';
        position: absolute;
        width: var(--vertex-size);
        height: var(--vertex-size);
        background-color: var(--vertex-color);
        box-sizing: border-box;
        
        /* Intermediate variables */
        --offset: calc(-0.5 * (var(--border-size) + var(--vertex-size)) );
        --adjusted-width: calc(var(--width) - var(--border-size));
        --adjusted-height: calc(var(--height) - var(--border-size));
        /* Center the first dot at (0,0) by shifting it by half its size */
        top: var(--offset);
        left: var(--offset);

        /* Creating three more squares using box-shadow, centered at each corner */
        box-shadow:
          var(--adjusted-width) 0 0 0 var(--vertex-color),
          var(--adjusted-width) var(--adjusted-height) 0 0 var(--vertex-color),
          0 var(--adjusted-height) 0 0 var(--vertex-color);
      }
    `;
    this.shadow.appendChild(style);
  }

  /**
   * Creates and appends a rectangle element with centered corner dots to the shadow DOM.
   * @param {number} x - The left position in pixels relative to the container.
   * @param {number} y - The top position in pixels relative to the container.
   * @param {number} width - Width of the rectangle in pixels.
   * @param {number} height - Height of the rectangle in pixels.
   * @param {Object} options - Customization options.
   * @returns {HTMLElement} - The created rectangle element.
   */
  createRect(x, y, width, height, options = {}) {
    // Merge options with default options
    const finalOptions = { ...this.defaultOptions, ...options };

    // Create the rectangle div
    const rect = document.createElement('div');
    rect.classList.add('rect-region');

    // Set position relative to the shadow container
    rect.style.left = `${x}px`;
    rect.style.top = `${y}px`;

    // Set width and height via CSS variables
    rect.style.setProperty('--width', `${width}px`);
    rect.style.setProperty('--height', `${height}px`);

    // Set customization options via CSS variables
    rect.style.setProperty('--vertex-size', finalOptions.vertexSize);
    rect.style.setProperty('--vertex-color', finalOptions.vertexColor);
    rect.style.setProperty('--border-size', finalOptions.borderSize);
    rect.style.setProperty('--border-color', finalOptions.borderColor);

    // Append the rectangle to the shadow DOM's container
    this.rectContainer.appendChild(rect);

    return rect;
  }

  /**
   * Updates an existing rectangle element within the shadow DOM.
   * @param {HTMLElement} rect - The rectangle element to update.
   * @param {Object} options - Customization and positional options.
   */
  updateRect(rect, options = {}) {
    if (!(rect instanceof HTMLElement)) {
      console.error('The first argument to updateRect must be a DOM element.');
      return;
    }

    if (!rect.classList.contains('rect-region')) {
      console.error('The provided element does not have the class "rect-region".');
      return;
    }

    // Destructure possible options
    const {
      x,
      y,
      width,
      height,
      vertexSize,
      vertexColor,
      borderColor,
      borderSize
    } = options;

    // Update position if provided
    if (x !== undefined) {
      rect.style.left = typeof x === 'number' ? `${x}px` : x;
    }

    if (y !== undefined) {
      rect.style.top = typeof y === 'number' ? `${y}px` : y;
    }

    // Update size if provided
    if (width !== undefined) {
      rect.style.setProperty('--width', typeof width === 'number' ? `${width}px` : width);
    }

    if (height !== undefined) {
      rect.style.setProperty('--height', typeof height === 'number' ? `${height}px` : height);
    }

    // Update customization options if provided
    if (vertexSize !== undefined) {
      rect.style.setProperty('--vertex-size', vertexSize);
    }

    if (vertexColor !== undefined) {
      rect.style.setProperty('--vertex-color', vertexColor);
      // Force re-render of box-shadows by updating the style
      rect.style.boxShadow = rect.style.boxShadow;
    }

    if (borderColor !== undefined) {
      rect.style.setProperty('--border-color', borderColor);
    }

    if (borderSize !== undefined) {
      rect.style.setProperty('--border-size', borderSize);
    }
  }
}

    const container = document.getElementById('rectangle-container');

    // Instantiate the factory with optional default options
    const factory = new RectRegionShapeFactory(container, {
      vertexSize: '20px',
      vertexColor: '#e74c3c',
      borderColor: '#2c3e50',
      borderSize: '3px'
    });

    // Create multiple rectangles with different properties
    const rect1 = factory.createRect(50, 50, 200, 100, {
      vertexSize: '12px',
      vertexColor: '#1abc9c',
      borderColor: '#16a085',
      borderSize: '2px'
    });

    const rect2 = factory.createRect(300, 150, 250, 150, {
      vertexSize: '24px',
      vertexColor: '#f1c40f',
      borderColor: '#f39c12',
      borderSize: '4px'
    });

    const rect3 = factory.createRect(600, 80, 180, 120); // Uses default options

```

Introduce the idea of plugin to this class.



every plugin can inject css
```
    style.textContent = `
      .rect-region {
        {{append plugin css  here}}
      }

      .rect-region::before {
        {{append plugin css here}}
      }
    `;
    ```
depends on what they do. thats how plugin order matters.


now refactor the code to move border and vertex as plugins
```
const plugins = [new BorderPlugin({size: '3px', color: '#2c3e50',}), new VertexPlugin({size: '20px', color: '#e74c3c' })]
// when creating the factory:

const factory = new RectRegionShapeFactory(container, plugins (by default you dont need to provide));
// yea no options anymore, instead plugins get options

```

factory should no longer return a rect element directly.

they return a rect wrapper that holds a weak reference to the element and maybe other necessary data

plugin should also expose state change methods, remove updateRect method in factory, instead,
the returned rect wrapper allows methods like this:
```
remove() // remove the rect itself

update({
      x: 46,
      y: 77,
      width: 120,
      height: 200,
}, [
  [BorderPlugin, {size: '6px',}], //  applies to the current rect only, depends on how plugin implements 
  [VertexPlugin, {size: '16px}] //  applies to the current rect only, depends on how plugin implements 
]);
```