@seed-design/lynx-react 0.7.1 → 0.9.0

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 (265) hide show
  1. package/lib/components/Accordion/Accordion.jsx +2 -2
  2. package/lib/components/ActionButton/ActionButton.jsx +1 -1
  3. package/lib/components/AlertDialog/AlertDialog.d.ts +64 -0
  4. package/lib/components/AlertDialog/AlertDialog.d.ts.map +1 -0
  5. package/lib/components/AlertDialog/AlertDialog.jsx +138 -0
  6. package/lib/components/AlertDialog/AlertDialog.namespace.d.ts +2 -0
  7. package/lib/components/AlertDialog/AlertDialog.namespace.d.ts.map +1 -0
  8. package/lib/components/AlertDialog/AlertDialog.namespace.js +17 -0
  9. package/lib/components/AlertDialog/index.d.ts +3 -0
  10. package/lib/components/AlertDialog/index.d.ts.map +1 -0
  11. package/lib/components/AppBar/AppBar.d.ts +14 -1
  12. package/lib/components/AppBar/AppBar.d.ts.map +1 -1
  13. package/lib/components/AppBar/AppBar.jsx +42 -16
  14. package/lib/components/AppBar/AppBar.namespace.d.ts +1 -1
  15. package/lib/components/AppBar/AppBar.namespace.d.ts.map +1 -1
  16. package/lib/components/AppBar/context.d.ts +2 -1
  17. package/lib/components/AppBar/context.d.ts.map +1 -1
  18. package/lib/components/AppBar/index.d.ts +1 -1
  19. package/lib/components/AppBar/index.d.ts.map +1 -1
  20. package/lib/components/AppBar/useAppBar.d.ts +2 -1
  21. package/lib/components/AppBar/useAppBar.d.ts.map +1 -1
  22. package/lib/components/AppBar/useAppBar.js +17 -15
  23. package/lib/components/AttachmentDisplay/AttachmentDisplay.d.ts +182 -0
  24. package/lib/components/AttachmentDisplay/AttachmentDisplay.d.ts.map +1 -0
  25. package/lib/components/AttachmentDisplay/AttachmentDisplay.jsx +444 -0
  26. package/lib/components/AttachmentDisplay/index.d.ts +2 -0
  27. package/lib/components/AttachmentDisplay/index.d.ts.map +1 -0
  28. package/lib/components/AttachmentInput/AttachmentInput.d.ts +179 -0
  29. package/lib/components/AttachmentInput/AttachmentInput.d.ts.map +1 -0
  30. package/lib/components/AttachmentInput/AttachmentInput.jsx +520 -0
  31. package/lib/components/AttachmentInput/index.d.ts +2 -0
  32. package/lib/components/AttachmentInput/index.d.ts.map +1 -0
  33. package/lib/components/BottomSheet/BottomSheet.d.ts +1 -1
  34. package/lib/components/BottomSheet/BottomSheet.d.ts.map +1 -1
  35. package/lib/components/BottomSheet/BottomSheet.jsx +1 -7
  36. package/lib/components/Box/Box.d.ts +3 -3
  37. package/lib/components/Box/Box.d.ts.map +1 -1
  38. package/lib/components/Callout/Callout.jsx +2 -2
  39. package/lib/components/Checkbox/Checkbox.jsx +2 -2
  40. package/lib/components/Chip/Chip.jsx +2 -2
  41. package/lib/components/ChipTabs/ChipTabs.d.ts +41 -0
  42. package/lib/components/ChipTabs/ChipTabs.d.ts.map +1 -0
  43. package/lib/components/ChipTabs/ChipTabs.jsx +39 -0
  44. package/lib/components/ChipTabs/ChipTabs.namespace.d.ts +2 -0
  45. package/lib/components/ChipTabs/ChipTabs.namespace.d.ts.map +1 -0
  46. package/lib/components/ChipTabs/ChipTabs.namespace.js +13 -0
  47. package/lib/components/ChipTabs/index.d.ts +3 -0
  48. package/lib/components/ChipTabs/index.d.ts.map +1 -0
  49. package/lib/components/ContextualFloatingButton/ContextualFloatingButton.d.ts +18 -0
  50. package/lib/components/ContextualFloatingButton/ContextualFloatingButton.d.ts.map +1 -0
  51. package/lib/components/ContextualFloatingButton/ContextualFloatingButton.jsx +113 -0
  52. package/lib/components/ContextualFloatingButton/index.d.ts +2 -0
  53. package/lib/components/ContextualFloatingButton/index.d.ts.map +1 -0
  54. package/lib/components/Dialog/Dialog.d.ts +87 -0
  55. package/lib/components/Dialog/Dialog.d.ts.map +1 -0
  56. package/lib/components/Dialog/Dialog.jsx +147 -0
  57. package/lib/components/Dialog/Dialog.namespace.d.ts +2 -0
  58. package/lib/components/Dialog/Dialog.namespace.d.ts.map +1 -0
  59. package/lib/components/Dialog/Dialog.namespace.js +18 -0
  60. package/lib/components/Dialog/index.d.ts +3 -0
  61. package/lib/components/Dialog/index.d.ts.map +1 -0
  62. package/lib/components/FloatingActionButton/FloatingActionButton.d.ts +23 -0
  63. package/lib/components/FloatingActionButton/FloatingActionButton.d.ts.map +1 -0
  64. package/lib/components/FloatingActionButton/FloatingActionButton.jsx +76 -0
  65. package/lib/components/FloatingActionButton/FloatingActionButton.namespace.d.ts +2 -0
  66. package/lib/components/FloatingActionButton/FloatingActionButton.namespace.d.ts.map +1 -0
  67. package/lib/components/FloatingActionButton/FloatingActionButton.namespace.js +10 -0
  68. package/lib/components/FloatingActionButton/index.d.ts +3 -0
  69. package/lib/components/FloatingActionButton/index.d.ts.map +1 -0
  70. package/lib/components/HelpBubble/HelpBubble.d.ts +67 -0
  71. package/lib/components/HelpBubble/HelpBubble.d.ts.map +1 -0
  72. package/lib/components/HelpBubble/HelpBubble.jsx +600 -0
  73. package/lib/components/HelpBubble/HelpBubble.namespace.d.ts +2 -0
  74. package/lib/components/HelpBubble/HelpBubble.namespace.d.ts.map +1 -0
  75. package/lib/components/HelpBubble/HelpBubble.namespace.js +18 -0
  76. package/lib/components/HelpBubble/index.d.ts +3 -0
  77. package/lib/components/HelpBubble/index.d.ts.map +1 -0
  78. package/lib/components/Icon/Icon.d.ts +1 -0
  79. package/lib/components/Icon/Icon.d.ts.map +1 -1
  80. package/lib/components/Icon/Icon.jsx +2 -1
  81. package/lib/components/IdentityPlaceholder/IdentityPlaceholder.d.ts +28 -0
  82. package/lib/components/IdentityPlaceholder/IdentityPlaceholder.d.ts.map +1 -0
  83. package/lib/components/IdentityPlaceholder/IdentityPlaceholder.jsx +37 -0
  84. package/lib/components/IdentityPlaceholder/IdentityPlaceholder.namespace.d.ts +2 -0
  85. package/lib/components/IdentityPlaceholder/IdentityPlaceholder.namespace.d.ts.map +1 -0
  86. package/lib/components/IdentityPlaceholder/IdentityPlaceholder.namespace.js +9 -0
  87. package/lib/components/IdentityPlaceholder/identity-placeholder-business.js +4 -0
  88. package/lib/components/IdentityPlaceholder/identity-placeholder-person.js +4 -0
  89. package/lib/components/IdentityPlaceholder/index.d.ts +3 -0
  90. package/lib/components/IdentityPlaceholder/index.d.ts.map +1 -0
  91. package/lib/components/InputButton/InputButton.d.ts +2 -0
  92. package/lib/components/InputButton/InputButton.d.ts.map +1 -1
  93. package/lib/components/InputButton/InputButton.jsx +40 -8
  94. package/lib/components/List/List.d.ts +1 -1
  95. package/lib/components/List/List.d.ts.map +1 -1
  96. package/lib/components/List/List.jsx +26 -12
  97. package/lib/components/Menu/Menu.d.ts.map +1 -1
  98. package/lib/components/Menu/Menu.jsx +15 -5
  99. package/lib/components/PageBanner/PageBanner.d.ts +3 -0
  100. package/lib/components/PageBanner/PageBanner.d.ts.map +1 -1
  101. package/lib/components/PageBanner/PageBanner.jsx +49 -11
  102. package/lib/components/QuantityPicker/QuantityPicker.d.ts +53 -0
  103. package/lib/components/QuantityPicker/QuantityPicker.d.ts.map +1 -0
  104. package/lib/components/QuantityPicker/QuantityPicker.jsx +282 -0
  105. package/lib/components/QuantityPicker/QuantityPicker.namespace.d.ts +2 -0
  106. package/lib/components/QuantityPicker/QuantityPicker.namespace.d.ts.map +1 -0
  107. package/lib/components/QuantityPicker/QuantityPicker.namespace.js +11 -0
  108. package/lib/components/QuantityPicker/index.d.ts +3 -0
  109. package/lib/components/QuantityPicker/index.d.ts.map +1 -0
  110. package/lib/components/RadioGroup/RadioGroup.jsx +2 -2
  111. package/lib/components/ReactionButton/ReactionButton.d.ts +1 -1
  112. package/lib/components/ReactionButton/ReactionButton.d.ts.map +1 -1
  113. package/lib/components/ReactionButton/ReactionButton.jsx +22 -13
  114. package/lib/components/ScrollFog/ScrollFog.d.ts +41 -0
  115. package/lib/components/ScrollFog/ScrollFog.d.ts.map +1 -0
  116. package/lib/components/ScrollFog/ScrollFog.jsx +65 -0
  117. package/lib/components/ScrollFog/index.d.ts +2 -0
  118. package/lib/components/ScrollFog/index.d.ts.map +1 -0
  119. package/lib/components/SegmentedControl/SegmentedControl.jsx +2 -2
  120. package/lib/components/Select/Select.d.ts +112 -0
  121. package/lib/components/Select/Select.d.ts.map +1 -0
  122. package/lib/components/Select/Select.jsx +885 -0
  123. package/lib/components/Select/Select.namespace.d.ts +2 -0
  124. package/lib/components/Select/Select.namespace.d.ts.map +1 -0
  125. package/lib/components/Select/Select.namespace.js +23 -0
  126. package/lib/components/Select/index.d.ts +3 -0
  127. package/lib/components/Select/index.d.ts.map +1 -0
  128. package/lib/components/Skeleton/Skeleton.d.ts +15 -0
  129. package/lib/components/Skeleton/Skeleton.d.ts.map +1 -0
  130. package/lib/components/Skeleton/Skeleton.jsx +18 -0
  131. package/lib/components/Skeleton/index.d.ts +2 -0
  132. package/lib/components/Skeleton/index.d.ts.map +1 -0
  133. package/lib/components/Slider/Slider.d.ts +101 -0
  134. package/lib/components/Slider/Slider.d.ts.map +1 -0
  135. package/lib/components/Slider/Slider.jsx +573 -0
  136. package/lib/components/Slider/Slider.namespace.d.ts +2 -0
  137. package/lib/components/Slider/Slider.namespace.d.ts.map +1 -0
  138. package/lib/components/Slider/Slider.namespace.js +19 -0
  139. package/lib/components/Slider/Slider.utils.d.ts +19 -0
  140. package/lib/components/Slider/Slider.utils.d.ts.map +1 -0
  141. package/lib/components/Slider/Slider.utils.js +106 -0
  142. package/lib/components/Slider/index.d.ts +3 -0
  143. package/lib/components/Slider/index.d.ts.map +1 -0
  144. package/lib/components/Stack/Stack.d.ts +7 -9
  145. package/lib/components/Stack/Stack.d.ts.map +1 -1
  146. package/lib/components/SwipeableMenuSheet/SwipeableMenuSheet.d.ts.map +1 -1
  147. package/lib/components/SwipeableMenuSheet/SwipeableMenuSheet.jsx +22 -8
  148. package/lib/components/Switch/Switch.d.ts.map +1 -1
  149. package/lib/components/Switch/Switch.jsx +5 -3
  150. package/lib/components/Tabs/Tabs.d.ts +34 -2
  151. package/lib/components/Tabs/Tabs.d.ts.map +1 -1
  152. package/lib/components/Tabs/Tabs.jsx +186 -56
  153. package/lib/components/Tabs/Tabs.utils.d.ts +14 -1
  154. package/lib/components/Tabs/Tabs.utils.d.ts.map +1 -1
  155. package/lib/components/Tabs/Tabs.utils.js +24 -3
  156. package/lib/components/Tabs/index.d.ts +1 -1
  157. package/lib/components/Tabs/index.d.ts.map +1 -1
  158. package/lib/components/index.d.ts +14 -0
  159. package/lib/components/index.d.ts.map +1 -1
  160. package/lib/hooks/useControllableState.d.ts +1 -14
  161. package/lib/hooks/useControllableState.d.ts.map +1 -1
  162. package/lib/hooks/usePressTap.d.ts +1 -27
  163. package/lib/hooks/usePressTap.d.ts.map +1 -1
  164. package/lib/hooks/useSafeArea.d.ts +8 -4
  165. package/lib/hooks/useSafeArea.d.ts.map +1 -1
  166. package/lib/hooks/useSafeArea.js +22 -20
  167. package/lib/index.js +29 -6
  168. package/lib/{hooks/useControllableState.js → packages/lynx-react-headless/use-controllable-state/lib/index.js} +2 -3
  169. package/lib/{hooks/usePressTap.js → packages/lynx-react-headless/use-press-tap/lib/index.js} +13 -10
  170. package/lib/types.d.ts +1 -0
  171. package/lib/types.d.ts.map +1 -1
  172. package/lib/utils/styled.d.ts +46 -6
  173. package/lib/utils/styled.d.ts.map +1 -1
  174. package/lib/utils/styled.js +19 -4
  175. package/package.json +9 -5
  176. package/src/components/AlertDialog/AlertDialog.namespace.ts +22 -0
  177. package/src/components/AlertDialog/AlertDialog.test.tsx +226 -0
  178. package/src/components/AlertDialog/AlertDialog.tsx +374 -0
  179. package/src/components/AlertDialog/index.ts +24 -0
  180. package/src/components/AppBar/AppBar.namespace.ts +1 -0
  181. package/src/components/AppBar/AppBar.test.tsx +252 -3
  182. package/src/components/AppBar/AppBar.tsx +108 -25
  183. package/src/components/AppBar/context.ts +3 -1
  184. package/src/components/AppBar/index.ts +1 -0
  185. package/src/components/AppBar/useAppBar.ts +21 -15
  186. package/src/components/AttachmentDisplay/AttachmentDisplay.tsx +886 -0
  187. package/src/components/AttachmentDisplay/index.ts +48 -0
  188. package/src/components/AttachmentInput/AttachmentInput.tsx +1001 -0
  189. package/src/components/AttachmentInput/index.ts +49 -0
  190. package/src/components/BottomSheet/BottomSheet.test.tsx +22 -7
  191. package/src/components/BottomSheet/BottomSheet.tsx +1 -19
  192. package/src/components/Box/Box.test.tsx +104 -0
  193. package/src/components/Box/Box.tsx +9 -6
  194. package/src/components/ChipTabs/ChipTabs.namespace.ts +14 -0
  195. package/src/components/ChipTabs/ChipTabs.tsx +119 -0
  196. package/src/components/ChipTabs/index.ts +16 -0
  197. package/src/components/ContextualFloatingButton/ContextualFloatingButton.test.tsx +63 -0
  198. package/src/components/ContextualFloatingButton/ContextualFloatingButton.tsx +232 -0
  199. package/src/components/ContextualFloatingButton/index.ts +4 -0
  200. package/src/components/Dialog/Dialog.namespace.ts +24 -0
  201. package/src/components/Dialog/Dialog.test.tsx +172 -0
  202. package/src/components/Dialog/Dialog.tsx +373 -0
  203. package/src/components/Dialog/index.ts +26 -0
  204. package/src/components/FloatingActionButton/FloatingActionButton.namespace.ts +8 -0
  205. package/src/components/FloatingActionButton/FloatingActionButton.test.tsx +59 -0
  206. package/src/components/FloatingActionButton/FloatingActionButton.tsx +207 -0
  207. package/src/components/FloatingActionButton/index.ts +10 -0
  208. package/src/components/HelpBubble/HelpBubble.namespace.ts +24 -0
  209. package/src/components/HelpBubble/HelpBubble.tsx +998 -0
  210. package/src/components/HelpBubble/index.ts +26 -0
  211. package/src/components/Icon/Icon.test.tsx +0 -3
  212. package/src/components/Icon/Icon.tsx +11 -1
  213. package/src/components/IdentityPlaceholder/IdentityPlaceholder.namespace.ts +6 -0
  214. package/src/components/IdentityPlaceholder/IdentityPlaceholder.tsx +103 -0
  215. package/src/components/IdentityPlaceholder/assets.d.ts +4 -0
  216. package/src/components/IdentityPlaceholder/identity-placeholder-business.webp +0 -0
  217. package/src/components/IdentityPlaceholder/identity-placeholder-person.webp +0 -0
  218. package/src/components/IdentityPlaceholder/index.ts +8 -0
  219. package/src/components/InputButton/InputButton.test.tsx +128 -1
  220. package/src/components/InputButton/InputButton.tsx +60 -9
  221. package/src/components/List/List.test.tsx +54 -2
  222. package/src/components/List/List.tsx +43 -10
  223. package/src/components/Menu/Menu.tsx +14 -4
  224. package/src/components/Menu/__tests__/Menu.test.tsx +34 -0
  225. package/src/components/PageBanner/PageBanner.test.tsx +110 -3
  226. package/src/components/PageBanner/PageBanner.tsx +83 -19
  227. package/src/components/QuantityPicker/QuantityPicker.namespace.ts +10 -0
  228. package/src/components/QuantityPicker/QuantityPicker.test.tsx +235 -0
  229. package/src/components/QuantityPicker/QuantityPicker.tsx +605 -0
  230. package/src/components/QuantityPicker/index.ts +14 -0
  231. package/src/components/ReactionButton/ReactionButton.feedback.test.tsx +50 -0
  232. package/src/components/ReactionButton/ReactionButton.test.tsx +5 -3
  233. package/src/components/ReactionButton/ReactionButton.tsx +20 -12
  234. package/src/components/ScrollFog/ScrollFog.test.tsx +222 -0
  235. package/src/components/ScrollFog/ScrollFog.tsx +172 -0
  236. package/src/components/ScrollFog/index.ts +1 -0
  237. package/src/components/Select/Select.namespace.ts +34 -0
  238. package/src/components/Select/Select.test.tsx +297 -0
  239. package/src/components/Select/Select.tsx +1483 -0
  240. package/src/components/Select/index.ts +39 -0
  241. package/src/components/Skeleton/Skeleton.test.tsx +64 -0
  242. package/src/components/Skeleton/Skeleton.tsx +45 -0
  243. package/src/components/Skeleton/index.ts +1 -0
  244. package/src/components/Slider/Slider.namespace.ts +26 -0
  245. package/src/components/Slider/Slider.test.tsx +260 -0
  246. package/src/components/Slider/Slider.tsx +897 -0
  247. package/src/components/Slider/Slider.utils.ts +167 -0
  248. package/src/components/Slider/index.ts +30 -0
  249. package/src/components/Stack/Stack.test.tsx +7 -0
  250. package/src/components/Stack/Stack.tsx +11 -10
  251. package/src/components/SwipeableMenuSheet/SwipeableMenuSheet.test.tsx +21 -1
  252. package/src/components/SwipeableMenuSheet/SwipeableMenuSheet.tsx +30 -7
  253. package/src/components/Switch/Switch.tsx +14 -13
  254. package/src/components/Tabs/Tabs.test.tsx +218 -1
  255. package/src/components/Tabs/Tabs.tsx +346 -75
  256. package/src/components/Tabs/Tabs.utils.ts +51 -1
  257. package/src/components/Tabs/index.ts +17 -1
  258. package/src/components/index.ts +14 -0
  259. package/src/hooks/useControllableState.ts +1 -43
  260. package/src/hooks/usePressTap.test.ts +23 -11
  261. package/src/hooks/usePressTap.ts +1 -60
  262. package/src/hooks/useSafeArea.test.ts +13 -1
  263. package/src/hooks/useSafeArea.ts +25 -23
  264. package/src/types.ts +1 -0
  265. package/src/utils/styled.ts +127 -9
@@ -0,0 +1,226 @@
1
+ import type { ReactNode } from "@lynx-js/react";
2
+
3
+ import { render } from "@lynx-js/react/testing-library";
4
+ import { beforeEach, describe, expect, it, vi } from "vitest";
5
+
6
+ const alertDialogMocks = vi.hoisted(() => ({
7
+ rootProps: [] as Array<Record<string, unknown>>,
8
+ viewProps: [] as Array<Record<string, unknown>>,
9
+ backdropProps: [] as Array<Record<string, unknown>>,
10
+ contentProps: [] as Array<Record<string, unknown>>,
11
+ closeProps: [] as Array<Record<string, unknown>>,
12
+ }));
13
+
14
+ vi.mock("@lynx-js/lynx-ui-dialog", () => {
15
+ const renderChildren = (children: unknown, status: Record<string, boolean>): ReactNode => {
16
+ if (typeof children === "function") {
17
+ return (children as (status: Record<string, boolean>) => ReactNode)(status);
18
+ }
19
+ return children as ReactNode;
20
+ };
21
+
22
+ const DialogRoot = (props: Record<string, unknown>) => {
23
+ alertDialogMocks.rootProps.push(props);
24
+ return <>{renderChildren(props["children"], { open: props["show"] === true })}</>;
25
+ };
26
+ DialogRoot.displayName = "MockDialogRoot";
27
+
28
+ const DialogTrigger = (props: Record<string, unknown>) => (
29
+ <view>{renderChildren(props["children"], { active: false, busy: false })}</view>
30
+ );
31
+ DialogTrigger.displayName = "MockDialogTrigger";
32
+
33
+ const DialogView = (props: Record<string, unknown>) => {
34
+ alertDialogMocks.viewProps.push(props);
35
+ return (
36
+ <view className={props["className"] as string}>
37
+ {renderChildren(props["children"], { open: props["show"] === true })}
38
+ </view>
39
+ );
40
+ };
41
+ DialogView.displayName = "MockDialogView";
42
+
43
+ const DialogBackdrop = (props: Record<string, unknown>) => {
44
+ alertDialogMocks.backdropProps.push(props);
45
+ return <view className={props["className"] as string}>{props["children"] as ReactNode}</view>;
46
+ };
47
+ DialogBackdrop.displayName = "MockDialogBackdrop";
48
+
49
+ const DialogContent = (props: Record<string, unknown>) => {
50
+ alertDialogMocks.contentProps.push(props);
51
+ return <view className={props["className"] as string}>{props["children"] as ReactNode}</view>;
52
+ };
53
+ DialogContent.displayName = "MockDialogContent";
54
+
55
+ const DialogClose = (props: Record<string, unknown>) => {
56
+ alertDialogMocks.closeProps.push(props);
57
+ return (
58
+ <view className={props["className"] as string}>
59
+ {renderChildren(props["children"], { active: false, busy: false })}
60
+ </view>
61
+ );
62
+ };
63
+ DialogClose.displayName = "MockDialogClose";
64
+
65
+ return {
66
+ DialogBackdrop,
67
+ DialogClose,
68
+ DialogContent,
69
+ DialogRoot,
70
+ DialogTrigger,
71
+ DialogView,
72
+ };
73
+ });
74
+
75
+ import * as AlertDialog from "./AlertDialog.namespace";
76
+
77
+ describe("AlertDialog", () => {
78
+ beforeEach(() => {
79
+ alertDialogMocks.rootProps = [];
80
+ alertDialogMocks.viewProps = [];
81
+ alertDialogMocks.backdropProps = [];
82
+ alertDialogMocks.contentProps = [];
83
+ alertDialogMocks.closeProps = [];
84
+ });
85
+
86
+ it("maps the namespace API and applies dialog recipe classes", () => {
87
+ const onOpenChange = vi.fn();
88
+ const { container } = render(
89
+ <AlertDialog.Root open onOpenChange={onOpenChange}>
90
+ <AlertDialog.Trigger>
91
+ <text>Open</text>
92
+ </AlertDialog.Trigger>
93
+ <AlertDialog.Positioner>
94
+ <AlertDialog.Backdrop />
95
+ <AlertDialog.Content>
96
+ <AlertDialog.Header>
97
+ <AlertDialog.Title>Title</AlertDialog.Title>
98
+ <AlertDialog.Description>Description</AlertDialog.Description>
99
+ </AlertDialog.Header>
100
+ <AlertDialog.Footer>
101
+ <AlertDialog.Action>
102
+ <text>Cancel</text>
103
+ </AlertDialog.Action>
104
+ </AlertDialog.Footer>
105
+ </AlertDialog.Content>
106
+ </AlertDialog.Positioner>
107
+ </AlertDialog.Root>,
108
+ );
109
+
110
+ expect(alertDialogMocks.rootProps.at(-1)).toMatchObject({
111
+ show: true,
112
+ onShowChange: onOpenChange,
113
+ });
114
+ expect(container.querySelector(".seed-alert-dialog__positioner")).not.toBeNull();
115
+ expect(container.querySelector(".seed-alert-dialog__backdrop")).not.toBeNull();
116
+ expect(container.querySelector(".seed-alert-dialog__content")).not.toBeNull();
117
+ expect(container.querySelector(".seed-alert-dialog__header")).not.toBeNull();
118
+ expect(container.querySelector(".seed-alert-dialog__title")).not.toBeNull();
119
+ expect(container.querySelector(".seed-alert-dialog__description")).not.toBeNull();
120
+ expect(container.querySelector(".seed-alert-dialog__footer")).not.toBeNull();
121
+ expect(container.querySelector(".seed-alert-dialog__action")).not.toBeNull();
122
+ });
123
+
124
+ it("does not dismiss from the backdrop by default and preserves explicit overrides", () => {
125
+ render(
126
+ <AlertDialog.Root defaultOpen>
127
+ <AlertDialog.Positioner>
128
+ <AlertDialog.Backdrop />
129
+ <AlertDialog.Content />
130
+ </AlertDialog.Positioner>
131
+ </AlertDialog.Root>,
132
+ );
133
+
134
+ expect(alertDialogMocks.backdropProps.at(-1)).toHaveProperty("clickToClose", false);
135
+
136
+ render(
137
+ <AlertDialog.Root defaultOpen>
138
+ <AlertDialog.Positioner>
139
+ <AlertDialog.Backdrop clickToClose />
140
+ <AlertDialog.Content />
141
+ </AlertDialog.Positioner>
142
+ </AlertDialog.Root>,
143
+ );
144
+
145
+ expect(alertDialogMocks.backdropProps.at(-1)).toHaveProperty("clickToClose", true);
146
+ });
147
+
148
+ it("provides alert dialog accessibility defaults and preserves consumer overrides", () => {
149
+ const { container } = render(
150
+ <AlertDialog.Root defaultOpen>
151
+ <AlertDialog.Positioner>
152
+ <AlertDialog.Backdrop />
153
+ <AlertDialog.Content>
154
+ <AlertDialog.Title>Title</AlertDialog.Title>
155
+ </AlertDialog.Content>
156
+ </AlertDialog.Positioner>
157
+ </AlertDialog.Root>,
158
+ );
159
+
160
+ expect(alertDialogMocks.contentProps.at(-1)?.["dialogContentProps"]).toMatchObject({
161
+ "accessibility-element": true,
162
+ "accessibility-role-description": "alertdialog",
163
+ });
164
+ expect(container.querySelector("text")?.getAttribute("accessibility-heading")).toBe("true");
165
+
166
+ const { container: overriddenContainer } = render(
167
+ <AlertDialog.Root defaultOpen>
168
+ <AlertDialog.Positioner>
169
+ <AlertDialog.Content
170
+ accessibility-element={false}
171
+ accessibility-role-description="custom dialog"
172
+ />
173
+ <AlertDialog.Title accessibility-heading={false}>Title</AlertDialog.Title>
174
+ </AlertDialog.Positioner>
175
+ </AlertDialog.Root>,
176
+ );
177
+
178
+ expect(alertDialogMocks.contentProps.at(-1)?.["dialogContentProps"]).toMatchObject({
179
+ "accessibility-element": false,
180
+ "accessibility-role-description": "custom dialog",
181
+ });
182
+ const overriddenTexts = overriddenContainer.querySelectorAll("text");
183
+ expect(
184
+ overriddenTexts.item(overriddenTexts.length - 1)?.getAttribute("accessibility-heading"),
185
+ ).toBe("false");
186
+ });
187
+
188
+ it("disables transitions with skipAnimation and removes reserved lifecycle handlers", () => {
189
+ const userBindTap = vi.fn();
190
+ const dialogContentProps = {
191
+ style: { paddingTop: "12px" },
192
+ bindtap: userBindTap,
193
+ };
194
+
195
+ render(
196
+ <AlertDialog.Root defaultOpen forceMount skipAnimation>
197
+ <AlertDialog.Positioner container="window" overlayLevel={2} style={{ width: "80%" }}>
198
+ <AlertDialog.Backdrop />
199
+ <AlertDialog.Content dialogContentProps={dialogContentProps} />
200
+ </AlertDialog.Positioner>
201
+ </AlertDialog.Root>,
202
+ );
203
+
204
+ expect(alertDialogMocks.rootProps.at(-1)).toMatchObject({
205
+ defaultShow: true,
206
+ forceMount: true,
207
+ });
208
+ expect(alertDialogMocks.viewProps.at(-1)).toMatchObject({
209
+ container: "window",
210
+ overlayLevel: 2,
211
+ style: { width: "80%", height: "100%" },
212
+ transition: false,
213
+ });
214
+ expect(alertDialogMocks.backdropProps.at(-1)).toMatchObject({ transition: false });
215
+ expect(alertDialogMocks.contentProps.at(-1)).toMatchObject({ transition: false });
216
+ expect(alertDialogMocks.contentProps.at(-1)?.["dialogContentProps"]).toMatchObject({
217
+ style: { paddingTop: "12px" },
218
+ "accessibility-element": true,
219
+ "accessibility-role-description": "alertdialog",
220
+ });
221
+ expect(alertDialogMocks.contentProps.at(-1)?.["dialogContentProps"]).not.toHaveProperty(
222
+ "bindtap",
223
+ );
224
+ expect(userBindTap).not.toHaveBeenCalled();
225
+ });
226
+ });
@@ -0,0 +1,374 @@
1
+ import {
2
+ DialogBackdrop as DialogBackdropPrimitive,
3
+ DialogClose as DialogClosePrimitive,
4
+ DialogContent as DialogContentPrimitive,
5
+ DialogRoot as DialogRootPrimitive,
6
+ DialogTrigger as DialogTriggerPrimitive,
7
+ DialogView as DialogViewPrimitive,
8
+ type DialogBackdropProps as DialogPrimitiveBackdropProps,
9
+ type DialogCloseProps as DialogPrimitiveCloseProps,
10
+ type DialogContentProps as DialogPrimitiveContentProps,
11
+ type DialogRootProps as DialogPrimitiveRootProps,
12
+ type DialogTriggerProps as DialogPrimitiveTriggerProps,
13
+ type DialogViewProps as DialogPrimitiveViewProps,
14
+ } from "@lynx-js/lynx-ui-dialog";
15
+ import {
16
+ forwardRef,
17
+ type ForwardRefExoticComponent,
18
+ type PropsWithoutRef,
19
+ type ReactElement,
20
+ type RefAttributes,
21
+ } from "@lynx-js/react";
22
+ import {
23
+ alertDialog,
24
+ type AlertDialogVariantProps,
25
+ } from "@seed-design/lynx-css/recipes/alert-dialog";
26
+ import clsx from "clsx";
27
+
28
+ import type {
29
+ LynxAccessibilityProps,
30
+ LynxStyledElementProps,
31
+ LynxTextRef,
32
+ LynxViewRef,
33
+ } from "../../types";
34
+ import { createSlotRecipeContext } from "../../utils/create-slot-recipe-context";
35
+ import { useStyleProps, type StyleProps } from "../../utils/styled";
36
+
37
+ type AlertDialogComponent<Props> = ((props: Props) => ReactElement) & {
38
+ displayName?: string;
39
+ };
40
+ type LynxForwardRefComponent<T, Props> = ForwardRefExoticComponent<
41
+ PropsWithoutRef<Props> & RefAttributes<T>
42
+ >;
43
+
44
+ type NativeLifecycleHandlers = {
45
+ bindanimationstart?: unknown;
46
+ bindanimationend?: unknown;
47
+ bindanimationcancel?: unknown;
48
+ bindtransitionstart?: unknown;
49
+ bindtransitionend?: unknown;
50
+ bindtap?: unknown;
51
+ };
52
+
53
+ const { ClassNamesProvider, PropsProvider, useClassNames, useProps } =
54
+ createSlotRecipeContext(alertDialog);
55
+
56
+ function omitHeadlessLifecycleHandlers<Props extends object>(
57
+ props: Props | undefined,
58
+ ): Props | undefined {
59
+ if (!props) return props;
60
+
61
+ const {
62
+ bindanimationstart: _bindanimationstart,
63
+ bindanimationend: _bindanimationend,
64
+ bindanimationcancel: _bindanimationcancel,
65
+ bindtransitionstart: _bindtransitionstart,
66
+ bindtransitionend: _bindtransitionend,
67
+ bindtap: _bindtap,
68
+ ...nativeProps
69
+ } = props as Props & NativeLifecycleHandlers;
70
+
71
+ return nativeProps as Props;
72
+ }
73
+
74
+ function useAlertDialogTransition(transition: boolean | undefined) {
75
+ const skipAnimation = useProps()?.skipAnimation === true;
76
+
77
+ return skipAnimation ? false : (transition ?? true);
78
+ }
79
+
80
+ ////////////////////////////////////////////////////////////////////////////////////
81
+ // Root
82
+ ////////////////////////////////////////////////////////////////////////////////////
83
+
84
+ export interface AlertDialogRootProps
85
+ extends AlertDialogVariantProps,
86
+ Omit<DialogPrimitiveRootProps, "show" | "defaultShow" | "onShowChange"> {
87
+ /** Whether the alert dialog is open (controlled mode). */
88
+ open?: boolean;
89
+ /** Whether the alert dialog is open by default (uncontrolled mode). */
90
+ defaultOpen?: boolean;
91
+ /** Called when the alert dialog's open state changes. */
92
+ onOpenChange?: (open: boolean) => void;
93
+ }
94
+
95
+ /**
96
+ * @platform Lynx — wraps `@lynx-js/lynx-ui-dialog` as an alert dialog.
97
+ * Refs, `asChild`, focus management, Escape-key dismissal, and close reasons are
98
+ * not supported by the Lynx primitive.
99
+ */
100
+ export const AlertDialogRoot = forwardRef<never, AlertDialogRootProps>((props, _ref) => {
101
+ const [variantProps, restProps] = alertDialog.splitVariantProps(props);
102
+ const { children, open, defaultOpen, onOpenChange, ...nativeProps } = restProps;
103
+ const classNames = alertDialog(variantProps);
104
+
105
+ return (
106
+ <ClassNamesProvider value={classNames}>
107
+ <PropsProvider value={variantProps}>
108
+ <DialogRootPrimitive
109
+ {...nativeProps}
110
+ show={open}
111
+ defaultShow={defaultOpen}
112
+ onShowChange={onOpenChange}
113
+ >
114
+ {children}
115
+ </DialogRootPrimitive>
116
+ </PropsProvider>
117
+ </ClassNamesProvider>
118
+ );
119
+ }) as AlertDialogComponent<AlertDialogRootProps>;
120
+ AlertDialogRoot.displayName = "AlertDialogRoot";
121
+
122
+ ////////////////////////////////////////////////////////////////////////////////////
123
+ // Trigger
124
+ ////////////////////////////////////////////////////////////////////////////////////
125
+
126
+ export interface AlertDialogTriggerProps extends DialogPrimitiveTriggerProps {}
127
+
128
+ /** @platform Lynx — `asChild` and refs are unsupported. */
129
+ export const AlertDialogTrigger = forwardRef<never, AlertDialogTriggerProps>((props, _ref) => {
130
+ const { children, transition, ...nativeProps } = props;
131
+ const resolvedTransition = useAlertDialogTransition(transition);
132
+
133
+ return (
134
+ <DialogTriggerPrimitive {...nativeProps} transition={resolvedTransition}>
135
+ {children}
136
+ </DialogTriggerPrimitive>
137
+ );
138
+ }) as AlertDialogComponent<AlertDialogTriggerProps>;
139
+ AlertDialogTrigger.displayName = "AlertDialogTrigger";
140
+
141
+ ////////////////////////////////////////////////////////////////////////////////////
142
+ // Positioner
143
+ ////////////////////////////////////////////////////////////////////////////////////
144
+
145
+ export interface AlertDialogPositionerProps extends DialogPrimitiveViewProps {}
146
+
147
+ /** @platform Lynx — maps to `DialogView`; refs are unsupported. */
148
+ export const AlertDialogPositioner = forwardRef<never, AlertDialogPositionerProps>(
149
+ (props, _ref) => {
150
+ const { children, className, container, style, transition, ...nativeProps } = props;
151
+ const classNames = useClassNames();
152
+ const resolvedTransition = useAlertDialogTransition(transition);
153
+ const positionerStyle = container ? { width: "100%", height: "100%", ...style } : style;
154
+
155
+ return (
156
+ <DialogViewPrimitive
157
+ {...nativeProps}
158
+ container={container}
159
+ className={clsx(classNames.positioner, className)}
160
+ style={positionerStyle}
161
+ transition={resolvedTransition}
162
+ >
163
+ {children}
164
+ </DialogViewPrimitive>
165
+ );
166
+ },
167
+ ) as AlertDialogComponent<AlertDialogPositionerProps>;
168
+ AlertDialogPositioner.displayName = "AlertDialogPositioner";
169
+
170
+ ////////////////////////////////////////////////////////////////////////////////////
171
+ // Backdrop
172
+ ////////////////////////////////////////////////////////////////////////////////////
173
+
174
+ export interface AlertDialogBackdropProps extends DialogPrimitiveBackdropProps {}
175
+
176
+ /**
177
+ * @platform Lynx — refs are unsupported. Native lifecycle handlers in
178
+ * `dialogBackdropProps` are reserved by the headless primitive and are omitted.
179
+ * Alert dialogs do not dismiss when the backdrop is tapped by default.
180
+ */
181
+ export const AlertDialogBackdrop = forwardRef<never, AlertDialogBackdropProps>((props, _ref) => {
182
+ const {
183
+ children,
184
+ className,
185
+ transition,
186
+ clickToClose = false,
187
+ dialogBackdropProps,
188
+ ...nativeProps
189
+ } = props;
190
+ const classNames = useClassNames();
191
+ const resolvedTransition = useAlertDialogTransition(transition);
192
+
193
+ return (
194
+ <DialogBackdropPrimitive
195
+ {...nativeProps}
196
+ className={clsx(classNames.backdrop, className)}
197
+ transition={resolvedTransition}
198
+ clickToClose={clickToClose}
199
+ dialogBackdropProps={omitHeadlessLifecycleHandlers(dialogBackdropProps)}
200
+ >
201
+ {children}
202
+ </DialogBackdropPrimitive>
203
+ );
204
+ }) as AlertDialogComponent<AlertDialogBackdropProps>;
205
+ AlertDialogBackdrop.displayName = "AlertDialogBackdrop";
206
+
207
+ ////////////////////////////////////////////////////////////////////////////////////
208
+ // Content
209
+ ////////////////////////////////////////////////////////////////////////////////////
210
+
211
+ export interface AlertDialogContentProps
212
+ extends DialogPrimitiveContentProps,
213
+ LynxAccessibilityProps {}
214
+
215
+ /**
216
+ * @platform Lynx — refs are unsupported. Native lifecycle handlers in
217
+ * `dialogContentProps` are reserved by the headless primitive and are omitted.
218
+ */
219
+ export const AlertDialogContent = forwardRef<never, AlertDialogContentProps>((props, _ref) => {
220
+ const {
221
+ children,
222
+ className,
223
+ transition,
224
+ dialogContentProps,
225
+ "accessibility-element": accessibilityElement = true,
226
+ "accessibility-role-description": accessibilityRoleDescription = "alertdialog",
227
+ ...nativeProps
228
+ } = props;
229
+ const classNames = useClassNames();
230
+ const resolvedTransition = useAlertDialogTransition(transition);
231
+ const resolvedDialogContentProps = {
232
+ "accessibility-element": accessibilityElement,
233
+ "accessibility-role-description": accessibilityRoleDescription,
234
+ ...omitHeadlessLifecycleHandlers(dialogContentProps),
235
+ };
236
+
237
+ return (
238
+ <DialogContentPrimitive
239
+ {...nativeProps}
240
+ className={clsx(classNames.content, className)}
241
+ transition={resolvedTransition}
242
+ dialogContentProps={resolvedDialogContentProps}
243
+ >
244
+ {children}
245
+ </DialogContentPrimitive>
246
+ );
247
+ }) as AlertDialogComponent<AlertDialogContentProps>;
248
+ AlertDialogContent.displayName = "AlertDialogContent";
249
+
250
+ ////////////////////////////////////////////////////////////////////////////////////
251
+ // Local slots
252
+ ////////////////////////////////////////////////////////////////////////////////////
253
+
254
+ export interface AlertDialogHeaderProps extends StyleProps, LynxStyledElementProps {}
255
+
256
+ export const AlertDialogHeader: LynxForwardRefComponent<unknown, AlertDialogHeaderProps> =
257
+ forwardRef<unknown, AlertDialogHeaderProps>((props, ref) => {
258
+ const { style, restProps } = useStyleProps(props);
259
+ const { children, className, ...nativeProps } = restProps;
260
+ const classNames = useClassNames();
261
+
262
+ return (
263
+ <view
264
+ {...(ref ? ({ ref: ref as LynxViewRef } as Record<string, unknown>) : {})}
265
+ {...nativeProps}
266
+ className={clsx(classNames.header, className)}
267
+ style={style as never}
268
+ >
269
+ {children}
270
+ </view>
271
+ );
272
+ });
273
+ AlertDialogHeader.displayName = "AlertDialogHeader";
274
+
275
+ export interface AlertDialogTitleProps
276
+ extends StyleProps,
277
+ LynxStyledElementProps,
278
+ LynxAccessibilityProps {}
279
+
280
+ export const AlertDialogTitle: LynxForwardRefComponent<unknown, AlertDialogTitleProps> = forwardRef<
281
+ unknown,
282
+ AlertDialogTitleProps
283
+ >((props, ref) => {
284
+ const { style, restProps } = useStyleProps(props);
285
+ const {
286
+ children,
287
+ className,
288
+ "accessibility-heading": accessibilityHeading = true,
289
+ ...nativeProps
290
+ } = restProps;
291
+ const classNames = useClassNames();
292
+
293
+ return (
294
+ <text
295
+ {...(ref ? ({ ref: ref as LynxTextRef } as Record<string, unknown>) : {})}
296
+ {...nativeProps}
297
+ className={clsx(classNames.title, className)}
298
+ style={style as never}
299
+ accessibility-heading={accessibilityHeading}
300
+ >
301
+ {children}
302
+ </text>
303
+ );
304
+ });
305
+ AlertDialogTitle.displayName = "AlertDialogTitle";
306
+
307
+ export interface AlertDialogDescriptionProps
308
+ extends StyleProps,
309
+ LynxStyledElementProps,
310
+ LynxAccessibilityProps {}
311
+
312
+ export const AlertDialogDescription: LynxForwardRefComponent<unknown, AlertDialogDescriptionProps> =
313
+ forwardRef<unknown, AlertDialogDescriptionProps>((props, ref) => {
314
+ const { style, restProps } = useStyleProps(props);
315
+ const { children, className, ...nativeProps } = restProps;
316
+ const classNames = useClassNames();
317
+
318
+ return (
319
+ <text
320
+ {...(ref ? ({ ref: ref as LynxTextRef } as Record<string, unknown>) : {})}
321
+ {...nativeProps}
322
+ className={clsx(classNames.description, className)}
323
+ style={style as never}
324
+ >
325
+ {children}
326
+ </text>
327
+ );
328
+ });
329
+ AlertDialogDescription.displayName = "AlertDialogDescription";
330
+
331
+ export interface AlertDialogFooterProps extends StyleProps, LynxStyledElementProps {}
332
+
333
+ export const AlertDialogFooter: LynxForwardRefComponent<unknown, AlertDialogFooterProps> =
334
+ forwardRef<unknown, AlertDialogFooterProps>((props, ref) => {
335
+ const { style, restProps } = useStyleProps(props);
336
+ const { children, className, ...nativeProps } = restProps;
337
+ const classNames = useClassNames();
338
+
339
+ return (
340
+ <view
341
+ {...(ref ? ({ ref: ref as LynxViewRef } as Record<string, unknown>) : {})}
342
+ {...nativeProps}
343
+ className={clsx(classNames.footer, className)}
344
+ style={style as never}
345
+ >
346
+ {children}
347
+ </view>
348
+ );
349
+ });
350
+ AlertDialogFooter.displayName = "AlertDialogFooter";
351
+
352
+ ////////////////////////////////////////////////////////////////////////////////////
353
+ // Action
354
+ ////////////////////////////////////////////////////////////////////////////////////
355
+
356
+ export interface AlertDialogActionProps extends DialogPrimitiveCloseProps {}
357
+
358
+ /** @platform Lynx — maps to `DialogClose`; `asChild` and refs are unsupported. */
359
+ export const AlertDialogAction = forwardRef<never, AlertDialogActionProps>((props, _ref) => {
360
+ const { children, className, transition, ...nativeProps } = props;
361
+ const classNames = useClassNames();
362
+ const resolvedTransition = useAlertDialogTransition(transition);
363
+
364
+ return (
365
+ <DialogClosePrimitive
366
+ {...nativeProps}
367
+ className={clsx(classNames.action, className)}
368
+ transition={resolvedTransition}
369
+ >
370
+ {children}
371
+ </DialogClosePrimitive>
372
+ );
373
+ }) as AlertDialogComponent<AlertDialogActionProps>;
374
+ AlertDialogAction.displayName = "AlertDialogAction";
@@ -0,0 +1,24 @@
1
+ export {
2
+ AlertDialogAction,
3
+ type AlertDialogActionProps,
4
+ AlertDialogBackdrop,
5
+ type AlertDialogBackdropProps,
6
+ AlertDialogContent,
7
+ type AlertDialogContentProps,
8
+ AlertDialogDescription,
9
+ type AlertDialogDescriptionProps,
10
+ AlertDialogFooter,
11
+ type AlertDialogFooterProps,
12
+ AlertDialogHeader,
13
+ type AlertDialogHeaderProps,
14
+ AlertDialogPositioner,
15
+ type AlertDialogPositionerProps,
16
+ AlertDialogRoot,
17
+ type AlertDialogRootProps,
18
+ AlertDialogTitle,
19
+ type AlertDialogTitleProps,
20
+ AlertDialogTrigger,
21
+ type AlertDialogTriggerProps,
22
+ } from "./AlertDialog";
23
+
24
+ export * as AlertDialog from "./AlertDialog.namespace";
@@ -7,6 +7,7 @@ export {
7
7
  AppBarSlot as Slot,
8
8
  AppBarSubtitle as Subtitle,
9
9
  AppBarTitle as Title,
10
+ type AppBarEdge as Edge,
10
11
  type AppBarIconButtonProps as IconButtonProps,
11
12
  type AppBarLeftProps as LeftProps,
12
13
  type AppBarMainProps as MainProps,