@ugfoundation/swaralipi-js 0.6.1 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -106,12 +106,39 @@ interface Cell {
106
106
  * The converter emits k notes × 1/k per source cell, so groups coincide
107
107
  * with source cells; an incomplete trailing group still closes at row end
108
108
  * (the matra carrier lands on its last note).
109
+ *
110
+ * Adjacent bar/carrier cells are finally merged, because NLTR types them as
111
+ * ONE table cell: the song-end `L L` (‖ ‖) and the asthayi-return `l [ ] l`
112
+ * each occupy a single column, not two or four.
109
113
  */
110
114
  declare function groupRowIntoCells(notes: Note[]): Cell[];
115
+ interface Layout {
116
+ /** Total columns the document's grid needs. */
117
+ width: number;
118
+ /** Column offset of each row, in document order. */
119
+ offsets: number[];
120
+ }
121
+ /**
122
+ * Give every row of a document its column offset, so all rows share one set
123
+ * of grid tracks (NLTR's single-table layout, re-derived from the spec JSON
124
+ * — the source column index is not stored).
125
+ *
126
+ * A full line is `W` cells wide (the modal width of rows that open on a bar).
127
+ * A shorter row is right-aligned into the সম only when it *starts* a phrase —
128
+ * it opens without a bar, or it is the first row, or the previous row closed
129
+ * a section (‖). A short row that merely finishes one stays flush left. A row
130
+ * without its own closing bar leaves that last column empty, so it ends one
131
+ * column earlier.
132
+ *
133
+ * Measured against all 1738 NLTR pages: 99.1 % of rows and 99.4 % of cells
134
+ * land on the source's exact column. The residual is source defects — rows
135
+ * where NLTR itself skips a column — which this packs flush instead.
136
+ */
137
+ declare function alignRows(rows: Cell[][]): Layout;
111
138
  interface Arc {
112
- /** 1-based grid column of the arc's first / last note column. */
113
- startCol: number;
114
- endCol: number;
139
+ /** 0-based index of the arc's first / last **cell** within the row. */
140
+ start: number;
141
+ end: number;
115
142
  /** True when the matching end lies on a previous / following system. */
116
143
  openLeft: boolean;
117
144
  openRight: boolean;
@@ -119,17 +146,17 @@ interface Arc {
119
146
  line?: boolean;
120
147
  }
121
148
  /**
122
- * Resolve under-arcs for one row. Sources, scanned left→right:
123
- * - below-annotation raws: `w` opens at its cell's first column, `x`
124
- * closes at its cell's last column ("xw" in one cell = close-then-open);
125
- * - spec `meend: 'start' | 'end'` fields feed the same scan as synthetic
126
- * w/x at the note's own column.
127
- * Unmatched `x` → arc from column 1 with a squared-off (open) left end;
128
- * unclosed `w` → arc to the last column with an open right end — both
129
- * match the print's behavior when an arc continues across a system wrap.
149
+ * Resolve under-arcs for one row, in **cell** indices (cells are the grid's
150
+ * columns). Sources, scanned left→right:
151
+ * - below-annotation raws: `w` opens at its cell, `x` closes at its cell
152
+ * ("xw" in one cell = close-then-open, in the order typed);
153
+ * - spec `meend: 'start' | 'end'` fields feed the same scan.
154
+ * Unmatched `x` → arc from cell 0 with a squared-off (open) left end;
155
+ * unclosed `w` → arc to the last cell with an open right end — both match
156
+ * the print's behavior when an arc continues across a system wrap.
130
157
  * A row with fill segments but no ends at all renders one straight line.
131
158
  */
132
- declare function resolveArcs(cells: Cell[], noteCount: number): Arc[];
159
+ declare function resolveArcs(cells: Cell[]): Arc[];
133
160
  /**
134
161
  * The matra marks a cell's final note carries: its total duration as whole
135
162
  * আ-কার matras plus an optional অর্ধমাত্রা ঃ (legend `রাঃ` = 1½, `সঃ` = ½).
@@ -152,6 +179,42 @@ declare function renderMetaHeader(meta: Meta, lang: GridLang, tr?: (s: string) =
152
179
  * `<style>` themselves). All source text is HTML-escaped. */
153
180
  declare function renderToHtml(doc: Swaralipi, opts?: RenderOptions): string;
154
181
 
182
+ /**
183
+ * Fit a sheet's shared grid to the width it has, then layer a user zoom on
184
+ * top.
185
+ *
186
+ * The whole document is one grid (see render.ts), so a sheet has exactly one
187
+ * natural width — a wide তাল overruns a phone or an A4 page. Two levers, in
188
+ * this order, because they cost different things:
189
+ *
190
+ * 1. **Spacing.** `--sw-cell-gap` and the `--sw-matra` column floor are
191
+ * 25–35 % of that natural width (measured over the corpus), and giving
192
+ * them up costs only air between the columns — the alignment is
193
+ * untouched, since every row still borrows the same tracks. Compressed
194
+ * only as far as the container demands, down to `minSpacing`.
195
+ * 2. **Type size.** Everything inside is em-relative, so scaling the sheet's
196
+ * `font-size` scales the notation without disturbing the columns (a
197
+ * `transform` would scale it too, but would also break print
198
+ * pagination). This is what actually makes the glyphs smaller, so it
199
+ * runs second and stops at `minSize` px — past that the block scrolls
200
+ * inside `.sw-scroll` rather than becoming unreadable.
201
+ *
202
+ * `zoom` (default 1) multiplies the fit scale so callers can zoom in past
203
+ * fit-to-width, or below the readability floor deliberately; past that point
204
+ * `.sw-scroll` panning is expected, same as a photo viewer. `minScale` is a
205
+ * second, relative floor used by print, where paper cannot scroll.
206
+ *
207
+ * Self-contained on purpose — print.ts serialises this function into the
208
+ * print page, so it must not close over anything or import anything (the
209
+ * defaults below are literals for the same reason).
210
+ */
211
+ declare function fitSwaralipi(root: Document | ShadowRoot | HTMLElement, minScale?: number, zoom?: number, minSpacing?: number, minSize?: number): void;
212
+ /** Zoom bounds/step for zoomIn()/zoomOut()/the `zoom` property — exported so
213
+ * a consumer's own zoom UI (e.g. a slider) can match the element's clamp. */
214
+ declare const MIN_ZOOM = 0.5;
215
+ declare const MAX_ZOOM = 3;
216
+ declare const ZOOM_STEP = 1.2;
217
+
155
218
  /**
156
219
  * Encapsulated stylesheet for the viewer. Injected into the
157
220
  * `<swaralipi-sheet>` shadow root automatically; SSR consumers emit it
@@ -161,6 +224,11 @@ declare function renderToHtml(doc: Swaralipi, opts?: RenderOptions): string;
161
224
  * --sw-font font stack (default: Noto Sans Bengali + system Bengali)
162
225
  * --sw-size base font size
163
226
  * --sw-cell-gap horizontal gap between source cells
227
+ * --sw-tight 0–1 multiplier on the column spacing (gap + matra floor);
228
+ * set by fitSwaralipi to compress before shrinking type
229
+ * --sw-matra minimum width of one matra column
230
+ * --sw-header-min floor for the নাম/তাল/আবর্তন header (it must stay legible
231
+ * when the notation is scaled down to fit a phone)
164
232
  * --sw-hl player-highlight background (P2.3)
165
233
  * --sw-rule header rule / muted line color
166
234
  *
@@ -188,7 +256,7 @@ declare const SWARALIPI_CSS: string;
188
256
  * - rows are un-clipped (no scrollbar on paper) and kept whole across page
189
257
  * breaks; part headings stay with their first row.
190
258
  */
191
- declare const SWARALIPI_PRINT_CSS = "\n@page { margin: 16mm; }\n@media print {\n .sw-sheet, .sw-staff { -webkit-print-color-adjust: exact; print-color-adjust: exact; color: #000; }\n .sw-row { overflow: visible !important; break-inside: avoid; page-break-inside: avoid; }\n .sw-part { break-inside: auto; }\n .sw-part-name, .sw-header { break-after: avoid-page; page-break-after: avoid; }\n .sw-hl { background: none !important; }\n /* Keep each engraved staff system whole across a page break (the abcjs line\n is a <div> wrapping the <svg>, so the break rule must sit on the div). */\n .sw-staff-lines > div { break-inside: avoid; page-break-inside: avoid; }\n .sw-staff-meta { break-after: avoid-page; page-break-after: avoid; }\n}\n";
259
+ declare const SWARALIPI_PRINT_CSS = "\n@page { margin: 16mm; }\n@media print {\n .sw-sheet, .sw-staff { -webkit-print-color-adjust: exact; print-color-adjust: exact; color: #000; }\n .sw-scroll { overflow: visible !important; }\n .sw-row { break-inside: avoid; page-break-inside: avoid; }\n .sw-part-name, .sw-header { break-after: avoid-page; page-break-after: avoid; }\n .sw-hl { background: none !important; }\n /* Keep each engraved staff system whole across a page break (the abcjs line\n is a <div> wrapping the <svg>, so the break rule must sit on the div). */\n .sw-staff-lines > div { break-inside: avoid; page-break-inside: avoid; }\n .sw-staff-meta { break-after: avoid-page; page-break-after: avoid; }\n}\n";
192
260
  /** Staff-notation (abcjs) wrapper chrome: instrument/tempo header + a fluid
193
261
  * SVG. The engraving itself is drawn by abcjs; this only frames it. */
194
262
  declare const SWARALIPI_STAFF_CSS = "\n.sw-staff { color: currentColor; }\n.sw-staff-meta { display: flex; gap: 1.25em; align-items: baseline; margin: 0 0 .5em; font-size: .95em; opacity: .85; }\n.sw-staff-instrument { font-weight: 600; }\n.sw-staff-drums { opacity: .75; }\n.sw-staff-tempo { font-variant-numeric: tabular-nums; }\n/* abcjs (oneSvgPerLine) wraps the music into one <div><svg> per system; stack\n them as short, swaralipi-style lines. abcjs sets a fixed pixel height +\n overflow:hidden on each wrapper div \u2014 neutralise it so the viewBox'd SVG can\n scale to the container (and to the print page) instead of being clipped. */\n.sw-staff-lines > div { margin: 0 0 .35em; height: auto !important; overflow: visible !important; }\n/* Fill up to the engraved (staffwidth) size \u2014 shrink to fit a narrow container,\n but never stretch past natural width (abcToSvg pins per-SVG max-width in px),\n else a short last system balloons. */\n.sw-staff-lines svg { display: block; width: 100%; height: auto; }\n.sw-staff-missing { padding: 1em; border: 1px dashed currentColor; border-radius: 6px; opacity: .8; font-size: .9em; }\n.sw-staff-title { font-size: 1.15em; font-weight: 700; }\n.sw-staff-subtitle { opacity: .8; font-size: .95em; margin-top: .15em; }\n";
@@ -436,6 +504,25 @@ interface SwaralipiSheetElement extends HTMLElement {
436
504
  print(options?: PrintOptions): void;
437
505
  /** Options for the `staff` language (instrument label, tonic, bpm…). */
438
506
  staffOptions: StaffOptions;
507
+ /** Re-fit the notation to the element's current width. */
508
+ fit(): void;
509
+ /** How far the column spacing may be compressed to fit a narrow container
510
+ * before the type is scaled down at all, 0–1 (attribute `min-spacing`;
511
+ * undefined = the library default). Lower = tighter columns, bigger glyphs. */
512
+ minSpacing: number | undefined;
513
+ /** Smallest notation size in px the fit may produce (attribute `min-size`);
514
+ * past it the sheet scrolls horizontally instead of shrinking further. */
515
+ minSize: number | undefined;
516
+ /** Zoom factor on top of fit-to-width (1 = fit; clamped to
517
+ * [MIN_ZOOM, MAX_ZOOM]). Assigning re-fits immediately. Resets to 1 on the
518
+ * next doc/lang re-render — a resize alone (fit()) does not reset it. */
519
+ zoom: number;
520
+ /** `zoom *= ZOOM_STEP`, clamped. */
521
+ zoomIn(): void;
522
+ /** `zoom /= ZOOM_STEP`, clamped. */
523
+ zoomOut(): void;
524
+ /** Back to fit-to-width (`zoom = 1`). */
525
+ resetZoom(): void;
439
526
  }
440
527
  /**
441
528
  * Register `<swaralipi-sheet>` (or a custom tag name). Idempotent. Throws
@@ -460,4 +547,4 @@ type Transliterator = (bengaliText: string) => string;
460
547
  */
461
548
  declare function loadLyricTransliterator(lang: ViewerLang): Promise<Transliterator | undefined>;
462
549
 
463
- export { type Arc, type Cell, type Cluster, type ComposeOptions, DEFAULT_NOTATOR, DEFAULT_WATERMARK, DIGITS, type GridLang, LABELS, MARKS, NOTATION_FONT_URLS, type PrintOptions, type RenderOptions, SWARALIPI_CSS, SWARALIPI_PRINT_CSS, SWARALIPI_STAFF_CSS, type StaffOptions, type SwaralipiSheetElement, type TaalStaffOptions, type Transliterator, type ViewerLang, abcDuration, abcToSvg, buildAbc, buildTaalAbc, cellMatra, composeCluster, defineSwaralipiSheet, docToAbc, groupRowIntoCells, loadLyricTransliterator, localizeDigits, midiToAbc, printSwaralipi, renderMetaHeader, renderPrintDocument, renderStaffHtml, renderStaffPrintDocument, renderTaalStaffHtml, renderToHtml, resolveArcs };
550
+ export { type Arc, type Cell, type Cluster, type ComposeOptions, DEFAULT_NOTATOR, DEFAULT_WATERMARK, DIGITS, type GridLang, LABELS, type Layout, MARKS, MAX_ZOOM, MIN_ZOOM, NOTATION_FONT_URLS, type PrintOptions, type RenderOptions, SWARALIPI_CSS, SWARALIPI_PRINT_CSS, SWARALIPI_STAFF_CSS, type StaffOptions, type SwaralipiSheetElement, type TaalStaffOptions, type Transliterator, type ViewerLang, ZOOM_STEP, abcDuration, abcToSvg, alignRows, buildAbc, buildTaalAbc, cellMatra, composeCluster, defineSwaralipiSheet, docToAbc, fitSwaralipi, groupRowIntoCells, loadLyricTransliterator, localizeDigits, midiToAbc, printSwaralipi, renderMetaHeader, renderPrintDocument, renderStaffHtml, renderStaffPrintDocument, renderTaalStaffHtml, renderToHtml, resolveArcs };
@@ -106,12 +106,39 @@ interface Cell {
106
106
  * The converter emits k notes × 1/k per source cell, so groups coincide
107
107
  * with source cells; an incomplete trailing group still closes at row end
108
108
  * (the matra carrier lands on its last note).
109
+ *
110
+ * Adjacent bar/carrier cells are finally merged, because NLTR types them as
111
+ * ONE table cell: the song-end `L L` (‖ ‖) and the asthayi-return `l [ ] l`
112
+ * each occupy a single column, not two or four.
109
113
  */
110
114
  declare function groupRowIntoCells(notes: Note[]): Cell[];
115
+ interface Layout {
116
+ /** Total columns the document's grid needs. */
117
+ width: number;
118
+ /** Column offset of each row, in document order. */
119
+ offsets: number[];
120
+ }
121
+ /**
122
+ * Give every row of a document its column offset, so all rows share one set
123
+ * of grid tracks (NLTR's single-table layout, re-derived from the spec JSON
124
+ * — the source column index is not stored).
125
+ *
126
+ * A full line is `W` cells wide (the modal width of rows that open on a bar).
127
+ * A shorter row is right-aligned into the সম only when it *starts* a phrase —
128
+ * it opens without a bar, or it is the first row, or the previous row closed
129
+ * a section (‖). A short row that merely finishes one stays flush left. A row
130
+ * without its own closing bar leaves that last column empty, so it ends one
131
+ * column earlier.
132
+ *
133
+ * Measured against all 1738 NLTR pages: 99.1 % of rows and 99.4 % of cells
134
+ * land on the source's exact column. The residual is source defects — rows
135
+ * where NLTR itself skips a column — which this packs flush instead.
136
+ */
137
+ declare function alignRows(rows: Cell[][]): Layout;
111
138
  interface Arc {
112
- /** 1-based grid column of the arc's first / last note column. */
113
- startCol: number;
114
- endCol: number;
139
+ /** 0-based index of the arc's first / last **cell** within the row. */
140
+ start: number;
141
+ end: number;
115
142
  /** True when the matching end lies on a previous / following system. */
116
143
  openLeft: boolean;
117
144
  openRight: boolean;
@@ -119,17 +146,17 @@ interface Arc {
119
146
  line?: boolean;
120
147
  }
121
148
  /**
122
- * Resolve under-arcs for one row. Sources, scanned left→right:
123
- * - below-annotation raws: `w` opens at its cell's first column, `x`
124
- * closes at its cell's last column ("xw" in one cell = close-then-open);
125
- * - spec `meend: 'start' | 'end'` fields feed the same scan as synthetic
126
- * w/x at the note's own column.
127
- * Unmatched `x` → arc from column 1 with a squared-off (open) left end;
128
- * unclosed `w` → arc to the last column with an open right end — both
129
- * match the print's behavior when an arc continues across a system wrap.
149
+ * Resolve under-arcs for one row, in **cell** indices (cells are the grid's
150
+ * columns). Sources, scanned left→right:
151
+ * - below-annotation raws: `w` opens at its cell, `x` closes at its cell
152
+ * ("xw" in one cell = close-then-open, in the order typed);
153
+ * - spec `meend: 'start' | 'end'` fields feed the same scan.
154
+ * Unmatched `x` → arc from cell 0 with a squared-off (open) left end;
155
+ * unclosed `w` → arc to the last cell with an open right end — both match
156
+ * the print's behavior when an arc continues across a system wrap.
130
157
  * A row with fill segments but no ends at all renders one straight line.
131
158
  */
132
- declare function resolveArcs(cells: Cell[], noteCount: number): Arc[];
159
+ declare function resolveArcs(cells: Cell[]): Arc[];
133
160
  /**
134
161
  * The matra marks a cell's final note carries: its total duration as whole
135
162
  * আ-কার matras plus an optional অর্ধমাত্রা ঃ (legend `রাঃ` = 1½, `সঃ` = ½).
@@ -152,6 +179,42 @@ declare function renderMetaHeader(meta: Meta, lang: GridLang, tr?: (s: string) =
152
179
  * `<style>` themselves). All source text is HTML-escaped. */
153
180
  declare function renderToHtml(doc: Swaralipi, opts?: RenderOptions): string;
154
181
 
182
+ /**
183
+ * Fit a sheet's shared grid to the width it has, then layer a user zoom on
184
+ * top.
185
+ *
186
+ * The whole document is one grid (see render.ts), so a sheet has exactly one
187
+ * natural width — a wide তাল overruns a phone or an A4 page. Two levers, in
188
+ * this order, because they cost different things:
189
+ *
190
+ * 1. **Spacing.** `--sw-cell-gap` and the `--sw-matra` column floor are
191
+ * 25–35 % of that natural width (measured over the corpus), and giving
192
+ * them up costs only air between the columns — the alignment is
193
+ * untouched, since every row still borrows the same tracks. Compressed
194
+ * only as far as the container demands, down to `minSpacing`.
195
+ * 2. **Type size.** Everything inside is em-relative, so scaling the sheet's
196
+ * `font-size` scales the notation without disturbing the columns (a
197
+ * `transform` would scale it too, but would also break print
198
+ * pagination). This is what actually makes the glyphs smaller, so it
199
+ * runs second and stops at `minSize` px — past that the block scrolls
200
+ * inside `.sw-scroll` rather than becoming unreadable.
201
+ *
202
+ * `zoom` (default 1) multiplies the fit scale so callers can zoom in past
203
+ * fit-to-width, or below the readability floor deliberately; past that point
204
+ * `.sw-scroll` panning is expected, same as a photo viewer. `minScale` is a
205
+ * second, relative floor used by print, where paper cannot scroll.
206
+ *
207
+ * Self-contained on purpose — print.ts serialises this function into the
208
+ * print page, so it must not close over anything or import anything (the
209
+ * defaults below are literals for the same reason).
210
+ */
211
+ declare function fitSwaralipi(root: Document | ShadowRoot | HTMLElement, minScale?: number, zoom?: number, minSpacing?: number, minSize?: number): void;
212
+ /** Zoom bounds/step for zoomIn()/zoomOut()/the `zoom` property — exported so
213
+ * a consumer's own zoom UI (e.g. a slider) can match the element's clamp. */
214
+ declare const MIN_ZOOM = 0.5;
215
+ declare const MAX_ZOOM = 3;
216
+ declare const ZOOM_STEP = 1.2;
217
+
155
218
  /**
156
219
  * Encapsulated stylesheet for the viewer. Injected into the
157
220
  * `<swaralipi-sheet>` shadow root automatically; SSR consumers emit it
@@ -161,6 +224,11 @@ declare function renderToHtml(doc: Swaralipi, opts?: RenderOptions): string;
161
224
  * --sw-font font stack (default: Noto Sans Bengali + system Bengali)
162
225
  * --sw-size base font size
163
226
  * --sw-cell-gap horizontal gap between source cells
227
+ * --sw-tight 0–1 multiplier on the column spacing (gap + matra floor);
228
+ * set by fitSwaralipi to compress before shrinking type
229
+ * --sw-matra minimum width of one matra column
230
+ * --sw-header-min floor for the নাম/তাল/আবর্তন header (it must stay legible
231
+ * when the notation is scaled down to fit a phone)
164
232
  * --sw-hl player-highlight background (P2.3)
165
233
  * --sw-rule header rule / muted line color
166
234
  *
@@ -188,7 +256,7 @@ declare const SWARALIPI_CSS: string;
188
256
  * - rows are un-clipped (no scrollbar on paper) and kept whole across page
189
257
  * breaks; part headings stay with their first row.
190
258
  */
191
- declare const SWARALIPI_PRINT_CSS = "\n@page { margin: 16mm; }\n@media print {\n .sw-sheet, .sw-staff { -webkit-print-color-adjust: exact; print-color-adjust: exact; color: #000; }\n .sw-row { overflow: visible !important; break-inside: avoid; page-break-inside: avoid; }\n .sw-part { break-inside: auto; }\n .sw-part-name, .sw-header { break-after: avoid-page; page-break-after: avoid; }\n .sw-hl { background: none !important; }\n /* Keep each engraved staff system whole across a page break (the abcjs line\n is a <div> wrapping the <svg>, so the break rule must sit on the div). */\n .sw-staff-lines > div { break-inside: avoid; page-break-inside: avoid; }\n .sw-staff-meta { break-after: avoid-page; page-break-after: avoid; }\n}\n";
259
+ declare const SWARALIPI_PRINT_CSS = "\n@page { margin: 16mm; }\n@media print {\n .sw-sheet, .sw-staff { -webkit-print-color-adjust: exact; print-color-adjust: exact; color: #000; }\n .sw-scroll { overflow: visible !important; }\n .sw-row { break-inside: avoid; page-break-inside: avoid; }\n .sw-part-name, .sw-header { break-after: avoid-page; page-break-after: avoid; }\n .sw-hl { background: none !important; }\n /* Keep each engraved staff system whole across a page break (the abcjs line\n is a <div> wrapping the <svg>, so the break rule must sit on the div). */\n .sw-staff-lines > div { break-inside: avoid; page-break-inside: avoid; }\n .sw-staff-meta { break-after: avoid-page; page-break-after: avoid; }\n}\n";
192
260
  /** Staff-notation (abcjs) wrapper chrome: instrument/tempo header + a fluid
193
261
  * SVG. The engraving itself is drawn by abcjs; this only frames it. */
194
262
  declare const SWARALIPI_STAFF_CSS = "\n.sw-staff { color: currentColor; }\n.sw-staff-meta { display: flex; gap: 1.25em; align-items: baseline; margin: 0 0 .5em; font-size: .95em; opacity: .85; }\n.sw-staff-instrument { font-weight: 600; }\n.sw-staff-drums { opacity: .75; }\n.sw-staff-tempo { font-variant-numeric: tabular-nums; }\n/* abcjs (oneSvgPerLine) wraps the music into one <div><svg> per system; stack\n them as short, swaralipi-style lines. abcjs sets a fixed pixel height +\n overflow:hidden on each wrapper div \u2014 neutralise it so the viewBox'd SVG can\n scale to the container (and to the print page) instead of being clipped. */\n.sw-staff-lines > div { margin: 0 0 .35em; height: auto !important; overflow: visible !important; }\n/* Fill up to the engraved (staffwidth) size \u2014 shrink to fit a narrow container,\n but never stretch past natural width (abcToSvg pins per-SVG max-width in px),\n else a short last system balloons. */\n.sw-staff-lines svg { display: block; width: 100%; height: auto; }\n.sw-staff-missing { padding: 1em; border: 1px dashed currentColor; border-radius: 6px; opacity: .8; font-size: .9em; }\n.sw-staff-title { font-size: 1.15em; font-weight: 700; }\n.sw-staff-subtitle { opacity: .8; font-size: .95em; margin-top: .15em; }\n";
@@ -436,6 +504,25 @@ interface SwaralipiSheetElement extends HTMLElement {
436
504
  print(options?: PrintOptions): void;
437
505
  /** Options for the `staff` language (instrument label, tonic, bpm…). */
438
506
  staffOptions: StaffOptions;
507
+ /** Re-fit the notation to the element's current width. */
508
+ fit(): void;
509
+ /** How far the column spacing may be compressed to fit a narrow container
510
+ * before the type is scaled down at all, 0–1 (attribute `min-spacing`;
511
+ * undefined = the library default). Lower = tighter columns, bigger glyphs. */
512
+ minSpacing: number | undefined;
513
+ /** Smallest notation size in px the fit may produce (attribute `min-size`);
514
+ * past it the sheet scrolls horizontally instead of shrinking further. */
515
+ minSize: number | undefined;
516
+ /** Zoom factor on top of fit-to-width (1 = fit; clamped to
517
+ * [MIN_ZOOM, MAX_ZOOM]). Assigning re-fits immediately. Resets to 1 on the
518
+ * next doc/lang re-render — a resize alone (fit()) does not reset it. */
519
+ zoom: number;
520
+ /** `zoom *= ZOOM_STEP`, clamped. */
521
+ zoomIn(): void;
522
+ /** `zoom /= ZOOM_STEP`, clamped. */
523
+ zoomOut(): void;
524
+ /** Back to fit-to-width (`zoom = 1`). */
525
+ resetZoom(): void;
439
526
  }
440
527
  /**
441
528
  * Register `<swaralipi-sheet>` (or a custom tag name). Idempotent. Throws
@@ -460,4 +547,4 @@ type Transliterator = (bengaliText: string) => string;
460
547
  */
461
548
  declare function loadLyricTransliterator(lang: ViewerLang): Promise<Transliterator | undefined>;
462
549
 
463
- export { type Arc, type Cell, type Cluster, type ComposeOptions, DEFAULT_NOTATOR, DEFAULT_WATERMARK, DIGITS, type GridLang, LABELS, MARKS, NOTATION_FONT_URLS, type PrintOptions, type RenderOptions, SWARALIPI_CSS, SWARALIPI_PRINT_CSS, SWARALIPI_STAFF_CSS, type StaffOptions, type SwaralipiSheetElement, type TaalStaffOptions, type Transliterator, type ViewerLang, abcDuration, abcToSvg, buildAbc, buildTaalAbc, cellMatra, composeCluster, defineSwaralipiSheet, docToAbc, groupRowIntoCells, loadLyricTransliterator, localizeDigits, midiToAbc, printSwaralipi, renderMetaHeader, renderPrintDocument, renderStaffHtml, renderStaffPrintDocument, renderTaalStaffHtml, renderToHtml, resolveArcs };
550
+ export { type Arc, type Cell, type Cluster, type ComposeOptions, DEFAULT_NOTATOR, DEFAULT_WATERMARK, DIGITS, type GridLang, LABELS, type Layout, MARKS, MAX_ZOOM, MIN_ZOOM, NOTATION_FONT_URLS, type PrintOptions, type RenderOptions, SWARALIPI_CSS, SWARALIPI_PRINT_CSS, SWARALIPI_STAFF_CSS, type StaffOptions, type SwaralipiSheetElement, type TaalStaffOptions, type Transliterator, type ViewerLang, ZOOM_STEP, abcDuration, abcToSvg, alignRows, buildAbc, buildTaalAbc, cellMatra, composeCluster, defineSwaralipiSheet, docToAbc, fitSwaralipi, groupRowIntoCells, loadLyricTransliterator, localizeDigits, midiToAbc, printSwaralipi, renderMetaHeader, renderPrintDocument, renderStaffHtml, renderStaffPrintDocument, renderTaalStaffHtml, renderToHtml, resolveArcs };