@juv/codego-react-ui 1.1.7 → 3.0.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.js CHANGED
@@ -4943,6 +4943,45 @@ function addTerrain(map) {
4943
4943
  });
4944
4944
  }
4945
4945
  }
4946
+ var OSRM_PROFILE2 = { drive: "driving", walk: "foot" };
4947
+ async function fetchOsrmRoute2(points, routeType) {
4948
+ const profile = OSRM_PROFILE2[routeType];
4949
+ const coords = points.map((p) => `${p.lng},${p.lat}`).join(";");
4950
+ const res = await fetch(`https://router.project-osrm.org/route/v1/${profile}/${coords}?overview=full&geometries=geojson`);
4951
+ if (!res.ok) throw new Error("OSRM failed");
4952
+ const data = await res.json();
4953
+ if (data.code !== "Ok" || !data.routes?.length) throw new Error("No route");
4954
+ const route = data.routes[0];
4955
+ return {
4956
+ coords: route.geometry.coordinates,
4957
+ // already [lng, lat] for MapLibre
4958
+ distance: route.distance,
4959
+ duration: route.duration
4960
+ };
4961
+ }
4962
+ function fmtDistance2(m) {
4963
+ return m >= 1e3 ? `${(m / 1e3).toFixed(1)} km` : `${Math.round(m)} m`;
4964
+ }
4965
+ function fmtDuration2(s) {
4966
+ const h = Math.floor(s / 3600), m = Math.floor(s % 3600 / 60);
4967
+ return h > 0 ? `${h}h ${m}min` : `${m} min`;
4968
+ }
4969
+ function makeClusterHTML(variant, count, color) {
4970
+ if (variant === "bubble") {
4971
+ const size = count > 99 ? 52 : count > 9 ? 44 : 36;
4972
+ return `<div style="width:${size}px;height:${size}px;border-radius:50%;background:${color};color:#fff;font-weight:700;font-size:${count > 99 ? 11 : 13}px;font-family:sans-serif;display:flex;align-items:center;justify-content:center;border:3px solid white;box-shadow:0 2px 8px rgba(0,0,0,.3);">${count}</div>`;
4973
+ }
4974
+ if (variant === "donut") {
4975
+ const r = 20, stroke = 5, circ = 2 * Math.PI * r;
4976
+ const dash = Math.min(count / 50, 1) * circ;
4977
+ return `<svg width="54" height="54" viewBox="0 0 54 54"><circle cx="27" cy="27" r="${r}" fill="none" stroke="${color}33" stroke-width="${stroke}"/><circle cx="27" cy="27" r="${r}" fill="none" stroke="${color}" stroke-width="${stroke}" stroke-dasharray="${dash} ${circ}" stroke-dashoffset="${circ / 4}" stroke-linecap="round"/><circle cx="27" cy="27" r="${r - stroke - 2}" fill="${color}22"/><text x="27" y="27" text-anchor="middle" dominant-baseline="middle" font-size="12" font-weight="700" fill="${color}" font-family="sans-serif">${count}</text></svg>`;
4978
+ }
4979
+ const w = count > 99 ? 52 : 40;
4980
+ return `<div style="min-width:${w}px;height:28px;border-radius:14px;background:${color};color:#fff;font-weight:700;font-size:12px;font-family:sans-serif;display:flex;align-items:center;justify-content:center;padding:0 8px;border:2px solid white;box-shadow:0 2px 8px rgba(0,0,0,.25);">${count}</div>`;
4981
+ }
4982
+ function makeEndpointHTML(color, label) {
4983
+ return `<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" viewBox="0 0 28 28"><circle cx="14" cy="14" r="12" fill="${color}" stroke="white" stroke-width="2.5"/><text x="14" y="14" text-anchor="middle" dominant-baseline="middle" font-size="12" font-weight="700" fill="white" font-family="sans-serif">${label}</text></svg>`;
4984
+ }
4946
4985
  function MapLibreMap({
4947
4986
  style: styleProp = "street",
4948
4987
  center = [0, 20],
@@ -4957,6 +4996,9 @@ function MapLibreMap({
4957
4996
  maxBearing = 180,
4958
4997
  flyTo,
4959
4998
  markers = [],
4999
+ routes = [],
5000
+ cluster = false,
5001
+ clusterVariant = "default",
4960
5002
  height = 480,
4961
5003
  showControls = true,
4962
5004
  showStyleSwitcher = true,
@@ -4967,7 +5009,9 @@ function MapLibreMap({
4967
5009
  const containerRef = React22.useRef(null);
4968
5010
  const mapRef = React22.useRef(null);
4969
5011
  const markersRef = React22.useRef([]);
5012
+ const routeMarkersRef = React22.useRef([]);
4970
5013
  const flyingRef = React22.useRef(false);
5014
+ const [routeLoading, setRouteLoading] = React22.useState(false);
4971
5015
  const [activeStyle, setActiveStyle] = React22.useState(styleProp);
4972
5016
  const [ready, setReady] = React22.useState(false);
4973
5017
  const [showCamera, setShowCamera] = React22.useState(false);
@@ -5055,6 +5099,109 @@ function MapLibreMap({
5055
5099
  if (ftBearing !== void 0) setBearing(clampBearing(ftBearing));
5056
5100
  });
5057
5101
  }, [flyTo]);
5102
+ React22.useEffect(() => {
5103
+ const map = mapRef.current;
5104
+ if (!map || !ready || routes.length === 0) return;
5105
+ function cleanRoutes() {
5106
+ routeMarkersRef.current.forEach((m) => m.remove());
5107
+ routeMarkersRef.current = [];
5108
+ const style = map.getStyle();
5109
+ (style.layers ?? []).forEach((l) => {
5110
+ if (l.id.startsWith("route-")) try {
5111
+ map.removeLayer(l.id);
5112
+ } catch {
5113
+ }
5114
+ });
5115
+ Object.keys(style.sources ?? {}).forEach((s) => {
5116
+ if (s.startsWith("route-")) try {
5117
+ map.removeSource(s);
5118
+ } catch {
5119
+ }
5120
+ });
5121
+ }
5122
+ cleanRoutes();
5123
+ setRouteLoading(true);
5124
+ Promise.all(
5125
+ routes.map(async (r, i) => {
5126
+ const points = [r.start, ...r.waypoints ?? [], r.end];
5127
+ try {
5128
+ const result = await fetchOsrmRoute2(points, r.routeType ?? "drive");
5129
+ return { route: r, idx: i, ...result, error: false };
5130
+ } catch {
5131
+ return { route: r, idx: i, coords: points.map((p) => [p.lng, p.lat]), distance: 0, duration: 0, error: true };
5132
+ }
5133
+ })
5134
+ ).then((results) => {
5135
+ setRouteLoading(false);
5136
+ if (!mapRef.current) return;
5137
+ const m = mapRef.current;
5138
+ const allCoords = [];
5139
+ results.forEach(({ route, idx, coords, distance, duration }) => {
5140
+ const color = route.color ?? (route.routeType === "walk" ? "#22c55e" : "#6366f1");
5141
+ const srcId = `route-${idx}`;
5142
+ const geojson = {
5143
+ type: "Feature",
5144
+ properties: {},
5145
+ geometry: { type: "LineString", coordinates: coords }
5146
+ };
5147
+ m.addSource(srcId, { type: "geojson", data: geojson });
5148
+ m.addLayer({
5149
+ id: `${srcId}-outline`,
5150
+ type: "line",
5151
+ source: srcId,
5152
+ layout: { "line-cap": "round", "line-join": "round" },
5153
+ paint: { "line-color": "#ffffff", "line-width": (route.weight ?? 5) + 4, "line-opacity": 0.3 }
5154
+ });
5155
+ m.addLayer({
5156
+ id: `${srcId}-line`,
5157
+ type: "line",
5158
+ source: srcId,
5159
+ layout: { "line-cap": "round", "line-join": "round" },
5160
+ paint: { "line-color": color, "line-width": route.weight ?? 5, "line-opacity": 0.9 }
5161
+ });
5162
+ allCoords.push(...coords);
5163
+ const makeEndpointMarker = (lngLat, label, markerColor, popupHtml) => {
5164
+ const el = document.createElement("div");
5165
+ el.innerHTML = makeEndpointHTML(markerColor, label);
5166
+ el.style.cssText = "width:28px;height:28px";
5167
+ const popup = new maplibregl.Popup({ offset: [0, -16], closeButton: false }).setHTML(popupHtml);
5168
+ const marker = new maplibregl.Marker({ element: el, anchor: "center" }).setLngLat(lngLat).setPopup(popup).addTo(m);
5169
+ routeMarkersRef.current.push(marker);
5170
+ };
5171
+ const infoHtml = distance > 0 ? `<p style="font-size:11px;color:#888;margin:2px 0 0">${fmtDistance2(distance)} \xB7 ${fmtDuration2(duration)} \xB7 ${route.routeType === "walk" ? "\u{1F6B6} Walk" : "\u{1F697} Drive"}</p>` : "";
5172
+ makeEndpointMarker(
5173
+ [route.start.lng, route.start.lat],
5174
+ "A",
5175
+ color,
5176
+ `<div style="padding:2px;min-width:120px"><p style="font-weight:700;font-size:13px;margin:0">${route.label ? `${route.label} \u2014 Start` : "Start"}</p>${infoHtml}</div>`
5177
+ );
5178
+ makeEndpointMarker(
5179
+ [route.end.lng, route.end.lat],
5180
+ "B",
5181
+ "#ef4444",
5182
+ `<div style="padding:2px;min-width:120px"><p style="font-weight:700;font-size:13px;margin:0">${route.label ? `${route.label} \u2014 End` : "End"}</p>${infoHtml}</div>`
5183
+ );
5184
+ if (distance > 0 && coords.length > 1) {
5185
+ const mid = coords[Math.floor(coords.length / 2)];
5186
+ const text = `${fmtDistance2(distance)} \xB7 ${fmtDuration2(duration)}`;
5187
+ const estW = text.length * 7 + 16;
5188
+ const el = document.createElement("div");
5189
+ el.innerHTML = `<div style="display:inline-flex;align-items:center;justify-content:center;background:${color};color:white;font-size:11px;font-weight:600;font-family:sans-serif;padding:3px 8px;border-radius:12px;border:2px solid white;box-shadow:0 2px 6px rgba(0,0,0,.25);white-space:nowrap;">${text}</div>`;
5190
+ el.style.cssText = `width:${estW}px;height:22px;pointer-events:none`;
5191
+ const badge = new maplibregl.Marker({ element: el, anchor: "center" }).setLngLat(mid).addTo(m);
5192
+ routeMarkersRef.current.push(badge);
5193
+ }
5194
+ });
5195
+ if (allCoords.length > 1) {
5196
+ const lngs = allCoords.map((c) => c[0]), lats = allCoords.map((c) => c[1]);
5197
+ m.fitBounds(
5198
+ [[Math.min(...lngs), Math.min(...lats)], [Math.max(...lngs), Math.max(...lats)]],
5199
+ { padding: 60, duration: 800 }
5200
+ );
5201
+ }
5202
+ });
5203
+ return cleanRoutes;
5204
+ }, [routes, ready]);
5058
5205
  function switchStyle(s) {
5059
5206
  const map = mapRef.current;
5060
5207
  if (!map) return;
@@ -5062,6 +5209,8 @@ function MapLibreMap({
5062
5209
  setReady(false);
5063
5210
  markersRef.current.forEach((m) => m.remove());
5064
5211
  markersRef.current = [];
5212
+ routeMarkersRef.current.forEach((m) => m.remove());
5213
+ routeMarkersRef.current = [];
5065
5214
  map.setStyle(s === "satellite" ? SATELLITE_STYLE : STYLE_URLS[s]);
5066
5215
  map.once("style.load", () => {
5067
5216
  if (s === "globe") {
@@ -5093,32 +5242,107 @@ function MapLibreMap({
5093
5242
  setReady(true);
5094
5243
  });
5095
5244
  }
5245
+ const [mapZoom, setMapZoom] = React22.useState(zoom);
5246
+ React22.useEffect(() => {
5247
+ const map = mapRef.current;
5248
+ if (!map) return;
5249
+ const h2 = () => setMapZoom(map.getZoom());
5250
+ map.on("zoomend", h2);
5251
+ return () => {
5252
+ map.off("zoomend", h2);
5253
+ };
5254
+ }, [ready]);
5096
5255
  React22.useEffect(() => {
5097
5256
  const map = mapRef.current;
5098
5257
  if (!map || !ready) return;
5099
5258
  markersRef.current.forEach((m) => m.remove());
5100
5259
  markersRef.current = [];
5101
- markers.forEach((m) => {
5102
- const color = resolveColor2(m.color);
5103
- const el = document.createElement("div");
5104
- el.innerHTML = makePinHTML(color, m.icon, m.image);
5105
- el.style.cssText = m.image ? "width:40px;height:50px" : "width:32px;height:42px";
5106
- const popup = new maplibregl.Popup({ offset: m.image ? [0, -52] : [0, -44], closeButton: false });
5107
- if (m.popup) {
5108
- if (typeof m.popup === "string") popup.setHTML(m.popup);
5109
- else popup.setDOMContent(m.popup);
5110
- } else if (m.label) {
5111
- popup.setHTML(`<span style="font-size:13px;font-weight:600">${m.label}</span>`);
5112
- }
5113
- const marker = new maplibregl.Marker({ element: el, anchor: "bottom" }).setLngLat([m.lng, m.lat]);
5114
- if (m.popup || m.label) marker.setPopup(popup);
5115
- el.addEventListener("click", () => onMarkerClick?.(m));
5116
- marker.addTo(map);
5117
- markersRef.current.push(marker);
5118
- });
5119
- }, [markers, ready, onMarkerClick]);
5260
+ if (cluster && markers.length > 0) {
5261
+ const GRID = 80;
5262
+ const used = /* @__PURE__ */ new Set();
5263
+ const groups = [];
5264
+ markers.forEach((m, i) => {
5265
+ if (used.has(i)) return;
5266
+ const pt = map.project([m.lng, m.lat]);
5267
+ const group = [m];
5268
+ used.add(i);
5269
+ markers.forEach((m2, j) => {
5270
+ if (used.has(j)) return;
5271
+ const pt2 = map.project([m2.lng, m2.lat]);
5272
+ if (Math.abs(pt.x - pt2.x) < GRID && Math.abs(pt.y - pt2.y) < GRID) {
5273
+ group.push(m2);
5274
+ used.add(j);
5275
+ }
5276
+ });
5277
+ const lat = group.reduce((s, x) => s + x.lat, 0) / group.length;
5278
+ const lng = group.reduce((s, x) => s + x.lng, 0) / group.length;
5279
+ groups.push({ center: { lng, lat }, items: group });
5280
+ });
5281
+ groups.forEach((g, gi) => {
5282
+ if (g.items.length === 1) {
5283
+ const m = g.items[0];
5284
+ const color = resolveColor2(m.color);
5285
+ const el = document.createElement("div");
5286
+ el.innerHTML = makePinHTML(color, m.icon, m.image);
5287
+ el.style.cssText = m.image ? "width:40px;height:50px" : "width:32px;height:42px";
5288
+ const popup = new maplibregl.Popup({ offset: m.image ? [0, -52] : [0, -44], closeButton: false });
5289
+ if (m.popup) {
5290
+ typeof m.popup === "string" ? popup.setHTML(m.popup) : popup.setDOMContent(m.popup);
5291
+ } else if (m.label) popup.setHTML(`<span style="font-size:13px;font-weight:600">${m.label}</span>`);
5292
+ const marker = new maplibregl.Marker({ element: el, anchor: "bottom" }).setLngLat([m.lng, m.lat]);
5293
+ if (m.popup || m.label) marker.setPopup(popup);
5294
+ el.addEventListener("click", () => onMarkerClick?.(m));
5295
+ marker.addTo(map);
5296
+ markersRef.current.push(marker);
5297
+ } else {
5298
+ const color = resolveColor2(g.items[0].color);
5299
+ const el = document.createElement("div");
5300
+ el.innerHTML = makeClusterHTML(clusterVariant, g.items.length, color);
5301
+ el.style.cssText = "cursor:pointer";
5302
+ const listItems = g.items.map(
5303
+ (m) => `<div data-id="${m.id}" style="font-size:12px;padding:2px 0;cursor:pointer;">${m.label ?? `Marker ${m.id}`}</div>`
5304
+ ).join("");
5305
+ const popup = new maplibregl.Popup({ offset: [0, -8], closeButton: false }).setHTML(`<div style="max-height:160px;overflow-y:auto;padding:2px">${listItems}</div>`);
5306
+ el.addEventListener("click", () => {
5307
+ map.flyTo({ center: [g.center.lng, g.center.lat], zoom: map.getZoom() + 2, duration: 400 });
5308
+ });
5309
+ const marker = new maplibregl.Marker({ element: el, anchor: "center" }).setLngLat([g.center.lng, g.center.lat]).setPopup(popup).addTo(map);
5310
+ markersRef.current.push(marker);
5311
+ marker.getPopup().on("open", () => {
5312
+ g.items.forEach((m) => {
5313
+ const node = document.querySelector(`[data-id="${m.id}"]`);
5314
+ node?.addEventListener("click", () => onMarkerClick?.(m));
5315
+ });
5316
+ });
5317
+ }
5318
+ });
5319
+ } else {
5320
+ markers.forEach((m) => {
5321
+ const color = resolveColor2(m.color);
5322
+ const el = document.createElement("div");
5323
+ el.innerHTML = makePinHTML(color, m.icon, m.image);
5324
+ el.style.cssText = m.image ? "width:40px;height:50px" : "width:32px;height:42px";
5325
+ const popup = new maplibregl.Popup({ offset: m.image ? [0, -52] : [0, -44], closeButton: false });
5326
+ if (m.popup) {
5327
+ if (typeof m.popup === "string") popup.setHTML(m.popup);
5328
+ else popup.setDOMContent(m.popup);
5329
+ } else if (m.label) {
5330
+ popup.setHTML(`<span style="font-size:13px;font-weight:600">${m.label}</span>`);
5331
+ }
5332
+ const marker = new maplibregl.Marker({ element: el, anchor: "bottom" }).setLngLat([m.lng, m.lat]);
5333
+ if (m.popup || m.label) marker.setPopup(popup);
5334
+ el.addEventListener("click", () => onMarkerClick?.(m));
5335
+ marker.addTo(map);
5336
+ markersRef.current.push(marker);
5337
+ });
5338
+ }
5339
+ }, [markers, ready, onMarkerClick, cluster, clusterVariant, mapZoom]);
5120
5340
  const cameraOpen = showCameraControls || showCamera;
5121
5341
  return /* @__PURE__ */ jsxs23("div", { className: cn("relative w-full overflow-hidden rounded-2xl border border-border", className), style: { height: h }, children: [
5342
+ routeLoading && /* @__PURE__ */ jsx27("div", { className: "absolute inset-0 z-[1000] flex items-center justify-center pointer-events-none", children: /* @__PURE__ */ jsxs23("div", { className: "flex items-center gap-2 bg-card/90 backdrop-blur-sm border border-border rounded-xl px-4 py-2 shadow-lg text-sm font-medium", children: [
5343
+ /* @__PURE__ */ jsx27("span", { className: "h-4 w-4 rounded-full border-2 border-primary border-t-transparent animate-spin" }),
5344
+ "Calculating route\u2026"
5345
+ ] }) }),
5122
5346
  /* @__PURE__ */ jsx27("div", { ref: containerRef, style: { width: "100%", height: "100%" } }),
5123
5347
  cameraOpen && /* @__PURE__ */ jsxs23("div", { className: "absolute top-4 left-4 z-10 bg-card/90 backdrop-blur-sm border border-border rounded-2xl p-3 shadow-xl space-y-3 w-52", children: [
5124
5348
  /* @__PURE__ */ jsxs23("div", { className: "flex items-center justify-between", children: [
@@ -5453,6 +5677,7 @@ function Select({
5453
5677
  const [isSearching, setIsSearching] = React25.useState(false);
5454
5678
  const containerRef = React25.useRef(null);
5455
5679
  const triggerRef = React25.useRef(null);
5680
+ const portalRef = React25.useRef(null);
5456
5681
  const [dropStyle, setDropStyle] = React25.useState({});
5457
5682
  const getKey = React25.useCallback((opt) => String(Object.keys(opt)[0]), []);
5458
5683
  const getLabel = React25.useCallback((opt) => Object.values(opt)[0], []);
@@ -5483,9 +5708,9 @@ function Select({
5483
5708
  };
5484
5709
  React25.useEffect(() => {
5485
5710
  const handler = (e) => {
5486
- if (containerRef.current && !containerRef.current.contains(e.target)) {
5487
- setIsOpen(false);
5488
- }
5711
+ const target = e.target;
5712
+ if (containerRef.current?.contains(target) || portalRef.current?.contains(target)) return;
5713
+ setIsOpen(false);
5489
5714
  };
5490
5715
  document.addEventListener("mousedown", handler);
5491
5716
  return () => document.removeEventListener("mousedown", handler);
@@ -5628,6 +5853,7 @@ function Select({
5628
5853
  isOpen && /* @__PURE__ */ jsx30(FloatingPortal, { children: /* @__PURE__ */ jsxs26(
5629
5854
  "div",
5630
5855
  {
5856
+ ref: portalRef,
5631
5857
  className: "max-h-60 overflow-auto rounded-md border border-white/10 bg-background/80 backdrop-blur-xl text-popover-foreground shadow-lg animate-in fade-in-80",
5632
5858
  style: dropStyle,
5633
5859
  children: [
@@ -6592,67 +6818,386 @@ import { createContext as createContext2, useContext as useContext2, useEffect a
6592
6818
 
6593
6819
  // src/components/conf/settingConfig.json
6594
6820
  var settingConfig_default = {
6595
- theme: "dark",
6596
- fontSize: "16px",
6597
- fontFamily: '"Space Grotesk", "Inter", sans-serif',
6598
- colors: {
6599
- primary: "#8b5cf6",
6600
- primaryHover: "#7c3aed",
6601
- secondary: "#171717",
6602
- secondaryHover: "#262626",
6603
- info: "#3b82f6",
6604
- infoHover: "#2563eb",
6605
- warning: "#f59e0b",
6606
- warningHover: "#d97706",
6607
- danger: "#ef4444",
6608
- dangerHover: "#dc2626"
6609
- }
6821
+ defaults: {
6822
+ theme: "light",
6823
+ fontSize: "16px",
6824
+ fontFamily: '"Space Grotesk", "Inter", sans-serif',
6825
+ colors: {
6826
+ primary: "#5CF6E2",
6827
+ primaryHover: "#73F3E2",
6828
+ secondary: "#171717",
6829
+ secondaryHover: "#262626",
6830
+ info: "#3b82f6",
6831
+ infoHover: "#2563eb",
6832
+ warning: "#f59e0b",
6833
+ warningHover: "#d97706",
6834
+ danger: "#ef4444",
6835
+ dangerHover: "#dc2626"
6836
+ }
6837
+ },
6838
+ themeOptions: [
6839
+ { light: "Light" },
6840
+ { dark: "Dark" },
6841
+ { system: "System" }
6842
+ ],
6843
+ fontSizes: [
6844
+ { "14px": "Small (14px)" },
6845
+ { "16px": "Medium (16px)" },
6846
+ { "18px": "Large (18px)" },
6847
+ { "20px": "Extra Large (20px)" }
6848
+ ],
6849
+ fontFamilies: [
6850
+ { '"Space Grotesk", "Inter", sans-serif': "Space Grotesk" },
6851
+ { '"Inter", sans-serif': "Inter" },
6852
+ { '"JetBrains Mono", monospace': "JetBrains Mono" },
6853
+ { "system-ui, sans-serif": "System UI" }
6854
+ ],
6855
+ colorPairs: [
6856
+ { base: "primary", hover: "primaryHover", label: "Primary" },
6857
+ { base: "secondary", hover: "secondaryHover", label: "Secondary" },
6858
+ { base: "info", hover: "infoHover", label: "Info" },
6859
+ { base: "warning", hover: "warningHover", label: "Warning" },
6860
+ { base: "danger", hover: "dangerHover", label: "Danger" }
6861
+ ],
6862
+ colorPalette: [
6863
+ {
6864
+ base: "#6366F1",
6865
+ hover: "#4F46E5",
6866
+ info: "#F59E0B",
6867
+ infoHover: "#D97706"
6868
+ },
6869
+ {
6870
+ base: "#818CF8",
6871
+ hover: "#6366F1",
6872
+ info: "#FBBF24",
6873
+ infoHover: "#F59E0B"
6874
+ },
6875
+ {
6876
+ base: "#4F46E5",
6877
+ hover: "#4338CA",
6878
+ info: "#F59E0B",
6879
+ infoHover: "#D97706"
6880
+ },
6881
+ {
6882
+ base: "#3730A3",
6883
+ hover: "#312E81",
6884
+ info: "#D97706",
6885
+ infoHover: "#B45309"
6886
+ },
6887
+ {
6888
+ base: "#7C3AED",
6889
+ hover: "#6D28D9",
6890
+ info: "#F97316",
6891
+ infoHover: "#EA580C"
6892
+ },
6893
+ {
6894
+ base: "#A78BFA",
6895
+ hover: "#8B5CF6",
6896
+ info: "#FB923C",
6897
+ infoHover: "#F97316"
6898
+ },
6899
+ {
6900
+ base: "#8B5CF6",
6901
+ hover: "#7C3AED",
6902
+ info: "#F97316",
6903
+ infoHover: "#EA580C"
6904
+ },
6905
+ {
6906
+ base: "#6D28D9",
6907
+ hover: "#5B21B6",
6908
+ info: "#EA580C",
6909
+ infoHover: "#C2410C"
6910
+ },
6911
+ {
6912
+ base: "#0EA5E9",
6913
+ hover: "#0284C7",
6914
+ info: "#F97316",
6915
+ infoHover: "#EA580C"
6916
+ },
6917
+ {
6918
+ base: "#38BDF8",
6919
+ hover: "#0EA5E9",
6920
+ info: "#FB923C",
6921
+ infoHover: "#F97316"
6922
+ },
6923
+ {
6924
+ base: "#3B82F6",
6925
+ hover: "#2563EB",
6926
+ info: "#F59E0B",
6927
+ infoHover: "#D97706"
6928
+ },
6929
+ {
6930
+ base: "#1D4ED8",
6931
+ hover: "#1E40AF",
6932
+ info: "#D97706",
6933
+ infoHover: "#B45309"
6934
+ },
6935
+ {
6936
+ base: "#06B6D4",
6937
+ hover: "#0891B2",
6938
+ info: "#A855F7",
6939
+ infoHover: "#9333EA"
6940
+ },
6941
+ {
6942
+ base: "#22D3EE",
6943
+ hover: "#06B6D4",
6944
+ info: "#C084FC",
6945
+ infoHover: "#A855F7"
6946
+ },
6947
+ {
6948
+ base: "#14B8A6",
6949
+ hover: "#0F766E",
6950
+ info: "#8B5CF6",
6951
+ infoHover: "#7C3AED"
6952
+ },
6953
+ {
6954
+ base: "#0D9488",
6955
+ hover: "#0F766E",
6956
+ info: "#7C3AED",
6957
+ infoHover: "#6D28D9"
6958
+ },
6959
+ {
6960
+ base: "#10B981",
6961
+ hover: "#059669",
6962
+ info: "#8B5CF6",
6963
+ infoHover: "#7C3AED"
6964
+ },
6965
+ {
6966
+ base: "#34D399",
6967
+ hover: "#10B981",
6968
+ info: "#A855F7",
6969
+ infoHover: "#9333EA"
6970
+ },
6971
+ {
6972
+ base: "#22C55E",
6973
+ hover: "#16A34A",
6974
+ info: "#7C3AED",
6975
+ infoHover: "#6D28D9"
6976
+ },
6977
+ {
6978
+ base: "#16A34A",
6979
+ hover: "#15803D",
6980
+ info: "#6D28D9",
6981
+ infoHover: "#5B21B6"
6982
+ },
6983
+ {
6984
+ base: "#84CC16",
6985
+ hover: "#65A30D",
6986
+ info: "#6366F1",
6987
+ infoHover: "#4F46E5"
6988
+ },
6989
+ {
6990
+ base: "#A3E635",
6991
+ hover: "#84CC16",
6992
+ info: "#818CF8",
6993
+ infoHover: "#6366F1"
6994
+ },
6995
+ {
6996
+ base: "#65A30D",
6997
+ hover: "#4D7C0F",
6998
+ info: "#4F46E5",
6999
+ infoHover: "#4338CA"
7000
+ },
7001
+ {
7002
+ base: "#4D7C0F",
7003
+ hover: "#3F6212",
7004
+ info: "#3730A3",
7005
+ infoHover: "#312E81"
7006
+ },
7007
+ {
7008
+ base: "#EAB308",
7009
+ hover: "#CA8A04",
7010
+ info: "#3B82F6",
7011
+ infoHover: "#2563EB"
7012
+ },
7013
+ {
7014
+ base: "#FACC15",
7015
+ hover: "#EAB308",
7016
+ info: "#60A5FA",
7017
+ infoHover: "#3B82F6"
7018
+ },
7019
+ {
7020
+ base: "#F59E0B",
7021
+ hover: "#D97706",
7022
+ info: "#2563EB",
7023
+ infoHover: "#1D4ED8"
7024
+ },
7025
+ {
7026
+ base: "#D97706",
7027
+ hover: "#B45309",
7028
+ info: "#1D4ED8",
7029
+ infoHover: "#1E40AF"
7030
+ },
7031
+ {
7032
+ base: "#F97316",
7033
+ hover: "#EA580C",
7034
+ info: "#0EA5E9",
7035
+ infoHover: "#0284C7"
7036
+ },
7037
+ {
7038
+ base: "#FB923C",
7039
+ hover: "#F97316",
7040
+ info: "#38BDF8",
7041
+ infoHover: "#0EA5E9"
7042
+ },
7043
+ {
7044
+ base: "#EA580C",
7045
+ hover: "#C2410C",
7046
+ info: "#0284C7",
7047
+ infoHover: "#0369A1"
7048
+ },
7049
+ {
7050
+ base: "#C2410C",
7051
+ hover: "#9A3412",
7052
+ info: "#0369A1",
7053
+ infoHover: "#075985"
7054
+ },
7055
+ {
7056
+ base: "#EF4444",
7057
+ hover: "#DC2626",
7058
+ info: "#0EA5E9",
7059
+ infoHover: "#0284C7"
7060
+ },
7061
+ {
7062
+ base: "#F87171",
7063
+ hover: "#EF4444",
7064
+ info: "#38BDF8",
7065
+ infoHover: "#0EA5E9"
7066
+ },
7067
+ {
7068
+ base: "#DC2626",
7069
+ hover: "#B91C1C",
7070
+ info: "#0284C7",
7071
+ infoHover: "#0369A1"
7072
+ },
7073
+ {
7074
+ base: "#B91C1C",
7075
+ hover: "#991B1B",
7076
+ info: "#0369A1",
7077
+ infoHover: "#075985"
7078
+ },
7079
+ {
7080
+ base: "#F43F5E",
7081
+ hover: "#E11D48",
7082
+ info: "#0EA5E9",
7083
+ infoHover: "#0284C7"
7084
+ },
7085
+ {
7086
+ base: "#FB7185",
7087
+ hover: "#F43F5E",
7088
+ info: "#38BDF8",
7089
+ infoHover: "#0EA5E9"
7090
+ },
7091
+ {
7092
+ base: "#E11D48",
7093
+ hover: "#BE123C",
7094
+ info: "#0284C7",
7095
+ infoHover: "#0369A1"
7096
+ },
7097
+ {
7098
+ base: "#BE123C",
7099
+ hover: "#9F1239",
7100
+ info: "#0369A1",
7101
+ infoHover: "#075985"
7102
+ },
7103
+ {
7104
+ base: "#EC4899",
7105
+ hover: "#DB2777",
7106
+ info: "#06B6D4",
7107
+ infoHover: "#0891B2"
7108
+ },
7109
+ {
7110
+ base: "#F472B6",
7111
+ hover: "#EC4899",
7112
+ info: "#22D3EE",
7113
+ infoHover: "#06B6D4"
7114
+ },
7115
+ {
7116
+ base: "#DB2777",
7117
+ hover: "#BE185D",
7118
+ info: "#0891B2",
7119
+ infoHover: "#0E7490"
7120
+ },
7121
+ {
7122
+ base: "#BE185D",
7123
+ hover: "#9D174D",
7124
+ info: "#0E7490",
7125
+ infoHover: "#155E75"
7126
+ },
7127
+ {
7128
+ base: "#D946EF",
7129
+ hover: "#C026D3",
7130
+ info: "#F59E0B",
7131
+ infoHover: "#D97706"
7132
+ },
7133
+ {
7134
+ base: "#E879F9",
7135
+ hover: "#D946EF",
7136
+ info: "#FBBF24",
7137
+ infoHover: "#F59E0B"
7138
+ },
7139
+ {
7140
+ base: "#C026D3",
7141
+ hover: "#A21CAF",
7142
+ info: "#D97706",
7143
+ infoHover: "#B45309"
7144
+ },
7145
+ {
7146
+ base: "#A21CAF",
7147
+ hover: "#86198F",
7148
+ info: "#B45309",
7149
+ infoHover: "#92400E"
7150
+ }
7151
+ ]
6610
7152
  };
6611
7153
 
6612
7154
  // src/components/theme-provider.tsx
6613
7155
  import { jsx as jsx36 } from "react/jsx-runtime";
6614
- var configDefaults = {
6615
- theme: settingConfig_default.theme,
6616
- fontSize: settingConfig_default.fontSize,
6617
- fontFamily: settingConfig_default.fontFamily,
6618
- colors: settingConfig_default.colors
7156
+ var FACTORY_DEFAULTS = {
7157
+ theme: settingConfig_default.defaults.theme,
7158
+ fontSize: settingConfig_default.defaults.fontSize,
7159
+ fontFamily: settingConfig_default.defaults.fontFamily,
7160
+ colors: settingConfig_default.defaults.colors
6619
7161
  };
7162
+ function loadJSON(key, fallback) {
7163
+ try {
7164
+ const raw = localStorage.getItem(key);
7165
+ if (raw) return { ...fallback, ...JSON.parse(raw) };
7166
+ } catch {
7167
+ }
7168
+ return fallback;
7169
+ }
7170
+ function saveJSON(key, value) {
7171
+ try {
7172
+ localStorage.setItem(key, JSON.stringify(value));
7173
+ } catch {
7174
+ }
7175
+ }
6620
7176
  var initialState = {
6621
- ...configDefaults,
7177
+ ...FACTORY_DEFAULTS,
6622
7178
  setTheme: () => null,
6623
7179
  setColors: () => null,
6624
7180
  setFontSize: () => null,
6625
7181
  setFontFamily: () => null,
7182
+ saveConfig: () => null,
6626
7183
  resetSettings: () => null
6627
7184
  };
6628
7185
  var ThemeProviderContext = createContext2(initialState);
6629
- var COLOR_PALETTE = [
6630
- { base: "#6366f1", hover: "#4f46e5" },
6631
- { base: "#8b5cf6", hover: "#7c3aed" },
6632
- { base: "#3b82f6", hover: "#2563eb" },
6633
- { base: "#10b981", hover: "#059669" },
6634
- { base: "#22c55e", hover: "#16a34a" },
6635
- { base: "#eab308", hover: "#ca8a04" },
6636
- { base: "#f59e0b", hover: "#d97706" },
6637
- { base: "#f97316", hover: "#ea580c" },
6638
- { base: "#ef4444", hover: "#dc2626" },
6639
- { base: "#ec4899", hover: "#db2777" }
6640
- ];
7186
+ var COLOR_PALETTE = settingConfig_default.colorPalette;
6641
7187
  function ThemeProvider({
6642
7188
  children,
6643
7189
  storageKey = "codego-ui-theme-settings",
7190
+ savedConfigKey = "codego-ui-saved-config",
6644
7191
  ...props
6645
7192
  }) {
6646
- const [settings, setSettings] = useState25(() => {
6647
- try {
6648
- const stored = localStorage.getItem(storageKey);
6649
- if (stored) return { ...configDefaults, ...JSON.parse(stored) };
6650
- } catch {
6651
- }
6652
- return configDefaults;
6653
- });
7193
+ const [savedConfig, setSavedConfig] = useState25(
7194
+ () => loadJSON(savedConfigKey, FACTORY_DEFAULTS)
7195
+ );
7196
+ const [settings, setSettings] = useState25(
7197
+ () => loadJSON(storageKey, savedConfig)
7198
+ );
6654
7199
  useEffect21(() => {
6655
- localStorage.setItem(storageKey, JSON.stringify(settings));
7200
+ saveJSON(storageKey, settings);
6656
7201
  }, [settings, storageKey]);
6657
7202
  useEffect21(() => {
6658
7203
  const root = window.document.documentElement;
@@ -6678,7 +7223,13 @@ function ThemeProvider({
6678
7223
  setColors: (colors) => setSettings((s) => ({ ...s, colors: { ...s.colors, ...colors } })),
6679
7224
  setFontSize: (fontSize) => setSettings((s) => ({ ...s, fontSize })),
6680
7225
  setFontFamily: (fontFamily) => setSettings((s) => ({ ...s, fontFamily })),
6681
- resetSettings: () => setSettings(configDefaults)
7226
+ // Save current live settings as the new persisted defaults
7227
+ saveConfig: () => {
7228
+ setSavedConfig(settings);
7229
+ saveJSON(savedConfigKey, settings);
7230
+ },
7231
+ // Reset live settings back to saved defaults
7232
+ resetSettings: () => setSettings(savedConfig)
6682
7233
  };
6683
7234
  return /* @__PURE__ */ jsx36(ThemeProviderContext.Provider, { ...props, value, children });
6684
7235
  }
@@ -7569,7 +8120,8 @@ function SectionBlock({
7569
8120
  }
7570
8121
 
7571
8122
  // src/components/ui/PanelSettings.tsx
7572
- import { RotateCcw as RotateCcw2 } from "lucide-react";
8123
+ import * as React39 from "react";
8124
+ import { RotateCcw as RotateCcw2, Save } from "lucide-react";
7573
8125
 
7574
8126
  // src/components/ui/tabs.tsx
7575
8127
  import * as React38 from "react";
@@ -7655,30 +8207,10 @@ function Tabs({
7655
8207
 
7656
8208
  // src/components/ui/PanelSettings.tsx
7657
8209
  import { jsx as jsx48, jsxs as jsxs42 } from "react/jsx-runtime";
7658
- var FONT_SIZES = [
7659
- { value: "14px", label: "Small (14px)" },
7660
- { value: "16px", label: "Medium (16px)" },
7661
- { value: "18px", label: "Large (18px)" },
7662
- { value: "20px", label: "Extra Large (20px)" }
7663
- ];
7664
- var FONT_FAMILIES = [
7665
- { value: '"Space Grotesk", "Inter", sans-serif', label: "Space Grotesk" },
7666
- { value: '"Inter", sans-serif', label: "Inter" },
7667
- { value: '"JetBrains Mono", monospace', label: "JetBrains Mono" },
7668
- { value: "system-ui, sans-serif", label: "System UI" }
7669
- ];
7670
- var THEME_OPTIONS = [
7671
- { value: "light", label: "Light" },
7672
- { value: "dark", label: "Dark" },
7673
- { value: "system", label: "System" }
7674
- ];
7675
- var COLOR_PAIRS = [
7676
- { base: "primary", hover: "primaryHover", label: "Primary" },
7677
- { base: "secondary", hover: "secondaryHover", label: "Secondary" },
7678
- { base: "info", hover: "infoHover", label: "Info" },
7679
- { base: "warning", hover: "warningHover", label: "Warning" },
7680
- { base: "danger", hover: "dangerHover", label: "Danger" }
7681
- ];
8210
+ var THEME_OPTIONS = settingConfig_default.themeOptions;
8211
+ var FONT_SIZES = settingConfig_default.fontSizes;
8212
+ var FONT_FAMILIES = settingConfig_default.fontFamilies;
8213
+ var COLOR_PAIRS = settingConfig_default.colorPairs;
7682
8214
  function SettingRow({ label, description, children }) {
7683
8215
  return /* @__PURE__ */ jsxs42("div", { className: "flex items-start justify-between gap-4 py-3 border-b border-border/60 last:border-0", children: [
7684
8216
  /* @__PURE__ */ jsxs42("div", { className: "min-w-0", children: [
@@ -7726,8 +8258,8 @@ function ColorsPanel({ onColorsChange }) {
7726
8258
  type: "button",
7727
8259
  title: c.base,
7728
8260
  onClick: () => {
7729
- setColors({ primary: c.base, primaryHover: c.hover });
7730
- onColorsChange?.({ primary: c.base, primaryHover: c.hover });
8261
+ setColors({ primary: c.base, primaryHover: c.hover, info: c.info, infoHover: c.infoHover });
8262
+ onColorsChange?.({ primary: c.base, primaryHover: c.hover, info: c.info, infoHover: c.infoHover });
7731
8263
  },
7732
8264
  className: cn(
7733
8265
  "h-7 w-full rounded-md border border-white/10 transition-transform hover:scale-110 focus:outline-none focus:ring-2 focus:ring-ring",
@@ -7803,10 +8335,18 @@ function PanelSettings({
7803
8335
  onColorsChange,
7804
8336
  onFontSizeChange,
7805
8337
  onFontFamilyChange,
8338
+ onSave,
7806
8339
  onReset,
7807
8340
  className
7808
8341
  }) {
7809
- const { resetSettings } = useTheme();
8342
+ const { saveConfig, resetSettings } = useTheme();
8343
+ const [saved, setSaved] = React39.useState(false);
8344
+ const handleSave = () => {
8345
+ saveConfig();
8346
+ onSave?.();
8347
+ setSaved(true);
8348
+ setTimeout(() => setSaved(false), 2e3);
8349
+ };
7810
8350
  const handleReset = () => {
7811
8351
  resetSettings();
7812
8352
  onReset?.();
@@ -7830,10 +8370,16 @@ function PanelSettings({
7830
8370
  ];
7831
8371
  return /* @__PURE__ */ jsxs42("div", { className: cn("flex flex-col gap-4", className), children: [
7832
8372
  /* @__PURE__ */ jsx48(Tabs, { items: tabs, defaultValue: defaultTab, variant: "pill" }),
7833
- /* @__PURE__ */ jsx48("div", { className: "flex justify-end pt-1", children: /* @__PURE__ */ jsxs42(Button, { variant: "outline", size: "sm", onClick: handleReset, children: [
7834
- /* @__PURE__ */ jsx48(RotateCcw2, { className: "h-3.5 w-3.5 mr-1.5" }),
7835
- "Reset to Defaults"
7836
- ] }) })
8373
+ /* @__PURE__ */ jsxs42("div", { className: "flex justify-end gap-2 pt-1", children: [
8374
+ /* @__PURE__ */ jsxs42(Button, { variant: "outline", size: "sm", onClick: handleReset, children: [
8375
+ /* @__PURE__ */ jsx48(RotateCcw2, { className: "h-3.5 w-3.5 mr-1.5" }),
8376
+ "Reset"
8377
+ ] }),
8378
+ /* @__PURE__ */ jsxs42(Button, { size: "sm", onClick: handleSave, children: [
8379
+ /* @__PURE__ */ jsx48(Save, { className: "h-3.5 w-3.5 mr-1.5" }),
8380
+ saved ? "Saved!" : "Save"
8381
+ ] })
8382
+ ] })
7837
8383
  ] });
7838
8384
  }
7839
8385
 
@@ -7853,7 +8399,7 @@ function Skeleton({
7853
8399
  }
7854
8400
 
7855
8401
  // src/components/ui/slider.tsx
7856
- import * as React39 from "react";
8402
+ import * as React40 from "react";
7857
8403
  import { jsx as jsx50, jsxs as jsxs43 } from "react/jsx-runtime";
7858
8404
  function pct(val, min, max) {
7859
8405
  return (val - min) / (max - min) * 100;
@@ -7873,8 +8419,8 @@ function Slider({
7873
8419
  showValue = false,
7874
8420
  className
7875
8421
  }) {
7876
- const [internal, setInternal] = React39.useState(defaultValue);
7877
- const [hovering, setHovering] = React39.useState(false);
8422
+ const [internal, setInternal] = React40.useState(defaultValue);
8423
+ const [hovering, setHovering] = React40.useState(false);
7878
8424
  const val = controlled ?? internal;
7879
8425
  function handleChange(e) {
7880
8426
  const v = Number(e.target.value);
@@ -7951,8 +8497,8 @@ function RangeSlider({
7951
8497
  showValue = false,
7952
8498
  className
7953
8499
  }) {
7954
- const [internal, setInternal] = React39.useState(defaultValue);
7955
- const [active, setActive] = React39.useState(null);
8500
+ const [internal, setInternal] = React40.useState(defaultValue);
8501
+ const [active, setActive] = React40.useState(null);
7956
8502
  const val = controlled ?? internal;
7957
8503
  function handleChange(idx, e) {
7958
8504
  const v = Number(e.target.value);
@@ -7975,7 +8521,7 @@ function RangeSlider({
7975
8521
  /* @__PURE__ */ jsx50("div", { className: "absolute w-full h-1.5 rounded-full bg-muted", children: /* @__PURE__ */ jsx50("div", { className: "absolute h-full rounded-full bg-primary", style: { left: `${p0}%`, width: `${p1 - p0}%` } }) }),
7976
8522
  [0, 1].map((idx) => {
7977
8523
  const p = idx === 0 ? p0 : p1;
7978
- return /* @__PURE__ */ jsxs43(React39.Fragment, { children: [
8524
+ return /* @__PURE__ */ jsxs43(React40.Fragment, { children: [
7979
8525
  showTooltip && active === idx && !disabled && /* @__PURE__ */ jsx50(
7980
8526
  "div",
7981
8527
  {
@@ -8086,7 +8632,7 @@ function StatCard({
8086
8632
  }
8087
8633
 
8088
8634
  // src/components/ui/stepper.tsx
8089
- import * as React40 from "react";
8635
+ import * as React41 from "react";
8090
8636
  import { Check as Check6, X as X11 } from "lucide-react";
8091
8637
  import { jsx as jsx52, jsxs as jsxs45 } from "react/jsx-runtime";
8092
8638
  function getStatus(idx, current) {
@@ -8109,7 +8655,7 @@ function Stepper({
8109
8655
  clickable = false,
8110
8656
  className
8111
8657
  }) {
8112
- const [internal, setInternal] = React40.useState(defaultCurrent);
8658
+ const [internal, setInternal] = React41.useState(defaultCurrent);
8113
8659
  const current = controlled ?? internal;
8114
8660
  function go(idx) {
8115
8661
  if (!clickable) return;
@@ -8124,7 +8670,7 @@ function Stepper({
8124
8670
  ), children: steps.map((step, i) => {
8125
8671
  const status = getStatus(i, current);
8126
8672
  const isLast = i === steps.length - 1;
8127
- return /* @__PURE__ */ jsx52(React40.Fragment, { children: /* @__PURE__ */ jsxs45("div", { className: cn(
8673
+ return /* @__PURE__ */ jsx52(React41.Fragment, { children: /* @__PURE__ */ jsxs45("div", { className: cn(
8128
8674
  "flex",
8129
8675
  isHorizontal ? "flex-col items-center flex-1" : "flex-row gap-4"
8130
8676
  ), children: [
@@ -8168,7 +8714,7 @@ function Stepper({
8168
8714
  }
8169
8715
 
8170
8716
  // src/components/ui/table.tsx
8171
- import * as React41 from "react";
8717
+ import * as React42 from "react";
8172
8718
  import { ChevronLeft as ChevronLeft5, ChevronRight as ChevronRight8, Search as Search5, Trash2 as Trash23, ChevronsUpDown as ChevronsUpDown2, ChevronUp as ChevronUp2, ChevronDown as ChevronDown7, X as X12 } from "lucide-react";
8173
8719
  import { Fragment as Fragment13, jsx as jsx53, jsxs as jsxs46 } from "react/jsx-runtime";
8174
8720
  var BADGE_COLORS = {
@@ -8193,11 +8739,11 @@ function Table({
8193
8739
  idKey = "id",
8194
8740
  className
8195
8741
  }) {
8196
- const [search, setSearch] = React41.useState("");
8197
- const [currentPage, setCurrentPage] = React41.useState(1);
8198
- const [selectedIds, setSelectedIds] = React41.useState([]);
8199
- const [sortKey, setSortKey] = React41.useState(null);
8200
- const [sortDir, setSortDir] = React41.useState(null);
8742
+ const [search, setSearch] = React42.useState("");
8743
+ const [currentPage, setCurrentPage] = React42.useState(1);
8744
+ const [selectedIds, setSelectedIds] = React42.useState([]);
8745
+ const [sortKey, setSortKey] = React42.useState(null);
8746
+ const [sortDir, setSortDir] = React42.useState(null);
8201
8747
  const handleSort = (key) => {
8202
8748
  if (sortKey !== key) {
8203
8749
  setSortKey(key);
@@ -8211,7 +8757,7 @@ function Table({
8211
8757
  setSortKey(null);
8212
8758
  setSortDir(null);
8213
8759
  };
8214
- const filteredData = React41.useMemo(() => {
8760
+ const filteredData = React42.useMemo(() => {
8215
8761
  let d = search ? data.filter(
8216
8762
  (item) => Object.values(item).some(
8217
8763
  (val) => val && typeof val === "string" && val.toLowerCase().includes(search.toLowerCase())
@@ -8229,18 +8775,18 @@ function Table({
8229
8775
  }, [data, search, sortKey, sortDir]);
8230
8776
  const totalPages = Math.max(1, Math.ceil(filteredData.length / itemsPerPage));
8231
8777
  const safePage = Math.min(currentPage, totalPages);
8232
- const paginatedData = React41.useMemo(() => {
8778
+ const paginatedData = React42.useMemo(() => {
8233
8779
  if (!pagination) return filteredData;
8234
8780
  const start = (safePage - 1) * itemsPerPage;
8235
8781
  return filteredData.slice(start, start + itemsPerPage);
8236
8782
  }, [filteredData, pagination, safePage, itemsPerPage]);
8237
- React41.useEffect(() => {
8783
+ React42.useEffect(() => {
8238
8784
  setCurrentPage(1);
8239
8785
  }, [search]);
8240
8786
  const handleSelectAll = (checked) => setSelectedIds(checked ? paginatedData.map((item) => String(item[idKey])) : []);
8241
8787
  const handleSelect = (id, checked) => setSelectedIds((prev) => checked ? [...prev, id] : prev.filter((i) => i !== id));
8242
8788
  const allSelected = paginatedData.length > 0 && selectedIds.length === paginatedData.length;
8243
- const pagePills = React41.useMemo(() => {
8789
+ const pagePills = React42.useMemo(() => {
8244
8790
  if (totalPages <= 5) return Array.from({ length: totalPages }, (_, i) => i + 1);
8245
8791
  if (safePage <= 3) return [1, 2, 3, 4, 5];
8246
8792
  if (safePage >= totalPages - 2) return [totalPages - 4, totalPages - 3, totalPages - 2, totalPages - 1, totalPages];
@@ -8469,7 +9015,7 @@ function Table({
8469
9015
  }
8470
9016
 
8471
9017
  // src/components/ui/tag-input.tsx
8472
- import * as React42 from "react";
9018
+ import * as React43 from "react";
8473
9019
  import { jsx as jsx54, jsxs as jsxs47 } from "react/jsx-runtime";
8474
9020
  function TagInput({
8475
9021
  value: controlled,
@@ -8481,9 +9027,9 @@ function TagInput({
8481
9027
  disabled = false,
8482
9028
  className
8483
9029
  }) {
8484
- const [internal, setInternal] = React42.useState(defaultValue);
8485
- const [input, setInput] = React42.useState("");
8486
- const inputRef = React42.useRef(null);
9030
+ const [internal, setInternal] = React43.useState(defaultValue);
9031
+ const [input, setInput] = React43.useState("");
9032
+ const inputRef = React43.useRef(null);
8487
9033
  const tags = controlled ?? internal;
8488
9034
  function addTag(raw) {
8489
9035
  const tag = raw.trim();
@@ -8588,9 +9134,9 @@ function Timeline({ items, align = "left", className }) {
8588
9134
  }
8589
9135
 
8590
9136
  // src/components/ui/toggle-switch.tsx
8591
- import * as React43 from "react";
9137
+ import * as React44 from "react";
8592
9138
  import { jsx as jsx56, jsxs as jsxs49 } from "react/jsx-runtime";
8593
- var ToggleSwitch = React43.forwardRef(
9139
+ var ToggleSwitch = React44.forwardRef(
8594
9140
  ({
8595
9141
  className,
8596
9142
  inline = false,
@@ -8608,10 +9154,10 @@ var ToggleSwitch = React43.forwardRef(
8608
9154
  disabled,
8609
9155
  ...props
8610
9156
  }, ref) => {
8611
- const toggleId = id ?? React43.useId();
9157
+ const toggleId = id ?? React44.useId();
8612
9158
  const trackW = width ? typeof width === "number" ? `${width}px` : width : "2.75rem";
8613
9159
  const trackH = height ? typeof height === "number" ? `${height}px` : height : "1.5rem";
8614
- const [internalChecked, setInternalChecked] = React43.useState(defaultChecked ?? false);
9160
+ const [internalChecked, setInternalChecked] = React44.useState(defaultChecked ?? false);
8615
9161
  const isControlled = checked !== void 0;
8616
9162
  const isOn = accepted ? true : declined ? false : isControlled ? checked : internalChecked;
8617
9163
  const stateColor = accepted ? acceptedColor ?? "#22c55e" : declined ? declinedColor ?? "#ef4444" : isOn ? void 0 : void 0;
@@ -8681,7 +9227,7 @@ var ToggleSwitch = React43.forwardRef(
8681
9227
  ToggleSwitch.displayName = "ToggleSwitch";
8682
9228
 
8683
9229
  // src/components/ui/tree-view.tsx
8684
- import * as React44 from "react";
9230
+ import * as React45 from "react";
8685
9231
  import { ChevronRight as ChevronRight9, Folder, FolderOpen, File } from "lucide-react";
8686
9232
  import { jsx as jsx57, jsxs as jsxs50 } from "react/jsx-runtime";
8687
9233
  function TreeNodeItem({ node, depth, selected, expanded, onToggleExpand, onSelect, multiple }) {
@@ -8735,8 +9281,8 @@ function TreeView({
8735
9281
  className
8736
9282
  }) {
8737
9283
  const init = defaultSelected ? Array.isArray(defaultSelected) ? defaultSelected : [defaultSelected] : [];
8738
- const [internal, setInternal] = React44.useState(init);
8739
- const [expanded, setExpanded] = React44.useState(defaultExpanded);
9284
+ const [internal, setInternal] = React45.useState(init);
9285
+ const [expanded, setExpanded] = React45.useState(defaultExpanded);
8740
9286
  const selected = controlled ? Array.isArray(controlled) ? controlled : [controlled] : internal;
8741
9287
  function handleSelect(id) {
8742
9288
  let next;
@@ -8767,7 +9313,7 @@ function TreeView({
8767
9313
  }
8768
9314
 
8769
9315
  // src/components/ui/widget.tsx
8770
- import * as React45 from "react";
9316
+ import * as React46 from "react";
8771
9317
  import { jsx as jsx58, jsxs as jsxs51 } from "react/jsx-runtime";
8772
9318
  var iconColorMap = {
8773
9319
  primary: "bg-primary/10 text-primary",
@@ -8796,8 +9342,8 @@ var variantMap = {
8796
9342
  outline: "bg-transparent border-2"
8797
9343
  };
8798
9344
  function useCountUp(target, enabled, duration = 1e3) {
8799
- const [display, setDisplay] = React45.useState(enabled ? 0 : target);
8800
- React45.useEffect(() => {
9345
+ const [display, setDisplay] = React46.useState(enabled ? 0 : target);
9346
+ React46.useEffect(() => {
8801
9347
  if (!enabled) {
8802
9348
  setDisplay(target);
8803
9349
  return;
@@ -8910,7 +9456,7 @@ function Widget({
8910
9456
  }
8911
9457
 
8912
9458
  // src/components/ui/wizard.tsx
8913
- import * as React46 from "react";
9459
+ import * as React47 from "react";
8914
9460
  import { Check as Check7, X as X13, ChevronLeft as ChevronLeft6, ChevronRight as ChevronRight10, AlertCircle } from "lucide-react";
8915
9461
  import { Fragment as Fragment15, jsx as jsx59, jsxs as jsxs52 } from "react/jsx-runtime";
8916
9462
  var SIZE_MAP = {
@@ -8934,7 +9480,7 @@ function HeaderDefault({
8934
9480
  return /* @__PURE__ */ jsx59("div", { className: "flex items-start w-full", children: steps.map((step, i) => {
8935
9481
  const status = stepStatus(i, current);
8936
9482
  const isLast = i === steps.length - 1;
8937
- return /* @__PURE__ */ jsx59(React46.Fragment, { children: /* @__PURE__ */ jsxs52("div", { className: "flex flex-col items-center flex-1 min-w-0", children: [
9483
+ return /* @__PURE__ */ jsx59(React47.Fragment, { children: /* @__PURE__ */ jsxs52("div", { className: "flex flex-col items-center flex-1 min-w-0", children: [
8938
9484
  /* @__PURE__ */ jsxs52("div", { className: "flex items-center w-full", children: [
8939
9485
  i > 0 && /* @__PURE__ */ jsx59("div", { className: cn("flex-1 h-0.5 transition-colors", i <= current ? "bg-primary" : "bg-border") }),
8940
9486
  /* @__PURE__ */ jsx59(
@@ -9162,7 +9708,7 @@ function WizardPanel({
9162
9708
  const isFirst = current === 0;
9163
9709
  const isLast = current === steps.length - 1;
9164
9710
  const isSidebar = variant === "sidebar";
9165
- const [validationError, setValidationError] = React46.useState(null);
9711
+ const [validationError, setValidationError] = React47.useState(null);
9166
9712
  const handleNext = () => {
9167
9713
  const validate = steps[current]?.validate;
9168
9714
  if (validate) {
@@ -9266,7 +9812,7 @@ function Wizard({
9266
9812
  className,
9267
9813
  contentClassName
9268
9814
  }) {
9269
- const [internalStep, setInternalStep] = React46.useState(defaultStep);
9815
+ const [internalStep, setInternalStep] = React47.useState(defaultStep);
9270
9816
  const current = controlledStep ?? internalStep;
9271
9817
  const go = (idx) => {
9272
9818
  const clamped = Math.max(0, Math.min(steps.length - 1, idx));
@@ -9281,7 +9827,7 @@ function Wizard({
9281
9827
  }
9282
9828
  go(current + 1);
9283
9829
  };
9284
- React46.useEffect(() => {
9830
+ React47.useEffect(() => {
9285
9831
  if (layout !== "modal" || !isOpen || unchange) return;
9286
9832
  const handler = (e) => {
9287
9833
  if (e.key === "Escape") onClose?.();