ooxml-core 0.21.2 → 0.22.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.
- package/README.md +3 -4
- package/dist/automation/index.cjs +34 -13
- package/dist/automation/index.mjs +34 -13
- package/dist/chart/index.cjs +242 -0
- package/dist/chart/index.d.ts +5 -0
- package/dist/chart/index.d.ts.map +1 -1
- package/dist/chart/index.mjs +227 -1
- package/dist/chart/pie-best-fit.d.ts +51 -0
- package/dist/chart/pie-best-fit.d.ts.map +1 -0
- package/dist/chart/pie-label-collision.d.ts +48 -0
- package/dist/chart/pie-label-collision.d.ts.map +1 -0
- package/dist/chart/radar-geometry.d.ts +19 -0
- package/dist/chart/radar-geometry.d.ts.map +1 -0
- package/dist/chart/treemap-squarify.d.ts +31 -0
- package/dist/chart/treemap-squarify.d.ts.map +1 -0
- package/dist/chart/trendline-equation.d.ts +39 -0
- package/dist/chart/trendline-equation.d.ts.map +1 -0
- package/dist/collab/index.cjs +6 -1
- package/dist/collab/index.mjs +6 -1
- package/dist/color/contrast.d.ts +18 -0
- package/dist/color/contrast.d.ts.map +1 -0
- package/dist/color/index.cjs +33 -0
- package/dist/color/index.d.ts +2 -0
- package/dist/color/index.d.ts.map +1 -1
- package/dist/color/index.mjs +31 -1
- package/dist/color/unit-rgb.d.ts +21 -0
- package/dist/color/unit-rgb.d.ts.map +1 -0
- package/dist/docx/embedded.cjs +1 -1
- package/dist/docx/embedded.mjs +1 -1
- package/dist/docx/index.cjs +1 -1
- package/dist/docx/index.mjs +1 -1
- package/dist/docx/load/index.cjs +1 -1
- package/dist/docx/load/index.mjs +1 -1
- package/dist/geometry/align-distribute.d.ts +145 -0
- package/dist/geometry/align-distribute.d.ts.map +1 -0
- package/dist/geometry/index.cjs +318 -0
- package/dist/geometry/index.d.ts +2 -0
- package/dist/geometry/index.d.ts.map +1 -1
- package/dist/geometry/index.mjs +307 -1
- package/dist/geometry/snap-guides.d.ts +125 -0
- package/dist/geometry/snap-guides.d.ts.map +1 -0
- package/dist/index.cjs +665 -0
- package/dist/index.mjs +665 -0
- package/dist/pptx/automation/index.cjs +24 -1
- package/dist/pptx/automation/index.d.ts +3 -3
- package/dist/pptx/automation/index.mjs +24 -1
- package/dist/pptx/chunks/{index-JaNVJ6Tf.d.ts → index-D2y7ehZ5.d.ts} +3 -3
- package/dist/pptx/chunks/{index-JaNVJ6Tf.d.ts.map → index-D2y7ehZ5.d.ts.map} +1 -1
- package/dist/pptx/chunks/{index-DHdHU9Qr.d.ts → index-ucqKcqvI.d.ts} +10 -2
- package/dist/pptx/chunks/{index-DHdHU9Qr.d.ts.map → index-ucqKcqvI.d.ts.map} +1 -1
- package/dist/pptx/chunks/{text-operations-DUEhSW5Z.d.ts → text-operations-CR3pUJi-.d.ts} +14 -2
- package/dist/pptx/chunks/text-operations-CR3pUJi-.d.ts.map +1 -0
- package/dist/pptx/cli/index.cjs +23 -0
- package/dist/pptx/cli/index.d.ts +1 -1
- package/dist/pptx/cli/index.mjs +23 -0
- package/dist/pptx/converter/index.d.ts +1 -1
- package/dist/pptx/index.cjs +33 -3
- package/dist/pptx/index.d.ts +3 -3
- package/dist/pptx/index.mjs +33 -3
- package/dist/teams/index.cjs +7 -2
- package/dist/teams/index.mjs +7 -2
- package/dist/text/decimal-tab.d.ts +24 -0
- package/dist/text/decimal-tab.d.ts.map +1 -0
- package/dist/text/index.cjs +72 -0
- package/dist/text/index.d.ts +2 -0
- package/dist/text/index.d.ts.map +1 -1
- package/dist/text/index.mjs +68 -1
- package/dist/text/tab-leader.d.ts +36 -0
- package/dist/text/tab-leader.d.ts.map +1 -0
- package/dist/xlsx/edit/charts.d.ts.map +1 -1
- package/dist/xlsx/edit/clipboard-html-parse.d.ts.map +1 -1
- package/dist/xlsx/index.cjs +33 -12
- package/dist/xlsx/index.mjs +33 -12
- package/dist/xlsx/ui/grid/cell-paint.d.ts.map +1 -1
- package/dist/xlsx/ui/index.cjs +37 -16
- package/dist/xlsx/ui/index.mjs +37 -16
- package/package.json +2 -2
- package/dist/pptx/chunks/text-operations-DUEhSW5Z.d.ts.map +0 -1
package/dist/chart/index.mjs
CHANGED
|
@@ -378,4 +378,230 @@ function aggregateByCategory(values, rawCategories) {
|
|
|
378
378
|
});
|
|
379
379
|
}
|
|
380
380
|
|
|
381
|
-
|
|
381
|
+
// chart/treemap-squarify.ts
|
|
382
|
+
function worstAspectRatio(areas, side) {
|
|
383
|
+
const sum = areas.reduce((total, area) => total + area, 0);
|
|
384
|
+
const max = Math.max(...areas);
|
|
385
|
+
const min = Math.min(...areas);
|
|
386
|
+
const sideSq = side * side;
|
|
387
|
+
const sumSq = sum * sum;
|
|
388
|
+
return Math.max(sideSq * max / sumSq, sumSq / (sideSq * min));
|
|
389
|
+
}
|
|
390
|
+
function squarify(nodes, box) {
|
|
391
|
+
const sorted = [...nodes].sort((a, b) => b.weight - a.weight);
|
|
392
|
+
const total = sorted.reduce((sum, node) => sum + node.weight, 0);
|
|
393
|
+
const scale = total > 0 ? box.w * box.h / total : box.w * box.h / sorted.length;
|
|
394
|
+
const items = sorted.map((node) => ({ node, area: (total > 0 ? node.weight : 1) * scale }));
|
|
395
|
+
const result = [];
|
|
396
|
+
let rect = { ...box };
|
|
397
|
+
let remaining = items;
|
|
398
|
+
for (let first = remaining[0]; first !== void 0; first = remaining[0]) {
|
|
399
|
+
const side = Math.min(rect.w, rect.h);
|
|
400
|
+
let row = [first];
|
|
401
|
+
let rowAreas = [first.area];
|
|
402
|
+
let worst = worstAspectRatio(rowAreas, side);
|
|
403
|
+
let cursor = 1;
|
|
404
|
+
for (let next = remaining[cursor]; next !== void 0; next = remaining[cursor]) {
|
|
405
|
+
const candidateAreas = [...rowAreas, next.area];
|
|
406
|
+
const candidateWorst = worstAspectRatio(candidateAreas, side);
|
|
407
|
+
if (candidateWorst > worst) {
|
|
408
|
+
break;
|
|
409
|
+
}
|
|
410
|
+
row = [...row, next];
|
|
411
|
+
rowAreas = candidateAreas;
|
|
412
|
+
worst = candidateWorst;
|
|
413
|
+
cursor++;
|
|
414
|
+
}
|
|
415
|
+
const rowTotalArea = rowAreas.reduce((sum, area) => sum + area, 0);
|
|
416
|
+
const thickness = side > 0 ? rowTotalArea / side : 0;
|
|
417
|
+
const layoutVertically = rect.w >= rect.h;
|
|
418
|
+
let offset = layoutVertically ? rect.y : rect.x;
|
|
419
|
+
for (const item of row) {
|
|
420
|
+
const length = thickness > 0 ? item.area / thickness : 0;
|
|
421
|
+
if (layoutVertically) {
|
|
422
|
+
result.push([item.node, { x: rect.x, y: offset, w: thickness, h: length }]);
|
|
423
|
+
} else {
|
|
424
|
+
result.push([item.node, { x: offset, y: rect.y, w: length, h: thickness }]);
|
|
425
|
+
}
|
|
426
|
+
offset += length;
|
|
427
|
+
}
|
|
428
|
+
rect = layoutVertically ? { ...rect, x: rect.x + thickness, w: rect.w - thickness } : { ...rect, y: rect.y + thickness, h: rect.h - thickness };
|
|
429
|
+
remaining = remaining.slice(row.length);
|
|
430
|
+
}
|
|
431
|
+
return result;
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
// chart/trendline-equation.ts
|
|
435
|
+
var SIGNIFICANT_DIGITS = 4;
|
|
436
|
+
function formatTrendlineCoefficient(value) {
|
|
437
|
+
if (!Number.isFinite(value) || value === 0) {
|
|
438
|
+
return "0";
|
|
439
|
+
}
|
|
440
|
+
const rounded = Number(value.toPrecision(SIGNIFICANT_DIGITS));
|
|
441
|
+
return rounded === 0 ? "0" : String(rounded);
|
|
442
|
+
}
|
|
443
|
+
function signedTerm(value) {
|
|
444
|
+
return { sign: value < 0 ? "-" : "+", abs: formatTrendlineCoefficient(Math.abs(value)) };
|
|
445
|
+
}
|
|
446
|
+
function formatLinearEquation(slope, intercept) {
|
|
447
|
+
const { sign, abs } = signedTerm(intercept);
|
|
448
|
+
return `y = ${formatTrendlineCoefficient(slope)}x ${sign} ${abs}`;
|
|
449
|
+
}
|
|
450
|
+
function formatExponentialEquation(a, b) {
|
|
451
|
+
return `y = ${formatTrendlineCoefficient(a)} e^(${formatTrendlineCoefficient(b)}x)`;
|
|
452
|
+
}
|
|
453
|
+
function formatLogarithmicEquation(slope, intercept) {
|
|
454
|
+
const { sign, abs } = signedTerm(intercept);
|
|
455
|
+
return `y = ${formatTrendlineCoefficient(slope)}ln(x) ${sign} ${abs}`;
|
|
456
|
+
}
|
|
457
|
+
function formatPowerEquation(a, b) {
|
|
458
|
+
return `y = ${formatTrendlineCoefficient(a)}x^${formatTrendlineCoefficient(b)}`;
|
|
459
|
+
}
|
|
460
|
+
function formatPolynomialEquation(coeffsAscending) {
|
|
461
|
+
const order = coeffsAscending.length - 1;
|
|
462
|
+
let out = "y = ";
|
|
463
|
+
for (let power = order; power >= 0; power--) {
|
|
464
|
+
const coeff = coeffsAscending[power] ?? 0;
|
|
465
|
+
const { sign, abs } = signedTerm(coeff);
|
|
466
|
+
const variable = power === 0 ? "" : power === 1 ? "x" : `x^${power}`;
|
|
467
|
+
out += power === order ? `${sign === "-" ? "-" : ""}${abs}${variable}` : ` ${sign} ${abs}${variable}`;
|
|
468
|
+
}
|
|
469
|
+
return out;
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
// chart/radar-geometry.ts
|
|
473
|
+
function radarAngle(index, catCount) {
|
|
474
|
+
const n = Math.max(catCount, 1);
|
|
475
|
+
return Math.PI * 2 * index / n - Math.PI / 2;
|
|
476
|
+
}
|
|
477
|
+
function computeRadarPoints(values, maxVal, radius, cx, cy, catCount) {
|
|
478
|
+
const denom = maxVal > 0 ? maxVal : 1;
|
|
479
|
+
return values.slice(0, Math.max(catCount, 1)).map((val, i) => {
|
|
480
|
+
const angle = radarAngle(i, catCount), r = Math.abs(val) / denom * radius;
|
|
481
|
+
return { x: cx + r * Math.cos(angle), y: cy + r * Math.sin(angle) };
|
|
482
|
+
});
|
|
483
|
+
}
|
|
484
|
+
function radarRingPoints(cx, cy, rr, catCount) {
|
|
485
|
+
const n = Math.max(catCount, 1);
|
|
486
|
+
return Array.from({ length: n }, (_, i) => {
|
|
487
|
+
const angle = radarAngle(i, n);
|
|
488
|
+
return `${(cx + rr * Math.cos(angle)).toFixed(2)},${(cy + rr * Math.sin(angle)).toFixed(2)}`;
|
|
489
|
+
}).join(" ");
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
// chart/pie-best-fit.ts
|
|
493
|
+
var PX_PER_PT = 4 / 3;
|
|
494
|
+
var BEST_FIT_RIM_INSET = 4 * PX_PER_PT;
|
|
495
|
+
var BEST_FIT_EDGE_TOLERANCE = 1.5 * PX_PER_PT;
|
|
496
|
+
var BEST_FIT_OUTSIDE_GAP = 2 * PX_PER_PT;
|
|
497
|
+
function farCorner(x, y, w, h) {
|
|
498
|
+
return Math.hypot(Math.abs(x) + w / 2, Math.abs(y) + h / 2);
|
|
499
|
+
}
|
|
500
|
+
function insideDistance(ux, uy, w, h, limit) {
|
|
501
|
+
if (farCorner(0, 0, w, h) > limit) {
|
|
502
|
+
return void 0;
|
|
503
|
+
}
|
|
504
|
+
let lo = 0;
|
|
505
|
+
let hi = limit;
|
|
506
|
+
for (let i = 0; i < 40; i++) {
|
|
507
|
+
const mid = (lo + hi) / 2;
|
|
508
|
+
if (farCorner(mid * ux, mid * uy, w, h) > limit) {
|
|
509
|
+
hi = mid;
|
|
510
|
+
} else {
|
|
511
|
+
lo = mid;
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
return lo;
|
|
515
|
+
}
|
|
516
|
+
function edgeOverhang(x, y, w, h, slice) {
|
|
517
|
+
let worst = Number.NEGATIVE_INFINITY;
|
|
518
|
+
const corners = [
|
|
519
|
+
[-w / 2, -h / 2],
|
|
520
|
+
[w / 2, -h / 2],
|
|
521
|
+
[-w / 2, h / 2],
|
|
522
|
+
[w / 2, h / 2]
|
|
523
|
+
];
|
|
524
|
+
for (const [dx, dy] of corners) {
|
|
525
|
+
const px = x + dx;
|
|
526
|
+
const py = y + dy;
|
|
527
|
+
const fromStart = Math.cos(slice.startAngle) * py - Math.sin(slice.startAngle) * px;
|
|
528
|
+
const fromEnd = Math.sin(slice.endAngle) * px - Math.cos(slice.endAngle) * py;
|
|
529
|
+
worst = Math.max(worst, -fromStart, -fromEnd);
|
|
530
|
+
}
|
|
531
|
+
return worst;
|
|
532
|
+
}
|
|
533
|
+
function placeBestFitLabel(slice, w, h) {
|
|
534
|
+
const mid = (slice.startAngle + slice.endAngle) / 2;
|
|
535
|
+
const ux = Math.cos(mid);
|
|
536
|
+
const uy = Math.sin(mid);
|
|
537
|
+
const distance = insideDistance(ux, uy, w, h, slice.outerR - BEST_FIT_RIM_INSET);
|
|
538
|
+
if (distance !== void 0) {
|
|
539
|
+
const x = distance * ux;
|
|
540
|
+
const y = distance * uy;
|
|
541
|
+
const reflex = slice.endAngle - slice.startAngle >= Math.PI;
|
|
542
|
+
if (reflex || edgeOverhang(x, y, w, h, slice) <= BEST_FIT_EDGE_TOLERANCE) {
|
|
543
|
+
return { x: slice.cx + x, y: slice.cy + y, inside: true };
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
const extent = Math.abs(ux) * w / 2 + Math.abs(uy) * h / 2;
|
|
547
|
+
const outside = slice.outerR + BEST_FIT_OUTSIDE_GAP + extent;
|
|
548
|
+
return { x: slice.cx + outside * ux, y: slice.cy + outside * uy, inside: false };
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
// chart/pie-label-collision.ts
|
|
552
|
+
var LABEL_COLLISION_GAP = 2;
|
|
553
|
+
function boxDistanceToCentre(box, y, disc) {
|
|
554
|
+
const nearestX = Math.max(box.x - box.w / 2, Math.min(disc.cx, box.x + box.w / 2));
|
|
555
|
+
const nearestY = Math.max(y - box.h / 2, Math.min(disc.cy, y + box.h / 2));
|
|
556
|
+
return Math.hypot(nearestX - disc.cx, nearestY - disc.cy);
|
|
557
|
+
}
|
|
558
|
+
function clearOfDisc(box, y, disc) {
|
|
559
|
+
if (boxDistanceToCentre(box, y, disc) >= disc.r) {
|
|
560
|
+
return 0;
|
|
561
|
+
}
|
|
562
|
+
const sign = box.x >= disc.cx ? 1 : -1;
|
|
563
|
+
let dx = 0;
|
|
564
|
+
while (dx < disc.r * 2 && boxDistanceToCentre({ ...box, x: box.x + sign * dx }, y, disc) < disc.r) {
|
|
565
|
+
dx += 1;
|
|
566
|
+
}
|
|
567
|
+
return sign * dx;
|
|
568
|
+
}
|
|
569
|
+
function overlapsX(a, b) {
|
|
570
|
+
return Math.abs(a.x - b.x) < (a.w + b.w) / 2;
|
|
571
|
+
}
|
|
572
|
+
function sweepSide(boxes, minY, maxY) {
|
|
573
|
+
const sorted = [...boxes].sort((a, b) => a.y - b.y || a.id - b.id);
|
|
574
|
+
const ys = sorted.map((box) => box.y);
|
|
575
|
+
for (let i = 1; i < sorted.length; i++) {
|
|
576
|
+
const prev = sorted[i - 1];
|
|
577
|
+
const box = sorted[i];
|
|
578
|
+
if (overlapsX(prev, box)) {
|
|
579
|
+
ys[i] = Math.max(ys[i], ys[i - 1] + (prev.h + box.h) / 2 + LABEL_COLLISION_GAP);
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
for (let i = sorted.length - 1; i >= 0; i--) {
|
|
583
|
+
const box = sorted[i];
|
|
584
|
+
const limit = i === sorted.length - 1 ? maxY - box.h / 2 : ys[i + 1] - (box.h + sorted[i + 1].h) / 2 - LABEL_COLLISION_GAP;
|
|
585
|
+
if (ys[i] > limit) {
|
|
586
|
+
ys[i] = Math.max(limit, minY + box.h / 2);
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
return new Map(sorted.map((box, i) => [box.id, ys[i]]));
|
|
590
|
+
}
|
|
591
|
+
function nudgeOutsideLabels(boxes, disc, minY, maxY) {
|
|
592
|
+
const resolved = /* @__PURE__ */ new Map();
|
|
593
|
+
for (const side of [
|
|
594
|
+
boxes.filter((box) => box.x >= disc.cx),
|
|
595
|
+
boxes.filter((box) => box.x < disc.cx)
|
|
596
|
+
]) {
|
|
597
|
+
for (const [id, y] of sweepSide(side, minY, maxY)) {
|
|
598
|
+
resolved.set(id, y);
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
return boxes.map((box) => {
|
|
602
|
+
const y = resolved.get(box.id) ?? box.y;
|
|
603
|
+
return { id: box.id, dx: y === box.y ? 0 : clearOfDisc(box, y, disc), dy: y - box.y };
|
|
604
|
+
});
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
export { BEST_FIT_EDGE_TOLERANCE, BEST_FIT_OUTSIDE_GAP, BEST_FIT_RIM_INSET, LABEL_COLLISION_GAP, aggregateByCategory, axisTargetIntervals, computeBoxStats, computeHistogramBins, computeLinearRegression, computeRSquared, computeRadarPoints, computeStackedSeriesPlots, fitPolynomial, formatExponentialEquation, formatLinearEquation, formatLogarithmicEquation, formatPolynomialEquation, formatPowerEquation, formatTrendlineCoefficient, groupRowsByCategory, niceAxisStep, niceValueAxisBounds, nudgeOutsideLabels, placeBestFitLabel, radarAngle, radarRingPoints, resolveBlankDisplay, scottBinCount, squarify, visibleRuns };
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where PowerPoint puts a pie data label at `c:dLblPos val="bestFit"`.
|
|
3
|
+
*
|
|
4
|
+
* COM ground truth (`chart-pie-best-fit.pptx`: eight pies of different slice
|
|
5
|
+
* sizes, boxed 12pt labels, measured from `Slide.Export` pixels at two pie
|
|
6
|
+
* sizes, R = 89.6pt and 190.3pt):
|
|
7
|
+
*
|
|
8
|
+
* - A label that fits inside its slice sits INSIDE it, on the slice's
|
|
9
|
+
* mid-angle, pushed out until the box corner farthest from the centre is
|
|
10
|
+
* 4pt inside the rim. The 4pt is the same for both pie sizes, so it is a
|
|
11
|
+
* fixed inset, not a fraction of the radius. (The renderer used to put
|
|
12
|
+
* every such label at 0.7 of the radius, well short of PowerPoint's.)
|
|
13
|
+
* - "Fits" means that box, so placed, stays inside the slice's two edges:
|
|
14
|
+
* PowerPoint tolerates about 1.5pt of overhang (a 10% slice with a
|
|
15
|
+
* two-line label is on the boundary: one of three stays inside).
|
|
16
|
+
* - A label that does not fit goes OUTSIDE, on the mid-angle, with the box
|
|
17
|
+
* side facing the pie 2pt beyond the rim. PowerPoint then nudges outside
|
|
18
|
+
* labels apart when they collide and draws leader lines to the nudged
|
|
19
|
+
* ones; that pass is `chart-pie-label-collision` (an approximation).
|
|
20
|
+
*
|
|
21
|
+
* All lengths are in the chart's px space (1pt = 4/3px).
|
|
22
|
+
*
|
|
23
|
+
* @module chart/pie-best-fit
|
|
24
|
+
*/
|
|
25
|
+
/** COM: the farthest box corner of an inside label sits this far inside the rim. */
|
|
26
|
+
export declare const BEST_FIT_RIM_INSET: number;
|
|
27
|
+
/** COM: how far a box may overhang a slice edge and still count as inside. */
|
|
28
|
+
export declare const BEST_FIT_EDGE_TOLERANCE: number;
|
|
29
|
+
/** COM: the gap between the rim and an outside label's box. */
|
|
30
|
+
export declare const BEST_FIT_OUTSIDE_GAP: number;
|
|
31
|
+
/** A slice as the placement needs it: centre, radius and its two edge angles. */
|
|
32
|
+
export interface BestFitSlice {
|
|
33
|
+
cx: number;
|
|
34
|
+
cy: number;
|
|
35
|
+
outerR: number;
|
|
36
|
+
/** Radians, SVG convention (0 = 3 o'clock, clockwise positive). */
|
|
37
|
+
startAngle: number;
|
|
38
|
+
endAngle: number;
|
|
39
|
+
}
|
|
40
|
+
/** Where the label box's centre goes, and whether that is inside the slice. */
|
|
41
|
+
export interface BestFitPlacement {
|
|
42
|
+
x: number;
|
|
43
|
+
y: number;
|
|
44
|
+
inside: boolean;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Place a `w x h` label box for a slice at `bestFit` (see the module doc).
|
|
48
|
+
* A slice of half the pie or more always has room, so its label stays inside.
|
|
49
|
+
*/
|
|
50
|
+
export declare function placeBestFitLabel(slice: BestFitSlice, w: number, h: number): BestFitPlacement;
|
|
51
|
+
//# sourceMappingURL=pie-best-fit.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pie-best-fit.d.ts","sourceRoot":"","sources":["../../chart/pie-best-fit.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAIH,oFAAoF;AACpF,eAAO,MAAM,kBAAkB,QAAgB,CAAC;AAChD,8EAA8E;AAC9E,eAAO,MAAM,uBAAuB,QAAkB,CAAC;AACvD,+DAA+D;AAC/D,eAAO,MAAM,oBAAoB,QAAgB,CAAC;AAElD,iFAAiF;AACjF,MAAM,WAAW,YAAY;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,mEAAmE;IACnE,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;CACjB;AAED,+EAA+E;AAC/E,MAAM,WAAW,gBAAgB;IAChC,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,MAAM,EAAE,OAAO,CAAC;CAChB;AAsDD;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,YAAY,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,gBAAgB,CAiB7F"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* chart-pie-label-collision.ts: nudge colliding OUTSIDE pie labels apart.
|
|
3
|
+
*
|
|
4
|
+
* At `c:dLblPos val="bestFit"` PowerPoint puts a label that does not fit in its
|
|
5
|
+
* slice outside the rim; when two such labels overlap it moves them apart
|
|
6
|
+
* (vertically, within their own side of the pie) and draws a leader line to
|
|
7
|
+
* each one it moved. This module is the pure geometry half: it takes the
|
|
8
|
+
* outside label boxes and returns how far each one moves. The caller decides
|
|
9
|
+
* what to draw (a moved label gets a leader line; see `chart-pie-labels`).
|
|
10
|
+
*
|
|
11
|
+
* The algorithm is a per-side sweep: labels on the right (or left) of the pie
|
|
12
|
+
* are sorted top to bottom, each is pushed below the previous one when they
|
|
13
|
+
* overlap, and if the stack then runs past the bottom bound it is shifted back
|
|
14
|
+
* up. Constants are not COM-measured; the gap is one line of breathing room.
|
|
15
|
+
*
|
|
16
|
+
* @module chart/pie-label-collision
|
|
17
|
+
*/
|
|
18
|
+
/** Minimum vertical gap (px) kept between two nudged labels. */
|
|
19
|
+
export declare const LABEL_COLLISION_GAP = 2;
|
|
20
|
+
/** One outside label box: its centre and size, keyed by an opaque id. */
|
|
21
|
+
export interface OutsideLabelBox {
|
|
22
|
+
id: number;
|
|
23
|
+
/** Box centre, in the same space as `pieCx`. */
|
|
24
|
+
x: number;
|
|
25
|
+
y: number;
|
|
26
|
+
w: number;
|
|
27
|
+
h: number;
|
|
28
|
+
}
|
|
29
|
+
/** How far one label moves (`dx`/`dy` are 0 when it stays put). */
|
|
30
|
+
export interface LabelNudge {
|
|
31
|
+
id: number;
|
|
32
|
+
dx: number;
|
|
33
|
+
dy: number;
|
|
34
|
+
}
|
|
35
|
+
/** The pie disc a nudged label must never be pushed into. */
|
|
36
|
+
export interface PieDisc {
|
|
37
|
+
cx: number;
|
|
38
|
+
cy: number;
|
|
39
|
+
r: number;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Compute the vertical nudges that separate overlapping outside labels.
|
|
43
|
+
* `disc` splits the labels into a left and a right column and keeps every
|
|
44
|
+
* nudged label outside the pie; `minY`/`maxY` bound the drawing area. Labels
|
|
45
|
+
* that do not collide get `dx: 0, dy: 0`.
|
|
46
|
+
*/
|
|
47
|
+
export declare function nudgeOutsideLabels(boxes: ReadonlyArray<OutsideLabelBox>, disc: PieDisc, minY: number, maxY: number): LabelNudge[];
|
|
48
|
+
//# sourceMappingURL=pie-label-collision.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pie-label-collision.d.ts","sourceRoot":"","sources":["../../chart/pie-label-collision.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,gEAAgE;AAChE,eAAO,MAAM,mBAAmB,IAAI,CAAC;AAErC,yEAAyE;AACzE,MAAM,WAAW,eAAe;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,gDAAgD;IAChD,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACV;AAED,mEAAmE;AACnE,MAAM,WAAW,UAAU;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;CACX;AAED,6DAA6D;AAC7D,MAAM,WAAW,OAAO;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,CAAC,EAAE,MAAM,CAAC;CACV;AA+DD;;;;;GAKG;AACH,wBAAgB,kBAAkB,CACjC,KAAK,EAAE,aAAa,CAAC,eAAe,CAAC,EACrC,IAAI,EAAE,OAAO,EACb,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GACV,UAAU,EAAE,CAcd"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* chart-radar-geometry.ts: radar (spider) chart polar-coordinate geometry,
|
|
3
|
+
* split out of `chart-view-model-points.ts` to keep that file within the
|
|
4
|
+
* repo's ~300-LOC limit. Re-exported from there (and from `chart-view-model.ts`)
|
|
5
|
+
* so the public import surface is unchanged.
|
|
6
|
+
*
|
|
7
|
+
* @module chart/radar-geometry
|
|
8
|
+
*/
|
|
9
|
+
/** Angle (radians) of the i-th radar spoke; 0 points up (-90°), clockwise. */
|
|
10
|
+
export declare function radarAngle(index: number, catCount: number): number;
|
|
11
|
+
export interface RadarPoint {
|
|
12
|
+
x: number;
|
|
13
|
+
y: number;
|
|
14
|
+
}
|
|
15
|
+
/** Project a series' values onto radar (polar) coordinates around (cx, cy). */
|
|
16
|
+
export declare function computeRadarPoints(values: ReadonlyArray<number>, maxVal: number, radius: number, cx: number, cy: number, catCount: number): RadarPoint[];
|
|
17
|
+
/** Points string for a radar gridline ring at radius `rr`. */
|
|
18
|
+
export declare function radarRingPoints(cx: number, cy: number, rr: number, catCount: number): string;
|
|
19
|
+
//# sourceMappingURL=radar-geometry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"radar-geometry.d.ts","sourceRoot":"","sources":["../../chart/radar-geometry.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,8EAA8E;AAC9E,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAGlE;AAED,MAAM,WAAW,UAAU;IAC1B,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACV;AAED,+EAA+E;AAC/E,wBAAgB,kBAAkB,CACjC,MAAM,EAAE,aAAa,CAAC,MAAM,CAAC,EAC7B,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,EACV,QAAQ,EAAE,MAAM,GACd,UAAU,EAAE,CAOd;AAED,8DAA8D;AAC9D,wBAAgB,eAAe,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAM5F"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Squarified treemap layout algorithm, generic over any weighted node.
|
|
3
|
+
* Split out of `chart-treemap-hierarchy.ts` (which supplies the node/box
|
|
4
|
+
* shapes and drives the recursive render) to keep each file under the
|
|
5
|
+
* repo's ~300-LOC budget.
|
|
6
|
+
*
|
|
7
|
+
* @module chart/treemap-squarify
|
|
8
|
+
*/
|
|
9
|
+
export interface TreemapBox {
|
|
10
|
+
x: number;
|
|
11
|
+
y: number;
|
|
12
|
+
w: number;
|
|
13
|
+
h: number;
|
|
14
|
+
}
|
|
15
|
+
interface WeightedNode {
|
|
16
|
+
weight: number;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Squarified treemap layout (Bruls, Huizing & van Wijk): repeatedly lays out
|
|
20
|
+
* the widest possible "row" of items along the box's shorter side, adding
|
|
21
|
+
* items to the row only while doing so keeps improving (or not worsening)
|
|
22
|
+
* that row's worst aspect ratio, so cells stay close to square instead of
|
|
23
|
+
* degenerating into thin slivers the way a plain alternating slice-and-dice
|
|
24
|
+
* split does. COM-verified against charts-com.pptx slide 28 (chartEx3.xml):
|
|
25
|
+
* PowerPoint's own treemap mixes row and column splits within the SAME
|
|
26
|
+
* parent region (e.g. a tall cell beside a further row/column split), which
|
|
27
|
+
* a single alternating dimension split can never reproduce.
|
|
28
|
+
*/
|
|
29
|
+
export declare function squarify<TNode extends WeightedNode>(nodes: readonly TNode[], box: TreemapBox): Array<[TNode, TreemapBox]>;
|
|
30
|
+
export {};
|
|
31
|
+
//# sourceMappingURL=treemap-squarify.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"treemap-squarify.d.ts","sourceRoot":"","sources":["../../chart/treemap-squarify.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,WAAW,UAAU;IAC1B,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACV;AAED,UAAU,YAAY;IACrB,MAAM,EAAE,MAAM,CAAC;CACf;AAYD;;;;;;;;;;GAUG;AACH,wBAAgB,QAAQ,CAAC,KAAK,SAAS,YAAY,EAClD,KAAK,EAAE,SAAS,KAAK,EAAE,EACvB,GAAG,EAAE,UAAU,GACb,KAAK,CAAC,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC,CAkD5B"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* chart-trendline-equation-format.ts: Excel-style trendline equation text
|
|
3
|
+
* formatting.
|
|
4
|
+
*
|
|
5
|
+
* Excel's own trendline equation display (`c:trendlineLbl` with
|
|
6
|
+
* `c:dispEq val="1"`) rounds every coefficient to a handful of SIGNIFICANT
|
|
7
|
+
* digits in plain decimal notation, not a fixed number of decimal places: a
|
|
8
|
+
* small slope like 0.003742 stays "0.003742"-ish (four significant figures),
|
|
9
|
+
* where `.toFixed(2)` would flatten it to "0.00" and silently erase the fit.
|
|
10
|
+
* It also lays out each trendline family in its own fixed shape (exponential
|
|
11
|
+
* as `y = a e^(bx)`, a polynomial in DESCENDING powers), which this module
|
|
12
|
+
* is the single source of truth for so it cannot drift between the fit types.
|
|
13
|
+
*
|
|
14
|
+
* @module chart/trendline-equation
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* Format one coefficient to `SIGNIFICANT_DIGITS` significant figures in plain
|
|
18
|
+
* decimal notation (falls back to exponential only where `Number#toString`
|
|
19
|
+
* itself would, i.e. extreme magnitudes), with insignificant trailing zeros
|
|
20
|
+
* dropped. `-0` normalises to `"0"`.
|
|
21
|
+
*/
|
|
22
|
+
export declare function formatTrendlineCoefficient(value: number): string;
|
|
23
|
+
/** `y = mx + b` (linear) or `y = mx - b` when the intercept is negative. */
|
|
24
|
+
export declare function formatLinearEquation(slope: number, intercept: number): string;
|
|
25
|
+
/** `y = a e^(bx)`: Excel's own exponential trendline layout. */
|
|
26
|
+
export declare function formatExponentialEquation(a: number, b: number): string;
|
|
27
|
+
/** `y = a ln(x) + b` (logarithmic), `-` glue when the intercept is negative. */
|
|
28
|
+
export declare function formatLogarithmicEquation(slope: number, intercept: number): string;
|
|
29
|
+
/** `y = a x^b` (power). */
|
|
30
|
+
export declare function formatPowerEquation(a: number, b: number): string;
|
|
31
|
+
/**
|
|
32
|
+
* `y = a_n x^n + ... + a_1 x + a_0`: a polynomial in DESCENDING powers of x
|
|
33
|
+
* (Excel's own layout), from `coeffsAscending` ([a0, a1, ..., an], the order
|
|
34
|
+
* `fitPolynomial` returns them in). The highest-order term never shows a
|
|
35
|
+
* redundant leading `+`; `x^1` drops its exponent; the constant term (`x^0`)
|
|
36
|
+
* drops the variable entirely.
|
|
37
|
+
*/
|
|
38
|
+
export declare function formatPolynomialEquation(coeffsAscending: readonly number[]): string;
|
|
39
|
+
//# sourceMappingURL=trendline-equation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trendline-equation.d.ts","sourceRoot":"","sources":["../../chart/trendline-equation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAKH;;;;;GAKG;AACH,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAWhE;AAOD,4EAA4E;AAC5E,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAG7E;AAED,gEAAgE;AAChE,wBAAgB,yBAAyB,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAEtE;AAED,gFAAgF;AAChF,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAGlF;AAED,2BAA2B;AAC3B,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAEhE;AAED;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CAAC,eAAe,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAanF"}
|
package/dist/collab/index.cjs
CHANGED
|
@@ -1274,7 +1274,7 @@ function createTransportProvider({ doc, awareness }, { transport, maxMessageByte
|
|
|
1274
1274
|
// collab/websocket-transport.ts
|
|
1275
1275
|
var OPEN = 1;
|
|
1276
1276
|
function roomUrl(server, roomId) {
|
|
1277
|
-
return `${server
|
|
1277
|
+
return `${trimTrailingSlashes(server)}/${encodeURIComponent(roomId)}`;
|
|
1278
1278
|
}
|
|
1279
1279
|
function createWebSocketTransport(options) {
|
|
1280
1280
|
const { baseDelayMs = 250, maxDelayMs = 1e4, maxRetries = Infinity } = options;
|
|
@@ -1345,6 +1345,11 @@ function createWebSocketTransport(options) {
|
|
|
1345
1345
|
}
|
|
1346
1346
|
};
|
|
1347
1347
|
}
|
|
1348
|
+
function trimTrailingSlashes(value) {
|
|
1349
|
+
let end = value.length;
|
|
1350
|
+
while (end > 0 && value.charCodeAt(end - 1) === 47) end--;
|
|
1351
|
+
return value.slice(0, end);
|
|
1352
|
+
}
|
|
1348
1353
|
|
|
1349
1354
|
exports.BROADCAST_THROTTLE_MS = BROADCAST_THROTTLE_MS;
|
|
1350
1355
|
exports.BoundedMap = BoundedMap;
|
package/dist/collab/index.mjs
CHANGED
|
@@ -1250,7 +1250,7 @@ function createTransportProvider({ doc, awareness }, { transport, maxMessageByte
|
|
|
1250
1250
|
// collab/websocket-transport.ts
|
|
1251
1251
|
var OPEN = 1;
|
|
1252
1252
|
function roomUrl(server, roomId) {
|
|
1253
|
-
return `${server
|
|
1253
|
+
return `${trimTrailingSlashes(server)}/${encodeURIComponent(roomId)}`;
|
|
1254
1254
|
}
|
|
1255
1255
|
function createWebSocketTransport(options) {
|
|
1256
1256
|
const { baseDelayMs = 250, maxDelayMs = 1e4, maxRetries = Infinity } = options;
|
|
@@ -1321,5 +1321,10 @@ function createWebSocketTransport(options) {
|
|
|
1321
1321
|
}
|
|
1322
1322
|
};
|
|
1323
1323
|
}
|
|
1324
|
+
function trimTrailingSlashes(value) {
|
|
1325
|
+
let end = value.length;
|
|
1326
|
+
while (end > 0 && value.charCodeAt(end - 1) === 47) end--;
|
|
1327
|
+
return value.slice(0, end);
|
|
1328
|
+
}
|
|
1324
1329
|
|
|
1325
1330
|
export { BROADCAST_THROTTLE_MS, BoundedMap, COLLABORATION_ROLES, COLLAB_LEAVE_MESSAGE, CONNECTION_TIMEOUT_MS, CURSOR_PALETTE, DEFAULT_COLOR, DEFAULT_MAX_PACKAGE_BYTES, DEPARTURE_CHANNEL, Emitter, INITIAL_SYNC_GRACE_MS, IdempotencyCache, LEGACY_PPTX_DEPARTURE_CHANNEL, LEGACY_PPTX_LEAVE_MESSAGE, LOCAL_ORIGIN, MAX_LABEL_CHARS, MAX_UPDATE_BYTES, MESSAGE_AWARENESS, MESSAGE_QUERY_AWARENESS, MESSAGE_SYNC, PRESENCE_FIELD, PRESENCE_HEARTBEAT_MS, STALE_PRESENCE_MS, SequenceTracker, adaptYjsProvider, applyUpdateSafe, asSelectionIds, assignUserColor, bindDocument, borrowAwareness, buildRoster, canBroadcast, canWrite, clampCoordinate, classifyVersion, clearLocalAwareness, createAssetSync, createBroadcastTransport, createClientId, createCollabSession, createDepartureChannel, createIdGenerator, createMemoryHub, createPresencePublisher, createSyncGate, createTransportProvider, createWebSocketTransport, deriveCanvasPresence, derivePresence, encodeDiff, encodeSnapshot, encodeStateVector2 as encodeStateVector, formatCursorLabel, freezeDeep, fromBase64, getUserInitials, isMixedContentBlocked, isNonNegativeSafeInteger, isPresenceFresh, isValidId, isValidRoomId, mergeUpdates2 as mergeUpdates, observeExternalSession, packageAdapter, presenceToCursors, registerTeardown, removeAwarenessStatesLocally, restoreSnapshot, roomUrl, sanitizeAvatarUrl, sanitizeCanvasPayload, sanitizeColor, sanitizeIdentity, sanitizeIndex, sanitizeRole, sanitizeUserName, shouldAutoFollowBroadcaster, shouldRoomReplaceLoad, stripHtmlTags, toBase64, transportProvider, validateDisplayName, validateRoomId, validateUpdate };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Readable-text-colour selection for fills whose text colour was left implicit.
|
|
3
|
+
*
|
|
4
|
+
* PowerPoint stores no colour for a great many runs and resolves one at paint
|
|
5
|
+
* time from what is behind them. Renderers that instead pick a fixed colour get
|
|
6
|
+
* white text on white panels, so both the 2D and 3D SmartArt paths need the same
|
|
7
|
+
* decision, made the same way.
|
|
8
|
+
*
|
|
9
|
+
* @module color/contrast
|
|
10
|
+
*/
|
|
11
|
+
/** Parse `#rgb`/`#rrggbb` into `[r, g, b]` (0..255); falls back to mid-grey. */
|
|
12
|
+
export declare function parseHex(hex: string): [number, number, number];
|
|
13
|
+
/**
|
|
14
|
+
* Pick a readable text colour (near-black or near-white) for a given fill,
|
|
15
|
+
* using the WCAG relative-luminance threshold.
|
|
16
|
+
*/
|
|
17
|
+
export declare function contrastTextColor(fill: string): string;
|
|
18
|
+
//# sourceMappingURL=contrast.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contrast.d.ts","sourceRoot":"","sources":["../../color/contrast.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,gFAAgF;AAChF,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAY9D;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAItD"}
|
package/dist/color/index.cjs
CHANGED
|
@@ -160,16 +160,49 @@ function linearToSrgb255(linear) {
|
|
|
160
160
|
return 255 * (c <= 31308e-7 ? c * 12.92 : 1.055 * c ** (1 / 2.4) - 0.055);
|
|
161
161
|
}
|
|
162
162
|
|
|
163
|
+
// color/contrast.ts
|
|
164
|
+
function parseHex(hex) {
|
|
165
|
+
let h = hex.trim().replace(/^#/u, "");
|
|
166
|
+
if (h.length === 3) {
|
|
167
|
+
h = h.split("").map((c) => c + c).join("");
|
|
168
|
+
}
|
|
169
|
+
if (h.length !== 6 || /[^0-9a-fA-F]/u.test(h)) {
|
|
170
|
+
return [128, 128, 128];
|
|
171
|
+
}
|
|
172
|
+
return [parseInt(h.slice(0, 2), 16), parseInt(h.slice(2, 4), 16), parseInt(h.slice(4, 6), 16)];
|
|
173
|
+
}
|
|
174
|
+
function contrastTextColor(fill) {
|
|
175
|
+
const [r, g, b] = parseHex(fill);
|
|
176
|
+
const lum = (0.299 * r + 0.587 * g + 0.114 * b) / 255;
|
|
177
|
+
return lum > 0.6 ? "#1a1a1a" : "#ffffff";
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// color/unit-rgb.ts
|
|
181
|
+
function hexToRgbUnit(hex) {
|
|
182
|
+
const clean = hex.replace(/^#/u, "");
|
|
183
|
+
const r = Number.parseInt(clean.substring(0, 2), 16) / 255;
|
|
184
|
+
const g = Number.parseInt(clean.substring(2, 4), 16) / 255;
|
|
185
|
+
const b = Number.parseInt(clean.substring(4, 6), 16) / 255;
|
|
186
|
+
return {
|
|
187
|
+
r: Number.isFinite(r) ? r : 0,
|
|
188
|
+
g: Number.isFinite(g) ? g : 0,
|
|
189
|
+
b: Number.isFinite(b) ? b : 0
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
|
|
163
193
|
exports.blendColorOntoWhite = blendColorOntoWhite;
|
|
164
194
|
exports.clampUnitInterval = clampUnitInterval;
|
|
165
195
|
exports.colorWithOpacity = colorWithOpacity;
|
|
196
|
+
exports.contrastTextColor = contrastTextColor;
|
|
166
197
|
exports.hexToRgbChannels = hexToRgbChannels;
|
|
198
|
+
exports.hexToRgbUnit = hexToRgbUnit;
|
|
167
199
|
exports.hslToRgb = hslToRgb;
|
|
168
200
|
exports.linearToSrgb255 = linearToSrgb255;
|
|
169
201
|
exports.normalizeHexColor = normalizeHexColor;
|
|
170
202
|
exports.parseDrawingFraction = parseDrawingFraction;
|
|
171
203
|
exports.parseDrawingHueDegrees = parseDrawingHueDegrees;
|
|
172
204
|
exports.parseDrawingPercent = parseDrawingPercent;
|
|
205
|
+
exports.parseHex = parseHex;
|
|
173
206
|
exports.parseOoxmlPercent = parseOoxmlPercent;
|
|
174
207
|
exports.rgbToHsl = rgbToHsl;
|
|
175
208
|
exports.scrgbLinearToSrgb8 = scrgbLinearToSrgb8;
|
package/dist/color/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../color/index.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC;AACtC,cAAc,mBAAmB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../color/index.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC;AACtC,cAAc,mBAAmB,CAAC;AAClC,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC"}
|
package/dist/color/index.mjs
CHANGED
|
@@ -158,4 +158,34 @@ function linearToSrgb255(linear) {
|
|
|
158
158
|
return 255 * (c <= 31308e-7 ? c * 12.92 : 1.055 * c ** (1 / 2.4) - 0.055);
|
|
159
159
|
}
|
|
160
160
|
|
|
161
|
-
|
|
161
|
+
// color/contrast.ts
|
|
162
|
+
function parseHex(hex) {
|
|
163
|
+
let h = hex.trim().replace(/^#/u, "");
|
|
164
|
+
if (h.length === 3) {
|
|
165
|
+
h = h.split("").map((c) => c + c).join("");
|
|
166
|
+
}
|
|
167
|
+
if (h.length !== 6 || /[^0-9a-fA-F]/u.test(h)) {
|
|
168
|
+
return [128, 128, 128];
|
|
169
|
+
}
|
|
170
|
+
return [parseInt(h.slice(0, 2), 16), parseInt(h.slice(2, 4), 16), parseInt(h.slice(4, 6), 16)];
|
|
171
|
+
}
|
|
172
|
+
function contrastTextColor(fill) {
|
|
173
|
+
const [r, g, b] = parseHex(fill);
|
|
174
|
+
const lum = (0.299 * r + 0.587 * g + 0.114 * b) / 255;
|
|
175
|
+
return lum > 0.6 ? "#1a1a1a" : "#ffffff";
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// color/unit-rgb.ts
|
|
179
|
+
function hexToRgbUnit(hex) {
|
|
180
|
+
const clean = hex.replace(/^#/u, "");
|
|
181
|
+
const r = Number.parseInt(clean.substring(0, 2), 16) / 255;
|
|
182
|
+
const g = Number.parseInt(clean.substring(2, 4), 16) / 255;
|
|
183
|
+
const b = Number.parseInt(clean.substring(4, 6), 16) / 255;
|
|
184
|
+
return {
|
|
185
|
+
r: Number.isFinite(r) ? r : 0,
|
|
186
|
+
g: Number.isFinite(g) ? g : 0,
|
|
187
|
+
b: Number.isFinite(b) ? b : 0
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
export { blendColorOntoWhite, clampUnitInterval, colorWithOpacity, contrastTextColor, hexToRgbChannels, hexToRgbUnit, hslToRgb, linearToSrgb255, normalizeHexColor, parseDrawingFraction, parseDrawingHueDegrees, parseDrawingPercent, parseHex, parseOoxmlPercent, rgbToHsl, scrgbLinearToSrgb8, srgb255ToLinear, toHex };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Colour-unit conversion helpers shared across the SVG `<filter>` builders in
|
|
3
|
+
* `render/`.
|
|
4
|
+
*
|
|
5
|
+
* `hexToRgbUnit` used to exist as three private, byte-identical copies:
|
|
6
|
+
* `visual-effects.ts` (DAG duotone filter), `image-effects.ts` (image duotone
|
|
7
|
+
* filter), and Angular's `duotone-filter.ts`. This is the one canonical copy;
|
|
8
|
+
* the other two shared modules now import it instead of redefining it.
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Parse a hex colour (`#RRGGBB`/`RRGGBB`, `#` optional) to normalised 0-1 RGB
|
|
12
|
+
* components. Any channel that fails to parse (missing/invalid hex digits,
|
|
13
|
+
* including a short 3-digit `#RGB` shorthand, which this does NOT expand)
|
|
14
|
+
* produces `0`, matching every prior copy's behaviour exactly.
|
|
15
|
+
*/
|
|
16
|
+
export declare function hexToRgbUnit(hex: string): {
|
|
17
|
+
r: number;
|
|
18
|
+
g: number;
|
|
19
|
+
b: number;
|
|
20
|
+
};
|
|
21
|
+
//# sourceMappingURL=unit-rgb.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"unit-rgb.d.ts","sourceRoot":"","sources":["../../color/unit-rgb.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAU7E"}
|
package/dist/docx/embedded.cjs
CHANGED
|
@@ -1149,7 +1149,7 @@ async function applyCoreProperties(zip, next, prior) {
|
|
|
1149
1149
|
await ensureContentTypeOverride(zip, CORE_PATH, CORE_TYPE);
|
|
1150
1150
|
const rels = zip.file("_rels/.rels");
|
|
1151
1151
|
const relsXml = await rels?.async("string") ?? '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"></Relationships>';
|
|
1152
|
-
if (!relsXml.includes(CORE_REL)) {
|
|
1152
|
+
if (!relsXml.includes(`Type="${CORE_REL}"`)) {
|
|
1153
1153
|
const ids = [...relsXml.matchAll(/Id="rId(\d+)"/g)].map((match) => Number(match[1]));
|
|
1154
1154
|
const id = `rId${Math.max(0, ...ids) + 1}`;
|
|
1155
1155
|
zip.file(
|
package/dist/docx/embedded.mjs
CHANGED
|
@@ -1143,7 +1143,7 @@ async function applyCoreProperties(zip, next, prior) {
|
|
|
1143
1143
|
await ensureContentTypeOverride(zip, CORE_PATH, CORE_TYPE);
|
|
1144
1144
|
const rels = zip.file("_rels/.rels");
|
|
1145
1145
|
const relsXml = await rels?.async("string") ?? '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"></Relationships>';
|
|
1146
|
-
if (!relsXml.includes(CORE_REL)) {
|
|
1146
|
+
if (!relsXml.includes(`Type="${CORE_REL}"`)) {
|
|
1147
1147
|
const ids = [...relsXml.matchAll(/Id="rId(\d+)"/g)].map((match) => Number(match[1]));
|
|
1148
1148
|
const id = `rId${Math.max(0, ...ids) + 1}`;
|
|
1149
1149
|
zip.file(
|