@canvas-components/utils 0.2.1 → 0.2.2

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/dist/index.js CHANGED
@@ -265,6 +265,161 @@ function getValueByDataIndex(source, dataIndex) {
265
265
  return current;
266
266
  }
267
267
 
268
+ // src/date/index.ts
269
+ var DATE_TIME_FORMAT_TOKEN = /Y{2,4}|M{1,4}|D{1,2}|d{1,4}|H{1,2}|h{1,2}|m{1,2}|s{1,2}|S{1,3}|A|a/;
270
+ var FORMAT_TOKEN = /\[[^\]]*\]|YYYY|MMMM|MMM|dddd|ddd|SSS|YY|MM|DD|dd|HH|hh|mm|ss|SS|M|D|d|H|h|m|s|S|A|a/g;
271
+ var ZH_WEEKDAYS = [
272
+ "\u661F\u671F\u65E5",
273
+ "\u661F\u671F\u4E00",
274
+ "\u661F\u671F\u4E8C",
275
+ "\u661F\u671F\u4E09",
276
+ "\u661F\u671F\u56DB",
277
+ "\u661F\u671F\u4E94",
278
+ "\u661F\u671F\u516D"
279
+ ];
280
+ var ZH_WEEKDAYS_SHORT = [
281
+ "\u5468\u65E5",
282
+ "\u5468\u4E00",
283
+ "\u5468\u4E8C",
284
+ "\u5468\u4E09",
285
+ "\u5468\u56DB",
286
+ "\u5468\u4E94",
287
+ "\u5468\u516D"
288
+ ];
289
+ var EN_WEEKDAYS = [
290
+ "Sunday",
291
+ "Monday",
292
+ "Tuesday",
293
+ "Wednesday",
294
+ "Thursday",
295
+ "Friday",
296
+ "Saturday"
297
+ ];
298
+ var EN_MONTHS = [
299
+ "January",
300
+ "February",
301
+ "March",
302
+ "April",
303
+ "May",
304
+ "June",
305
+ "July",
306
+ "August",
307
+ "September",
308
+ "October",
309
+ "November",
310
+ "December"
311
+ ];
312
+ function resolveDateValue(value) {
313
+ if (value instanceof Date) {
314
+ return Number.isNaN(value.getTime()) ? null : value;
315
+ }
316
+ if (typeof value !== "string" && typeof value !== "number") {
317
+ return null;
318
+ }
319
+ if (typeof value === "string") {
320
+ const localDate = resolveLocalDateString(value);
321
+ if (localDate) {
322
+ return localDate;
323
+ }
324
+ }
325
+ const resolved = new Date(value);
326
+ return Number.isNaN(resolved.getTime()) ? null : resolved;
327
+ }
328
+ function isDateTimeFormatPattern(pattern) {
329
+ return DATE_TIME_FORMAT_TOKEN.test(pattern.replace(/\[[^\]]*\]/g, ""));
330
+ }
331
+ function formatDateTimeValue(value, pattern, locale = "zh-cn") {
332
+ const date = resolveDateValue(value);
333
+ const normalizedPattern = pattern.trim();
334
+ if (!date || !normalizedPattern) {
335
+ return null;
336
+ }
337
+ const year = date.getFullYear();
338
+ const monthIndex = date.getMonth();
339
+ const month = monthIndex + 1;
340
+ const day = date.getDate();
341
+ const weekdayIndex = date.getDay();
342
+ const hour = date.getHours();
343
+ const hour12 = hour % 12 || 12;
344
+ const minute = date.getMinutes();
345
+ const second = date.getSeconds();
346
+ const millisecond = date.getMilliseconds();
347
+ const chinese = locale.toLowerCase().startsWith("zh");
348
+ const marker = hour >= 12 ? chinese ? "\u4E0B\u5348" : "PM" : chinese ? "\u4E0A\u5348" : "AM";
349
+ const weekday = chinese ? ZH_WEEKDAYS[weekdayIndex] ?? "" : EN_WEEKDAYS[weekdayIndex] ?? "";
350
+ const weekdayShort = chinese ? ZH_WEEKDAYS_SHORT[weekdayIndex] ?? "" : weekday.slice(0, 3);
351
+ const monthName = chinese ? `${month}\u6708` : EN_MONTHS[monthIndex] ?? "";
352
+ const values = {
353
+ YYYY: String(year).padStart(4, "0"),
354
+ YY: String(year).slice(-2),
355
+ M: String(month),
356
+ MM: padNumber(month),
357
+ MMM: chinese ? monthName : monthName.slice(0, 3),
358
+ MMMM: monthName,
359
+ D: String(day),
360
+ DD: padNumber(day),
361
+ d: String(weekdayIndex),
362
+ dd: chinese ? weekdayShort.slice(-1) : weekday.slice(0, 2),
363
+ ddd: weekdayShort,
364
+ dddd: weekday,
365
+ H: String(hour),
366
+ HH: padNumber(hour),
367
+ h: String(hour12),
368
+ hh: padNumber(hour12),
369
+ m: String(minute),
370
+ mm: padNumber(minute),
371
+ s: String(second),
372
+ ss: padNumber(second),
373
+ S: String(Math.floor(millisecond / 100)),
374
+ SS: String(Math.floor(millisecond / 10)).padStart(2, "0"),
375
+ SSS: String(millisecond).padStart(3, "0"),
376
+ A: marker,
377
+ a: marker.toLowerCase()
378
+ };
379
+ return normalizedPattern.replace(
380
+ FORMAT_TOKEN,
381
+ (token) => token.startsWith("[") && token.endsWith("]") ? token.slice(1, -1) : values[token] ?? token
382
+ );
383
+ }
384
+ function padNumber(value) {
385
+ return String(value).padStart(2, "0");
386
+ }
387
+ function resolveLocalDateString(value) {
388
+ const match = value.trim().match(
389
+ /^(\d{4})[-/](\d{1,2})[-/](\d{1,2})(?:[ T](\d{1,2}):?(\d{2})?(?::?(\d{2}))?(?:\.(\d{1,3}))?)?$/
390
+ );
391
+ if (!match) {
392
+ return null;
393
+ }
394
+ const [
395
+ ,
396
+ yearText,
397
+ monthText,
398
+ dayText,
399
+ hourText,
400
+ minuteText,
401
+ secondText,
402
+ millisecondText
403
+ ] = match;
404
+ const year = Number(yearText);
405
+ const monthIndex = Number(monthText) - 1;
406
+ const day = Number(dayText);
407
+ const hour = Number(hourText ?? 0);
408
+ const minute = Number(minuteText ?? 0);
409
+ const second = Number(secondText ?? 0);
410
+ const millisecond = Number((millisecondText ?? "0").padEnd(3, "0"));
411
+ const resolved = new Date(
412
+ year,
413
+ monthIndex,
414
+ day,
415
+ hour,
416
+ minute,
417
+ second,
418
+ millisecond
419
+ );
420
+ return resolved.getFullYear() === year && resolved.getMonth() === monthIndex && resolved.getDate() === day && resolved.getHours() === hour && resolved.getMinutes() === minute && resolved.getSeconds() === second ? resolved : null;
421
+ }
422
+
268
423
  // src/geometry/index.ts
269
424
  function clamp(value, minimum, maximum) {
270
425
  return Math.min(Math.max(value, minimum), maximum);
@@ -273,6 +428,387 @@ function isPointInRect(x, y, rect) {
273
428
  return x >= rect.x && x <= rect.x + rect.width && y >= rect.y && y <= rect.y + rect.height;
274
429
  }
275
430
 
276
- export { buildCsvContent, buildTxtContent, clamp, copyJson, copyRows, copyText, copyTextSync, downloadJsonFile, exportTableToCsv, exportTableToTxt, exportTableToXlsx, formatRowsForClipboard, getValueByDataIndex, isPointInRect, isSameDataIndex, mapRowsToExportRecords, serializeCsvRows, stringifyDataIndex };
431
+ // src/number/precise.ts
432
+ function addPreciseNumbers(left, right) {
433
+ const leftParts = parseDecimal(left);
434
+ const rightParts = parseDecimal(right);
435
+ if (!leftParts || !rightParts) return null;
436
+ return formatDecimal(addParts(leftParts, rightParts));
437
+ }
438
+ function sumPreciseNumbers(values) {
439
+ let result = { coefficient: 0n, scale: 0 };
440
+ let count = 0;
441
+ for (const value of values) {
442
+ const parts = parseDecimal(value);
443
+ if (!parts) continue;
444
+ result = addParts(result, parts);
445
+ count += 1;
446
+ }
447
+ return count === 0 ? null : formatDecimal(result);
448
+ }
449
+ function comparePreciseNumbers(left, right) {
450
+ const leftParts = parseDecimal(left);
451
+ const rightParts = parseDecimal(right);
452
+ if (!leftParts || !rightParts) return null;
453
+ const scale = Math.max(leftParts.scale, rightParts.scale);
454
+ const leftValue = leftParts.coefficient * 10n ** BigInt(scale - leftParts.scale);
455
+ const rightValue = rightParts.coefficient * 10n ** BigInt(scale - rightParts.scale);
456
+ return leftValue < rightValue ? -1 : leftValue > rightValue ? 1 : 0;
457
+ }
458
+ function dividePreciseNumber(value, divisor, precision = 20) {
459
+ const valueParts = parseDecimal(value);
460
+ const divisorParts = parseDecimal(divisor);
461
+ if (!valueParts || !divisorParts || divisorParts.coefficient === 0n)
462
+ return null;
463
+ const places = normalizePrecision(precision);
464
+ const scale = places + divisorParts.scale - valueParts.scale;
465
+ const factor = 10n ** BigInt(Math.max(scale, 0));
466
+ const numerator = valueParts.coefficient * factor;
467
+ const denominator = divisorParts.coefficient;
468
+ const quotient = numerator / denominator;
469
+ const remainder = numerator % denominator;
470
+ const rounded = remainder === 0n ? quotient : quotient + (numerator < 0n === denominator < 0n ? 1n : -1n) * (abs(remainder) * 2n >= abs(denominator) ? 1n : 0n);
471
+ return formatDecimal({ coefficient: rounded, scale: Math.max(places, 0) });
472
+ }
473
+ function roundPreciseNumber(value, precision, mode = "round") {
474
+ const parts = parseDecimal(value);
475
+ if (!parts) return null;
476
+ const places = normalizePrecision(precision);
477
+ if (parts.scale <= places)
478
+ return formatDecimal(
479
+ {
480
+ ...parts,
481
+ coefficient: parts.coefficient * 10n ** BigInt(places - parts.scale)
482
+ },
483
+ places
484
+ );
485
+ const factor = 10n ** BigInt(parts.scale - places);
486
+ let quotient = parts.coefficient / factor;
487
+ const remainder = parts.coefficient % factor;
488
+ if (remainder !== 0n) {
489
+ const isNegative = parts.coefficient < 0n;
490
+ const direction = isNegative ? -1n : 1n;
491
+ if (mode === "ceil" && !isNegative || mode === "floor" && isNegative || mode === "round" && abs(remainder) * 2n >= factor) {
492
+ quotient += direction;
493
+ }
494
+ }
495
+ return formatDecimal({ coefficient: quotient, scale: places }, places);
496
+ }
497
+ function formatPreciseNumber(value, precision, preserveTrailingZeros = false) {
498
+ const parts = parseDecimal(value);
499
+ if (!parts) return null;
500
+ return precision == null ? formatDecimal(parts, preserveTrailingZeros ? parts.scale : 0) : roundPreciseNumber(value, precision);
501
+ }
502
+ function parseDecimal(value) {
503
+ if (typeof value === "number") {
504
+ if (!Number.isFinite(value)) return null;
505
+ value = String(value);
506
+ } else if (typeof value === "bigint") {
507
+ return { coefficient: value, scale: 0 };
508
+ }
509
+ const match = value.trim().match(/^([+-]?)(\d+)(?:\.(\d*))?(?:e([+-]?\d+))?$/i);
510
+ if (!match) return null;
511
+ const fraction = match[3] ?? "";
512
+ const exponent = Number(match[4] ?? 0);
513
+ if (!Number.isSafeInteger(exponent)) return null;
514
+ const scale = fraction.length - exponent;
515
+ const coefficient = BigInt(
516
+ `${match[1] === "-" ? "-" : ""}${match[2]}${fraction}`
517
+ );
518
+ return scale >= 0 ? { coefficient, scale } : { coefficient: coefficient * 10n ** BigInt(-scale), scale: 0 };
519
+ }
520
+ function addParts(left, right) {
521
+ const scale = Math.max(left.scale, right.scale);
522
+ return {
523
+ coefficient: left.coefficient * 10n ** BigInt(scale - left.scale) + right.coefficient * 10n ** BigInt(scale - right.scale),
524
+ scale
525
+ };
526
+ }
527
+ function formatDecimal(parts, minimumScale = 0) {
528
+ const negative = parts.coefficient < 0n;
529
+ const digits = abs(parts.coefficient).toString().padStart(parts.scale + 1, "0");
530
+ const scale = Math.max(parts.scale, minimumScale);
531
+ const padded = digits.padStart(scale + 1, "0");
532
+ const integer = padded.slice(0, -scale || void 0) || "0";
533
+ const fraction = scale > 0 ? padded.slice(-scale).padEnd(scale, "0") : "";
534
+ const displayFraction = minimumScale > 0 ? fraction : fraction.replace(/0+$/, "");
535
+ return `${negative ? "-" : ""}${integer}${displayFraction ? `.${displayFraction}` : ""}`;
536
+ }
537
+ function normalizePrecision(value) {
538
+ return Math.min(
539
+ 100,
540
+ Math.max(0, Math.trunc(Number.isFinite(value) ? value : 20))
541
+ );
542
+ }
543
+ function abs(value) {
544
+ return value < 0n ? -value : value;
545
+ }
546
+
547
+ // src/number/index.ts
548
+ var COMMON_CHINESE_DIGITS = [
549
+ "\u96F6",
550
+ "\u4E00",
551
+ "\u4E8C",
552
+ "\u4E09",
553
+ "\u56DB",
554
+ "\u4E94",
555
+ "\u516D",
556
+ "\u4E03",
557
+ "\u516B",
558
+ "\u4E5D"
559
+ ];
560
+ var FINANCIAL_CHINESE_DIGITS = [
561
+ "\u96F6",
562
+ "\u58F9",
563
+ "\u8D30",
564
+ "\u53C1",
565
+ "\u8086",
566
+ "\u4F0D",
567
+ "\u9646",
568
+ "\u67D2",
569
+ "\u634C",
570
+ "\u7396"
571
+ ];
572
+ var COMMON_SECTION_UNITS = ["", "\u5341", "\u767E", "\u5343"];
573
+ var FINANCIAL_SECTION_UNITS = ["", "\u62FE", "\u4F70", "\u4EDF"];
574
+ var LARGE_CHINESE_UNITS = ["", "\u4E07", "\u4EBF", "\u5146", "\u4EAC"];
575
+ var CHINESE_DIGIT_VALUES = {
576
+ \u96F6: 0,
577
+ "\u3007": 0,
578
+ \u4E00: 1,
579
+ \u58F9: 1,
580
+ \u4E8C: 2,
581
+ \u8D30: 2,
582
+ \u8CB3: 2,
583
+ \u4E24: 2,
584
+ \u5169: 2,
585
+ \u4E09: 3,
586
+ \u53C1: 3,
587
+ \u53C3: 3,
588
+ \u56DB: 4,
589
+ \u8086: 4,
590
+ \u4E94: 5,
591
+ \u4F0D: 5,
592
+ \u516D: 6,
593
+ \u9646: 6,
594
+ \u9678: 6,
595
+ \u4E03: 7,
596
+ \u67D2: 7,
597
+ \u516B: 8,
598
+ \u634C: 8,
599
+ \u4E5D: 9,
600
+ \u7396: 9
601
+ };
602
+ var CHINESE_SMALL_UNIT_VALUES = {
603
+ \u5341: 10,
604
+ \u62FE: 10,
605
+ \u767E: 100,
606
+ \u4F70: 100,
607
+ \u5343: 1e3,
608
+ \u4EDF: 1e3
609
+ };
610
+ var CHINESE_LARGE_UNIT_VALUES = {
611
+ \u4E07: 1e4,
612
+ \u842C: 1e4,
613
+ \u4EBF: 1e8,
614
+ \u5104: 1e8,
615
+ \u5146: 1e12
616
+ };
617
+ function parseNumberValue(value) {
618
+ if (typeof value === "number") return Number.isFinite(value) ? value : null;
619
+ if (typeof value !== "string") return null;
620
+ const normalized = value.trim().replace(/,/g, "");
621
+ if (!normalized) return null;
622
+ const numericValue = Number(normalized);
623
+ return Number.isFinite(numericValue) ? numericValue : null;
624
+ }
625
+ function normalizeDecimalPlaces(decimalPlaces, fallback = 2) {
626
+ if (typeof decimalPlaces !== "number" || !Number.isFinite(decimalPlaces)) {
627
+ return fallback;
628
+ }
629
+ return Math.min(20, Math.max(Math.trunc(decimalPlaces), 0));
630
+ }
631
+ function formatNumberValue(value, options = {}) {
632
+ if (value == null || value === "") return "";
633
+ const numericValue = parseNumberValue(value);
634
+ if (numericValue == null) return String(value);
635
+ const separator = resolveThousandsSeparator(options.thousandsSeparator);
636
+ const decimalPlaces = options.decimalPlaces === "auto" ? void 0 : normalizeDecimalPlaces(options.decimalPlaces);
637
+ const absoluteText = decimalPlaces == null ? String(Math.abs(numericValue)) : Math.abs(numericValue).toFixed(decimalPlaces);
638
+ const [integerText = "0", decimalText] = absoluteText.split(".");
639
+ const formattedInteger = separator ? integerText.replace(/\B(?=(\d{3})+(?!\d))/g, separator) : integerText;
640
+ const sign = numericValue < 0 ? "-" : "";
641
+ return `${sign}${options.symbol ?? ""}${formattedInteger}${decimalText ? `.${decimalText}` : ""}`;
642
+ }
643
+ function formatPercentValue(value, decimalPlaces = 2) {
644
+ const numericValue = parseNumberValue(value);
645
+ if (numericValue == null) return String(value ?? "");
646
+ return `${(numericValue * 100).toFixed(normalizeDecimalPlaces(decimalPlaces))}%`;
647
+ }
648
+ function formatScientificValue(value, decimalPlaces = 2) {
649
+ const numericValue = parseNumberValue(value);
650
+ if (numericValue == null) return String(value ?? "");
651
+ const [mantissa, exponentText] = numericValue.toExponential(normalizeDecimalPlaces(decimalPlaces)).split("e");
652
+ const exponent = Number(exponentText ?? 0);
653
+ return `${mantissa}E${exponent >= 0 ? "+" : "-"}${String(Math.abs(exponent)).padStart(3, "0")}`;
654
+ }
655
+ function formatCustomNumberPattern(value, pattern) {
656
+ if (pattern.includes("@") || pattern.includes("\u901A\u7528\u683C\u5F0F")) {
657
+ return String(value ?? "");
658
+ }
659
+ const literalOnly = pattern.match(/^"([^"]*)"$/);
660
+ if (literalOnly) return literalOnly[1] ?? "";
661
+ const numericValue = parseNumberValue(value);
662
+ if (numericValue == null) return String(value ?? "");
663
+ const percent = pattern.includes("%");
664
+ const tenThousands = pattern.includes("\u4E07");
665
+ const decimalPlaces = pattern.match(/\.(0+)/)?.[1]?.length ?? 0;
666
+ const scaled = numericValue * (percent ? 100 : 1) / (tenThousands ? 1e4 : 1);
667
+ const symbol = pattern.includes("\xA5") ? "\xA5" : pattern.includes("$") ? "$" : "";
668
+ if (/e\+/i.test(pattern)) return formatScientificValue(scaled, decimalPlaces);
669
+ const text = formatNumberValue(scaled, {
670
+ decimalPlaces,
671
+ thousandsSeparator: pattern.includes(",") && !tenThousands,
672
+ symbol
673
+ });
674
+ return `${text}${tenThousands ? "\u4E07" : ""}${percent ? "%" : ""}`;
675
+ }
676
+ function formatChineseNumber(value, style = "financial") {
677
+ const numericValue = parseNumberValue(value) ?? (typeof value === "string" ? parseChineseNumber(value) : null);
678
+ if (numericValue == null || !Number.isFinite(numericValue)) return null;
679
+ const negative = numericValue < 0;
680
+ const absoluteValue = Math.abs(numericValue);
681
+ const [integerText, decimalText = ""] = toPlainNumberText(absoluteValue).split(".");
682
+ const digits = style === "financial" ? FINANCIAL_CHINESE_DIGITS : COMMON_CHINESE_DIGITS;
683
+ const sectionUnits = style === "financial" ? FINANCIAL_SECTION_UNITS : COMMON_SECTION_UNITS;
684
+ const integerResult = formatChineseInteger(
685
+ integerText ?? "0",
686
+ digits,
687
+ sectionUnits
688
+ );
689
+ const decimalResult = decimalText ? `\u70B9${Array.from(decimalText, (digit) => digits[Number(digit)] ?? "").join("")}` : "";
690
+ return `${negative ? "\u8D1F" : ""}${integerResult}${decimalResult}`;
691
+ }
692
+ function parseChineseNumber(value) {
693
+ if (typeof value === "number") return Number.isFinite(value) ? value : null;
694
+ if (typeof value !== "string") return null;
695
+ let source = value.trim().replace(/[\s,,]/g, "");
696
+ if (!source) return null;
697
+ const negative = source.startsWith("\u8D1F") || source.startsWith("-");
698
+ if (negative) source = source.slice(1);
699
+ const [integerSource = "", decimalSource] = source.split(/[点\.]/, 2);
700
+ if (!integerSource) return null;
701
+ const integerValue = parseChineseInteger(integerSource);
702
+ if (integerValue == null) return null;
703
+ let decimalValue = 0;
704
+ if (decimalSource) {
705
+ let scale = 0.1;
706
+ for (const character of decimalSource) {
707
+ const digit = resolveChineseDigit(character);
708
+ if (digit == null) return null;
709
+ decimalValue += digit * scale;
710
+ scale /= 10;
711
+ }
712
+ }
713
+ const result = integerValue + decimalValue;
714
+ return negative ? -result : result;
715
+ }
716
+ function formatChineseInteger(integerText, digits, sectionUnits) {
717
+ const normalized = integerText.replace(/^0+(?=\d)/, "");
718
+ if (normalized === "0") return digits[0] ?? "\u96F6";
719
+ const sections = [];
720
+ for (let end = normalized.length; end > 0; end -= 4) {
721
+ sections.push(Number(normalized.slice(Math.max(0, end - 4), end)));
722
+ }
723
+ let result = "";
724
+ let pendingZero = false;
725
+ for (let index = sections.length - 1; index >= 0; index -= 1) {
726
+ const section = sections[index] ?? 0;
727
+ if (section === 0) {
728
+ if (result) pendingZero = true;
729
+ continue;
730
+ }
731
+ if (result && (pendingZero || section < 1e3)) result += digits[0] ?? "\u96F6";
732
+ result += formatChineseSection(section, digits, sectionUnits);
733
+ result += LARGE_CHINESE_UNITS[index] ?? "";
734
+ pendingZero = false;
735
+ }
736
+ return digits === COMMON_CHINESE_DIGITS && result.startsWith("\u4E00\u5341") ? result.slice(1) : result;
737
+ }
738
+ function formatChineseSection(section, digits, sectionUnits) {
739
+ let result = "";
740
+ let pendingZero = false;
741
+ for (let position = 3; position >= 0; position -= 1) {
742
+ const unitValue = 10 ** position;
743
+ const digit = Math.floor(section / unitValue) % 10;
744
+ if (digit === 0) {
745
+ if (result && section % unitValue !== 0) pendingZero = true;
746
+ continue;
747
+ }
748
+ if (pendingZero) result += digits[0] ?? "\u96F6";
749
+ result += `${digits[digit] ?? ""}${sectionUnits[position] ?? ""}`;
750
+ pendingZero = false;
751
+ }
752
+ return result;
753
+ }
754
+ function parseChineseInteger(source) {
755
+ const hasUnit = Array.from(source).some(
756
+ (character) => character in CHINESE_SMALL_UNIT_VALUES || character in CHINESE_LARGE_UNIT_VALUES
757
+ );
758
+ if (!hasUnit) {
759
+ let text = "";
760
+ for (const character of source) {
761
+ const digit2 = resolveChineseDigit(character);
762
+ if (digit2 == null) return null;
763
+ text += String(digit2);
764
+ }
765
+ return text ? Number(text) : null;
766
+ }
767
+ let total = 0;
768
+ let section = 0;
769
+ let digit = null;
770
+ for (const character of source) {
771
+ const digitValue = resolveChineseDigit(character);
772
+ if (digitValue != null) {
773
+ digit = digitValue;
774
+ continue;
775
+ }
776
+ const smallUnit = CHINESE_SMALL_UNIT_VALUES[character];
777
+ if (smallUnit) {
778
+ section += (digit ?? 1) * smallUnit;
779
+ digit = null;
780
+ continue;
781
+ }
782
+ const largeUnit = CHINESE_LARGE_UNIT_VALUES[character];
783
+ if (largeUnit) {
784
+ section += digit ?? 0;
785
+ total += section * largeUnit;
786
+ section = 0;
787
+ digit = null;
788
+ continue;
789
+ }
790
+ return null;
791
+ }
792
+ return total + section + (digit ?? 0);
793
+ }
794
+ function resolveChineseDigit(character) {
795
+ if (/\d/.test(character)) return Number(character);
796
+ return CHINESE_DIGIT_VALUES[character] ?? null;
797
+ }
798
+ function toPlainNumberText(value) {
799
+ const source = String(value);
800
+ if (!/[eE]/.test(source)) return source;
801
+ return value.toLocaleString("en-US", {
802
+ useGrouping: false,
803
+ maximumFractionDigits: 20
804
+ });
805
+ }
806
+ function resolveThousandsSeparator(separator) {
807
+ if (separator == null || separator === false) return "";
808
+ if (typeof separator === "string") return separator;
809
+ return ",";
810
+ }
811
+
812
+ export { addPreciseNumbers, buildCsvContent, buildTxtContent, clamp, comparePreciseNumbers, copyJson, copyRows, copyText, copyTextSync, dividePreciseNumber, downloadJsonFile, exportTableToCsv, exportTableToTxt, exportTableToXlsx, formatChineseNumber, formatCustomNumberPattern, formatDateTimeValue, formatNumberValue, formatPercentValue, formatPreciseNumber, formatRowsForClipboard, formatScientificValue, getValueByDataIndex, isDateTimeFormatPattern, isPointInRect, isSameDataIndex, mapRowsToExportRecords, normalizeDecimalPlaces, parseChineseNumber, parseNumberValue, resolveDateValue, roundPreciseNumber, serializeCsvRows, stringifyDataIndex, sumPreciseNumbers };
277
813
  //# sourceMappingURL=index.js.map
278
814
  //# sourceMappingURL=index.js.map