notations 1.0.4 → 1.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/dist/notations.umd.js +329 -84
- package/dist/notations.umd.min.js +2 -2
- package/dist/notations.umd.min.js.map +1 -1
- package/lib/cjs/block.d.ts +4 -0
- package/lib/cjs/block.js +24 -0
- package/lib/cjs/block.js.map +1 -1
- package/lib/cjs/core.d.ts +15 -0
- package/lib/cjs/core.js +144 -4
- package/lib/cjs/core.js.map +1 -1
- package/lib/cjs/entity.d.ts +4 -0
- package/lib/cjs/entity.js +12 -0
- package/lib/cjs/entity.js.map +1 -1
- package/lib/cjs/events.d.ts +56 -0
- package/lib/cjs/events.js +27 -0
- package/lib/cjs/events.js.map +1 -0
- package/lib/cjs/index.d.ts +1 -0
- package/lib/cjs/index.js +1 -0
- package/lib/cjs/index.js.map +1 -1
- package/lib/cjs/shapes.d.ts +11 -0
- package/lib/cjs/shapes.js +25 -2
- package/lib/cjs/shapes.js.map +1 -1
- package/lib/esm/block.d.ts +4 -0
- package/lib/esm/block.js +24 -0
- package/lib/esm/block.js.map +1 -1
- package/lib/esm/core.d.ts +15 -0
- package/lib/esm/core.js +144 -4
- package/lib/esm/core.js.map +1 -1
- package/lib/esm/entity.d.ts +4 -0
- package/lib/esm/entity.js +12 -0
- package/lib/esm/entity.js.map +1 -1
- package/lib/esm/events.d.ts +56 -0
- package/lib/esm/events.js +24 -0
- package/lib/esm/events.js.map +1 -0
- package/lib/esm/index.d.ts +1 -0
- package/lib/esm/index.js +1 -0
- package/lib/esm/index.js.map +1 -1
- package/lib/esm/shapes.d.ts +11 -0
- package/lib/esm/shapes.js +24 -2
- package/lib/esm/shapes.js.map +1 -1
- package/package.json +3 -1
package/lib/cjs/shapes.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shapes.js","sourceRoot":"","sources":["../../src/shapes.ts"],"names":[],"mappings":"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","sourcesContent":["import * as TSU from \"@panyam/tsutils\";\nimport { ZERO, Atom, LeafAtom, Group } from \"./core\";\n\n/**\n * Base class for all renderable objects.\n *\n * Shape caches properties like bounding boxes to improve performance,\n * since bounding box calculations can be expensive. This also allows\n * testing layouts and positioning without worrying about implementation details.\n */\nexport abstract class Shape {\n private static idCounter = 0;\n readonly shapeId: number = Shape.idCounter++;\n\n /**\n * Note that x and y coordinates are not always the x and y coordinates\n * of the bounding box.\n * E.g., a circle's x and y coordinates are its center point and not the\n * top left corner.\n * These \"main\" coordinates are referred to as control coordinates.\n */\n protected _x: number | null = null;\n protected _y: number | null = null;\n protected _width: number | null = null;\n protected _height: number | null = null;\n protected _bbox: TSU.Geom.Rect;\n protected _minSize: TSU.Geom.Size;\n protected parentShape: Shape | null = null;\n /** Child shapes contained within this shape */\n children: Shape[] = [];\n\n /**\n * Gets the bounding box of this shape.\n * Calculates it if it hasn't been calculated yet.\n */\n get bbox(): TSU.Geom.Rect {\n if (!this._bbox) {\n this._bbox = this.refreshBBox();\n }\n return this._bbox;\n }\n\n /**\n * Gets the minimum size of this shape.\n * This is usually the size of the bounding box.\n */\n get minSize(): TSU.Geom.Size {\n if (!this._minSize) {\n this._minSize = this.refreshMinSize();\n }\n return this._minSize;\n }\n\n /**\n * Refreshes the bounding box of this shape.\n * Called when the shape knows the bbox it is tracking cannot be trusted\n * and has to be refreshed by calling native methods.\n * @returns The refreshed bounding box\n */\n protected abstract refreshBBox(): TSU.Geom.Rect;\n\n /**\n * Refreshes the minimum size of this shape.\n * @returns The refreshed minimum size\n */\n protected abstract refreshMinSize(): TSU.Geom.Size;\n\n /**\n * Updates the bounds of this shape.\n * @param x New x coordinate, or null to keep current value\n * @param y New y coordinate, or null to keep current value\n * @param w New width, or null to keep current value\n * @param h New height, or null to keep current value\n * @returns The updated bounds values\n */\n protected abstract updateBounds(\n x: null | number,\n y: null | number,\n w: null | number,\n h: null | number,\n ): [number | null, number | null, number | null, number | null];\n\n /**\n * Invalidates the cached bounds of this shape.\n * Forces recalculation of bounding box and minimum size.\n */\n invalidateBounds(): void {\n this._minSize = null as unknown as TSU.Geom.Size;\n this._bbox = null as unknown as TSU.Geom.Rect;\n }\n\n /**\n * Sets the bounds of this shape.\n *\n * Note that null and NaN are valid values and mean the following:\n * - null: Don't change the value\n * - NaN: Set the value to null (use the bounding box's value)\n *\n * @param x New x coordinate, or null to keep current value\n * @param y New y coordinate, or null to keep current value\n * @param w New width, or null to keep current value\n * @param h New height, or null to keep current value\n * @param applyLayout Whether to apply layout immediately\n * @returns The updated bounds values\n */\n setBounds(\n x: number | null,\n y: number | null,\n w: number | null,\n h: number | null,\n applyLayout = false,\n ): [number | null, number | null, number | null, number | null] {\n if (x != null) {\n if (isNaN(x)) {\n this._x = null;\n } else {\n this._x = x;\n }\n }\n if (y != null) {\n if (isNaN(y)) {\n this._y = null;\n } else {\n this._y = y;\n }\n }\n if (w != null) {\n if (isNaN(w)) {\n this._width = null;\n } else {\n this._width = w;\n }\n }\n if (h != null) {\n if (isNaN(h)) {\n this._height = null;\n } else {\n this._height = h;\n }\n }\n const [nx, ny, nw, nh] = this.updateBounds(x, y, w, h);\n if (nx != null) {\n if (isNaN(nx)) {\n this._x = null;\n } else {\n this._x = nx;\n }\n }\n if (ny != null) {\n if (isNaN(ny)) {\n this._y = null;\n } else {\n this._y = ny;\n }\n }\n if (nw != null) {\n if (isNaN(nw)) {\n this._width = null;\n } else {\n this._width = nw;\n }\n }\n if (nh != null) {\n if (isNaN(nh)) {\n this._height = null;\n } else {\n this._height = nh;\n }\n }\n if (applyLayout) this.refreshLayout();\n // this.resetBBox();\n return [nx, ny, nw, nh];\n }\n\n /**\n * Checks if this shape has an explicit x coordinate.\n */\n get hasX(): boolean {\n return this._x != null && !isNaN(this._x);\n }\n\n /**\n * Checks if this shape has an explicit y coordinate.\n */\n get hasY(): boolean {\n return this._y != null && !isNaN(this._y);\n }\n\n /**\n * Checks if this shape has an explicit width.\n */\n get hasWidth(): boolean {\n return this._width != null && !isNaN(this._width);\n }\n\n /**\n * Checks if this shape has an explicit height.\n */\n get hasHeight(): boolean {\n return this._height != null && !isNaN(this._height);\n }\n\n /**\n * Gets the x coordinate within the parent's coordinate system.\n */\n get x(): number {\n return this._x || 0;\n }\n\n /**\n * Sets the x coordinate within the parent's coordinate system.\n */\n set x(x: number | null) {\n // Here a manual x is being set - how does this interfere with the bounding box?\n // We should _x to the new value to indicate a manual value was set.\n // and reset bbox so that based on this x a new bbox may need to be calculated\n this.setBounds(x == null ? NaN : x, null, null, null);\n }\n\n /**\n * Gets the y coordinate within the parent's coordinate system.\n */\n get y(): number {\n if (this._y != null) return this._y;\n return 0; // this.bbox.y;\n }\n\n /**\n * Sets the y coordinate within the parent's coordinate system.\n */\n set y(y: number | null) {\n this.setBounds(null, y == null ? NaN : y, null, null);\n }\n\n /**\n * Gets the width of this shape.\n */\n get width(): number {\n if (this._width != null) return this._width;\n return 0; // this.bbox.width;\n }\n\n /**\n * Sets the width of this shape.\n */\n set width(w: number | null) {\n this.setBounds(null, null, w == null ? NaN : w, null);\n }\n\n /**\n * Gets the height of this shape.\n */\n get height(): number {\n if (this._height != null) return this._height;\n return 0; // this.bbox.height;\n }\n\n /**\n * Sets the height of this shape.\n */\n set height(h: number | null) {\n this.setBounds(null, null, null, h == null ? NaN : h);\n }\n\n /**\n * Refreshes the layout of this shape.\n * Called when bounds or other properties have changed to give the shape an\n * opportunity to layout its children. For shapes with no children this is a no-op.\n */\n refreshLayout(): void {\n // throw new Error(\"Implement this\");\n }\n}\n\n/**\n * Represents an embellishment applied to a musical element.\n */\nexport abstract class Embelishment extends Shape {}\n\n/**\n * A shape that wraps an SVG element.\n * ElementShape provides the base class for all shapes that are rendered as SVG elements.\n */\nexport class ElementShape<T extends SVGGraphicsElement = SVGGraphicsElement> extends Shape {\n /**\n * Creates a new ElementShape.\n * @param element The SVG element this shape wraps\n */\n constructor(public readonly element: T) {\n super();\n }\n\n /**\n * Refreshes the bounding box of this element.\n * @returns The refreshed bounding box\n */\n protected refreshBBox(): TSU.Geom.Rect {\n return TSU.DOM.svgBBox(this.element);\n }\n\n /**\n * Refreshes the minimum size of this element.\n * @returns The refreshed minimum size\n */\n protected refreshMinSize(): TSU.Geom.Size {\n return TSU.DOM.svgBBox(this.element);\n }\n\n /**\n * Updates the bounds of this element.\n * @param x New x coordinate, or null to keep current value\n * @param y New y coordinate, or null to keep current value\n * @param w New width, or null to keep current value\n * @param h New height, or null to keep current value\n * @returns The updated bounds values\n */\n protected updateBounds(\n x: null | number,\n y: null | number,\n w: null | number,\n h: null | number,\n ): [number | null, number | null, number | null, number | null] {\n return [x, y, w, h];\n }\n\n /**\n * Refreshes the layout of this element.\n * Updates the element's attributes based on the shape's properties.\n */\n refreshLayout(): void {\n if (this.hasX) this.element.setAttribute(\"x\", \"\" + this._x);\n if (this.hasY) this.element.setAttribute(\"y\", \"\" + this._y);\n }\n}\n\n/**\n * Base class for views that represent atoms in the notation.\n * AtomView provides the visual representation of an atom.\n */\nexport abstract class AtomView extends Shape {\n /** Nesting depth of this atom in the structure */\n depth = 0;\n /** Index of the role containing this atom */\n roleIndex = 0;\n\n // LayoutMetrics for the AtomView so all atomviews laid out on the\n // same baseline will show up aligned vertically\n /** Baseline position for vertical alignment */\n baseline: number;\n /** Ascent (space above baseline) */\n ascent: number;\n /** Descent (space below baseline) */\n descent: number;\n /** Height of capital letters */\n capHeight: number;\n /** Space between lines */\n leading: number;\n\n /**\n * Checks if this atom view represents a leaf atom.\n */\n abstract isLeaf(): boolean;\n\n abstract get totalDuration(): TSU.Num.Fraction;\n\n /**\n * Returns the horizontal offset from the atom's origin to where the note glyph starts.\n * This accounts for left embellishments that appear before the note.\n * Used by GroupView to align note glyphs at their correct time positions.\n *\n * Default is 0 (glyph starts at origin). Subclasses with left embellishments\n * should override to return the width of left-side decorations.\n */\n get glyphOffset(): number {\n return 0;\n }\n\n /**\n * Creates the SVG elements needed for this atom view.\n * @param parent The parent SVG element to attach to\n */\n abstract createElements(parent: SVGGraphicsElement): void;\n}\n\n/**\n * A view for leaf atoms (those that cannot contain other atoms).\n */\nexport abstract class LeafAtomView extends AtomView {\n /**\n * Creates a new LeafAtomView.\n * @param leafAtom The leaf atom this view represents\n */\n constructor(public leafAtom: LeafAtom) {\n super();\n }\n\n /**\n * Leaf atom views always return true for isLeaf().\n */\n isLeaf(): boolean {\n return true;\n }\n\n /**\n * Gets a unique identifier for this view based on the atom's UUID.\n */\n get viewId(): number {\n return this.leafAtom.uuid;\n }\n\n /**\n * Returns the total duration of the atom rendered by this view.\n */\n get totalDuration(): TSU.Num.Fraction {\n return this.leafAtom.duration;\n }\n}\n\n/**\n * A view for group atoms that contain multiple child atoms.\n */\nexport abstract class GroupView extends AtomView {\n /** Space between atoms in this group */\n protected atomSpacing: number;\n /** The SVG group element for this view */\n protected groupElement: SVGGElement;\n /** Views for the atoms in this group */\n protected atomViews: AtomView[] = [];\n private _embelishments: Embelishment[];\n /** Whether this group represents notes by default */\n defaultToNotes = true;\n /** Whether this view needs layout */\n needsLayout = true;\n /** Scale factor for this group */\n scaleFactor = 1.0;\n /**\n * When true, shows continuation markers (\",\") for atoms with duration > 1\n * instead of just leaving empty space.\n */\n showContinuationMarkers = true;\n /** SVG elements for continuation markers */\n protected continuationMarkerElements: SVGTextElement[] = [];\n\n /**\n * Creates a new GroupView.\n * @param group The group atom this view represents\n * @param config Optional configuration object\n */\n constructor(\n public group: Group,\n config?: any,\n ) {\n super();\n this.atomSpacing = 5;\n this.setStyles(config || {});\n }\n\n /**\n * Returns the total duration of the group rendered by this view.\n */\n get totalDuration(): TSU.Num.Fraction {\n return this.group.totalChildDuration;\n }\n\n /**\n * Creates the SVG elements needed for this group view.\n * @param parent The parent SVG element to attach to\n */\n createElements(parent: SVGGraphicsElement): void {\n this.groupElement = TSU.DOM.createSVGNode(\"g\", {\n parent: parent,\n attrs: {\n class: \"groupViewRoot\",\n id: \"groupViewRoot\" + this.group.uuid,\n },\n });\n\n // now create child atom views for each atom in this Group\n for (const atom of this.group.atoms.values()) {\n const atomView = this.createAtomView(atom);\n this.atomViews.push(atomView);\n }\n this.invalidateBounds();\n }\n\n /**\n * Group views always return false for isLeaf().\n */\n isLeaf(): boolean {\n return false;\n }\n\n /**\n * Refreshes the bounding box of this group.\n * @returns The refreshed bounding box\n */\n protected refreshBBox(): TSU.Geom.Rect {\n return TSU.DOM.svgBBox(this.groupElement);\n }\n\n /**\n * Refreshes the minimum size of this group using duration-based width calculation.\n *\n * ## Duration-Based Width Algorithm\n *\n * This algorithm ensures atoms with extended durations receive proportionally\n * more horizontal space. For example, with `\\beatDuration(4)` and input `S 2 R G M`:\n * - S has duration 1, R has duration 2, G has duration 1\n * - R should visually occupy twice the horizontal space of S or G\n *\n * ### Algorithm Steps:\n *\n * 1. **Calculate width per duration unit**: For each atom, compute the visual width\n * needed per unit of duration: `(visualWidth + spacing) / duration`\n *\n * 2. **Find maximum**: Take the maximum width-per-duration across all atoms.\n * This ensures every atom has enough space for its visual content.\n *\n * 3. **Scale by total duration**: Multiply the max width-per-duration by the\n * group's total duration to get the final group width.\n *\n * ### Example:\n * ```\n * Atoms: S(dur=1, width=10px), R(dur=2, width=10px), G(dur=1, width=10px)\n * Spacing: 5px\n *\n * Width per duration:\n * S: (10 + 5) / 1 = 15 px/unit\n * R: (10 + 5) / 2 = 7.5 px/unit\n * G: (10 + 5) / 1 = 15 px/unit\n *\n * Max width per duration: 15 px/unit\n * Total duration: 1 + 2 + 1 = 4 units\n * Group width: 15 * 4 = 60px\n *\n * Positioning:\n * S at x=0 (time 0/4 * 60 = 0)\n * R at x=15 (time 1/4 * 60 = 15)\n * G at x=45 (time 3/4 * 60 = 45)\n * ```\n *\n * @returns The refreshed minimum size\n */\n protected refreshMinSize(): TSU.Geom.Size {\n let maxHeight = 0;\n\n // Step 1: Calculate width per duration unit for each atom\n let minWidthPerDuration = 0;\n this.atomViews.forEach((av) => {\n const ms = av.minSize;\n const dur = av.totalDuration;\n if (!dur.isZero) {\n const durValue = dur.num / dur.den;\n const widthPerDur = (ms.width + this.atomSpacing) / durValue;\n // Step 2: Track maximum width per duration\n minWidthPerDuration = Math.max(minWidthPerDuration, widthPerDur);\n }\n maxHeight = Math.max(maxHeight, ms.height);\n });\n\n // Step 3: Scale by total duration\n const totalDuration = this.group.totalChildDuration;\n const totalDurValue = totalDuration.num / totalDuration.den;\n const totalWidth = minWidthPerDuration * totalDurValue;\n\n return new TSU.Geom.Size(totalWidth * this.scaleFactor, maxHeight * this.scaleFactor);\n }\n\n /**\n * Creates an atom view for a specific atom.\n * @param atom The atom to create a view for\n * @returns The created atom view\n */\n abstract createAtomView(atom: Atom): AtomView;\n\n /**\n * Updates the bounds of this group.\n * @param x New x coordinate, or null to keep current value\n * @param y New y coordinate, or null to keep current value\n * @param w New width, or null to keep current value\n * @param h New height, or null to keep current value\n * @returns The updated bounds values\n */\n protected updateBounds(\n x: null | number,\n y: null | number,\n w: null | number,\n h: null | number,\n ): [number | null, number | null, number | null, number | null] {\n return [x, y, w, h];\n }\n\n /**\n * Refreshes the layout of this group using duration-based positioning.\n *\n * ## Duration-Based Positioning Algorithm\n *\n * Atoms are positioned at x-coordinates proportional to their time offset\n * within the group's total duration. This ensures that atoms with extended\n * durations visually occupy the correct amount of horizontal space.\n *\n * ### Width Source Priority:\n *\n * 1. **Column width** (preferred): If width was set via `setBounds()` from the\n * grid layout system (ColAlign), use that width. This enables global alignment\n * across all beats in the same column.\n *\n * 2. **Minimum size**: Fall back to `minSize.width` calculated by `refreshMinSize()`.\n *\n * ### Positioning Formula:\n * ```\n * xPosition = (timeOffset / totalDuration) * groupWidth\n * ```\n *\n * ### Continuation Markers:\n *\n * When `showContinuationMarkers` is true (default), atoms with duration > 1\n * will have \",\" markers rendered at each additional time slot. For example,\n * an atom with duration 2 will show \"R ,\" instead of \"R \".\n *\n * This helps users visually understand that the note continues through\n * multiple time slots without relying on empty space alone.\n *\n * ### Example:\n * ```\n * Input: S 2 R G (with beatDuration=4)\n * Group width: 60px, Total duration: 4 units\n *\n * Positioning:\n * S at x=0 (time 0, offset 0/4 * 60 = 0)\n * R at x=15 (time 1, offset 1/4 * 60 = 15)\n * \",\" at x=30 (continuation marker for R at time 2)\n * G at x=45 (time 3, offset 3/4 * 60 = 45)\n * ```\n */\n refreshLayout(): void {\n let transform = \"translate(\" + this.x + \",\" + this.y + \")\";\n if (this.scaleFactor < 1) {\n transform += \" scale(\" + this.scaleFactor + \")\";\n }\n this.groupElement.setAttribute(\"transform\", transform);\n\n const currY = 0;\n const totalDur = this.group.totalChildDuration;\n\n // Width source priority: column width (for global alignment) > minSize\n const unscaledMinWidth = this.minSize.width / this.scaleFactor;\n const groupWidth = this.hasWidth ? this.width / this.scaleFactor : unscaledMinWidth;\n\n // Clear existing continuation markers before re-rendering\n this.clearContinuationMarkers();\n\n // Position each atom based on its time offset\n let currTime = ZERO;\n this.atomViews.forEach((av, index) => {\n // Calculate where the NOTE GLYPH should appear based on time offset\n const glyphX = totalDur.isZero ? 0 : currTime.timesNum(groupWidth).divby(totalDur).floor;\n // Subtract glyphOffset so left embellishments don't push the glyph past its time position\n // The atom origin is placed earlier, so the glyph ends up at the correct time position\n const xPos = Math.max(0, glyphX - av.glyphOffset);\n av.setBounds(xPos, currY, null, null, true);\n\n // Render continuation markers for atoms with duration > 1\n if (this.showContinuationMarkers && !totalDur.isZero) {\n const atomDur = av.totalDuration;\n const durValue = atomDur.num / atomDur.den;\n if (durValue > 1) {\n // Render one marker at each additional time slot within the atom's duration\n const numMarkers = Math.floor(durValue) - 1;\n for (let i = 1; i <= numMarkers; i++) {\n // Marker time = currTime + (atomDuration * i / floor(duration))\n const markerTime = currTime.plus(atomDur.timesNum(i).divbyNum(Math.floor(durValue)));\n const markerX = markerTime.timesNum(groupWidth).divby(totalDur).floor;\n this.renderContinuationMarker(markerX, currY);\n }\n }\n }\n\n currTime = currTime.plus(av.totalDuration);\n });\n\n this.invalidateBounds();\n for (const e of this.embelishments) e.refreshLayout();\n this.invalidateBounds();\n }\n\n /**\n * Clears all continuation marker elements.\n */\n protected clearContinuationMarkers(): void {\n for (const el of this.continuationMarkerElements) {\n el.remove();\n }\n this.continuationMarkerElements = [];\n }\n\n /**\n * Renders a continuation marker (\",\") at the specified position.\n * @param x X position for the marker\n * @param y Y position for the marker\n */\n protected renderContinuationMarker(x: number, y: number): void {\n const marker = TSU.DOM.createSVGNode(\"text\", {\n parent: this.groupElement,\n attrs: {\n class: \"continuationMarker\",\n x: x.toString(),\n y: y.toString(),\n },\n text: \",\",\n }) as SVGTextElement;\n this.continuationMarkerElements.push(marker);\n }\n\n /**\n * Gets the embellishments for this group.\n */\n get embelishments(): Embelishment[] {\n if (!this._embelishments) {\n this._embelishments = this.createEmbelishments();\n }\n return this._embelishments;\n }\n\n /**\n * Creates the embellishments for this group.\n * @returns An array of embellishments\n */\n protected createEmbelishments(): Embelishment[] {\n return [];\n }\n\n /**\n * Sets the styles for this group.\n * @param config Style configuration object\n */\n setStyles(config: any): void {\n if (\"atomSpacing\" in config) this.atomSpacing = config.atomSpacing;\n if (\"showContinuationMarkers\" in config) this.showContinuationMarkers = config.showContinuationMarkers;\n this.needsLayout = true;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"shapes.js","sourceRoot":"","sources":["../../src/shapes.ts"],"names":[],"mappings":"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","sourcesContent":["import * as TSU from \"@panyam/tsutils\";\nimport { ZERO, Atom, LeafAtom, Group } from \"./core\";\n\n/**\n * Represents an item to be positioned in collision-based layout.\n */\nexport interface CollisionLayoutItem {\n /** Time offset as a fraction (numerator/denominator) */\n timeOffset: TSU.Num.Fraction;\n /** Duration of this item */\n duration: TSU.Num.Fraction;\n /** Width of pre-embellishments (extends left from glyph position) */\n glyphOffset: number;\n /** Minimum width of the item (includes all embellishments and glyph) */\n minWidth: number;\n}\n\n/**\n * Result of collision-based layout for a single item.\n */\nexport interface CollisionLayoutResult {\n /** The calculated x position for the item */\n x: number;\n /** Whether the item was pushed right due to collision */\n wasCollision: boolean;\n}\n\n/**\n * Computes collision-based positions for a sequence of items within a container.\n *\n * ## Algorithm\n *\n * 1. Calculate ideal glyph position: `glyphX = (timeOffset / totalDuration) * containerWidth`\n * 2. Pre-embellishments extend left: `realX = glyphX - glyphOffset`\n * 3. Collision check: if `realX < prevItemEndX`, then `realX = prevItemEndX`\n * 4. Track: `prevItemEndX = realX + minWidth`\n *\n * @param items Items to position (must be in time order)\n * @param totalDuration Total duration of all items\n * @param containerWidth Width of the container to position items within\n * @returns Array of positions for each item\n */\nexport function computeCollisionLayout(\n items: CollisionLayoutItem[],\n totalDuration: TSU.Num.Fraction,\n containerWidth: number,\n): CollisionLayoutResult[] {\n const results: CollisionLayoutResult[] = [];\n let prevItemEndX = 0;\n let currTime = ZERO;\n\n for (const item of items) {\n // 1. Calculate ideal glyph position based on time offset\n const glyphX = totalDuration.isZero ? 0 : currTime.timesNum(containerWidth).divby(totalDuration).floor;\n\n // 2. Pre-embellishments extend left from glyph position\n let realX = glyphX - item.glyphOffset;\n\n // 3. Collision check: push right if overlapping previous item\n const wasCollision = realX < prevItemEndX;\n if (wasCollision) {\n realX = prevItemEndX;\n }\n\n results.push({ x: realX, wasCollision });\n\n // 4. Track end position for next collision check\n prevItemEndX = realX + item.minWidth;\n\n currTime = currTime.plus(item.duration);\n }\n\n return results;\n}\n\n/**\n * Base class for all renderable objects.\n *\n * Shape caches properties like bounding boxes to improve performance,\n * since bounding box calculations can be expensive. This also allows\n * testing layouts and positioning without worrying about implementation details.\n */\nexport abstract class Shape {\n private static idCounter = 0;\n readonly shapeId: number = Shape.idCounter++;\n\n /**\n * Note that x and y coordinates are not always the x and y coordinates\n * of the bounding box.\n * E.g., a circle's x and y coordinates are its center point and not the\n * top left corner.\n * These \"main\" coordinates are referred to as control coordinates.\n */\n protected _x: number | null = null;\n protected _y: number | null = null;\n protected _width: number | null = null;\n protected _height: number | null = null;\n protected _bbox: TSU.Geom.Rect;\n protected _minSize: TSU.Geom.Size;\n protected parentShape: Shape | null = null;\n /** Child shapes contained within this shape */\n children: Shape[] = [];\n\n /**\n * Gets the bounding box of this shape.\n * Calculates it if it hasn't been calculated yet.\n */\n get bbox(): TSU.Geom.Rect {\n if (!this._bbox) {\n this._bbox = this.refreshBBox();\n }\n return this._bbox;\n }\n\n /**\n * Gets the minimum size of this shape.\n * This is usually the size of the bounding box.\n */\n get minSize(): TSU.Geom.Size {\n if (!this._minSize) {\n this._minSize = this.refreshMinSize();\n }\n return this._minSize;\n }\n\n /**\n * Refreshes the bounding box of this shape.\n * Called when the shape knows the bbox it is tracking cannot be trusted\n * and has to be refreshed by calling native methods.\n * @returns The refreshed bounding box\n */\n protected abstract refreshBBox(): TSU.Geom.Rect;\n\n /**\n * Refreshes the minimum size of this shape.\n * @returns The refreshed minimum size\n */\n protected abstract refreshMinSize(): TSU.Geom.Size;\n\n /**\n * Updates the bounds of this shape.\n * @param x New x coordinate, or null to keep current value\n * @param y New y coordinate, or null to keep current value\n * @param w New width, or null to keep current value\n * @param h New height, or null to keep current value\n * @returns The updated bounds values\n */\n protected abstract updateBounds(\n x: null | number,\n y: null | number,\n w: null | number,\n h: null | number,\n ): [number | null, number | null, number | null, number | null];\n\n /**\n * Invalidates the cached bounds of this shape.\n * Forces recalculation of bounding box and minimum size.\n */\n invalidateBounds(): void {\n this._minSize = null as unknown as TSU.Geom.Size;\n this._bbox = null as unknown as TSU.Geom.Rect;\n }\n\n /**\n * Sets the bounds of this shape.\n *\n * Note that null and NaN are valid values and mean the following:\n * - null: Don't change the value\n * - NaN: Set the value to null (use the bounding box's value)\n *\n * @param x New x coordinate, or null to keep current value\n * @param y New y coordinate, or null to keep current value\n * @param w New width, or null to keep current value\n * @param h New height, or null to keep current value\n * @param applyLayout Whether to apply layout immediately\n * @returns The updated bounds values\n */\n setBounds(\n x: number | null,\n y: number | null,\n w: number | null,\n h: number | null,\n applyLayout = false,\n ): [number | null, number | null, number | null, number | null] {\n if (x != null) {\n if (isNaN(x)) {\n this._x = null;\n } else {\n this._x = x;\n }\n }\n if (y != null) {\n if (isNaN(y)) {\n this._y = null;\n } else {\n this._y = y;\n }\n }\n if (w != null) {\n if (isNaN(w)) {\n this._width = null;\n } else {\n this._width = w;\n }\n }\n if (h != null) {\n if (isNaN(h)) {\n this._height = null;\n } else {\n this._height = h;\n }\n }\n const [nx, ny, nw, nh] = this.updateBounds(x, y, w, h);\n if (nx != null) {\n if (isNaN(nx)) {\n this._x = null;\n } else {\n this._x = nx;\n }\n }\n if (ny != null) {\n if (isNaN(ny)) {\n this._y = null;\n } else {\n this._y = ny;\n }\n }\n if (nw != null) {\n if (isNaN(nw)) {\n this._width = null;\n } else {\n this._width = nw;\n }\n }\n if (nh != null) {\n if (isNaN(nh)) {\n this._height = null;\n } else {\n this._height = nh;\n }\n }\n if (applyLayout) this.refreshLayout();\n // this.resetBBox();\n return [nx, ny, nw, nh];\n }\n\n /**\n * Checks if this shape has an explicit x coordinate.\n */\n get hasX(): boolean {\n return this._x != null && !isNaN(this._x);\n }\n\n /**\n * Checks if this shape has an explicit y coordinate.\n */\n get hasY(): boolean {\n return this._y != null && !isNaN(this._y);\n }\n\n /**\n * Checks if this shape has an explicit width.\n */\n get hasWidth(): boolean {\n return this._width != null && !isNaN(this._width);\n }\n\n /**\n * Checks if this shape has an explicit height.\n */\n get hasHeight(): boolean {\n return this._height != null && !isNaN(this._height);\n }\n\n /**\n * Gets the x coordinate within the parent's coordinate system.\n */\n get x(): number {\n return this._x || 0;\n }\n\n /**\n * Sets the x coordinate within the parent's coordinate system.\n */\n set x(x: number | null) {\n // Here a manual x is being set - how does this interfere with the bounding box?\n // We should _x to the new value to indicate a manual value was set.\n // and reset bbox so that based on this x a new bbox may need to be calculated\n this.setBounds(x == null ? NaN : x, null, null, null);\n }\n\n /**\n * Gets the y coordinate within the parent's coordinate system.\n */\n get y(): number {\n if (this._y != null) return this._y;\n return 0; // this.bbox.y;\n }\n\n /**\n * Sets the y coordinate within the parent's coordinate system.\n */\n set y(y: number | null) {\n this.setBounds(null, y == null ? NaN : y, null, null);\n }\n\n /**\n * Gets the width of this shape.\n */\n get width(): number {\n if (this._width != null) return this._width;\n return 0; // this.bbox.width;\n }\n\n /**\n * Sets the width of this shape.\n */\n set width(w: number | null) {\n this.setBounds(null, null, w == null ? NaN : w, null);\n }\n\n /**\n * Gets the height of this shape.\n */\n get height(): number {\n if (this._height != null) return this._height;\n return 0; // this.bbox.height;\n }\n\n /**\n * Sets the height of this shape.\n */\n set height(h: number | null) {\n this.setBounds(null, null, null, h == null ? NaN : h);\n }\n\n /**\n * Refreshes the layout of this shape.\n * Called when bounds or other properties have changed to give the shape an\n * opportunity to layout its children. For shapes with no children this is a no-op.\n */\n refreshLayout(): void {\n // throw new Error(\"Implement this\");\n }\n}\n\n/**\n * Represents an embellishment applied to a musical element.\n */\nexport abstract class Embelishment extends Shape {}\n\n/**\n * A shape that wraps an SVG element.\n * ElementShape provides the base class for all shapes that are rendered as SVG elements.\n */\nexport class ElementShape<T extends SVGGraphicsElement = SVGGraphicsElement> extends Shape {\n /**\n * Creates a new ElementShape.\n * @param element The SVG element this shape wraps\n */\n constructor(public readonly element: T) {\n super();\n }\n\n /**\n * Refreshes the bounding box of this element.\n * @returns The refreshed bounding box\n */\n protected refreshBBox(): TSU.Geom.Rect {\n return TSU.DOM.svgBBox(this.element);\n }\n\n /**\n * Refreshes the minimum size of this element.\n * @returns The refreshed minimum size\n */\n protected refreshMinSize(): TSU.Geom.Size {\n return TSU.DOM.svgBBox(this.element);\n }\n\n /**\n * Updates the bounds of this element.\n * @param x New x coordinate, or null to keep current value\n * @param y New y coordinate, or null to keep current value\n * @param w New width, or null to keep current value\n * @param h New height, or null to keep current value\n * @returns The updated bounds values\n */\n protected updateBounds(\n x: null | number,\n y: null | number,\n w: null | number,\n h: null | number,\n ): [number | null, number | null, number | null, number | null] {\n return [x, y, w, h];\n }\n\n /**\n * Refreshes the layout of this element.\n * Updates the element's attributes based on the shape's properties.\n */\n refreshLayout(): void {\n if (this.hasX) this.element.setAttribute(\"x\", \"\" + this._x);\n if (this.hasY) this.element.setAttribute(\"y\", \"\" + this._y);\n }\n}\n\n/**\n * Base class for views that represent atoms in the notation.\n * AtomView provides the visual representation of an atom.\n */\nexport abstract class AtomView extends Shape {\n /** Nesting depth of this atom in the structure */\n depth = 0;\n /** Index of the role containing this atom */\n roleIndex = 0;\n\n // LayoutMetrics for the AtomView so all atomviews laid out on the\n // same baseline will show up aligned vertically\n /** Baseline position for vertical alignment */\n baseline: number;\n /** Ascent (space above baseline) */\n ascent: number;\n /** Descent (space below baseline) */\n descent: number;\n /** Height of capital letters */\n capHeight: number;\n /** Space between lines */\n leading: number;\n\n /**\n * Checks if this atom view represents a leaf atom.\n */\n abstract isLeaf(): boolean;\n\n abstract get totalDuration(): TSU.Num.Fraction;\n\n /**\n * Returns the horizontal offset from the atom's origin to where the note glyph starts.\n * This accounts for left embellishments that appear before the note.\n * Used by GroupView to align note glyphs at their correct time positions.\n *\n * Default is 0 (glyph starts at origin). Subclasses with left embellishments\n * should override to return the width of left-side decorations.\n */\n get glyphOffset(): number {\n return 0;\n }\n\n /**\n * Creates the SVG elements needed for this atom view.\n * @param parent The parent SVG element to attach to\n */\n abstract createElements(parent: SVGGraphicsElement): void;\n}\n\n/**\n * A view for leaf atoms (those that cannot contain other atoms).\n */\nexport abstract class LeafAtomView extends AtomView {\n /**\n * Creates a new LeafAtomView.\n * @param leafAtom The leaf atom this view represents\n */\n constructor(public leafAtom: LeafAtom) {\n super();\n }\n\n /**\n * Leaf atom views always return true for isLeaf().\n */\n isLeaf(): boolean {\n return true;\n }\n\n /**\n * Gets a unique identifier for this view based on the atom's UUID.\n */\n get viewId(): number {\n return this.leafAtom.uuid;\n }\n\n /**\n * Returns the total duration of the atom rendered by this view.\n */\n get totalDuration(): TSU.Num.Fraction {\n return this.leafAtom.duration;\n }\n}\n\n/**\n * A view for group atoms that contain multiple child atoms.\n */\nexport abstract class GroupView extends AtomView {\n /** Space between atoms in this group */\n protected atomSpacing: number;\n /** The SVG group element for this view */\n protected groupElement: SVGGElement;\n /** Views for the atoms in this group */\n protected atomViews: AtomView[] = [];\n private _embelishments: Embelishment[];\n /** Whether this group represents notes by default */\n defaultToNotes = true;\n /** Whether this view needs layout */\n needsLayout = true;\n /** Scale factor for this group */\n scaleFactor = 1.0;\n /**\n * When true, shows continuation markers (\",\") for atoms with duration > 1\n * instead of just leaving empty space.\n */\n showContinuationMarkers = true;\n /** SVG elements for continuation markers */\n protected continuationMarkerElements: SVGTextElement[] = [];\n\n /**\n * Creates a new GroupView.\n * @param group The group atom this view represents\n * @param config Optional configuration object\n */\n constructor(\n public group: Group,\n config?: any,\n ) {\n super();\n this.atomSpacing = 5;\n this.setStyles(config || {});\n }\n\n /**\n * Returns the total duration of the group rendered by this view.\n */\n get totalDuration(): TSU.Num.Fraction {\n return this.group.totalChildDuration;\n }\n\n /**\n * Creates the SVG elements needed for this group view.\n * @param parent The parent SVG element to attach to\n */\n createElements(parent: SVGGraphicsElement): void {\n this.groupElement = TSU.DOM.createSVGNode(\"g\", {\n parent: parent,\n attrs: {\n class: \"groupViewRoot\",\n id: \"groupViewRoot\" + this.group.uuid,\n },\n });\n\n // now create child atom views for each atom in this Group\n for (const atom of this.group.atoms.values()) {\n const atomView = this.createAtomView(atom);\n this.atomViews.push(atomView);\n }\n this.invalidateBounds();\n }\n\n /**\n * Group views always return false for isLeaf().\n */\n isLeaf(): boolean {\n return false;\n }\n\n /**\n * Refreshes the bounding box of this group.\n * @returns The refreshed bounding box\n */\n protected refreshBBox(): TSU.Geom.Rect {\n return TSU.DOM.svgBBox(this.groupElement);\n }\n\n /**\n * Refreshes the minimum size of this group using duration-based width calculation.\n *\n * ## Duration-Based Width Algorithm\n *\n * This algorithm ensures atoms with extended durations receive proportionally\n * more horizontal space. For example, with `\\beatDuration(4)` and input `S 2 R G M`:\n * - S has duration 1, R has duration 2, G has duration 1\n * - R should visually occupy twice the horizontal space of S or G\n *\n * ### Algorithm Steps:\n *\n * 1. **Calculate width per duration unit**: For each atom, compute the visual width\n * needed per unit of duration: `(visualWidth + spacing) / duration`\n *\n * 2. **Find maximum**: Take the maximum width-per-duration across all atoms.\n * This ensures every atom has enough space for its visual content.\n *\n * 3. **Scale by total duration**: Multiply the max width-per-duration by the\n * group's total duration to get the final group width.\n *\n * ### Example:\n * ```\n * Atoms: S(dur=1, width=10px), R(dur=2, width=10px), G(dur=1, width=10px)\n * Spacing: 5px\n *\n * Width per duration:\n * S: (10 + 5) / 1 = 15 px/unit\n * R: (10 + 5) / 2 = 7.5 px/unit\n * G: (10 + 5) / 1 = 15 px/unit\n *\n * Max width per duration: 15 px/unit\n * Total duration: 1 + 2 + 1 = 4 units\n * Group width: 15 * 4 = 60px\n *\n * Positioning:\n * S at x=0 (time 0/4 * 60 = 0)\n * R at x=15 (time 1/4 * 60 = 15)\n * G at x=45 (time 3/4 * 60 = 45)\n * ```\n *\n * @returns The refreshed minimum size\n */\n protected refreshMinSize(): TSU.Geom.Size {\n let maxHeight = 0;\n\n // Step 1: Calculate width per duration unit for each atom\n let minWidthPerDuration = 0;\n this.atomViews.forEach((av) => {\n const ms = av.minSize;\n const dur = av.totalDuration;\n if (!dur.isZero) {\n const durValue = dur.num / dur.den;\n const widthPerDur = (ms.width + this.atomSpacing) / durValue;\n // Step 2: Track maximum width per duration\n minWidthPerDuration = Math.max(minWidthPerDuration, widthPerDur);\n }\n maxHeight = Math.max(maxHeight, ms.height);\n });\n\n // Step 3: Scale by total duration\n const totalDuration = this.group.totalChildDuration;\n const totalDurValue = totalDuration.num / totalDuration.den;\n const totalWidth = minWidthPerDuration * totalDurValue;\n\n return new TSU.Geom.Size(totalWidth * this.scaleFactor, maxHeight * this.scaleFactor);\n }\n\n /**\n * Creates an atom view for a specific atom.\n * @param atom The atom to create a view for\n * @returns The created atom view\n */\n abstract createAtomView(atom: Atom): AtomView;\n\n /**\n * Updates the bounds of this group.\n * @param x New x coordinate, or null to keep current value\n * @param y New y coordinate, or null to keep current value\n * @param w New width, or null to keep current value\n * @param h New height, or null to keep current value\n * @returns The updated bounds values\n */\n protected updateBounds(\n x: null | number,\n y: null | number,\n w: null | number,\n h: null | number,\n ): [number | null, number | null, number | null, number | null] {\n return [x, y, w, h];\n }\n\n /**\n * Refreshes the layout of this group using collision-based positioning.\n *\n * ## Collision-Based Layout Algorithm\n *\n * Atoms are positioned using time-based positioning with collision avoidance.\n * Each atom starts at its ideal time-based position, but is pushed right if\n * it would overlap with the previous atom (including embellishments).\n *\n * ### Algorithm:\n * ```\n * 1. Calculate ideal glyph position: glyphX = (time / totalDuration) * groupWidth\n * 2. Pre-embellishments extend left: realX = glyphX - preEmbellishmentWidth\n * 3. Collision check: if (realX < prevNoteEndX) realX = prevNoteEndX\n * 4. Position the atom at realX\n * 5. Track: prevNoteEndX = realX + atom.minSize.width\n * ```\n *\n * ### Width Source Priority:\n *\n * 1. **Column width** (preferred): If width was set via `setBounds()` from the\n * grid layout system (ColAlign), use that width. This enables global alignment\n * across all beats in the same column.\n *\n * 2. **Minimum size**: Fall back to `minSize.width` calculated by `refreshMinSize()`.\n *\n * ### Continuation Markers:\n *\n * When `showContinuationMarkers` is true (default), atoms with duration > 1\n * will have \",\" markers rendered at each additional time slot. For example,\n * an atom with duration 2 will show \"R ,\" instead of \"R \".\n *\n * ### Example (no collisions):\n * ```\n * Input: S R G M (equal duration, no embellishments)\n * Group width: 60px, Total duration: 4 units\n *\n * Positioning:\n * S at x=0 (time 0/4 * 60 = 0)\n * R at x=15 (time 1/4 * 60 = 15)\n * G at x=30 (time 2/4 * 60 = 30)\n * M at x=45 (time 3/4 * 60 = 45)\n * ```\n *\n * ### Example (with collision):\n * ```\n * Input: [Jaaru+S] R (S has 10px pre-embellishment, each atom 15px wide)\n * Group width: 60px, Total duration: 2 units\n *\n * Without collision avoidance:\n * S.glyphX = 0, S.realX = 0 - 10 = -10 (clamped to 0)\n * R.glyphX = 30, R overlaps with S\n *\n * With collision avoidance:\n * S at x=0 (prevNoteEndX becomes 15)\n * R.glyphX = 30, R.realX = 30 - 0 = 30\n * 30 >= 15, no collision, R at x=30\n * ```\n */\n refreshLayout(): void {\n let transform = \"translate(\" + this.x + \",\" + this.y + \")\";\n if (this.scaleFactor < 1) {\n transform += \" scale(\" + this.scaleFactor + \")\";\n }\n this.groupElement.setAttribute(\"transform\", transform);\n\n const currY = 0;\n const totalDur = this.group.totalChildDuration;\n\n // Width source priority: column width (for global alignment) > minSize\n const unscaledMinWidth = this.minSize.width / this.scaleFactor;\n const groupWidth = this.hasWidth ? this.width / this.scaleFactor : unscaledMinWidth;\n\n // Clear existing continuation markers before re-rendering\n this.clearContinuationMarkers();\n\n // Position each atom using collision-based layout\n // Atoms start at their time-based position, but are pushed right if they would\n // overlap with the previous atom (including embellishments)\n let currTime = ZERO;\n let prevNoteEndX = 0;\n this.atomViews.forEach((av, index) => {\n // 1. Calculate ideal glyph position based on time offset\n const glyphX = totalDur.isZero ? 0 : currTime.timesNum(groupWidth).divby(totalDur).floor;\n\n // 2. Pre-embellishments extend left from glyph position\n // realX is where the atom origin should be placed\n let realX = glyphX - av.glyphOffset;\n\n // 3. Collision check: push right if overlapping previous atom\n if (realX < prevNoteEndX) {\n realX = prevNoteEndX;\n }\n\n // 4. Position the atom\n av.setBounds(realX, currY, null, null, true);\n\n // 5. Track end position for next collision check\n prevNoteEndX = realX + av.minSize.width;\n\n // Render continuation markers for atoms with duration > 1\n if (this.showContinuationMarkers && !totalDur.isZero) {\n const atomDur = av.totalDuration;\n const durValue = atomDur.num / atomDur.den;\n if (durValue > 1) {\n // Render one marker at each additional time slot within the atom's duration\n const numMarkers = Math.floor(durValue) - 1;\n for (let i = 1; i <= numMarkers; i++) {\n // Marker time = currTime + (atomDuration * i / floor(duration))\n const markerTime = currTime.plus(atomDur.timesNum(i).divbyNum(Math.floor(durValue)));\n const markerX = markerTime.timesNum(groupWidth).divby(totalDur).floor;\n this.renderContinuationMarker(markerX, currY);\n }\n }\n }\n\n currTime = currTime.plus(av.totalDuration);\n });\n\n this.invalidateBounds();\n for (const e of this.embelishments) e.refreshLayout();\n this.invalidateBounds();\n }\n\n /**\n * Clears all continuation marker elements.\n */\n protected clearContinuationMarkers(): void {\n for (const el of this.continuationMarkerElements) {\n el.remove();\n }\n this.continuationMarkerElements = [];\n }\n\n /**\n * Renders a continuation marker (\",\") at the specified position.\n * @param x X position for the marker\n * @param y Y position for the marker\n */\n protected renderContinuationMarker(x: number, y: number): void {\n const marker = TSU.DOM.createSVGNode(\"text\", {\n parent: this.groupElement,\n attrs: {\n class: \"continuationMarker\",\n x: x.toString(),\n y: y.toString(),\n },\n text: \",\",\n }) as SVGTextElement;\n this.continuationMarkerElements.push(marker);\n }\n\n /**\n * Gets the embellishments for this group.\n */\n get embelishments(): Embelishment[] {\n if (!this._embelishments) {\n this._embelishments = this.createEmbelishments();\n }\n return this._embelishments;\n }\n\n /**\n * Creates the embellishments for this group.\n * @returns An array of embellishments\n */\n protected createEmbelishments(): Embelishment[] {\n return [];\n }\n\n /**\n * Sets the styles for this group.\n * @param config Style configuration object\n */\n setStyles(config: any): void {\n if (\"atomSpacing\" in config) this.atomSpacing = config.atomSpacing;\n if (\"showContinuationMarkers\" in config) this.showContinuationMarkers = config.showContinuationMarkers;\n this.needsLayout = true;\n }\n}\n"]}
|
package/lib/esm/block.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { Entity } from "./entity";
|
|
|
3
3
|
import { Cycle } from "./cycle";
|
|
4
4
|
import { Line } from "./core";
|
|
5
5
|
import { LayoutParams } from "./layouts";
|
|
6
|
+
import { BlockObserver } from "./events";
|
|
6
7
|
export declare class RoleDef {
|
|
7
8
|
name: string;
|
|
8
9
|
notesOnly: boolean;
|
|
@@ -31,7 +32,10 @@ export declare class Block extends Entity {
|
|
|
31
32
|
private _parentBlock;
|
|
32
33
|
protected _currRoleDef: TSU.Nullable<RoleDef>;
|
|
33
34
|
protected _currentLine: TSU.Nullable<Line>;
|
|
35
|
+
private _observers;
|
|
34
36
|
constructor(blockType: string, parent?: TSU.Nullable<Block>, name?: TSU.Nullable<string>);
|
|
37
|
+
addObserver(observer: BlockObserver<BlockItem, Block>): () => void;
|
|
38
|
+
removeObserver(observer: BlockObserver<BlockItem, Block>): void;
|
|
35
39
|
children(): BlockItem[];
|
|
36
40
|
get parentBlock(): TSU.Nullable<Block>;
|
|
37
41
|
get cycle(): TSU.Nullable<Cycle>;
|
package/lib/esm/block.js
CHANGED
|
@@ -40,6 +40,7 @@ export class Block extends Entity {
|
|
|
40
40
|
this._parentBlock = null;
|
|
41
41
|
this._currRoleDef = null;
|
|
42
42
|
this._currentLine = null;
|
|
43
|
+
this._observers = [];
|
|
43
44
|
this._unnamedLayoutParams = [];
|
|
44
45
|
this._namedLayoutParams = new Map();
|
|
45
46
|
this._layoutParams = null;
|
|
@@ -50,6 +51,16 @@ export class Block extends Entity {
|
|
|
50
51
|
this.setParent(parent);
|
|
51
52
|
}
|
|
52
53
|
}
|
|
54
|
+
addObserver(observer) {
|
|
55
|
+
this._observers.push(observer);
|
|
56
|
+
return () => this.removeObserver(observer);
|
|
57
|
+
}
|
|
58
|
+
removeObserver(observer) {
|
|
59
|
+
const index = this._observers.indexOf(observer);
|
|
60
|
+
if (index >= 0) {
|
|
61
|
+
this._observers.splice(index, 1);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
53
64
|
children() {
|
|
54
65
|
return this.blockItems;
|
|
55
66
|
}
|
|
@@ -195,14 +206,27 @@ export class Block extends Entity {
|
|
|
195
206
|
return rd;
|
|
196
207
|
}
|
|
197
208
|
addBlockItem(item) {
|
|
209
|
+
var _a;
|
|
210
|
+
const index = this.blockItems.length;
|
|
198
211
|
item.setParent(this);
|
|
199
212
|
this.blockItems.push(item);
|
|
213
|
+
if (this._eventsEnabled) {
|
|
214
|
+
for (const observer of this._observers) {
|
|
215
|
+
(_a = observer.onItemAdded) === null || _a === void 0 ? void 0 : _a.call(observer, this, item, index);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
200
218
|
}
|
|
201
219
|
removeBlockItem(item) {
|
|
220
|
+
var _a;
|
|
202
221
|
const index = this.blockItems.indexOf(item);
|
|
203
222
|
if (index >= 0) {
|
|
204
223
|
this.blockItems.splice(index, 1);
|
|
205
224
|
item.setParent(null);
|
|
225
|
+
if (this._eventsEnabled) {
|
|
226
|
+
for (const observer of this._observers) {
|
|
227
|
+
(_a = observer.onItemRemoved) === null || _a === void 0 ? void 0 : _a.call(observer, this, item, index);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
206
230
|
}
|
|
207
231
|
return index;
|
|
208
232
|
}
|
package/lib/esm/block.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"block.js","sourceRoot":"","sources":["../../src/block.ts"],"names":[],"mappings":"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","sourcesContent":["import * as TSU from \"@panyam/tsutils\";\nimport { Entity } from \"./entity\";\nimport { Cycle } from \"./cycle\";\nimport { Line } from \"./core\";\nimport { LayoutParams } from \"./layouts\";\n\n/**\n * Definition of a role in a block context.\n * This is used for block-scoped role definitions.\n */\nexport class RoleDef {\n /** Name of the role */\n name = \"\";\n\n /** Whether this role contains only notes (true) or can also contain syllables/text (false) */\n notesOnly = false;\n\n /** Index of this role in the notation */\n index = 0;\n}\n\n/**\n * Represents a raw block of content in the notation.\n * Raw blocks can contain arbitrary content like markdown, HTML, etc.\n */\nexport class RawBlock extends Entity {\n readonly TYPE: string = \"RawBlock\";\n\n /**\n * Creates a new RawBlock.\n * @param content The content of the block\n * @param contentType The type of content (e.g., \"md\" for markdown)\n */\n constructor(\n public content: string,\n public contentType: string = \"md\",\n ) {\n super();\n }\n\n /**\n * Returns a debug-friendly representation of this raw block.\n * @returns An object containing debug information\n */\n debugValue(): any {\n return { ...super.debugValue(), content: this.content, contentType: this.contentType };\n }\n}\n\n/**\n * Union type for items that can appear in a block.\n */\nexport type BlockItem = Block | Line | RawBlock;\n\n/**\n * Type guard to check if an entity is a Block.\n */\nexport function isBlock(item: BlockItem): item is Block {\n return item.TYPE === \"Block\";\n}\n\n/**\n * Type guard to check if an entity is a Line.\n */\nexport function isLine(item: BlockItem): item is Line {\n return item.TYPE === \"Line\";\n}\n\n/**\n * Type guard to check if an entity is a RawBlock.\n */\nexport function isRawBlock(item: BlockItem): item is RawBlock {\n return item.TYPE === \"RawBlock\";\n}\n\n/**\n * Represents a scoped block created by a command with braces.\n * For example: \\section(\"Pallavi\") { ... }\n *\n * Blocks inherit properties from their parent Block and can override them locally.\n * Properties are resolved lazily by walking up the tree.\n *\n * Block = Command + Children (unified model)\n */\nexport class Block extends Entity {\n readonly TYPE: string = \"Block\";\n\n /** The type of block (e.g., \"section\", \"repeat\", \"cycle\") */\n readonly blockType: string;\n\n /** Optional name for the block (e.g., section name) */\n readonly name: TSU.Nullable<string>;\n\n /** Child items (before expansion by subclasses) */\n readonly blockItems: BlockItem[] = [];\n\n // Local properties\n localCycle: TSU.Nullable<Cycle> = null;\n localAtomsPerBeat: TSU.Nullable<number> = null;\n localBreaks: TSU.Nullable<number[]> = null;\n readonly localRoles = new Map<string, RoleDef>();\n\n // Store parent reference (Block or null for root)\n private _parentBlock: TSU.Nullable<Block> = null;\n\n // State tracking for command application (protected for Notation override)\n protected _currRoleDef: TSU.Nullable<RoleDef> = null;\n protected _currentLine: TSU.Nullable<Line> = null;\n\n /**\n * Creates a new Block.\n * @param blockType The type of block (e.g., \"section\", \"group\")\n * @param parent The parent block (null for root)\n * @param name Optional name for the block\n */\n constructor(blockType: string, parent: TSU.Nullable<Block> = null, name: TSU.Nullable<string> = null) {\n super();\n this.blockType = blockType;\n this.name = name;\n this._parentBlock = parent;\n // Also set Entity's parent for tree traversal\n if (parent) {\n this.setParent(parent);\n }\n }\n\n /**\n * Returns the expanded children for layout iteration.\n * Subclasses can override this to transform children (e.g., Repeat, Section).\n */\n children(): BlockItem[] {\n return this.blockItems;\n }\n\n /**\n * Gets the parent block.\n */\n get parentBlock(): TSU.Nullable<Block> {\n return this._parentBlock;\n }\n\n // ============================================\n // Property inheritance via tree walking\n // ============================================\n\n /**\n * Gets the effective cycle by walking up the tree.\n */\n get cycle(): TSU.Nullable<Cycle> {\n if (this.localCycle !== null) {\n return this.localCycle;\n }\n return this.parentBlock?.cycle ?? null;\n }\n\n /**\n * Gets the effective atoms per beat by walking up the tree.\n * Defaults to 1 if not set anywhere in the tree.\n */\n get atomsPerBeat(): number {\n if (this.localAtomsPerBeat !== null) {\n return this.localAtomsPerBeat;\n }\n return this.parentBlock?.atomsPerBeat ?? 1;\n }\n\n /**\n * Gets the effective line breaks by walking up the tree.\n * Defaults to empty array if not set anywhere.\n */\n get breaks(): number[] {\n if (this.localBreaks !== null) {\n return this.localBreaks;\n }\n return this.parentBlock?.breaks ?? [];\n }\n\n // ============================================\n // Layout parameters management\n // ============================================\n\n /** Layout parameters caching for this block scope */\n private _unnamedLayoutParams: LayoutParams[] = [];\n private _namedLayoutParams = new Map<string, LayoutParams>();\n private _layoutParams: LayoutParams | null = null;\n\n /**\n * Gets the unnamed layout parameters for this block.\n */\n get unnamedLayoutParams(): ReadonlyArray<LayoutParams> {\n return this._unnamedLayoutParams;\n }\n\n /**\n * Gets the named layout parameters for this block.\n */\n get namedLayoutParams(): ReadonlyMap<string, LayoutParams> {\n return this._namedLayoutParams;\n }\n\n /**\n * Gets the current layout parameters for this block scope.\n * Uses the effective cycle, atomsPerBeat, and breaks from tree walking.\n * Creates or finds a matching LayoutParams if needed.\n */\n get layoutParams(): LayoutParams {\n if (this._layoutParams == null) {\n // Find or create layout params matching current effective values\n this._layoutParams = this.findUnnamedLayoutParams();\n if (this._layoutParams == null) {\n this._layoutParams = this.snapshotLayoutParams();\n this._unnamedLayoutParams.push(this._layoutParams);\n }\n }\n return this._layoutParams;\n }\n\n /**\n * Resets the current layout parameters to null.\n * Called when layout-affecting properties change.\n */\n resetLayoutParams(): void {\n this._layoutParams = null;\n this.resetLine();\n }\n\n /**\n * Creates a snapshot of the current layout parameters.\n * @returns A new LayoutParams object with the current effective settings\n */\n protected snapshotLayoutParams(): LayoutParams {\n const effectiveCycle = this.cycle;\n if (effectiveCycle == null) {\n throw new Error(\"Cannot create layout params: no cycle defined\");\n }\n return new LayoutParams({\n cycle: effectiveCycle,\n beatDuration: this.atomsPerBeat,\n layout: this.breaks,\n });\n }\n\n /**\n * Finds an unnamed layout parameters object that matches the current effective settings.\n * @returns Matching layout parameters, or null if none found\n */\n protected findUnnamedLayoutParams(): LayoutParams | null {\n const effectiveCycle = this.cycle;\n if (effectiveCycle == null) return null;\n\n return (\n this._unnamedLayoutParams.find((lp) => {\n return (\n lp.beatDuration == this.atomsPerBeat && effectiveCycle.equals(lp.cycle) && lp.lineBreaksEqual(this.breaks)\n );\n }) || null\n );\n }\n\n /**\n * Ensures that named layout parameters with the given name exist.\n * @param name The name of the layout parameters\n * @returns The layout parameters\n */\n ensureNamedLayoutParams(name: string): LayoutParams {\n let lp = this._namedLayoutParams.get(name) || null;\n if (lp == null || this._layoutParams != lp) {\n if (lp == null) {\n // Create new named layout params\n lp = this.snapshotLayoutParams();\n this._namedLayoutParams.set(name, lp);\n } else {\n // Copy named LPs attributes into our locals\n this.localCycle = lp.cycle;\n this.localAtomsPerBeat = lp.beatDuration;\n this.localBreaks = lp.lineBreaks;\n }\n this._layoutParams = lp;\n this.resetLine();\n }\n return this._layoutParams!;\n }\n\n /**\n * Gets a role definition by name, walking up the tree if not found locally.\n * @param name The name of the role\n */\n getRole(name: string): TSU.Nullable<RoleDef> {\n const local = this.localRoles.get(name.toLowerCase());\n if (local) {\n return local;\n }\n return this.parentBlock?.getRole(name) ?? null;\n }\n\n // ============================================\n // State tracking for command application\n // ============================================\n\n /**\n * Gets the current role definition.\n * Falls back to parent's current role or the last defined role.\n */\n get currRoleDef(): TSU.Nullable<RoleDef> {\n if (this._currRoleDef !== null) {\n return this._currRoleDef;\n }\n // Fall back to parent's current role\n if (this.parentBlock) {\n return this.parentBlock.currRoleDef;\n }\n // Or use the last locally defined role\n const roles = Array.from(this.localRoles.values());\n return roles.length > 0 ? roles[roles.length - 1] : null;\n }\n\n /**\n * Sets the current role by name.\n * If the role doesn't exist, tries to create it via the root container's onMissingRole.\n * @param name The name of the role to activate\n * @throws Error if the role is not found and cannot be created\n */\n setCurrRole(name: string): void {\n name = name.trim().toLowerCase();\n if (name === \"\") {\n throw new Error(\"Role name cannot be empty\");\n }\n let roleDef = this.getRole(name);\n // If role not found, try auto-creation\n if (roleDef == null) {\n // Create the role locally in this block\n // Default: \"sw\" is notes-only, others are not\n roleDef = this.newRoleDef(name, name === \"sw\");\n }\n this._currRoleDef = roleDef;\n }\n\n /**\n * Gets the current line, creating one if needed.\n */\n get currentLine(): Line {\n if (this._currentLine === null) {\n return this.newLine();\n }\n return this._currentLine;\n }\n\n /**\n * Creates a new line in this block.\n */\n newLine(): Line {\n if (this._currentLine !== null && this._currentLine.isEmpty) {\n // Remove empty line before creating new one\n this.removeBlockItem(this._currentLine);\n }\n this._currentLine = new Line();\n this.addBlockItem(this._currentLine);\n return this._currentLine;\n }\n\n /**\n * Resets the current line pointer to null.\n * Called when layout parameters change to force a new line.\n */\n resetLine(): void {\n this._currentLine = null;\n }\n\n /**\n * Creates a new role definition local to this block.\n * @param name The name of the role\n * @param notesOnly Whether this role contains only notes\n */\n newRoleDef(name: string, notesOnly = false): RoleDef {\n name = name.trim().toLowerCase();\n if (name === \"\") {\n throw new Error(\"Role name cannot be empty\");\n }\n if (this.localRoles.has(name)) {\n throw new Error(`Role '${name}' already exists in this block`);\n }\n const rd = new RoleDef();\n rd.name = name;\n rd.notesOnly = notesOnly;\n rd.index = this.localRoles.size;\n this.localRoles.set(name, rd);\n return rd;\n }\n\n // ============================================\n // Child management\n // ============================================\n\n /**\n * Adds a child item to this block.\n * @param item The item to add\n */\n addBlockItem(item: BlockItem): void {\n item.setParent(this);\n this.blockItems.push(item);\n }\n\n /**\n * Removes a child item from this block.\n * @param item The item to remove\n * @returns The index of the removed item, or -1 if not found\n */\n removeBlockItem(item: BlockItem): number {\n const index = this.blockItems.indexOf(item);\n if (index >= 0) {\n this.blockItems.splice(index, 1);\n item.setParent(null);\n }\n return index;\n }\n\n /**\n * Returns a debug-friendly representation of this block.\n */\n debugValue(): any {\n const out: any = {\n ...super.debugValue(),\n blockType: this.blockType,\n blockItems: this.blockItems.map((c) => c.debugValue()),\n };\n if (this.name) {\n out.name = this.name;\n }\n if (this.localCycle) {\n out.localCycle = this.localCycle.uuid;\n }\n if (this.localAtomsPerBeat !== null) {\n out.localAtomsPerBeat = this.localAtomsPerBeat;\n }\n if (this.localBreaks !== null) {\n out.localBreaks = this.localBreaks;\n }\n if (this.localRoles.size > 0) {\n out.localRoles = Array.from(this.localRoles.keys());\n }\n return out;\n }\n}\n\n/**\n * Helper function to find the containing block of an entity by walking up the tree.\n * @param entity The entity to start from\n * @returns The containing Block, or null if not found\n */\nexport function findContainingBlock(entity: Entity): TSU.Nullable<Block> {\n let current: TSU.Nullable<Entity> = entity.parent;\n while (current !== null) {\n if (current instanceof Block) {\n return current;\n }\n current = current.parent;\n }\n return null;\n}\n\n// ============================================\n// Block Subclasses\n// ============================================\n\n/**\n * A section block with a heading.\n * Expands children to include a heading RawBlock followed by the content.\n *\n * Usage: \\section(\"Pallavi\") { ... }\n */\nexport class SectionBlock extends Block {\n constructor(sectionName: string, parent: TSU.Nullable<Block> = null) {\n super(\"section\", parent, sectionName);\n }\n\n /**\n * Expands children to include a heading RawBlock.\n */\n children(): BlockItem[] {\n const heading = new RawBlock(`# ${this.name}`, \"md\");\n return [heading, ...this.blockItems];\n }\n}\n\n/**\n * A repeat block that expands its children N times.\n *\n * Usage: \\repeat(2) { ... }\n */\nexport class RepeatBlock extends Block {\n /** Number of times to repeat (0 = visual markers only) */\n readonly repeatCount: number;\n\n constructor(repeatCount: number, parent: TSU.Nullable<Block> = null) {\n super(\"repeat\", parent);\n this.repeatCount = repeatCount;\n }\n\n /**\n * Expands children by repeating them N times.\n * If count is 0, returns children as-is (visual repeat markers only).\n */\n children(): BlockItem[] {\n if (this.repeatCount <= 0) {\n return this.blockItems;\n }\n const expanded: BlockItem[] = [];\n for (let i = 0; i < this.repeatCount; i++) {\n expanded.push(...this.blockItems);\n }\n return expanded;\n }\n}\n\n/**\n * A cycle block that sets localCycle for scoped notation.\n *\n * Usage: \\cycle(\"|4|4|\") { ... }\n */\nexport class CycleBlock extends Block {\n constructor(cycle: Cycle, parent: TSU.Nullable<Block> = null) {\n super(\"cycle\", parent);\n this.localCycle = cycle;\n }\n}\n\n/**\n * A beat duration block that sets localAtomsPerBeat for scoped notation.\n *\n * Usage: \\beatDuration(2) { ... }\n */\nexport class BeatDurationBlock extends Block {\n constructor(atomsPerBeat: number, parent: TSU.Nullable<Block> = null) {\n super(\"beatduration\", parent);\n this.localAtomsPerBeat = atomsPerBeat;\n }\n}\n\n/**\n * A breaks block that sets localBreaks for scoped notation.\n *\n * Usage: \\breaks(4, 2, 2) { ... }\n */\nexport class BreaksBlock extends Block {\n constructor(breaks: number[], parent: TSU.Nullable<Block> = null) {\n super(\"breaks\", parent);\n this.localBreaks = breaks;\n }\n}\n\n/**\n * A role block that creates a local role definition.\n *\n * Usage: \\role(\"Vocals\", notes=false) { ... }\n */\nexport class RoleBlock extends Block {\n constructor(roleName: string, notesOnly: boolean, parent: TSU.Nullable<Block> = null) {\n super(\"role\", parent);\n // Create the role locally\n this.newRoleDef(roleName, notesOnly);\n }\n}\n\n/**\n * A group block for organizing notation without special semantics.\n *\n * Usage: \\group(\"optional-name\") { ... }\n */\nexport class GroupBlock extends Block {\n constructor(groupName: string | null, parent: TSU.Nullable<Block> = null) {\n super(\"group\", parent, groupName);\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"block.js","sourceRoot":"","sources":["../../src/block.ts"],"names":[],"mappings":"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","sourcesContent":["import * as TSU from \"@panyam/tsutils\";\nimport { Entity } from \"./entity\";\nimport { Cycle } from \"./cycle\";\nimport { Line } from \"./core\";\nimport { LayoutParams } from \"./layouts\";\nimport { BlockObserver } from \"./events\";\n\n/**\n * Definition of a role in a block context.\n * This is used for block-scoped role definitions.\n */\nexport class RoleDef {\n /** Name of the role */\n name = \"\";\n\n /** Whether this role contains only notes (true) or can also contain syllables/text (false) */\n notesOnly = false;\n\n /** Index of this role in the notation */\n index = 0;\n}\n\n/**\n * Represents a raw block of content in the notation.\n * Raw blocks can contain arbitrary content like markdown, HTML, etc.\n */\nexport class RawBlock extends Entity {\n readonly TYPE: string = \"RawBlock\";\n\n /**\n * Creates a new RawBlock.\n * @param content The content of the block\n * @param contentType The type of content (e.g., \"md\" for markdown)\n */\n constructor(\n public content: string,\n public contentType: string = \"md\",\n ) {\n super();\n }\n\n /**\n * Returns a debug-friendly representation of this raw block.\n * @returns An object containing debug information\n */\n debugValue(): any {\n return { ...super.debugValue(), content: this.content, contentType: this.contentType };\n }\n}\n\n/**\n * Union type for items that can appear in a block.\n */\nexport type BlockItem = Block | Line | RawBlock;\n\n/**\n * Type guard to check if an entity is a Block.\n */\nexport function isBlock(item: BlockItem): item is Block {\n return item.TYPE === \"Block\";\n}\n\n/**\n * Type guard to check if an entity is a Line.\n */\nexport function isLine(item: BlockItem): item is Line {\n return item.TYPE === \"Line\";\n}\n\n/**\n * Type guard to check if an entity is a RawBlock.\n */\nexport function isRawBlock(item: BlockItem): item is RawBlock {\n return item.TYPE === \"RawBlock\";\n}\n\n/**\n * Represents a scoped block created by a command with braces.\n * For example: \\section(\"Pallavi\") { ... }\n *\n * Blocks inherit properties from their parent Block and can override them locally.\n * Properties are resolved lazily by walking up the tree.\n *\n * Block = Command + Children (unified model)\n */\nexport class Block extends Entity {\n readonly TYPE: string = \"Block\";\n\n /** The type of block (e.g., \"section\", \"repeat\", \"cycle\") */\n readonly blockType: string;\n\n /** Optional name for the block (e.g., section name) */\n readonly name: TSU.Nullable<string>;\n\n /** Child items (before expansion by subclasses) */\n readonly blockItems: BlockItem[] = [];\n\n // Local properties\n localCycle: TSU.Nullable<Cycle> = null;\n localAtomsPerBeat: TSU.Nullable<number> = null;\n localBreaks: TSU.Nullable<number[]> = null;\n readonly localRoles = new Map<string, RoleDef>();\n\n // Store parent reference (Block or null for root)\n private _parentBlock: TSU.Nullable<Block> = null;\n\n // State tracking for command application (protected for Notation override)\n protected _currRoleDef: TSU.Nullable<RoleDef> = null;\n protected _currentLine: TSU.Nullable<Line> = null;\n\n /**\n * Observers that receive notifications when block items change.\n */\n private _observers: BlockObserver<BlockItem, Block>[] = [];\n\n /**\n * Creates a new Block.\n * @param blockType The type of block (e.g., \"section\", \"group\")\n * @param parent The parent block (null for root)\n * @param name Optional name for the block\n */\n constructor(blockType: string, parent: TSU.Nullable<Block> = null, name: TSU.Nullable<string> = null) {\n super();\n this.blockType = blockType;\n this.name = name;\n this._parentBlock = parent;\n // Also set Entity's parent for tree traversal\n if (parent) {\n this.setParent(parent);\n }\n }\n\n /**\n * Adds an observer to receive block item change notifications.\n * @param observer The observer to add\n * @returns A function to remove the observer\n */\n addObserver(observer: BlockObserver<BlockItem, Block>): () => void {\n this._observers.push(observer);\n return () => this.removeObserver(observer);\n }\n\n /**\n * Removes an observer.\n * @param observer The observer to remove\n */\n removeObserver(observer: BlockObserver<BlockItem, Block>): void {\n const index = this._observers.indexOf(observer);\n if (index >= 0) {\n this._observers.splice(index, 1);\n }\n }\n\n /**\n * Returns the expanded children for layout iteration.\n * Subclasses can override this to transform children (e.g., Repeat, Section).\n */\n children(): BlockItem[] {\n return this.blockItems;\n }\n\n /**\n * Gets the parent block.\n */\n get parentBlock(): TSU.Nullable<Block> {\n return this._parentBlock;\n }\n\n // ============================================\n // Property inheritance via tree walking\n // ============================================\n\n /**\n * Gets the effective cycle by walking up the tree.\n */\n get cycle(): TSU.Nullable<Cycle> {\n if (this.localCycle !== null) {\n return this.localCycle;\n }\n return this.parentBlock?.cycle ?? null;\n }\n\n /**\n * Gets the effective atoms per beat by walking up the tree.\n * Defaults to 1 if not set anywhere in the tree.\n */\n get atomsPerBeat(): number {\n if (this.localAtomsPerBeat !== null) {\n return this.localAtomsPerBeat;\n }\n return this.parentBlock?.atomsPerBeat ?? 1;\n }\n\n /**\n * Gets the effective line breaks by walking up the tree.\n * Defaults to empty array if not set anywhere.\n */\n get breaks(): number[] {\n if (this.localBreaks !== null) {\n return this.localBreaks;\n }\n return this.parentBlock?.breaks ?? [];\n }\n\n // ============================================\n // Layout parameters management\n // ============================================\n\n /** Layout parameters caching for this block scope */\n private _unnamedLayoutParams: LayoutParams[] = [];\n private _namedLayoutParams = new Map<string, LayoutParams>();\n private _layoutParams: LayoutParams | null = null;\n\n /**\n * Gets the unnamed layout parameters for this block.\n */\n get unnamedLayoutParams(): ReadonlyArray<LayoutParams> {\n return this._unnamedLayoutParams;\n }\n\n /**\n * Gets the named layout parameters for this block.\n */\n get namedLayoutParams(): ReadonlyMap<string, LayoutParams> {\n return this._namedLayoutParams;\n }\n\n /**\n * Gets the current layout parameters for this block scope.\n * Uses the effective cycle, atomsPerBeat, and breaks from tree walking.\n * Creates or finds a matching LayoutParams if needed.\n */\n get layoutParams(): LayoutParams {\n if (this._layoutParams == null) {\n // Find or create layout params matching current effective values\n this._layoutParams = this.findUnnamedLayoutParams();\n if (this._layoutParams == null) {\n this._layoutParams = this.snapshotLayoutParams();\n this._unnamedLayoutParams.push(this._layoutParams);\n }\n }\n return this._layoutParams;\n }\n\n /**\n * Resets the current layout parameters to null.\n * Called when layout-affecting properties change.\n */\n resetLayoutParams(): void {\n this._layoutParams = null;\n this.resetLine();\n }\n\n /**\n * Creates a snapshot of the current layout parameters.\n * @returns A new LayoutParams object with the current effective settings\n */\n protected snapshotLayoutParams(): LayoutParams {\n const effectiveCycle = this.cycle;\n if (effectiveCycle == null) {\n throw new Error(\"Cannot create layout params: no cycle defined\");\n }\n return new LayoutParams({\n cycle: effectiveCycle,\n beatDuration: this.atomsPerBeat,\n layout: this.breaks,\n });\n }\n\n /**\n * Finds an unnamed layout parameters object that matches the current effective settings.\n * @returns Matching layout parameters, or null if none found\n */\n protected findUnnamedLayoutParams(): LayoutParams | null {\n const effectiveCycle = this.cycle;\n if (effectiveCycle == null) return null;\n\n return (\n this._unnamedLayoutParams.find((lp) => {\n return (\n lp.beatDuration == this.atomsPerBeat && effectiveCycle.equals(lp.cycle) && lp.lineBreaksEqual(this.breaks)\n );\n }) || null\n );\n }\n\n /**\n * Ensures that named layout parameters with the given name exist.\n * @param name The name of the layout parameters\n * @returns The layout parameters\n */\n ensureNamedLayoutParams(name: string): LayoutParams {\n let lp = this._namedLayoutParams.get(name) || null;\n if (lp == null || this._layoutParams != lp) {\n if (lp == null) {\n // Create new named layout params\n lp = this.snapshotLayoutParams();\n this._namedLayoutParams.set(name, lp);\n } else {\n // Copy named LPs attributes into our locals\n this.localCycle = lp.cycle;\n this.localAtomsPerBeat = lp.beatDuration;\n this.localBreaks = lp.lineBreaks;\n }\n this._layoutParams = lp;\n this.resetLine();\n }\n return this._layoutParams!;\n }\n\n /**\n * Gets a role definition by name, walking up the tree if not found locally.\n * @param name The name of the role\n */\n getRole(name: string): TSU.Nullable<RoleDef> {\n const local = this.localRoles.get(name.toLowerCase());\n if (local) {\n return local;\n }\n return this.parentBlock?.getRole(name) ?? null;\n }\n\n // ============================================\n // State tracking for command application\n // ============================================\n\n /**\n * Gets the current role definition.\n * Falls back to parent's current role or the last defined role.\n */\n get currRoleDef(): TSU.Nullable<RoleDef> {\n if (this._currRoleDef !== null) {\n return this._currRoleDef;\n }\n // Fall back to parent's current role\n if (this.parentBlock) {\n return this.parentBlock.currRoleDef;\n }\n // Or use the last locally defined role\n const roles = Array.from(this.localRoles.values());\n return roles.length > 0 ? roles[roles.length - 1] : null;\n }\n\n /**\n * Sets the current role by name.\n * If the role doesn't exist, tries to create it via the root container's onMissingRole.\n * @param name The name of the role to activate\n * @throws Error if the role is not found and cannot be created\n */\n setCurrRole(name: string): void {\n name = name.trim().toLowerCase();\n if (name === \"\") {\n throw new Error(\"Role name cannot be empty\");\n }\n let roleDef = this.getRole(name);\n // If role not found, try auto-creation\n if (roleDef == null) {\n // Create the role locally in this block\n // Default: \"sw\" is notes-only, others are not\n roleDef = this.newRoleDef(name, name === \"sw\");\n }\n this._currRoleDef = roleDef;\n }\n\n /**\n * Gets the current line, creating one if needed.\n */\n get currentLine(): Line {\n if (this._currentLine === null) {\n return this.newLine();\n }\n return this._currentLine;\n }\n\n /**\n * Creates a new line in this block.\n */\n newLine(): Line {\n if (this._currentLine !== null && this._currentLine.isEmpty) {\n // Remove empty line before creating new one\n this.removeBlockItem(this._currentLine);\n }\n this._currentLine = new Line();\n this.addBlockItem(this._currentLine);\n return this._currentLine;\n }\n\n /**\n * Resets the current line pointer to null.\n * Called when layout parameters change to force a new line.\n */\n resetLine(): void {\n this._currentLine = null;\n }\n\n /**\n * Creates a new role definition local to this block.\n * @param name The name of the role\n * @param notesOnly Whether this role contains only notes\n */\n newRoleDef(name: string, notesOnly = false): RoleDef {\n name = name.trim().toLowerCase();\n if (name === \"\") {\n throw new Error(\"Role name cannot be empty\");\n }\n if (this.localRoles.has(name)) {\n throw new Error(`Role '${name}' already exists in this block`);\n }\n const rd = new RoleDef();\n rd.name = name;\n rd.notesOnly = notesOnly;\n rd.index = this.localRoles.size;\n this.localRoles.set(name, rd);\n return rd;\n }\n\n // ============================================\n // Child management\n // ============================================\n\n /**\n * Adds a child item to this block.\n * @param item The item to add\n */\n addBlockItem(item: BlockItem): void {\n const index = this.blockItems.length;\n item.setParent(this);\n this.blockItems.push(item);\n\n // Notify observers of added item\n if (this._eventsEnabled) {\n for (const observer of this._observers) {\n observer.onItemAdded?.(this, item, index);\n }\n }\n }\n\n /**\n * Removes a child item from this block.\n * @param item The item to remove\n * @returns The index of the removed item, or -1 if not found\n */\n removeBlockItem(item: BlockItem): number {\n const index = this.blockItems.indexOf(item);\n if (index >= 0) {\n this.blockItems.splice(index, 1);\n item.setParent(null);\n\n // Notify observers of removed item\n if (this._eventsEnabled) {\n for (const observer of this._observers) {\n observer.onItemRemoved?.(this, item, index);\n }\n }\n }\n return index;\n }\n\n /**\n * Returns a debug-friendly representation of this block.\n */\n debugValue(): any {\n const out: any = {\n ...super.debugValue(),\n blockType: this.blockType,\n blockItems: this.blockItems.map((c) => c.debugValue()),\n };\n if (this.name) {\n out.name = this.name;\n }\n if (this.localCycle) {\n out.localCycle = this.localCycle.uuid;\n }\n if (this.localAtomsPerBeat !== null) {\n out.localAtomsPerBeat = this.localAtomsPerBeat;\n }\n if (this.localBreaks !== null) {\n out.localBreaks = this.localBreaks;\n }\n if (this.localRoles.size > 0) {\n out.localRoles = Array.from(this.localRoles.keys());\n }\n return out;\n }\n}\n\n/**\n * Helper function to find the containing block of an entity by walking up the tree.\n * @param entity The entity to start from\n * @returns The containing Block, or null if not found\n */\nexport function findContainingBlock(entity: Entity): TSU.Nullable<Block> {\n let current: TSU.Nullable<Entity> = entity.parent;\n while (current !== null) {\n if (current instanceof Block) {\n return current;\n }\n current = current.parent;\n }\n return null;\n}\n\n// ============================================\n// Block Subclasses\n// ============================================\n\n/**\n * A section block with a heading.\n * Expands children to include a heading RawBlock followed by the content.\n *\n * Usage: \\section(\"Pallavi\") { ... }\n */\nexport class SectionBlock extends Block {\n constructor(sectionName: string, parent: TSU.Nullable<Block> = null) {\n super(\"section\", parent, sectionName);\n }\n\n /**\n * Expands children to include a heading RawBlock.\n */\n children(): BlockItem[] {\n const heading = new RawBlock(`# ${this.name}`, \"md\");\n return [heading, ...this.blockItems];\n }\n}\n\n/**\n * A repeat block that expands its children N times.\n *\n * Usage: \\repeat(2) { ... }\n */\nexport class RepeatBlock extends Block {\n /** Number of times to repeat (0 = visual markers only) */\n readonly repeatCount: number;\n\n constructor(repeatCount: number, parent: TSU.Nullable<Block> = null) {\n super(\"repeat\", parent);\n this.repeatCount = repeatCount;\n }\n\n /**\n * Expands children by repeating them N times.\n * If count is 0, returns children as-is (visual repeat markers only).\n */\n children(): BlockItem[] {\n if (this.repeatCount <= 0) {\n return this.blockItems;\n }\n const expanded: BlockItem[] = [];\n for (let i = 0; i < this.repeatCount; i++) {\n expanded.push(...this.blockItems);\n }\n return expanded;\n }\n}\n\n/**\n * A cycle block that sets localCycle for scoped notation.\n *\n * Usage: \\cycle(\"|4|4|\") { ... }\n */\nexport class CycleBlock extends Block {\n constructor(cycle: Cycle, parent: TSU.Nullable<Block> = null) {\n super(\"cycle\", parent);\n this.localCycle = cycle;\n }\n}\n\n/**\n * A beat duration block that sets localAtomsPerBeat for scoped notation.\n *\n * Usage: \\beatDuration(2) { ... }\n */\nexport class BeatDurationBlock extends Block {\n constructor(atomsPerBeat: number, parent: TSU.Nullable<Block> = null) {\n super(\"beatduration\", parent);\n this.localAtomsPerBeat = atomsPerBeat;\n }\n}\n\n/**\n * A breaks block that sets localBreaks for scoped notation.\n *\n * Usage: \\breaks(4, 2, 2) { ... }\n */\nexport class BreaksBlock extends Block {\n constructor(breaks: number[], parent: TSU.Nullable<Block> = null) {\n super(\"breaks\", parent);\n this.localBreaks = breaks;\n }\n}\n\n/**\n * A role block that creates a local role definition.\n *\n * Usage: \\role(\"Vocals\", notes=false) { ... }\n */\nexport class RoleBlock extends Block {\n constructor(roleName: string, notesOnly: boolean, parent: TSU.Nullable<Block> = null) {\n super(\"role\", parent);\n // Create the role locally\n this.newRoleDef(roleName, notesOnly);\n }\n}\n\n/**\n * A group block for organizing notation without special semantics.\n *\n * Usage: \\group(\"optional-name\") { ... }\n */\nexport class GroupBlock extends Block {\n constructor(groupName: string | null, parent: TSU.Nullable<Block> = null) {\n super(\"group\", parent, groupName);\n }\n}\n"]}
|
package/lib/esm/core.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as TSU from "@panyam/tsutils";
|
|
2
2
|
import { Entity, TimedEntity } from "./entity";
|
|
3
3
|
import { LayoutParams } from "./layouts";
|
|
4
|
+
import { GroupObserver, RoleObserver, LineObserver } from "./events";
|
|
4
5
|
type Fraction = TSU.Num.Fraction;
|
|
5
6
|
export declare const ZERO: TSU.Num.Fraction;
|
|
6
7
|
export declare const ONE: TSU.Num.Fraction;
|
|
@@ -89,7 +90,11 @@ export declare class Group extends Atom {
|
|
|
89
90
|
readonly TYPE = "Group";
|
|
90
91
|
durationIsMultiplier: boolean;
|
|
91
92
|
readonly atoms: TSU.Lists.ValueList<Atom>;
|
|
93
|
+
private _observers;
|
|
92
94
|
constructor(...atoms: Atom[]);
|
|
95
|
+
addObserver(observer: GroupObserver<Atom, Group>): () => void;
|
|
96
|
+
removeObserver(observer: GroupObserver<Atom, Group>): void;
|
|
97
|
+
private notifyObservers;
|
|
93
98
|
equals(another: this, expect?: boolean): boolean;
|
|
94
99
|
copyTo(another: this): void;
|
|
95
100
|
get duration(): Fraction;
|
|
@@ -108,12 +113,16 @@ export declare class Line extends Entity {
|
|
|
108
113
|
roles: Role[];
|
|
109
114
|
marginText: string;
|
|
110
115
|
layoutParams: LayoutParams;
|
|
116
|
+
private _observers;
|
|
117
|
+
addObserver(observer: LineObserver<Role, Line>): () => void;
|
|
118
|
+
removeObserver(observer: LineObserver<Role, Line>): void;
|
|
111
119
|
indexOfRole(name: string): number;
|
|
112
120
|
get isEmpty(): boolean;
|
|
113
121
|
debugValue(): any;
|
|
114
122
|
copyTo(another: this): void;
|
|
115
123
|
addAtoms(roleName: string, defaultToNotes: boolean, ...atoms: Atom[]): this;
|
|
116
124
|
ensureRole(roleName: string, defaultToNotes: boolean): Role;
|
|
125
|
+
removeRole(roleName: string): boolean;
|
|
117
126
|
get duration(): Fraction;
|
|
118
127
|
}
|
|
119
128
|
export declare class Role extends Entity {
|
|
@@ -122,10 +131,16 @@ export declare class Role extends Entity {
|
|
|
122
131
|
readonly TYPE = "Role";
|
|
123
132
|
defaultToNotes: boolean;
|
|
124
133
|
atoms: Atom[];
|
|
134
|
+
private _observers;
|
|
125
135
|
constructor(line: Line, name: string);
|
|
136
|
+
addObserver(observer: RoleObserver<Atom, Role>): () => void;
|
|
137
|
+
removeObserver(observer: RoleObserver<Atom, Role>): void;
|
|
138
|
+
private notifyObservers;
|
|
126
139
|
get isEmpty(): boolean;
|
|
127
140
|
debugValue(): any;
|
|
128
141
|
addAtoms(...atoms: Atom[]): void;
|
|
142
|
+
insertAtomsAt(index: number, ...atoms: Atom[]): void;
|
|
143
|
+
removeAtoms(...atoms: Atom[]): void;
|
|
129
144
|
copyTo(another: Role): void;
|
|
130
145
|
get duration(): Fraction;
|
|
131
146
|
}
|