@juv/codego-react-ui 3.2.8 → 3.3.1

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.
@@ -271,7 +271,7 @@ var CodegoUI = (() => {
271
271
  }
272
272
  console.error(error);
273
273
  };
274
- var Children = {
274
+ var Children2 = {
275
275
  map: mapChildren,
276
276
  forEach: function(children, forEachFunc, forEachContext) {
277
277
  mapChildren(
@@ -303,7 +303,7 @@ var CodegoUI = (() => {
303
303
  }
304
304
  };
305
305
  exports.Activity = REACT_ACTIVITY_TYPE;
306
- exports.Children = Children;
306
+ exports.Children = Children2;
307
307
  exports.Component = Component;
308
308
  exports.Fragment = REACT_FRAGMENT_TYPE;
309
309
  exports.Profiler = REACT_PROFILER_TYPE;
@@ -69673,15 +69673,16 @@ ${n2.shaderPreludeCode.vertexSource}`, define: n2.shaderDefine }, defaultProject
69673
69673
  }
69674
69674
  function FieldRenderer({ field, value, onChange }) {
69675
69675
  if (field.render) return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_jsx_runtime32.Fragment, { children: field.render(value, onChange) });
69676
+ const toLabelValue = (o) => {
69677
+ if (typeof o === "string") return { label: o, value: o };
69678
+ if (Array.isArray(o)) return { label: o[0], value: o[1] };
69679
+ return o;
69680
+ };
69676
69681
  const strOptions = (field.options ?? []).map(
69677
- (o) => typeof o === "string" ? o : o.value
69678
- );
69679
- const comboOptions = (field.options ?? []).map(
69680
- (o) => typeof o === "string" ? { label: o, value: o } : o
69681
- );
69682
- const radioOptions = (field.options ?? []).map(
69683
- (o) => typeof o === "string" ? { label: o, value: o } : o
69682
+ (o) => typeof o === "string" ? o : Array.isArray(o) ? o[1] : o.value
69684
69683
  );
69684
+ const comboOptions = (field.options ?? []).map(toLabelValue);
69685
+ const radioOptions = (field.options ?? []).map(toLabelValue);
69685
69686
  switch (field.type) {
69686
69687
  case "textarea":
69687
69688
  return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(Textarea, { value: value ?? "", onChange: (e) => onChange(e.target.value), placeholder: field.placeholder, rows: 3 });
@@ -69943,8 +69944,7 @@ ${n2.shaderPreludeCode.vertexSource}`, define: n2.shaderDefine }, defaultProject
69943
69944
  itemId,
69944
69945
  onClose,
69945
69946
  onSuccess,
69946
- notif,
69947
- width
69947
+ notif
69948
69948
  }) {
69949
69949
  const [loading, setLoading] = React28.useState(false);
69950
69950
  const [error, setError] = React28.useState(null);
@@ -69966,7 +69966,7 @@ ${n2.shaderPreludeCode.vertexSource}`, define: n2.shaderDefine }, defaultProject
69966
69966
  {
69967
69967
  title: "Confirm Delete",
69968
69968
  onClose,
69969
- width,
69969
+ width: "lg",
69970
69970
  footer: /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(import_jsx_runtime32.Fragment, { children: [
69971
69971
  /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(Button, { variant: "outline", size: "sm", onClick: onClose, disabled: loading, children: "Cancel" }),
69972
69972
  /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(Button, { variant: "danger", size: "sm", onClick: handleDelete, disabled: loading, children: [
@@ -69986,17 +69986,19 @@ ${n2.shaderPreludeCode.vertexSource}`, define: n2.shaderDefine }, defaultProject
69986
69986
  defaultIcon,
69987
69987
  defaultLabel,
69988
69988
  defaultVariant,
69989
+ defaultSize,
69989
69990
  onClick
69990
69991
  }) {
69991
69992
  const mode = cfg?.displayMode ?? "icon";
69992
69993
  const icon = cfg?.icon ?? defaultIcon;
69993
69994
  const label = cfg?.label ?? defaultLabel;
69995
+ const buttonSize = cfg?.size ?? defaultSize ?? "xs";
69994
69996
  return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
69995
69997
  Button,
69996
69998
  {
69997
69999
  type: "button",
69998
70000
  title: label,
69999
- size: cfg?.size ?? "xs",
70001
+ size: buttonSize,
70000
70002
  variant: cfg?.variant ?? defaultVariant,
70001
70003
  rounded: cfg?.rounded ?? "lg",
70002
70004
  gradientFrom: cfg?.gradientFrom,
@@ -70105,6 +70107,7 @@ ${n2.shaderPreludeCode.vertexSource}`, define: n2.shaderDefine }, defaultProject
70105
70107
  defaultIcon: extra.icon,
70106
70108
  defaultLabel: extra.label ?? extra.key,
70107
70109
  defaultVariant: extra.variant ?? "outline",
70110
+ defaultSize: defaultActions.actionsSize,
70108
70111
  onClick: () => extra.onClick(item)
70109
70112
  },
70110
70113
  extra.key
@@ -70483,7 +70486,6 @@ ${n2.shaderPreludeCode.vertexSource}`, define: n2.shaderDefine }, defaultProject
70483
70486
  baseUrl: defaultActions.baseUrl,
70484
70487
  itemId: String(deleteItem[actionIdKey] ?? ""),
70485
70488
  notif: defaultActions.onSuccessNotif,
70486
- width: defaultActions.modalWidth,
70487
70489
  onClose: () => setDeleteItem(null),
70488
70490
  onSuccess: (deleted) => {
70489
70491
  setTableData(
@@ -70579,17 +70581,19 @@ ${n2.shaderPreludeCode.vertexSource}`, define: n2.shaderDefine }, defaultProject
70579
70581
  defaultIcon,
70580
70582
  defaultLabel,
70581
70583
  defaultVariant,
70584
+ defaultSize,
70582
70585
  onClick
70583
70586
  }) {
70584
70587
  const mode = cfg?.displayMode ?? "icon";
70585
70588
  const icon = cfg?.icon ?? defaultIcon;
70586
70589
  const label = cfg?.label ?? defaultLabel;
70590
+ const buttonSize = cfg?.size ?? defaultSize ?? "xs";
70587
70591
  return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
70588
70592
  Button,
70589
70593
  {
70590
70594
  type: "button",
70591
70595
  title: label,
70592
- size: cfg?.size ?? "xs",
70596
+ size: buttonSize,
70593
70597
  variant: cfg?.variant ?? defaultVariant,
70594
70598
  rounded: cfg?.rounded ?? "lg",
70595
70599
  gradientFrom: cfg?.gradientFrom,
@@ -70633,15 +70637,16 @@ ${n2.shaderPreludeCode.vertexSource}`, define: n2.shaderDefine }, defaultProject
70633
70637
  }
70634
70638
  function DGFieldRenderer({ field, value, onChange }) {
70635
70639
  if (field.render) return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_jsx_runtime33.Fragment, { children: field.render(value, onChange) });
70640
+ const toLabelValue = (o) => {
70641
+ if (typeof o === "string") return { label: o, value: o };
70642
+ if (Array.isArray(o)) return { label: o[0], value: o[1] };
70643
+ return o;
70644
+ };
70636
70645
  const strOptions = (field.options ?? []).map(
70637
- (o) => typeof o === "string" ? o : o.value
70638
- );
70639
- const comboOptions = (field.options ?? []).map(
70640
- (o) => typeof o === "string" ? { label: o, value: o } : o
70641
- );
70642
- const radioOptions = (field.options ?? []).map(
70643
- (o) => typeof o === "string" ? { label: o, value: o } : o
70646
+ (o) => typeof o === "string" ? o : Array.isArray(o) ? o[1] : o.value
70644
70647
  );
70648
+ const comboOptions = (field.options ?? []).map(toLabelValue);
70649
+ const radioOptions = (field.options ?? []).map(toLabelValue);
70645
70650
  switch (field.type) {
70646
70651
  case "textarea":
70647
70652
  return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(Textarea, { value: value ?? "", onChange: (e) => onChange(e.target.value), placeholder: field.placeholder, rows: 3 });
@@ -70812,8 +70817,7 @@ ${n2.shaderPreludeCode.vertexSource}`, define: n2.shaderDefine }, defaultProject
70812
70817
  itemId,
70813
70818
  onClose,
70814
70819
  onSuccess,
70815
- notif,
70816
- width
70820
+ notif
70817
70821
  }) {
70818
70822
  const [loading, setLoading] = React29.useState(false);
70819
70823
  const [error, setError] = React29.useState(null);
@@ -70835,7 +70839,7 @@ ${n2.shaderPreludeCode.vertexSource}`, define: n2.shaderDefine }, defaultProject
70835
70839
  {
70836
70840
  title: "Confirm Delete",
70837
70841
  onClose,
70838
- width,
70842
+ width: "lg",
70839
70843
  footer: /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_jsx_runtime33.Fragment, { children: [
70840
70844
  /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("button", { onClick: onClose, disabled: loading, className: "px-4 py-1.5 text-sm rounded-xl border border-border hover:bg-accent transition-colors", children: "Cancel" }),
70841
70845
  /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("button", { onClick: handleDelete, disabled: loading, className: "px-4 py-1.5 text-sm rounded-xl bg-danger text-danger-foreground hover:bg-danger-hover transition-colors flex items-center gap-1.5", children: [
@@ -70956,6 +70960,7 @@ ${n2.shaderPreludeCode.vertexSource}`, define: n2.shaderDefine }, defaultProject
70956
70960
  defaultIcon: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(Eye, { className: "h-3.5 w-3.5" }),
70957
70961
  defaultLabel: "View",
70958
70962
  defaultVariant: "outline",
70963
+ defaultSize: defaultActions.actionsSize,
70959
70964
  onClick: () => setViewItem(row)
70960
70965
  }
70961
70966
  ),
@@ -70966,6 +70971,7 @@ ${n2.shaderPreludeCode.vertexSource}`, define: n2.shaderDefine }, defaultProject
70966
70971
  defaultIcon: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(Pencil, { className: "h-3.5 w-3.5" }),
70967
70972
  defaultLabel: "Edit",
70968
70973
  defaultVariant: "outline",
70974
+ defaultSize: defaultActions.actionsSize,
70969
70975
  onClick: () => setEditItem(row)
70970
70976
  }
70971
70977
  ),
@@ -70976,6 +70982,7 @@ ${n2.shaderPreludeCode.vertexSource}`, define: n2.shaderDefine }, defaultProject
70976
70982
  defaultIcon: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(Trash, { className: "h-3.5 w-3.5" }),
70977
70983
  defaultLabel: "Delete",
70978
70984
  defaultVariant: "danger",
70985
+ defaultSize: defaultActions.actionsSize,
70979
70986
  onClick: () => setDeleteItem(row)
70980
70987
  }
70981
70988
  ),
@@ -70986,6 +70993,7 @@ ${n2.shaderPreludeCode.vertexSource}`, define: n2.shaderDefine }, defaultProject
70986
70993
  defaultIcon: extra.icon,
70987
70994
  defaultLabel: extra.label ?? extra.key,
70988
70995
  defaultVariant: extra.variant ?? "outline",
70996
+ defaultSize: defaultActions.actionsSize,
70989
70997
  onClick: () => extra.onClick(row)
70990
70998
  },
70991
70999
  extra.key
@@ -71219,7 +71227,6 @@ ${n2.shaderPreludeCode.vertexSource}`, define: n2.shaderDefine }, defaultProject
71219
71227
  baseUrl: defaultActions.baseUrl,
71220
71228
  itemId: String(deleteItem[actionIdKey] ?? ""),
71221
71229
  notif: defaultActions.onSuccessNotif,
71222
- width: defaultActions.modalWidth,
71223
71230
  onClose: () => setDeleteItem(null),
71224
71231
  onSuccess: (deleted) => {
71225
71232
  setTableData((prev) => prev.filter((r2) => String(r2[actionIdKey]) !== String(deleted[actionIdKey])));
@@ -74441,6 +74448,8 @@ ${n2.shaderPreludeCode.vertexSource}`, define: n2.shaderDefine }, defaultProject
74441
74448
  // src/components/ui/panel.tsx
74442
74449
  var import_jsx_runtime46 = __toESM(require_jsx_runtime(), 1);
74443
74450
  var PanelCollapsedContext = React42.createContext(false);
74451
+ var PanelGroupsContext = React42.createContext({ expandedGroups: /* @__PURE__ */ new Set(), onGroupToggle: () => {
74452
+ } });
74444
74453
  function PanelThemeToggle() {
74445
74454
  const { theme, setTheme } = useTheme();
74446
74455
  return /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(
@@ -74467,15 +74476,109 @@ ${n2.shaderPreludeCode.vertexSource}`, define: n2.shaderDefine }, defaultProject
74467
74476
  topbar,
74468
74477
  topbarTrailing,
74469
74478
  defaultCollapsed = false,
74479
+ collapsed: controlledCollapsed,
74480
+ onCollapsedChange,
74470
74481
  collapsible = false,
74471
74482
  showThemeToggle = false,
74472
74483
  defaultPage,
74484
+ currentPage: controlledPage,
74485
+ onPageChange,
74473
74486
  height = "h-[520px]",
74474
74487
  children,
74475
- className
74488
+ className,
74489
+ loading = false,
74490
+ emptyState,
74491
+ error = null,
74492
+ showGroupDividers = false,
74493
+ expandedGroups: controlledExpandedGroups,
74494
+ onGroupToggle,
74495
+ theme: themeProp,
74496
+ collapseIcon,
74497
+ expandIcon,
74498
+ meta,
74499
+ actions,
74500
+ keyboardNavigation = false,
74501
+ draggable = false,
74502
+ onSidebarReorder,
74503
+ animationDuration = 200,
74504
+ animationEasing = "ease-in-out",
74505
+ sidebarTooltip,
74506
+ mobileBreakpoint = 768,
74507
+ mobileCollapsed: controlledMobileCollapsed,
74508
+ onMobileCollapseChange
74476
74509
  }) {
74477
- const [collapsed, setCollapsed] = React42.useState(defaultCollapsed);
74478
- return /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(PanelCollapsedContext.Provider, { value: collapsed, children: /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(
74510
+ const [internalCollapsed, setInternalCollapsed] = React42.useState(defaultCollapsed);
74511
+ const [internalPage, setInternalPage] = React42.useState(defaultPage || "");
74512
+ const [internalExpandedGroups, setInternalExpandedGroups] = React42.useState(
74513
+ new Set(controlledExpandedGroups)
74514
+ );
74515
+ const [isMobile, setIsMobile] = React42.useState(false);
74516
+ const [internalMobileCollapsed, setInternalMobileCollapsed] = React42.useState(true);
74517
+ const isCollapsed = controlledCollapsed !== void 0 ? controlledCollapsed : internalCollapsed;
74518
+ const currentPage = controlledPage !== void 0 ? controlledPage : internalPage;
74519
+ const expandedGroups = controlledExpandedGroups !== void 0 ? new Set(controlledExpandedGroups) : internalExpandedGroups;
74520
+ const mobileCollapsed = controlledMobileCollapsed !== void 0 ? controlledMobileCollapsed : internalMobileCollapsed;
74521
+ const handleCollapsedChange = (value) => {
74522
+ if (controlledCollapsed === void 0) setInternalCollapsed(value);
74523
+ onCollapsedChange?.(value);
74524
+ };
74525
+ const handlePageChange = (page) => {
74526
+ if (controlledPage === void 0) setInternalPage(page);
74527
+ onPageChange?.(page);
74528
+ };
74529
+ const handleGroupToggle = (title, expanded) => {
74530
+ if (controlledExpandedGroups === void 0) {
74531
+ setInternalExpandedGroups((prev) => {
74532
+ const next = new Set(prev);
74533
+ if (expanded) next.add(title);
74534
+ else next.delete(title);
74535
+ return next;
74536
+ });
74537
+ }
74538
+ onGroupToggle?.(title, expanded);
74539
+ };
74540
+ const handleMobileCollapseChange = (value) => {
74541
+ if (controlledMobileCollapsed === void 0) setInternalMobileCollapsed(value);
74542
+ onMobileCollapseChange?.(value);
74543
+ };
74544
+ React42.useEffect(() => {
74545
+ const handleResize = () => {
74546
+ const mobile = window.innerWidth < mobileBreakpoint;
74547
+ setIsMobile(mobile);
74548
+ if (mobile && !internalMobileCollapsed) {
74549
+ handleMobileCollapseChange(true);
74550
+ }
74551
+ };
74552
+ handleResize();
74553
+ window.addEventListener("resize", handleResize);
74554
+ return () => window.removeEventListener("resize", handleResize);
74555
+ }, [mobileBreakpoint, internalMobileCollapsed]);
74556
+ const handleKeyDown = React42.useCallback(
74557
+ (e) => {
74558
+ if (!keyboardNavigation) return;
74559
+ if (e.key === "Escape" && !isCollapsed && collapsible) {
74560
+ handleCollapsedChange(true);
74561
+ }
74562
+ if (e.key === "Enter" && isCollapsed && collapsible) {
74563
+ handleCollapsedChange(false);
74564
+ }
74565
+ },
74566
+ [keyboardNavigation, isCollapsed, collapsible]
74567
+ );
74568
+ React42.useEffect(() => {
74569
+ if (keyboardNavigation) {
74570
+ window.addEventListener("keydown", handleKeyDown);
74571
+ return () => window.removeEventListener("keydown", handleKeyDown);
74572
+ }
74573
+ }, [keyboardNavigation, handleKeyDown]);
74574
+ const effectiveCollapsed = isMobile ? mobileCollapsed : isCollapsed;
74575
+ const animStyle = {
74576
+ transitionDuration: `${animationDuration}ms`,
74577
+ transitionTimingFunction: animationEasing
74578
+ };
74579
+ const hasContent = React42.Children.count(children) > 0;
74580
+ const showEmpty = !loading && !hasContent && emptyState;
74581
+ return /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(PanelCollapsedContext.Provider, { value: effectiveCollapsed, children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(PanelGroupsContext.Provider, { value: { expandedGroups, onGroupToggle: handleGroupToggle }, children: /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(
74479
74582
  "div",
74480
74583
  {
74481
74584
  className: cn(
@@ -74483,6 +74586,7 @@ ${n2.shaderPreludeCode.vertexSource}`, define: n2.shaderDefine }, defaultProject
74483
74586
  height,
74484
74587
  className
74485
74588
  ),
74589
+ style: { ...animStyle },
74486
74590
  children: [
74487
74591
  /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "pointer-events-none absolute inset-0 overflow-hidden", children: [
74488
74592
  /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { className: "absolute -top-[40%] -left-[20%] h-[80%] w-[60%] rounded-full bg-primary/10 blur-[120px]" }),
@@ -74492,23 +74596,36 @@ ${n2.shaderPreludeCode.vertexSource}`, define: n2.shaderDefine }, defaultProject
74492
74596
  "aside",
74493
74597
  {
74494
74598
  className: cn(
74495
- "relative z-10 flex flex-col shrink-0 border-r border-border transition-all duration-200",
74496
- collapsed ? "w-14" : sidebarWidth
74599
+ "relative z-10 flex flex-col shrink-0 border-r border-border transition-all",
74600
+ effectiveCollapsed ? "w-14" : sidebarWidth
74497
74601
  ),
74602
+ style: { transitionDuration: `${animationDuration}ms`, transitionTimingFunction: animationEasing },
74498
74603
  children: [
74499
- (sidebarBrand || sidebarHeader) && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { className: cn(
74500
- "shrink-0 border-b border-border",
74501
- collapsed ? "flex items-center justify-center py-3" : "flex items-center gap-2 px-4 py-3"
74502
- ), children: sidebarBrand ? collapsed ? sidebarBrand.image ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("img", { src: sidebarBrand.image, alt: "logo", className: "h-7 w-7 rounded-md object-cover shrink-0" }) : /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "shrink-0", children: sidebarBrand.icon }) : /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(import_jsx_runtime46.Fragment, { children: [
74503
- sidebarBrand.image ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("img", { src: sidebarBrand.image, alt: "logo", className: "h-7 w-7 rounded-md object-cover shrink-0" }) : sidebarBrand.icon && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "shrink-0", children: sidebarBrand.icon }),
74504
- sidebarBrand.title && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "flex-1 truncate text-sm font-semibold", children: sidebarBrand.title }),
74505
- sidebarBrand.trailing && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "shrink-0", children: sidebarBrand.trailing })
74506
- ] }) : !collapsed && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { className: "text-sm font-semibold", children: sidebarHeader }) }),
74604
+ (sidebarBrand || sidebarHeader) && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
74605
+ "div",
74606
+ {
74607
+ className: cn(
74608
+ "shrink-0 border-b border-border",
74609
+ effectiveCollapsed ? "flex items-center justify-center py-3" : "flex items-center gap-2 px-4 py-3"
74610
+ ),
74611
+ children: sidebarBrand ? effectiveCollapsed ? sidebarBrand.image ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("img", { src: sidebarBrand.image, alt: "logo", className: "h-7 w-7 rounded-md object-cover shrink-0" }) : /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "shrink-0", children: sidebarBrand.icon }) : /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(import_jsx_runtime46.Fragment, { children: [
74612
+ sidebarBrand.image ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("img", { src: sidebarBrand.image, alt: "logo", className: "h-7 w-7 rounded-md object-cover shrink-0" }) : sidebarBrand.icon && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "shrink-0", children: sidebarBrand.icon }),
74613
+ sidebarBrand.title && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "flex-1 truncate text-sm font-semibold", children: sidebarBrand.title }),
74614
+ sidebarBrand.trailing && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "shrink-0", children: sidebarBrand.trailing })
74615
+ ] }) : !effectiveCollapsed && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { className: "text-sm font-semibold", children: sidebarHeader })
74616
+ }
74617
+ ),
74507
74618
  /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { className: "flex-1 overflow-y-auto py-2", children: sidebar }),
74508
- (sidebarProfile || sidebarFooter) && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { className: cn(
74509
- "shrink-0 border-t border-border",
74510
- collapsed ? "flex items-center justify-center py-3" : "px-4 py-3"
74511
- ), children: sidebarProfile ? collapsed ? sidebarProfile.image ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("img", { src: sidebarProfile.image, alt: "profile", className: "h-7 w-7 rounded-full object-cover shrink-0" }) : /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "shrink-0", children: sidebarProfile.icon }) : sidebarProfile.content ?? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { className: "flex items-center gap-2", children: sidebarProfile.image ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("img", { src: sidebarProfile.image, alt: "profile", className: "h-7 w-7 rounded-full object-cover shrink-0" }) : sidebarProfile.icon && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "shrink-0", children: sidebarProfile.icon }) }) : !collapsed && sidebarFooter })
74619
+ (sidebarProfile || sidebarFooter) && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
74620
+ "div",
74621
+ {
74622
+ className: cn(
74623
+ "shrink-0 border-t border-border",
74624
+ effectiveCollapsed ? "flex items-center justify-center py-3" : "px-4 py-3"
74625
+ ),
74626
+ children: sidebarProfile ? effectiveCollapsed ? sidebarProfile.image ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("img", { src: sidebarProfile.image, alt: "profile", className: "h-7 w-7 rounded-full object-cover shrink-0" }) : /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "shrink-0", children: sidebarProfile.icon }) : sidebarProfile.content ?? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { className: "flex items-center gap-2", children: sidebarProfile.image ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("img", { src: sidebarProfile.image, alt: "profile", className: "h-7 w-7 rounded-full object-cover shrink-0" }) : sidebarProfile.icon && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "shrink-0", children: sidebarProfile.icon }) }) : !effectiveCollapsed && sidebarFooter
74627
+ }
74628
+ )
74512
74629
  ]
74513
74630
  }
74514
74631
  ),
@@ -74518,16 +74635,22 @@ ${n2.shaderPreludeCode.vertexSource}`, define: n2.shaderDefine }, defaultProject
74518
74635
  collapsible && sidebar && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
74519
74636
  Tooltip,
74520
74637
  {
74521
- content: collapsed ? "Expand sidebar" : "Collapse sidebar",
74638
+ content: effectiveCollapsed ? "Expand sidebar" : "Collapse sidebar",
74522
74639
  side: "bottom",
74523
74640
  children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
74524
74641
  "button",
74525
74642
  {
74526
74643
  type: "button",
74527
- onClick: () => setCollapsed((c) => !c),
74644
+ onClick: () => {
74645
+ if (isMobile) {
74646
+ handleMobileCollapseChange(!mobileCollapsed);
74647
+ } else {
74648
+ handleCollapsedChange(!isCollapsed);
74649
+ }
74650
+ },
74528
74651
  className: "text-muted-foreground hover:text-foreground transition-colors",
74529
- "aria-label": collapsed ? "Expand sidebar" : "Collapse sidebar",
74530
- children: collapsed ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(PanelLeftOpen, { className: "h-5 w-5" }) : /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(PanelLeftClose, { className: "h-5 w-5" })
74652
+ "aria-label": effectiveCollapsed ? "Expand sidebar" : "Collapse sidebar",
74653
+ children: effectiveCollapsed ? expandIcon || /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(PanelLeftOpen, { className: "h-5 w-5" }) : collapseIcon || /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(PanelLeftClose, { className: "h-5 w-5" })
74531
74654
  }
74532
74655
  )
74533
74656
  }
@@ -74539,11 +74662,16 @@ ${n2.shaderPreludeCode.vertexSource}`, define: n2.shaderDefine }, defaultProject
74539
74662
  showThemeToggle && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(PanelThemeToggle, {})
74540
74663
  ] })
74541
74664
  ] }),
74542
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("main", { className: "flex-1 overflow-y-auto p-4", children })
74665
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("main", { className: "flex-1 overflow-y-auto p-4", children: [
74666
+ error && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { className: "mb-4 p-3 rounded-md bg-destructive/10 text-destructive text-sm", children: error }),
74667
+ loading && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { className: "flex items-center justify-center h-full", children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(LoaderCircle, { className: "h-6 w-6 animate-spin text-muted-foreground" }) }),
74668
+ showEmpty && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { className: "flex items-center justify-center h-full text-muted-foreground", children: emptyState }),
74669
+ !loading && !showEmpty && children
74670
+ ] })
74543
74671
  ] })
74544
74672
  ]
74545
74673
  }
74546
- ) });
74674
+ ) }) });
74547
74675
  }
74548
74676
  function PanelSidebarItem({
74549
74677
  icon: Icon2,
@@ -74574,10 +74702,20 @@ ${n2.shaderPreludeCode.vertexSource}`, define: n2.shaderDefine }, defaultProject
74574
74702
  children
74575
74703
  }) {
74576
74704
  const collapsed = React42.useContext(PanelCollapsedContext);
74705
+ const { expandedGroups, onGroupToggle } = React42.useContext(PanelGroupsContext);
74706
+ const isExpanded = title ? expandedGroups.has(title) : true;
74577
74707
  return /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "px-2 py-1", children: [
74578
- title && !collapsed && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("p", { className: "mb-1 px-2 text-[11px] font-semibold uppercase tracking-wider text-muted-foreground", children: title }),
74708
+ title && !collapsed && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
74709
+ "button",
74710
+ {
74711
+ type: "button",
74712
+ onClick: () => onGroupToggle(title, !isExpanded),
74713
+ className: "mb-1 px-2 text-[11px] font-semibold uppercase tracking-wider text-muted-foreground hover:text-foreground transition-colors w-full text-left",
74714
+ children: title
74715
+ }
74716
+ ),
74579
74717
  title && collapsed && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { className: "mx-1 mb-1 h-px bg-border" }),
74580
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("main", { className: "space-y-0.5", children })
74718
+ (!title || isExpanded) && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("main", { className: "space-y-0.5", children })
74581
74719
  ] });
74582
74720
  }
74583
74721