@kerusiweb/core 2.3.0 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/LICENSE +22 -22
  2. package/README.md +74 -68
  3. package/dist/kerusi/index.d.ts +4 -3
  4. package/dist/kerusi/index.d.ts.map +1 -1
  5. package/dist/kerusi/index.js +4 -3
  6. package/dist/kerusi/index.js.map +1 -1
  7. package/dist/kerusi/kerusi-geometry.d.ts +47 -0
  8. package/dist/kerusi/kerusi-geometry.d.ts.map +1 -0
  9. package/dist/kerusi/kerusi-geometry.js +111 -0
  10. package/dist/kerusi/kerusi-geometry.js.map +1 -0
  11. package/dist/kerusi/kerusi-map.model.d.ts +121 -68
  12. package/dist/kerusi/kerusi-map.model.d.ts.map +1 -1
  13. package/dist/kerusi/kerusi-map.model.js +6 -2
  14. package/dist/kerusi/kerusi-map.model.js.map +1 -1
  15. package/dist/kerusi/kerusi-rows.d.ts +2 -2
  16. package/dist/kerusi/kerusi-rows.js +2 -2
  17. package/dist/kerusi/kerusi-validator.d.ts +18 -9
  18. package/dist/kerusi/kerusi-validator.d.ts.map +1 -1
  19. package/dist/kerusi/kerusi-validator.js +301 -122
  20. package/dist/kerusi/kerusi-validator.js.map +1 -1
  21. package/dist/render/build-render-model.d.ts +8 -4
  22. package/dist/render/build-render-model.d.ts.map +1 -1
  23. package/dist/render/build-render-model.js +147 -45
  24. package/dist/render/build-render-model.js.map +1 -1
  25. package/dist/render/index.d.ts +1 -1
  26. package/dist/render/index.d.ts.map +1 -1
  27. package/dist/render/index.js +1 -1
  28. package/dist/render/index.js.map +1 -1
  29. package/dist/render/map-layout.d.ts +92 -0
  30. package/dist/render/map-layout.d.ts.map +1 -0
  31. package/dist/render/map-layout.js +93 -0
  32. package/dist/render/map-layout.js.map +1 -0
  33. package/dist/render/navigation-order.d.ts +20 -10
  34. package/dist/render/navigation-order.d.ts.map +1 -1
  35. package/dist/render/navigation-order.js +72 -57
  36. package/dist/render/navigation-order.js.map +1 -1
  37. package/dist/render/render-model.d.ts +48 -26
  38. package/dist/render/render-model.d.ts.map +1 -1
  39. package/dist/render/seat-shapes.d.ts +3 -3
  40. package/dist/render/seat-shapes.js +3 -3
  41. package/dist/view/index.d.ts +6 -2
  42. package/dist/view/index.d.ts.map +1 -1
  43. package/dist/view/index.js +6 -2
  44. package/dist/view/index.js.map +1 -1
  45. package/dist/view/rtl.d.ts +1 -1
  46. package/dist/view/rtl.js +1 -1
  47. package/dist/view/seat-aria.d.ts +6 -0
  48. package/dist/view/seat-aria.d.ts.map +1 -1
  49. package/dist/view/seat-aria.js +8 -0
  50. package/dist/view/seat-aria.js.map +1 -1
  51. package/dist/view/seat-card-placement.d.ts +60 -0
  52. package/dist/view/seat-card-placement.d.ts.map +1 -0
  53. package/dist/view/seat-card-placement.js +94 -0
  54. package/dist/view/seat-card-placement.js.map +1 -0
  55. package/dist/view/seat-card.d.ts +83 -0
  56. package/dist/view/seat-card.d.ts.map +1 -0
  57. package/dist/view/seat-card.js +68 -0
  58. package/dist/view/seat-card.js.map +1 -0
  59. package/dist/view/seat-glyph.d.ts +1 -1
  60. package/dist/view/seat-glyph.d.ts.map +1 -1
  61. package/dist/view/seat-hover.d.ts +90 -0
  62. package/dist/view/seat-hover.d.ts.map +1 -0
  63. package/dist/view/seat-hover.js +205 -0
  64. package/dist/view/seat-hover.js.map +1 -0
  65. package/dist/view/viewport.d.ts +35 -7
  66. package/dist/view/viewport.d.ts.map +1 -1
  67. package/dist/view/viewport.js +56 -7
  68. package/dist/view/viewport.js.map +1 -1
  69. package/package.json +42 -42
  70. package/dist/kerusi/kerusi-layout-mode.d.ts +0 -58
  71. package/dist/kerusi/kerusi-layout-mode.d.ts.map +0 -1
  72. package/dist/kerusi/kerusi-layout-mode.js +0 -117
  73. package/dist/kerusi/kerusi-layout-mode.js.map +0 -1
  74. package/dist/render/section-layout.d.ts +0 -66
  75. package/dist/render/section-layout.d.ts.map +0 -1
  76. package/dist/render/section-layout.js +0 -186
  77. package/dist/render/section-layout.js.map +0 -1
@@ -1,117 +0,0 @@
1
- import { error } from './kerusi-violation.js';
2
- /** True when the item carries a usable grid column. */
3
- export function hasCol(item) {
4
- return item.col !== undefined && item.col !== null;
5
- }
6
- /** True when the item carries both freeform coordinates. Neither alone counts. */
7
- export function hasXY(item) {
8
- return item.x !== undefined && item.x !== null && item.y !== undefined && item.y !== null;
9
- }
10
- /** True when the item carries either coordinate — the `grid` prohibition. */
11
- export function hasAnyCoordinate(item) {
12
- return (item.x !== undefined && item.x !== null) || (item.y !== undefined && item.y !== null);
13
- }
14
- /**
15
- * Infers a section's mode from its seats when `Section.layout` is omitted
16
- * (§4.5). Returns `undefined` when the seats are inconsistent — the caller MUST
17
- * reject such a section.
18
- *
19
- * An empty section infers `grid`: it satisfies "every seat has `col`" vacuously
20
- * and grid is the cheaper mode to render.
21
- */
22
- export function inferSectionLayoutMode(section) {
23
- const seats = section.seats ?? [];
24
- if (seats.length === 0) {
25
- return 'grid';
26
- }
27
- if (seats.every((s) => hasCol(s) && !hasAnyCoordinate(s))) {
28
- return 'grid';
29
- }
30
- if (seats.every((s) => hasXY(s) && !hasCol(s))) {
31
- return 'freeform';
32
- }
33
- // The spec defines no inference for `mixed`; declaring it is required. Every
34
- // other shape is inconsistent.
35
- return undefined;
36
- }
37
- /**
38
- * The mode a section renders in: its declared `layout`, or the inferred one.
39
- * Falls back to `grid` for an inconsistent section so a renderer can still draw
40
- * *something* after the validator has reported the fault. Callers that must not
41
- * render an invalid document should check {@link checkSectionLayout} first.
42
- */
43
- export function resolveSectionLayoutMode(section) {
44
- return section.layout ?? inferSectionLayoutMode(section) ?? 'grid';
45
- }
46
- /**
47
- * Validates a section against §4.5. Returns every violation found, in seat
48
- * declaration order; an empty array means the section conforms.
49
- *
50
- * @param path Document path prefix for the violations, e.g. `sections[1]`.
51
- */
52
- export function checkSectionLayout(section, path) {
53
- const seats = section.seats ?? [];
54
- if (section.layout === undefined) {
55
- if (inferSectionLayoutMode(section) === undefined) {
56
- const offender = firstInconsistentSeat(seats);
57
- return [
58
- error('section-layout-inconsistent', `Section "${section.id}" omits "layout" and its seats mix positioning ` +
59
- `methods, so no mode can be inferred: seat "${offender?.id}" does not ` +
60
- 'match the section\'s prevailing method. Declare "layout" explicitly, ' +
61
- 'or make every seat use the same method (§4.5).', { id: section.id, path }),
62
- ];
63
- }
64
- // An inferred mode is, by construction, satisfied by every seat.
65
- return [];
66
- }
67
- const violations = [];
68
- seats.forEach((seat, i) => {
69
- const seatPath = path ? `${path}.seats[${i}]` : undefined;
70
- switch (section.layout) {
71
- case 'grid':
72
- if (!hasCol(seat)) {
73
- violations.push(error('section-layout-grid', `Seat "${seat.id}" is in grid section "${section.id}" but has no ` +
74
- '"col". Every seat in a grid section must declare "col" ' +
75
- 'explicitly; it is never inferred from array order (§4.5).', { id: seat.id, path: seatPath }));
76
- }
77
- if (hasAnyCoordinate(seat)) {
78
- violations.push(error('section-layout-grid', `Seat "${seat.id}" is in grid section "${section.id}" but carries ` +
79
- '"x"/"y". No seat in a grid section may have freeform ' +
80
- 'coordinates; use layout "mixed" to combine both (§4.5).', { id: seat.id, path: seatPath }));
81
- }
82
- break;
83
- case 'freeform':
84
- if (!hasXY(seat)) {
85
- violations.push(error('section-layout-freeform', `Seat "${seat.id}" is in freeform section "${section.id}" but is ` +
86
- 'missing "x" or "y". Every seat in a freeform section must have ' +
87
- 'both (§4.5).', { id: seat.id, path: seatPath }));
88
- }
89
- if (hasCol(seat)) {
90
- violations.push(error('section-layout-freeform', `Seat "${seat.id}" is in freeform section "${section.id}" but ` +
91
- 'carries "col". No seat in a freeform section may have a grid ' +
92
- 'column; use layout "mixed" to combine both (§4.5).', { id: seat.id, path: seatPath }));
93
- }
94
- break;
95
- case 'mixed':
96
- if (!hasCol(seat) || !hasXY(seat)) {
97
- violations.push(error('section-layout-mixed', `Seat "${seat.id}" is in mixed section "${section.id}" but does not ` +
98
- 'have all of "col", "x" and "y". A mixed section requires every ' +
99
- 'seat to carry both addressing methods (§4.5).', { id: seat.id, path: seatPath }));
100
- }
101
- break;
102
- }
103
- });
104
- return violations;
105
- }
106
- /**
107
- * The first seat that breaks the section's prevailing positioning method, used
108
- * to make an "inconsistent" message point at something concrete.
109
- */
110
- function firstInconsistentSeat(seats) {
111
- const gridLike = seats.filter((s) => hasCol(s) && !hasAnyCoordinate(s)).length;
112
- const freeformLike = seats.filter((s) => hasXY(s) && !hasCol(s)).length;
113
- return gridLike >= freeformLike
114
- ? seats.find((s) => !(hasCol(s) && !hasAnyCoordinate(s)))
115
- : seats.find((s) => !(hasXY(s) && !hasCol(s)));
116
- }
117
- //# sourceMappingURL=kerusi-layout-mode.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"kerusi-layout-mode.js","sourceRoot":"","sources":["../../src/kerusi/kerusi-layout-mode.ts"],"names":[],"mappings":"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"}
@@ -1,66 +0,0 @@
1
- import { RenderElement, RenderSeat, RenderSection } from './render-model.js';
2
- /**
3
- * Section geometry: turning a `RenderSection` into placed rectangles.
4
- *
5
- * Each section computes its own *intrinsic* size — a grid section is as wide as
6
- * its widest row and as tall as its row count; a freeform section takes its
7
- * proportions from `Section.aspectRatio`. The component then hands that size to
8
- * the SVG as a `viewBox` and lets CSS scale it. The pre-1.0 renderer instead
9
- * stretched every layout to fill a fixed 500x500 canvas, which squashed a wide
10
- * auditorium into flattened rectangles.
11
- */
12
- export interface PlacedSeat {
13
- seat: RenderSeat;
14
- /** Top-left corner, in viewBox units. */
15
- x: number;
16
- y: number;
17
- width: number;
18
- height: number;
19
- centerX: number;
20
- centerY: number;
21
- fontSize: number;
22
- /** Degrees about the seat center; 0 unless the document asked for a tilt. */
23
- rotation: number;
24
- }
25
- export interface PlacedElement {
26
- element: RenderElement;
27
- x: number;
28
- y: number;
29
- width: number;
30
- height: number;
31
- centerX: number;
32
- centerY: number;
33
- fontSize: number;
34
- rotation: number;
35
- }
36
- export interface SectionLayout {
37
- /** Intrinsic viewBox width. */
38
- width: number;
39
- /** Intrinsic viewBox height. */
40
- height: number;
41
- seats: readonly PlacedSeat[];
42
- elements: readonly PlacedElement[];
43
- }
44
- export interface SectionLayoutOptions {
45
- /** Grid cell edge, in viewBox units. */
46
- seatSize?: number;
47
- /** Gap between adjacent cells, in viewBox units. */
48
- seatGap?: number;
49
- /** Freeform viewBox width; height follows from the aspect ratio. */
50
- freeformBasis?: number;
51
- /** Overrides `Section.aspectRatio`. */
52
- aspectRatio?: string;
53
- /** Mirrors the grid horizontally, for right-to-left locales. */
54
- rtl?: boolean;
55
- }
56
- /**
57
- * Places a section's seats and elements. Dispatches on the section's own
58
- * resolved layout mode, so a map may mix grid, freeform and mixed sections —
59
- * the pre-1.0 adapter collapsed the whole map to a single mode.
60
- *
61
- * `mixed` is laid out as freeform: §4.3.1 makes `x`/`y` authoritative for
62
- * visual placement when both are present. Its `col` survives on the seat and is
63
- * consumed by `navigation-order.ts`.
64
- */
65
- export declare function computeSectionLayout(section: RenderSection, options?: SectionLayoutOptions): SectionLayout;
66
- //# sourceMappingURL=section-layout.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"section-layout.d.ts","sourceRoot":"","sources":["../../src/render/section-layout.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAE7E;;;;;;;;;GASG;AAEH,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,UAAU,CAAC;IACjB,yCAAyC;IACzC,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,6EAA6E;IAC7E,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,aAAa,CAAC;IACvB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,aAAa;IAC5B,+BAA+B;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,gCAAgC;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,SAAS,UAAU,EAAE,CAAC;IAC7B,QAAQ,EAAE,SAAS,aAAa,EAAE,CAAC;CACpC;AAED,MAAM,WAAW,oBAAoB;IACnC,wCAAwC;IACxC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,oDAAoD;IACpD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,oEAAoE;IACpE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,uCAAuC;IACvC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gEAAgE;IAChE,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAWD;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,aAAa,EACtB,OAAO,GAAE,oBAAyB,GACjC,aAAa,CAIf"}
@@ -1,186 +0,0 @@
1
- import { elementStyle } from './element-shapes.js';
2
- const DEFAULTS = {
3
- seatSize: 28,
4
- seatGap: 6,
5
- freeformBasis: 1000,
6
- };
7
- /** Padding around the seating area, as a multiple of the seat size. */
8
- const PADDING_RATIO = 0.5;
9
- /**
10
- * Places a section's seats and elements. Dispatches on the section's own
11
- * resolved layout mode, so a map may mix grid, freeform and mixed sections —
12
- * the pre-1.0 adapter collapsed the whole map to a single mode.
13
- *
14
- * `mixed` is laid out as freeform: §4.3.1 makes `x`/`y` authoritative for
15
- * visual placement when both are present. Its `col` survives on the seat and is
16
- * consumed by `navigation-order.ts`.
17
- */
18
- export function computeSectionLayout(section, options = {}) {
19
- return section.layoutMode === 'grid'
20
- ? computeGridLayout(section, options)
21
- : computeFreeformLayout(section, options);
22
- }
23
- // --- grid -------------------------------------------------------------------
24
- /**
25
- * Places seats and elements on the `(row, col)` lattice.
26
- *
27
- * Both axes reserve space the same way. A column no seat occupies is simply
28
- * empty space — §4.3.2's "no filler objects": the gap that is an aisle needs no
29
- * placeholder seat, and none is synthesized. A row no seat occupies is an empty
30
- * row the document declared (§4.2.2), already materialized in `section.rows`,
31
- * so it costs a full row pitch here without this function knowing it is empty.
32
- * That is what opens the throw between a cinema screen and row A.
33
- */
34
- function computeGridLayout(section, options) {
35
- const size = options.seatSize ?? DEFAULTS.seatSize;
36
- const gap = options.seatGap ?? DEFAULTS.seatGap;
37
- const pitch = size + gap;
38
- const padding = size * PADDING_RATIO;
39
- const columns = columnExtent(section);
40
- const rowCount = Math.max(section.rows.length, 1);
41
- const width = padding * 2 + columns.count * pitch - gap;
42
- const height = padding * 2 + rowCount * pitch - gap;
43
- /** Column index → x, mirrored when the locale reads right-to-left. */
44
- const colX = (col) => {
45
- const offset = options.rtl ? columns.max - col : col - columns.min;
46
- return padding + offset * pitch;
47
- };
48
- const seats = [];
49
- for (const row of section.rows) {
50
- const y = padding + row.index * pitch;
51
- row.seats.forEach((seat, i) => {
52
- // A grid seat is required to carry `col` (§4.5); fall back to its index
53
- // so an unvalidated document still draws something in order.
54
- const x = colX(seat.col ?? columns.min + i);
55
- seats.push(box(seat, x, y, size, size, seat.rotation ?? 0));
56
- });
57
- }
58
- const elements = section.elements.map((element) => {
59
- // §4.4.1: in grid mode width/height are column and row spans in cells, not
60
- // percentages — a two-seat-wide lavatory is `{ col: 1, width: 2 }`, and a
61
- // screen filling two empty rows is `{ row: "screen-1", height: 2 }`. The
62
- // spec requires positive integers; a fractional span is an
63
- // `element-span-invalid` the validator rejects, and is rounded here so an
64
- // unvalidated document still draws something.
65
- const spanY = gridSpan(element.height);
66
- // Omitting `col` spans the section's full column extent and ignores
67
- // `width` — the usual form for a screen or a stage (§4.4.1).
68
- const elWidth = element.col !== undefined
69
- ? gridSpan(element.width) * pitch - gap
70
- : columns.count * pitch - gap;
71
- const elHeight = spanY * pitch - gap;
72
- // An element carrying x/y in a grid section violates §4.4.1 and the
73
- // validator rejects it; it still places, by percentage of the section box,
74
- // rather than collapsing into the corner.
75
- const x = element.col !== undefined
76
- ? colX(element.col)
77
- : element.x !== undefined
78
- ? (element.x / 100) * width - elWidth / 2
79
- : padding;
80
- const y = element.rowIndex !== undefined
81
- ? padding + element.rowIndex * pitch
82
- : element.y !== undefined
83
- ? (element.y / 100) * height - elHeight / 2
84
- : padding;
85
- return elementBox(element, x, y, elWidth, elHeight);
86
- });
87
- return { width, height, seats, elements };
88
- }
89
- /**
90
- * A grid `width`/`height`, normalized. §4.4.1 makes these positive integers
91
- * defaulting to 1; rounding rather than rejecting keeps an invalid document
92
- * drawable, since the validator is what refuses it.
93
- */
94
- function gridSpan(span) {
95
- return Math.max(Math.round(span ?? 1), 1);
96
- }
97
- /** The lowest and highest column any seat occupies, and how many that spans. */
98
- function columnExtent(section) {
99
- const cols = section.seats
100
- .map((s) => s.col)
101
- .filter((c) => c !== undefined && c !== null);
102
- // An element's `width` is a column span in grid mode, so a two-cell-wide
103
- // lavatory at column 4 reaches column 5 and the canvas must cover it.
104
- const elementCols = section.elements
105
- .filter((e) => e.col !== undefined && e.col !== null)
106
- .flatMap((e) => [e.col, e.col + gridSpan(e.width) - 1]);
107
- const all = [...cols, ...elementCols];
108
- if (all.length === 0) {
109
- const fallback = Math.max(...section.rows.map((r) => r.seats.length), 1);
110
- return { min: 0, max: fallback - 1, count: fallback };
111
- }
112
- const min = Math.min(...all);
113
- const max = Math.max(...all);
114
- return { min, max, count: max - min + 1 };
115
- }
116
- // --- freeform / mixed -------------------------------------------------------
117
- /**
118
- * Places seats from percentage coordinates inside a box of the section's
119
- * aspect ratio. Because the box *is* the viewBox, percentages map linearly and
120
- * no letterboxing is needed — the SVG's `preserveAspectRatio` handles fitting
121
- * the box into whatever space CSS gives it.
122
- */
123
- function computeFreeformLayout(section, options) {
124
- const width = options.freeformBasis ?? DEFAULTS.freeformBasis;
125
- const height = width / parseAspectRatio(options.aspectRatio ?? section.aspectRatio);
126
- const size = options.seatSize ?? Math.min(width, height) * 0.05;
127
- const seats = section.seats.map((seat) => {
128
- const centerX = ((seat.x ?? 0) / 100) * width;
129
- const centerY = ((seat.y ?? 0) / 100) * height;
130
- return box(seat, centerX - size / 2, centerY - size / 2, size, size, seat.rotation ?? 0);
131
- });
132
- const elements = section.elements.map((element) => {
133
- // In freeform mode width/height are percentages of the section box.
134
- const elWidth = ((element.width ?? 6) / 100) * width;
135
- const elHeight = ((element.height ?? 6) / 100) * height;
136
- const centerX = ((element.x ?? 50) / 100) * width;
137
- const centerY = ((element.y ?? 50) / 100) * height;
138
- return elementBox(element, centerX - elWidth / 2, centerY - elHeight / 2, elWidth, elHeight);
139
- });
140
- return { width, height, seats, elements };
141
- }
142
- /** "16:9" → 1.777…. Falls back to square for anything unparseable. */
143
- function parseAspectRatio(ratio) {
144
- const [w, h] = ratio.split(':').map(Number);
145
- return w > 0 && h > 0 ? w / h : 1;
146
- }
147
- // --- shared -----------------------------------------------------------------
148
- function box(seat, x, y, width, height, rotation) {
149
- return {
150
- seat,
151
- x,
152
- y,
153
- width,
154
- height,
155
- centerX: x + width / 2,
156
- centerY: y + height / 2,
157
- fontSize: width * 0.4,
158
- rotation,
159
- };
160
- }
161
- function elementBox(element, x, y, width, height) {
162
- return {
163
- element,
164
- x,
165
- y,
166
- width,
167
- height,
168
- centerX: x + width / 2,
169
- centerY: y + height / 2,
170
- fontSize: elementFontSize(element, width, height),
171
- rotation: element.rotation ?? 0,
172
- };
173
- }
174
- /** Average glyph advance as a fraction of the font size, for fitting text to a width. */
175
- const GLYPH_WIDTH = 0.6;
176
- function elementFontSize(element, width, height) {
177
- if (elementStyle(element.kind).shape !== 'text') {
178
- return Math.max(Math.min(height * 0.5, width * 0.18), 6);
179
- }
180
- // A text element has no box to read from, so the height sets the size and the
181
- // width only shrinks it, so the whole label fits however long it is.
182
- const base = Math.max(height * 0.6, 6);
183
- const length = element.label?.length ?? 0;
184
- return length ? Math.min(base, width / (length * GLYPH_WIDTH)) : base;
185
- }
186
- //# sourceMappingURL=section-layout.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"section-layout.js","sourceRoot":"","sources":["../../src/render/section-layout.ts"],"names":[],"mappings":"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"}