hazo_ui 4.2.0 → 4.3.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
@@ -5904,7 +5904,9 @@ var HardBreak = core.Node.create({
5904
5904
  const marks = storedMarks || selection.$to.parentOffset && selection.$from.marks();
5905
5905
  return chain().insertContent({ type: this.name }).command(({ tr, dispatch }) => {
5906
5906
  if (dispatch && marks && keepMarks) {
5907
- const filteredMarks = marks.filter((mark) => splittableMarks.includes(mark.type.name));
5907
+ const filteredMarks = marks.filter(
5908
+ (mark) => splittableMarks.includes(mark.type.name)
5909
+ );
5908
5910
  tr.ensureMarks(filteredMarks);
5909
5911
  }
5910
5912
  return true;
@@ -7975,6 +7977,149 @@ function ProgressiveImage({
7975
7977
  }
7976
7978
  );
7977
7979
  }
7980
+ function NotificationCountBadge({
7981
+ count,
7982
+ max = 9,
7983
+ className
7984
+ }) {
7985
+ if (count <= 0) return null;
7986
+ const isOverflow = count > max;
7987
+ const label = isOverflow ? `${max}+` : String(count);
7988
+ return /* @__PURE__ */ jsxRuntime.jsx(
7989
+ "span",
7990
+ {
7991
+ "aria-label": `${count} unread`,
7992
+ className: cn(
7993
+ "cls_notification_count_badge",
7994
+ "inline-flex items-center justify-center",
7995
+ "bg-destructive text-destructive-foreground",
7996
+ "text-[10px] font-semibold leading-none select-none",
7997
+ // pill for "9+", circle for single/double digits
7998
+ isOverflow ? "rounded-full px-1.5 py-0.5 min-w-[1.25rem] h-5" : "rounded-full w-5 h-5",
7999
+ className
8000
+ ),
8001
+ children: label
8002
+ }
8003
+ );
8004
+ }
8005
+ function NotificationItem({
8006
+ isRead,
8007
+ timestamp,
8008
+ children,
8009
+ actions,
8010
+ onClick,
8011
+ onContextMenu,
8012
+ onMarkRead,
8013
+ markReadLabel
8014
+ }) {
8015
+ const handleMarkRead = (e) => {
8016
+ e.stopPropagation();
8017
+ onMarkRead?.();
8018
+ };
8019
+ return /* @__PURE__ */ jsxRuntime.jsxs(
8020
+ "div",
8021
+ {
8022
+ role: "listitem",
8023
+ onClick,
8024
+ onContextMenu,
8025
+ className: cn(
8026
+ "cls_notification_item",
8027
+ "relative flex gap-3 px-4 py-3 text-sm transition-colors",
8028
+ onClick && "cursor-pointer hover:bg-accent/60",
8029
+ !isRead && "bg-primary/5"
8030
+ ),
8031
+ children: [
8032
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "cls_notification_item_dot_col flex-shrink-0 pt-1.5", children: !isRead ? /* @__PURE__ */ jsxRuntime.jsx(
8033
+ "span",
8034
+ {
8035
+ "aria-label": "Unread",
8036
+ className: "cls_notification_item_dot block w-2 h-2 rounded-full bg-primary"
8037
+ }
8038
+ ) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "block w-2 h-2", "aria-hidden": "true" }) }),
8039
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "cls_notification_item_body flex-1 min-w-0 space-y-1", children: [
8040
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "cls_notification_item_message leading-snug text-foreground", children }),
8041
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "cls_notification_item_meta flex items-center gap-3 flex-wrap", children: [
8042
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "cls_notification_item_timestamp text-xs text-muted-foreground", children: timestamp }),
8043
+ !isRead && onMarkRead ? /* @__PURE__ */ jsxRuntime.jsx(
8044
+ "button",
8045
+ {
8046
+ type: "button",
8047
+ onClick: handleMarkRead,
8048
+ className: "cls_notification_item_mark_read text-primary text-xs hover:underline focus:outline-none focus-visible:ring-2 focus-visible:ring-primary rounded",
8049
+ children: markReadLabel
8050
+ }
8051
+ ) : null
8052
+ ] }),
8053
+ actions ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "cls_notification_item_actions flex items-center gap-2 pt-1", children: actions }) : null
8054
+ ] })
8055
+ ]
8056
+ }
8057
+ );
8058
+ }
8059
+ function LoadingSkeletons() {
8060
+ return /* @__PURE__ */ jsxRuntime.jsx(
8061
+ "div",
8062
+ {
8063
+ "aria-busy": "true",
8064
+ "aria-label": "Loading notifications",
8065
+ className: "cls_notification_panel_loading space-y-0",
8066
+ children: [0, 1, 2].map((i) => /* @__PURE__ */ jsxRuntime.jsxs(
8067
+ "div",
8068
+ {
8069
+ className: "cls_notification_panel_skeleton flex gap-3 px-4 py-3 animate-pulse",
8070
+ children: [
8071
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-shrink-0 pt-1.5", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-2 h-2 rounded-full bg-muted" }) }),
8072
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 space-y-2 pt-0.5", children: [
8073
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-3 bg-muted rounded w-3/4" }),
8074
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-3 bg-muted rounded w-1/2" }),
8075
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-2.5 bg-muted rounded w-1/4 mt-1" })
8076
+ ] })
8077
+ ]
8078
+ },
8079
+ i
8080
+ ))
8081
+ }
8082
+ );
8083
+ }
8084
+ function NotificationPanel({
8085
+ children,
8086
+ onMarkAllRead,
8087
+ markAllReadLabel,
8088
+ emptyState,
8089
+ loading = false,
8090
+ className
8091
+ }) {
8092
+ const hasChildren = React26__namespace.Children.count(children) > 0 && children !== null && children !== void 0;
8093
+ return /* @__PURE__ */ jsxRuntime.jsxs(
8094
+ "div",
8095
+ {
8096
+ className: cn(
8097
+ "cls_notification_panel",
8098
+ "flex flex-col bg-background border border-border rounded-lg overflow-hidden shadow-md",
8099
+ className
8100
+ ),
8101
+ children: [
8102
+ /* @__PURE__ */ jsxRuntime.jsx(
8103
+ "div",
8104
+ {
8105
+ role: "list",
8106
+ className: "cls_notification_panel_list flex-1 overflow-y-auto max-h-[480px] divide-y divide-border",
8107
+ children: loading ? /* @__PURE__ */ jsxRuntime.jsx(LoadingSkeletons, {}) : hasChildren ? children : emptyState ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "cls_notification_panel_empty px-4 py-8 flex items-center justify-center", children: emptyState }) : null
8108
+ }
8109
+ ),
8110
+ onMarkAllRead ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "cls_notification_panel_footer border-t border-border px-4 py-2 flex justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(
8111
+ "button",
8112
+ {
8113
+ type: "button",
8114
+ onClick: onMarkAllRead,
8115
+ className: "cls_notification_panel_mark_all text-primary text-xs hover:underline focus:outline-none focus-visible:ring-2 focus-visible:ring-primary rounded",
8116
+ children: markAllReadLabel
8117
+ }
8118
+ ) }) : null
8119
+ ]
8120
+ }
8121
+ );
8122
+ }
7978
8123
  function HazoUiToaster({
7979
8124
  position = "bottom-right",
7980
8125
  closeButton = true,
@@ -10885,6 +11030,9 @@ exports.InverseSparkline = InverseSparkline;
10885
11030
  exports.Label = Label3;
10886
11031
  exports.LoadingTimeout = LoadingTimeout;
10887
11032
  exports.MarkdownEditor = MarkdownEditor;
11033
+ exports.NotificationCountBadge = NotificationCountBadge;
11034
+ exports.NotificationItem = NotificationItem;
11035
+ exports.NotificationPanel = NotificationPanel;
10888
11036
  exports.Popover = Popover;
10889
11037
  exports.PopoverContent = PopoverContent;
10890
11038
  exports.PopoverTrigger = PopoverTrigger;