asterui 0.12.44 → 0.12.45

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.
@@ -0,0 +1,20 @@
1
+ import { default as React } from 'react';
2
+ export interface MessageConfig {
3
+ duration?: number;
4
+ key?: string;
5
+ icon?: React.ReactNode;
6
+ className?: string;
7
+ style?: React.CSSProperties;
8
+ 'data-testid'?: string;
9
+ onClick?: () => void;
10
+ onClose?: () => void;
11
+ }
12
+ export declare class MessageManager {
13
+ success(content: React.ReactNode, config?: MessageConfig): string;
14
+ error(content: React.ReactNode, config?: MessageConfig): string;
15
+ info(content: React.ReactNode, config?: MessageConfig): string;
16
+ warning(content: React.ReactNode, config?: MessageConfig): string;
17
+ loading(content: React.ReactNode, config?: MessageConfig): string;
18
+ destroy(id?: string): void;
19
+ }
20
+ export declare const message: MessageManager;
@@ -0,0 +1,56 @@
1
+ import { jsx as s } from "react/jsx-runtime";
2
+ import { notification as a } from "./Notification.js";
3
+ class r {
4
+ success(e, n) {
5
+ return a.open({
6
+ message: e,
7
+ type: "success",
8
+ variant: "compact",
9
+ ...n
10
+ });
11
+ }
12
+ error(e, n) {
13
+ return a.open({
14
+ message: e,
15
+ type: "error",
16
+ variant: "compact",
17
+ ...n
18
+ });
19
+ }
20
+ info(e, n) {
21
+ return a.open({
22
+ message: e,
23
+ type: "info",
24
+ variant: "compact",
25
+ ...n
26
+ });
27
+ }
28
+ warning(e, n) {
29
+ return a.open({
30
+ message: e,
31
+ type: "warning",
32
+ variant: "compact",
33
+ ...n
34
+ });
35
+ }
36
+ loading(e, n) {
37
+ const o = /* @__PURE__ */ s("span", { className: "loading loading-spinner loading-sm" });
38
+ return a.open({
39
+ message: e,
40
+ type: "info",
41
+ variant: "compact",
42
+ duration: 0,
43
+ icon: o,
44
+ ...n
45
+ });
46
+ }
47
+ destroy(e) {
48
+ e ? a.close(e) : a.destroy();
49
+ }
50
+ }
51
+ const p = new r();
52
+ export {
53
+ r as MessageManager,
54
+ p as message
55
+ };
56
+ //# sourceMappingURL=Message.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Message.js","sources":["../../src/components/Message.tsx"],"sourcesContent":["import React from 'react'\nimport { notification } from './Notification'\n\nexport interface MessageConfig {\n duration?: number\n key?: string\n icon?: React.ReactNode\n className?: string\n style?: React.CSSProperties\n 'data-testid'?: string\n onClick?: () => void\n onClose?: () => void\n}\n\nexport class MessageManager {\n success(content: React.ReactNode, config?: MessageConfig) {\n return notification.open({\n message: content,\n type: 'success',\n variant: 'compact',\n ...config,\n })\n }\n\n error(content: React.ReactNode, config?: MessageConfig) {\n return notification.open({\n message: content,\n type: 'error',\n variant: 'compact',\n ...config,\n })\n }\n\n info(content: React.ReactNode, config?: MessageConfig) {\n return notification.open({\n message: content,\n type: 'info',\n variant: 'compact',\n ...config,\n })\n }\n\n warning(content: React.ReactNode, config?: MessageConfig) {\n return notification.open({\n message: content,\n type: 'warning',\n variant: 'compact',\n ...config,\n })\n }\n\n loading(content: React.ReactNode, config?: MessageConfig) {\n const loadingIcon = (\n <span className=\"loading loading-spinner loading-sm\" />\n )\n return notification.open({\n message: content,\n type: 'info',\n variant: 'compact',\n duration: 0,\n icon: loadingIcon,\n ...config,\n })\n }\n\n destroy(id?: string) {\n if (id) {\n notification.close(id)\n } else {\n notification.destroy()\n }\n }\n}\n\nexport const message = new MessageManager()\n"],"names":["MessageManager","content","config","notification","loadingIcon","jsx","id","message"],"mappings":";;AAcO,MAAMA,EAAe;AAAA,EAC1B,QAAQC,GAA0BC,GAAwB;AACxD,WAAOC,EAAa,KAAK;AAAA,MACvB,SAASF;AAAA,MACT,MAAM;AAAA,MACN,SAAS;AAAA,MACT,GAAGC;AAAA,IAAA,CACJ;AAAA,EACH;AAAA,EAEA,MAAMD,GAA0BC,GAAwB;AACtD,WAAOC,EAAa,KAAK;AAAA,MACvB,SAASF;AAAA,MACT,MAAM;AAAA,MACN,SAAS;AAAA,MACT,GAAGC;AAAA,IAAA,CACJ;AAAA,EACH;AAAA,EAEA,KAAKD,GAA0BC,GAAwB;AACrD,WAAOC,EAAa,KAAK;AAAA,MACvB,SAASF;AAAA,MACT,MAAM;AAAA,MACN,SAAS;AAAA,MACT,GAAGC;AAAA,IAAA,CACJ;AAAA,EACH;AAAA,EAEA,QAAQD,GAA0BC,GAAwB;AACxD,WAAOC,EAAa,KAAK;AAAA,MACvB,SAASF;AAAA,MACT,MAAM;AAAA,MACN,SAAS;AAAA,MACT,GAAGC;AAAA,IAAA,CACJ;AAAA,EACH;AAAA,EAEA,QAAQD,GAA0BC,GAAwB;AACxD,UAAME,IACJ,gBAAAC,EAAC,QAAA,EAAK,WAAU,qCAAA,CAAqC;AAEvD,WAAOF,EAAa,KAAK;AAAA,MACvB,SAASF;AAAA,MACT,MAAM;AAAA,MACN,SAAS;AAAA,MACT,UAAU;AAAA,MACV,MAAMG;AAAA,MACN,GAAGF;AAAA,IAAA,CACJ;AAAA,EACH;AAAA,EAEA,QAAQI,GAAa;AACnB,IAAIA,IACFH,EAAa,MAAMG,CAAE,IAErBH,EAAa,QAAA;AAAA,EAEjB;AACF;AAEO,MAAMI,IAAU,IAAIP,EAAA;"}
@@ -1,13 +1,20 @@
1
1
  import { default as React } from 'react';
2
2
  export type NotificationType = 'success' | 'info' | 'warning' | 'error';
3
- export type NotificationPlacement = 'topLeft' | 'topRight' | 'bottomLeft' | 'bottomRight';
3
+ export type NotificationPlacement = 'topLeft' | 'topRight' | 'bottomLeft' | 'bottomRight' | 'topCenter' | 'bottomCenter';
4
+ export type NotificationVariant = 'default' | 'compact';
4
5
  export interface NotificationConfig {
5
6
  message: React.ReactNode;
6
7
  description?: React.ReactNode;
7
8
  type?: NotificationType;
8
9
  duration?: number;
9
10
  placement?: NotificationPlacement;
11
+ variant?: NotificationVariant;
10
12
  closable?: boolean;
13
+ icon?: React.ReactNode;
14
+ key?: string;
15
+ className?: string;
16
+ style?: React.CSSProperties;
17
+ 'data-testid'?: string;
11
18
  onClick?: () => void;
12
19
  onClose?: () => void;
13
20
  }
@@ -1,115 +1,139 @@
1
- import { jsx as i, Fragment as h, jsxs as l } from "react/jsx-runtime";
2
- import { useState as u, useEffect as p } from "react";
3
- import d from "react-dom/client";
1
+ import { jsx as s, Fragment as d, jsxs as c } from "react/jsx-runtime";
2
+ import { useState as h, useEffect as p } from "react";
3
+ import u from "react-dom/client";
4
4
  class m {
5
5
  notifications = [];
6
6
  listeners = [];
7
7
  container = null;
8
8
  root = null;
9
9
  idCounter = 0;
10
- subscribe(t) {
11
- return this.listeners.push(t), () => {
12
- this.listeners = this.listeners.filter((o) => o !== t);
10
+ subscribe(e) {
11
+ return this.listeners.push(e), () => {
12
+ this.listeners = this.listeners.filter((o) => o !== e);
13
13
  };
14
14
  }
15
15
  getNotifications() {
16
16
  return this.notifications;
17
17
  }
18
18
  emit() {
19
- this.listeners.forEach((t) => t());
19
+ this.listeners.forEach((e) => e());
20
20
  }
21
21
  ensureContainer() {
22
- this.container || (this.container = document.createElement("div"), document.body.appendChild(this.container), this.root = d.createRoot(this.container), this.root.render(/* @__PURE__ */ i(f, { manager: this })));
22
+ this.container || (this.container = document.createElement("div"), document.body.appendChild(this.container), this.root = u.createRoot(this.container), this.root.render(/* @__PURE__ */ s(v, { manager: this })));
23
23
  }
24
- open(t) {
24
+ open(e) {
25
25
  this.ensureContainer();
26
- const o = `notification-${++this.idCounter}`, s = {
27
- ...t,
26
+ const o = e.key ?? `notification-${++this.idCounter}`, r = e.variant === "compact", a = {
27
+ ...e,
28
28
  id: o,
29
29
  createdAt: Date.now(),
30
- duration: t.duration ?? 4.5,
31
- placement: t.placement ?? "topRight",
32
- closable: t.closable ?? !0,
33
- type: t.type ?? "info"
34
- };
35
- return this.notifications.push(s), this.emit(), s.duration && s.duration > 0 && setTimeout(() => {
30
+ duration: e.duration ?? (r ? 3 : 4.5),
31
+ placement: e.placement ?? (r ? "topCenter" : "topRight"),
32
+ variant: e.variant ?? "default",
33
+ closable: e.closable ?? !r,
34
+ type: e.type ?? "info"
35
+ }, n = this.notifications.findIndex((i) => i.id === o);
36
+ return n !== -1 ? this.notifications[n] = a : this.notifications.push(a), this.emit(), a.duration && a.duration > 0 && setTimeout(() => {
36
37
  this.close(o);
37
- }, s.duration * 1e3), o;
38
+ }, a.duration * 1e3), o;
38
39
  }
39
- close(t) {
40
- const o = this.notifications.find((s) => s.id === t);
41
- this.notifications = this.notifications.filter((s) => s.id !== t), this.emit(), o?.onClose && o.onClose();
40
+ close(e) {
41
+ const o = this.notifications.find((r) => r.id === e);
42
+ this.notifications = this.notifications.filter((r) => r.id !== e), this.emit(), o?.onClose && o.onClose();
42
43
  }
43
- success(t) {
44
- return this.open({ ...t, type: "success" });
44
+ success(e) {
45
+ return this.open({ ...e, type: "success" });
45
46
  }
46
- error(t) {
47
- return this.open({ ...t, type: "error" });
47
+ error(e) {
48
+ return this.open({ ...e, type: "error" });
48
49
  }
49
- info(t) {
50
- return this.open({ ...t, type: "info" });
50
+ info(e) {
51
+ return this.open({ ...e, type: "info" });
51
52
  }
52
- warning(t) {
53
- return this.open({ ...t, type: "warning" });
53
+ warning(e) {
54
+ return this.open({ ...e, type: "warning" });
54
55
  }
55
56
  destroy() {
56
57
  this.notifications = [], this.emit();
57
58
  }
58
59
  }
59
- function f({ manager: e }) {
60
- const [, t] = u({});
61
- p(() => e.subscribe(() => {
62
- t({});
63
- }), [e]);
64
- const o = e.getNotifications(), s = {
60
+ function v({ manager: t }) {
61
+ const [, e] = h({});
62
+ p(() => t.subscribe(() => {
63
+ e({});
64
+ }), [t]);
65
+ const o = t.getNotifications(), r = {
65
66
  topLeft: [],
66
67
  topRight: [],
68
+ topCenter: [],
67
69
  bottomLeft: [],
68
- bottomRight: []
70
+ bottomRight: [],
71
+ bottomCenter: []
69
72
  };
70
73
  o.forEach((n) => {
71
- s[n.placement].push(n);
74
+ r[n.placement].push(n);
72
75
  });
73
- const r = {
76
+ const a = {
74
77
  topRight: "toast toast-top toast-end",
75
78
  topLeft: "toast toast-top toast-start",
79
+ topCenter: "toast toast-top toast-center",
76
80
  bottomRight: "toast toast-bottom toast-end",
77
- bottomLeft: "toast toast-bottom toast-start"
81
+ bottomLeft: "toast toast-bottom toast-start",
82
+ bottomCenter: "toast toast-bottom toast-center"
78
83
  };
79
- return /* @__PURE__ */ i(h, { children: Object.entries(s).map(([n, c]) => c.length === 0 ? null : /* @__PURE__ */ i("div", { className: r[n], children: c.map((a) => /* @__PURE__ */ i(
80
- b,
84
+ return /* @__PURE__ */ s(d, { children: Object.entries(r).map(([n, i]) => i.length === 0 ? null : /* @__PURE__ */ s("div", { className: a[n], children: i.map((l) => /* @__PURE__ */ s(
85
+ w,
81
86
  {
82
- notification: a,
83
- onClose: () => e.close(a.id)
87
+ notification: l,
88
+ onClose: () => t.close(l.id)
84
89
  },
85
- a.id
90
+ l.id
86
91
  )) }, n)) });
87
92
  }
88
- function b({ notification: e, onClose: t }) {
89
- const o = {
93
+ function w({ notification: t, onClose: e }) {
94
+ const o = t.variant === "compact", r = {
90
95
  success: "alert-success",
91
96
  error: "alert-error",
92
97
  info: "alert-info",
93
98
  warning: "alert-warning"
94
- }, s = () => {
95
- e.onClick && e.onClick();
96
- };
97
- return /* @__PURE__ */ l(
99
+ }, a = {
100
+ success: /* @__PURE__ */ s("svg", { xmlns: "http://www.w3.org/2000/svg", className: "h-5 w-5", viewBox: "0 0 20 20", fill: "currentColor", children: /* @__PURE__ */ s("path", { fillRule: "evenodd", d: "M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z", clipRule: "evenodd" }) }),
101
+ error: /* @__PURE__ */ s("svg", { xmlns: "http://www.w3.org/2000/svg", className: "h-5 w-5", viewBox: "0 0 20 20", fill: "currentColor", children: /* @__PURE__ */ s("path", { fillRule: "evenodd", d: "M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z", clipRule: "evenodd" }) }),
102
+ info: /* @__PURE__ */ s("svg", { xmlns: "http://www.w3.org/2000/svg", className: "h-5 w-5", viewBox: "0 0 20 20", fill: "currentColor", children: /* @__PURE__ */ s("path", { fillRule: "evenodd", d: "M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z", clipRule: "evenodd" }) }),
103
+ warning: /* @__PURE__ */ s("svg", { xmlns: "http://www.w3.org/2000/svg", className: "h-5 w-5", viewBox: "0 0 20 20", fill: "currentColor", children: /* @__PURE__ */ s("path", { fillRule: "evenodd", d: "M8.257 3.099c.765-1.36 2.722-1.36 3.486 0l5.58 9.92c.75 1.334-.213 2.98-1.742 2.98H4.42c-1.53 0-2.493-1.646-1.743-2.98l5.58-9.92zM11 13a1 1 0 11-2 0 1 1 0 012 0zm-1-8a1 1 0 00-1 1v3a1 1 0 002 0V6a1 1 0 00-1-1z", clipRule: "evenodd" }) })
104
+ }, n = () => {
105
+ t.onClick && t.onClick();
106
+ }, i = t.icon ?? a[t.type];
107
+ return o ? /* @__PURE__ */ s(
108
+ "div",
109
+ {
110
+ className: `alert ${r[t.type]} shadow-md py-2 px-4 cursor-pointer${t.className ? ` ${t.className}` : ""}`,
111
+ style: t.style,
112
+ "data-testid": t["data-testid"],
113
+ onClick: n,
114
+ children: /* @__PURE__ */ c("div", { className: "flex items-center gap-2", children: [
115
+ i,
116
+ /* @__PURE__ */ s("span", { children: t.message })
117
+ ] })
118
+ }
119
+ ) : /* @__PURE__ */ c(
98
120
  "div",
99
121
  {
100
- className: `alert ${o[e.type]} shadow-lg cursor-pointer min-w-[300px] max-w-[400px] relative`,
101
- onClick: s,
122
+ className: `alert ${r[t.type]} shadow-lg cursor-pointer min-w-[300px] max-w-[400px] relative${t.className ? ` ${t.className}` : ""}`,
123
+ style: t.style,
124
+ "data-testid": t["data-testid"],
125
+ onClick: n,
102
126
  children: [
103
- /* @__PURE__ */ l("div", { className: e.closable ? "pr-8" : "", children: [
104
- e.message && /* @__PURE__ */ i("div", { className: "font-bold", children: e.message }),
105
- e.description && /* @__PURE__ */ i("div", { className: "text-sm", children: e.description })
127
+ /* @__PURE__ */ c("div", { className: t.closable ? "pr-8" : "", children: [
128
+ t.message && /* @__PURE__ */ s("div", { className: "font-bold", children: t.message }),
129
+ t.description && /* @__PURE__ */ s("div", { className: "text-sm", children: t.description })
106
130
  ] }),
107
- e.closable && /* @__PURE__ */ i(
131
+ t.closable && /* @__PURE__ */ s(
108
132
  "button",
109
133
  {
110
134
  className: "btn btn-xs btn-ghost btn-circle absolute top-2 right-2",
111
- onClick: (r) => {
112
- r.stopPropagation(), t();
135
+ onClick: (l) => {
136
+ l.stopPropagation(), e();
113
137
  },
114
138
  children: "✕"
115
139
  }
@@ -118,8 +142,8 @@ function b({ notification: e, onClose: t }) {
118
142
  }
119
143
  );
120
144
  }
121
- const y = new m();
145
+ const C = new m();
122
146
  export {
123
- y as notification
147
+ C as notification
124
148
  };
125
149
  //# sourceMappingURL=Notification.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Notification.js","sources":["../../src/components/Notification.tsx"],"sourcesContent":["import React, { useEffect, useState } from 'react'\nimport ReactDOM from 'react-dom/client'\n\nexport type NotificationType = 'success' | 'info' | 'warning' | 'error'\nexport type NotificationPlacement = 'topLeft' | 'topRight' | 'bottomLeft' | 'bottomRight'\n\nexport interface NotificationConfig {\n message: React.ReactNode\n description?: React.ReactNode\n type?: NotificationType\n duration?: number // in seconds, 0 = no auto close\n placement?: NotificationPlacement\n closable?: boolean\n onClick?: () => void\n onClose?: () => void\n}\n\ninterface NotificationItem extends NotificationConfig {\n id: string\n createdAt: number\n}\n\ntype Listener = () => void\n\nclass NotificationManager {\n private notifications: NotificationItem[] = []\n private listeners: Listener[] = []\n private container: HTMLDivElement | null = null\n private root: ReactDOM.Root | null = null\n private idCounter = 0\n\n subscribe(listener: Listener) {\n this.listeners.push(listener)\n return () => {\n this.listeners = this.listeners.filter((l) => l !== listener)\n }\n }\n\n getNotifications() {\n return this.notifications\n }\n\n private emit() {\n this.listeners.forEach((listener) => listener())\n }\n\n private ensureContainer() {\n if (!this.container) {\n this.container = document.createElement('div')\n document.body.appendChild(this.container)\n this.root = ReactDOM.createRoot(this.container)\n this.root.render(<NotificationContainer manager={this} />)\n }\n }\n\n open(config: NotificationConfig) {\n this.ensureContainer()\n\n const id = `notification-${++this.idCounter}`\n const notification: NotificationItem = {\n ...config,\n id,\n createdAt: Date.now(),\n duration: config.duration ?? 4.5,\n placement: config.placement ?? 'topRight',\n closable: config.closable ?? true,\n type: config.type ?? 'info',\n }\n\n this.notifications.push(notification)\n this.emit()\n\n // Auto-dismiss\n if (notification.duration && notification.duration > 0) {\n setTimeout(() => {\n this.close(id)\n }, notification.duration * 1000)\n }\n\n return id\n }\n\n close(id: string) {\n const notification = this.notifications.find((n) => n.id === id)\n this.notifications = this.notifications.filter((n) => n.id !== id)\n this.emit()\n\n if (notification?.onClose) {\n notification.onClose()\n }\n }\n\n success(config: Omit<NotificationConfig, 'type'>) {\n return this.open({ ...config, type: 'success' })\n }\n\n error(config: Omit<NotificationConfig, 'type'>) {\n return this.open({ ...config, type: 'error' })\n }\n\n info(config: Omit<NotificationConfig, 'type'>) {\n return this.open({ ...config, type: 'info' })\n }\n\n warning(config: Omit<NotificationConfig, 'type'>) {\n return this.open({ ...config, type: 'warning' })\n }\n\n destroy() {\n this.notifications = []\n this.emit()\n }\n}\n\ninterface NotificationContainerProps {\n manager: NotificationManager\n}\n\nfunction NotificationContainer({ manager }: NotificationContainerProps) {\n const [, forceUpdate] = useState({})\n\n useEffect(() => {\n const unsubscribe = manager.subscribe(() => {\n forceUpdate({})\n })\n return unsubscribe\n }, [manager])\n\n const notifications = manager.getNotifications()\n\n // Group by placement\n const grouped: Record<NotificationPlacement, NotificationItem[]> = {\n topLeft: [],\n topRight: [],\n bottomLeft: [],\n bottomRight: [],\n }\n\n notifications.forEach((notification) => {\n grouped[notification.placement!].push(notification)\n })\n\n const placementClasses: Record<NotificationPlacement, string> = {\n topRight: 'toast toast-top toast-end',\n topLeft: 'toast toast-top toast-start',\n bottomRight: 'toast toast-bottom toast-end',\n bottomLeft: 'toast toast-bottom toast-start',\n }\n\n return (\n <>\n {Object.entries(grouped).map(([placement, items]) => {\n if (items.length === 0) return null\n\n return (\n <div key={placement} className={placementClasses[placement as NotificationPlacement]}>\n {items.map((notification) => (\n <NotificationItem\n key={notification.id}\n notification={notification}\n onClose={() => manager.close(notification.id)}\n />\n ))}\n </div>\n )\n })}\n </>\n )\n}\n\ninterface NotificationItemProps {\n notification: NotificationItem\n onClose: () => void\n}\n\nfunction NotificationItem({ notification, onClose }: NotificationItemProps) {\n const alertTypeClasses: Record<NotificationType, string> = {\n success: 'alert-success',\n error: 'alert-error',\n info: 'alert-info',\n warning: 'alert-warning',\n }\n\n const handleClick = () => {\n if (notification.onClick) {\n notification.onClick()\n }\n }\n\n return (\n <div\n className={`alert ${alertTypeClasses[notification.type!]} shadow-lg cursor-pointer min-w-[300px] max-w-[400px] relative`}\n onClick={handleClick}\n >\n <div className={notification.closable ? 'pr-8' : ''}>\n {notification.message && <div className=\"font-bold\">{notification.message}</div>}\n {notification.description && <div className=\"text-sm\">{notification.description}</div>}\n </div>\n {notification.closable && (\n <button\n className=\"btn btn-xs btn-ghost btn-circle absolute top-2 right-2\"\n onClick={(e) => {\n e.stopPropagation()\n onClose()\n }}\n >\n ✕\n </button>\n )}\n </div>\n )\n}\n\nexport const notification = new NotificationManager()\n"],"names":["NotificationManager","listener","l","ReactDOM","jsx","NotificationContainer","config","id","notification","n","manager","forceUpdate","useState","useEffect","notifications","grouped","placementClasses","Fragment","placement","items","NotificationItem","onClose","alertTypeClasses","handleClick","jsxs","e"],"mappings":";;;AAwBA,MAAMA,EAAoB;AAAA,EAChB,gBAAoC,CAAA;AAAA,EACpC,YAAwB,CAAA;AAAA,EACxB,YAAmC;AAAA,EACnC,OAA6B;AAAA,EAC7B,YAAY;AAAA,EAEpB,UAAUC,GAAoB;AAC5B,gBAAK,UAAU,KAAKA,CAAQ,GACrB,MAAM;AACX,WAAK,YAAY,KAAK,UAAU,OAAO,CAACC,MAAMA,MAAMD,CAAQ;AAAA,IAC9D;AAAA,EACF;AAAA,EAEA,mBAAmB;AACjB,WAAO,KAAK;AAAA,EACd;AAAA,EAEQ,OAAO;AACb,SAAK,UAAU,QAAQ,CAACA,MAAaA,GAAU;AAAA,EACjD;AAAA,EAEQ,kBAAkB;AACxB,IAAK,KAAK,cACR,KAAK,YAAY,SAAS,cAAc,KAAK,GAC7C,SAAS,KAAK,YAAY,KAAK,SAAS,GACxC,KAAK,OAAOE,EAAS,WAAW,KAAK,SAAS,GAC9C,KAAK,KAAK,OAAO,gBAAAC,EAACC,GAAA,EAAsB,SAAS,MAAM,CAAE;AAAA,EAE7D;AAAA,EAEA,KAAKC,GAA4B;AAC/B,SAAK,gBAAA;AAEL,UAAMC,IAAK,gBAAgB,EAAE,KAAK,SAAS,IACrCC,IAAiC;AAAA,MACrC,GAAGF;AAAA,MACH,IAAAC;AAAA,MACA,WAAW,KAAK,IAAA;AAAA,MAChB,UAAUD,EAAO,YAAY;AAAA,MAC7B,WAAWA,EAAO,aAAa;AAAA,MAC/B,UAAUA,EAAO,YAAY;AAAA,MAC7B,MAAMA,EAAO,QAAQ;AAAA,IAAA;AAGvB,gBAAK,cAAc,KAAKE,CAAY,GACpC,KAAK,KAAA,GAGDA,EAAa,YAAYA,EAAa,WAAW,KACnD,WAAW,MAAM;AACf,WAAK,MAAMD,CAAE;AAAA,IACf,GAAGC,EAAa,WAAW,GAAI,GAG1BD;AAAA,EACT;AAAA,EAEA,MAAMA,GAAY;AAChB,UAAMC,IAAe,KAAK,cAAc,KAAK,CAACC,MAAMA,EAAE,OAAOF,CAAE;AAC/D,SAAK,gBAAgB,KAAK,cAAc,OAAO,CAACE,MAAMA,EAAE,OAAOF,CAAE,GACjE,KAAK,KAAA,GAEDC,GAAc,WAChBA,EAAa,QAAA;AAAA,EAEjB;AAAA,EAEA,QAAQF,GAA0C;AAChD,WAAO,KAAK,KAAK,EAAE,GAAGA,GAAQ,MAAM,WAAW;AAAA,EACjD;AAAA,EAEA,MAAMA,GAA0C;AAC9C,WAAO,KAAK,KAAK,EAAE,GAAGA,GAAQ,MAAM,SAAS;AAAA,EAC/C;AAAA,EAEA,KAAKA,GAA0C;AAC7C,WAAO,KAAK,KAAK,EAAE,GAAGA,GAAQ,MAAM,QAAQ;AAAA,EAC9C;AAAA,EAEA,QAAQA,GAA0C;AAChD,WAAO,KAAK,KAAK,EAAE,GAAGA,GAAQ,MAAM,WAAW;AAAA,EACjD;AAAA,EAEA,UAAU;AACR,SAAK,gBAAgB,CAAA,GACrB,KAAK,KAAA;AAAA,EACP;AACF;AAMA,SAASD,EAAsB,EAAE,SAAAK,KAAuC;AACtE,QAAM,GAAGC,CAAW,IAAIC,EAAS,EAAE;AAEnC,EAAAC,EAAU,MACYH,EAAQ,UAAU,MAAM;AAC1C,IAAAC,EAAY,CAAA,CAAE;AAAA,EAChB,CAAC,GAEA,CAACD,CAAO,CAAC;AAEZ,QAAMI,IAAgBJ,EAAQ,iBAAA,GAGxBK,IAA6D;AAAA,IACjE,SAAS,CAAA;AAAA,IACT,UAAU,CAAA;AAAA,IACV,YAAY,CAAA;AAAA,IACZ,aAAa,CAAA;AAAA,EAAC;AAGhB,EAAAD,EAAc,QAAQ,CAACN,MAAiB;AACtC,IAAAO,EAAQP,EAAa,SAAU,EAAE,KAAKA,CAAY;AAAA,EACpD,CAAC;AAED,QAAMQ,IAA0D;AAAA,IAC9D,UAAU;AAAA,IACV,SAAS;AAAA,IACT,aAAa;AAAA,IACb,YAAY;AAAA,EAAA;AAGd,SACE,gBAAAZ,EAAAa,GAAA,EACG,UAAA,OAAO,QAAQF,CAAO,EAAE,IAAI,CAAC,CAACG,GAAWC,CAAK,MACzCA,EAAM,WAAW,IAAU,OAG7B,gBAAAf,EAAC,SAAoB,WAAWY,EAAiBE,CAAkC,GAChF,UAAAC,EAAM,IAAI,CAACX,MACV,gBAAAJ;AAAA,IAACgB;AAAA,IAAA;AAAA,MAEC,cAAcZ;AAAAA,MACd,SAAS,MAAME,EAAQ,MAAMF,EAAa,EAAE;AAAA,IAAA;AAAA,IAFvCA,EAAa;AAAA,EAAA,CAIrB,KAPOU,CAQV,CAEH,EAAA,CACH;AAEJ;AAOA,SAASE,EAAiB,EAAE,cAAAZ,GAAc,SAAAa,KAAkC;AAC1E,QAAMC,IAAqD;AAAA,IACzD,SAAS;AAAA,IACT,OAAO;AAAA,IACP,MAAM;AAAA,IACN,SAAS;AAAA,EAAA,GAGLC,IAAc,MAAM;AACxB,IAAIf,EAAa,WACfA,EAAa,QAAA;AAAA,EAEjB;AAEA,SACE,gBAAAgB;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAW,SAASF,EAAiBd,EAAa,IAAK,CAAC;AAAA,MACxD,SAASe;AAAA,MAET,UAAA;AAAA,QAAA,gBAAAC,EAAC,OAAA,EAAI,WAAWhB,EAAa,WAAW,SAAS,IAC9C,UAAA;AAAA,UAAAA,EAAa,WAAW,gBAAAJ,EAAC,OAAA,EAAI,WAAU,aAAa,UAAAI,EAAa,SAAQ;AAAA,UACzEA,EAAa,eAAe,gBAAAJ,EAAC,OAAA,EAAI,WAAU,WAAW,UAAAI,EAAa,YAAA,CAAY;AAAA,QAAA,GAClF;AAAA,QACCA,EAAa,YACZ,gBAAAJ;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,WAAU;AAAA,YACV,SAAS,CAACqB,MAAM;AACd,cAAAA,EAAE,gBAAA,GACFJ,EAAA;AAAA,YACF;AAAA,YACD,UAAA;AAAA,UAAA;AAAA,QAAA;AAAA,MAED;AAAA,IAAA;AAAA,EAAA;AAIR;AAEO,MAAMb,IAAe,IAAIR,EAAA;"}
1
+ {"version":3,"file":"Notification.js","sources":["../../src/components/Notification.tsx"],"sourcesContent":["import React, { useEffect, useState } from 'react'\nimport ReactDOM from 'react-dom/client'\n\nexport type NotificationType = 'success' | 'info' | 'warning' | 'error'\nexport type NotificationPlacement = 'topLeft' | 'topRight' | 'bottomLeft' | 'bottomRight' | 'topCenter' | 'bottomCenter'\nexport type NotificationVariant = 'default' | 'compact'\n\nexport interface NotificationConfig {\n message: React.ReactNode\n description?: React.ReactNode\n type?: NotificationType\n duration?: number // in seconds, 0 = no auto close\n placement?: NotificationPlacement\n variant?: NotificationVariant\n closable?: boolean\n icon?: React.ReactNode\n key?: string\n className?: string\n style?: React.CSSProperties\n 'data-testid'?: string\n onClick?: () => void\n onClose?: () => void\n}\n\ninterface NotificationItem extends NotificationConfig {\n id: string\n createdAt: number\n}\n\ntype Listener = () => void\n\nclass NotificationManager {\n private notifications: NotificationItem[] = []\n private listeners: Listener[] = []\n private container: HTMLDivElement | null = null\n private root: ReactDOM.Root | null = null\n private idCounter = 0\n\n subscribe(listener: Listener) {\n this.listeners.push(listener)\n return () => {\n this.listeners = this.listeners.filter((l) => l !== listener)\n }\n }\n\n getNotifications() {\n return this.notifications\n }\n\n private emit() {\n this.listeners.forEach((listener) => listener())\n }\n\n private ensureContainer() {\n if (!this.container) {\n this.container = document.createElement('div')\n document.body.appendChild(this.container)\n this.root = ReactDOM.createRoot(this.container)\n this.root.render(<NotificationContainer manager={this} />)\n }\n }\n\n open(config: NotificationConfig) {\n this.ensureContainer()\n\n const id = config.key ?? `notification-${++this.idCounter}`\n const isCompact = config.variant === 'compact'\n const notificationItem: NotificationItem = {\n ...config,\n id,\n createdAt: Date.now(),\n duration: config.duration ?? (isCompact ? 3 : 4.5),\n placement: config.placement ?? (isCompact ? 'topCenter' : 'topRight'),\n variant: config.variant ?? 'default',\n closable: config.closable ?? !isCompact,\n type: config.type ?? 'info',\n }\n\n // If key exists, update the existing notification\n const existingIndex = this.notifications.findIndex((n) => n.id === id)\n if (existingIndex !== -1) {\n this.notifications[existingIndex] = notificationItem\n } else {\n this.notifications.push(notificationItem)\n }\n this.emit()\n\n // Auto-dismiss\n if (notificationItem.duration && notificationItem.duration > 0) {\n setTimeout(() => {\n this.close(id)\n }, notificationItem.duration * 1000)\n }\n\n return id\n }\n\n close(id: string) {\n const notification = this.notifications.find((n) => n.id === id)\n this.notifications = this.notifications.filter((n) => n.id !== id)\n this.emit()\n\n if (notification?.onClose) {\n notification.onClose()\n }\n }\n\n success(config: Omit<NotificationConfig, 'type'>) {\n return this.open({ ...config, type: 'success' })\n }\n\n error(config: Omit<NotificationConfig, 'type'>) {\n return this.open({ ...config, type: 'error' })\n }\n\n info(config: Omit<NotificationConfig, 'type'>) {\n return this.open({ ...config, type: 'info' })\n }\n\n warning(config: Omit<NotificationConfig, 'type'>) {\n return this.open({ ...config, type: 'warning' })\n }\n\n destroy() {\n this.notifications = []\n this.emit()\n }\n}\n\ninterface NotificationContainerProps {\n manager: NotificationManager\n}\n\nfunction NotificationContainer({ manager }: NotificationContainerProps) {\n const [, forceUpdate] = useState({})\n\n useEffect(() => {\n const unsubscribe = manager.subscribe(() => {\n forceUpdate({})\n })\n return unsubscribe\n }, [manager])\n\n const notifications = manager.getNotifications()\n\n // Group by placement\n const grouped: Record<NotificationPlacement, NotificationItem[]> = {\n topLeft: [],\n topRight: [],\n topCenter: [],\n bottomLeft: [],\n bottomRight: [],\n bottomCenter: [],\n }\n\n notifications.forEach((notification) => {\n grouped[notification.placement!].push(notification)\n })\n\n const placementClasses: Record<NotificationPlacement, string> = {\n topRight: 'toast toast-top toast-end',\n topLeft: 'toast toast-top toast-start',\n topCenter: 'toast toast-top toast-center',\n bottomRight: 'toast toast-bottom toast-end',\n bottomLeft: 'toast toast-bottom toast-start',\n bottomCenter: 'toast toast-bottom toast-center',\n }\n\n return (\n <>\n {Object.entries(grouped).map(([placement, items]) => {\n if (items.length === 0) return null\n\n return (\n <div key={placement} className={placementClasses[placement as NotificationPlacement]}>\n {items.map((notification) => (\n <NotificationItem\n key={notification.id}\n notification={notification}\n onClose={() => manager.close(notification.id)}\n />\n ))}\n </div>\n )\n })}\n </>\n )\n}\n\ninterface NotificationItemProps {\n notification: NotificationItem\n onClose: () => void\n}\n\nfunction NotificationItem({ notification, onClose }: NotificationItemProps) {\n const isCompact = notification.variant === 'compact'\n\n const alertTypeClasses: Record<NotificationType, string> = {\n success: 'alert-success',\n error: 'alert-error',\n info: 'alert-info',\n warning: 'alert-warning',\n }\n\n const typeIcons: Record<NotificationType, React.ReactNode> = {\n success: <svg xmlns=\"http://www.w3.org/2000/svg\" className=\"h-5 w-5\" viewBox=\"0 0 20 20\" fill=\"currentColor\"><path fillRule=\"evenodd\" d=\"M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z\" clipRule=\"evenodd\" /></svg>,\n error: <svg xmlns=\"http://www.w3.org/2000/svg\" className=\"h-5 w-5\" viewBox=\"0 0 20 20\" fill=\"currentColor\"><path fillRule=\"evenodd\" d=\"M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z\" clipRule=\"evenodd\" /></svg>,\n info: <svg xmlns=\"http://www.w3.org/2000/svg\" className=\"h-5 w-5\" viewBox=\"0 0 20 20\" fill=\"currentColor\"><path fillRule=\"evenodd\" d=\"M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z\" clipRule=\"evenodd\" /></svg>,\n warning: <svg xmlns=\"http://www.w3.org/2000/svg\" className=\"h-5 w-5\" viewBox=\"0 0 20 20\" fill=\"currentColor\"><path fillRule=\"evenodd\" d=\"M8.257 3.099c.765-1.36 2.722-1.36 3.486 0l5.58 9.92c.75 1.334-.213 2.98-1.742 2.98H4.42c-1.53 0-2.493-1.646-1.743-2.98l5.58-9.92zM11 13a1 1 0 11-2 0 1 1 0 012 0zm-1-8a1 1 0 00-1 1v3a1 1 0 002 0V6a1 1 0 00-1-1z\" clipRule=\"evenodd\" /></svg>,\n }\n\n const handleClick = () => {\n if (notification.onClick) {\n notification.onClick()\n }\n }\n\n const icon = notification.icon ?? typeIcons[notification.type!]\n\n if (isCompact) {\n return (\n <div\n className={`alert ${alertTypeClasses[notification.type!]} shadow-md py-2 px-4 cursor-pointer${notification.className ? ` ${notification.className}` : ''}`}\n style={notification.style}\n data-testid={notification['data-testid']}\n onClick={handleClick}\n >\n <div className=\"flex items-center gap-2\">\n {icon}\n <span>{notification.message}</span>\n </div>\n </div>\n )\n }\n\n return (\n <div\n className={`alert ${alertTypeClasses[notification.type!]} shadow-lg cursor-pointer min-w-[300px] max-w-[400px] relative${notification.className ? ` ${notification.className}` : ''}`}\n style={notification.style}\n data-testid={notification['data-testid']}\n onClick={handleClick}\n >\n <div className={notification.closable ? 'pr-8' : ''}>\n {notification.message && <div className=\"font-bold\">{notification.message}</div>}\n {notification.description && <div className=\"text-sm\">{notification.description}</div>}\n </div>\n {notification.closable && (\n <button\n className=\"btn btn-xs btn-ghost btn-circle absolute top-2 right-2\"\n onClick={(e) => {\n e.stopPropagation()\n onClose()\n }}\n >\n ✕\n </button>\n )}\n </div>\n )\n}\n\nexport const notification = new NotificationManager()\n"],"names":["NotificationManager","listener","l","ReactDOM","jsx","NotificationContainer","config","id","isCompact","notificationItem","existingIndex","n","notification","manager","forceUpdate","useState","useEffect","notifications","grouped","placementClasses","Fragment","placement","items","NotificationItem","onClose","alertTypeClasses","typeIcons","handleClick","icon","jsxs","e"],"mappings":"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"}
@@ -1,5 +1,17 @@
1
1
  import { default as React } from 'react';
2
2
  export type TourPlacement = 'top' | 'topLeft' | 'topRight' | 'bottom' | 'bottomLeft' | 'bottomRight' | 'left' | 'leftTop' | 'leftBottom' | 'right' | 'rightTop' | 'rightBottom' | 'center';
3
+ export type TourType = 'default' | 'primary';
4
+ export interface TourArrowConfig {
5
+ pointAtCenter?: boolean;
6
+ }
7
+ export interface TourMaskConfig {
8
+ style?: React.CSSProperties;
9
+ color?: string;
10
+ }
11
+ export interface TourButtonProps {
12
+ children?: React.ReactNode;
13
+ onClick?: () => void;
14
+ }
3
15
  export interface TourStepProps {
4
16
  /** Target element ref or function returning element */
5
17
  target?: React.RefObject<HTMLElement | null> | (() => HTMLElement | null) | null;
@@ -11,14 +23,43 @@ export interface TourStepProps {
11
23
  cover?: React.ReactNode;
12
24
  /** Placement of popover relative to target */
13
25
  placement?: TourPlacement;
26
+ /** Whether to show arrow (overrides Tour setting) */
27
+ arrow?: boolean | TourArrowConfig;
28
+ /** Custom close icon for this step */
29
+ closeIcon?: React.ReactNode;
30
+ /** Show mask overlay (overrides Tour setting) */
31
+ mask?: boolean | TourMaskConfig;
32
+ /** Type affects styling (overrides Tour setting) */
33
+ type?: TourType;
34
+ /** Scroll into view options (overrides Tour setting) */
35
+ scrollIntoViewOptions?: boolean | ScrollIntoViewOptions;
36
+ /** Next button props */
37
+ nextButtonProps?: TourButtonProps;
38
+ /** Previous button props */
39
+ prevButtonProps?: TourButtonProps;
14
40
  /** Custom class for this step's popover */
15
41
  className?: string;
42
+ /** Custom style for this step's popover */
43
+ style?: React.CSSProperties;
16
44
  /** Called when this step becomes active */
17
- onOpen?: () => void;
18
- /** Called when leaving this step */
19
45
  onClose?: () => void;
20
46
  }
21
- export interface TourProps {
47
+ export type TourSemanticName = 'root' | 'mask' | 'popover' | 'header' | 'content' | 'footer' | 'indicator' | 'close';
48
+ export interface TourActionInfo {
49
+ current: number;
50
+ total: number;
51
+ }
52
+ export interface TourRef {
53
+ /** Go to a specific step */
54
+ goTo: (step: number) => void;
55
+ /** Go to the next step */
56
+ next: () => void;
57
+ /** Go to the previous step */
58
+ prev: () => void;
59
+ /** Close the tour */
60
+ close: () => void;
61
+ }
62
+ export interface TourProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'onChange'> {
22
63
  /** Whether tour is visible */
23
64
  open?: boolean;
24
65
  /** Callback when tour closes */
@@ -31,12 +72,21 @@ export interface TourProps {
31
72
  current?: number;
32
73
  /** Callback when step changes */
33
74
  onChange?: (current: number) => void;
75
+ /** Whether to show arrow on popover */
76
+ arrow?: boolean | TourArrowConfig;
77
+ /** Custom close icon */
78
+ closeIcon?: React.ReactNode;
34
79
  /** Show mask overlay */
35
- mask?: boolean;
80
+ mask?: boolean | TourMaskConfig;
81
+ /** Disable interaction on highlighted area */
82
+ disabledInteraction?: boolean;
36
83
  /** Type affects styling */
37
- type?: 'default' | 'primary';
38
- /** Gap between highlight and target [radius, offset] or single number */
39
- gap?: number | [number, number];
84
+ type?: TourType;
85
+ /** Gap between highlight and target */
86
+ gap?: {
87
+ offset?: number | [number, number];
88
+ radius?: number;
89
+ };
40
90
  /** Text for prev button */
41
91
  prevButtonText?: React.ReactNode;
42
92
  /** Text for next button */
@@ -54,8 +104,20 @@ export interface TourProps {
54
104
  /** Close on escape key */
55
105
  closeOnEscape?: boolean;
56
106
  /** Scroll target into view */
57
- scrollIntoView?: boolean;
107
+ scrollIntoViewOptions?: boolean | ScrollIntoViewOptions;
58
108
  /** Z-index for tour overlay */
59
109
  zIndex?: number;
110
+ /** Custom indicator renderer */
111
+ indicatorsRender?: (current: number, total: number) => React.ReactNode;
112
+ /** Custom action buttons renderer */
113
+ actionsRender?: (originNode: React.ReactNode, info: TourActionInfo) => React.ReactNode;
114
+ /** Rendering container for tour */
115
+ getPopupContainer?: (node: HTMLElement) => HTMLElement;
116
+ /** Semantic class names */
117
+ classNames?: Partial<Record<TourSemanticName, string>>;
118
+ /** Semantic styles */
119
+ styles?: Partial<Record<TourSemanticName, React.CSSProperties>>;
120
+ /** Test ID for testing */
121
+ 'data-testid'?: string;
60
122
  }
61
- export declare const Tour: React.FC<TourProps>;
123
+ export declare const Tour: React.ForwardRefExoticComponent<TourProps & React.RefAttributes<TourRef>>;