@constela/core 0.18.4 → 0.19.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/dist/index.d.ts +18 -62
- package/dist/index.js +768 -50
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -2439,78 +2439,34 @@ declare function isSuspenseBoundary(value: unknown): value is SuspenseBoundary;
|
|
|
2439
2439
|
declare function isStreamChunk(value: unknown): value is StreamChunk;
|
|
2440
2440
|
|
|
2441
2441
|
/**
|
|
2442
|
-
*
|
|
2442
|
+
* Global Helper Functions
|
|
2443
2443
|
*
|
|
2444
|
-
*
|
|
2445
|
-
*
|
|
2446
|
-
* for chart rendering.
|
|
2447
|
-
*/
|
|
2448
|
-
/**
|
|
2449
|
-
* Normalizes a value to 0-1 range
|
|
2450
|
-
*
|
|
2451
|
-
* @param value - The value to normalize
|
|
2452
|
-
* @param min - The minimum value of the range
|
|
2453
|
-
* @param max - The maximum value of the range
|
|
2454
|
-
* @returns Normalized value (0-1), or undefined for invalid input
|
|
2455
|
-
*/
|
|
2456
|
-
declare function normalizeValue(value: unknown, min: unknown, max: unknown): number | undefined;
|
|
2457
|
-
/**
|
|
2458
|
-
* Scales a value from one range to another
|
|
2444
|
+
* Pure helper functions shared between runtime (client) and server (SSR).
|
|
2445
|
+
* These functions are callable as global helpers in Constela expressions.
|
|
2459
2446
|
*
|
|
2460
|
-
*
|
|
2461
|
-
*
|
|
2462
|
-
* @param domainMax - Maximum of source range
|
|
2463
|
-
* @param rangeMin - Minimum of target range
|
|
2464
|
-
* @param rangeMax - Maximum of target range
|
|
2465
|
-
* @returns Scaled value, or undefined for invalid input
|
|
2447
|
+
* All functions are pure (no DOM, no browser APIs).
|
|
2448
|
+
* They use only: Math, Date, Intl.DateTimeFormat, Array methods.
|
|
2466
2449
|
*/
|
|
2467
|
-
declare function scaleValue(value: unknown, domainMin: unknown, domainMax: unknown, rangeMin: unknown, rangeMax: unknown): number | undefined;
|
|
2468
2450
|
/**
|
|
2469
|
-
*
|
|
2470
|
-
*
|
|
2471
|
-
* @param data - Array of objects
|
|
2472
|
-
* @param valueKey - Key to use for values
|
|
2473
|
-
* @returns Object with min and max, or undefined for invalid input
|
|
2451
|
+
* CalendarDay type - represents a day in the calendar grid
|
|
2474
2452
|
*/
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
*
|
|
2482
|
-
* @param data - Array of data objects
|
|
2483
|
-
* @param valueKey - Key to extract values from data
|
|
2484
|
-
* @param width - Chart width
|
|
2485
|
-
* @param height - Chart height
|
|
2486
|
-
* @param padding - Padding around chart area (default: 40)
|
|
2487
|
-
* @returns Array of {x, y} points scaled to fit the chart area
|
|
2488
|
-
*/
|
|
2489
|
-
declare function getLinePoints(data: unknown, valueKey: unknown, width: unknown, height: unknown, padding?: unknown): Array<{
|
|
2490
|
-
x: number;
|
|
2491
|
-
y: number;
|
|
2492
|
-
}> | undefined;
|
|
2493
|
-
/**
|
|
2494
|
-
* Generates SVG path string for line chart
|
|
2495
|
-
*
|
|
2496
|
-
* @param points - Array of {x, y} points
|
|
2497
|
-
* @param curved - Whether to use curved lines (Catmull-Rom spline)
|
|
2498
|
-
* @returns SVG path string, or undefined for invalid input
|
|
2499
|
-
*/
|
|
2500
|
-
declare function getLinePath(points: unknown, curved?: unknown): string | undefined;
|
|
2453
|
+
interface CalendarDay {
|
|
2454
|
+
readonly date: number;
|
|
2455
|
+
readonly month: number;
|
|
2456
|
+
readonly year: number;
|
|
2457
|
+
readonly isCurrentMonth: boolean;
|
|
2458
|
+
}
|
|
2501
2459
|
/**
|
|
2502
|
-
*
|
|
2503
|
-
* This is used by both runtime evaluator and SSR renderer.
|
|
2460
|
+
* Whitelist of global helper functions that can be called with target: null
|
|
2504
2461
|
*/
|
|
2505
|
-
declare const
|
|
2462
|
+
declare const GLOBAL_FUNCTIONS: Record<string, (...args: unknown[]) => unknown>;
|
|
2506
2463
|
/**
|
|
2507
|
-
* Calls a
|
|
2508
|
-
* Returns undefined if the function is not found.
|
|
2464
|
+
* Calls a global helper function by name
|
|
2509
2465
|
*
|
|
2510
2466
|
* @param method - The function name to call
|
|
2511
2467
|
* @param args - Arguments to pass to the function
|
|
2512
|
-
* @returns The function result, or undefined if not found
|
|
2468
|
+
* @returns The function result, or undefined if the function is not found
|
|
2513
2469
|
*/
|
|
2514
|
-
declare function
|
|
2470
|
+
declare function callGlobalFunction(method: string, args: unknown[]): unknown;
|
|
2515
2471
|
|
|
2516
|
-
export { AI_OUTPUT_TYPES, AI_PROVIDER_TYPES, type ActionDefinition, type ActionStep, type AiDataSource, type AiOutputType, type AiProviderType, type ArrayExpr, BINARY_OPERATORS, type BinExpr, type BinaryOperator, type BindStep, type BooleanField,
|
|
2472
|
+
export { AI_OUTPUT_TYPES, AI_PROVIDER_TYPES, type ActionDefinition, type ActionStep, type AiDataSource, type AiOutputType, type AiProviderType, type ArrayExpr, BINARY_OPERATORS, type BinExpr, type BinaryOperator, type BindStep, type BooleanField, CLIPBOARD_OPERATIONS, COLOR_SCHEMES, type CalendarDay, type CallExpr, type CallStep, type ClearTimerStep, type ClipboardOperation, type ClipboardStep, type CloseStep, type CodeNode, type ColorScheme, type ComponentDef, type ComponentNode, type ComponentsRef, type CompoundVariant, type ConcatExpr, type CondExpr, type ConfirmStep, type ConstelaAst, ConstelaError, type ConstelaProgram, type CookieInitialExpr, DATA_SOURCE_TYPES, DATA_TRANSFORMS, type DataExpr, type DataSource, type DataSourceType, type DataTransform, type DelayStep, type DisposeStep, type DomStep, type EachNode, type ElementNode, type ErrorBoundaryNode, type ErrorCode, type ErrorOptions, type EventHandler, type EventHandlerOptions, type Expression, FOCUS_OPERATIONS, type FetchStep, type FlushStrategy, type FocusOperation, type FocusStep, GLOBAL_FUNCTIONS, type GenerateStep, type GetExpr, HTTP_METHODS, type HttpMethod, ISLAND_STRATEGIES, type IfNode, type IfStep, type ImportExpr, type ImportStep, type IndexExpr, type IntervalStep, type IslandNode, type IslandStrategy, type IslandStrategyOptions, type LambdaExpr, type LayoutProgram, type LifecycleHooks, type ListField, type LitExpr, type LocalActionDefinition, type LocalActionStep, type LocalExpr, type MarkdownNode, NAVIGATE_TARGETS, type NavigateStep, type NavigateTarget, type NotExpr, type NumberField, type ObjExpr, type ObjectField, type OptimisticStep, PARAM_TYPES, type ParamDef, type ParamExpr, type ParamType, type PortalNode, type Program, type ReconnectConfig, type RefExpr, type RejectStep, type RouteDefinition, type RouteExpr, type SSECloseStep, type SSEConnectStep, STORAGE_OPERATIONS, STORAGE_TYPES, type SendStep, type SetPathStep, type SetStep, type SlotNode, type StateExpr, type StateField, type StaticPathsDefinition, type StorageOperation, type StorageStep, type StorageType, type StreamChunk, type StreamChunkType, type StreamingRenderOptions, type StringField, type StyleExpr, type StylePreset, type SubscribeStep, type SuspenseBoundary, type SuspenseNode, type TextNode, type ThemeColors, type ThemeConfig, type ThemeFonts, UPDATE_OPERATIONS, type UnbindStep, type UpdateOperation, type UpdateStep, VALIDITY_PROPERTIES, type ValidationFailure, type ValidationResult, type ValidationSuccess, type ValidityExpr, type ValidityProperty, type VarExpr, type ViewNode, astSchema, callGlobalFunction, createClipboardWriteMissingValueError, createComponentCycleError, createComponentNotFoundError, createComponentPropMissingError, createComponentPropTypeError, createCondElseRequiredError, createDataNotDefinedError, createDuplicateActionError, createDuplicateDefaultSlotError, createDuplicateIslandIdError, createDuplicateSlotNameError, createImportsNotDefinedError, createInvalidClipboardOperationError, createInvalidDataSourceError, createInvalidNavigateTargetError, createInvalidSlotNameError, createInvalidStorageOperationError, createInvalidStorageTypeError, createLayoutMissingSlotError, createLayoutNotFoundError, createLocalActionInvalidStepError, createOperationInvalidForTypeError, createOperationMissingFieldError, createOperationUnknownError, createRouteNotDefinedError, createSchemaError, createSlotInLoopError, createStorageSetMissingValueError, createUndefinedActionError, createUndefinedDataError, createUndefinedDataSourceError, createUndefinedImportError, createUndefinedLocalStateError, createUndefinedParamError, createUndefinedRefError, createUndefinedRouteParamError, createUndefinedStateError, createUndefinedStyleError, createUndefinedVarError, createUndefinedVariantError, createUnsupportedVersionError, findSimilarNames, isActionStep, isAiDataSource, isArrayExpr, isBinExpr, isBooleanField, isCallStep, isClipboardStep, isCodeNode, isColorScheme, isComponentNode, isConcatExpr, isCondExpr, isConstelaError, isCookieInitialExpr, isDataExpr, isDataSource, isDisposeStep, isEachNode, isElementNode, isErrorBoundaryNode, isEventHandler, isExpression, isFetchStep, isFocusStep, isGenerateStep, isGetExpr, isIfNode, isImportExpr, isImportStep, isIslandNode, isIslandStrategy, isIslandStrategyOptions, isLayoutProgram, isLifecycleHooks, isListField, isLitExpr, isLocalActionDefinition, isLocalActionStep, isMarkdownNode, isNamedSlotNode, isNavigateStep, isNotExpr, isNumberField, isObjectField, isParamExpr, isPortalNode, isRefExpr, isRouteDefinition, isRouteExpr, isSetPathStep, isSetStep, isSlotNode, isStateExpr, isStateField, isStaticPathsDefinition, isStorageStep, isStreamChunk, isStreamingRenderOptions, isStringField, isStyleExpr, isSubscribeStep, isSuspenseBoundary, isSuspenseNode, isTextNode, isThemeColors, isThemeConfig, isThemeFonts, isUpdateStep, isValidityExpr, isVarExpr, isViewNode, validateAst };
|
package/dist/index.js
CHANGED
|
@@ -2655,7 +2655,273 @@ function isStreamChunk(value) {
|
|
|
2655
2655
|
return true;
|
|
2656
2656
|
}
|
|
2657
2657
|
|
|
2658
|
-
// src/helpers/
|
|
2658
|
+
// src/helpers/global-functions.ts
|
|
2659
|
+
function getCalendarDays(year, month) {
|
|
2660
|
+
if (typeof year !== "number" || typeof month !== "number") {
|
|
2661
|
+
return void 0;
|
|
2662
|
+
}
|
|
2663
|
+
if (month < 0 || month > 11) {
|
|
2664
|
+
return void 0;
|
|
2665
|
+
}
|
|
2666
|
+
const days = [];
|
|
2667
|
+
const firstDayOfMonth = new Date(year, month, 1);
|
|
2668
|
+
const dayOfWeek = firstDayOfMonth.getDay();
|
|
2669
|
+
const lastDayOfMonth = new Date(year, month + 1, 0);
|
|
2670
|
+
const daysInMonth = lastDayOfMonth.getDate();
|
|
2671
|
+
const prevMonthDays = dayOfWeek;
|
|
2672
|
+
const prevMonthLastDay = new Date(year, month, 0);
|
|
2673
|
+
const prevMonthDaysCount = prevMonthLastDay.getDate();
|
|
2674
|
+
const prevMonth = month === 0 ? 11 : month - 1;
|
|
2675
|
+
const prevYear = month === 0 ? year - 1 : year;
|
|
2676
|
+
for (let i = prevMonthDays - 1; i >= 0; i--) {
|
|
2677
|
+
days.push({
|
|
2678
|
+
date: prevMonthDaysCount - i,
|
|
2679
|
+
month: prevMonth,
|
|
2680
|
+
year: prevYear,
|
|
2681
|
+
isCurrentMonth: false
|
|
2682
|
+
});
|
|
2683
|
+
}
|
|
2684
|
+
for (let i = 1; i <= daysInMonth; i++) {
|
|
2685
|
+
days.push({
|
|
2686
|
+
date: i,
|
|
2687
|
+
month,
|
|
2688
|
+
year,
|
|
2689
|
+
isCurrentMonth: true
|
|
2690
|
+
});
|
|
2691
|
+
}
|
|
2692
|
+
const totalDaysSoFar = days.length;
|
|
2693
|
+
const totalWeeksNeeded = Math.ceil(totalDaysSoFar / 7);
|
|
2694
|
+
const targetDays = totalWeeksNeeded * 7;
|
|
2695
|
+
const nextMonth = month === 11 ? 0 : month + 1;
|
|
2696
|
+
const nextYear = month === 11 ? year + 1 : year;
|
|
2697
|
+
const nextMonthDaysNeeded = targetDays - totalDaysSoFar;
|
|
2698
|
+
for (let i = 1; i <= nextMonthDaysNeeded; i++) {
|
|
2699
|
+
days.push({
|
|
2700
|
+
date: i,
|
|
2701
|
+
month: nextMonth,
|
|
2702
|
+
year: nextYear,
|
|
2703
|
+
isCurrentMonth: false
|
|
2704
|
+
});
|
|
2705
|
+
}
|
|
2706
|
+
return days;
|
|
2707
|
+
}
|
|
2708
|
+
function getWeekDays(locale) {
|
|
2709
|
+
const effectiveLocale = typeof locale === "string" ? locale : "en-US";
|
|
2710
|
+
const baseSunday = new Date(2024, 0, 7);
|
|
2711
|
+
const weekDays = [];
|
|
2712
|
+
try {
|
|
2713
|
+
const formatter = new Intl.DateTimeFormat(effectiveLocale || "en-US", { weekday: "short" });
|
|
2714
|
+
for (let i = 0; i < 7; i++) {
|
|
2715
|
+
const date = new Date(baseSunday);
|
|
2716
|
+
date.setDate(baseSunday.getDate() + i);
|
|
2717
|
+
weekDays.push(formatter.format(date));
|
|
2718
|
+
}
|
|
2719
|
+
return weekDays;
|
|
2720
|
+
} catch {
|
|
2721
|
+
const fallbackFormatter = new Intl.DateTimeFormat("en-US", { weekday: "short" });
|
|
2722
|
+
for (let i = 0; i < 7; i++) {
|
|
2723
|
+
const date = new Date(baseSunday);
|
|
2724
|
+
date.setDate(baseSunday.getDate() + i);
|
|
2725
|
+
weekDays.push(fallbackFormatter.format(date));
|
|
2726
|
+
}
|
|
2727
|
+
return weekDays;
|
|
2728
|
+
}
|
|
2729
|
+
}
|
|
2730
|
+
function getMonthName(month, locale) {
|
|
2731
|
+
if (typeof month !== "number" || month < 0 || month > 11) {
|
|
2732
|
+
return void 0;
|
|
2733
|
+
}
|
|
2734
|
+
const effectiveLocale = typeof locale === "string" ? locale : "en-US";
|
|
2735
|
+
try {
|
|
2736
|
+
const date = new Date(2024, month, 1);
|
|
2737
|
+
const formatter = new Intl.DateTimeFormat(effectiveLocale, { month: "long" });
|
|
2738
|
+
return formatter.format(date);
|
|
2739
|
+
} catch {
|
|
2740
|
+
const date = new Date(2024, month, 1);
|
|
2741
|
+
const formatter = new Intl.DateTimeFormat("en-US", { month: "long" });
|
|
2742
|
+
return formatter.format(date);
|
|
2743
|
+
}
|
|
2744
|
+
}
|
|
2745
|
+
function formatDateISO(year, month, date) {
|
|
2746
|
+
if (typeof year !== "number" || typeof month !== "number" || typeof date !== "number") {
|
|
2747
|
+
return void 0;
|
|
2748
|
+
}
|
|
2749
|
+
const y = String(year).padStart(4, "0");
|
|
2750
|
+
const m = String(month + 1).padStart(2, "0");
|
|
2751
|
+
const d = String(date).padStart(2, "0");
|
|
2752
|
+
return `${y}-${m}-${d}`;
|
|
2753
|
+
}
|
|
2754
|
+
function sortBy(items, key, direction) {
|
|
2755
|
+
if (!Array.isArray(items)) {
|
|
2756
|
+
return void 0;
|
|
2757
|
+
}
|
|
2758
|
+
if (typeof key !== "string") {
|
|
2759
|
+
return void 0;
|
|
2760
|
+
}
|
|
2761
|
+
const forbiddenKeys = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
|
|
2762
|
+
if (forbiddenKeys.has(key)) {
|
|
2763
|
+
return void 0;
|
|
2764
|
+
}
|
|
2765
|
+
const dir = direction === "desc" ? "desc" : "asc";
|
|
2766
|
+
const sorted = [...items];
|
|
2767
|
+
sorted.sort((a, b) => {
|
|
2768
|
+
const aVal = a != null && typeof a === "object" ? a[key] : void 0;
|
|
2769
|
+
const bVal = b != null && typeof b === "object" ? b[key] : void 0;
|
|
2770
|
+
if (aVal == null && bVal == null) return 0;
|
|
2771
|
+
if (aVal == null) return 1;
|
|
2772
|
+
if (bVal == null) return -1;
|
|
2773
|
+
let comparison = 0;
|
|
2774
|
+
if (typeof aVal === "number" && typeof bVal === "number") {
|
|
2775
|
+
comparison = aVal - bVal;
|
|
2776
|
+
} else {
|
|
2777
|
+
comparison = String(aVal).localeCompare(String(bVal));
|
|
2778
|
+
}
|
|
2779
|
+
return dir === "desc" ? -comparison : comparison;
|
|
2780
|
+
});
|
|
2781
|
+
return sorted;
|
|
2782
|
+
}
|
|
2783
|
+
function getPaginatedItems(items, page, pageSize) {
|
|
2784
|
+
if (!Array.isArray(items)) {
|
|
2785
|
+
return void 0;
|
|
2786
|
+
}
|
|
2787
|
+
if (typeof page !== "number" || page < 0) {
|
|
2788
|
+
return void 0;
|
|
2789
|
+
}
|
|
2790
|
+
if (typeof pageSize !== "number" || pageSize <= 0) {
|
|
2791
|
+
return void 0;
|
|
2792
|
+
}
|
|
2793
|
+
const start = page * pageSize;
|
|
2794
|
+
const end = start + pageSize;
|
|
2795
|
+
return items.slice(start, end);
|
|
2796
|
+
}
|
|
2797
|
+
function getTotalPages(itemCount, pageSize) {
|
|
2798
|
+
if (typeof itemCount !== "number" || typeof pageSize !== "number") {
|
|
2799
|
+
return 0;
|
|
2800
|
+
}
|
|
2801
|
+
if (itemCount < 0 || pageSize <= 0) {
|
|
2802
|
+
return 0;
|
|
2803
|
+
}
|
|
2804
|
+
if (itemCount === 0) {
|
|
2805
|
+
return 0;
|
|
2806
|
+
}
|
|
2807
|
+
return Math.ceil(itemCount / pageSize);
|
|
2808
|
+
}
|
|
2809
|
+
function getPageNumbers(currentPage, totalPages, maxVisible) {
|
|
2810
|
+
if (typeof currentPage !== "number" || typeof totalPages !== "number" || typeof maxVisible !== "number") {
|
|
2811
|
+
return [];
|
|
2812
|
+
}
|
|
2813
|
+
if (totalPages <= 0) {
|
|
2814
|
+
return [];
|
|
2815
|
+
}
|
|
2816
|
+
if (currentPage < 0 || currentPage >= totalPages) {
|
|
2817
|
+
return [];
|
|
2818
|
+
}
|
|
2819
|
+
if (totalPages <= maxVisible) {
|
|
2820
|
+
return Array.from({ length: totalPages }, (_, i) => i);
|
|
2821
|
+
}
|
|
2822
|
+
const result = [];
|
|
2823
|
+
const firstPage = 0;
|
|
2824
|
+
const lastPage = totalPages - 1;
|
|
2825
|
+
result.push(firstPage);
|
|
2826
|
+
const middleSlots = maxVisible - 2;
|
|
2827
|
+
let middleStart = currentPage - Math.floor((middleSlots - 1) / 2);
|
|
2828
|
+
let middleEnd = currentPage + Math.ceil((middleSlots - 1) / 2);
|
|
2829
|
+
if (middleStart <= 1) {
|
|
2830
|
+
middleStart = 1;
|
|
2831
|
+
middleEnd = Math.min(middleSlots, lastPage - 1);
|
|
2832
|
+
}
|
|
2833
|
+
if (middleEnd >= lastPage - 1) {
|
|
2834
|
+
middleEnd = lastPage - 1;
|
|
2835
|
+
middleStart = Math.max(1, lastPage - middleSlots);
|
|
2836
|
+
}
|
|
2837
|
+
if (middleStart > 1) {
|
|
2838
|
+
result.push(-1);
|
|
2839
|
+
}
|
|
2840
|
+
for (let i = middleStart; i <= middleEnd; i++) {
|
|
2841
|
+
if (i > firstPage && i < lastPage) {
|
|
2842
|
+
result.push(i);
|
|
2843
|
+
}
|
|
2844
|
+
}
|
|
2845
|
+
if (middleEnd < lastPage - 1) {
|
|
2846
|
+
result.push(-1);
|
|
2847
|
+
}
|
|
2848
|
+
result.push(lastPage);
|
|
2849
|
+
return result;
|
|
2850
|
+
}
|
|
2851
|
+
function getVisibleRange(scrollTop, itemHeight, containerHeight, overscan) {
|
|
2852
|
+
if (typeof scrollTop !== "number" || typeof itemHeight !== "number" || typeof containerHeight !== "number" || typeof overscan !== "number") {
|
|
2853
|
+
return void 0;
|
|
2854
|
+
}
|
|
2855
|
+
if (scrollTop < 0 || itemHeight <= 0 || containerHeight <= 0) {
|
|
2856
|
+
return void 0;
|
|
2857
|
+
}
|
|
2858
|
+
const firstVisible = Math.floor(scrollTop / itemHeight);
|
|
2859
|
+
const visibleCount = Math.ceil(containerHeight / itemHeight);
|
|
2860
|
+
const start = Math.max(0, firstVisible - overscan);
|
|
2861
|
+
const end = firstVisible + visibleCount + overscan - 1;
|
|
2862
|
+
return { start, end };
|
|
2863
|
+
}
|
|
2864
|
+
function getTotalHeight(itemCount, itemHeight) {
|
|
2865
|
+
if (typeof itemCount !== "number" || typeof itemHeight !== "number") {
|
|
2866
|
+
return 0;
|
|
2867
|
+
}
|
|
2868
|
+
if (itemCount < 0 || itemHeight <= 0) {
|
|
2869
|
+
return 0;
|
|
2870
|
+
}
|
|
2871
|
+
return itemCount * itemHeight;
|
|
2872
|
+
}
|
|
2873
|
+
function formatDate(dateStr, format, locale) {
|
|
2874
|
+
if (typeof dateStr !== "string" || !dateStr) {
|
|
2875
|
+
return void 0;
|
|
2876
|
+
}
|
|
2877
|
+
const isoDateRegex = /^\d{4}-\d{2}-\d{2}$/;
|
|
2878
|
+
if (!isoDateRegex.test(dateStr)) {
|
|
2879
|
+
return void 0;
|
|
2880
|
+
}
|
|
2881
|
+
const [yearStr, monthStr, dayStr] = dateStr.split("-");
|
|
2882
|
+
const year = parseInt(yearStr, 10);
|
|
2883
|
+
const month = parseInt(monthStr, 10) - 1;
|
|
2884
|
+
const day = parseInt(dayStr, 10);
|
|
2885
|
+
const date = new Date(Date.UTC(year, month, day));
|
|
2886
|
+
if (isNaN(date.getTime()) || date.getUTCFullYear() !== year || date.getUTCMonth() !== month || date.getUTCDate() !== day) {
|
|
2887
|
+
return void 0;
|
|
2888
|
+
}
|
|
2889
|
+
const effectiveFormat = typeof format === "string" ? format : "medium";
|
|
2890
|
+
const effectiveLocale = typeof locale === "string" ? locale : "en-US";
|
|
2891
|
+
if (effectiveFormat === "iso") {
|
|
2892
|
+
return dateStr;
|
|
2893
|
+
}
|
|
2894
|
+
try {
|
|
2895
|
+
let options;
|
|
2896
|
+
switch (effectiveFormat) {
|
|
2897
|
+
case "short":
|
|
2898
|
+
if (effectiveLocale.startsWith("ja")) {
|
|
2899
|
+
options = { year: "numeric", month: "2-digit", day: "2-digit", timeZone: "UTC" };
|
|
2900
|
+
} else {
|
|
2901
|
+
options = { year: "2-digit", month: "numeric", day: "numeric", timeZone: "UTC" };
|
|
2902
|
+
}
|
|
2903
|
+
break;
|
|
2904
|
+
case "medium":
|
|
2905
|
+
options = { year: "numeric", month: "short", day: "numeric", timeZone: "UTC" };
|
|
2906
|
+
break;
|
|
2907
|
+
case "long":
|
|
2908
|
+
options = { year: "numeric", month: "long", day: "numeric", timeZone: "UTC" };
|
|
2909
|
+
break;
|
|
2910
|
+
default:
|
|
2911
|
+
options = { year: "numeric", month: "short", day: "numeric", timeZone: "UTC" };
|
|
2912
|
+
}
|
|
2913
|
+
const formatter = new Intl.DateTimeFormat(effectiveLocale, options);
|
|
2914
|
+
return formatter.format(date);
|
|
2915
|
+
} catch {
|
|
2916
|
+
const formatter = new Intl.DateTimeFormat("en-US", {
|
|
2917
|
+
year: "numeric",
|
|
2918
|
+
month: "short",
|
|
2919
|
+
day: "numeric",
|
|
2920
|
+
timeZone: "UTC"
|
|
2921
|
+
});
|
|
2922
|
+
return formatter.format(date);
|
|
2923
|
+
}
|
|
2924
|
+
}
|
|
2659
2925
|
function normalizeValue(value, min, max) {
|
|
2660
2926
|
if (typeof value !== "number" || typeof min !== "number" || typeof max !== "number") {
|
|
2661
2927
|
return void 0;
|
|
@@ -2675,50 +2941,60 @@ function scaleValue(value, domainMin, domainMax, rangeMin, rangeMax) {
|
|
|
2675
2941
|
const normalized = (value - domainMin) / (domainMax - domainMin);
|
|
2676
2942
|
return rangeMin + normalized * (rangeMax - rangeMin);
|
|
2677
2943
|
}
|
|
2678
|
-
function
|
|
2679
|
-
if (
|
|
2944
|
+
function scaleChartY(value, boundsMin, boundsMax, height, paddingTop, paddingBottom) {
|
|
2945
|
+
if (typeof value !== "number" || typeof boundsMin !== "number" || typeof boundsMax !== "number" || typeof height !== "number" || typeof paddingTop !== "number" || typeof paddingBottom !== "number") {
|
|
2680
2946
|
return void 0;
|
|
2681
2947
|
}
|
|
2682
|
-
|
|
2948
|
+
const drawableHeight = height - paddingTop - paddingBottom;
|
|
2949
|
+
if (drawableHeight <= 0) {
|
|
2950
|
+
return paddingTop;
|
|
2951
|
+
}
|
|
2952
|
+
if (boundsMax === boundsMin) {
|
|
2953
|
+
return paddingTop + drawableHeight / 2;
|
|
2954
|
+
}
|
|
2955
|
+
const normalized = (value - boundsMin) / (boundsMax - boundsMin);
|
|
2956
|
+
return paddingTop + drawableHeight * (1 - normalized);
|
|
2957
|
+
}
|
|
2958
|
+
function getBarDimensions(data, index, width, height, gap, orientation) {
|
|
2959
|
+
if (!Array.isArray(data) || data.length === 0) {
|
|
2683
2960
|
return void 0;
|
|
2684
2961
|
}
|
|
2685
|
-
|
|
2686
|
-
|
|
2687
|
-
if (typeof item !== "object" || item === null) {
|
|
2688
|
-
continue;
|
|
2689
|
-
}
|
|
2690
|
-
const val = item[valueKey];
|
|
2691
|
-
if (typeof val === "number") {
|
|
2692
|
-
values.push(val);
|
|
2693
|
-
}
|
|
2962
|
+
if (typeof index !== "number" || index < 0 || index >= data.length) {
|
|
2963
|
+
return void 0;
|
|
2694
2964
|
}
|
|
2695
|
-
if (
|
|
2965
|
+
if (typeof width !== "number" || typeof height !== "number" || typeof gap !== "number") {
|
|
2696
2966
|
return void 0;
|
|
2697
2967
|
}
|
|
2698
|
-
|
|
2699
|
-
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
|
|
2704
|
-
|
|
2705
|
-
|
|
2706
|
-
|
|
2707
|
-
|
|
2708
|
-
|
|
2709
|
-
|
|
2710
|
-
|
|
2711
|
-
|
|
2712
|
-
|
|
2713
|
-
|
|
2714
|
-
|
|
2715
|
-
|
|
2716
|
-
const
|
|
2717
|
-
|
|
2718
|
-
const
|
|
2719
|
-
const
|
|
2720
|
-
|
|
2721
|
-
|
|
2968
|
+
const isVertical = orientation === "vertical";
|
|
2969
|
+
const barCount = data.length;
|
|
2970
|
+
const values = data.map((d) => typeof d === "number" ? d : 0);
|
|
2971
|
+
const maxValue = Math.max(...values);
|
|
2972
|
+
if (isVertical) {
|
|
2973
|
+
const totalGap = gap * (barCount + 1);
|
|
2974
|
+
const barWidth = (width - totalGap) / barCount;
|
|
2975
|
+
const barX = gap + index * (barWidth + gap);
|
|
2976
|
+
const value = values[index] ?? 0;
|
|
2977
|
+
const barHeight = maxValue > 0 ? value / maxValue * height : 0;
|
|
2978
|
+
const barY = height - barHeight;
|
|
2979
|
+
return {
|
|
2980
|
+
x: barX,
|
|
2981
|
+
y: barY,
|
|
2982
|
+
width: barWidth,
|
|
2983
|
+
height: barHeight
|
|
2984
|
+
};
|
|
2985
|
+
} else {
|
|
2986
|
+
const totalGap = gap * barCount;
|
|
2987
|
+
const barHeight = (height - totalGap) / barCount;
|
|
2988
|
+
const barY = gap + index * (barHeight + gap);
|
|
2989
|
+
const value = values[index] ?? 0;
|
|
2990
|
+
const barWidth = maxValue > 0 ? value / maxValue * width : 0;
|
|
2991
|
+
return {
|
|
2992
|
+
x: 0,
|
|
2993
|
+
y: barY,
|
|
2994
|
+
width: barWidth,
|
|
2995
|
+
height: barHeight
|
|
2996
|
+
};
|
|
2997
|
+
}
|
|
2722
2998
|
}
|
|
2723
2999
|
function getCurvedPath(points) {
|
|
2724
3000
|
if (points.length < 2) {
|
|
@@ -2766,15 +3042,462 @@ function getLinePath(points, curved) {
|
|
|
2766
3042
|
}
|
|
2767
3043
|
return getCurvedPath(validPoints);
|
|
2768
3044
|
}
|
|
2769
|
-
|
|
3045
|
+
function getAreaPath(points, baseline, curved) {
|
|
3046
|
+
if (!Array.isArray(points)) {
|
|
3047
|
+
return void 0;
|
|
3048
|
+
}
|
|
3049
|
+
if (typeof baseline !== "number") {
|
|
3050
|
+
return void 0;
|
|
3051
|
+
}
|
|
3052
|
+
if (points.length === 0) {
|
|
3053
|
+
return "";
|
|
3054
|
+
}
|
|
3055
|
+
for (const point of points) {
|
|
3056
|
+
if (typeof point !== "object" || point === null || typeof point.x !== "number" || typeof point.y !== "number") {
|
|
3057
|
+
return void 0;
|
|
3058
|
+
}
|
|
3059
|
+
}
|
|
3060
|
+
const validPoints = points;
|
|
3061
|
+
let upperPath;
|
|
3062
|
+
if (curved === true && validPoints.length > 2) {
|
|
3063
|
+
upperPath = getCurvedPath(validPoints);
|
|
3064
|
+
} else {
|
|
3065
|
+
upperPath = validPoints.map((p, i) => (i === 0 ? "M" : "L") + `${p.x},${p.y}`).join(" ");
|
|
3066
|
+
}
|
|
3067
|
+
const lastPoint = validPoints[validPoints.length - 1];
|
|
3068
|
+
const firstPoint = validPoints[0];
|
|
3069
|
+
return `${upperPath} L${lastPoint.x},${baseline} L${firstPoint.x},${baseline} Z`;
|
|
3070
|
+
}
|
|
3071
|
+
function getArcPath(cx, cy, radius, startAngle, endAngle) {
|
|
3072
|
+
if (typeof cx !== "number" || typeof cy !== "number" || typeof radius !== "number" || typeof startAngle !== "number" || typeof endAngle !== "number") {
|
|
3073
|
+
return void 0;
|
|
3074
|
+
}
|
|
3075
|
+
if (radius <= 0) {
|
|
3076
|
+
return void 0;
|
|
3077
|
+
}
|
|
3078
|
+
const x1 = cx + radius * Math.cos(startAngle);
|
|
3079
|
+
const y1 = cy + radius * Math.sin(startAngle);
|
|
3080
|
+
const x2 = cx + radius * Math.cos(endAngle);
|
|
3081
|
+
const y2 = cy + radius * Math.sin(endAngle);
|
|
3082
|
+
const angleDiff = endAngle - startAngle;
|
|
3083
|
+
const largeArcFlag = Math.abs(angleDiff) > Math.PI ? 1 : 0;
|
|
3084
|
+
return `M${x1},${y1} A${radius},${radius} 0 ${largeArcFlag},1 ${x2},${y2}`;
|
|
3085
|
+
}
|
|
3086
|
+
function getPieSlices(data, valueKey) {
|
|
3087
|
+
if (!Array.isArray(data)) {
|
|
3088
|
+
return void 0;
|
|
3089
|
+
}
|
|
3090
|
+
if (typeof valueKey !== "string") {
|
|
3091
|
+
return void 0;
|
|
3092
|
+
}
|
|
3093
|
+
if (data.length === 0) {
|
|
3094
|
+
return [];
|
|
3095
|
+
}
|
|
3096
|
+
const values = data.map((item) => {
|
|
3097
|
+
if (typeof item !== "object" || item === null) return 0;
|
|
3098
|
+
const val = item[valueKey];
|
|
3099
|
+
return typeof val === "number" ? val : 0;
|
|
3100
|
+
});
|
|
3101
|
+
const total = values.reduce((sum, val) => sum + val, 0);
|
|
3102
|
+
const slices = [];
|
|
3103
|
+
let currentAngle = 0;
|
|
3104
|
+
for (let i = 0; i < values.length; i++) {
|
|
3105
|
+
const value = values[i];
|
|
3106
|
+
const percentage = total > 0 ? value / total * 100 : 0;
|
|
3107
|
+
const angleSpan = total > 0 ? value / total * Math.PI * 2 : 0;
|
|
3108
|
+
slices.push({
|
|
3109
|
+
startAngle: currentAngle,
|
|
3110
|
+
endAngle: currentAngle + angleSpan,
|
|
3111
|
+
value,
|
|
3112
|
+
percentage
|
|
3113
|
+
});
|
|
3114
|
+
currentAngle += angleSpan;
|
|
3115
|
+
}
|
|
3116
|
+
return slices;
|
|
3117
|
+
}
|
|
3118
|
+
function getDonutSlices(data, valueKey, innerRadius) {
|
|
3119
|
+
if (typeof innerRadius !== "number" || innerRadius < 0) {
|
|
3120
|
+
return void 0;
|
|
3121
|
+
}
|
|
3122
|
+
const pieSlices = getPieSlices(data, valueKey);
|
|
3123
|
+
if (pieSlices === void 0) {
|
|
3124
|
+
return void 0;
|
|
3125
|
+
}
|
|
3126
|
+
const outerRadius = 100;
|
|
3127
|
+
return pieSlices.map((slice) => ({
|
|
3128
|
+
...slice,
|
|
3129
|
+
outerRadius,
|
|
3130
|
+
innerRadius
|
|
3131
|
+
}));
|
|
3132
|
+
}
|
|
3133
|
+
function getRadarPoints(data, valueKey, cx, cy, radius, maxValue) {
|
|
3134
|
+
if (!Array.isArray(data)) {
|
|
3135
|
+
return void 0;
|
|
3136
|
+
}
|
|
3137
|
+
if (typeof valueKey !== "string") {
|
|
3138
|
+
return void 0;
|
|
3139
|
+
}
|
|
3140
|
+
if (typeof cx !== "number" || typeof cy !== "number" || typeof radius !== "number" || typeof maxValue !== "number") {
|
|
3141
|
+
return void 0;
|
|
3142
|
+
}
|
|
3143
|
+
if (maxValue <= 0) {
|
|
3144
|
+
return void 0;
|
|
3145
|
+
}
|
|
3146
|
+
if (data.length === 0) {
|
|
3147
|
+
return [];
|
|
3148
|
+
}
|
|
3149
|
+
const points = [];
|
|
3150
|
+
const angleStep = Math.PI * 2 / data.length;
|
|
3151
|
+
for (let i = 0; i < data.length; i++) {
|
|
3152
|
+
const item = data[i];
|
|
3153
|
+
const value = typeof item === "object" && item !== null ? item[valueKey] : 0;
|
|
3154
|
+
const numValue = typeof value === "number" ? value : 0;
|
|
3155
|
+
const scaledRadius = numValue / maxValue * radius;
|
|
3156
|
+
const angle = -Math.PI / 2 + i * angleStep;
|
|
3157
|
+
const x = cx + scaledRadius * Math.cos(angle);
|
|
3158
|
+
const y = cy + scaledRadius * Math.sin(angle);
|
|
3159
|
+
points.push({ x, y });
|
|
3160
|
+
}
|
|
3161
|
+
return points;
|
|
3162
|
+
}
|
|
3163
|
+
function getRadarAxes(labels, cx, cy, radius) {
|
|
3164
|
+
if (!Array.isArray(labels)) {
|
|
3165
|
+
return void 0;
|
|
3166
|
+
}
|
|
3167
|
+
if (typeof cx !== "number" || typeof cy !== "number" || typeof radius !== "number") {
|
|
3168
|
+
return void 0;
|
|
3169
|
+
}
|
|
3170
|
+
if (radius < 0) {
|
|
3171
|
+
return void 0;
|
|
3172
|
+
}
|
|
3173
|
+
if (labels.length === 0) {
|
|
3174
|
+
return [];
|
|
3175
|
+
}
|
|
3176
|
+
const axes = [];
|
|
3177
|
+
const angleStep = Math.PI * 2 / labels.length;
|
|
3178
|
+
for (let i = 0; i < labels.length; i++) {
|
|
3179
|
+
const label = String(labels[i]);
|
|
3180
|
+
const angle = -Math.PI / 2 + i * angleStep;
|
|
3181
|
+
const x2 = cx + radius * Math.cos(angle);
|
|
3182
|
+
const y2 = cy + radius * Math.sin(angle);
|
|
3183
|
+
axes.push({
|
|
3184
|
+
x1: cx,
|
|
3185
|
+
y1: cy,
|
|
3186
|
+
x2,
|
|
3187
|
+
y2,
|
|
3188
|
+
label,
|
|
3189
|
+
angle
|
|
3190
|
+
});
|
|
3191
|
+
}
|
|
3192
|
+
return axes;
|
|
3193
|
+
}
|
|
3194
|
+
function getChartBounds(data, valueKey) {
|
|
3195
|
+
if (!Array.isArray(data) || data.length === 0) {
|
|
3196
|
+
return void 0;
|
|
3197
|
+
}
|
|
3198
|
+
if (typeof valueKey !== "string") {
|
|
3199
|
+
return void 0;
|
|
3200
|
+
}
|
|
3201
|
+
const values = [];
|
|
3202
|
+
for (const item of data) {
|
|
3203
|
+
if (typeof item !== "object" || item === null) {
|
|
3204
|
+
continue;
|
|
3205
|
+
}
|
|
3206
|
+
const val = item[valueKey];
|
|
3207
|
+
if (typeof val === "number") {
|
|
3208
|
+
values.push(val);
|
|
3209
|
+
}
|
|
3210
|
+
}
|
|
3211
|
+
if (values.length === 0) {
|
|
3212
|
+
return void 0;
|
|
3213
|
+
}
|
|
3214
|
+
return {
|
|
3215
|
+
min: Math.min(...values),
|
|
3216
|
+
max: Math.max(...values)
|
|
3217
|
+
};
|
|
3218
|
+
}
|
|
3219
|
+
function generateTicks(min, max, count) {
|
|
3220
|
+
if (typeof min !== "number" || typeof max !== "number" || typeof count !== "number") {
|
|
3221
|
+
return [];
|
|
3222
|
+
}
|
|
3223
|
+
if (count <= 0) {
|
|
3224
|
+
return [];
|
|
3225
|
+
}
|
|
3226
|
+
if (min === max) {
|
|
3227
|
+
return [min];
|
|
3228
|
+
}
|
|
3229
|
+
if (count === 1) {
|
|
3230
|
+
return [min];
|
|
3231
|
+
}
|
|
3232
|
+
if (count === 2) {
|
|
3233
|
+
return [min, max];
|
|
3234
|
+
}
|
|
3235
|
+
const range = max - min;
|
|
3236
|
+
const rawStep = range / (count - 1);
|
|
3237
|
+
const niceStep = getNiceStep(rawStep);
|
|
3238
|
+
const niceMin = Math.floor(min / niceStep) * niceStep;
|
|
3239
|
+
const ticks = [];
|
|
3240
|
+
for (let i = 0; i < count; i++) {
|
|
3241
|
+
const tick = niceMin + i * niceStep;
|
|
3242
|
+
ticks.push(Math.round(tick * 1e10) / 1e10);
|
|
3243
|
+
}
|
|
3244
|
+
return ticks;
|
|
3245
|
+
}
|
|
3246
|
+
function getNiceStep(rawStep) {
|
|
3247
|
+
const magnitude = Math.pow(10, Math.floor(Math.log10(rawStep)));
|
|
3248
|
+
const normalized = rawStep / magnitude;
|
|
3249
|
+
let niceNormalized;
|
|
3250
|
+
if (normalized <= 1) {
|
|
3251
|
+
niceNormalized = 1;
|
|
3252
|
+
} else if (normalized <= 2) {
|
|
3253
|
+
niceNormalized = 2;
|
|
3254
|
+
} else if (normalized <= 2.5) {
|
|
3255
|
+
niceNormalized = 2.5;
|
|
3256
|
+
} else if (normalized <= 5) {
|
|
3257
|
+
niceNormalized = 5;
|
|
3258
|
+
} else {
|
|
3259
|
+
niceNormalized = 10;
|
|
3260
|
+
}
|
|
3261
|
+
return niceNormalized * magnitude;
|
|
3262
|
+
}
|
|
3263
|
+
function binData(data, valueKey, binCount) {
|
|
3264
|
+
if (!Array.isArray(data)) {
|
|
3265
|
+
return void 0;
|
|
3266
|
+
}
|
|
3267
|
+
if (typeof valueKey !== "string") {
|
|
3268
|
+
return void 0;
|
|
3269
|
+
}
|
|
3270
|
+
if (typeof binCount !== "number" || binCount <= 0) {
|
|
3271
|
+
return [];
|
|
3272
|
+
}
|
|
3273
|
+
if (data.length === 0) {
|
|
3274
|
+
return [];
|
|
3275
|
+
}
|
|
3276
|
+
const values = [];
|
|
3277
|
+
for (const item of data) {
|
|
3278
|
+
if (typeof item !== "object" || item === null) continue;
|
|
3279
|
+
const val = item[valueKey];
|
|
3280
|
+
if (typeof val === "number") {
|
|
3281
|
+
values.push(val);
|
|
3282
|
+
}
|
|
3283
|
+
}
|
|
3284
|
+
if (values.length === 0) {
|
|
3285
|
+
return [];
|
|
3286
|
+
}
|
|
3287
|
+
const minVal = Math.min(...values);
|
|
3288
|
+
const maxVal = Math.max(...values);
|
|
3289
|
+
const binWidth = maxVal === minVal ? 1 : (maxVal - minVal) / binCount;
|
|
3290
|
+
const bins = [];
|
|
3291
|
+
for (let i = 0; i < binCount; i++) {
|
|
3292
|
+
bins.push({
|
|
3293
|
+
binStart: minVal + i * binWidth,
|
|
3294
|
+
binEnd: minVal + (i + 1) * binWidth,
|
|
3295
|
+
count: 0,
|
|
3296
|
+
values: []
|
|
3297
|
+
});
|
|
3298
|
+
}
|
|
3299
|
+
for (const val of values) {
|
|
3300
|
+
let binIndex = Math.floor((val - minVal) / binWidth);
|
|
3301
|
+
if (binIndex >= binCount) {
|
|
3302
|
+
binIndex = binCount - 1;
|
|
3303
|
+
}
|
|
3304
|
+
bins[binIndex].count++;
|
|
3305
|
+
bins[binIndex].values.push(val);
|
|
3306
|
+
}
|
|
3307
|
+
return bins;
|
|
3308
|
+
}
|
|
3309
|
+
function aggregateData(data, groupKey, valueKey, aggregation) {
|
|
3310
|
+
if (!Array.isArray(data)) {
|
|
3311
|
+
return void 0;
|
|
3312
|
+
}
|
|
3313
|
+
if (typeof groupKey !== "string" || typeof valueKey !== "string") {
|
|
3314
|
+
return void 0;
|
|
3315
|
+
}
|
|
3316
|
+
const validAggregations = /* @__PURE__ */ new Set(["sum", "avg", "min", "max", "count"]);
|
|
3317
|
+
if (typeof aggregation !== "string" || !validAggregations.has(aggregation)) {
|
|
3318
|
+
return void 0;
|
|
3319
|
+
}
|
|
3320
|
+
if (data.length === 0) {
|
|
3321
|
+
return [];
|
|
3322
|
+
}
|
|
3323
|
+
const groups = /* @__PURE__ */ new Map();
|
|
3324
|
+
for (const item of data) {
|
|
3325
|
+
if (typeof item !== "object" || item === null) continue;
|
|
3326
|
+
const obj = item;
|
|
3327
|
+
const group = String(obj[groupKey] ?? "");
|
|
3328
|
+
const val = obj[valueKey];
|
|
3329
|
+
const numVal = typeof val === "number" ? val : 0;
|
|
3330
|
+
if (!groups.has(group)) {
|
|
3331
|
+
groups.set(group, []);
|
|
3332
|
+
}
|
|
3333
|
+
groups.get(group).push(numVal);
|
|
3334
|
+
}
|
|
3335
|
+
const result = [];
|
|
3336
|
+
for (const [group, groupValues] of groups) {
|
|
3337
|
+
let aggregatedValue;
|
|
3338
|
+
switch (aggregation) {
|
|
3339
|
+
case "sum":
|
|
3340
|
+
aggregatedValue = groupValues.reduce((sum, v) => sum + v, 0);
|
|
3341
|
+
break;
|
|
3342
|
+
case "avg":
|
|
3343
|
+
aggregatedValue = groupValues.reduce((sum, v) => sum + v, 0) / groupValues.length;
|
|
3344
|
+
break;
|
|
3345
|
+
case "min":
|
|
3346
|
+
aggregatedValue = Math.min(...groupValues);
|
|
3347
|
+
break;
|
|
3348
|
+
case "max":
|
|
3349
|
+
aggregatedValue = Math.max(...groupValues);
|
|
3350
|
+
break;
|
|
3351
|
+
case "count":
|
|
3352
|
+
aggregatedValue = groupValues.length;
|
|
3353
|
+
break;
|
|
3354
|
+
default:
|
|
3355
|
+
aggregatedValue = 0;
|
|
3356
|
+
}
|
|
3357
|
+
result.push({ group, value: aggregatedValue });
|
|
3358
|
+
}
|
|
3359
|
+
return result;
|
|
3360
|
+
}
|
|
3361
|
+
function downsample(data, targetCount, method) {
|
|
3362
|
+
if (!Array.isArray(data)) {
|
|
3363
|
+
return void 0;
|
|
3364
|
+
}
|
|
3365
|
+
if (typeof targetCount !== "number" || targetCount <= 0) {
|
|
3366
|
+
return void 0;
|
|
3367
|
+
}
|
|
3368
|
+
const validMethods = /* @__PURE__ */ new Set(["uniform", "lttb"]);
|
|
3369
|
+
if (typeof method !== "string" || !validMethods.has(method)) {
|
|
3370
|
+
return void 0;
|
|
3371
|
+
}
|
|
3372
|
+
if (data.length === 0) {
|
|
3373
|
+
return [];
|
|
3374
|
+
}
|
|
3375
|
+
if (targetCount >= data.length) {
|
|
3376
|
+
return data;
|
|
3377
|
+
}
|
|
3378
|
+
if (method === "uniform") {
|
|
3379
|
+
return downsampleUniform(data, targetCount);
|
|
3380
|
+
} else {
|
|
3381
|
+
return downsampleLTTB(data, targetCount);
|
|
3382
|
+
}
|
|
3383
|
+
}
|
|
3384
|
+
function downsampleUniform(data, targetCount) {
|
|
3385
|
+
if (targetCount === 1) {
|
|
3386
|
+
return [data[0]];
|
|
3387
|
+
}
|
|
3388
|
+
if (targetCount === 2) {
|
|
3389
|
+
return [data[0], data[data.length - 1]];
|
|
3390
|
+
}
|
|
3391
|
+
const result = [];
|
|
3392
|
+
const step = (data.length - 1) / (targetCount - 1);
|
|
3393
|
+
for (let i = 0; i < targetCount; i++) {
|
|
3394
|
+
const index = Math.round(i * step);
|
|
3395
|
+
result.push(data[index]);
|
|
3396
|
+
}
|
|
3397
|
+
return result;
|
|
3398
|
+
}
|
|
3399
|
+
function downsampleLTTB(data, targetCount) {
|
|
3400
|
+
if (targetCount === 1) {
|
|
3401
|
+
return [data[0]];
|
|
3402
|
+
}
|
|
3403
|
+
if (targetCount === 2) {
|
|
3404
|
+
return [data[0], data[data.length - 1]];
|
|
3405
|
+
}
|
|
3406
|
+
const getXY = (point) => {
|
|
3407
|
+
if (typeof point !== "object" || point === null) {
|
|
3408
|
+
return { x: 0, y: 0 };
|
|
3409
|
+
}
|
|
3410
|
+
const obj = point;
|
|
3411
|
+
const x = typeof obj["x"] === "number" ? obj["x"] : typeof obj["timestamp"] === "number" ? obj["timestamp"] : 0;
|
|
3412
|
+
const y = typeof obj["y"] === "number" ? obj["y"] : typeof obj["value"] === "number" ? obj["value"] : 0;
|
|
3413
|
+
return { x, y };
|
|
3414
|
+
};
|
|
3415
|
+
const result = [];
|
|
3416
|
+
result.push(data[0]);
|
|
3417
|
+
const numBuckets = targetCount - 2;
|
|
3418
|
+
const middleData = data.length - 2;
|
|
3419
|
+
const bucketSize = middleData / numBuckets;
|
|
3420
|
+
let prevSelectedIndex = 0;
|
|
3421
|
+
for (let bucketIndex = 0; bucketIndex < numBuckets; bucketIndex++) {
|
|
3422
|
+
const bucketStart = Math.floor(bucketIndex * bucketSize) + 1;
|
|
3423
|
+
const bucketEnd = Math.floor((bucketIndex + 1) * bucketSize) + 1;
|
|
3424
|
+
const nextBucketStart = bucketEnd;
|
|
3425
|
+
const nextBucketEnd = bucketIndex < numBuckets - 1 ? Math.floor((bucketIndex + 2) * bucketSize) + 1 : data.length;
|
|
3426
|
+
let avgX = 0;
|
|
3427
|
+
let avgY = 0;
|
|
3428
|
+
const nextLen = nextBucketEnd - nextBucketStart;
|
|
3429
|
+
if (nextLen > 0) {
|
|
3430
|
+
for (let j = nextBucketStart; j < nextBucketEnd; j++) {
|
|
3431
|
+
const point = getXY(data[j]);
|
|
3432
|
+
avgX += point.x;
|
|
3433
|
+
avgY += point.y;
|
|
3434
|
+
}
|
|
3435
|
+
avgX /= nextLen;
|
|
3436
|
+
avgY /= nextLen;
|
|
3437
|
+
} else {
|
|
3438
|
+
const lastPoint = getXY(data[data.length - 1]);
|
|
3439
|
+
avgX = lastPoint.x;
|
|
3440
|
+
avgY = lastPoint.y;
|
|
3441
|
+
}
|
|
3442
|
+
const pointA = getXY(data[prevSelectedIndex]);
|
|
3443
|
+
let maxArea = -1;
|
|
3444
|
+
let maxAreaIndex = bucketStart;
|
|
3445
|
+
for (let j = bucketStart; j < bucketEnd; j++) {
|
|
3446
|
+
const pointB = getXY(data[j]);
|
|
3447
|
+
const area = Math.abs(
|
|
3448
|
+
pointA.x * (pointB.y - avgY) + pointB.x * (avgY - pointA.y) + avgX * (pointA.y - pointB.y)
|
|
3449
|
+
);
|
|
3450
|
+
if (area > maxArea) {
|
|
3451
|
+
maxArea = area;
|
|
3452
|
+
maxAreaIndex = j;
|
|
3453
|
+
}
|
|
3454
|
+
}
|
|
3455
|
+
result.push(data[maxAreaIndex]);
|
|
3456
|
+
prevSelectedIndex = maxAreaIndex;
|
|
3457
|
+
}
|
|
3458
|
+
result.push(data[data.length - 1]);
|
|
3459
|
+
return result;
|
|
3460
|
+
}
|
|
3461
|
+
var GLOBAL_FUNCTIONS = {
|
|
3462
|
+
// Date helpers
|
|
3463
|
+
getCalendarDays: (year, month) => getCalendarDays(year, month),
|
|
3464
|
+
getWeekDays: (locale) => getWeekDays(locale),
|
|
3465
|
+
getMonthName: (month, locale) => getMonthName(month, locale),
|
|
3466
|
+
formatDate: (dateStr, format, locale) => formatDate(dateStr, format, locale),
|
|
3467
|
+
formatDateISO: (year, month, date) => formatDateISO(year, month, date),
|
|
3468
|
+
// DataTable helpers
|
|
3469
|
+
sortBy: (items, key, direction) => sortBy(items, key, direction),
|
|
3470
|
+
getPaginatedItems: (items, page, pageSize) => getPaginatedItems(items, page, pageSize),
|
|
3471
|
+
getTotalPages: (itemCount, pageSize) => getTotalPages(itemCount, pageSize),
|
|
3472
|
+
getPageNumbers: (currentPage, totalPages, maxVisible) => getPageNumbers(currentPage, totalPages, maxVisible),
|
|
3473
|
+
// Virtual scroll helpers
|
|
3474
|
+
getVisibleRange: (scrollTop, itemHeight, containerHeight, overscan) => getVisibleRange(scrollTop, itemHeight, containerHeight, overscan),
|
|
3475
|
+
getTotalHeight: (itemCount, itemHeight) => getTotalHeight(itemCount, itemHeight),
|
|
3476
|
+
// Chart helpers - Coordinate calculation
|
|
2770
3477
|
normalizeValue: (value, min, max) => normalizeValue(value, min, max),
|
|
2771
3478
|
scaleValue: (value, domainMin, domainMax, rangeMin, rangeMax) => scaleValue(value, domainMin, domainMax, rangeMin, rangeMax),
|
|
3479
|
+
getBarDimensions: (data, index, width, height, gap, orientation) => getBarDimensions(data, index, width, height, gap, orientation),
|
|
3480
|
+
// Chart helpers - Path generation
|
|
3481
|
+
getLinePath: (points, curved) => getLinePath(points, curved),
|
|
3482
|
+
getAreaPath: (points, baseline, curved) => getAreaPath(points, baseline, curved),
|
|
3483
|
+
getArcPath: (cx, cy, radius, startAngle, endAngle) => getArcPath(cx, cy, radius, startAngle, endAngle),
|
|
3484
|
+
// Chart helpers - Pie/Donut
|
|
3485
|
+
getPieSlices: (data, valueKey) => getPieSlices(data, valueKey),
|
|
3486
|
+
getDonutSlices: (data, valueKey, innerRadius) => getDonutSlices(data, valueKey, innerRadius),
|
|
3487
|
+
// Chart helpers - Radar
|
|
3488
|
+
getRadarPoints: (data, valueKey, cx, cy, radius, maxValue) => getRadarPoints(data, valueKey, cx, cy, radius, maxValue),
|
|
3489
|
+
getRadarAxes: (labels, cx, cy, radius) => getRadarAxes(labels, cx, cy, radius),
|
|
3490
|
+
// Chart helpers - Utilities
|
|
2772
3491
|
getChartBounds: (data, valueKey) => getChartBounds(data, valueKey),
|
|
2773
|
-
|
|
2774
|
-
|
|
3492
|
+
scaleChartY: (value, boundsMin, boundsMax, height, paddingTop, paddingBottom) => scaleChartY(value, boundsMin, boundsMax, height, paddingTop, paddingBottom),
|
|
3493
|
+
generateTicks: (min, max, count) => generateTicks(min, max, count),
|
|
3494
|
+
// Chart helpers - Data aggregation
|
|
3495
|
+
binData: (data, valueKey, binCount) => binData(data, valueKey, binCount),
|
|
3496
|
+
aggregateData: (data, groupKey, valueKey, aggregation) => aggregateData(data, groupKey, valueKey, aggregation),
|
|
3497
|
+
downsample: (data, targetCount, method) => downsample(data, targetCount, method)
|
|
2775
3498
|
};
|
|
2776
|
-
function
|
|
2777
|
-
const fn =
|
|
3499
|
+
function callGlobalFunction(method, args) {
|
|
3500
|
+
const fn = GLOBAL_FUNCTIONS[method];
|
|
2778
3501
|
if (!fn) {
|
|
2779
3502
|
return void 0;
|
|
2780
3503
|
}
|
|
@@ -2784,13 +3507,13 @@ export {
|
|
|
2784
3507
|
AI_OUTPUT_TYPES,
|
|
2785
3508
|
AI_PROVIDER_TYPES,
|
|
2786
3509
|
BINARY_OPERATORS,
|
|
2787
|
-
CHART_HELPERS,
|
|
2788
3510
|
CLIPBOARD_OPERATIONS,
|
|
2789
3511
|
COLOR_SCHEMES,
|
|
2790
3512
|
ConstelaError,
|
|
2791
3513
|
DATA_SOURCE_TYPES,
|
|
2792
3514
|
DATA_TRANSFORMS,
|
|
2793
3515
|
FOCUS_OPERATIONS,
|
|
3516
|
+
GLOBAL_FUNCTIONS,
|
|
2794
3517
|
HTTP_METHODS,
|
|
2795
3518
|
ISLAND_STRATEGIES,
|
|
2796
3519
|
NAVIGATE_TARGETS,
|
|
@@ -2800,7 +3523,7 @@ export {
|
|
|
2800
3523
|
UPDATE_OPERATIONS,
|
|
2801
3524
|
VALIDITY_PROPERTIES,
|
|
2802
3525
|
astSchema,
|
|
2803
|
-
|
|
3526
|
+
callGlobalFunction,
|
|
2804
3527
|
createClipboardWriteMissingValueError,
|
|
2805
3528
|
createComponentCycleError,
|
|
2806
3529
|
createComponentNotFoundError,
|
|
@@ -2843,9 +3566,6 @@ export {
|
|
|
2843
3566
|
createUndefinedVariantError,
|
|
2844
3567
|
createUnsupportedVersionError,
|
|
2845
3568
|
findSimilarNames,
|
|
2846
|
-
getChartBounds,
|
|
2847
|
-
getLinePath,
|
|
2848
|
-
getLinePoints,
|
|
2849
3569
|
isActionStep,
|
|
2850
3570
|
isAiDataSource,
|
|
2851
3571
|
isArrayExpr,
|
|
@@ -2917,7 +3637,5 @@ export {
|
|
|
2917
3637
|
isValidityExpr,
|
|
2918
3638
|
isVarExpr,
|
|
2919
3639
|
isViewNode,
|
|
2920
|
-
normalizeValue,
|
|
2921
|
-
scaleValue,
|
|
2922
3640
|
validateAst
|
|
2923
3641
|
};
|