@charcoal-ui/react 6.1.0-beta.2 → 6.1.0-beta.4

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.
Files changed (29) hide show
  1. package/dist/_lib/compat.d.ts +4 -3
  2. package/dist/_lib/compat.d.ts.map +1 -1
  3. package/dist/components/Notification/Snackbar/index.d.ts +4 -0
  4. package/dist/components/Notification/Snackbar/index.d.ts.map +1 -1
  5. package/dist/components/Notification/Snackbar/index2.cjs +11 -8
  6. package/dist/components/Notification/Snackbar/index2.cjs.map +1 -1
  7. package/dist/components/Notification/Snackbar/index2.js +12 -9
  8. package/dist/components/Notification/Snackbar/index2.js.map +1 -1
  9. package/dist/components/Notification/useNotificationQueue.cjs +11 -11
  10. package/dist/components/Notification/useNotificationQueue.cjs.map +1 -1
  11. package/dist/components/Notification/useNotificationQueue.d.ts +2 -1
  12. package/dist/components/Notification/useNotificationQueue.d.ts.map +1 -1
  13. package/dist/components/Notification/useNotificationQueue.js +11 -11
  14. package/dist/components/Notification/useNotificationQueue.js.map +1 -1
  15. package/dist/index.css +574 -575
  16. package/dist/index.d.ts +1 -1
  17. package/dist/index.d.ts.map +1 -1
  18. package/dist/layered.css +574 -575
  19. package/dist/layered.css.map +1 -1
  20. package/package.json +5 -5
  21. package/src/_lib/compat.ts +4 -3
  22. package/src/components/Carousel/__snapshots__/index.css.snap +4 -4
  23. package/src/components/Carousel/index.css +4 -4
  24. package/src/components/Notification/Snackbar/index.test.tsx +25 -4
  25. package/src/components/Notification/Snackbar/index.tsx +16 -1
  26. package/src/components/Notification/useNotificationQueue.ts +16 -15
  27. package/src/components/Pagination/__snapshots__/index.css.snap +0 -1
  28. package/src/components/Pagination/index.css +0 -1
  29. package/src/index.ts +1 -0
@@ -1,12 +1,13 @@
1
1
  import * as React from 'react';
2
2
  /**
3
- * react-ariaの`useTextField()`は、<textarea>をサポートするにも関わらず、
3
+ * react-aria@3.48.0の`useTextField()`は、<textarea>をサポートするにも関わらず、
4
4
  * `React.KeyboardEvent<HTMLInputElement>`しか想定していないイベントハンドラがいくつかある
5
- * ↓ が直るまで、以下のイベントハンドラの型は信用しない(本当は`Element`ではなく`HTMLTextAreaElement`とかにしたい)
5
+ * react-aria@3.49.0で修正済みだが、peerDependenciesで3.48.0もサポートしているため、
6
+ * 以下のイベントハンドラの型は信用しない(本当は`Element`ではなく`HTMLTextAreaElement`とかにしたい)
6
7
  *
7
8
  * @see https://github.com/adobe/react-spectrum/issues/4662
8
9
  */
9
- export interface ReactAreaUseTextFieldCompat<E = Element> {
10
+ export interface ReactAriaUseTextFieldCompat<E = Element> {
10
11
  readonly onCopy?: React.ClipboardEventHandler<E>;
11
12
  readonly onPaste?: React.ClipboardEventHandler<E>;
12
13
  readonly onCut?: React.ClipboardEventHandler<E>;
@@ -1 +1 @@
1
- {"version":3,"file":"compat.d.ts","sourceRoot":"","sources":["../../src/_lib/compat.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B;;;;;;GAMG;AACH,MAAM,WAAW,2BAA2B,CAAC,CAAC,GAAG,OAAO;IACtD,QAAQ,CAAC,MAAM,CAAC,EAAE,KAAK,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAA;IAChD,QAAQ,CAAC,OAAO,CAAC,EAAE,KAAK,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAA;IACjD,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAA;IAC/C,QAAQ,CAAC,kBAAkB,CAAC,EAAE,KAAK,CAAC,uBAAuB,CAAC,CAAC,CAAC,CAAA;IAC9D,QAAQ,CAAC,gBAAgB,CAAC,EAAE,KAAK,CAAC,uBAAuB,CAAC,CAAC,CAAC,CAAA;IAC5D,QAAQ,CAAC,mBAAmB,CAAC,EAAE,KAAK,CAAC,uBAAuB,CAAC,CAAC,CAAC,CAAA;IAC/D,QAAQ,CAAC,QAAQ,CAAC,EAAE,KAAK,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAA;IAC9C,QAAQ,CAAC,aAAa,CAAC,EAAE,KAAK,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAA;IAClD,QAAQ,CAAC,OAAO,CAAC,EAAE,KAAK,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAA;IAC5C,QAAQ,CAAC,cAAc,CAAC,EACtB,MAAM,GAAG,IAAI,GAAG,KAAK,GAAG,WAAW,GAAG,OAAO,GAAG,YAAY,GAAG,SAAS,CAAA;CAC3E"}
1
+ {"version":3,"file":"compat.d.ts","sourceRoot":"","sources":["../../src/_lib/compat.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B;;;;;;;GAOG;AACH,MAAM,WAAW,2BAA2B,CAAC,CAAC,GAAG,OAAO;IACtD,QAAQ,CAAC,MAAM,CAAC,EAAE,KAAK,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAA;IAChD,QAAQ,CAAC,OAAO,CAAC,EAAE,KAAK,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAA;IACjD,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAA;IAC/C,QAAQ,CAAC,kBAAkB,CAAC,EAAE,KAAK,CAAC,uBAAuB,CAAC,CAAC,CAAC,CAAA;IAC9D,QAAQ,CAAC,gBAAgB,CAAC,EAAE,KAAK,CAAC,uBAAuB,CAAC,CAAC,CAAC,CAAA;IAC5D,QAAQ,CAAC,mBAAmB,CAAC,EAAE,KAAK,CAAC,uBAAuB,CAAC,CAAC,CAAC,CAAA;IAC/D,QAAQ,CAAC,QAAQ,CAAC,EAAE,KAAK,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAA;IAC9C,QAAQ,CAAC,aAAa,CAAC,EAAE,KAAK,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAA;IAClD,QAAQ,CAAC,OAAO,CAAC,EAAE,KAAK,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAA;IAC5C,QAAQ,CAAC,cAAc,CAAC,EACtB,MAAM,GAAG,IAAI,GAAG,KAAK,GAAG,WAAW,GAAG,OAAO,GAAG,YAAY,GAAG,SAAS,CAAA;CAC3E"}
@@ -3,9 +3,13 @@ import './index.css';
3
3
  import { type HTMLAttributes, type ReactNode } from 'react';
4
4
  import type { NotificationProps, Position } from '../types';
5
5
  export type SnackbarCloseReason = 'timeout' | 'replaced' | 'action' | 'close' | 'unmounted';
6
+ export type SnackbarRootAttributes = {
7
+ [key: `data-${string}`]: string | number | boolean | undefined;
8
+ };
6
9
  export type ShowSnackbarOptions = {
7
10
  action?: ReactNode;
8
11
  onClose?: (reason: SnackbarCloseReason) => void;
12
+ rootAttributes?: SnackbarRootAttributes;
9
13
  };
10
14
  type SnackbarBaseProps = {
11
15
  message: ReactNode;
@@ -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,GAC7B,SAAS,GAAG,UAAU,GAAG,QAAQ,GAAG,OAAO,GAAG,WAAW,CAAA;AAE3D,MAAM,MAAM,mBAAmB,GAAG;IAChC,MAAM,CAAC,EAAE,SAAS,CAAA;IAClB,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,mBAAmB,KAAK,IAAI,CAAA;CAChD,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;AAOD,QAAA,MAAM,QAAQ;IAdZ,6BAA6B;YACrB,WAAW,CAAC,SAAS,CAAC;kDAiB/B,CAAA;eAEc,QAAQ;AAEvB,wBAAgB,WAAW,CAAC,KAAK,GAAE,gBAAqB,gEAkB/B,SAAS,YAAW,mBAAmB,WAsC/D"}
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,GAC7B,SAAS,GAAG,UAAU,GAAG,QAAQ,GAAG,OAAO,GAAG,WAAW,CAAA;AAE3D,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,gEAmB/B,SAAS,YAAW,mBAAmB,WA8C/D"}
@@ -21,13 +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,
24
25
  timeoutReason: "timeout",
25
26
  unmountedReason: "unmounted"
26
27
  });
27
28
  function show(message, options = {}) {
28
29
  enqueue({
29
30
  message,
30
- action: options.action
31
+ action: options.action,
32
+ rootAttributes: options.rootAttributes
31
33
  }, options.onClose);
32
34
  }
33
35
  return [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_NotificationRegion.NotificationRegion, {
@@ -35,7 +37,9 @@ function useSnackbar(props = {}) {
35
37
  state,
36
38
  position: state.visibleToasts.some((toast) => toast.content.action !== void 0) ? "bottom" : position,
37
39
  ...regionProps,
38
- children: state.visibleToasts.map((toast_0) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_NotificationItem.NotificationItem, {
40
+ children: state.visibleToasts.map((toast_0) => /* @__PURE__ */ (0, react.createElement)(require_NotificationItem.NotificationItem, {
41
+ ...toast_0.content.rootAttributes,
42
+ key: toast_0.key,
39
43
  name: "snackbar",
40
44
  toast: toast_0,
41
45
  state,
@@ -43,12 +47,11 @@ function useSnackbar(props = {}) {
43
47
  onHoverStart,
44
48
  onHoverEnd,
45
49
  "data-dim": dim,
46
- "data-with-action": toast_0.content.action !== void 0,
47
- children: toast_0.content.action !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
48
- onClick: () => close(toast_0.key, "action"),
49
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SnackbarAction, { action: toast_0.content.action })
50
- })
51
- }, toast_0.key))
50
+ "data-with-action": toast_0.content.action !== void 0
51
+ }, toast_0.content.action !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
52
+ onClick: () => close(toast_0.key, "action"),
53
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SnackbarAction, { action: toast_0.content.action })
54
+ })))
52
55
  }), show];
53
56
  }
54
57
  const SnackbarBase = (0, react.forwardRef)(function SnackbarBase({ message, action, dim = false, className, ...rootProps }, ref) {
@@ -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 =\n 'timeout' | 'replaced' | 'action' | 'close' | 'unmounted'\n\nexport type ShowSnackbarOptions = {\n action?: ReactNode\n onClose?: (reason: SnackbarCloseReason) => void\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}\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, SnackbarCloseReason>('snackbar', {\n duration,\n order,\n timeoutReason: 'timeout',\n unmountedReason: 'unmounted',\n })\n\n function show(message: ReactNode, options: ShowSnackbarOptions = {}) {\n enqueue({ message, action: options.action }, options.onClose)\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 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":";;;;;;;;;;;AAuCA,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,kDAA2D,YAAY;EACrE;EACA;EACA,eAAe;EACf,iBAAiB;CACnB,CAAC;CAEH,SAAS,KAAK,SAAoB,UAA+B,CAAC,GAAG;EACnE,QAAQ;GAAE;GAAS,QAAQ,QAAQ;EAAO,GAAG,QAAQ,OAAO;CAC9D;CAmCA,OAAO,CAAC,2CA5BL,+CAAD;EACE,MAAK;EACE;EACP,UARc,MAAM,cAAc,MACnC,UAAU,MAAM,QAAQ,WAAW,MAEZ,IAAY,WAAW;EAM7C,GAAI;YAEH,MAAM,cAAc,KAAKA,YACxB,2CAAC,2CAAD;GAEE,MAAK;GACL,OAAOA;GACA;GACE;GACK;GACF;GACZ,YAAU;GACV,oBAAkBA,QAAM,QAAQ,WAAW;aAE1CA,QAAM,QAAQ,WAAW,UACxB,2CAAC,OAAD;IAAK,eAAe,MAAMA,QAAM,KAAK,QAAQ;cAC3C,2CAAC,gBAAD,EAAgB,QAAQA,QAAM,QAAQ,OAAO;GAC1C;EAES,GAfXA,QAAM,GAeK,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"}
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 =\n 'timeout' | 'replaced' | 'action' | 'close' | '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, SnackbarCloseReason>('snackbar', {\n duration,\n order,\n animateReplace: true,\n timeoutReason: 'timeout',\n unmountedReason: 'unmounted',\n })\n\n function show(message: ReactNode, options: ShowSnackbarOptions = {}) {\n enqueue(\n {\n message,\n action: options.action,\n rootAttributes: options.rootAttributes,\n },\n options.onClose,\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":";;;;;;;;;;;AA6CA,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,kDAA2D,YAAY;EACrE;EACA;EACA,gBAAgB;EAChB,eAAe;EACf,iBAAiB;CACnB,CAAC;CAEH,SAAS,KAAK,SAAoB,UAA+B,CAAC,GAAG;EACnE,QACE;GACE;GACA,QAAQ,QAAQ;GAChB,gBAAgB,QAAQ;EAC1B,GACA,QAAQ,OACV;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"}
@@ -5,7 +5,7 @@ import { useClassNames } from "../../../_lib/useClassNames.js";
5
5
  import { NotificationItem } from "../NotificationItem.js";
6
6
  import { NotificationRegion } from "../NotificationRegion.js";
7
7
  import { useNotificationQueue } from "../useNotificationQueue.js";
8
- import { forwardRef } from "react";
8
+ import { createElement, forwardRef } from "react";
9
9
  import { jsx, jsxs } from "react/jsx-runtime";
10
10
 
11
11
  //#region src/components/Notification/Snackbar/index.tsx
@@ -21,13 +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,
24
25
  timeoutReason: "timeout",
25
26
  unmountedReason: "unmounted"
26
27
  });
27
28
  function show(message, options = {}) {
28
29
  enqueue({
29
30
  message,
30
- action: options.action
31
+ action: options.action,
32
+ rootAttributes: options.rootAttributes
31
33
  }, options.onClose);
32
34
  }
33
35
  return [/* @__PURE__ */ jsx(NotificationRegion, {
@@ -35,7 +37,9 @@ function useSnackbar(props = {}) {
35
37
  state,
36
38
  position: state.visibleToasts.some((toast) => toast.content.action !== void 0) ? "bottom" : position,
37
39
  ...regionProps,
38
- children: state.visibleToasts.map((toast_0) => /* @__PURE__ */ jsx(NotificationItem, {
40
+ children: state.visibleToasts.map((toast_0) => /* @__PURE__ */ createElement(NotificationItem, {
41
+ ...toast_0.content.rootAttributes,
42
+ key: toast_0.key,
39
43
  name: "snackbar",
40
44
  toast: toast_0,
41
45
  state,
@@ -43,12 +47,11 @@ function useSnackbar(props = {}) {
43
47
  onHoverStart,
44
48
  onHoverEnd,
45
49
  "data-dim": dim,
46
- "data-with-action": toast_0.content.action !== void 0,
47
- children: toast_0.content.action !== void 0 && /* @__PURE__ */ jsx("div", {
48
- onClick: () => close(toast_0.key, "action"),
49
- children: /* @__PURE__ */ jsx(SnackbarAction, { action: toast_0.content.action })
50
- })
51
- }, toast_0.key))
50
+ "data-with-action": toast_0.content.action !== void 0
51
+ }, toast_0.content.action !== void 0 && /* @__PURE__ */ jsx("div", {
52
+ onClick: () => close(toast_0.key, "action"),
53
+ children: /* @__PURE__ */ jsx(SnackbarAction, { action: toast_0.content.action })
54
+ })))
52
55
  }), show];
53
56
  }
54
57
  const SnackbarBase = forwardRef(function SnackbarBase({ message, action, dim = false, className, ...rootProps }, ref) {
@@ -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 =\n 'timeout' | 'replaced' | 'action' | 'close' | 'unmounted'\n\nexport type ShowSnackbarOptions = {\n action?: ReactNode\n onClose?: (reason: SnackbarCloseReason) => void\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}\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, SnackbarCloseReason>('snackbar', {\n duration,\n order,\n timeoutReason: 'timeout',\n unmountedReason: 'unmounted',\n })\n\n function show(message: ReactNode, options: ShowSnackbarOptions = {}) {\n enqueue({ message, action: options.action }, options.onClose)\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 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":";;;;;;;;;;;AAuCA,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,qBAA2D,YAAY;EACrE;EACA;EACA,eAAe;EACf,iBAAiB;CACnB,CAAC;CAEH,SAAS,KAAK,SAAoB,UAA+B,CAAC,GAAG;EACnE,QAAQ;GAAE;GAAS,QAAQ,QAAQ;EAAO,GAAG,QAAQ,OAAO;CAC9D;CAmCA,OAAO,CAAC,oBA5BL,oBAAD;EACE,MAAK;EACE;EACP,UARc,MAAM,cAAc,MACnC,UAAU,MAAM,QAAQ,WAAW,MAEZ,IAAY,WAAW;EAM7C,GAAI;YAEH,MAAM,cAAc,KAAKA,YACxB,oBAAC,kBAAD;GAEE,MAAK;GACL,OAAOA;GACA;GACE;GACK;GACF;GACZ,YAAU;GACV,oBAAkBA,QAAM,QAAQ,WAAW;aAE1CA,QAAM,QAAQ,WAAW,UACxB,oBAAC,OAAD;IAAK,eAAe,MAAMA,QAAM,KAAK,QAAQ;cAC3C,oBAAC,gBAAD,EAAgB,QAAQA,QAAM,QAAQ,OAAO;GAC1C;EAES,GAfXA,QAAM,GAeK,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"}
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 =\n 'timeout' | 'replaced' | 'action' | 'close' | '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, SnackbarCloseReason>('snackbar', {\n duration,\n order,\n animateReplace: true,\n timeoutReason: 'timeout',\n unmountedReason: 'unmounted',\n })\n\n function show(message: ReactNode, options: ShowSnackbarOptions = {}) {\n enqueue(\n {\n message,\n action: options.action,\n rootAttributes: options.rootAttributes,\n },\n options.onClose,\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":";;;;;;;;;;;AA6CA,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,qBAA2D,YAAY;EACrE;EACA;EACA,gBAAgB;EAChB,eAAe;EACf,iBAAiB;CACnB,CAAC;CAEH,SAAS,KAAK,SAAoB,UAA+B,CAAC,GAAG;EACnE,QACE;GACE;GACA,QAAQ,QAAQ;GAChB,gBAAgB,QAAQ;EAC1B,GACA,QAAQ,OACV;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", timeoutReason, unmountedReason } = {}) {
8
+ function useNotificationQueue(name, { duration: durationOption, order = "queue", animateReplace = false, timeoutReason, unmountedReason } = {}) {
9
9
  const itemRef = (0, react.useRef)(null);
10
10
  const queueRef = (0, react.useRef)([]);
11
11
  const isShowingRef = (0, react.useRef)(false);
@@ -23,19 +23,17 @@ function useNotificationQueue(name, { duration: durationOption, order = "queue",
23
23
  update();
24
24
  return;
25
25
  }
26
- function notifyActive() {
27
- const active = activeRef.current;
28
- if (active === void 0 || active.notified) return;
29
- active.notified = true;
30
- const reason = active.reason ?? timeoutReason;
31
- if (reason !== void 0) active.onClose?.(reason);
32
- }
33
26
  function finish() {
27
+ const active = activeRef.current;
34
28
  activeRef.current = void 0;
35
29
  update();
30
+ if (active !== void 0 && !active.notified) {
31
+ active.notified = true;
32
+ const reason = active.reason ?? timeoutReason;
33
+ if (reason !== void 0) active.onClose?.(reason);
34
+ }
36
35
  playNextRef.current?.();
37
36
  }
38
- notifyActive();
39
37
  if (hoverRef.current.active) {
40
38
  hoverRef.current.pending = () => wrapUpdate(update, "remove");
41
39
  return;
@@ -72,7 +70,9 @@ function useNotificationQueue(name, { duration: durationOption, order = "queue",
72
70
  return () => {
73
71
  const active = activeRef.current;
74
72
  if (active !== void 0 && !active.notified) {
75
- if (unmountedReason !== void 0) active.onClose?.(unmountedReason);
73
+ active.notified = true;
74
+ const reason = active.reason ?? unmountedReason;
75
+ if (reason !== void 0) active.onClose?.(reason);
76
76
  }
77
77
  activeRef.current = void 0;
78
78
  queueRef.current = [];
@@ -108,7 +108,7 @@ function useNotificationQueue(name, { duration: durationOption, order = "queue",
108
108
  const active = activeRef.current;
109
109
  if (active === void 0) return;
110
110
  active.reason = "replaced";
111
- replaceRef.current = true;
111
+ replaceRef.current = !animateReplace;
112
112
  hoverRef.current.active = false;
113
113
  const pending = hoverRef.current.pending;
114
114
  hoverRef.current.pending = void 0;
@@ -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: 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 timeoutReason,\n unmountedReason,\n }: {\n duration?: number\n order?: NotificationOrder\n timeoutReason?: TCloseReason\n unmountedReason?: TCloseReason\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 notifyActive() {\n const active = activeRef.current\n if (active === undefined || active.notified) return\n active.notified = true\n const reason = active.reason ?? timeoutReason\n if (reason !== undefined) {\n active.onClose?.(reason)\n }\n }\n\n function finish() {\n activeRef.current = undefined\n update()\n playNextRef.current?.()\n }\n\n notifyActive()\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 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, timeoutReason],\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 if (unmountedReason !== undefined) {\n active.onClose?.(unmountedReason)\n }\n }\n activeRef.current = undefined\n queueRef.current = []\n isShowingRef.current = false\n }\n }, [unmountedReason])\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 active.reason = 'replaced' as TCloseReason\n replaceRef.current = true\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
+ {"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 timeoutReason,\n unmountedReason,\n }: {\n duration?: number\n order?: NotificationOrder\n animateReplace?: boolean\n timeoutReason?: TCloseReason\n unmountedReason?: TCloseReason\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 const reason = active.reason ?? timeoutReason\n if (reason !== undefined) {\n active.onClose?.(reason)\n }\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, timeoutReason],\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 const reason = active.reason ?? unmountedReason\n if (reason !== undefined) {\n active.onClose?.(reason)\n }\n }\n activeRef.current = undefined\n queueRef.current = []\n isShowingRef.current = false\n }\n }, [unmountedReason])\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 active.reason = 'replaced' as TCloseReason\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,7 +1,8 @@
1
1
  import type { NotificationName, NotificationOrder } from './types';
2
- export declare function useNotificationQueue<TContent, TCloseReason extends string = never>(name: NotificationName, { duration: durationOption, order, timeoutReason, unmountedReason, }?: {
2
+ export declare function useNotificationQueue<TContent, TCloseReason extends string = never>(name: NotificationName, { duration: durationOption, order, animateReplace, timeoutReason, unmountedReason, }?: {
3
3
  duration?: number;
4
4
  order?: NotificationOrder;
5
+ animateReplace?: boolean;
5
6
  timeoutReason?: TCloseReason;
6
7
  unmountedReason?: TCloseReason;
7
8
  }): {
@@ -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,aAAa,EACb,eAAe,GAChB,GAAE;IACD,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,KAAK,CAAC,EAAE,iBAAiB,CAAA;IACzB,aAAa,CAAC,EAAE,YAAY,CAAA;IAC5B,eAAe,CAAC,EAAE,YAAY,CAAA;CAC1B;;;uBAwIK,QAAQ,YACP,CAAC,MAAM,EAAE,YAAY,KAAK,IAAI;iBA+BtB,MAAM,UAAU,YAAY;;;;EAuCjD"}
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,EACtB,aAAa,EACb,eAAe,GAChB,GAAE;IACD,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,KAAK,CAAC,EAAE,iBAAiB,CAAA;IACzB,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,aAAa,CAAC,EAAE,YAAY,CAAA;IAC5B,eAAe,CAAC,EAAE,YAAY,CAAA;CAC1B;;;uBAuIK,QAAQ,YACP,CAAC,MAAM,EAAE,YAAY,KAAK,IAAI;iBA+BtB,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", timeoutReason, unmountedReason } = {}) {
8
+ function useNotificationQueue(name, { duration: durationOption, order = "queue", animateReplace = false, timeoutReason, unmountedReason } = {}) {
9
9
  const itemRef = useRef(null);
10
10
  const queueRef = useRef([]);
11
11
  const isShowingRef = useRef(false);
@@ -23,19 +23,17 @@ function useNotificationQueue(name, { duration: durationOption, order = "queue",
23
23
  update();
24
24
  return;
25
25
  }
26
- function notifyActive() {
27
- const active = activeRef.current;
28
- if (active === void 0 || active.notified) return;
29
- active.notified = true;
30
- const reason = active.reason ?? timeoutReason;
31
- if (reason !== void 0) active.onClose?.(reason);
32
- }
33
26
  function finish() {
27
+ const active = activeRef.current;
34
28
  activeRef.current = void 0;
35
29
  update();
30
+ if (active !== void 0 && !active.notified) {
31
+ active.notified = true;
32
+ const reason = active.reason ?? timeoutReason;
33
+ if (reason !== void 0) active.onClose?.(reason);
34
+ }
36
35
  playNextRef.current?.();
37
36
  }
38
- notifyActive();
39
37
  if (hoverRef.current.active) {
40
38
  hoverRef.current.pending = () => wrapUpdate(update, "remove");
41
39
  return;
@@ -72,7 +70,9 @@ function useNotificationQueue(name, { duration: durationOption, order = "queue",
72
70
  return () => {
73
71
  const active = activeRef.current;
74
72
  if (active !== void 0 && !active.notified) {
75
- if (unmountedReason !== void 0) active.onClose?.(unmountedReason);
73
+ active.notified = true;
74
+ const reason = active.reason ?? unmountedReason;
75
+ if (reason !== void 0) active.onClose?.(reason);
76
76
  }
77
77
  activeRef.current = void 0;
78
78
  queueRef.current = [];
@@ -108,7 +108,7 @@ function useNotificationQueue(name, { duration: durationOption, order = "queue",
108
108
  const active = activeRef.current;
109
109
  if (active === void 0) return;
110
110
  active.reason = "replaced";
111
- replaceRef.current = true;
111
+ replaceRef.current = !animateReplace;
112
112
  hoverRef.current.active = false;
113
113
  const pending = hoverRef.current.pending;
114
114
  hoverRef.current.pending = void 0;
@@ -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: 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 timeoutReason,\n unmountedReason,\n }: {\n duration?: number\n order?: NotificationOrder\n timeoutReason?: TCloseReason\n unmountedReason?: TCloseReason\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 notifyActive() {\n const active = activeRef.current\n if (active === undefined || active.notified) return\n active.notified = true\n const reason = active.reason ?? timeoutReason\n if (reason !== undefined) {\n active.onClose?.(reason)\n }\n }\n\n function finish() {\n activeRef.current = undefined\n update()\n playNextRef.current?.()\n }\n\n notifyActive()\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 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, timeoutReason],\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 if (unmountedReason !== undefined) {\n active.onClose?.(unmountedReason)\n }\n }\n activeRef.current = undefined\n queueRef.current = []\n isShowingRef.current = false\n }\n }, [unmountedReason])\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 active.reason = 'replaced' as TCloseReason\n replaceRef.current = true\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
+ {"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 timeoutReason,\n unmountedReason,\n }: {\n duration?: number\n order?: NotificationOrder\n animateReplace?: boolean\n timeoutReason?: TCloseReason\n unmountedReason?: TCloseReason\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 const reason = active.reason ?? timeoutReason\n if (reason !== undefined) {\n active.onClose?.(reason)\n }\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, timeoutReason],\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 const reason = active.reason ?? unmountedReason\n if (reason !== undefined) {\n active.onClose?.(reason)\n }\n }\n activeRef.current = undefined\n queueRef.current = []\n isShowingRef.current = false\n }\n }, [unmountedReason])\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 active.reason = 'replaced' as TCloseReason\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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"}