@charcoal-ui/react 6.1.0-beta.4 → 6.1.0-beta.5
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/components/Notification/Snackbar/index.d.ts +1 -1
- package/dist/components/Notification/Snackbar/index.d.ts.map +1 -1
- package/dist/components/Notification/Snackbar/index2.cjs +3 -4
- package/dist/components/Notification/Snackbar/index2.cjs.map +1 -1
- package/dist/components/Notification/Snackbar/index2.js +3 -4
- package/dist/components/Notification/Snackbar/index2.js.map +1 -1
- package/dist/components/Notification/useNotificationQueue.cjs +5 -8
- package/dist/components/Notification/useNotificationQueue.cjs.map +1 -1
- package/dist/components/Notification/useNotificationQueue.d.ts +2 -4
- package/dist/components/Notification/useNotificationQueue.d.ts.map +1 -1
- package/dist/components/Notification/useNotificationQueue.js +5 -8
- package/dist/components/Notification/useNotificationQueue.js.map +1 -1
- package/dist/index.css +1308 -1308
- package/dist/layered.css +1308 -1308
- package/dist/layered.css.map +1 -1
- package/package.json +5 -5
- package/src/components/Notification/Snackbar/index.test.tsx +21 -5
- package/src/components/Notification/Snackbar/index.tsx +6 -6
- package/src/components/Notification/useNotificationQueue.ts +7 -18
|
@@ -2,7 +2,7 @@ import '../layout.css';
|
|
|
2
2
|
import './index.css';
|
|
3
3
|
import { type HTMLAttributes, type ReactNode } from 'react';
|
|
4
4
|
import type { NotificationProps, Position } from '../types';
|
|
5
|
-
export type SnackbarCloseReason = '
|
|
5
|
+
export type SnackbarCloseReason = 'action' | 'unmounted';
|
|
6
6
|
export type SnackbarRootAttributes = {
|
|
7
7
|
[key: `data-${string}`]: string | number | boolean | undefined;
|
|
8
8
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/Notification/Snackbar/index.tsx"],"names":[],"mappings":"AAAA,OAAO,eAAe,CAAA;AACtB,OAAO,aAAa,CAAA;AAEpB,OAAO,EAAc,KAAK,cAAc,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAKvE,OAAO,KAAK,EAAE,iBAAiB,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AAE3D,MAAM,MAAM,mBAAmB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/Notification/Snackbar/index.tsx"],"names":[],"mappings":"AAAA,OAAO,eAAe,CAAA;AACtB,OAAO,aAAa,CAAA;AAEpB,OAAO,EAAc,KAAK,cAAc,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAKvE,OAAO,KAAK,EAAE,iBAAiB,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AAE3D,MAAM,MAAM,mBAAmB,GAAG,QAAQ,GAAG,WAAW,CAAA;AAExD,MAAM,MAAM,sBAAsB,GAAG;IACnC,CAAC,GAAG,EAAE,QAAQ,MAAM,EAAE,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,CAAA;CAC/D,CAAA;AAED,MAAM,MAAM,mBAAmB,GAAG;IAChC,MAAM,CAAC,EAAE,SAAS,CAAA;IAClB,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,mBAAmB,KAAK,IAAI,CAAA;IAC/C,cAAc,CAAC,EAAE,sBAAsB,CAAA;CACxC,CAAA;AAED,KAAK,iBAAiB,GAAG;IACvB,OAAO,EAAE,SAAS,CAAA;IAClB,MAAM,CAAC,EAAE,SAAS,CAAA;IAClB,GAAG,CAAC,EAAE,OAAO,CAAA;CACd,GAAG,IAAI,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,UAAU,CAAC,CAAA;AAEpD,MAAM,MAAM,aAAa,GAAG,IAAI,CAAC,iBAAiB,EAAE,QAAQ,CAAC,GAAG;IAC9D,6BAA6B;IAC7B,MAAM,EAAE,WAAW,CAAC,SAAS,CAAC,CAAA;CAC/B,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG,IAAI,CAAC,iBAAiB,EAAE,UAAU,CAAC,GAAG;IACnE,QAAQ,CAAC,EAAE,QAAQ,CAAA;IACnB,GAAG,CAAC,EAAE,OAAO,CAAA;CACd,CAAA;AAQD,QAAA,MAAM,QAAQ;IAfZ,6BAA6B;YACrB,WAAW,CAAC,SAAS,CAAC;kDAkB/B,CAAA;eAEc,QAAQ;AAEvB,wBAAgB,WAAW,CAAC,KAAK,GAAE,gBAAqB,gEAiB/B,SAAS,YAAW,mBAAmB,WAiD/D"}
|
|
@@ -21,16 +21,15 @@ function useSnackbar(props = {}) {
|
|
|
21
21
|
const { state, itemRef, enqueue, close, onHoverStart, onHoverEnd } = require_useNotificationQueue.useNotificationQueue("snackbar", {
|
|
22
22
|
duration,
|
|
23
23
|
order,
|
|
24
|
-
animateReplace: true
|
|
25
|
-
timeoutReason: "timeout",
|
|
26
|
-
unmountedReason: "unmounted"
|
|
24
|
+
animateReplace: true
|
|
27
25
|
});
|
|
28
26
|
function show(message, options = {}) {
|
|
27
|
+
const onClose = options.onClose;
|
|
29
28
|
enqueue({
|
|
30
29
|
message,
|
|
31
30
|
action: options.action,
|
|
32
31
|
rootAttributes: options.rootAttributes
|
|
33
|
-
},
|
|
32
|
+
}, onClose === void 0 ? void 0 : (reason) => onClose(reason ?? "unmounted"));
|
|
34
33
|
}
|
|
35
34
|
return [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_NotificationRegion.NotificationRegion, {
|
|
36
35
|
name: "snackbar",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index2.cjs","names":["toast"],"sources":["../../../../src/components/Notification/Snackbar/index.tsx"],"sourcesContent":["import '../layout.css'\nimport './index.css'\n\nimport { forwardRef, type HTMLAttributes, type ReactNode } from 'react'\nimport { useClassNames } from '../../../_lib/useClassNames'\nimport { NotificationItem } from '../NotificationItem'\nimport { NotificationRegion } from '../NotificationRegion'\nimport { useNotificationQueue } from '../useNotificationQueue'\nimport type { NotificationProps, Position } from '../types'\n\nexport type SnackbarCloseReason
|
|
1
|
+
{"version":3,"file":"index2.cjs","names":["toast"],"sources":["../../../../src/components/Notification/Snackbar/index.tsx"],"sourcesContent":["import '../layout.css'\nimport './index.css'\n\nimport { forwardRef, type HTMLAttributes, type ReactNode } from 'react'\nimport { useClassNames } from '../../../_lib/useClassNames'\nimport { NotificationItem } from '../NotificationItem'\nimport { NotificationRegion } from '../NotificationRegion'\nimport { useNotificationQueue } from '../useNotificationQueue'\nimport type { NotificationProps, Position } from '../types'\n\nexport type SnackbarCloseReason = 'action' | 'unmounted'\n\nexport type SnackbarRootAttributes = {\n [key: `data-${string}`]: string | number | boolean | undefined\n}\n\nexport type ShowSnackbarOptions = {\n action?: ReactNode\n onClose?: (reason: SnackbarCloseReason) => void\n rootAttributes?: SnackbarRootAttributes\n}\n\ntype SnackbarBaseProps = {\n message: ReactNode\n action?: ReactNode\n dim?: boolean\n} & Omit<HTMLAttributes<HTMLDivElement>, 'children'>\n\nexport type SnackbarProps = Omit<SnackbarBaseProps, 'action'> & {\n /** Snackbar の右側に表示するアクション */\n action: NonNullable<ReactNode>\n}\n\nexport type UseSnackbarProps = Omit<NotificationProps, 'position'> & {\n position?: Position\n dim?: boolean\n}\n\ntype SnackbarContent = {\n message: ReactNode\n action?: ReactNode\n rootAttributes?: SnackbarRootAttributes\n}\n\nconst Snackbar = forwardRef<HTMLDivElement, SnackbarProps>(\n function Snackbar(props, ref) {\n return <SnackbarBase {...props} ref={ref} />\n },\n)\n\nexport default Snackbar\n\nexport function useSnackbar(props: UseSnackbarProps = {}) {\n 'use memo'\n\n const {\n position = 'bottom',\n dim = false,\n duration,\n order,\n ...regionProps\n } = props\n const { state, itemRef, enqueue, close, onHoverStart, onHoverEnd } =\n useNotificationQueue<SnackbarContent, 'action'>('snackbar', {\n duration,\n order,\n animateReplace: true,\n })\n\n function show(message: ReactNode, options: ShowSnackbarOptions = {}) {\n const onClose = options.onClose\n enqueue(\n {\n message,\n action: options.action,\n rootAttributes: options.rootAttributes,\n },\n onClose === undefined\n ? undefined\n : (reason) => onClose(reason ?? 'unmounted'),\n )\n }\n\n const hasAction = state.visibleToasts.some(\n (toast) => toast.content.action !== undefined,\n )\n const effectivePosition = hasAction ? 'bottom' : position\n const element = (\n <NotificationRegion\n name=\"snackbar\"\n state={state}\n position={effectivePosition}\n {...regionProps}\n >\n {state.visibleToasts.map((toast) => (\n <NotificationItem\n {...toast.content.rootAttributes}\n key={toast.key}\n name=\"snackbar\"\n toast={toast}\n state={state}\n itemRef={itemRef}\n onHoverStart={onHoverStart}\n onHoverEnd={onHoverEnd}\n data-dim={dim}\n data-with-action={toast.content.action !== undefined}\n >\n {toast.content.action !== undefined && (\n <div onClick={() => close(toast.key, 'action')}>\n <SnackbarAction action={toast.content.action} />\n </div>\n )}\n </NotificationItem>\n ))}\n </NotificationRegion>\n )\n\n return [element, show] as const\n}\n\nconst SnackbarBase = forwardRef<HTMLDivElement, SnackbarBaseProps>(\n function SnackbarBase(\n { message, action, dim = false, className, ...rootProps },\n ref,\n ) {\n const classNames = useClassNames(\n 'charcoal-notification',\n 'charcoal-snackbar',\n className,\n )\n\n return (\n <div\n {...rootProps}\n ref={ref}\n className={classNames}\n data-dim={dim}\n data-with-action={action !== undefined}\n >\n <div role=\"status\" className=\"charcoal-notification-content\">\n <div className=\"charcoal-notification-label\">{message}</div>\n </div>\n {action !== undefined && <SnackbarAction action={action} />}\n </div>\n )\n },\n)\n\nfunction SnackbarAction({ action }: { action: ReactNode }) {\n return <div>{action}</div>\n}\n"],"mappings":";;;;;;;;;;;AA4CA,MAAM,iCACJ,SAAS,SAAS,OAAO,KAAK;CAC5B,OAAO,2CAAC,cAAD;EAAc,GAAI;EAAY;CAAI;AAC3C,CACF;AAIA,SAAgB,YAAY,QAA0B,CAAC,GAAG;CACxD;CAEA,MAAM,EACJ,WAAW,UACX,MAAM,OACN,UACA,OACA,GAAG,gBACD;CACJ,MAAM,EAAE,OAAO,SAAS,SAAS,OAAO,cAAc,eACpD,kDAAgD,YAAY;EAC1D;EACA;EACA,gBAAgB;CAClB,CAAC;CAEH,SAAS,KAAK,SAAoB,UAA+B,CAAC,GAAG;EACnE,MAAM,UAAU,QAAQ;EACxB,QACE;GACE;GACA,QAAQ,QAAQ;GAChB,gBAAgB,QAAQ;EAC1B,GACA,YAAY,SACR,UACC,WAAW,QAAQ,UAAU,WAAW,CAC/C;CACF;CAoCA,OAAO,CAAC,2CA7BL,+CAAD;EACE,MAAK;EACE;EACP,UARc,MAAM,cAAc,MACnC,UAAU,MAAM,QAAQ,WAAW,MAEZ,IAAY,WAAW;EAM7C,GAAI;YAEH,MAAM,cAAc,KAAKA,YACxB,yCAAC,2CAAD;GACE,GAAIA,QAAM,QAAQ;GAClB,KAAKA,QAAM;GACX,MAAK;GACL,OAAOA;GACA;GACE;GACK;GACF;GACZ,YAAU;GACV,oBAAkBA,QAAM,QAAQ,WAAW;EAO3B,GALfA,QAAM,QAAQ,WAAW,UACxB,2CAAC,OAAD;GAAK,eAAe,MAAMA,QAAM,KAAK,QAAQ;aAC3C,2CAAC,gBAAD,EAAgB,QAAQA,QAAM,QAAQ,OAAO;EAC1C,EAES,CACnB;CACiB,CAGd,GAAS,IAAI;AACvB;AAEA,MAAM,qCACJ,SAAS,aACP,EAAE,SAAS,QAAQ,MAAM,OAAO,WAAW,GAAG,aAC9C,KACA;CACA,MAAM,aAAa,oCACjB,yBACA,qBACA,SACF;CAEA,OACE,4CAAC,OAAD;EACE,GAAI;EACC;EACL,WAAW;EACX,YAAU;EACV,oBAAkB,WAAW;YAL/B,CAOE,2CAAC,OAAD;GAAK,MAAK;GAAS,WAAU;aAC3B,2CAAC,OAAD;IAAK,WAAU;cAA+B;GAAa;EACxD,IACJ,WAAW,UAAa,2CAAC,gBAAD,EAAwB,OAAO,EACrD;;AAET,CACF;AAEA,SAAS,eAAe,EAAE,UAAiC;CACzD,OAAO,2CAAC,OAAD,YAAM,OAAY;AAC3B"}
|
|
@@ -21,16 +21,15 @@ function useSnackbar(props = {}) {
|
|
|
21
21
|
const { state, itemRef, enqueue, close, onHoverStart, onHoverEnd } = useNotificationQueue("snackbar", {
|
|
22
22
|
duration,
|
|
23
23
|
order,
|
|
24
|
-
animateReplace: true
|
|
25
|
-
timeoutReason: "timeout",
|
|
26
|
-
unmountedReason: "unmounted"
|
|
24
|
+
animateReplace: true
|
|
27
25
|
});
|
|
28
26
|
function show(message, options = {}) {
|
|
27
|
+
const onClose = options.onClose;
|
|
29
28
|
enqueue({
|
|
30
29
|
message,
|
|
31
30
|
action: options.action,
|
|
32
31
|
rootAttributes: options.rootAttributes
|
|
33
|
-
},
|
|
32
|
+
}, onClose === void 0 ? void 0 : (reason) => onClose(reason ?? "unmounted"));
|
|
34
33
|
}
|
|
35
34
|
return [/* @__PURE__ */ jsx(NotificationRegion, {
|
|
36
35
|
name: "snackbar",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index2.js","names":["toast"],"sources":["../../../../src/components/Notification/Snackbar/index.tsx"],"sourcesContent":["import '../layout.css'\nimport './index.css'\n\nimport { forwardRef, type HTMLAttributes, type ReactNode } from 'react'\nimport { useClassNames } from '../../../_lib/useClassNames'\nimport { NotificationItem } from '../NotificationItem'\nimport { NotificationRegion } from '../NotificationRegion'\nimport { useNotificationQueue } from '../useNotificationQueue'\nimport type { NotificationProps, Position } from '../types'\n\nexport type SnackbarCloseReason
|
|
1
|
+
{"version":3,"file":"index2.js","names":["toast"],"sources":["../../../../src/components/Notification/Snackbar/index.tsx"],"sourcesContent":["import '../layout.css'\nimport './index.css'\n\nimport { forwardRef, type HTMLAttributes, type ReactNode } from 'react'\nimport { useClassNames } from '../../../_lib/useClassNames'\nimport { NotificationItem } from '../NotificationItem'\nimport { NotificationRegion } from '../NotificationRegion'\nimport { useNotificationQueue } from '../useNotificationQueue'\nimport type { NotificationProps, Position } from '../types'\n\nexport type SnackbarCloseReason = 'action' | 'unmounted'\n\nexport type SnackbarRootAttributes = {\n [key: `data-${string}`]: string | number | boolean | undefined\n}\n\nexport type ShowSnackbarOptions = {\n action?: ReactNode\n onClose?: (reason: SnackbarCloseReason) => void\n rootAttributes?: SnackbarRootAttributes\n}\n\ntype SnackbarBaseProps = {\n message: ReactNode\n action?: ReactNode\n dim?: boolean\n} & Omit<HTMLAttributes<HTMLDivElement>, 'children'>\n\nexport type SnackbarProps = Omit<SnackbarBaseProps, 'action'> & {\n /** Snackbar の右側に表示するアクション */\n action: NonNullable<ReactNode>\n}\n\nexport type UseSnackbarProps = Omit<NotificationProps, 'position'> & {\n position?: Position\n dim?: boolean\n}\n\ntype SnackbarContent = {\n message: ReactNode\n action?: ReactNode\n rootAttributes?: SnackbarRootAttributes\n}\n\nconst Snackbar = forwardRef<HTMLDivElement, SnackbarProps>(\n function Snackbar(props, ref) {\n return <SnackbarBase {...props} ref={ref} />\n },\n)\n\nexport default Snackbar\n\nexport function useSnackbar(props: UseSnackbarProps = {}) {\n 'use memo'\n\n const {\n position = 'bottom',\n dim = false,\n duration,\n order,\n ...regionProps\n } = props\n const { state, itemRef, enqueue, close, onHoverStart, onHoverEnd } =\n useNotificationQueue<SnackbarContent, 'action'>('snackbar', {\n duration,\n order,\n animateReplace: true,\n })\n\n function show(message: ReactNode, options: ShowSnackbarOptions = {}) {\n const onClose = options.onClose\n enqueue(\n {\n message,\n action: options.action,\n rootAttributes: options.rootAttributes,\n },\n onClose === undefined\n ? undefined\n : (reason) => onClose(reason ?? 'unmounted'),\n )\n }\n\n const hasAction = state.visibleToasts.some(\n (toast) => toast.content.action !== undefined,\n )\n const effectivePosition = hasAction ? 'bottom' : position\n const element = (\n <NotificationRegion\n name=\"snackbar\"\n state={state}\n position={effectivePosition}\n {...regionProps}\n >\n {state.visibleToasts.map((toast) => (\n <NotificationItem\n {...toast.content.rootAttributes}\n key={toast.key}\n name=\"snackbar\"\n toast={toast}\n state={state}\n itemRef={itemRef}\n onHoverStart={onHoverStart}\n onHoverEnd={onHoverEnd}\n data-dim={dim}\n data-with-action={toast.content.action !== undefined}\n >\n {toast.content.action !== undefined && (\n <div onClick={() => close(toast.key, 'action')}>\n <SnackbarAction action={toast.content.action} />\n </div>\n )}\n </NotificationItem>\n ))}\n </NotificationRegion>\n )\n\n return [element, show] as const\n}\n\nconst SnackbarBase = forwardRef<HTMLDivElement, SnackbarBaseProps>(\n function SnackbarBase(\n { message, action, dim = false, className, ...rootProps },\n ref,\n ) {\n const classNames = useClassNames(\n 'charcoal-notification',\n 'charcoal-snackbar',\n className,\n )\n\n return (\n <div\n {...rootProps}\n ref={ref}\n className={classNames}\n data-dim={dim}\n data-with-action={action !== undefined}\n >\n <div role=\"status\" className=\"charcoal-notification-content\">\n <div className=\"charcoal-notification-label\">{message}</div>\n </div>\n {action !== undefined && <SnackbarAction action={action} />}\n </div>\n )\n },\n)\n\nfunction SnackbarAction({ action }: { action: ReactNode }) {\n return <div>{action}</div>\n}\n"],"mappings":";;;;;;;;;;;AA4CA,MAAM,WAAW,WACf,SAAS,SAAS,OAAO,KAAK;CAC5B,OAAO,oBAAC,cAAD;EAAc,GAAI;EAAY;CAAI;AAC3C,CACF;AAIA,SAAgB,YAAY,QAA0B,CAAC,GAAG;CACxD;CAEA,MAAM,EACJ,WAAW,UACX,MAAM,OACN,UACA,OACA,GAAG,gBACD;CACJ,MAAM,EAAE,OAAO,SAAS,SAAS,OAAO,cAAc,eACpD,qBAAgD,YAAY;EAC1D;EACA;EACA,gBAAgB;CAClB,CAAC;CAEH,SAAS,KAAK,SAAoB,UAA+B,CAAC,GAAG;EACnE,MAAM,UAAU,QAAQ;EACxB,QACE;GACE;GACA,QAAQ,QAAQ;GAChB,gBAAgB,QAAQ;EAC1B,GACA,YAAY,SACR,UACC,WAAW,QAAQ,UAAU,WAAW,CAC/C;CACF;CAoCA,OAAO,CAAC,oBA7BL,oBAAD;EACE,MAAK;EACE;EACP,UARc,MAAM,cAAc,MACnC,UAAU,MAAM,QAAQ,WAAW,MAEZ,IAAY,WAAW;EAM7C,GAAI;YAEH,MAAM,cAAc,KAAKA,YACxB,8BAAC,kBAAD;GACE,GAAIA,QAAM,QAAQ;GAClB,KAAKA,QAAM;GACX,MAAK;GACL,OAAOA;GACA;GACE;GACK;GACF;GACZ,YAAU;GACV,oBAAkBA,QAAM,QAAQ,WAAW;EAO3B,GALfA,QAAM,QAAQ,WAAW,UACxB,oBAAC,OAAD;GAAK,eAAe,MAAMA,QAAM,KAAK,QAAQ;aAC3C,oBAAC,gBAAD,EAAgB,QAAQA,QAAM,QAAQ,OAAO;EAC1C,EAES,CACnB;CACiB,CAGd,GAAS,IAAI;AACvB;AAEA,MAAM,eAAe,WACnB,SAAS,aACP,EAAE,SAAS,QAAQ,MAAM,OAAO,WAAW,GAAG,aAC9C,KACA;CACA,MAAM,aAAa,cACjB,yBACA,qBACA,SACF;CAEA,OACE,qBAAC,OAAD;EACE,GAAI;EACC;EACL,WAAW;EACX,YAAU;EACV,oBAAkB,WAAW;YAL/B,CAOE,oBAAC,OAAD;GAAK,MAAK;GAAS,WAAU;aAC3B,oBAAC,OAAD;IAAK,WAAU;cAA+B;GAAa;EACxD,IACJ,WAAW,UAAa,oBAAC,gBAAD,EAAwB,OAAO,EACrD;;AAET,CACF;AAEA,SAAS,eAAe,EAAE,UAAiC;CACzD,OAAO,oBAAC,OAAD,YAAM,OAAY;AAC3B"}
|
|
@@ -5,7 +5,7 @@ let react_stately_useToastState = require("react-stately/useToastState");
|
|
|
5
5
|
//#region src/components/Notification/useNotificationQueue.ts
|
|
6
6
|
const DEFAULT_DURATION_MS = 5e3;
|
|
7
7
|
const ANIMATION_DURATION_MS = 300;
|
|
8
|
-
function useNotificationQueue(name, { duration: durationOption, order = "queue", animateReplace = false
|
|
8
|
+
function useNotificationQueue(name, { duration: durationOption, order = "queue", animateReplace = false } = {}) {
|
|
9
9
|
const itemRef = (0, react.useRef)(null);
|
|
10
10
|
const queueRef = (0, react.useRef)([]);
|
|
11
11
|
const isShowingRef = (0, react.useRef)(false);
|
|
@@ -29,8 +29,7 @@ function useNotificationQueue(name, { duration: durationOption, order = "queue",
|
|
|
29
29
|
update();
|
|
30
30
|
if (active !== void 0 && !active.notified) {
|
|
31
31
|
active.notified = true;
|
|
32
|
-
|
|
33
|
-
if (reason !== void 0) active.onClose?.(reason);
|
|
32
|
+
active.onClose?.(active.reason);
|
|
34
33
|
}
|
|
35
34
|
playNextRef.current?.();
|
|
36
35
|
}
|
|
@@ -64,21 +63,20 @@ function useNotificationQueue(name, { duration: durationOption, order = "queue",
|
|
|
64
63
|
item.addEventListener("animationend", handleAnimationEnd);
|
|
65
64
|
fallbackTimer = window.setTimeout(complete, 400);
|
|
66
65
|
if (window.matchMedia?.("(prefers-reduced-motion: reduce)").matches) complete();
|
|
67
|
-
}, [name
|
|
66
|
+
}, [name])
|
|
68
67
|
});
|
|
69
68
|
(0, react.useEffect)(() => {
|
|
70
69
|
return () => {
|
|
71
70
|
const active = activeRef.current;
|
|
72
71
|
if (active !== void 0 && !active.notified) {
|
|
73
72
|
active.notified = true;
|
|
74
|
-
|
|
75
|
-
if (reason !== void 0) active.onClose?.(reason);
|
|
73
|
+
active.onClose?.(active.reason);
|
|
76
74
|
}
|
|
77
75
|
activeRef.current = void 0;
|
|
78
76
|
queueRef.current = [];
|
|
79
77
|
isShowingRef.current = false;
|
|
80
78
|
};
|
|
81
|
-
}, [
|
|
79
|
+
}, []);
|
|
82
80
|
function playNext() {
|
|
83
81
|
const next = queueRef.current.shift();
|
|
84
82
|
if (next === void 0) {
|
|
@@ -107,7 +105,6 @@ function useNotificationQueue(name, { duration: durationOption, order = "queue",
|
|
|
107
105
|
else if (order === "replace") {
|
|
108
106
|
const active = activeRef.current;
|
|
109
107
|
if (active === void 0) return;
|
|
110
|
-
active.reason = "replaced";
|
|
111
108
|
replaceRef.current = !animateReplace;
|
|
112
109
|
hoverRef.current.active = false;
|
|
113
110
|
const pending = hoverRef.current.pending;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useNotificationQueue.cjs","names":[],"sources":["../../../src/components/Notification/useNotificationQueue.ts"],"sourcesContent":["import { useCallback, useEffect, useRef } from 'react'\nimport { useToastState } from 'react-stately/useToastState'\nimport type { NotificationName, NotificationOrder } from './types'\n\nconst DEFAULT_DURATION_MS = 5000\nconst ANIMATION_DURATION_MS = 300\n\ntype QueueItem<TContent, TCloseReason> = {\n content: TContent\n onClose?: (reason
|
|
1
|
+
{"version":3,"file":"useNotificationQueue.cjs","names":[],"sources":["../../../src/components/Notification/useNotificationQueue.ts"],"sourcesContent":["import { useCallback, useEffect, useRef } from 'react'\nimport { useToastState } from 'react-stately/useToastState'\nimport type { NotificationName, NotificationOrder } from './types'\n\nconst DEFAULT_DURATION_MS = 5000\nconst ANIMATION_DURATION_MS = 300\n\ntype QueueItem<TContent, TCloseReason> = {\n content: TContent\n onClose?: (reason?: TCloseReason) => void\n}\n\nexport function useNotificationQueue<\n TContent,\n TCloseReason extends string = never,\n>(\n name: NotificationName,\n {\n duration: durationOption,\n order = 'queue',\n animateReplace = false,\n }: {\n duration?: number\n order?: NotificationOrder\n animateReplace?: boolean\n } = {},\n) {\n const itemRef = useRef<HTMLDivElement>(null)\n const queueRef = useRef<\n Array<QueueItem<TContent, TCloseReason> & { duration: number }>\n >([])\n const isShowingRef = useRef(false)\n const activeRef = useRef<{\n key: string\n onClose?: (reason?: TCloseReason) => void\n reason?: TCloseReason\n notified: boolean\n }>()\n const replaceRef = useRef(false)\n const hoverRef = useRef({\n active: false,\n pending: undefined as (() => void) | undefined,\n })\n // wrapUpdate を固定したまま、後から定義する playNext の最新版を呼ぶ\n const playNextRef = useRef<(() => void) | undefined>(undefined)\n\n // wrapUpdate の参照が変わると useToastState が ToastQueue を作り直すため useCallback で固定する\n const wrapUpdate = useCallback(\n function wrapUpdate(\n update: () => void,\n action: 'add' | 'remove' | 'clear',\n ) {\n if (action !== 'remove') {\n update()\n return\n }\n\n function finish() {\n const active = activeRef.current\n activeRef.current = undefined\n update()\n if (active !== undefined && !active.notified) {\n active.notified = true\n active.onClose?.(active.reason)\n }\n playNextRef.current?.()\n }\n\n if (hoverRef.current.active) {\n hoverRef.current.pending = () => wrapUpdate(update, 'remove')\n return\n }\n\n if (itemRef.current === null) {\n finish()\n return\n }\n\n if (replaceRef.current) {\n replaceRef.current = false\n finish()\n return\n }\n\n const item: HTMLDivElement = itemRef.current\n\n // allow-discreteが Newly Available で使えないので、要素の削除をアニメーション完了まで待つ\n item.dataset.exiting = 'true'\n let completed = false\n let fallbackTimer = 0 // complete 内で clearTimeout(setTimeout(...)) すると新規タイマーを即キャンセルしてしまう\n function handleAnimationEnd(event: AnimationEvent) {\n if (\n event.target === item &&\n event.animationName === `charcoal-${name}-exit`\n ) {\n complete()\n }\n }\n function complete() {\n if (completed) return\n completed = true\n item.removeEventListener('animationend', handleAnimationEnd)\n window.clearTimeout(fallbackTimer)\n finish()\n }\n item.addEventListener('animationend', handleAnimationEnd)\n fallbackTimer = window.setTimeout(complete, ANIMATION_DURATION_MS + 100)\n if (window.matchMedia?.('(prefers-reduced-motion: reduce)').matches) {\n complete()\n }\n },\n [name],\n )\n\n const state = useToastState<TContent>({\n maxVisibleToasts: 1,\n wrapUpdate,\n })\n\n useEffect(() => {\n return () => {\n const active = activeRef.current\n if (active !== undefined && !active.notified) {\n active.notified = true\n active.onClose?.(active.reason)\n }\n activeRef.current = undefined\n queueRef.current = []\n isShowingRef.current = false\n }\n }, [])\n\n function playNext() {\n const next = queueRef.current.shift()\n if (next === undefined) {\n isShowingRef.current = false\n return\n }\n\n const { duration, onClose, content } = next\n isShowingRef.current = true\n const enterMs = window.matchMedia?.('(prefers-reduced-motion: reduce)')\n .matches\n ? 0\n : ANIMATION_DURATION_MS\n const key = state.add(content, {\n // react-stately は 0 を「タイマーなし」と扱うため、最小の正数を渡す\n timeout: Math.max(1, duration + enterMs),\n })\n activeRef.current = { key, onClose, notified: false }\n }\n playNextRef.current = playNext\n\n function enqueue(\n content: TContent,\n onClose?: (reason?: TCloseReason) => void,\n ) {\n const duration =\n typeof durationOption === 'number' && Number.isFinite(durationOption)\n ? Math.max(0, durationOption)\n : DEFAULT_DURATION_MS\n\n queueRef.current.push({\n content,\n onClose,\n duration,\n })\n if (!isShowingRef.current) {\n playNext()\n } else if (order === 'replace') {\n const active = activeRef.current\n if (active === undefined) return\n\n replaceRef.current = !animateReplace\n hoverRef.current.active = false\n const pending = hoverRef.current.pending\n hoverRef.current.pending = undefined\n if (pending !== undefined) {\n pending()\n } else {\n state.close(active.key)\n }\n }\n }\n\n function close(key: string, reason: TCloseReason) {\n const active = activeRef.current\n if (active?.key !== key) return\n active.reason = reason\n hoverRef.current.active = false\n const pending = hoverRef.current.pending\n hoverRef.current.pending = undefined\n if (pending !== undefined) {\n pending()\n } else {\n state.close(key)\n }\n }\n\n function onHoverStart() {\n hoverRef.current.active = true\n }\n\n function onHoverEnd() {\n hoverRef.current.active = false\n const pending = hoverRef.current.pending\n hoverRef.current.pending = undefined\n pending?.()\n }\n\n function clearHover() {\n hoverRef.current.active = false\n hoverRef.current.pending = undefined\n }\n\n return {\n state,\n itemRef,\n enqueue,\n close,\n onHoverStart,\n onHoverEnd,\n clearHover,\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
import type { NotificationName, NotificationOrder } from './types';
|
|
2
|
-
export declare function useNotificationQueue<TContent, TCloseReason extends string = never>(name: NotificationName, { duration: durationOption, order, animateReplace,
|
|
2
|
+
export declare function useNotificationQueue<TContent, TCloseReason extends string = never>(name: NotificationName, { duration: durationOption, order, animateReplace, }?: {
|
|
3
3
|
duration?: number;
|
|
4
4
|
order?: NotificationOrder;
|
|
5
5
|
animateReplace?: boolean;
|
|
6
|
-
timeoutReason?: TCloseReason;
|
|
7
|
-
unmountedReason?: TCloseReason;
|
|
8
6
|
}): {
|
|
9
7
|
state: import("react-stately/useToastState").ToastState<TContent>;
|
|
10
8
|
itemRef: import("react").RefObject<HTMLDivElement>;
|
|
11
|
-
enqueue: (content: TContent, onClose?: (reason
|
|
9
|
+
enqueue: (content: TContent, onClose?: (reason?: TCloseReason) => void) => void;
|
|
12
10
|
close: (key: string, reason: TCloseReason) => void;
|
|
13
11
|
onHoverStart: () => void;
|
|
14
12
|
onHoverEnd: () => void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useNotificationQueue.d.ts","sourceRoot":"","sources":["../../../src/components/Notification/useNotificationQueue.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAA;AAUlE,wBAAgB,oBAAoB,CAClC,QAAQ,EACR,YAAY,SAAS,MAAM,GAAG,KAAK,EAEnC,IAAI,EAAE,gBAAgB,EACtB,EACE,QAAQ,EAAE,cAAc,EACxB,KAAe,EACf,cAAsB,
|
|
1
|
+
{"version":3,"file":"useNotificationQueue.d.ts","sourceRoot":"","sources":["../../../src/components/Notification/useNotificationQueue.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAA;AAUlE,wBAAgB,oBAAoB,CAClC,QAAQ,EACR,YAAY,SAAS,MAAM,GAAG,KAAK,EAEnC,IAAI,EAAE,gBAAgB,EACtB,EACE,QAAQ,EAAE,cAAc,EACxB,KAAe,EACf,cAAsB,GACvB,GAAE;IACD,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,KAAK,CAAC,EAAE,iBAAiB,CAAA;IACzB,cAAc,CAAC,EAAE,OAAO,CAAA;CACpB;;;uBAiIK,QAAQ,YACP,CAAC,MAAM,CAAC,EAAE,YAAY,KAAK,IAAI;iBA8BvB,MAAM,UAAU,YAAY;;;;EAuCjD"}
|
|
@@ -5,7 +5,7 @@ import { useToastState } from "react-stately/useToastState";
|
|
|
5
5
|
//#region src/components/Notification/useNotificationQueue.ts
|
|
6
6
|
const DEFAULT_DURATION_MS = 5e3;
|
|
7
7
|
const ANIMATION_DURATION_MS = 300;
|
|
8
|
-
function useNotificationQueue(name, { duration: durationOption, order = "queue", animateReplace = false
|
|
8
|
+
function useNotificationQueue(name, { duration: durationOption, order = "queue", animateReplace = false } = {}) {
|
|
9
9
|
const itemRef = useRef(null);
|
|
10
10
|
const queueRef = useRef([]);
|
|
11
11
|
const isShowingRef = useRef(false);
|
|
@@ -29,8 +29,7 @@ function useNotificationQueue(name, { duration: durationOption, order = "queue",
|
|
|
29
29
|
update();
|
|
30
30
|
if (active !== void 0 && !active.notified) {
|
|
31
31
|
active.notified = true;
|
|
32
|
-
|
|
33
|
-
if (reason !== void 0) active.onClose?.(reason);
|
|
32
|
+
active.onClose?.(active.reason);
|
|
34
33
|
}
|
|
35
34
|
playNextRef.current?.();
|
|
36
35
|
}
|
|
@@ -64,21 +63,20 @@ function useNotificationQueue(name, { duration: durationOption, order = "queue",
|
|
|
64
63
|
item.addEventListener("animationend", handleAnimationEnd);
|
|
65
64
|
fallbackTimer = window.setTimeout(complete, 400);
|
|
66
65
|
if (window.matchMedia?.("(prefers-reduced-motion: reduce)").matches) complete();
|
|
67
|
-
}, [name
|
|
66
|
+
}, [name])
|
|
68
67
|
});
|
|
69
68
|
useEffect(() => {
|
|
70
69
|
return () => {
|
|
71
70
|
const active = activeRef.current;
|
|
72
71
|
if (active !== void 0 && !active.notified) {
|
|
73
72
|
active.notified = true;
|
|
74
|
-
|
|
75
|
-
if (reason !== void 0) active.onClose?.(reason);
|
|
73
|
+
active.onClose?.(active.reason);
|
|
76
74
|
}
|
|
77
75
|
activeRef.current = void 0;
|
|
78
76
|
queueRef.current = [];
|
|
79
77
|
isShowingRef.current = false;
|
|
80
78
|
};
|
|
81
|
-
}, [
|
|
79
|
+
}, []);
|
|
82
80
|
function playNext() {
|
|
83
81
|
const next = queueRef.current.shift();
|
|
84
82
|
if (next === void 0) {
|
|
@@ -107,7 +105,6 @@ function useNotificationQueue(name, { duration: durationOption, order = "queue",
|
|
|
107
105
|
else if (order === "replace") {
|
|
108
106
|
const active = activeRef.current;
|
|
109
107
|
if (active === void 0) return;
|
|
110
|
-
active.reason = "replaced";
|
|
111
108
|
replaceRef.current = !animateReplace;
|
|
112
109
|
hoverRef.current.active = false;
|
|
113
110
|
const pending = hoverRef.current.pending;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useNotificationQueue.js","names":[],"sources":["../../../src/components/Notification/useNotificationQueue.ts"],"sourcesContent":["import { useCallback, useEffect, useRef } from 'react'\nimport { useToastState } from 'react-stately/useToastState'\nimport type { NotificationName, NotificationOrder } from './types'\n\nconst DEFAULT_DURATION_MS = 5000\nconst ANIMATION_DURATION_MS = 300\n\ntype QueueItem<TContent, TCloseReason> = {\n content: TContent\n onClose?: (reason
|
|
1
|
+
{"version":3,"file":"useNotificationQueue.js","names":[],"sources":["../../../src/components/Notification/useNotificationQueue.ts"],"sourcesContent":["import { useCallback, useEffect, useRef } from 'react'\nimport { useToastState } from 'react-stately/useToastState'\nimport type { NotificationName, NotificationOrder } from './types'\n\nconst DEFAULT_DURATION_MS = 5000\nconst ANIMATION_DURATION_MS = 300\n\ntype QueueItem<TContent, TCloseReason> = {\n content: TContent\n onClose?: (reason?: TCloseReason) => void\n}\n\nexport function useNotificationQueue<\n TContent,\n TCloseReason extends string = never,\n>(\n name: NotificationName,\n {\n duration: durationOption,\n order = 'queue',\n animateReplace = false,\n }: {\n duration?: number\n order?: NotificationOrder\n animateReplace?: boolean\n } = {},\n) {\n const itemRef = useRef<HTMLDivElement>(null)\n const queueRef = useRef<\n Array<QueueItem<TContent, TCloseReason> & { duration: number }>\n >([])\n const isShowingRef = useRef(false)\n const activeRef = useRef<{\n key: string\n onClose?: (reason?: TCloseReason) => void\n reason?: TCloseReason\n notified: boolean\n }>()\n const replaceRef = useRef(false)\n const hoverRef = useRef({\n active: false,\n pending: undefined as (() => void) | undefined,\n })\n // wrapUpdate を固定したまま、後から定義する playNext の最新版を呼ぶ\n const playNextRef = useRef<(() => void) | undefined>(undefined)\n\n // wrapUpdate の参照が変わると useToastState が ToastQueue を作り直すため useCallback で固定する\n const wrapUpdate = useCallback(\n function wrapUpdate(\n update: () => void,\n action: 'add' | 'remove' | 'clear',\n ) {\n if (action !== 'remove') {\n update()\n return\n }\n\n function finish() {\n const active = activeRef.current\n activeRef.current = undefined\n update()\n if (active !== undefined && !active.notified) {\n active.notified = true\n active.onClose?.(active.reason)\n }\n playNextRef.current?.()\n }\n\n if (hoverRef.current.active) {\n hoverRef.current.pending = () => wrapUpdate(update, 'remove')\n return\n }\n\n if (itemRef.current === null) {\n finish()\n return\n }\n\n if (replaceRef.current) {\n replaceRef.current = false\n finish()\n return\n }\n\n const item: HTMLDivElement = itemRef.current\n\n // allow-discreteが Newly Available で使えないので、要素の削除をアニメーション完了まで待つ\n item.dataset.exiting = 'true'\n let completed = false\n let fallbackTimer = 0 // complete 内で clearTimeout(setTimeout(...)) すると新規タイマーを即キャンセルしてしまう\n function handleAnimationEnd(event: AnimationEvent) {\n if (\n event.target === item &&\n event.animationName === `charcoal-${name}-exit`\n ) {\n complete()\n }\n }\n function complete() {\n if (completed) return\n completed = true\n item.removeEventListener('animationend', handleAnimationEnd)\n window.clearTimeout(fallbackTimer)\n finish()\n }\n item.addEventListener('animationend', handleAnimationEnd)\n fallbackTimer = window.setTimeout(complete, ANIMATION_DURATION_MS + 100)\n if (window.matchMedia?.('(prefers-reduced-motion: reduce)').matches) {\n complete()\n }\n },\n [name],\n )\n\n const state = useToastState<TContent>({\n maxVisibleToasts: 1,\n wrapUpdate,\n })\n\n useEffect(() => {\n return () => {\n const active = activeRef.current\n if (active !== undefined && !active.notified) {\n active.notified = true\n active.onClose?.(active.reason)\n }\n activeRef.current = undefined\n queueRef.current = []\n isShowingRef.current = false\n }\n }, [])\n\n function playNext() {\n const next = queueRef.current.shift()\n if (next === undefined) {\n isShowingRef.current = false\n return\n }\n\n const { duration, onClose, content } = next\n isShowingRef.current = true\n const enterMs = window.matchMedia?.('(prefers-reduced-motion: reduce)')\n .matches\n ? 0\n : ANIMATION_DURATION_MS\n const key = state.add(content, {\n // react-stately は 0 を「タイマーなし」と扱うため、最小の正数を渡す\n timeout: Math.max(1, duration + enterMs),\n })\n activeRef.current = { key, onClose, notified: false }\n }\n playNextRef.current = playNext\n\n function enqueue(\n content: TContent,\n onClose?: (reason?: TCloseReason) => void,\n ) {\n const duration =\n typeof durationOption === 'number' && Number.isFinite(durationOption)\n ? Math.max(0, durationOption)\n : DEFAULT_DURATION_MS\n\n queueRef.current.push({\n content,\n onClose,\n duration,\n })\n if (!isShowingRef.current) {\n playNext()\n } else if (order === 'replace') {\n const active = activeRef.current\n if (active === undefined) return\n\n replaceRef.current = !animateReplace\n hoverRef.current.active = false\n const pending = hoverRef.current.pending\n hoverRef.current.pending = undefined\n if (pending !== undefined) {\n pending()\n } else {\n state.close(active.key)\n }\n }\n }\n\n function close(key: string, reason: TCloseReason) {\n const active = activeRef.current\n if (active?.key !== key) return\n active.reason = reason\n hoverRef.current.active = false\n const pending = hoverRef.current.pending\n hoverRef.current.pending = undefined\n if (pending !== undefined) {\n pending()\n } else {\n state.close(key)\n }\n }\n\n function onHoverStart() {\n hoverRef.current.active = true\n }\n\n function onHoverEnd() {\n hoverRef.current.active = false\n const pending = hoverRef.current.pending\n hoverRef.current.pending = undefined\n pending?.()\n }\n\n function clearHover() {\n hoverRef.current.active = false\n hoverRef.current.pending = undefined\n }\n\n return {\n state,\n itemRef,\n enqueue,\n close,\n onHoverStart,\n onHoverEnd,\n clearHover,\n }\n}\n"],"mappings":"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"}
|