react-panel-layout 0.6.0 → 0.6.1

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 (216) hide show
  1. package/dist/{FloatingPanelFrame-SgYLc6Ud.js → FloatingPanelFrame-3eU9AwPo.js} +2 -2
  2. package/dist/{FloatingPanelFrame-SgYLc6Ud.js.map → FloatingPanelFrame-3eU9AwPo.js.map} +1 -1
  3. package/dist/FloatingWindow-CUXnEtrb.js +827 -0
  4. package/dist/FloatingWindow-CUXnEtrb.js.map +1 -0
  5. package/dist/FloatingWindow-DMwyK0eK.cjs +2 -0
  6. package/dist/FloatingWindow-DMwyK0eK.cjs.map +1 -0
  7. package/dist/GridLayout-DKTg_N61.cjs +2 -0
  8. package/dist/{GridLayout-B4VRsC0r.cjs.map → GridLayout-DKTg_N61.cjs.map} +1 -1
  9. package/dist/{GridLayout-BltqeCPK.js → GridLayout-UWNxXw77.js} +34 -35
  10. package/dist/{GridLayout-BltqeCPK.js.map → GridLayout-UWNxXw77.js.map} +1 -1
  11. package/dist/{HorizontalDivider-WF1k_qND.js → HorizontalDivider-DdxzfV0l.js} +3 -3
  12. package/dist/{HorizontalDivider-WF1k_qND.js.map → HorizontalDivider-DdxzfV0l.js.map} +1 -1
  13. package/dist/{HorizontalDivider-B5Z-KZLk.cjs → HorizontalDivider-_pgV4Mcv.cjs} +2 -2
  14. package/dist/{HorizontalDivider-B5Z-KZLk.cjs.map → HorizontalDivider-_pgV4Mcv.cjs.map} +1 -1
  15. package/dist/{PanelSystem-Dr1TBhxM.js → PanelSystem-BqUzNtf2.js} +5 -5
  16. package/dist/{PanelSystem-Dr1TBhxM.js.map → PanelSystem-BqUzNtf2.js.map} +1 -1
  17. package/dist/{PanelSystem-Bs8bQwQF.cjs → PanelSystem-D603LKKv.cjs} +2 -2
  18. package/dist/{PanelSystem-Bs8bQwQF.cjs.map → PanelSystem-D603LKKv.cjs.map} +1 -1
  19. package/dist/ResizeHandle-CBcAS918.cjs +2 -0
  20. package/dist/{ResizeHandle-CScipO5l.cjs.map → ResizeHandle-CBcAS918.cjs.map} +1 -1
  21. package/dist/{ResizeHandle-CdA_JYfN.js → ResizeHandle-CXjc1meV.js} +28 -29
  22. package/dist/{ResizeHandle-CdA_JYfN.js.map → ResizeHandle-CXjc1meV.js.map} +1 -1
  23. package/dist/SwipePivotTabBar-DWrCuwEI.js +411 -0
  24. package/dist/SwipePivotTabBar-DWrCuwEI.js.map +1 -0
  25. package/dist/SwipePivotTabBar-fjjXkpj7.cjs +2 -0
  26. package/dist/SwipePivotTabBar-fjjXkpj7.cjs.map +1 -0
  27. package/dist/components/gesture/SwipeSafeZone.d.ts +40 -0
  28. package/dist/components/window/Drawer.d.ts +3 -1
  29. package/dist/components/window/DrawerLayers.d.ts +1 -1
  30. package/dist/components/window/drawerStyles.d.ts +69 -0
  31. package/dist/components/window/drawerSwipeConfig.d.ts +29 -0
  32. package/dist/components/window/useDrawerSwipeTransform.d.ts +23 -0
  33. package/dist/config.cjs +1 -1
  34. package/dist/config.js +3 -3
  35. package/dist/constants/styles.d.ts +17 -0
  36. package/dist/dialog/index.d.ts +69 -0
  37. package/dist/floating.js +1 -1
  38. package/dist/grid.cjs +1 -1
  39. package/dist/grid.js +2 -2
  40. package/dist/hooks/gesture/testing/createGestureSimulator.d.ts +7 -0
  41. package/dist/hooks/gesture/types.d.ts +48 -5
  42. package/dist/hooks/gesture/utils.d.ts +19 -0
  43. package/dist/hooks/useAnimationFrame.d.ts +2 -0
  44. package/dist/hooks/useOperationContinuity.d.ts +64 -0
  45. package/dist/hooks/useResizeObserver.d.ts +33 -1
  46. package/dist/hooks/useSharedElementTransition.d.ts +112 -0
  47. package/dist/hooks/useSwipeContentTransform.d.ts +9 -2
  48. package/dist/index.cjs +1 -1
  49. package/dist/index.js +7 -7
  50. package/dist/modules/dialog/AlertDialog.d.ts +9 -0
  51. package/dist/modules/dialog/DialogContainer.d.ts +37 -0
  52. package/dist/modules/dialog/Modal.d.ts +26 -0
  53. package/dist/modules/dialog/SwipeDialogContainer.d.ts +16 -0
  54. package/dist/modules/dialog/dialogAnimationUtils.d.ts +113 -0
  55. package/dist/modules/dialog/types.d.ts +183 -0
  56. package/dist/modules/dialog/useDialog.d.ts +39 -0
  57. package/dist/modules/dialog/useDialogContainer.d.ts +47 -0
  58. package/dist/modules/dialog/useDialogSwipeInput.d.ts +70 -0
  59. package/dist/modules/dialog/useDialogTransform.d.ts +82 -0
  60. package/dist/modules/drawer/types.d.ts +74 -0
  61. package/dist/modules/drawer/useDrawerSwipeInput.d.ts +24 -0
  62. package/dist/modules/pivot/SwipePivotTabBar.d.ts +3 -0
  63. package/dist/modules/stack/SwipeStackContent.d.ts +6 -3
  64. package/dist/modules/stack/SwipeStackOutlet.d.ts +4 -4
  65. package/dist/modules/stack/computeSwipeStackTransform.d.ts +1 -1
  66. package/dist/panels.cjs +1 -1
  67. package/dist/panels.js +1 -1
  68. package/dist/pivot.cjs +1 -1
  69. package/dist/pivot.js +1 -1
  70. package/dist/resizer.cjs +1 -1
  71. package/dist/resizer.js +2 -2
  72. package/dist/stack.cjs +1 -1
  73. package/dist/stack.cjs.map +1 -1
  74. package/dist/stack.js +503 -762
  75. package/dist/stack.js.map +1 -1
  76. package/dist/sticky-header/calculateStickyMetrics.d.ts +28 -0
  77. package/dist/sticky-header.cjs +1 -1
  78. package/dist/sticky-header.cjs.map +1 -1
  79. package/dist/sticky-header.js +59 -51
  80. package/dist/sticky-header.js.map +1 -1
  81. package/dist/{styles-DPPuJ0sf.js → styles-NkjuMOVS.js} +13 -13
  82. package/dist/{styles-DPPuJ0sf.js.map → styles-NkjuMOVS.js.map} +1 -1
  83. package/dist/styles-qf6ptVLD.cjs.map +1 -1
  84. package/dist/types.d.ts +16 -0
  85. package/dist/useDocumentPointerEvents-DXxw3qWj.js +54 -0
  86. package/dist/useDocumentPointerEvents-DXxw3qWj.js.map +1 -0
  87. package/dist/useDocumentPointerEvents-DxDSOtip.cjs +2 -0
  88. package/dist/useDocumentPointerEvents-DxDSOtip.cjs.map +1 -0
  89. package/dist/useNativeGestureGuard-C7TSqEkr.cjs +2 -0
  90. package/dist/useNativeGestureGuard-C7TSqEkr.cjs.map +1 -0
  91. package/dist/useNativeGestureGuard-CGYo6O0r.js +347 -0
  92. package/dist/useNativeGestureGuard-CGYo6O0r.js.map +1 -0
  93. package/dist/window/index.d.ts +2 -0
  94. package/dist/window.cjs +1 -1
  95. package/dist/window.cjs.map +1 -1
  96. package/dist/window.js +114 -103
  97. package/dist/window.js.map +1 -1
  98. package/package.json +6 -1
  99. package/src/components/gesture/SwipeSafeZone.tsx +69 -0
  100. package/src/components/window/Drawer.tsx +249 -162
  101. package/src/components/window/DrawerLayers.tsx +13 -3
  102. package/src/components/window/drawerStyles.spec.ts +263 -0
  103. package/src/components/window/drawerStyles.ts +228 -0
  104. package/src/components/window/drawerSwipeConfig.spec.ts +131 -0
  105. package/src/components/window/drawerSwipeConfig.ts +112 -0
  106. package/src/components/window/useDrawerSwipeTransform.spec.ts +234 -0
  107. package/src/components/window/useDrawerSwipeTransform.ts +129 -0
  108. package/src/constants/styles.ts +19 -0
  109. package/src/demo/pages/Dialog/alerts/index.tsx +22 -0
  110. package/src/demo/pages/Dialog/card/index.tsx +22 -0
  111. package/src/demo/pages/Dialog/components/AlertDialogDemo.tsx +124 -0
  112. package/src/demo/pages/Dialog/components/CardExpandDemo.module.css +243 -0
  113. package/src/demo/pages/Dialog/components/CardExpandDemo.tsx +204 -0
  114. package/src/demo/pages/Dialog/components/CustomAlertDialogDemo.tsx +219 -0
  115. package/src/demo/pages/Dialog/components/DialogDemos.module.css +77 -0
  116. package/src/demo/pages/Dialog/components/ModalBasics.tsx +45 -0
  117. package/src/demo/pages/Dialog/components/SwipeDialogDemo.module.css +77 -0
  118. package/src/demo/pages/Dialog/components/SwipeDialogDemo.tsx +181 -0
  119. package/src/demo/pages/Dialog/custom-alert/index.tsx +22 -0
  120. package/src/demo/pages/Dialog/modal/index.tsx +17 -0
  121. package/src/demo/pages/Dialog/swipe/index.tsx +22 -0
  122. package/src/demo/pages/Drawer/components/DrawerSwipe.module.css +316 -0
  123. package/src/demo/pages/Drawer/components/DrawerSwipe.tsx +178 -0
  124. package/src/demo/pages/Drawer/swipe/index.tsx +17 -0
  125. package/src/demo/pages/Pivot/components/SwipeTabsPivot.tsx +54 -23
  126. package/src/demo/pages/Pivot/swipe-debug/index.tsx +1 -1
  127. package/src/demo/pages/Stack/components/StackBasics.spec.tsx +152 -0
  128. package/src/demo/pages/Stack/components/StackBasics.tsx +179 -95
  129. package/src/demo/pages/Stack/components/StackTablet.spec.tsx +120 -0
  130. package/src/demo/pages/Stack/components/StackTablet.tsx +42 -21
  131. package/src/demo/routes.tsx +22 -1
  132. package/src/dialog/index.ts +85 -0
  133. package/src/hooks/gesture/testing/createGestureSimulator.spec.ts +68 -64
  134. package/src/hooks/gesture/testing/createGestureSimulator.ts +112 -37
  135. package/src/hooks/gesture/types.ts +83 -6
  136. package/src/hooks/gesture/useEdgeSwipeInput.spec.ts +22 -14
  137. package/src/hooks/gesture/useNativeGestureGuard.spec.ts +91 -31
  138. package/src/hooks/gesture/useNativeGestureGuard.ts +3 -1
  139. package/src/hooks/gesture/utils.ts +91 -0
  140. package/src/hooks/useAnimatedVisibility.spec.ts +44 -24
  141. package/src/hooks/useAnimatedVisibility.ts +28 -2
  142. package/src/hooks/useAnimationFrame.ts +8 -0
  143. package/src/hooks/useOperationContinuity.spec.ts +387 -0
  144. package/src/hooks/useOperationContinuity.ts +135 -0
  145. package/src/hooks/useResizeObserver.spec.tsx +277 -0
  146. package/src/hooks/useResizeObserver.tsx +108 -39
  147. package/src/hooks/useScrollContainer.ts +4 -10
  148. package/src/hooks/useSharedElementTransition.ts +333 -0
  149. package/src/hooks/useSwipeContentTransform.spec.ts +18 -18
  150. package/src/hooks/useSwipeContentTransform.ts +166 -28
  151. package/src/modules/dialog/AlertDialog.spec.tsx +387 -0
  152. package/src/modules/dialog/AlertDialog.tsx +221 -0
  153. package/src/modules/dialog/DialogContainer.spec.tsx +228 -0
  154. package/src/modules/dialog/DialogContainer.tsx +188 -0
  155. package/src/modules/dialog/Modal.spec.tsx +220 -0
  156. package/src/modules/dialog/Modal.tsx +182 -0
  157. package/src/modules/dialog/SwipeDialogContainer.tsx +208 -0
  158. package/src/modules/dialog/dialogAnimationUtils.spec.ts +253 -0
  159. package/src/modules/dialog/dialogAnimationUtils.ts +297 -0
  160. package/src/modules/dialog/types.ts +186 -0
  161. package/src/modules/dialog/useDialog.spec.tsx +447 -0
  162. package/src/modules/dialog/useDialog.ts +214 -0
  163. package/src/modules/dialog/useDialogContainer.spec.ts +331 -0
  164. package/src/modules/dialog/useDialogContainer.ts +150 -0
  165. package/src/modules/dialog/useDialogSwipeInput.spec.ts +157 -0
  166. package/src/modules/dialog/useDialogSwipeInput.ts +319 -0
  167. package/src/modules/dialog/useDialogTransform.spec.ts +370 -0
  168. package/src/modules/dialog/useDialogTransform.ts +407 -0
  169. package/src/modules/drawer/types.ts +102 -0
  170. package/src/modules/drawer/useDrawerSwipeInput.spec.ts +566 -0
  171. package/src/modules/drawer/useDrawerSwipeInput.ts +399 -0
  172. package/src/modules/panels/rendering/ContentRegistry.spec.tsx +21 -14
  173. package/src/modules/pivot/SwipePivotContent.position.spec.tsx +12 -8
  174. package/src/modules/pivot/SwipePivotContent.spec.tsx +55 -25
  175. package/src/modules/pivot/SwipePivotContent.tsx +2 -2
  176. package/src/modules/pivot/SwipePivotTabBar.spec.tsx +85 -68
  177. package/src/modules/pivot/SwipePivotTabBar.tsx +75 -15
  178. package/src/modules/pivot/scaleInputState.spec.ts +11 -2
  179. package/src/modules/pivot/usePivot.spec.ts +17 -3
  180. package/src/modules/pivot/usePivotSwipeInput.spec.ts +182 -123
  181. package/src/modules/stack/SwipeStackContent.spec.tsx +387 -100
  182. package/src/modules/stack/SwipeStackContent.tsx +43 -33
  183. package/src/modules/stack/SwipeStackOutlet.spec.tsx +14 -16
  184. package/src/modules/stack/SwipeStackOutlet.tsx +6 -6
  185. package/src/modules/stack/computeSwipeStackTransform.spec.ts +5 -5
  186. package/src/modules/stack/computeSwipeStackTransform.ts +3 -3
  187. package/src/modules/stack/swipeTransitionContinuity.spec.tsx +1133 -0
  188. package/src/modules/stack/useStackAnimationState.spec.ts +3 -1
  189. package/src/modules/stack/useStackAnimationState.ts +18 -13
  190. package/src/modules/stack/useStackNavigation.spec.ts +198 -3
  191. package/src/modules/stack/useStackNavigation.tsx +113 -56
  192. package/src/modules/stack/useStackSwipeInput.spec.ts +65 -32
  193. package/src/modules/stack/useStackSwipeInput.ts +1 -1
  194. package/src/sticky-header/StickyArea.tsx +29 -57
  195. package/src/sticky-header/calculateStickyMetrics.spec.ts +105 -0
  196. package/src/sticky-header/calculateStickyMetrics.ts +50 -0
  197. package/src/types.ts +18 -0
  198. package/src/window/index.ts +2 -0
  199. package/dist/FloatingWindow-BpdOpg_L.js +0 -400
  200. package/dist/FloatingWindow-BpdOpg_L.js.map +0 -1
  201. package/dist/FloatingWindow-TCDNY5gE.cjs +0 -2
  202. package/dist/FloatingWindow-TCDNY5gE.cjs.map +0 -1
  203. package/dist/GridLayout-B4VRsC0r.cjs +0 -2
  204. package/dist/ResizeHandle-CScipO5l.cjs +0 -2
  205. package/dist/SwipePivotTabBar-BGO9X94m.js +0 -407
  206. package/dist/SwipePivotTabBar-BGO9X94m.js.map +0 -1
  207. package/dist/SwipePivotTabBar-BrQismcZ.cjs +0 -2
  208. package/dist/SwipePivotTabBar-BrQismcZ.cjs.map +0 -1
  209. package/dist/useDocumentPointerEvents-CKdhGXd0.js +0 -46
  210. package/dist/useDocumentPointerEvents-CKdhGXd0.js.map +0 -1
  211. package/dist/useDocumentPointerEvents-ChqrKXDk.cjs +0 -2
  212. package/dist/useDocumentPointerEvents-ChqrKXDk.cjs.map +0 -1
  213. package/dist/useEffectEvent-Dp7HLCf0.js +0 -13
  214. package/dist/useEffectEvent-Dp7HLCf0.js.map +0 -1
  215. package/dist/useEffectEvent-huSsGUnl.cjs +0 -2
  216. package/dist/useEffectEvent-huSsGUnl.cjs.map +0 -1
@@ -0,0 +1,243 @@
1
+ .container {
2
+ padding: 16px;
3
+ }
4
+
5
+ .header {
6
+ margin-bottom: 16px;
7
+ }
8
+
9
+ .sectionTitle {
10
+ margin: 0 0 4px;
11
+ font-size: 20px;
12
+ font-weight: 600;
13
+ color: var(--color-text-primary, #1a1a1a);
14
+ }
15
+
16
+ .hint {
17
+ margin: 0;
18
+ font-size: 13px;
19
+ color: var(--color-text-secondary, #6b7280);
20
+ }
21
+
22
+ .grid {
23
+ display: grid;
24
+ grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
25
+ gap: 12px;
26
+ }
27
+
28
+ /* Card styles */
29
+ .card {
30
+ display: flex;
31
+ flex-direction: column;
32
+ aspect-ratio: 1;
33
+ border: none;
34
+ border-radius: 12px;
35
+ padding: 0;
36
+ cursor: pointer;
37
+ overflow: hidden;
38
+ transition: transform 0.15s ease, box-shadow 0.15s ease;
39
+ }
40
+
41
+ .card:hover {
42
+ transform: scale(1.02);
43
+ box-shadow: 0 8px 24px rgba(0, 0, 0, 0.2);
44
+ }
45
+
46
+ .card:active {
47
+ transform: scale(0.98);
48
+ }
49
+
50
+ .cardArt {
51
+ flex: 1;
52
+ display: flex;
53
+ align-items: center;
54
+ justify-content: center;
55
+ }
56
+
57
+ .cardIcon {
58
+ width: 60%;
59
+ height: 60%;
60
+ opacity: 0.8;
61
+ }
62
+
63
+ .cardInfo {
64
+ padding: 10px;
65
+ background: rgba(0, 0, 0, 0.3);
66
+ backdrop-filter: blur(10px);
67
+ }
68
+
69
+ .cardTitle {
70
+ font-size: 13px;
71
+ font-weight: 600;
72
+ color: #fff;
73
+ white-space: nowrap;
74
+ overflow: hidden;
75
+ text-overflow: ellipsis;
76
+ }
77
+
78
+ .cardArtist {
79
+ font-size: 11px;
80
+ color: rgba(255, 255, 255, 0.7);
81
+ white-space: nowrap;
82
+ overflow: hidden;
83
+ text-overflow: ellipsis;
84
+ }
85
+
86
+ /* Backdrop */
87
+ .backdrop {
88
+ position: fixed;
89
+ inset: 0;
90
+ background: rgba(0, 0, 0, 0.6);
91
+ display: flex;
92
+ align-items: flex-end;
93
+ justify-content: center;
94
+ z-index: 1000;
95
+ /* Fade in animation separate from view transition */
96
+ animation: backdropFadeIn 0.35s ease-out;
97
+ }
98
+
99
+ @keyframes backdropFadeIn {
100
+ from {
101
+ opacity: 0;
102
+ }
103
+ to {
104
+ opacity: 1;
105
+ }
106
+ }
107
+
108
+ /* Expanded view styles */
109
+ .expanded {
110
+ width: 100vw;
111
+ max-width: 420px;
112
+ height: 85vh;
113
+ max-height: 700px;
114
+ border-radius: 24px 24px 0 0;
115
+ display: flex;
116
+ flex-direction: column;
117
+ align-items: center;
118
+ padding: 12px 24px 32px;
119
+ box-sizing: border-box;
120
+ color: #fff;
121
+ }
122
+
123
+ .dragHandle {
124
+ width: 36px;
125
+ height: 5px;
126
+ background: rgba(255, 255, 255, 0.4);
127
+ border-radius: 3px;
128
+ margin-bottom: 24px;
129
+ flex-shrink: 0;
130
+ }
131
+
132
+ .expandedArt {
133
+ width: min(280px, 70vw);
134
+ aspect-ratio: 1;
135
+ background: rgba(0, 0, 0, 0.2);
136
+ border-radius: 16px;
137
+ display: flex;
138
+ align-items: center;
139
+ justify-content: center;
140
+ box-shadow: 0 16px 48px rgba(0, 0, 0, 0.3);
141
+ margin-bottom: 32px;
142
+ }
143
+
144
+ .expandedIcon {
145
+ width: 70%;
146
+ height: 70%;
147
+ }
148
+
149
+ .expandedInfo {
150
+ text-align: center;
151
+ margin-bottom: 32px;
152
+ }
153
+
154
+ .expandedTitle {
155
+ margin: 0 0 8px;
156
+ font-size: 22px;
157
+ font-weight: 700;
158
+ }
159
+
160
+ .expandedArtist {
161
+ margin: 0;
162
+ font-size: 16px;
163
+ opacity: 0.8;
164
+ }
165
+
166
+ .controls {
167
+ width: 100%;
168
+ max-width: 320px;
169
+ margin-bottom: 24px;
170
+ }
171
+
172
+ .progressBar {
173
+ height: 4px;
174
+ background: rgba(255, 255, 255, 0.3);
175
+ border-radius: 2px;
176
+ overflow: hidden;
177
+ }
178
+
179
+ .progressFill {
180
+ height: 100%;
181
+ background: #fff;
182
+ border-radius: 2px;
183
+ }
184
+
185
+ .timeLabels {
186
+ display: flex;
187
+ justify-content: space-between;
188
+ margin-top: 8px;
189
+ font-size: 12px;
190
+ opacity: 0.7;
191
+ }
192
+
193
+ .playbackControls {
194
+ display: flex;
195
+ align-items: center;
196
+ gap: 32px;
197
+ margin-bottom: 24px;
198
+ }
199
+
200
+ .controlButton {
201
+ background: none;
202
+ border: none;
203
+ color: #fff;
204
+ cursor: pointer;
205
+ padding: 8px;
206
+ opacity: 0.9;
207
+ transition: opacity 0.15s, transform 0.15s;
208
+ }
209
+
210
+ .controlButton:hover {
211
+ opacity: 1;
212
+ }
213
+
214
+ .controlButton:active {
215
+ transform: scale(0.9);
216
+ }
217
+
218
+ .playButton {
219
+ width: 64px;
220
+ height: 64px;
221
+ border-radius: 50%;
222
+ background: rgba(255, 255, 255, 0.2);
223
+ border: none;
224
+ color: #fff;
225
+ cursor: pointer;
226
+ display: flex;
227
+ align-items: center;
228
+ justify-content: center;
229
+ transition: background 0.15s, transform 0.15s;
230
+ }
231
+
232
+ .playButton:hover {
233
+ background: rgba(255, 255, 255, 0.3);
234
+ }
235
+
236
+ .playButton:active {
237
+ transform: scale(0.95);
238
+ }
239
+
240
+ .closeButton {
241
+ margin-top: auto;
242
+ color: rgba(255, 255, 255, 0.8);
243
+ }
@@ -0,0 +1,204 @@
1
+ /**
2
+ * @file CardExpandDemo - Apple Music style card expansion using viewTransition
3
+ */
4
+ import * as React from "react";
5
+ import { useSharedElementTransition } from "../../../../hooks/useSharedElementTransition.js";
6
+ import { DemoButton } from "../../../components/ui/DemoButton.js";
7
+ import styles from "./CardExpandDemo.module.css";
8
+
9
+ type Album = {
10
+ id: string;
11
+ title: string;
12
+ artist: string;
13
+ color: string;
14
+ };
15
+
16
+ const albums: Album[] = [
17
+ { id: "1", title: "Midnight Dreams", artist: "Luna", color: "#1a1a2e" },
18
+ { id: "2", title: "Ocean Waves", artist: "The Currents", color: "#16213e" },
19
+ { id: "3", title: "Summer Nights", artist: "Sunset", color: "#e94560" },
20
+ { id: "4", title: "City Lights", artist: "Neon", color: "#0f3460" },
21
+ { id: "5", title: "Forest Walk", artist: "Nature", color: "#2d4a22" },
22
+ { id: "6", title: "Golden Hour", artist: "Horizon", color: "#c9a227" },
23
+ ];
24
+
25
+ type AlbumCardProps = {
26
+ album: Album;
27
+ sourceProps: { style: React.CSSProperties };
28
+ onClick: () => void;
29
+ };
30
+
31
+ const AlbumCard: React.FC<AlbumCardProps> = ({ album, sourceProps, onClick }) => {
32
+ return (
33
+ <button
34
+ type="button"
35
+ className={styles.card}
36
+ style={{ backgroundColor: album.color, ...sourceProps.style }}
37
+ onClick={onClick}
38
+ >
39
+ <div className={styles.cardArt}>
40
+ <svg viewBox="0 0 100 100" className={styles.cardIcon}>
41
+ <circle cx="50" cy="50" r="30" fill="rgba(255,255,255,0.2)" />
42
+ <circle cx="50" cy="50" r="10" fill="rgba(255,255,255,0.4)" />
43
+ </svg>
44
+ </div>
45
+ <div className={styles.cardInfo}>
46
+ <div className={styles.cardTitle}>{album.title}</div>
47
+ <div className={styles.cardArtist}>{album.artist}</div>
48
+ </div>
49
+ </button>
50
+ );
51
+ };
52
+
53
+ type ExpandedViewProps = {
54
+ album: Album;
55
+ targetProps: { style: React.CSSProperties };
56
+ swipeContainerProps: React.HTMLAttributes<HTMLElement> & { style: React.CSSProperties };
57
+ onClose: () => void;
58
+ };
59
+
60
+ const ExpandedView: React.FC<ExpandedViewProps> = ({ album, targetProps, swipeContainerProps, onClose }) => {
61
+ const handleBackdropClick = (e: React.MouseEvent) => {
62
+ if (e.target === e.currentTarget) {
63
+ onClose();
64
+ }
65
+ };
66
+
67
+ // Extract event handlers from swipeContainerProps (exclude style to merge manually)
68
+ const { style: swipeStyle, ...swipeEventHandlers } = swipeContainerProps;
69
+
70
+ // Merge all styles properly
71
+ const mergedStyle: React.CSSProperties = {
72
+ backgroundColor: album.color,
73
+ ...swipeStyle,
74
+ ...targetProps.style,
75
+ };
76
+
77
+ return (
78
+ <div className={styles.backdrop} onClick={handleBackdropClick}>
79
+ <div
80
+ className={styles.expanded}
81
+ style={mergedStyle}
82
+ {...swipeEventHandlers}
83
+ >
84
+ <div className={styles.dragHandle} />
85
+
86
+ <div className={styles.expandedArt}>
87
+ <svg viewBox="0 0 100 100" className={styles.expandedIcon}>
88
+ <circle cx="50" cy="50" r="40" fill="rgba(255,255,255,0.15)" />
89
+ <circle cx="50" cy="50" r="15" fill="rgba(255,255,255,0.3)" />
90
+ </svg>
91
+ </div>
92
+
93
+ <div className={styles.expandedInfo}>
94
+ <h2 className={styles.expandedTitle}>{album.title}</h2>
95
+ <p className={styles.expandedArtist}>{album.artist}</p>
96
+ </div>
97
+
98
+ <div className={styles.controls}>
99
+ <div className={styles.progressBar}>
100
+ <div className={styles.progressFill} style={{ width: "35%" }} />
101
+ </div>
102
+ <div className={styles.timeLabels}>
103
+ <span>1:24</span>
104
+ <span>-2:36</span>
105
+ </div>
106
+ </div>
107
+
108
+ <div className={styles.playbackControls}>
109
+ <button type="button" className={styles.controlButton}>
110
+ <svg viewBox="0 0 24 24" width="32" height="32">
111
+ <path fill="currentColor" d="M6 6h2v12H6zm3.5 6l8.5 6V6z" />
112
+ </svg>
113
+ </button>
114
+ <button type="button" className={styles.playButton}>
115
+ <svg viewBox="0 0 24 24" width="40" height="40">
116
+ <path fill="currentColor" d="M6 4h4v16H6zm8 0h4v16h-4z" />
117
+ </svg>
118
+ </button>
119
+ <button type="button" className={styles.controlButton}>
120
+ <svg viewBox="0 0 24 24" width="32" height="32">
121
+ <path fill="currentColor" d="M6 18l8.5-6L6 6v12zm10-12v12h2V6h-2z" />
122
+ </svg>
123
+ </button>
124
+ </div>
125
+
126
+ <DemoButton variant="ghost" onClick={onClose} className={styles.closeButton}>
127
+ Close
128
+ </DemoButton>
129
+ </div>
130
+ </div>
131
+ );
132
+ };
133
+
134
+ // Global CSS for view transitions (CSS Modules don't support global pseudo-elements)
135
+ const viewTransitionStyles = `
136
+ /* Disable default root crossfade during view transition */
137
+ ::view-transition-old(root),
138
+ ::view-transition-new(root) {
139
+ animation: none;
140
+ }
141
+
142
+ /* Album card/expanded morph animation */
143
+ ::view-transition-group(*) {
144
+ animation-duration: 0.35s;
145
+ animation-timing-function: cubic-bezier(0.32, 0.72, 0, 1);
146
+ /* Ensure morph is above backdrop */
147
+ z-index: 2000;
148
+ }
149
+
150
+ /* Show destination state immediately, hide source */
151
+ ::view-transition-old(*) {
152
+ animation: none;
153
+ opacity: 0;
154
+ }
155
+ ::view-transition-new(*) {
156
+ animation: none;
157
+ opacity: 1;
158
+ }
159
+ `;
160
+
161
+ /**
162
+ * Demo component for Apple Music style card expansion using viewTransition
163
+ */
164
+ export const CardExpandDemo: React.FC = () => {
165
+ const { expandedItem, expand, collapse, getSourceProps, getTargetProps, getSwipeContainerProps, isSupported } =
166
+ useSharedElementTransition<Album>({
167
+ // Use single transition name for the whole card/expanded view
168
+ getTransitionName: (album) => `album-${album.id}`,
169
+ getKey: (album) => album.id,
170
+ });
171
+
172
+ return (
173
+ <div className={styles.container}>
174
+ <style>{viewTransitionStyles}</style>
175
+ <div className={styles.header}>
176
+ <h3 className={styles.sectionTitle}>Recently Played</h3>
177
+ <p className={styles.hint}>
178
+ Tap a card to expand
179
+ {isSupported ? " (View Transitions API)" : " (fallback mode)"}
180
+ </p>
181
+ </div>
182
+
183
+ <div className={styles.grid}>
184
+ {albums.map((album) => (
185
+ <AlbumCard
186
+ key={album.id}
187
+ album={album}
188
+ sourceProps={getSourceProps(album)}
189
+ onClick={() => expand(album)}
190
+ />
191
+ ))}
192
+ </div>
193
+
194
+ {expandedItem && (
195
+ <ExpandedView
196
+ album={expandedItem}
197
+ targetProps={getTargetProps()}
198
+ swipeContainerProps={getSwipeContainerProps()}
199
+ onClose={collapse}
200
+ />
201
+ )}
202
+ </div>
203
+ );
204
+ };
@@ -0,0 +1,219 @@
1
+ /**
2
+ * @file Custom AlertDialog demo - shows how to replace the default dialog component
3
+ */
4
+ import * as React from "react";
5
+ import { useDialog } from "../../../../modules/dialog/useDialog";
6
+ import type { AlertDialogProps } from "../../../../modules/dialog/types";
7
+ import { DialogContainer } from "../../../../modules/dialog/DialogContainer";
8
+ import { DemoButton } from "../../../components/ui/DemoButton";
9
+ import styles from "./DialogDemos.module.css";
10
+
11
+ /**
12
+ * Custom AlertDialog with a different visual style
13
+ */
14
+ const CustomAlertDialog: React.FC<AlertDialogProps> = ({
15
+ type,
16
+ visible,
17
+ title,
18
+ message,
19
+ confirmLabel = "OK",
20
+ cancelLabel = "Cancel",
21
+ placeholder,
22
+ defaultValue = "",
23
+ inputType = "text",
24
+ onConfirm,
25
+ onCancel,
26
+ }) => {
27
+ const [inputValue, setInputValue] = React.useState(defaultValue);
28
+
29
+ React.useEffect(() => {
30
+ if (visible) {
31
+ setInputValue(defaultValue);
32
+ }
33
+ }, [visible, defaultValue]);
34
+
35
+ const handleConfirm = () => {
36
+ if (type === "prompt") {
37
+ onConfirm(inputValue);
38
+ } else {
39
+ onConfirm();
40
+ }
41
+ };
42
+
43
+ const containerStyle: React.CSSProperties = {
44
+ background: "linear-gradient(135deg, #667eea 0%, #764ba2 100%)",
45
+ borderRadius: "16px",
46
+ padding: "24px",
47
+ minWidth: "320px",
48
+ maxWidth: "90vw",
49
+ color: "#fff",
50
+ boxShadow: "0 20px 60px rgba(0, 0, 0, 0.3)",
51
+ };
52
+
53
+ const titleStyle: React.CSSProperties = {
54
+ fontSize: "20px",
55
+ fontWeight: 700,
56
+ marginBottom: "12px",
57
+ };
58
+
59
+ const messageStyle: React.CSSProperties = {
60
+ fontSize: "15px",
61
+ lineHeight: 1.6,
62
+ opacity: 0.9,
63
+ marginBottom: "20px",
64
+ };
65
+
66
+ const inputStyle: React.CSSProperties = {
67
+ width: "100%",
68
+ padding: "12px 16px",
69
+ border: "2px solid rgba(255, 255, 255, 0.3)",
70
+ borderRadius: "8px",
71
+ fontSize: "15px",
72
+ background: "rgba(255, 255, 255, 0.15)",
73
+ color: "#fff",
74
+ marginBottom: "20px",
75
+ boxSizing: "border-box",
76
+ };
77
+
78
+ const buttonRowStyle: React.CSSProperties = {
79
+ display: "flex",
80
+ justifyContent: "flex-end",
81
+ gap: "12px",
82
+ };
83
+
84
+ const buttonBaseStyle: React.CSSProperties = {
85
+ padding: "10px 20px",
86
+ borderRadius: "8px",
87
+ fontSize: "14px",
88
+ fontWeight: 600,
89
+ cursor: "pointer",
90
+ border: "none",
91
+ transition: "transform 0.15s ease, opacity 0.15s ease",
92
+ };
93
+
94
+ const primaryButtonStyle: React.CSSProperties = {
95
+ ...buttonBaseStyle,
96
+ background: "#fff",
97
+ color: "#667eea",
98
+ };
99
+
100
+ const secondaryButtonStyle: React.CSSProperties = {
101
+ ...buttonBaseStyle,
102
+ background: "rgba(255, 255, 255, 0.2)",
103
+ color: "#fff",
104
+ border: "1px solid rgba(255, 255, 255, 0.3)",
105
+ };
106
+
107
+ return (
108
+ <DialogContainer
109
+ visible={visible}
110
+ onClose={onCancel}
111
+ position="center"
112
+ dismissible={type !== "alert"}
113
+ closeOnEscape={true}
114
+ ariaLabel={title ?? (type === "prompt" ? "Prompt" : type === "confirm" ? "Confirm" : "Alert")}
115
+ >
116
+ <div style={containerStyle}>
117
+ {title ? <div style={titleStyle}>{title}</div> : null}
118
+ <div style={messageStyle}>{message}</div>
119
+ <React.Activity mode={type === "prompt" ? "visible" : "hidden"}>
120
+ <input
121
+ type={inputType}
122
+ value={inputValue}
123
+ onChange={(e) => setInputValue(e.target.value)}
124
+ onKeyDown={(e) => {
125
+ if (e.key === "Enter") {
126
+ e.preventDefault();
127
+ handleConfirm();
128
+ }
129
+ }}
130
+ placeholder={placeholder}
131
+ style={inputStyle}
132
+ autoFocus
133
+ />
134
+ </React.Activity>
135
+ <div style={buttonRowStyle}>
136
+ <React.Activity mode={type !== "alert" ? "visible" : "hidden"}>
137
+ <button type="button" style={secondaryButtonStyle} onClick={onCancel}>
138
+ {cancelLabel}
139
+ </button>
140
+ </React.Activity>
141
+ <button type="button" style={primaryButtonStyle} onClick={handleConfirm}>
142
+ {confirmLabel}
143
+ </button>
144
+ </div>
145
+ </div>
146
+ </DialogContainer>
147
+ );
148
+ };
149
+
150
+ export const CustomAlertDialogDemo: React.FC = () => {
151
+ const { alert, confirm, prompt, Outlet } = useDialog({
152
+ alertDialogComponent: CustomAlertDialog,
153
+ });
154
+ const [lastResult, setLastResult] = React.useState<string>("");
155
+
156
+ const handleAlert = async () => {
157
+ await alert({
158
+ title: "Custom Alert",
159
+ message: "This is a custom-styled alert dialog with gradient background!",
160
+ okLabel: "Awesome!",
161
+ });
162
+ setLastResult("alert: acknowledged");
163
+ };
164
+
165
+ const handleConfirm = async () => {
166
+ const result = await confirm({
167
+ title: "Custom Confirm",
168
+ message: "Do you like this custom dialog style?",
169
+ confirmLabel: "Love it!",
170
+ cancelLabel: "Not really",
171
+ });
172
+ setLastResult(`confirm: ${result ? "loved it" : "not really"}`);
173
+ };
174
+
175
+ const handlePrompt = async () => {
176
+ const result = await prompt({
177
+ title: "Custom Prompt",
178
+ message: "What's your favorite color?",
179
+ placeholder: "Enter a color...",
180
+ defaultValue: "",
181
+ });
182
+ setLastResult(`prompt: ${result === null ? "cancelled" : `"${result}"`}`);
183
+ };
184
+
185
+ return (
186
+ <div className={styles.container}>
187
+ <div className={styles.section}>
188
+ <h3>Custom Alert Dialog Component</h3>
189
+ <p>
190
+ Replace the default AlertDialog with your own component by passing
191
+ <code style={{ background: "#f0f0f0", padding: "2px 6px", borderRadius: "4px", margin: "0 4px" }}>
192
+ alertDialogComponent
193
+ </code>
194
+ to useDialog.
195
+ </p>
196
+ </div>
197
+
198
+ <div className={styles.section}>
199
+ <h3>Gradient Style Dialogs</h3>
200
+ <p>These dialogs use a custom component with gradient background.</p>
201
+ <div className={styles.buttonGroup}>
202
+ <DemoButton variant="primary" size="md" onClick={handleAlert}>
203
+ Show Custom Alert
204
+ </DemoButton>
205
+ <DemoButton variant="primary" size="md" onClick={handleConfirm}>
206
+ Show Custom Confirm
207
+ </DemoButton>
208
+ <DemoButton variant="primary" size="md" onClick={handlePrompt}>
209
+ Show Custom Prompt
210
+ </DemoButton>
211
+ </div>
212
+ </div>
213
+
214
+ {lastResult ? <div className={styles.resultBox}>Last result: {lastResult}</div> : null}
215
+
216
+ <Outlet />
217
+ </div>
218
+ );
219
+ };