@charcoal-ui/react 6.0.0-rc.3 → 6.0.0-rc.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.
Files changed (39) hide show
  1. package/dist/_lib/useIsomorphicLayoutEffect.d.ts +6 -0
  2. package/dist/_lib/useIsomorphicLayoutEffect.d.ts.map +1 -0
  3. package/dist/components/Carousel/index.d.ts +2 -6
  4. package/dist/components/Carousel/index.d.ts.map +1 -1
  5. package/dist/components/Carousel/useCarouselScroller.d.ts.map +1 -1
  6. package/dist/components/Modal/index.d.ts.map +1 -1
  7. package/dist/components/Modal/useTransitionPresence.d.ts +19 -0
  8. package/dist/components/Modal/useTransitionPresence.d.ts.map +1 -0
  9. package/dist/index.cjs +2 -2
  10. package/dist/index.cjs.map +1 -1
  11. package/dist/index.css +100 -47
  12. package/dist/index.d.ts +1 -1
  13. package/dist/index.d.ts.map +1 -1
  14. package/dist/index.js +2 -2
  15. package/dist/index.js.map +1 -1
  16. package/dist/layered.css +100 -47
  17. package/dist/layered.css.map +1 -1
  18. package/package.json +5 -6
  19. package/src/__tests__/css-variables.test.ts +1 -1
  20. package/src/__tests__/token-v1-compat.test.ts +1 -2
  21. package/src/__tests__/token-v1-remap.test.ts +6 -6
  22. package/src/_lib/useIsomorphicLayoutEffect.ts +7 -0
  23. package/src/components/Carousel/MIGRATION.md +39 -39
  24. package/src/components/Carousel/__snapshots__/index.css.snap +39 -37
  25. package/src/components/Carousel/index.css +45 -44
  26. package/src/components/Carousel/index.story.tsx +87 -68
  27. package/src/components/Carousel/index.test.tsx +68 -47
  28. package/src/components/Carousel/index.tsx +23 -14
  29. package/src/components/Carousel/useCarouselScroller.ts +8 -12
  30. package/src/components/FieldLabel/__snapshots__/index.css.snap +1 -1
  31. package/src/components/FieldLabel/index.css +1 -1
  32. package/src/components/IconButton/__snapshots__/index.css.snap +1 -1
  33. package/src/components/IconButton/index.css +1 -1
  34. package/src/components/Modal/__snapshots__/index.css.snap +32 -1
  35. package/src/components/Modal/index.css +34 -0
  36. package/src/components/Modal/index.test.tsx +200 -0
  37. package/src/components/Modal/index.tsx +48 -78
  38. package/src/components/Modal/useTransitionPresence.ts +95 -0
  39. package/src/index.ts +0 -1
@@ -0,0 +1,95 @@
1
+ import {
2
+ useCallback,
3
+ useEffect,
4
+ useState,
5
+ RefObject,
6
+ TransitionEvent,
7
+ } from 'react'
8
+ import { useIsomorphicLayoutEffect } from '../../_lib/useIsomorphicLayoutEffect'
9
+
10
+ // index.css の transition-duration と一致させること
11
+ export const MODAL_TRANSITION_DURATION_MS = 400
12
+
13
+ type AnimationState = 'exited' | 'entering' | 'entered' | 'exiting'
14
+
15
+ /**
16
+ * アニメーション終了時の状態遷移。
17
+ * 途中で open/close が切り替わって state が既に進んでいた場合は何もしない
18
+ */
19
+ function settle(state: AnimationState): AnimationState {
20
+ if (state === 'entering') return 'entered'
21
+ if (state === 'exiting') return 'exited'
22
+ return state
23
+ }
24
+
25
+ /**
26
+ * CSS transition によるモーダルの開閉アニメーションを管理する。
27
+ * exit アニメーションが終わるまで DOM をマウントしたままにする
28
+ *
29
+ * @param isOpen モーダルを開くべきか
30
+ * @param enabled アニメーションを行うか(false なら即座にマウント・アンマウント)
31
+ * @param backgroundRef 背景要素。マウント直後の layout flush に使う
32
+ * @param dialogRef transform をアニメーションさせる要素(ダイアログ)
33
+ */
34
+ export function useTransitionPresence(
35
+ isOpen: boolean,
36
+ enabled: boolean,
37
+ backgroundRef: RefObject<HTMLElement>,
38
+ dialogRef: RefObject<HTMLElement>,
39
+ ) {
40
+ // 開いた状態で初回マウントされた場合もアニメーションさせるため常に 'exited' から始める。
41
+ // enabled でない場合は下の layout effect が描画前に 'entered' へ進める
42
+ const [state, setState] = useState<AnimationState>('exited')
43
+
44
+ useIsomorphicLayoutEffect(() => {
45
+ if (!enabled) {
46
+ setState(isOpen ? 'entered' : 'exited')
47
+ } else if (isOpen) {
48
+ // 閉じた状態のスタイルを確定させ、enter の transition が発火するようにする。
49
+ // dialogRef は子コンポーネントの passive effect で張られるためこの時点では
50
+ // まだ古い/null のことがあり、同じ commit で同期的に張られる背景要素を読む
51
+ if (backgroundRef.current) void backgroundRef.current.offsetHeight
52
+ setState((s) => (s === 'exited' || s === 'exiting' ? 'entering' : s))
53
+ } else {
54
+ setState((s) => (s === 'exited' ? s : 'exiting'))
55
+ }
56
+ }, [isOpen, enabled, backgroundRef])
57
+
58
+ // safety net: transitionend が来なくても(トランジションのキャンセル、
59
+ // reduced-motion、バックグラウンドタブ等)モーダルが永遠に残らないようにする
60
+ const isAnimating = state === 'entering' || state === 'exiting'
61
+ useEffect(() => {
62
+ if (!isAnimating) return
63
+ // transitionend と同時刻に発火して競合しないよう少し遅らせる
64
+ const timer = setTimeout(
65
+ () => setState(settle),
66
+ MODAL_TRANSITION_DURATION_MS + 100,
67
+ )
68
+ return () => clearTimeout(timer)
69
+ }, [isAnimating, state])
70
+
71
+ // 背景 div に付ける。ダイアログの transform の transitionend だけが
72
+ // 開閉アニメーションの終了を意味する(他のトランジションもバブルしてくるため絞り込む)。
73
+ // propertyName は index.css がアニメーションさせるプロパティと一致させること。
74
+ // なお enter 完了直後の close では、完了済み enter の transitionend が
75
+ // 'exiting' へ遷移した後に届いて exit アニメーションが省略される可能性が
76
+ // 理論上あるが、サブフレーム幅のレースで実害は見た目のみのため許容している
77
+ const handleTransitionEnd = useCallback(
78
+ (e: TransitionEvent<HTMLElement>) => {
79
+ const isDialogSlide =
80
+ e.target === dialogRef.current && e.propertyName === 'transform'
81
+ if (isDialogSlide) {
82
+ setState(settle)
83
+ }
84
+ },
85
+ [dialogRef],
86
+ )
87
+
88
+ return {
89
+ // enabled でないときは isOpen だけで即座にマウント・アンマウントする
90
+ // (state 経由にすると close 時に開いたツリーを丸ごと 1 回余計に描画する)
91
+ isPresent: enabled ? isOpen || state !== 'exited' : isOpen,
92
+ animationState: state,
93
+ handleTransitionEnd,
94
+ }
95
+ }
package/src/index.ts CHANGED
@@ -98,7 +98,6 @@ export {
98
98
  export {
99
99
  default as Carousel,
100
100
  type CarouselProps,
101
- type CarouselItem,
102
101
  type CarouselHandlerRef,
103
102
  type ScrollAlign,
104
103
  type ScrollSnap,