pxengine 0.1.120 → 0.1.122
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.mjs
CHANGED
|
@@ -15748,6 +15748,8 @@ import { useCallback as useCallback4, useEffect as useEffect7, useRef as useRef8
|
|
|
15748
15748
|
|
|
15749
15749
|
// src/lib/shared-poll.ts
|
|
15750
15750
|
import { useEffect as useEffect6, useRef as useRef7 } from "react";
|
|
15751
|
+
var MAX_RETAINED = 50;
|
|
15752
|
+
var RETAIN_TTL_MS = 30 * 60 * 1e3;
|
|
15751
15753
|
var entries = /* @__PURE__ */ new Map();
|
|
15752
15754
|
function clearTimer(entry) {
|
|
15753
15755
|
if (entry.timer !== null) {
|
|
@@ -15757,6 +15759,32 @@ function clearTimer(entry) {
|
|
|
15757
15759
|
entry.controller?.abort();
|
|
15758
15760
|
entry.controller = null;
|
|
15759
15761
|
}
|
|
15762
|
+
function isIdle(entry) {
|
|
15763
|
+
return entry.dataListeners.size === 0 && entry.errorListeners.size === 0;
|
|
15764
|
+
}
|
|
15765
|
+
function pruneRetained(keepKey) {
|
|
15766
|
+
const now = Date.now();
|
|
15767
|
+
const idle = [];
|
|
15768
|
+
for (const [key, entry] of entries) {
|
|
15769
|
+
if (!isIdle(entry)) continue;
|
|
15770
|
+
if (entry.retainedAt != null && now - entry.retainedAt > RETAIN_TTL_MS) {
|
|
15771
|
+
entries.delete(key);
|
|
15772
|
+
continue;
|
|
15773
|
+
}
|
|
15774
|
+
idle.push([key, entry]);
|
|
15775
|
+
}
|
|
15776
|
+
if (idle.length <= MAX_RETAINED) return;
|
|
15777
|
+
idle.sort(
|
|
15778
|
+
(a, b) => (a[1].retainedAt ?? 0) - (b[1].retainedAt ?? 0)
|
|
15779
|
+
);
|
|
15780
|
+
let excess = idle.length - MAX_RETAINED;
|
|
15781
|
+
for (const [key] of idle) {
|
|
15782
|
+
if (excess <= 0) break;
|
|
15783
|
+
if (key === keepKey) continue;
|
|
15784
|
+
entries.delete(key);
|
|
15785
|
+
excess -= 1;
|
|
15786
|
+
}
|
|
15787
|
+
}
|
|
15760
15788
|
async function runPoll(key) {
|
|
15761
15789
|
const entry = entries.get(key);
|
|
15762
15790
|
if (!entry || entry.inFlight || entry.stopped) return;
|
|
@@ -15807,11 +15835,13 @@ function subscribeSharedPoll(config, onData, onError) {
|
|
|
15807
15835
|
lastData: void 0,
|
|
15808
15836
|
hasData: false,
|
|
15809
15837
|
stopped: false,
|
|
15810
|
-
inFlight: false
|
|
15838
|
+
inFlight: false,
|
|
15839
|
+
retainedAt: null
|
|
15811
15840
|
};
|
|
15812
15841
|
entries.set(key, entry);
|
|
15813
15842
|
}
|
|
15814
15843
|
const activeEntry = entry;
|
|
15844
|
+
activeEntry.retainedAt = null;
|
|
15815
15845
|
activeEntry.dataListeners.add(onData);
|
|
15816
15846
|
if (onError) activeEntry.errorListeners.add(onError);
|
|
15817
15847
|
if (activeEntry.hasData && activeEntry.lastData !== void 0) {
|
|
@@ -15829,6 +15859,11 @@ function subscribeSharedPoll(config, onData, onError) {
|
|
|
15829
15859
|
if (onError) activeEntry.errorListeners.delete(onError);
|
|
15830
15860
|
if (activeEntry.dataListeners.size === 0 && activeEntry.errorListeners.size === 0) {
|
|
15831
15861
|
clearTimer(activeEntry);
|
|
15862
|
+
if (activeEntry.hasData) {
|
|
15863
|
+
activeEntry.retainedAt = Date.now();
|
|
15864
|
+
pruneRetained(key);
|
|
15865
|
+
return;
|
|
15866
|
+
}
|
|
15832
15867
|
entries.delete(key);
|
|
15833
15868
|
}
|
|
15834
15869
|
};
|
|
@@ -15839,6 +15874,16 @@ function stopSharedPoll(key) {
|
|
|
15839
15874
|
entry.stopped = true;
|
|
15840
15875
|
clearTimer(entry);
|
|
15841
15876
|
}
|
|
15877
|
+
function getSharedPollLastData(key) {
|
|
15878
|
+
if (!key) return void 0;
|
|
15879
|
+
const entry = entries.get(key);
|
|
15880
|
+
if (!entry || !entry.hasData) return void 0;
|
|
15881
|
+
return entry.lastData;
|
|
15882
|
+
}
|
|
15883
|
+
function isSharedPollStopped(key) {
|
|
15884
|
+
if (!key) return false;
|
|
15885
|
+
return entries.get(key)?.stopped === true;
|
|
15886
|
+
}
|
|
15842
15887
|
function useSharedPoll(config, onData, onError) {
|
|
15843
15888
|
const fetcherRef = useRef7(config.fetcher);
|
|
15844
15889
|
fetcherRef.current = config.fetcher;
|
|
@@ -22820,6 +22865,15 @@ var formatTime = (seconds) => {
|
|
|
22820
22865
|
const minutes = Math.floor(seconds / 60);
|
|
22821
22866
|
return minutes >= 1 ? `${minutes} min remaining...` : `${seconds} sec remaining...`;
|
|
22822
22867
|
};
|
|
22868
|
+
function isTerminalStatus(status) {
|
|
22869
|
+
return status === "completed" || status === "complete" || status === "failed";
|
|
22870
|
+
}
|
|
22871
|
+
function versionPollKey(sessionId, version, validated) {
|
|
22872
|
+
return `creator:versions:${sessionId}:${version ?? "latest"}:${validated ? 1 : 0}`;
|
|
22873
|
+
}
|
|
22874
|
+
function statusPollKey(sessionId, version) {
|
|
22875
|
+
return `creator:status:${sessionId}:${version}`;
|
|
22876
|
+
}
|
|
22823
22877
|
function useCreatorWidgetPolling({
|
|
22824
22878
|
sessionId,
|
|
22825
22879
|
currentVersion,
|
|
@@ -22834,17 +22888,53 @@ function useCreatorWidgetPolling({
|
|
|
22834
22888
|
() => ({ ...DEFAULT_POLLING_CONFIG, ...pollingConfig }),
|
|
22835
22889
|
[pollingConfig]
|
|
22836
22890
|
);
|
|
22837
|
-
const
|
|
22838
|
-
|
|
22891
|
+
const hydrated = useMemo11(() => {
|
|
22892
|
+
if (!sessionId) {
|
|
22893
|
+
return {
|
|
22894
|
+
versionData: null,
|
|
22895
|
+
statusPayload: void 0,
|
|
22896
|
+
activeVersion: currentVersion
|
|
22897
|
+
};
|
|
22898
|
+
}
|
|
22899
|
+
const versionHint = currentVersion;
|
|
22900
|
+
const cachedVersion = getSharedPollLastData(
|
|
22901
|
+
versionPollKey(sessionId, versionHint, true)
|
|
22902
|
+
) ?? getSharedPollLastData(
|
|
22903
|
+
versionPollKey(sessionId, versionHint, false)
|
|
22904
|
+
);
|
|
22905
|
+
const activeVersion2 = versionHint ?? cachedVersion?.currentVersion ?? void 0;
|
|
22906
|
+
const statusPayload = activeVersion2 != null ? getSharedPollLastData(
|
|
22907
|
+
statusPollKey(sessionId, activeVersion2)
|
|
22908
|
+
) : void 0;
|
|
22909
|
+
return { versionData: cachedVersion ?? null, statusPayload, activeVersion: activeVersion2 };
|
|
22910
|
+
}, [sessionId, currentVersion]);
|
|
22911
|
+
const hydratedStatus = hydrated.statusPayload?.status?.status;
|
|
22912
|
+
const hydratedTerminal = isTerminalStatus(hydratedStatus);
|
|
22913
|
+
const [versionData, setVersionData] = useState21(
|
|
22914
|
+
hydrated.versionData
|
|
22915
|
+
);
|
|
22916
|
+
const [totalVersions, setTotalVersions] = useState21(
|
|
22917
|
+
hydrated.versionData?.totalVersions || 0
|
|
22918
|
+
);
|
|
22839
22919
|
const [selectedVersion, setSelectedVersion] = useState21();
|
|
22840
|
-
const [isLoadingVersion, setIsLoadingVersion] = useState21(
|
|
22841
|
-
const [isValidationComplete, setIsValidationComplete] = useState21(
|
|
22842
|
-
|
|
22843
|
-
|
|
22920
|
+
const [isLoadingVersion, setIsLoadingVersion] = useState21(!hydrated.versionData);
|
|
22921
|
+
const [isValidationComplete, setIsValidationComplete] = useState21(
|
|
22922
|
+
hydratedTerminal && hydratedStatus !== "failed"
|
|
22923
|
+
);
|
|
22924
|
+
const [versionStatus, setVersionStatus] = useState21(
|
|
22925
|
+
hydratedStatus || (hydrated.versionData ? "in-progress" : "checking")
|
|
22926
|
+
);
|
|
22927
|
+
const [statusDetails, setStatusDetails] = useState21(
|
|
22928
|
+
hydrated.statusPayload?.status
|
|
22929
|
+
);
|
|
22844
22930
|
const [timeDisplay, setTimeDisplay] = useState21("");
|
|
22845
|
-
const [loadingStatus, setLoadingStatus] = useState21(
|
|
22931
|
+
const [loadingStatus, setLoadingStatus] = useState21(
|
|
22932
|
+
!(hydrated.versionData && hydratedTerminal)
|
|
22933
|
+
);
|
|
22846
22934
|
const remainingTimeRef = useRef13(0);
|
|
22847
22935
|
const countdownRef = useRef13(null);
|
|
22936
|
+
const versionDataRef = useRef13(versionData);
|
|
22937
|
+
versionDataRef.current = versionData;
|
|
22848
22938
|
const requestedVersion = selectedVersion ?? currentVersion ?? versionData?.currentVersion;
|
|
22849
22939
|
const updateStatus = useCallback8(
|
|
22850
22940
|
(status) => {
|
|
@@ -22853,13 +22943,13 @@ function useCreatorWidgetPolling({
|
|
|
22853
22943
|
},
|
|
22854
22944
|
[onStatusChange]
|
|
22855
22945
|
);
|
|
22856
|
-
const versionKey = sessionId ?
|
|
22946
|
+
const versionKey = sessionId ? versionPollKey(sessionId, requestedVersion, isValidationComplete) : null;
|
|
22857
22947
|
useSharedPoll(
|
|
22858
22948
|
{
|
|
22859
22949
|
key: versionKey,
|
|
22860
22950
|
intervalMs: config.pollInterval,
|
|
22861
22951
|
fetcher: async () => {
|
|
22862
|
-
if (!
|
|
22952
|
+
if (!versionDataRef.current) setIsLoadingVersion(true);
|
|
22863
22953
|
return fetchVersions({
|
|
22864
22954
|
sessionId,
|
|
22865
22955
|
version: requestedVersion,
|
|
@@ -22883,10 +22973,10 @@ function useCreatorWidgetPolling({
|
|
|
22883
22973
|
}
|
|
22884
22974
|
);
|
|
22885
22975
|
const activeVersion = selectedVersion ?? requestedVersion;
|
|
22886
|
-
const statusKey = sessionId && activeVersion != null ?
|
|
22976
|
+
const statusKey = sessionId && activeVersion != null ? statusPollKey(sessionId, activeVersion) : null;
|
|
22887
22977
|
const errorCountRef = useRef13(0);
|
|
22888
22978
|
const deadlineRef = useRef13(0);
|
|
22889
|
-
const doneRef = useRef13(
|
|
22979
|
+
const doneRef = useRef13(hydratedTerminal);
|
|
22890
22980
|
const stopCountdown = useCallback8(() => {
|
|
22891
22981
|
if (countdownRef.current) {
|
|
22892
22982
|
clearInterval(countdownRef.current);
|
|
@@ -22896,13 +22986,28 @@ function useCreatorWidgetPolling({
|
|
|
22896
22986
|
}, []);
|
|
22897
22987
|
useEffect15(() => {
|
|
22898
22988
|
if (statusKey == null) return;
|
|
22989
|
+
const cached = getSharedPollLastData(statusKey);
|
|
22990
|
+
const cachedStatus = cached?.status?.status;
|
|
22991
|
+
if (isTerminalStatus(cachedStatus) && isSharedPollStopped(statusKey)) {
|
|
22992
|
+
setStatusDetails(cached?.status);
|
|
22993
|
+
setVersionStatus(cachedStatus);
|
|
22994
|
+
onStatusChange?.(cachedStatus);
|
|
22995
|
+
if (cachedStatus === "completed" || cachedStatus === "complete") {
|
|
22996
|
+
setIsValidationComplete(true);
|
|
22997
|
+
}
|
|
22998
|
+
setLoadingStatus(false);
|
|
22999
|
+
doneRef.current = true;
|
|
23000
|
+
errorCountRef.current = 0;
|
|
23001
|
+
stopCountdown();
|
|
23002
|
+
return;
|
|
23003
|
+
}
|
|
22899
23004
|
setLoadingStatus(true);
|
|
22900
23005
|
setStatusDetails(void 0);
|
|
22901
23006
|
setVersionStatus("checking");
|
|
22902
23007
|
errorCountRef.current = 0;
|
|
22903
23008
|
doneRef.current = false;
|
|
22904
23009
|
deadlineRef.current = Date.now() + config.maxDuration;
|
|
22905
|
-
const creatorLength2 =
|
|
23010
|
+
const creatorLength2 = versionDataRef.current?.length || 0;
|
|
22906
23011
|
remainingTimeRef.current = creatorLength2 > 0 ? creatorLength2 * config.secondsPerCreator : 60;
|
|
22907
23012
|
setTimeDisplay(formatTime(remainingTimeRef.current));
|
|
22908
23013
|
countdownRef.current = setInterval(() => {
|
|
@@ -22924,7 +23029,7 @@ function useCreatorWidgetPolling({
|
|
|
22924
23029
|
shouldContinue: (data) => {
|
|
22925
23030
|
if (Date.now() >= deadlineRef.current) return false;
|
|
22926
23031
|
const s = data?.status?.status;
|
|
22927
|
-
return !(s
|
|
23032
|
+
return !isTerminalStatus(s);
|
|
22928
23033
|
}
|
|
22929
23034
|
},
|
|
22930
23035
|
(data) => {
|
|
@@ -23069,7 +23174,186 @@ function CreatorWidgetInner({
|
|
|
23069
23174
|
var CreatorWidget = memo(CreatorWidgetInner);
|
|
23070
23175
|
|
|
23071
23176
|
// src/molecules/analytics/AnalyticsChart.tsx
|
|
23072
|
-
import { useEffect as useEffect16, useRef as useRef14, useState as useState23 } from "react";
|
|
23177
|
+
import { useEffect as useEffect16, useMemo as useMemo12, useRef as useRef14, useState as useState23 } from "react";
|
|
23178
|
+
|
|
23179
|
+
// src/molecules/analytics/buildOptions.ts
|
|
23180
|
+
function deepMerge(base, override) {
|
|
23181
|
+
const out = Array.isArray(base) ? [...base] : { ...base };
|
|
23182
|
+
for (const key of Object.keys(override)) {
|
|
23183
|
+
const o = override[key];
|
|
23184
|
+
const b = out[key];
|
|
23185
|
+
if (o && typeof o === "object" && !Array.isArray(o) && b && typeof b === "object" && !Array.isArray(b)) {
|
|
23186
|
+
out[key] = deepMerge(b, o);
|
|
23187
|
+
} else if (o !== void 0) {
|
|
23188
|
+
out[key] = o;
|
|
23189
|
+
}
|
|
23190
|
+
}
|
|
23191
|
+
return out;
|
|
23192
|
+
}
|
|
23193
|
+
function highchartsType(type) {
|
|
23194
|
+
if (type === "donut") return "pie";
|
|
23195
|
+
return type;
|
|
23196
|
+
}
|
|
23197
|
+
function buildAxis(axis, fallbackCategories) {
|
|
23198
|
+
const cfg = {};
|
|
23199
|
+
if (!axis) {
|
|
23200
|
+
if (fallbackCategories) cfg.categories = fallbackCategories;
|
|
23201
|
+
return cfg;
|
|
23202
|
+
}
|
|
23203
|
+
if (axis.title) cfg.title = { text: axis.title };
|
|
23204
|
+
if (axis.type) cfg.type = axis.type;
|
|
23205
|
+
if (axis.categories || fallbackCategories) cfg.categories = axis.categories ?? fallbackCategories;
|
|
23206
|
+
if (axis.format) cfg.labels = { format: axis.format };
|
|
23207
|
+
if (typeof axis.min === "number") cfg.min = axis.min;
|
|
23208
|
+
if (typeof axis.max === "number") cfg.max = axis.max;
|
|
23209
|
+
if (axis.opposite) cfg.opposite = true;
|
|
23210
|
+
return cfg;
|
|
23211
|
+
}
|
|
23212
|
+
function resolveStacking(stacked) {
|
|
23213
|
+
if (stacked === true || stacked === "normal") return "normal";
|
|
23214
|
+
if (stacked === "percent") return "percent";
|
|
23215
|
+
return void 0;
|
|
23216
|
+
}
|
|
23217
|
+
function buildChartOptions(config, palette) {
|
|
23218
|
+
const hcType = highchartsType(config.type);
|
|
23219
|
+
const isCircular = config.type === "pie" || config.type === "donut";
|
|
23220
|
+
const seriesColors = config.colors ?? palette.series;
|
|
23221
|
+
const safeSeries = Array.isArray(config.series) ? config.series : [];
|
|
23222
|
+
const options = {
|
|
23223
|
+
chart: { type: hcType, ...config.height && { height: config.height } },
|
|
23224
|
+
title: { text: config.title ?? void 0 },
|
|
23225
|
+
subtitle: { text: config.subtitle ?? void 0 },
|
|
23226
|
+
series: safeSeries.map((s, i) => ({
|
|
23227
|
+
name: s.name,
|
|
23228
|
+
data: s.data,
|
|
23229
|
+
...s.type && { type: highchartsType(s.type) },
|
|
23230
|
+
...s.stack && { stack: s.stack },
|
|
23231
|
+
...typeof s.yAxis === "number" && { yAxis: s.yAxis },
|
|
23232
|
+
color: s.color ?? seriesColors[i % seriesColors.length]
|
|
23233
|
+
})),
|
|
23234
|
+
legend: { enabled: config.legend ?? (safeSeries.length > 1 || isCircular) }
|
|
23235
|
+
};
|
|
23236
|
+
if (config.colors) options.colors = config.colors;
|
|
23237
|
+
if (!isCircular && config.type !== "funnel") {
|
|
23238
|
+
options.xAxis = buildAxis(config.xAxis, config.categories);
|
|
23239
|
+
const yAxes = Array.isArray(config.yAxis) ? config.yAxis : [config.yAxis];
|
|
23240
|
+
options.yAxis = yAxes.map((a) => buildAxis(a));
|
|
23241
|
+
if (options.yAxis.length === 1) options.yAxis = options.yAxis[0];
|
|
23242
|
+
}
|
|
23243
|
+
if (config.tooltip) {
|
|
23244
|
+
options.tooltip = {
|
|
23245
|
+
...config.tooltip.shared !== void 0 && { shared: config.tooltip.shared },
|
|
23246
|
+
...config.tooltip.valuePrefix && { valuePrefix: config.tooltip.valuePrefix },
|
|
23247
|
+
...config.tooltip.valueSuffix && { valueSuffix: config.tooltip.valueSuffix },
|
|
23248
|
+
...config.tooltip.pointFormat && { pointFormat: config.tooltip.pointFormat }
|
|
23249
|
+
};
|
|
23250
|
+
}
|
|
23251
|
+
const stacking = resolveStacking(config.stacked);
|
|
23252
|
+
const dataLabels = config.dataLabels === true ? { enabled: true } : config.dataLabels && typeof config.dataLabels === "object" ? { enabled: true, ...config.dataLabels } : void 0;
|
|
23253
|
+
const plotOptions = {};
|
|
23254
|
+
if (stacking || dataLabels) {
|
|
23255
|
+
plotOptions.series = {
|
|
23256
|
+
...stacking && { stacking },
|
|
23257
|
+
...dataLabels && { dataLabels }
|
|
23258
|
+
};
|
|
23259
|
+
}
|
|
23260
|
+
if (config.type === "donut") {
|
|
23261
|
+
plotOptions.pie = {
|
|
23262
|
+
innerSize: "55%",
|
|
23263
|
+
dataLabels: dataLabels ?? {
|
|
23264
|
+
enabled: true,
|
|
23265
|
+
format: "<b>{point.name}</b>: {point.percentage:.1f}%"
|
|
23266
|
+
}
|
|
23267
|
+
};
|
|
23268
|
+
} else if (config.type === "pie") {
|
|
23269
|
+
plotOptions.pie = {
|
|
23270
|
+
dataLabels: dataLabels ?? {
|
|
23271
|
+
enabled: true,
|
|
23272
|
+
format: "<b>{point.name}</b>: {point.percentage:.1f}%"
|
|
23273
|
+
}
|
|
23274
|
+
};
|
|
23275
|
+
} else if (config.type === "funnel") {
|
|
23276
|
+
plotOptions.funnel = {
|
|
23277
|
+
neckWidth: "30%",
|
|
23278
|
+
neckHeight: "25%",
|
|
23279
|
+
dataLabels: dataLabels ?? { enabled: true, format: "<b>{point.name}</b> ({point.y:,.0f})" }
|
|
23280
|
+
};
|
|
23281
|
+
}
|
|
23282
|
+
if (Object.keys(plotOptions).length) options.plotOptions = plotOptions;
|
|
23283
|
+
return options;
|
|
23284
|
+
}
|
|
23285
|
+
|
|
23286
|
+
// src/molecules/analytics/highchartsTheme.ts
|
|
23287
|
+
var PXENGINE_SERIES_COLORS = [
|
|
23288
|
+
"#6366f1",
|
|
23289
|
+
// indigo
|
|
23290
|
+
"#10b981",
|
|
23291
|
+
// emerald
|
|
23292
|
+
"#f59e0b",
|
|
23293
|
+
// amber
|
|
23294
|
+
"#ec4899",
|
|
23295
|
+
// pink
|
|
23296
|
+
"#8b5cf6",
|
|
23297
|
+
// violet
|
|
23298
|
+
"#06b6d4",
|
|
23299
|
+
// cyan
|
|
23300
|
+
"#f43f5e",
|
|
23301
|
+
// rose
|
|
23302
|
+
"#84cc16",
|
|
23303
|
+
// lime
|
|
23304
|
+
"#3b82f6",
|
|
23305
|
+
// blue
|
|
23306
|
+
"#f97316"
|
|
23307
|
+
// orange
|
|
23308
|
+
];
|
|
23309
|
+
var DARK_PALETTE = {
|
|
23310
|
+
text: "#e5e7eb",
|
|
23311
|
+
textMuted: "#9ca3af",
|
|
23312
|
+
grid: "rgba(255,255,255,0.08)",
|
|
23313
|
+
border: "rgba(255,255,255,0.12)",
|
|
23314
|
+
background: "transparent",
|
|
23315
|
+
series: PXENGINE_SERIES_COLORS,
|
|
23316
|
+
tooltipBg: "rgba(17,24,39,0.95)",
|
|
23317
|
+
tooltipText: "#f9fafb"
|
|
23318
|
+
};
|
|
23319
|
+
var LIGHT_PALETTE = {
|
|
23320
|
+
text: "#1f2937",
|
|
23321
|
+
textMuted: "#6b7280",
|
|
23322
|
+
grid: "rgba(0,0,0,0.06)",
|
|
23323
|
+
border: "rgba(0,0,0,0.10)",
|
|
23324
|
+
background: "transparent",
|
|
23325
|
+
series: PXENGINE_SERIES_COLORS,
|
|
23326
|
+
tooltipBg: "rgba(255,255,255,0.98)",
|
|
23327
|
+
tooltipText: "#111827"
|
|
23328
|
+
};
|
|
23329
|
+
function resolveColorMode(mode = "auto") {
|
|
23330
|
+
if (mode === "light" || mode === "dark") return mode;
|
|
23331
|
+
if (typeof document !== "undefined") {
|
|
23332
|
+
if (document.documentElement.classList.contains("dark")) return "dark";
|
|
23333
|
+
if (typeof window !== "undefined" && window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches) {
|
|
23334
|
+
return "dark";
|
|
23335
|
+
}
|
|
23336
|
+
return "light";
|
|
23337
|
+
}
|
|
23338
|
+
return "dark";
|
|
23339
|
+
}
|
|
23340
|
+
function buildChartPalette(theme, mode = "auto") {
|
|
23341
|
+
const base = resolveColorMode(mode) === "dark" ? DARK_PALETTE : LIGHT_PALETTE;
|
|
23342
|
+
if (!theme) return base;
|
|
23343
|
+
const series = theme.accent ? [theme.accent, ...base.series.filter((c) => c.toLowerCase() !== theme.accent.toLowerCase())] : base.series;
|
|
23344
|
+
return {
|
|
23345
|
+
...base,
|
|
23346
|
+
...theme.text && { text: theme.text },
|
|
23347
|
+
...theme.textMuted && { textMuted: theme.textMuted },
|
|
23348
|
+
...theme.border && { border: theme.border, grid: theme.border },
|
|
23349
|
+
...theme.surface && { tooltipBg: theme.surface },
|
|
23350
|
+
...theme.text && { tooltipText: theme.text },
|
|
23351
|
+
...theme.fontFamily && { fontFamily: theme.fontFamily },
|
|
23352
|
+
series
|
|
23353
|
+
};
|
|
23354
|
+
}
|
|
23355
|
+
|
|
23356
|
+
// src/molecules/analytics/AnalyticsChart.tsx
|
|
23073
23357
|
import { jsx as jsx179, jsxs as jsxs137 } from "react/jsx-runtime";
|
|
23074
23358
|
function getCSSVar(name) {
|
|
23075
23359
|
if (typeof document === "undefined") return "";
|
|
@@ -23106,6 +23390,30 @@ function stripNulls(val) {
|
|
|
23106
23390
|
}
|
|
23107
23391
|
return val;
|
|
23108
23392
|
}
|
|
23393
|
+
function resolveDeclarativeConfig(props) {
|
|
23394
|
+
if (props.chartConfig) {
|
|
23395
|
+
return {
|
|
23396
|
+
...props.chartConfig,
|
|
23397
|
+
...props.height != null && !props.chartConfig.height ? { height: props.height } : {}
|
|
23398
|
+
};
|
|
23399
|
+
}
|
|
23400
|
+
if (!props.chartType) return null;
|
|
23401
|
+
return {
|
|
23402
|
+
type: props.chartType,
|
|
23403
|
+
title: props.title,
|
|
23404
|
+
subtitle: props.subtitle,
|
|
23405
|
+
series: props.series ?? [],
|
|
23406
|
+
categories: props.categories,
|
|
23407
|
+
xAxis: props.xAxis,
|
|
23408
|
+
yAxis: props.yAxis,
|
|
23409
|
+
colors: props.colors,
|
|
23410
|
+
stacked: props.stacked,
|
|
23411
|
+
legend: props.legend,
|
|
23412
|
+
tooltip: props.tooltip,
|
|
23413
|
+
dataLabels: props.dataLabels,
|
|
23414
|
+
height: props.height
|
|
23415
|
+
};
|
|
23416
|
+
}
|
|
23109
23417
|
var hcSingleton = null;
|
|
23110
23418
|
var hcLoadPromise = null;
|
|
23111
23419
|
function loadHighcharts() {
|
|
@@ -23174,9 +23482,25 @@ function buildTheme(height) {
|
|
|
23174
23482
|
}
|
|
23175
23483
|
function AnalyticsChart({
|
|
23176
23484
|
config: configProp,
|
|
23485
|
+
chartConfig,
|
|
23486
|
+
chartType,
|
|
23487
|
+
series,
|
|
23488
|
+
categories,
|
|
23489
|
+
xAxis,
|
|
23490
|
+
yAxis,
|
|
23491
|
+
colors,
|
|
23492
|
+
stacked,
|
|
23493
|
+
legend,
|
|
23494
|
+
tooltip,
|
|
23495
|
+
dataLabels,
|
|
23496
|
+
extraOptions,
|
|
23177
23497
|
chartId,
|
|
23178
23498
|
apiBase = "",
|
|
23179
23499
|
authToken,
|
|
23500
|
+
title,
|
|
23501
|
+
subtitle,
|
|
23502
|
+
theme,
|
|
23503
|
+
mode = "auto",
|
|
23180
23504
|
height = 400,
|
|
23181
23505
|
className,
|
|
23182
23506
|
loading: loadingProp,
|
|
@@ -23188,11 +23512,51 @@ function AnalyticsChart({
|
|
|
23188
23512
|
const [fetchError, setFetchError] = useState23(null);
|
|
23189
23513
|
const containerRef = useRef14(null);
|
|
23190
23514
|
const chartRef = useRef14(null);
|
|
23515
|
+
const declarative = useMemo12(
|
|
23516
|
+
() => resolveDeclarativeConfig({
|
|
23517
|
+
chartConfig,
|
|
23518
|
+
chartType,
|
|
23519
|
+
title,
|
|
23520
|
+
subtitle,
|
|
23521
|
+
series,
|
|
23522
|
+
categories,
|
|
23523
|
+
xAxis,
|
|
23524
|
+
yAxis,
|
|
23525
|
+
colors,
|
|
23526
|
+
stacked,
|
|
23527
|
+
legend,
|
|
23528
|
+
tooltip,
|
|
23529
|
+
dataLabels,
|
|
23530
|
+
height
|
|
23531
|
+
}),
|
|
23532
|
+
[
|
|
23533
|
+
chartConfig,
|
|
23534
|
+
chartType,
|
|
23535
|
+
title,
|
|
23536
|
+
subtitle,
|
|
23537
|
+
series,
|
|
23538
|
+
categories,
|
|
23539
|
+
xAxis,
|
|
23540
|
+
yAxis,
|
|
23541
|
+
colors,
|
|
23542
|
+
stacked,
|
|
23543
|
+
legend,
|
|
23544
|
+
tooltip,
|
|
23545
|
+
dataLabels,
|
|
23546
|
+
height
|
|
23547
|
+
]
|
|
23548
|
+
);
|
|
23549
|
+
const builtConfig = useMemo12(() => {
|
|
23550
|
+
if (!declarative) return null;
|
|
23551
|
+
const palette = buildChartPalette(theme, mode);
|
|
23552
|
+
const options = buildChartOptions(declarative, palette);
|
|
23553
|
+
return extraOptions ? deepMerge(options, extraOptions) : options;
|
|
23554
|
+
}, [declarative, theme, mode, extraOptions]);
|
|
23191
23555
|
useEffect16(() => {
|
|
23192
23556
|
setMounted(true);
|
|
23193
23557
|
}, []);
|
|
23194
23558
|
useEffect16(() => {
|
|
23195
|
-
if (!chartId || configProp) return;
|
|
23559
|
+
if (!chartId || configProp || builtConfig) return;
|
|
23196
23560
|
let cancelled = false;
|
|
23197
23561
|
setFetching(true);
|
|
23198
23562
|
setFetchError(null);
|
|
@@ -23211,8 +23575,8 @@ function AnalyticsChart({
|
|
|
23211
23575
|
return () => {
|
|
23212
23576
|
cancelled = true;
|
|
23213
23577
|
};
|
|
23214
|
-
}, [chartId, apiBase, authToken, configProp]);
|
|
23215
|
-
const activeConfig = configProp ?? fetchedConfig;
|
|
23578
|
+
}, [chartId, apiBase, authToken, configProp, builtConfig]);
|
|
23579
|
+
const activeConfig = configProp ?? builtConfig ?? fetchedConfig;
|
|
23216
23580
|
useEffect16(() => {
|
|
23217
23581
|
if (!mounted || !activeConfig || !containerRef.current) return;
|
|
23218
23582
|
const container = containerRef.current;
|
|
@@ -23726,7 +24090,7 @@ function EmptyContent({ className, ...props }) {
|
|
|
23726
24090
|
}
|
|
23727
24091
|
|
|
23728
24092
|
// src/components/ui/field.tsx
|
|
23729
|
-
import { useMemo as
|
|
24093
|
+
import { useMemo as useMemo13 } from "react";
|
|
23730
24094
|
import { cva as cva10 } from "class-variance-authority";
|
|
23731
24095
|
import { jsx as jsx182, jsxs as jsxs138 } from "react/jsx-runtime";
|
|
23732
24096
|
function FieldSet({ className, ...props }) {
|
|
@@ -23909,7 +24273,7 @@ function FieldError({
|
|
|
23909
24273
|
errors,
|
|
23910
24274
|
...props
|
|
23911
24275
|
}) {
|
|
23912
|
-
const content =
|
|
24276
|
+
const content = useMemo13(() => {
|
|
23913
24277
|
if (children) {
|
|
23914
24278
|
return children;
|
|
23915
24279
|
}
|