pxengine 0.1.120 → 0.1.121
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.cjs +381 -17
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +44 -6
- package/dist/index.d.ts +44 -6
- package/dist/index.mjs +384 -20
- package/dist/index.mjs.map +1 -1
- package/dist/registry.json +1533 -188
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -16080,6 +16080,8 @@ var import_react79 = require("react");
|
|
|
16080
16080
|
|
|
16081
16081
|
// src/lib/shared-poll.ts
|
|
16082
16082
|
var import_react78 = require("react");
|
|
16083
|
+
var MAX_RETAINED = 50;
|
|
16084
|
+
var RETAIN_TTL_MS = 30 * 60 * 1e3;
|
|
16083
16085
|
var entries = /* @__PURE__ */ new Map();
|
|
16084
16086
|
function clearTimer(entry) {
|
|
16085
16087
|
if (entry.timer !== null) {
|
|
@@ -16089,6 +16091,32 @@ function clearTimer(entry) {
|
|
|
16089
16091
|
entry.controller?.abort();
|
|
16090
16092
|
entry.controller = null;
|
|
16091
16093
|
}
|
|
16094
|
+
function isIdle(entry) {
|
|
16095
|
+
return entry.dataListeners.size === 0 && entry.errorListeners.size === 0;
|
|
16096
|
+
}
|
|
16097
|
+
function pruneRetained(keepKey) {
|
|
16098
|
+
const now = Date.now();
|
|
16099
|
+
const idle = [];
|
|
16100
|
+
for (const [key, entry] of entries) {
|
|
16101
|
+
if (!isIdle(entry)) continue;
|
|
16102
|
+
if (entry.retainedAt != null && now - entry.retainedAt > RETAIN_TTL_MS) {
|
|
16103
|
+
entries.delete(key);
|
|
16104
|
+
continue;
|
|
16105
|
+
}
|
|
16106
|
+
idle.push([key, entry]);
|
|
16107
|
+
}
|
|
16108
|
+
if (idle.length <= MAX_RETAINED) return;
|
|
16109
|
+
idle.sort(
|
|
16110
|
+
(a, b) => (a[1].retainedAt ?? 0) - (b[1].retainedAt ?? 0)
|
|
16111
|
+
);
|
|
16112
|
+
let excess = idle.length - MAX_RETAINED;
|
|
16113
|
+
for (const [key] of idle) {
|
|
16114
|
+
if (excess <= 0) break;
|
|
16115
|
+
if (key === keepKey) continue;
|
|
16116
|
+
entries.delete(key);
|
|
16117
|
+
excess -= 1;
|
|
16118
|
+
}
|
|
16119
|
+
}
|
|
16092
16120
|
async function runPoll(key) {
|
|
16093
16121
|
const entry = entries.get(key);
|
|
16094
16122
|
if (!entry || entry.inFlight || entry.stopped) return;
|
|
@@ -16139,11 +16167,13 @@ function subscribeSharedPoll(config, onData, onError) {
|
|
|
16139
16167
|
lastData: void 0,
|
|
16140
16168
|
hasData: false,
|
|
16141
16169
|
stopped: false,
|
|
16142
|
-
inFlight: false
|
|
16170
|
+
inFlight: false,
|
|
16171
|
+
retainedAt: null
|
|
16143
16172
|
};
|
|
16144
16173
|
entries.set(key, entry);
|
|
16145
16174
|
}
|
|
16146
16175
|
const activeEntry = entry;
|
|
16176
|
+
activeEntry.retainedAt = null;
|
|
16147
16177
|
activeEntry.dataListeners.add(onData);
|
|
16148
16178
|
if (onError) activeEntry.errorListeners.add(onError);
|
|
16149
16179
|
if (activeEntry.hasData && activeEntry.lastData !== void 0) {
|
|
@@ -16161,6 +16191,11 @@ function subscribeSharedPoll(config, onData, onError) {
|
|
|
16161
16191
|
if (onError) activeEntry.errorListeners.delete(onError);
|
|
16162
16192
|
if (activeEntry.dataListeners.size === 0 && activeEntry.errorListeners.size === 0) {
|
|
16163
16193
|
clearTimer(activeEntry);
|
|
16194
|
+
if (activeEntry.hasData) {
|
|
16195
|
+
activeEntry.retainedAt = Date.now();
|
|
16196
|
+
pruneRetained(key);
|
|
16197
|
+
return;
|
|
16198
|
+
}
|
|
16164
16199
|
entries.delete(key);
|
|
16165
16200
|
}
|
|
16166
16201
|
};
|
|
@@ -16171,6 +16206,16 @@ function stopSharedPoll(key) {
|
|
|
16171
16206
|
entry.stopped = true;
|
|
16172
16207
|
clearTimer(entry);
|
|
16173
16208
|
}
|
|
16209
|
+
function getSharedPollLastData(key) {
|
|
16210
|
+
if (!key) return void 0;
|
|
16211
|
+
const entry = entries.get(key);
|
|
16212
|
+
if (!entry || !entry.hasData) return void 0;
|
|
16213
|
+
return entry.lastData;
|
|
16214
|
+
}
|
|
16215
|
+
function isSharedPollStopped(key) {
|
|
16216
|
+
if (!key) return false;
|
|
16217
|
+
return entries.get(key)?.stopped === true;
|
|
16218
|
+
}
|
|
16174
16219
|
function useSharedPoll(config, onData, onError) {
|
|
16175
16220
|
const fetcherRef = (0, import_react78.useRef)(config.fetcher);
|
|
16176
16221
|
fetcherRef.current = config.fetcher;
|
|
@@ -23152,6 +23197,15 @@ var formatTime = (seconds) => {
|
|
|
23152
23197
|
const minutes = Math.floor(seconds / 60);
|
|
23153
23198
|
return minutes >= 1 ? `${minutes} min remaining...` : `${seconds} sec remaining...`;
|
|
23154
23199
|
};
|
|
23200
|
+
function isTerminalStatus(status) {
|
|
23201
|
+
return status === "completed" || status === "complete" || status === "failed";
|
|
23202
|
+
}
|
|
23203
|
+
function versionPollKey(sessionId, version, validated) {
|
|
23204
|
+
return `creator:versions:${sessionId}:${version ?? "latest"}:${validated ? 1 : 0}`;
|
|
23205
|
+
}
|
|
23206
|
+
function statusPollKey(sessionId, version) {
|
|
23207
|
+
return `creator:status:${sessionId}:${version}`;
|
|
23208
|
+
}
|
|
23155
23209
|
function useCreatorWidgetPolling({
|
|
23156
23210
|
sessionId,
|
|
23157
23211
|
currentVersion,
|
|
@@ -23166,17 +23220,53 @@ function useCreatorWidgetPolling({
|
|
|
23166
23220
|
() => ({ ...DEFAULT_POLLING_CONFIG, ...pollingConfig }),
|
|
23167
23221
|
[pollingConfig]
|
|
23168
23222
|
);
|
|
23169
|
-
const
|
|
23170
|
-
|
|
23223
|
+
const hydrated = (0, import_react94.useMemo)(() => {
|
|
23224
|
+
if (!sessionId) {
|
|
23225
|
+
return {
|
|
23226
|
+
versionData: null,
|
|
23227
|
+
statusPayload: void 0,
|
|
23228
|
+
activeVersion: currentVersion
|
|
23229
|
+
};
|
|
23230
|
+
}
|
|
23231
|
+
const versionHint = currentVersion;
|
|
23232
|
+
const cachedVersion = getSharedPollLastData(
|
|
23233
|
+
versionPollKey(sessionId, versionHint, true)
|
|
23234
|
+
) ?? getSharedPollLastData(
|
|
23235
|
+
versionPollKey(sessionId, versionHint, false)
|
|
23236
|
+
);
|
|
23237
|
+
const activeVersion2 = versionHint ?? cachedVersion?.currentVersion ?? void 0;
|
|
23238
|
+
const statusPayload = activeVersion2 != null ? getSharedPollLastData(
|
|
23239
|
+
statusPollKey(sessionId, activeVersion2)
|
|
23240
|
+
) : void 0;
|
|
23241
|
+
return { versionData: cachedVersion ?? null, statusPayload, activeVersion: activeVersion2 };
|
|
23242
|
+
}, [sessionId, currentVersion]);
|
|
23243
|
+
const hydratedStatus = hydrated.statusPayload?.status?.status;
|
|
23244
|
+
const hydratedTerminal = isTerminalStatus(hydratedStatus);
|
|
23245
|
+
const [versionData, setVersionData] = (0, import_react94.useState)(
|
|
23246
|
+
hydrated.versionData
|
|
23247
|
+
);
|
|
23248
|
+
const [totalVersions, setTotalVersions] = (0, import_react94.useState)(
|
|
23249
|
+
hydrated.versionData?.totalVersions || 0
|
|
23250
|
+
);
|
|
23171
23251
|
const [selectedVersion, setSelectedVersion] = (0, import_react94.useState)();
|
|
23172
|
-
const [isLoadingVersion, setIsLoadingVersion] = (0, import_react94.useState)(
|
|
23173
|
-
const [isValidationComplete, setIsValidationComplete] = (0, import_react94.useState)(
|
|
23174
|
-
|
|
23175
|
-
|
|
23252
|
+
const [isLoadingVersion, setIsLoadingVersion] = (0, import_react94.useState)(!hydrated.versionData);
|
|
23253
|
+
const [isValidationComplete, setIsValidationComplete] = (0, import_react94.useState)(
|
|
23254
|
+
hydratedTerminal && hydratedStatus !== "failed"
|
|
23255
|
+
);
|
|
23256
|
+
const [versionStatus, setVersionStatus] = (0, import_react94.useState)(
|
|
23257
|
+
hydratedStatus || (hydrated.versionData ? "in-progress" : "checking")
|
|
23258
|
+
);
|
|
23259
|
+
const [statusDetails, setStatusDetails] = (0, import_react94.useState)(
|
|
23260
|
+
hydrated.statusPayload?.status
|
|
23261
|
+
);
|
|
23176
23262
|
const [timeDisplay, setTimeDisplay] = (0, import_react94.useState)("");
|
|
23177
|
-
const [loadingStatus, setLoadingStatus] = (0, import_react94.useState)(
|
|
23263
|
+
const [loadingStatus, setLoadingStatus] = (0, import_react94.useState)(
|
|
23264
|
+
!(hydrated.versionData && hydratedTerminal)
|
|
23265
|
+
);
|
|
23178
23266
|
const remainingTimeRef = (0, import_react94.useRef)(0);
|
|
23179
23267
|
const countdownRef = (0, import_react94.useRef)(null);
|
|
23268
|
+
const versionDataRef = (0, import_react94.useRef)(versionData);
|
|
23269
|
+
versionDataRef.current = versionData;
|
|
23180
23270
|
const requestedVersion = selectedVersion ?? currentVersion ?? versionData?.currentVersion;
|
|
23181
23271
|
const updateStatus = (0, import_react94.useCallback)(
|
|
23182
23272
|
(status) => {
|
|
@@ -23185,13 +23275,13 @@ function useCreatorWidgetPolling({
|
|
|
23185
23275
|
},
|
|
23186
23276
|
[onStatusChange]
|
|
23187
23277
|
);
|
|
23188
|
-
const versionKey = sessionId ?
|
|
23278
|
+
const versionKey = sessionId ? versionPollKey(sessionId, requestedVersion, isValidationComplete) : null;
|
|
23189
23279
|
useSharedPoll(
|
|
23190
23280
|
{
|
|
23191
23281
|
key: versionKey,
|
|
23192
23282
|
intervalMs: config.pollInterval,
|
|
23193
23283
|
fetcher: async () => {
|
|
23194
|
-
if (!
|
|
23284
|
+
if (!versionDataRef.current) setIsLoadingVersion(true);
|
|
23195
23285
|
return fetchVersions({
|
|
23196
23286
|
sessionId,
|
|
23197
23287
|
version: requestedVersion,
|
|
@@ -23215,10 +23305,10 @@ function useCreatorWidgetPolling({
|
|
|
23215
23305
|
}
|
|
23216
23306
|
);
|
|
23217
23307
|
const activeVersion = selectedVersion ?? requestedVersion;
|
|
23218
|
-
const statusKey = sessionId && activeVersion != null ?
|
|
23308
|
+
const statusKey = sessionId && activeVersion != null ? statusPollKey(sessionId, activeVersion) : null;
|
|
23219
23309
|
const errorCountRef = (0, import_react94.useRef)(0);
|
|
23220
23310
|
const deadlineRef = (0, import_react94.useRef)(0);
|
|
23221
|
-
const doneRef = (0, import_react94.useRef)(
|
|
23311
|
+
const doneRef = (0, import_react94.useRef)(hydratedTerminal);
|
|
23222
23312
|
const stopCountdown = (0, import_react94.useCallback)(() => {
|
|
23223
23313
|
if (countdownRef.current) {
|
|
23224
23314
|
clearInterval(countdownRef.current);
|
|
@@ -23228,13 +23318,28 @@ function useCreatorWidgetPolling({
|
|
|
23228
23318
|
}, []);
|
|
23229
23319
|
(0, import_react94.useEffect)(() => {
|
|
23230
23320
|
if (statusKey == null) return;
|
|
23321
|
+
const cached = getSharedPollLastData(statusKey);
|
|
23322
|
+
const cachedStatus = cached?.status?.status;
|
|
23323
|
+
if (isTerminalStatus(cachedStatus) && isSharedPollStopped(statusKey)) {
|
|
23324
|
+
setStatusDetails(cached?.status);
|
|
23325
|
+
setVersionStatus(cachedStatus);
|
|
23326
|
+
onStatusChange?.(cachedStatus);
|
|
23327
|
+
if (cachedStatus === "completed" || cachedStatus === "complete") {
|
|
23328
|
+
setIsValidationComplete(true);
|
|
23329
|
+
}
|
|
23330
|
+
setLoadingStatus(false);
|
|
23331
|
+
doneRef.current = true;
|
|
23332
|
+
errorCountRef.current = 0;
|
|
23333
|
+
stopCountdown();
|
|
23334
|
+
return;
|
|
23335
|
+
}
|
|
23231
23336
|
setLoadingStatus(true);
|
|
23232
23337
|
setStatusDetails(void 0);
|
|
23233
23338
|
setVersionStatus("checking");
|
|
23234
23339
|
errorCountRef.current = 0;
|
|
23235
23340
|
doneRef.current = false;
|
|
23236
23341
|
deadlineRef.current = Date.now() + config.maxDuration;
|
|
23237
|
-
const creatorLength2 =
|
|
23342
|
+
const creatorLength2 = versionDataRef.current?.length || 0;
|
|
23238
23343
|
remainingTimeRef.current = creatorLength2 > 0 ? creatorLength2 * config.secondsPerCreator : 60;
|
|
23239
23344
|
setTimeDisplay(formatTime(remainingTimeRef.current));
|
|
23240
23345
|
countdownRef.current = setInterval(() => {
|
|
@@ -23256,7 +23361,7 @@ function useCreatorWidgetPolling({
|
|
|
23256
23361
|
shouldContinue: (data) => {
|
|
23257
23362
|
if (Date.now() >= deadlineRef.current) return false;
|
|
23258
23363
|
const s = data?.status?.status;
|
|
23259
|
-
return !(s
|
|
23364
|
+
return !isTerminalStatus(s);
|
|
23260
23365
|
}
|
|
23261
23366
|
},
|
|
23262
23367
|
(data) => {
|
|
@@ -23402,6 +23507,185 @@ var CreatorWidget = (0, import_react95.memo)(CreatorWidgetInner);
|
|
|
23402
23507
|
|
|
23403
23508
|
// src/molecules/analytics/AnalyticsChart.tsx
|
|
23404
23509
|
var import_react96 = require("react");
|
|
23510
|
+
|
|
23511
|
+
// src/molecules/analytics/buildOptions.ts
|
|
23512
|
+
function deepMerge(base, override) {
|
|
23513
|
+
const out = Array.isArray(base) ? [...base] : { ...base };
|
|
23514
|
+
for (const key of Object.keys(override)) {
|
|
23515
|
+
const o = override[key];
|
|
23516
|
+
const b = out[key];
|
|
23517
|
+
if (o && typeof o === "object" && !Array.isArray(o) && b && typeof b === "object" && !Array.isArray(b)) {
|
|
23518
|
+
out[key] = deepMerge(b, o);
|
|
23519
|
+
} else if (o !== void 0) {
|
|
23520
|
+
out[key] = o;
|
|
23521
|
+
}
|
|
23522
|
+
}
|
|
23523
|
+
return out;
|
|
23524
|
+
}
|
|
23525
|
+
function highchartsType(type) {
|
|
23526
|
+
if (type === "donut") return "pie";
|
|
23527
|
+
return type;
|
|
23528
|
+
}
|
|
23529
|
+
function buildAxis(axis, fallbackCategories) {
|
|
23530
|
+
const cfg = {};
|
|
23531
|
+
if (!axis) {
|
|
23532
|
+
if (fallbackCategories) cfg.categories = fallbackCategories;
|
|
23533
|
+
return cfg;
|
|
23534
|
+
}
|
|
23535
|
+
if (axis.title) cfg.title = { text: axis.title };
|
|
23536
|
+
if (axis.type) cfg.type = axis.type;
|
|
23537
|
+
if (axis.categories || fallbackCategories) cfg.categories = axis.categories ?? fallbackCategories;
|
|
23538
|
+
if (axis.format) cfg.labels = { format: axis.format };
|
|
23539
|
+
if (typeof axis.min === "number") cfg.min = axis.min;
|
|
23540
|
+
if (typeof axis.max === "number") cfg.max = axis.max;
|
|
23541
|
+
if (axis.opposite) cfg.opposite = true;
|
|
23542
|
+
return cfg;
|
|
23543
|
+
}
|
|
23544
|
+
function resolveStacking(stacked) {
|
|
23545
|
+
if (stacked === true || stacked === "normal") return "normal";
|
|
23546
|
+
if (stacked === "percent") return "percent";
|
|
23547
|
+
return void 0;
|
|
23548
|
+
}
|
|
23549
|
+
function buildChartOptions(config, palette) {
|
|
23550
|
+
const hcType = highchartsType(config.type);
|
|
23551
|
+
const isCircular = config.type === "pie" || config.type === "donut";
|
|
23552
|
+
const seriesColors = config.colors ?? palette.series;
|
|
23553
|
+
const safeSeries = Array.isArray(config.series) ? config.series : [];
|
|
23554
|
+
const options = {
|
|
23555
|
+
chart: { type: hcType, ...config.height && { height: config.height } },
|
|
23556
|
+
title: { text: config.title ?? void 0 },
|
|
23557
|
+
subtitle: { text: config.subtitle ?? void 0 },
|
|
23558
|
+
series: safeSeries.map((s, i) => ({
|
|
23559
|
+
name: s.name,
|
|
23560
|
+
data: s.data,
|
|
23561
|
+
...s.type && { type: highchartsType(s.type) },
|
|
23562
|
+
...s.stack && { stack: s.stack },
|
|
23563
|
+
...typeof s.yAxis === "number" && { yAxis: s.yAxis },
|
|
23564
|
+
color: s.color ?? seriesColors[i % seriesColors.length]
|
|
23565
|
+
})),
|
|
23566
|
+
legend: { enabled: config.legend ?? (safeSeries.length > 1 || isCircular) }
|
|
23567
|
+
};
|
|
23568
|
+
if (config.colors) options.colors = config.colors;
|
|
23569
|
+
if (!isCircular && config.type !== "funnel") {
|
|
23570
|
+
options.xAxis = buildAxis(config.xAxis, config.categories);
|
|
23571
|
+
const yAxes = Array.isArray(config.yAxis) ? config.yAxis : [config.yAxis];
|
|
23572
|
+
options.yAxis = yAxes.map((a) => buildAxis(a));
|
|
23573
|
+
if (options.yAxis.length === 1) options.yAxis = options.yAxis[0];
|
|
23574
|
+
}
|
|
23575
|
+
if (config.tooltip) {
|
|
23576
|
+
options.tooltip = {
|
|
23577
|
+
...config.tooltip.shared !== void 0 && { shared: config.tooltip.shared },
|
|
23578
|
+
...config.tooltip.valuePrefix && { valuePrefix: config.tooltip.valuePrefix },
|
|
23579
|
+
...config.tooltip.valueSuffix && { valueSuffix: config.tooltip.valueSuffix },
|
|
23580
|
+
...config.tooltip.pointFormat && { pointFormat: config.tooltip.pointFormat }
|
|
23581
|
+
};
|
|
23582
|
+
}
|
|
23583
|
+
const stacking = resolveStacking(config.stacked);
|
|
23584
|
+
const dataLabels = config.dataLabels === true ? { enabled: true } : config.dataLabels && typeof config.dataLabels === "object" ? { enabled: true, ...config.dataLabels } : void 0;
|
|
23585
|
+
const plotOptions = {};
|
|
23586
|
+
if (stacking || dataLabels) {
|
|
23587
|
+
plotOptions.series = {
|
|
23588
|
+
...stacking && { stacking },
|
|
23589
|
+
...dataLabels && { dataLabels }
|
|
23590
|
+
};
|
|
23591
|
+
}
|
|
23592
|
+
if (config.type === "donut") {
|
|
23593
|
+
plotOptions.pie = {
|
|
23594
|
+
innerSize: "55%",
|
|
23595
|
+
dataLabels: dataLabels ?? {
|
|
23596
|
+
enabled: true,
|
|
23597
|
+
format: "<b>{point.name}</b>: {point.percentage:.1f}%"
|
|
23598
|
+
}
|
|
23599
|
+
};
|
|
23600
|
+
} else if (config.type === "pie") {
|
|
23601
|
+
plotOptions.pie = {
|
|
23602
|
+
dataLabels: dataLabels ?? {
|
|
23603
|
+
enabled: true,
|
|
23604
|
+
format: "<b>{point.name}</b>: {point.percentage:.1f}%"
|
|
23605
|
+
}
|
|
23606
|
+
};
|
|
23607
|
+
} else if (config.type === "funnel") {
|
|
23608
|
+
plotOptions.funnel = {
|
|
23609
|
+
neckWidth: "30%",
|
|
23610
|
+
neckHeight: "25%",
|
|
23611
|
+
dataLabels: dataLabels ?? { enabled: true, format: "<b>{point.name}</b> ({point.y:,.0f})" }
|
|
23612
|
+
};
|
|
23613
|
+
}
|
|
23614
|
+
if (Object.keys(plotOptions).length) options.plotOptions = plotOptions;
|
|
23615
|
+
return options;
|
|
23616
|
+
}
|
|
23617
|
+
|
|
23618
|
+
// src/molecules/analytics/highchartsTheme.ts
|
|
23619
|
+
var PXENGINE_SERIES_COLORS = [
|
|
23620
|
+
"#6366f1",
|
|
23621
|
+
// indigo
|
|
23622
|
+
"#10b981",
|
|
23623
|
+
// emerald
|
|
23624
|
+
"#f59e0b",
|
|
23625
|
+
// amber
|
|
23626
|
+
"#ec4899",
|
|
23627
|
+
// pink
|
|
23628
|
+
"#8b5cf6",
|
|
23629
|
+
// violet
|
|
23630
|
+
"#06b6d4",
|
|
23631
|
+
// cyan
|
|
23632
|
+
"#f43f5e",
|
|
23633
|
+
// rose
|
|
23634
|
+
"#84cc16",
|
|
23635
|
+
// lime
|
|
23636
|
+
"#3b82f6",
|
|
23637
|
+
// blue
|
|
23638
|
+
"#f97316"
|
|
23639
|
+
// orange
|
|
23640
|
+
];
|
|
23641
|
+
var DARK_PALETTE = {
|
|
23642
|
+
text: "#e5e7eb",
|
|
23643
|
+
textMuted: "#9ca3af",
|
|
23644
|
+
grid: "rgba(255,255,255,0.08)",
|
|
23645
|
+
border: "rgba(255,255,255,0.12)",
|
|
23646
|
+
background: "transparent",
|
|
23647
|
+
series: PXENGINE_SERIES_COLORS,
|
|
23648
|
+
tooltipBg: "rgba(17,24,39,0.95)",
|
|
23649
|
+
tooltipText: "#f9fafb"
|
|
23650
|
+
};
|
|
23651
|
+
var LIGHT_PALETTE = {
|
|
23652
|
+
text: "#1f2937",
|
|
23653
|
+
textMuted: "#6b7280",
|
|
23654
|
+
grid: "rgba(0,0,0,0.06)",
|
|
23655
|
+
border: "rgba(0,0,0,0.10)",
|
|
23656
|
+
background: "transparent",
|
|
23657
|
+
series: PXENGINE_SERIES_COLORS,
|
|
23658
|
+
tooltipBg: "rgba(255,255,255,0.98)",
|
|
23659
|
+
tooltipText: "#111827"
|
|
23660
|
+
};
|
|
23661
|
+
function resolveColorMode(mode = "auto") {
|
|
23662
|
+
if (mode === "light" || mode === "dark") return mode;
|
|
23663
|
+
if (typeof document !== "undefined") {
|
|
23664
|
+
if (document.documentElement.classList.contains("dark")) return "dark";
|
|
23665
|
+
if (typeof window !== "undefined" && window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches) {
|
|
23666
|
+
return "dark";
|
|
23667
|
+
}
|
|
23668
|
+
return "light";
|
|
23669
|
+
}
|
|
23670
|
+
return "dark";
|
|
23671
|
+
}
|
|
23672
|
+
function buildChartPalette(theme, mode = "auto") {
|
|
23673
|
+
const base = resolveColorMode(mode) === "dark" ? DARK_PALETTE : LIGHT_PALETTE;
|
|
23674
|
+
if (!theme) return base;
|
|
23675
|
+
const series = theme.accent ? [theme.accent, ...base.series.filter((c) => c.toLowerCase() !== theme.accent.toLowerCase())] : base.series;
|
|
23676
|
+
return {
|
|
23677
|
+
...base,
|
|
23678
|
+
...theme.text && { text: theme.text },
|
|
23679
|
+
...theme.textMuted && { textMuted: theme.textMuted },
|
|
23680
|
+
...theme.border && { border: theme.border, grid: theme.border },
|
|
23681
|
+
...theme.surface && { tooltipBg: theme.surface },
|
|
23682
|
+
...theme.text && { tooltipText: theme.text },
|
|
23683
|
+
...theme.fontFamily && { fontFamily: theme.fontFamily },
|
|
23684
|
+
series
|
|
23685
|
+
};
|
|
23686
|
+
}
|
|
23687
|
+
|
|
23688
|
+
// src/molecules/analytics/AnalyticsChart.tsx
|
|
23405
23689
|
var import_jsx_runtime179 = require("react/jsx-runtime");
|
|
23406
23690
|
function getCSSVar(name) {
|
|
23407
23691
|
if (typeof document === "undefined") return "";
|
|
@@ -23438,6 +23722,30 @@ function stripNulls(val) {
|
|
|
23438
23722
|
}
|
|
23439
23723
|
return val;
|
|
23440
23724
|
}
|
|
23725
|
+
function resolveDeclarativeConfig(props) {
|
|
23726
|
+
if (props.chartConfig) {
|
|
23727
|
+
return {
|
|
23728
|
+
...props.chartConfig,
|
|
23729
|
+
...props.height != null && !props.chartConfig.height ? { height: props.height } : {}
|
|
23730
|
+
};
|
|
23731
|
+
}
|
|
23732
|
+
if (!props.chartType) return null;
|
|
23733
|
+
return {
|
|
23734
|
+
type: props.chartType,
|
|
23735
|
+
title: props.title,
|
|
23736
|
+
subtitle: props.subtitle,
|
|
23737
|
+
series: props.series ?? [],
|
|
23738
|
+
categories: props.categories,
|
|
23739
|
+
xAxis: props.xAxis,
|
|
23740
|
+
yAxis: props.yAxis,
|
|
23741
|
+
colors: props.colors,
|
|
23742
|
+
stacked: props.stacked,
|
|
23743
|
+
legend: props.legend,
|
|
23744
|
+
tooltip: props.tooltip,
|
|
23745
|
+
dataLabels: props.dataLabels,
|
|
23746
|
+
height: props.height
|
|
23747
|
+
};
|
|
23748
|
+
}
|
|
23441
23749
|
var hcSingleton = null;
|
|
23442
23750
|
var hcLoadPromise = null;
|
|
23443
23751
|
function loadHighcharts() {
|
|
@@ -23506,9 +23814,25 @@ function buildTheme(height) {
|
|
|
23506
23814
|
}
|
|
23507
23815
|
function AnalyticsChart({
|
|
23508
23816
|
config: configProp,
|
|
23817
|
+
chartConfig,
|
|
23818
|
+
chartType,
|
|
23819
|
+
series,
|
|
23820
|
+
categories,
|
|
23821
|
+
xAxis,
|
|
23822
|
+
yAxis,
|
|
23823
|
+
colors,
|
|
23824
|
+
stacked,
|
|
23825
|
+
legend,
|
|
23826
|
+
tooltip,
|
|
23827
|
+
dataLabels,
|
|
23828
|
+
extraOptions,
|
|
23509
23829
|
chartId,
|
|
23510
23830
|
apiBase = "",
|
|
23511
23831
|
authToken,
|
|
23832
|
+
title,
|
|
23833
|
+
subtitle,
|
|
23834
|
+
theme,
|
|
23835
|
+
mode = "auto",
|
|
23512
23836
|
height = 400,
|
|
23513
23837
|
className,
|
|
23514
23838
|
loading: loadingProp,
|
|
@@ -23520,11 +23844,51 @@ function AnalyticsChart({
|
|
|
23520
23844
|
const [fetchError, setFetchError] = (0, import_react96.useState)(null);
|
|
23521
23845
|
const containerRef = (0, import_react96.useRef)(null);
|
|
23522
23846
|
const chartRef = (0, import_react96.useRef)(null);
|
|
23847
|
+
const declarative = (0, import_react96.useMemo)(
|
|
23848
|
+
() => resolveDeclarativeConfig({
|
|
23849
|
+
chartConfig,
|
|
23850
|
+
chartType,
|
|
23851
|
+
title,
|
|
23852
|
+
subtitle,
|
|
23853
|
+
series,
|
|
23854
|
+
categories,
|
|
23855
|
+
xAxis,
|
|
23856
|
+
yAxis,
|
|
23857
|
+
colors,
|
|
23858
|
+
stacked,
|
|
23859
|
+
legend,
|
|
23860
|
+
tooltip,
|
|
23861
|
+
dataLabels,
|
|
23862
|
+
height
|
|
23863
|
+
}),
|
|
23864
|
+
[
|
|
23865
|
+
chartConfig,
|
|
23866
|
+
chartType,
|
|
23867
|
+
title,
|
|
23868
|
+
subtitle,
|
|
23869
|
+
series,
|
|
23870
|
+
categories,
|
|
23871
|
+
xAxis,
|
|
23872
|
+
yAxis,
|
|
23873
|
+
colors,
|
|
23874
|
+
stacked,
|
|
23875
|
+
legend,
|
|
23876
|
+
tooltip,
|
|
23877
|
+
dataLabels,
|
|
23878
|
+
height
|
|
23879
|
+
]
|
|
23880
|
+
);
|
|
23881
|
+
const builtConfig = (0, import_react96.useMemo)(() => {
|
|
23882
|
+
if (!declarative) return null;
|
|
23883
|
+
const palette = buildChartPalette(theme, mode);
|
|
23884
|
+
const options = buildChartOptions(declarative, palette);
|
|
23885
|
+
return extraOptions ? deepMerge(options, extraOptions) : options;
|
|
23886
|
+
}, [declarative, theme, mode, extraOptions]);
|
|
23523
23887
|
(0, import_react96.useEffect)(() => {
|
|
23524
23888
|
setMounted(true);
|
|
23525
23889
|
}, []);
|
|
23526
23890
|
(0, import_react96.useEffect)(() => {
|
|
23527
|
-
if (!chartId || configProp) return;
|
|
23891
|
+
if (!chartId || configProp || builtConfig) return;
|
|
23528
23892
|
let cancelled = false;
|
|
23529
23893
|
setFetching(true);
|
|
23530
23894
|
setFetchError(null);
|
|
@@ -23543,8 +23907,8 @@ function AnalyticsChart({
|
|
|
23543
23907
|
return () => {
|
|
23544
23908
|
cancelled = true;
|
|
23545
23909
|
};
|
|
23546
|
-
}, [chartId, apiBase, authToken, configProp]);
|
|
23547
|
-
const activeConfig = configProp ?? fetchedConfig;
|
|
23910
|
+
}, [chartId, apiBase, authToken, configProp, builtConfig]);
|
|
23911
|
+
const activeConfig = configProp ?? builtConfig ?? fetchedConfig;
|
|
23548
23912
|
(0, import_react96.useEffect)(() => {
|
|
23549
23913
|
if (!mounted || !activeConfig || !containerRef.current) return;
|
|
23550
23914
|
const container = containerRef.current;
|