@sarunyu/system-one 4.5.1 → 4.6.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.cjs CHANGED
@@ -263,11 +263,10 @@ function Badge({
263
263
  ...props
264
264
  }) {
265
265
  const hasCount = count > 0;
266
- const isActive = hasCount;
267
266
  const resolvedNotificationState = notificationState ?? (hasCount ? "noti" : "default");
268
267
  const notificationIsFilled = resolvedNotificationState === "active" || resolvedNotificationState === "noti";
269
268
  const showNotificationDot = resolvedNotificationState === "noti" && hasCount;
270
- const visualIcon = variant === "notification" ? notificationIsFilled ? /* @__PURE__ */ jsxRuntime.jsx(react.BellSimple, { size: 19, weight: "fill" }) : /* @__PURE__ */ jsxRuntime.jsx(react.BellSimple, { size: 19, weight: "regular" }) : icon ?? /* @__PURE__ */ jsxRuntime.jsx(react.FunnelSimple, { size: 18, weight: "regular" });
269
+ const visualIcon = variant === "notification" ? /* @__PURE__ */ jsxRuntime.jsx(react.BellSimple, { size: 18, weight: notificationIsFilled ? "fill" : "regular" }) : icon ?? /* @__PURE__ */ jsxRuntime.jsx(react.FunnelSimple, { size: 18, weight: "regular" });
271
270
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("relative inline-flex", className), children: [
272
271
  variant === "notification" ? /* @__PURE__ */ jsxRuntime.jsx(
273
272
  Button,
@@ -275,10 +274,7 @@ function Badge({
275
274
  "aria-label": "Notification",
276
275
  size: "icon-xs",
277
276
  variant: "plain-black",
278
- className: cn(
279
- "text-subtle-text",
280
- notificationIsFilled && "text-primary-action"
281
- ),
277
+ className: "text-icon-brand [&>span]:!h-[18px] [&>span]:!w-[18px]",
282
278
  ...props,
283
279
  children: visualIcon
284
280
  }
@@ -287,8 +283,8 @@ function Badge({
287
283
  {
288
284
  "aria-label": label,
289
285
  size: "icon-md",
290
- variant: isActive ? "outline" : "outline-black",
291
- className: cn(isActive && "bg-primary-action-light border-primary-action-light"),
286
+ variant: hasCount ? "outline" : "outline-black",
287
+ className: cn(hasCount && "bg-primary-action-light border-primary-action-light"),
292
288
  ...props,
293
289
  children: visualIcon
294
290
  }
@@ -297,8 +293,8 @@ function Badge({
297
293
  {
298
294
  size: "md",
299
295
  leftIcon: visualIcon,
300
- variant: isActive ? "outline" : "outline-black",
301
- className: cn(isActive && "bg-primary-action-light border-primary-action-light"),
296
+ variant: hasCount ? "outline" : "outline-black",
297
+ className: cn(hasCount && "bg-primary-action-light border-primary-action-light"),
302
298
  ...props,
303
299
  children: label
304
300
  }
@@ -307,10 +303,10 @@ function Badge({
307
303
  "div",
308
304
  {
309
305
  className: cn(
310
- "absolute flex items-center justify-center rounded-[60px] px-1",
311
- variant === "notification" ? "-right-0.5 -top-0.5 h-[14px] min-w-[14px] bg-destructive" : "-right-1 -top-[7px] h-4 min-w-4 bg-primary-action"
306
+ "absolute flex h-[14px] min-h-[14px] min-w-[14px] items-center justify-center rounded-[60px]",
307
+ variant === "notification" ? "-right-0.5 -top-0.5 bg-destructive px-[2.5px]" : "-right-1 -top-[7px] h-4 min-w-4 bg-primary-action"
312
308
  ),
313
- children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-center text-xs leading-4 text-on-primary-action", children: formatCount(count, maxCount) })
309
+ children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-center text-xs leading-4 font-normal text-text-default-white", children: formatCount(count, maxCount) })
314
310
  }
315
311
  )
316
312
  ] });
@@ -382,6 +378,22 @@ const Alert = React.forwardRef(function Alert2({ status = "normal", message, mul
382
378
  );
383
379
  });
384
380
  Alert.displayName = "Alert";
381
+ const MOBILE_BREAKPOINT = 768;
382
+ function useIsMobile() {
383
+ const [isMobile, setIsMobile] = React__namespace.useState(
384
+ void 0
385
+ );
386
+ React__namespace.useEffect(() => {
387
+ const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`);
388
+ const onChange = () => {
389
+ setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
390
+ };
391
+ mql.addEventListener("change", onChange);
392
+ setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
393
+ return () => mql.removeEventListener("change", onChange);
394
+ }, []);
395
+ return !!isMobile;
396
+ }
385
397
  function BannerMedia({ src, alt }) {
386
398
  if (!src) {
387
399
  return /* @__PURE__ */ jsxRuntime.jsx("div", { "aria-hidden": "true", className: "absolute inset-0 bg-muted" });
@@ -489,7 +501,7 @@ const tagConfig = {
489
501
  };
490
502
  const Card = React.forwardRef(function Card2({
491
503
  variant = "default",
492
- size = "desktop",
504
+ size: sizeProp,
493
505
  children,
494
506
  title,
495
507
  locked = true,
@@ -513,9 +525,11 @@ const Card = React.forwardRef(function Card2({
513
525
  // live
514
526
  duration
515
527
  }, ref) {
528
+ const isMobile = useIsMobile();
529
+ const size = sizeProp ?? (isMobile ? "mobile" : "desktop");
516
530
  const bannerSrc = image ?? "";
517
531
  if (variant === "default") {
518
- const shellPadding = size === "desktop" ? "p-4" : size === "tablet" ? "p-3" : "p-2.5";
532
+ const shellPadding = size === "desktop" ? "p-4" : "p-3";
519
533
  const shellRadius = size === "mobile" ? "rounded-[6px]" : "rounded-[8px]";
520
534
  return /* @__PURE__ */ jsxRuntime.jsx(
521
535
  "div",
@@ -973,7 +987,8 @@ function NewsContent({
973
987
  }
974
988
  function CheckboxVisual({
975
989
  state,
976
- disabled
990
+ disabled,
991
+ error
977
992
  }) {
978
993
  if (state === "default") {
979
994
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -982,12 +997,12 @@ function CheckboxVisual({
982
997
  "aria-hidden": "true",
983
998
  className: cn(
984
999
  "block w-4 h-4 rounded-[2px] border-[1.5px]",
985
- disabled ? "bg-disabled-bg border-[var(--fill-black-100)]" : "bg-background border-[var(--fill-black-200)]"
1000
+ disabled ? "bg-disabled-bg border-[var(--fill-black-100)]" : error ? "bg-background border-destructive" : "bg-background border-[var(--fill-black-200)]"
986
1001
  )
987
1002
  }
988
1003
  );
989
1004
  }
990
- const containerFill = disabled ? "var(--fill-gray-300)" : "var(--fill-p1-600)";
1005
+ const containerFill = disabled ? "var(--disabled-bg)" : "var(--fill-p1-600)";
991
1006
  const iconFill = disabled ? "var(--fill-gray-400)" : "var(--fill-white-1000)";
992
1007
  if (state === "checked") {
993
1008
  return /* @__PURE__ */ jsxRuntime.jsxs(
@@ -1049,6 +1064,8 @@ function CheckboxVisual({
1049
1064
  const Checkbox = React.forwardRef(function Checkbox2({
1050
1065
  checked = false,
1051
1066
  disabled = false,
1067
+ error = false,
1068
+ errorMessage = "Error message",
1052
1069
  label,
1053
1070
  description,
1054
1071
  variant = "text",
@@ -1080,59 +1097,72 @@ const Checkbox = React.forwardRef(function Checkbox2({
1080
1097
  const hasText = label !== void 0 || description !== void 0;
1081
1098
  const hasActiveBorder = state === "checked" || state === "indeterminate";
1082
1099
  const isButton = variant === "button";
1083
- const buttonBorder = disabled ? "border-[var(--fill-black-100)]" : hasActiveBorder ? "border-primary-action" : "border-[var(--fill-black-200)]";
1100
+ const buttonBorder = disabled ? "border-[var(--fill-black-100)]" : error ? "border-destructive" : hasActiveBorder ? "border-primary-action" : "border-[var(--fill-black-200)]";
1101
+ const showError = error && !disabled;
1084
1102
  return /* @__PURE__ */ jsxRuntime.jsxs(
1085
1103
  "label",
1086
1104
  {
1087
1105
  className: cn(
1088
- "inline-flex gap-1 select-none",
1089
- description ? "items-start" : "items-center",
1106
+ "flex flex-col select-none",
1090
1107
  disabled ? "cursor-not-allowed" : "cursor-pointer",
1091
- isButton && cn("bg-background rounded-lg border py-2.5 pl-3 pr-4", buttonBorder),
1092
1108
  className
1093
1109
  ),
1094
1110
  children: [
1095
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "relative inline-flex items-center justify-center w-6 h-6 shrink-0", children: [
1096
- /* @__PURE__ */ jsxRuntime.jsx(
1097
- "input",
1098
- {
1099
- ref: setRefs,
1100
- id,
1101
- name,
1102
- value,
1103
- type: "checkbox",
1104
- checked: checked === true,
1105
- disabled,
1106
- onChange: handleChange,
1107
- "aria-label": ariaLabel,
1108
- "aria-checked": checked === "indeterminate" ? "mixed" : checked,
1109
- className: "absolute inset-0 w-full h-full opacity-0 m-0 cursor-[inherit] disabled:cursor-[inherit]"
1110
- }
1111
- ),
1112
- /* @__PURE__ */ jsxRuntime.jsx(CheckboxVisual, { state, disabled })
1113
- ] }),
1114
- hasText && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex flex-col", children: [
1115
- label !== void 0 && /* @__PURE__ */ jsxRuntime.jsx(
1116
- "span",
1117
- {
1118
- className: cn(
1119
- "text-base leading-6",
1120
- disabled ? "text-disabled" : "text-foreground"
1121
- ),
1122
- children: label
1123
- }
1124
- ),
1125
- description !== void 0 && /* @__PURE__ */ jsxRuntime.jsx(
1126
- "span",
1127
- {
1128
- className: cn(
1129
- "text-xs leading-4",
1130
- disabled ? "text-disabled" : "text-subtle-text"
1131
- ),
1132
- children: description
1133
- }
1134
- )
1135
- ] })
1111
+ /* @__PURE__ */ jsxRuntime.jsxs(
1112
+ "span",
1113
+ {
1114
+ className: cn(
1115
+ "inline-flex gap-1",
1116
+ description ? "items-start" : "items-center",
1117
+ isButton && cn("bg-background rounded-lg border py-2.5 pl-3 pr-4", buttonBorder)
1118
+ ),
1119
+ children: [
1120
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "relative inline-flex items-center justify-center w-6 h-6 shrink-0", children: [
1121
+ /* @__PURE__ */ jsxRuntime.jsx(
1122
+ "input",
1123
+ {
1124
+ ref: setRefs,
1125
+ id,
1126
+ name,
1127
+ value,
1128
+ type: "checkbox",
1129
+ checked: checked === true,
1130
+ disabled,
1131
+ onChange: handleChange,
1132
+ "aria-label": ariaLabel,
1133
+ "aria-checked": checked === "indeterminate" ? "mixed" : checked,
1134
+ "aria-invalid": showError || void 0,
1135
+ className: "absolute inset-0 w-full h-full opacity-0 m-0 cursor-[inherit] disabled:cursor-[inherit]"
1136
+ }
1137
+ ),
1138
+ /* @__PURE__ */ jsxRuntime.jsx(CheckboxVisual, { state, disabled, error: showError })
1139
+ ] }),
1140
+ hasText && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex flex-col", children: [
1141
+ label !== void 0 && /* @__PURE__ */ jsxRuntime.jsx(
1142
+ "span",
1143
+ {
1144
+ className: cn(
1145
+ "text-base leading-6",
1146
+ disabled ? "text-disabled" : "text-foreground"
1147
+ ),
1148
+ children: label
1149
+ }
1150
+ ),
1151
+ description !== void 0 && /* @__PURE__ */ jsxRuntime.jsx(
1152
+ "span",
1153
+ {
1154
+ className: cn(
1155
+ "text-xs leading-4",
1156
+ disabled ? "text-disabled" : "text-subtle-text"
1157
+ ),
1158
+ children: description
1159
+ }
1160
+ )
1161
+ ] })
1162
+ ]
1163
+ }
1164
+ ),
1165
+ showError && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "mt-1 ml-7 text-xs text-destructive", children: errorMessage })
1136
1166
  ]
1137
1167
  }
1138
1168
  );
@@ -1400,22 +1430,6 @@ const Chip = React.forwardRef(function Chip2({
1400
1430
  );
1401
1431
  });
1402
1432
  Chip.displayName = "Chip";
1403
- const MOBILE_BREAKPOINT = 768;
1404
- function useIsMobile() {
1405
- const [isMobile, setIsMobile] = React__namespace.useState(
1406
- void 0
1407
- );
1408
- React__namespace.useEffect(() => {
1409
- const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`);
1410
- const onChange = () => {
1411
- setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
1412
- };
1413
- mql.addEventListener("change", onChange);
1414
- setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
1415
- return () => mql.removeEventListener("change", onChange);
1416
- }, []);
1417
- return !!isMobile;
1418
- }
1419
1433
  function Drawer({
1420
1434
  ...props
1421
1435
  }) {
@@ -3666,7 +3680,7 @@ const Input = React.forwardRef(function Input2({
3666
3680
  Input.displayName = "Input";
3667
3681
  const ALERT_CONFIG = {
3668
3682
  warning: {
3669
- titleColor: "var(--accent-orange)",
3683
+ titleColor: "var(--text-warning-primary)",
3670
3684
  background: "https://www.figma.com/api/mcp/asset/f4ca68ad-5732-4124-9ff4-cfb69330cc02",
3671
3685
  layers: [
3672
3686
  {
@@ -3684,7 +3698,7 @@ const ALERT_CONFIG = {
3684
3698
  ]
3685
3699
  },
3686
3700
  success: {
3687
- titleColor: "var(--success)",
3701
+ titleColor: "var(--text-success-primary)",
3688
3702
  background: "https://www.figma.com/api/mcp/asset/2a865e6f-8a92-4496-88b5-71ac99e2c385",
3689
3703
  layers: [
3690
3704
  {
@@ -3698,7 +3712,7 @@ const ALERT_CONFIG = {
3698
3712
  ]
3699
3713
  },
3700
3714
  danger: {
3701
- titleColor: "var(--destructive)",
3715
+ titleColor: "var(--text-danger-primary)",
3702
3716
  background: "https://www.figma.com/api/mcp/asset/c7a65595-684e-4a04-b7fd-d443951f680a",
3703
3717
  layers: [
3704
3718
  {
@@ -3883,18 +3897,19 @@ function NotificationDivider({ label }) {
3883
3897
  }
3884
3898
  function NotificationRow({
3885
3899
  item,
3886
- onItemClick
3900
+ onItemClick,
3901
+ hideIndicator = false,
3902
+ demoteNewBackground = false
3887
3903
  }) {
3888
3904
  const rowType = item.type ?? "icon";
3889
3905
  const showImage = rowType === "image";
3890
- const showUnread = Boolean(item.unread);
3906
+ const status = item.status ?? (item.unread ? "unread" : "read");
3907
+ const showIndicator = (status === "new" || status === "unread") && !hideIndicator;
3908
+ const rowBackground = status === "new" && !demoteNewBackground ? "bg-muted" : "bg-background";
3891
3909
  return /* @__PURE__ */ jsxRuntime.jsxs(
3892
3910
  "div",
3893
3911
  {
3894
- className: cn(
3895
- "flex w-full items-start gap-3 px-4 py-3",
3896
- showUnread ? "bg-primary-action-light/40" : "bg-background"
3897
- ),
3912
+ className: cn("flex w-full items-start gap-3 px-4 py-3", rowBackground),
3898
3913
  role: "button",
3899
3914
  tabIndex: 0,
3900
3915
  onClick: () => onItemClick == null ? void 0 : onItemClick(item),
@@ -3912,22 +3927,11 @@ function NotificationRow({
3912
3927
  className: "h-10 w-10 rounded object-cover",
3913
3928
  src: item.imageSrc
3914
3929
  }
3915
- ) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-10 w-10 items-center justify-center rounded bg-disabled-bg text-disabled", children: /* @__PURE__ */ jsxRuntime.jsx(react.ImageSquare, { size: 20, weight: "regular" }) }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-6 w-6 items-center justify-center text-subtle-text", children: item.icon ?? /* @__PURE__ */ jsxRuntime.jsx(react.Circle, { size: 20, weight: "regular" }) }) }),
3916
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex-1", children: [
3917
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-[minmax(0,1fr)_auto] items-start gap-x-2", children: [
3918
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "min-w-0 flex-1 truncate text-base leading-6 font-bold text-foreground", children: item.title }),
3919
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex shrink-0 items-center gap-2", children: [
3920
- showUnread && /* @__PURE__ */ jsxRuntime.jsx(
3921
- "span",
3922
- {
3923
- "aria-hidden": "true",
3924
- className: "h-2 w-2 rounded-full bg-primary-action"
3925
- }
3926
- ),
3927
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs leading-4 text-muted-foreground", children: item.time })
3928
- ] }),
3929
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "col-start-1 mt-1 line-clamp-2 text-sm leading-5 text-muted-foreground", children: item.description })
3930
- ] }),
3930
+ ) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-10 w-10 items-center justify-center rounded bg-disabled-bg text-disabled", children: /* @__PURE__ */ jsxRuntime.jsx(react.ImageSquare, { size: 20, weight: "regular" }) }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-6 w-6 items-center justify-center text-subtle-text", children: item.icon ?? /* @__PURE__ */ jsxRuntime.jsx(react.Gift, { size: 20, weight: "regular" }) }) }),
3931
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex-1 space-y-1", children: [
3932
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "line-clamp-2 text-base leading-6 font-semibold text-foreground", children: item.title }),
3933
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "line-clamp-3 text-sm leading-5 text-muted-foreground", children: item.description }),
3934
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs leading-4 text-muted-foreground", children: item.time }),
3931
3935
  item.actionLabel && /* @__PURE__ */ jsxRuntime.jsx(
3932
3936
  Button,
3933
3937
  {
@@ -3942,7 +3946,14 @@ function NotificationRow({
3942
3946
  children: item.actionLabel
3943
3947
  }
3944
3948
  )
3945
- ] })
3949
+ ] }),
3950
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex w-2 shrink-0 items-start justify-center pt-2", children: showIndicator ? /* @__PURE__ */ jsxRuntime.jsx(
3951
+ "span",
3952
+ {
3953
+ "aria-hidden": "true",
3954
+ className: "h-2 w-2 rounded-full bg-destructive"
3955
+ }
3956
+ ) : null })
3946
3957
  ]
3947
3958
  }
3948
3959
  );
@@ -3953,6 +3964,7 @@ const Notification = React.forwardRef(
3953
3964
  badgeCount,
3954
3965
  panelWidth = 375,
3955
3966
  emptyText = "No notifications",
3967
+ showGroupLabels = true,
3956
3968
  clearBadgeOnOpen = true,
3957
3969
  open,
3958
3970
  defaultOpen,
@@ -3964,16 +3976,23 @@ const Notification = React.forwardRef(
3964
3976
  }, ref) {
3965
3977
  const [internalOpen, setInternalOpen] = React.useState(defaultOpen ?? false);
3966
3978
  const [isBadgeCleared, setIsBadgeCleared] = React.useState(false);
3979
+ const [clickedItemIds, setClickedItemIds] = React.useState(/* @__PURE__ */ new Set());
3980
+ const [wasDismissed, setWasDismissed] = React.useState(false);
3981
+ const [mobileAlign, setMobileAlign] = React.useState(null);
3982
+ const triggerRef = React.useRef(null);
3967
3983
  const controlled = open !== void 0;
3968
3984
  const resolvedOpen = controlled ? open : internalOpen;
3969
- const unreadCount = React.useMemo(
3985
+ const newCount = React.useMemo(
3970
3986
  () => groups.reduce(
3971
- (acc, group) => acc + group.items.filter((item) => Boolean(item.unread)).length,
3987
+ (acc, group) => acc + group.items.filter((item) => {
3988
+ const status = item.status ?? (item.unread ? "unread" : "read");
3989
+ return status === "new";
3990
+ }).length,
3972
3991
  0
3973
3992
  ),
3974
3993
  [groups]
3975
3994
  );
3976
- const nextCount = badgeCount ?? unreadCount;
3995
+ const nextCount = badgeCount ?? newCount;
3977
3996
  const prevCountRef = React.useRef(nextCount);
3978
3997
  React.useEffect(() => {
3979
3998
  const prevCount = prevCountRef.current;
@@ -3982,9 +4001,29 @@ const Notification = React.forwardRef(
3982
4001
  }
3983
4002
  prevCountRef.current = nextCount;
3984
4003
  }, [nextCount]);
4004
+ React.useEffect(() => {
4005
+ const update = () => {
4006
+ if (window.innerWidth > 640 || !triggerRef.current) {
4007
+ setMobileAlign(null);
4008
+ return;
4009
+ }
4010
+ const contentWidth = Math.min(panelWidth, window.innerWidth - 32);
4011
+ const triggerLeft = triggerRef.current.getBoundingClientRect().left;
4012
+ setMobileAlign({
4013
+ alignOffset: (window.innerWidth - contentWidth) / 2 - triggerLeft,
4014
+ width: contentWidth
4015
+ });
4016
+ };
4017
+ update();
4018
+ window.addEventListener("resize", update);
4019
+ return () => window.removeEventListener("resize", update);
4020
+ }, [panelWidth]);
3985
4021
  const displayCount = clearBadgeOnOpen && isBadgeCleared ? 0 : nextCount;
3986
4022
  const hasItems = groups.some((group) => group.items.length > 0);
3987
4023
  const handleOpenChange = (next) => {
4024
+ if (resolvedOpen && !next) {
4025
+ setWasDismissed(true);
4026
+ }
3988
4027
  if (next && clearBadgeOnOpen && nextCount > 0) {
3989
4028
  setIsBadgeCleared(true);
3990
4029
  onBadgeCleared == null ? void 0 : onBadgeCleared();
@@ -3992,8 +4031,17 @@ const Notification = React.forwardRef(
3992
4031
  if (!controlled) setInternalOpen(next);
3993
4032
  onOpenChange == null ? void 0 : onOpenChange(next);
3994
4033
  };
4034
+ const handleItemClick = (item) => {
4035
+ setClickedItemIds((prev) => {
4036
+ if (prev.has(item.id)) return prev;
4037
+ const next = new Set(prev);
4038
+ next.add(item.id);
4039
+ return next;
4040
+ });
4041
+ onItemClick == null ? void 0 : onItemClick(item);
4042
+ };
3995
4043
  return /* @__PURE__ */ jsxRuntime.jsxs(Popover__namespace.Root, { open: resolvedOpen, onOpenChange: handleOpenChange, children: [
3996
- /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn("inline-flex", className), children: /* @__PURE__ */ jsxRuntime.jsx(Popover__namespace.Trigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative", children: /* @__PURE__ */ jsxRuntime.jsx(
4044
+ /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn("inline-flex", className), children: /* @__PURE__ */ jsxRuntime.jsx(Popover__namespace.Trigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx("div", { ref: triggerRef, className: "relative", children: /* @__PURE__ */ jsxRuntime.jsx(
3997
4045
  Badge,
3998
4046
  {
3999
4047
  variant: "notification",
@@ -4006,22 +4054,26 @@ const Notification = React.forwardRef(
4006
4054
  /* @__PURE__ */ jsxRuntime.jsx(Popover__namespace.Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(
4007
4055
  Popover__namespace.Content,
4008
4056
  {
4009
- align: "end",
4057
+ align: mobileAlign ? "start" : "end",
4058
+ alignOffset: (mobileAlign == null ? void 0 : mobileAlign.alignOffset) ?? 0,
4059
+ avoidCollisions: !mobileAlign,
4010
4060
  sideOffset: 10,
4011
4061
  className: cn(
4012
4062
  "z-50 overflow-hidden rounded-lg border border-border bg-background shadow-lg",
4013
4063
  panelClassName
4014
4064
  ),
4015
- style: { width: panelWidth },
4016
- children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "max-h-[480px] overflow-y-auto py-2", children: [
4065
+ style: { width: (mobileAlign == null ? void 0 : mobileAlign.width) ?? panelWidth },
4066
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "max-h-[480px] overflow-y-auto", children: [
4017
4067
  !hasItems && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-4 py-8 text-center text-sm text-muted-foreground", children: emptyText }),
4018
4068
  groups.map((group) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "w-full", children: [
4019
- /* @__PURE__ */ jsxRuntime.jsx(NotificationDivider, { label: group.label }),
4069
+ showGroupLabels && group.label ? /* @__PURE__ */ jsxRuntime.jsx(NotificationDivider, { label: group.label }) : null,
4020
4070
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "divide-y divide-divider", children: group.items.map((item) => /* @__PURE__ */ jsxRuntime.jsx(
4021
4071
  NotificationRow,
4022
4072
  {
4023
4073
  item,
4024
- onItemClick
4074
+ onItemClick: handleItemClick,
4075
+ hideIndicator: clickedItemIds.has(item.id),
4076
+ demoteNewBackground: wasDismissed
4025
4077
  },
4026
4078
  item.id
4027
4079
  )) })