@seed-design/lynx-react 0.7.0 → 0.8.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 (245) 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 +46 -10
  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/index.d.ts +1 -1
  17. package/lib/components/AppBar/index.d.ts.map +1 -1
  18. package/lib/components/AttachmentDisplay/AttachmentDisplay.d.ts +182 -0
  19. package/lib/components/AttachmentDisplay/AttachmentDisplay.d.ts.map +1 -0
  20. package/lib/components/AttachmentDisplay/AttachmentDisplay.jsx +444 -0
  21. package/lib/components/AttachmentDisplay/index.d.ts +2 -0
  22. package/lib/components/AttachmentDisplay/index.d.ts.map +1 -0
  23. package/lib/components/AttachmentInput/AttachmentInput.d.ts +179 -0
  24. package/lib/components/AttachmentInput/AttachmentInput.d.ts.map +1 -0
  25. package/lib/components/AttachmentInput/AttachmentInput.jsx +520 -0
  26. package/lib/components/AttachmentInput/index.d.ts +2 -0
  27. package/lib/components/AttachmentInput/index.d.ts.map +1 -0
  28. package/lib/components/BottomSheet/BottomSheet.d.ts +1 -1
  29. package/lib/components/BottomSheet/BottomSheet.d.ts.map +1 -1
  30. package/lib/components/BottomSheet/BottomSheet.jsx +1 -7
  31. package/lib/components/Callout/Callout.jsx +2 -2
  32. package/lib/components/Checkbox/Checkbox.jsx +2 -2
  33. package/lib/components/Chip/Chip.jsx +2 -2
  34. package/lib/components/ChipTabs/ChipTabs.d.ts +41 -0
  35. package/lib/components/ChipTabs/ChipTabs.d.ts.map +1 -0
  36. package/lib/components/ChipTabs/ChipTabs.jsx +39 -0
  37. package/lib/components/ChipTabs/ChipTabs.namespace.d.ts +2 -0
  38. package/lib/components/ChipTabs/ChipTabs.namespace.d.ts.map +1 -0
  39. package/lib/components/ChipTabs/ChipTabs.namespace.js +13 -0
  40. package/lib/components/ChipTabs/index.d.ts +3 -0
  41. package/lib/components/ChipTabs/index.d.ts.map +1 -0
  42. package/lib/components/ContextualFloatingButton/ContextualFloatingButton.d.ts +18 -0
  43. package/lib/components/ContextualFloatingButton/ContextualFloatingButton.d.ts.map +1 -0
  44. package/lib/components/ContextualFloatingButton/ContextualFloatingButton.jsx +113 -0
  45. package/lib/components/ContextualFloatingButton/index.d.ts +2 -0
  46. package/lib/components/ContextualFloatingButton/index.d.ts.map +1 -0
  47. package/lib/components/Dialog/Dialog.d.ts +87 -0
  48. package/lib/components/Dialog/Dialog.d.ts.map +1 -0
  49. package/lib/components/Dialog/Dialog.jsx +147 -0
  50. package/lib/components/Dialog/Dialog.namespace.d.ts +2 -0
  51. package/lib/components/Dialog/Dialog.namespace.d.ts.map +1 -0
  52. package/lib/components/Dialog/Dialog.namespace.js +18 -0
  53. package/lib/components/Dialog/index.d.ts +3 -0
  54. package/lib/components/Dialog/index.d.ts.map +1 -0
  55. package/lib/components/FloatingActionButton/FloatingActionButton.d.ts +23 -0
  56. package/lib/components/FloatingActionButton/FloatingActionButton.d.ts.map +1 -0
  57. package/lib/components/FloatingActionButton/FloatingActionButton.jsx +76 -0
  58. package/lib/components/FloatingActionButton/FloatingActionButton.namespace.d.ts +2 -0
  59. package/lib/components/FloatingActionButton/FloatingActionButton.namespace.d.ts.map +1 -0
  60. package/lib/components/FloatingActionButton/FloatingActionButton.namespace.js +10 -0
  61. package/lib/components/FloatingActionButton/index.d.ts +3 -0
  62. package/lib/components/FloatingActionButton/index.d.ts.map +1 -0
  63. package/lib/components/HelpBubble/HelpBubble.d.ts +67 -0
  64. package/lib/components/HelpBubble/HelpBubble.d.ts.map +1 -0
  65. package/lib/components/HelpBubble/HelpBubble.jsx +600 -0
  66. package/lib/components/HelpBubble/HelpBubble.namespace.d.ts +2 -0
  67. package/lib/components/HelpBubble/HelpBubble.namespace.d.ts.map +1 -0
  68. package/lib/components/HelpBubble/HelpBubble.namespace.js +18 -0
  69. package/lib/components/HelpBubble/index.d.ts +3 -0
  70. package/lib/components/HelpBubble/index.d.ts.map +1 -0
  71. package/lib/components/Icon/Icon.d.ts +1 -0
  72. package/lib/components/Icon/Icon.d.ts.map +1 -1
  73. package/lib/components/Icon/Icon.jsx +3 -2
  74. package/lib/components/IdentityPlaceholder/IdentityPlaceholder.d.ts +28 -0
  75. package/lib/components/IdentityPlaceholder/IdentityPlaceholder.d.ts.map +1 -0
  76. package/lib/components/IdentityPlaceholder/IdentityPlaceholder.jsx +37 -0
  77. package/lib/components/IdentityPlaceholder/IdentityPlaceholder.namespace.d.ts +2 -0
  78. package/lib/components/IdentityPlaceholder/IdentityPlaceholder.namespace.d.ts.map +1 -0
  79. package/lib/components/IdentityPlaceholder/IdentityPlaceholder.namespace.js +9 -0
  80. package/lib/components/IdentityPlaceholder/identity-placeholder-business.js +4 -0
  81. package/lib/components/IdentityPlaceholder/identity-placeholder-person.js +4 -0
  82. package/lib/components/IdentityPlaceholder/index.d.ts +3 -0
  83. package/lib/components/IdentityPlaceholder/index.d.ts.map +1 -0
  84. package/lib/components/InputButton/InputButton.d.ts +2 -0
  85. package/lib/components/InputButton/InputButton.d.ts.map +1 -1
  86. package/lib/components/InputButton/InputButton.jsx +40 -8
  87. package/lib/components/List/List.d.ts +1 -1
  88. package/lib/components/List/List.d.ts.map +1 -1
  89. package/lib/components/List/List.jsx +26 -12
  90. package/lib/components/Menu/Menu.d.ts.map +1 -1
  91. package/lib/components/Menu/Menu.jsx +15 -5
  92. package/lib/components/PageBanner/PageBanner.d.ts +3 -0
  93. package/lib/components/PageBanner/PageBanner.d.ts.map +1 -1
  94. package/lib/components/PageBanner/PageBanner.jsx +49 -11
  95. package/lib/components/QuantityPicker/QuantityPicker.d.ts +53 -0
  96. package/lib/components/QuantityPicker/QuantityPicker.d.ts.map +1 -0
  97. package/lib/components/QuantityPicker/QuantityPicker.jsx +282 -0
  98. package/lib/components/QuantityPicker/QuantityPicker.namespace.d.ts +2 -0
  99. package/lib/components/QuantityPicker/QuantityPicker.namespace.d.ts.map +1 -0
  100. package/lib/components/QuantityPicker/QuantityPicker.namespace.js +11 -0
  101. package/lib/components/QuantityPicker/index.d.ts +3 -0
  102. package/lib/components/QuantityPicker/index.d.ts.map +1 -0
  103. package/lib/components/RadioGroup/RadioGroup.jsx +2 -2
  104. package/lib/components/ReactionButton/ReactionButton.d.ts +1 -1
  105. package/lib/components/ReactionButton/ReactionButton.d.ts.map +1 -1
  106. package/lib/components/ReactionButton/ReactionButton.jsx +22 -13
  107. package/lib/components/ScrollFog/ScrollFog.d.ts +41 -0
  108. package/lib/components/ScrollFog/ScrollFog.d.ts.map +1 -0
  109. package/lib/components/ScrollFog/ScrollFog.jsx +65 -0
  110. package/lib/components/ScrollFog/index.d.ts +2 -0
  111. package/lib/components/ScrollFog/index.d.ts.map +1 -0
  112. package/lib/components/SegmentedControl/SegmentedControl.jsx +2 -2
  113. package/lib/components/Select/Select.d.ts +112 -0
  114. package/lib/components/Select/Select.d.ts.map +1 -0
  115. package/lib/components/Select/Select.jsx +885 -0
  116. package/lib/components/Select/Select.namespace.d.ts +2 -0
  117. package/lib/components/Select/Select.namespace.d.ts.map +1 -0
  118. package/lib/components/Select/Select.namespace.js +23 -0
  119. package/lib/components/Select/index.d.ts +3 -0
  120. package/lib/components/Select/index.d.ts.map +1 -0
  121. package/lib/components/Skeleton/Skeleton.d.ts +15 -0
  122. package/lib/components/Skeleton/Skeleton.d.ts.map +1 -0
  123. package/lib/components/Skeleton/Skeleton.jsx +18 -0
  124. package/lib/components/Skeleton/index.d.ts +2 -0
  125. package/lib/components/Skeleton/index.d.ts.map +1 -0
  126. package/lib/components/Slider/Slider.d.ts +101 -0
  127. package/lib/components/Slider/Slider.d.ts.map +1 -0
  128. package/lib/components/Slider/Slider.jsx +573 -0
  129. package/lib/components/Slider/Slider.namespace.d.ts +2 -0
  130. package/lib/components/Slider/Slider.namespace.d.ts.map +1 -0
  131. package/lib/components/Slider/Slider.namespace.js +19 -0
  132. package/lib/components/Slider/Slider.utils.d.ts +19 -0
  133. package/lib/components/Slider/Slider.utils.d.ts.map +1 -0
  134. package/lib/components/Slider/Slider.utils.js +106 -0
  135. package/lib/components/Slider/index.d.ts +3 -0
  136. package/lib/components/Slider/index.d.ts.map +1 -0
  137. package/lib/components/SwipeableMenuSheet/SwipeableMenuSheet.d.ts.map +1 -1
  138. package/lib/components/SwipeableMenuSheet/SwipeableMenuSheet.jsx +22 -8
  139. package/lib/components/Switch/Switch.d.ts.map +1 -1
  140. package/lib/components/Switch/Switch.jsx +5 -3
  141. package/lib/components/Tabs/Tabs.d.ts +34 -2
  142. package/lib/components/Tabs/Tabs.d.ts.map +1 -1
  143. package/lib/components/Tabs/Tabs.jsx +186 -56
  144. package/lib/components/Tabs/Tabs.utils.d.ts +14 -1
  145. package/lib/components/Tabs/Tabs.utils.d.ts.map +1 -1
  146. package/lib/components/Tabs/Tabs.utils.js +24 -3
  147. package/lib/components/Tabs/index.d.ts +1 -1
  148. package/lib/components/Tabs/index.d.ts.map +1 -1
  149. package/lib/components/index.d.ts +14 -0
  150. package/lib/components/index.d.ts.map +1 -1
  151. package/lib/hooks/useControllableState.d.ts +1 -14
  152. package/lib/hooks/useControllableState.d.ts.map +1 -1
  153. package/lib/hooks/usePressTap.d.ts +1 -27
  154. package/lib/hooks/usePressTap.d.ts.map +1 -1
  155. package/lib/hooks/useScaleFeedback.d.ts +1 -1
  156. package/lib/hooks/useScaleFeedback.js +1 -1
  157. package/lib/index.js +29 -6
  158. package/lib/{hooks/useControllableState.js → packages/lynx-react-headless/use-controllable-state/lib/index.js} +2 -3
  159. package/lib/{hooks/usePressTap.js → packages/lynx-react-headless/use-press-tap/lib/index.js} +13 -10
  160. package/lib/types.d.ts +1 -0
  161. package/lib/types.d.ts.map +1 -1
  162. package/package.json +9 -5
  163. package/src/components/ActionButton/ActionButton.test.tsx +7 -7
  164. package/src/components/AlertDialog/AlertDialog.namespace.ts +22 -0
  165. package/src/components/AlertDialog/AlertDialog.test.tsx +226 -0
  166. package/src/components/AlertDialog/AlertDialog.tsx +374 -0
  167. package/src/components/AlertDialog/index.ts +24 -0
  168. package/src/components/AppBar/AppBar.namespace.ts +1 -0
  169. package/src/components/AppBar/AppBar.test.tsx +257 -0
  170. package/src/components/AppBar/AppBar.tsx +109 -14
  171. package/src/components/AppBar/index.ts +1 -0
  172. package/src/components/AttachmentDisplay/AttachmentDisplay.tsx +886 -0
  173. package/src/components/AttachmentDisplay/index.ts +48 -0
  174. package/src/components/AttachmentInput/AttachmentInput.tsx +1001 -0
  175. package/src/components/AttachmentInput/index.ts +49 -0
  176. package/src/components/BottomSheet/BottomSheet.test.tsx +22 -7
  177. package/src/components/BottomSheet/BottomSheet.tsx +1 -19
  178. package/src/components/ChipTabs/ChipTabs.namespace.ts +14 -0
  179. package/src/components/ChipTabs/ChipTabs.tsx +119 -0
  180. package/src/components/ChipTabs/index.ts +16 -0
  181. package/src/components/ContextualFloatingButton/ContextualFloatingButton.test.tsx +63 -0
  182. package/src/components/ContextualFloatingButton/ContextualFloatingButton.tsx +232 -0
  183. package/src/components/ContextualFloatingButton/index.ts +4 -0
  184. package/src/components/Dialog/Dialog.namespace.ts +24 -0
  185. package/src/components/Dialog/Dialog.test.tsx +172 -0
  186. package/src/components/Dialog/Dialog.tsx +373 -0
  187. package/src/components/Dialog/index.ts +26 -0
  188. package/src/components/FloatingActionButton/FloatingActionButton.namespace.ts +8 -0
  189. package/src/components/FloatingActionButton/FloatingActionButton.test.tsx +59 -0
  190. package/src/components/FloatingActionButton/FloatingActionButton.tsx +207 -0
  191. package/src/components/FloatingActionButton/index.ts +10 -0
  192. package/src/components/HelpBubble/HelpBubble.namespace.ts +24 -0
  193. package/src/components/HelpBubble/HelpBubble.tsx +998 -0
  194. package/src/components/HelpBubble/index.ts +26 -0
  195. package/src/components/Icon/Icon.test.tsx +57 -5
  196. package/src/components/Icon/Icon.tsx +16 -2
  197. package/src/components/IdentityPlaceholder/IdentityPlaceholder.namespace.ts +6 -0
  198. package/src/components/IdentityPlaceholder/IdentityPlaceholder.tsx +103 -0
  199. package/src/components/IdentityPlaceholder/assets.d.ts +4 -0
  200. package/src/components/IdentityPlaceholder/identity-placeholder-business.webp +0 -0
  201. package/src/components/IdentityPlaceholder/identity-placeholder-person.webp +0 -0
  202. package/src/components/IdentityPlaceholder/index.ts +8 -0
  203. package/src/components/InputButton/InputButton.test.tsx +128 -1
  204. package/src/components/InputButton/InputButton.tsx +60 -9
  205. package/src/components/List/List.test.tsx +54 -2
  206. package/src/components/List/List.tsx +43 -10
  207. package/src/components/Menu/Menu.tsx +14 -4
  208. package/src/components/Menu/__tests__/Menu.test.tsx +34 -0
  209. package/src/components/PageBanner/PageBanner.test.tsx +110 -3
  210. package/src/components/PageBanner/PageBanner.tsx +83 -19
  211. package/src/components/QuantityPicker/QuantityPicker.namespace.ts +10 -0
  212. package/src/components/QuantityPicker/QuantityPicker.test.tsx +235 -0
  213. package/src/components/QuantityPicker/QuantityPicker.tsx +605 -0
  214. package/src/components/QuantityPicker/index.ts +14 -0
  215. package/src/components/ReactionButton/ReactionButton.feedback.test.tsx +50 -0
  216. package/src/components/ReactionButton/ReactionButton.test.tsx +6 -4
  217. package/src/components/ReactionButton/ReactionButton.tsx +20 -12
  218. package/src/components/ScrollFog/ScrollFog.test.tsx +222 -0
  219. package/src/components/ScrollFog/ScrollFog.tsx +172 -0
  220. package/src/components/ScrollFog/index.ts +1 -0
  221. package/src/components/Select/Select.namespace.ts +34 -0
  222. package/src/components/Select/Select.test.tsx +297 -0
  223. package/src/components/Select/Select.tsx +1483 -0
  224. package/src/components/Select/index.ts +39 -0
  225. package/src/components/Skeleton/Skeleton.test.tsx +64 -0
  226. package/src/components/Skeleton/Skeleton.tsx +45 -0
  227. package/src/components/Skeleton/index.ts +1 -0
  228. package/src/components/Slider/Slider.namespace.ts +26 -0
  229. package/src/components/Slider/Slider.test.tsx +260 -0
  230. package/src/components/Slider/Slider.tsx +897 -0
  231. package/src/components/Slider/Slider.utils.ts +167 -0
  232. package/src/components/Slider/index.ts +30 -0
  233. package/src/components/SwipeableMenuSheet/SwipeableMenuSheet.test.tsx +21 -1
  234. package/src/components/SwipeableMenuSheet/SwipeableMenuSheet.tsx +30 -7
  235. package/src/components/Switch/Switch.tsx +14 -13
  236. package/src/components/Tabs/Tabs.test.tsx +218 -1
  237. package/src/components/Tabs/Tabs.tsx +346 -75
  238. package/src/components/Tabs/Tabs.utils.ts +51 -1
  239. package/src/components/Tabs/index.ts +17 -1
  240. package/src/components/index.ts +14 -0
  241. package/src/hooks/useControllableState.ts +1 -43
  242. package/src/hooks/usePressTap.test.ts +23 -11
  243. package/src/hooks/usePressTap.ts +1 -60
  244. package/src/hooks/useScaleFeedback.ts +1 -1
  245. package/src/types.ts +1 -0
@@ -0,0 +1,886 @@
1
+ import * as React from "@lynx-js/react";
2
+ import { isValidElement } from "@lynx-js/react";
3
+ import type { IntrinsicElements, NodesRef } from "@lynx-js/types";
4
+ import {
5
+ attachmentInput,
6
+ type AttachmentInputVariantProps,
7
+ } from "@seed-design/lynx-css/recipes/attachment-input";
8
+ import {
9
+ attachmentInputItem,
10
+ type AttachmentInputItemVariantProps,
11
+ } from "@seed-design/lynx-css/recipes/attachment-input-item";
12
+ import {
13
+ attachmentInputTrigger,
14
+ type AttachmentInputTriggerVariantProps,
15
+ } from "@seed-design/lynx-css/recipes/attachment-input-trigger";
16
+ import { fieldLabel, type FieldLabelVariantProps } from "@seed-design/lynx-css/recipes/field-label";
17
+ import type {
18
+ LynxAccessibilityProps,
19
+ LynxIconElementProps,
20
+ LynxPressableProps,
21
+ LynxStyledElementProps,
22
+ } from "../../types";
23
+ import { useControllableState } from "../../hooks/useControllableState";
24
+ import { usePressTap } from "../../hooks/usePressTap";
25
+ import { createSlotRecipeContext } from "../../utils/create-slot-recipe-context";
26
+ import { mergeProps } from "../../utils/merge-props";
27
+ import { toArray } from "../../utils/children";
28
+ import clsx from "clsx";
29
+ import { IconSlotProvider, InternalIcon } from "../Icon/Icon";
30
+
31
+ export type AttachmentDisplayStatusDetails =
32
+ | { status: "pending" }
33
+ | { status: "uploading"; progress?: number }
34
+ | { status: "success" }
35
+ | { status: "error" };
36
+
37
+ export type AttachmentDisplayEntry = {
38
+ id: string;
39
+ thumbnailUrl?: string;
40
+ name?: string;
41
+ type?: string;
42
+ size?: number;
43
+ } & AttachmentDisplayStatusDetails;
44
+
45
+ export interface AttachmentDisplayProps {
46
+ entries?: AttachmentDisplayEntry[];
47
+ defaultEntries?: AttachmentDisplayEntry[];
48
+ onEntriesChange?: (entries: AttachmentDisplayEntry[]) => void;
49
+ disabled?: boolean;
50
+ invalid?: boolean;
51
+ readOnly?: boolean;
52
+ required?: boolean;
53
+ maxEntries?: number;
54
+ onTriggerTap?: (helpers: {
55
+ addEntries: (entries: AttachmentDisplayEntry[]) => void;
56
+ updateEntryStatus: (id: string, details: AttachmentDisplayStatusDetails) => void;
57
+ }) => void;
58
+ }
59
+
60
+ interface AttachmentDisplayStateProps {
61
+ "data-disabled": boolean;
62
+ "data-readonly": boolean;
63
+ "data-invalid": boolean;
64
+ "data-required": boolean;
65
+ }
66
+
67
+ interface AttachmentDisplayContextValue {
68
+ entries: AttachmentDisplayEntry[];
69
+ currentEntryCount: number;
70
+ disabled: boolean;
71
+ invalid: boolean;
72
+ readOnly: boolean;
73
+ required: boolean;
74
+ maxEntries: number;
75
+ triggerDisabled: boolean;
76
+ stateProps: AttachmentDisplayStateProps;
77
+ onTriggerTap?: AttachmentDisplayProps["onTriggerTap"];
78
+ addEntries: (entries: AttachmentDisplayEntry[]) => void;
79
+ removeEntry: (id: string) => void;
80
+ reorderEntry: (fromIndex: number, toIndex: number) => void;
81
+ clearEntries: () => void;
82
+ updateEntryStatus: (id: string, details: AttachmentDisplayStatusDetails) => void;
83
+ }
84
+
85
+ type AttachmentDisplayItemContextValue = AttachmentDisplayEntry & {
86
+ imageProps?: { src: string; alt?: string };
87
+ };
88
+
89
+ type NativeScrollViewProps = Omit<
90
+ IntrinsicElements["scroll-view"],
91
+ "children" | "className" | "style"
92
+ >;
93
+
94
+ const { ClassNamesProvider: RootClassNamesProvider, useClassNames: useRootClassNames } =
95
+ createSlotRecipeContext(attachmentInput);
96
+ const { ClassNamesProvider: TriggerClassNamesProvider, useClassNames: useTriggerClassNames } =
97
+ createSlotRecipeContext(attachmentInputTrigger);
98
+ const { ClassNamesProvider: ItemClassNamesProvider, useClassNames: useItemClassNames } =
99
+ createSlotRecipeContext(attachmentInputItem);
100
+ const { ClassNamesProvider: LabelClassNamesProvider, useClassNames: useLabelClassNames } =
101
+ createSlotRecipeContext(fieldLabel);
102
+
103
+ const DisplayContextObject = React.createContext<AttachmentDisplayContextValue | null>(null);
104
+ const DisplayItemContextObject = React.createContext<AttachmentDisplayItemContextValue | null>(
105
+ null,
106
+ );
107
+
108
+ export function useAttachmentDisplayContext() {
109
+ const context = React.useContext(DisplayContextObject);
110
+ if (!context)
111
+ throw new Error("AttachmentDisplay components must be used within AttachmentDisplay.Root");
112
+ return context;
113
+ }
114
+
115
+ export function useAttachmentDisplayItemContext() {
116
+ const context = React.useContext(DisplayItemContextObject);
117
+ if (!context)
118
+ throw new Error("AttachmentDisplay item components must be used within AttachmentDisplay.Item");
119
+ return context;
120
+ }
121
+
122
+ function withUpdatedStatus(
123
+ entry: AttachmentDisplayEntry,
124
+ details: AttachmentDisplayStatusDetails,
125
+ ): AttachmentDisplayEntry {
126
+ const metadata = {
127
+ id: entry.id,
128
+ thumbnailUrl: entry.thumbnailUrl,
129
+ name: entry.name,
130
+ type: entry.type,
131
+ size: entry.size,
132
+ };
133
+ return details.status === "uploading"
134
+ ? { ...metadata, status: details.status, progress: details.progress }
135
+ : { ...metadata, status: details.status };
136
+ }
137
+
138
+ export function useAttachmentDisplay(props: AttachmentDisplayProps = {}) {
139
+ const {
140
+ entries: value,
141
+ defaultEntries = [],
142
+ onEntriesChange,
143
+ disabled = false,
144
+ invalid = false,
145
+ readOnly = false,
146
+ required = false,
147
+ maxEntries = 1,
148
+ onTriggerTap,
149
+ } = props;
150
+ const [entries, setEntries] = useControllableState<AttachmentDisplayEntry[]>({
151
+ value,
152
+ defaultValue: defaultEntries,
153
+ onChange: onEntriesChange,
154
+ });
155
+ const currentEntries = entries ?? [];
156
+ const entriesRef = React.useRef(currentEntries);
157
+ entriesRef.current = currentEntries;
158
+ const optionsRef = React.useRef({ disabled, readOnly, maxEntries, onTriggerTap });
159
+ optionsRef.current = { disabled, readOnly, maxEntries, onTriggerTap };
160
+ const triggerDisabled = disabled || readOnly || currentEntries.length >= maxEntries;
161
+
162
+ const addEntries = React.useCallback(
163
+ (incoming: AttachmentDisplayEntry[]) => {
164
+ const options = optionsRef.current;
165
+ if (options.disabled || options.readOnly || incoming.length === 0) return;
166
+ const current = entriesRef.current;
167
+ const next =
168
+ options.maxEntries > 1
169
+ ? [...current, ...incoming.slice(0, Math.max(0, options.maxEntries - current.length))]
170
+ : [incoming[0]];
171
+ entriesRef.current = next;
172
+ setEntries(next);
173
+ },
174
+ [setEntries],
175
+ );
176
+
177
+ const removeEntry = React.useCallback(
178
+ (id: string) => {
179
+ if (optionsRef.current.readOnly) return;
180
+ const next = entriesRef.current.filter((entry) => entry.id !== id);
181
+ entriesRef.current = next;
182
+ setEntries(next);
183
+ },
184
+ [setEntries],
185
+ );
186
+
187
+ const clearEntries = React.useCallback(() => {
188
+ if (optionsRef.current.readOnly) return;
189
+ entriesRef.current = [];
190
+ setEntries([]);
191
+ }, [setEntries]);
192
+
193
+ const reorderEntry = React.useCallback(
194
+ (fromIndex: number, toIndex: number) => {
195
+ const options = optionsRef.current;
196
+ if (options.disabled || options.readOnly) return;
197
+ const next = [...entriesRef.current];
198
+ if (fromIndex < 0 || toIndex < 0 || fromIndex >= next.length || toIndex >= next.length)
199
+ return;
200
+ const [entry] = next.splice(fromIndex, 1);
201
+ next.splice(toIndex, 0, entry);
202
+ entriesRef.current = next;
203
+ setEntries(next);
204
+ },
205
+ [setEntries],
206
+ );
207
+
208
+ const updateEntryStatus = React.useCallback(
209
+ (id: string, details: AttachmentDisplayStatusDetails) => {
210
+ const next = entriesRef.current.map((entry) =>
211
+ entry.id === id ? withUpdatedStatus(entry, details) : entry,
212
+ );
213
+ entriesRef.current = next;
214
+ setEntries(next);
215
+ },
216
+ [setEntries],
217
+ );
218
+
219
+ return {
220
+ entries: currentEntries,
221
+ currentEntryCount: currentEntries.length,
222
+ disabled,
223
+ invalid,
224
+ readOnly,
225
+ required,
226
+ maxEntries,
227
+ triggerDisabled,
228
+ stateProps: {
229
+ "data-disabled": disabled,
230
+ "data-readonly": readOnly,
231
+ "data-invalid": invalid,
232
+ "data-required": required,
233
+ },
234
+ addEntries,
235
+ removeEntry,
236
+ reorderEntry,
237
+ clearEntries,
238
+ updateEntryStatus,
239
+ onTriggerTap,
240
+ } satisfies AttachmentDisplayContextValue;
241
+ }
242
+
243
+ export interface AttachmentDisplayRootProps
244
+ extends AttachmentDisplayProps,
245
+ AttachmentInputVariantProps,
246
+ LynxStyledElementProps {}
247
+
248
+ export const AttachmentDisplayRoot = React.forwardRef<NodesRef, AttachmentDisplayRootProps>(
249
+ (props, ref) => {
250
+ const [variantProps, otherProps] = attachmentInput.splitVariantProps(props);
251
+ const {
252
+ children,
253
+ className,
254
+ entries,
255
+ defaultEntries,
256
+ onEntriesChange,
257
+ disabled,
258
+ invalid,
259
+ readOnly,
260
+ required,
261
+ maxEntries,
262
+ onTriggerTap,
263
+ ...nativeProps
264
+ } = otherProps;
265
+ const api = useAttachmentDisplay({
266
+ entries,
267
+ defaultEntries,
268
+ onEntriesChange,
269
+ disabled,
270
+ invalid,
271
+ readOnly,
272
+ required,
273
+ maxEntries,
274
+ onTriggerTap,
275
+ });
276
+ const classes = attachmentInput(variantProps);
277
+ return (
278
+ <DisplayContextObject.Provider value={api}>
279
+ <RootClassNamesProvider value={classes}>
280
+ <view
281
+ {...mergeProps(ref ? { ref } : {}, api.stateProps, nativeProps)}
282
+ className={clsx(classes.root, className)}
283
+ >
284
+ {children}
285
+ </view>
286
+ </RootClassNamesProvider>
287
+ </DisplayContextObject.Provider>
288
+ );
289
+ },
290
+ );
291
+ AttachmentDisplayRoot.displayName = "AttachmentDisplayRoot";
292
+
293
+ export interface AttachmentDisplayControlProps
294
+ extends AttachmentInputVariantProps,
295
+ LynxStyledElementProps {}
296
+
297
+ export const AttachmentDisplayControl = React.forwardRef<NodesRef, AttachmentDisplayControlProps>(
298
+ (props, ref) => {
299
+ const { children, className, ...nativeProps } = props;
300
+ const [variantProps] = attachmentInput.splitVariantProps(props);
301
+ const classes = attachmentInput(variantProps);
302
+ return (
303
+ <view
304
+ {...mergeProps(ref ? { ref } : {}, nativeProps)}
305
+ className={clsx(classes.root, className)}
306
+ >
307
+ {children}
308
+ </view>
309
+ );
310
+ },
311
+ );
312
+ AttachmentDisplayControl.displayName = "AttachmentDisplayControl";
313
+
314
+ export interface AttachmentDisplayContainerProps
315
+ extends LynxStyledElementProps,
316
+ Omit<NativeScrollViewProps, "scroll-orientation" | "scroll-bar-enable"> {}
317
+
318
+ export const AttachmentDisplayContainer = React.forwardRef<
319
+ NodesRef,
320
+ AttachmentDisplayContainerProps
321
+ >((props, ref) => {
322
+ const { children, className, ...nativeProps } = props;
323
+ const classes = useRootClassNames();
324
+ return (
325
+ <scroll-view
326
+ {...mergeProps(ref ? { ref } : {}, nativeProps)}
327
+ scroll-orientation="horizontal"
328
+ scroll-bar-enable={false}
329
+ className={clsx(classes.container, className)}
330
+ >
331
+ <view className={classes.containerContent}>{children}</view>
332
+ </scroll-view>
333
+ );
334
+ });
335
+ AttachmentDisplayContainer.displayName = "AttachmentDisplayContainer";
336
+
337
+ export const AttachmentDisplayItemGroup = React.forwardRef<NodesRef, LynxStyledElementProps>(
338
+ (props, ref) => {
339
+ const { children, className, ...nativeProps } = props;
340
+ const classes = useRootClassNames();
341
+ return (
342
+ <view
343
+ {...mergeProps(ref ? { ref } : {}, nativeProps)}
344
+ className={clsx(classes.itemGroup, className)}
345
+ >
346
+ {children}
347
+ </view>
348
+ );
349
+ },
350
+ );
351
+ AttachmentDisplayItemGroup.displayName = "AttachmentDisplayItemGroup";
352
+
353
+ export const AttachmentDisplayFooter = React.forwardRef<NodesRef, LynxStyledElementProps>(
354
+ (props, ref) => {
355
+ const { children, className, ...nativeProps } = props;
356
+ const context = useAttachmentDisplayContext();
357
+ return (
358
+ <view
359
+ {...mergeProps(ref ? { ref } : {}, context.stateProps, nativeProps)}
360
+ className={className}
361
+ >
362
+ {children}
363
+ </view>
364
+ );
365
+ },
366
+ );
367
+ AttachmentDisplayFooter.displayName = "AttachmentDisplayFooter";
368
+
369
+ export const AttachmentDisplayDescription = React.forwardRef<NodesRef, LynxStyledElementProps>(
370
+ (props, ref) => {
371
+ const { children, className, ...nativeProps } = props;
372
+ const context = useAttachmentDisplayContext();
373
+ return (
374
+ <text
375
+ {...mergeProps(ref ? { ref } : {}, context.stateProps, nativeProps)}
376
+ className={className}
377
+ >
378
+ {children}
379
+ </text>
380
+ );
381
+ },
382
+ );
383
+ AttachmentDisplayDescription.displayName = "AttachmentDisplayDescription";
384
+
385
+ export const AttachmentDisplayErrorMessage = React.forwardRef<NodesRef, LynxStyledElementProps>(
386
+ (props, ref) => {
387
+ const { children, className, ...nativeProps } = props;
388
+ const context = useAttachmentDisplayContext();
389
+ return (
390
+ <text
391
+ {...mergeProps(ref ? { ref } : {}, context.stateProps, nativeProps)}
392
+ className={className}
393
+ >
394
+ {children}
395
+ </text>
396
+ );
397
+ },
398
+ );
399
+ AttachmentDisplayErrorMessage.displayName = "AttachmentDisplayErrorMessage";
400
+
401
+ export interface AttachmentDisplayHeaderProps extends LynxStyledElementProps {}
402
+ export const AttachmentDisplayHeader = React.forwardRef<NodesRef, AttachmentDisplayHeaderProps>(
403
+ (props, ref) => {
404
+ const { children, className, ...nativeProps } = props;
405
+ const context = useAttachmentDisplayContext();
406
+ return (
407
+ <view
408
+ {...mergeProps(ref ? { ref } : {}, context.stateProps, nativeProps)}
409
+ className={className}
410
+ >
411
+ {children}
412
+ </view>
413
+ );
414
+ },
415
+ );
416
+ AttachmentDisplayHeader.displayName = "AttachmentDisplayHeader";
417
+
418
+ export interface AttachmentDisplayLabelProps
419
+ extends FieldLabelVariantProps,
420
+ LynxStyledElementProps {}
421
+ export const AttachmentDisplayLabel = React.forwardRef<NodesRef, AttachmentDisplayLabelProps>(
422
+ (props, ref) => {
423
+ const [variantProps, otherProps] = fieldLabel.splitVariantProps(props);
424
+ const { children, className, ...nativeProps } = otherProps;
425
+ const classes = fieldLabel(variantProps);
426
+ const context = useAttachmentDisplayContext();
427
+ return (
428
+ <LabelClassNamesProvider value={classes}>
429
+ <text
430
+ {...mergeProps(ref ? { ref } : {}, context.stateProps, nativeProps)}
431
+ className={clsx(classes.root, className)}
432
+ >
433
+ {children}
434
+ </text>
435
+ </LabelClassNamesProvider>
436
+ );
437
+ },
438
+ );
439
+ AttachmentDisplayLabel.displayName = "AttachmentDisplayLabel";
440
+
441
+ export interface AttachmentDisplayIndicatorTextProps extends LynxStyledElementProps {}
442
+ export const AttachmentDisplayIndicatorText = React.forwardRef<
443
+ NodesRef,
444
+ AttachmentDisplayIndicatorTextProps
445
+ >((props, ref) => {
446
+ const { children, className, ...nativeProps } = props;
447
+ const classes = useLabelClassNames();
448
+ const context = useAttachmentDisplayContext();
449
+ return (
450
+ <text
451
+ {...mergeProps(ref ? { ref } : {}, context.stateProps, nativeProps)}
452
+ className={clsx(classes.indicatorText, className)}
453
+ >
454
+ {"\u00a0"}
455
+ {children}
456
+ </text>
457
+ );
458
+ });
459
+ AttachmentDisplayIndicatorText.displayName = "AttachmentDisplayIndicatorText";
460
+
461
+ export interface AttachmentDisplayRequiredIndicatorProps extends LynxStyledElementProps {}
462
+ export const AttachmentDisplayRequiredIndicator = React.forwardRef<
463
+ NodesRef,
464
+ AttachmentDisplayRequiredIndicatorProps
465
+ >((props, ref) => {
466
+ const { children = "*", className, ...nativeProps } = props;
467
+ const classes = useLabelClassNames();
468
+ const context = useAttachmentDisplayContext();
469
+ return (
470
+ <text
471
+ {...mergeProps(ref ? { ref } : {}, context.stateProps, nativeProps)}
472
+ accessibility-elements-hidden={true}
473
+ className={clsx(classes.indicatorIcon, className)}
474
+ >
475
+ {"\u200a"}
476
+ {children}
477
+ </text>
478
+ );
479
+ });
480
+ AttachmentDisplayRequiredIndicator.displayName = "AttachmentDisplayRequiredIndicator";
481
+
482
+ export interface AttachmentDisplayTriggerProps
483
+ extends AttachmentInputTriggerVariantProps,
484
+ LynxStyledElementProps,
485
+ LynxPressableProps,
486
+ LynxAccessibilityProps {}
487
+
488
+ export const AttachmentDisplayTrigger = React.forwardRef<NodesRef, AttachmentDisplayTriggerProps>(
489
+ (props, ref) => {
490
+ const [variantProps, restProps] = attachmentInputTrigger.splitVariantProps(props);
491
+ const {
492
+ children,
493
+ className,
494
+ bindtap,
495
+ "main-thread:bindtap": mainThreadBindtap,
496
+ "accessibility-element": accessibilityElement = true,
497
+ "accessibility-label": accessibilityLabel,
498
+ "accessibility-role-description": accessibilityRoleDescription = "button",
499
+ "accessibility-traits": accessibilityTraits,
500
+ ...nativeProps
501
+ } = restProps;
502
+ const context = useAttachmentDisplayContext();
503
+ const press = usePressTap({
504
+ disabled: context.triggerDisabled,
505
+ onTap: () =>
506
+ context.onTriggerTap?.({
507
+ addEntries: context.addEntries,
508
+ updateEntryStatus: context.updateEntryStatus,
509
+ }),
510
+ mainThreadOnTap: mainThreadBindtap,
511
+ });
512
+ const classes = attachmentInputTrigger({
513
+ ...variantProps,
514
+ pressed: press.pressed,
515
+ disabled: context.triggerDisabled,
516
+ });
517
+ return (
518
+ <TriggerClassNamesProvider value={classes}>
519
+ <view
520
+ {...mergeProps(
521
+ ref ? { ref } : {},
522
+ press,
523
+ { bindtap: context.triggerDisabled ? undefined : bindtap },
524
+ nativeProps,
525
+ context.stateProps,
526
+ )}
527
+ accessibility-element={accessibilityElement}
528
+ accessibility-label={accessibilityLabel}
529
+ accessibility-role-description={accessibilityRoleDescription}
530
+ accessibility-traits={
531
+ accessibilityTraits ?? (context.triggerDisabled ? "disabled" : "button")
532
+ }
533
+ flatten={false}
534
+ className={clsx(classes.root, className)}
535
+ >
536
+ {children}
537
+ </view>
538
+ </TriggerClassNamesProvider>
539
+ );
540
+ },
541
+ );
542
+ AttachmentDisplayTrigger.displayName = "AttachmentDisplayTrigger";
543
+
544
+ export interface AttachmentDisplayTriggerIconProps extends LynxStyledElementProps {
545
+ image?: React.ReactNode;
546
+ }
547
+ export const AttachmentDisplayTriggerIcon = React.forwardRef<
548
+ NodesRef,
549
+ AttachmentDisplayTriggerIconProps
550
+ >((props, ref) => {
551
+ const { image, children, className, ...nativeProps } = props;
552
+ const context = useAttachmentDisplayContext();
553
+ const classes = useTriggerClassNames();
554
+ const icon = image ?? children;
555
+ if (!isValidElement<LynxIconElementProps>(icon)) return null;
556
+ return (
557
+ <InternalIcon
558
+ icon={icon}
559
+ ref={ref}
560
+ {...nativeProps}
561
+ className={clsx(classes.icon, className)}
562
+ accessibility-elements-hidden={true}
563
+ deps={[context.triggerDisabled]}
564
+ />
565
+ );
566
+ });
567
+ AttachmentDisplayTriggerIcon.displayName = "AttachmentDisplayTriggerIcon";
568
+
569
+ export interface AttachmentDisplayTriggerItemCountProps extends LynxStyledElementProps {}
570
+ export const AttachmentDisplayTriggerItemCount = React.forwardRef<
571
+ NodesRef,
572
+ AttachmentDisplayTriggerItemCountProps
573
+ >((props, ref) => {
574
+ const { children, className, ...nativeProps } = props;
575
+ const context = useAttachmentDisplayContext();
576
+ const classes = useTriggerClassNames();
577
+ return (
578
+ <view
579
+ {...mergeProps(ref ? { ref } : {}, nativeProps)}
580
+ className={clsx(classes.itemCountArea, className)}
581
+ >
582
+ <text
583
+ {...(context.currentEntryCount === 0 ? { "data-empty": true } : {})}
584
+ {...context.stateProps}
585
+ className={classes.itemCount}
586
+ >
587
+ {context.currentEntryCount}
588
+ </text>
589
+ <text {...context.stateProps} className={classes.maxItemCount}>
590
+ /{context.maxEntries}
591
+ </text>
592
+ {children}
593
+ </view>
594
+ );
595
+ });
596
+ AttachmentDisplayTriggerItemCount.displayName = "AttachmentDisplayTriggerItemCount";
597
+
598
+ export interface AttachmentDisplayItemProps
599
+ extends Omit<AttachmentInputItemVariantProps, "type">,
600
+ LynxStyledElementProps {
601
+ entry: AttachmentDisplayEntry;
602
+ }
603
+ export const AttachmentDisplayItem = React.forwardRef<NodesRef, AttachmentDisplayItemProps>(
604
+ (props, ref) => {
605
+ const { entry, children, className, ...restProps } = props;
606
+ const [variantProps, nativeProps] = attachmentInputItem.splitVariantProps({
607
+ type: "image",
608
+ ...restProps,
609
+ });
610
+ const root = useAttachmentDisplayContext();
611
+ const classes = attachmentInputItem({
612
+ ...variantProps,
613
+ type: "image",
614
+ disabled: root.disabled,
615
+ readOnly: root.readOnly,
616
+ pressed: false,
617
+ dragging: variantProps.dragging ?? false,
618
+ });
619
+ const item = {
620
+ ...entry,
621
+ imageProps: entry.thumbnailUrl ? { src: entry.thumbnailUrl, alt: entry.name } : undefined,
622
+ };
623
+ return (
624
+ <DisplayItemContextObject.Provider value={item}>
625
+ <ItemClassNamesProvider value={classes}>
626
+ <view
627
+ {...mergeProps(ref ? { ref } : {}, root.stateProps, nativeProps)}
628
+ className={clsx(classes.root, className)}
629
+ >
630
+ {children}
631
+ </view>
632
+ </ItemClassNamesProvider>
633
+ </DisplayItemContextObject.Provider>
634
+ );
635
+ },
636
+ );
637
+ AttachmentDisplayItem.displayName = "AttachmentDisplayItem";
638
+
639
+ export const AttachmentDisplayItemSurface = React.forwardRef<NodesRef, LynxStyledElementProps>(
640
+ (props, ref) => {
641
+ const { children, className, ...nativeProps } = props;
642
+ const classes = useItemClassNames();
643
+ return (
644
+ <view
645
+ {...mergeProps(ref ? { ref } : {}, nativeProps)}
646
+ className={clsx(classes.surface, className)}
647
+ >
648
+ {children}
649
+ </view>
650
+ );
651
+ },
652
+ );
653
+ AttachmentDisplayItemSurface.displayName = "AttachmentDisplayItemSurface";
654
+
655
+ export const AttachmentDisplayItemImage = React.forwardRef<NodesRef, LynxStyledElementProps>(
656
+ (props, ref) => {
657
+ const { className, ...nativeProps } = props;
658
+ const item = useAttachmentDisplayItemContext();
659
+ const classes = useItemClassNames();
660
+ if (!item.imageProps) return null;
661
+ return (
662
+ <image
663
+ {...mergeProps(ref ? { ref } : {}, nativeProps)}
664
+ src={item.imageProps.src}
665
+ accessibility-label={item.imageProps.alt}
666
+ className={clsx(classes.image, className)}
667
+ />
668
+ );
669
+ },
670
+ );
671
+ AttachmentDisplayItemImage.displayName = "AttachmentDisplayItemImage";
672
+
673
+ export const AttachmentDisplayItemThumbnail = React.forwardRef<NodesRef, LynxStyledElementProps>(
674
+ (props, ref) => {
675
+ const { children, className, ...nativeProps } = props;
676
+ const classes = useItemClassNames();
677
+ const context = useAttachmentDisplayContext();
678
+ return (
679
+ <IconSlotProvider
680
+ value={{
681
+ classNames: { icon: classes.thumbnailIcon },
682
+ deps: [context.disabled, context.readOnly],
683
+ }}
684
+ >
685
+ <view
686
+ {...mergeProps(ref ? { ref } : {}, nativeProps)}
687
+ className={clsx(classes.thumbnail, className)}
688
+ >
689
+ {children}
690
+ </view>
691
+ </IconSlotProvider>
692
+ );
693
+ },
694
+ );
695
+ AttachmentDisplayItemThumbnail.displayName = "AttachmentDisplayItemThumbnail";
696
+
697
+ export const AttachmentDisplayItemMetadata = React.forwardRef<NodesRef, LynxStyledElementProps>(
698
+ (props, ref) => {
699
+ const { children, className, ...nativeProps } = props;
700
+ const classes = useItemClassNames();
701
+ return (
702
+ <view
703
+ {...mergeProps(ref ? { ref } : {}, nativeProps)}
704
+ className={clsx(classes.metadata, className)}
705
+ >
706
+ {children}
707
+ </view>
708
+ );
709
+ },
710
+ );
711
+ AttachmentDisplayItemMetadata.displayName = "AttachmentDisplayItemMetadata";
712
+
713
+ export const AttachmentDisplayItemBadge = React.forwardRef<NodesRef, LynxStyledElementProps>(
714
+ (props, ref) => {
715
+ const { children, className, ...nativeProps } = props;
716
+ const classes = useItemClassNames();
717
+ return (
718
+ <view
719
+ {...mergeProps(ref ? { ref } : {}, nativeProps)}
720
+ className={clsx(classes.badge, className)}
721
+ >
722
+ <text className={classes.badgeLabel}>{children}</text>
723
+ </view>
724
+ );
725
+ },
726
+ );
727
+ AttachmentDisplayItemBadge.displayName = "AttachmentDisplayItemBadge";
728
+
729
+ export interface AttachmentDisplayItemActionButtonProps
730
+ extends LynxStyledElementProps,
731
+ LynxPressableProps {}
732
+ export const AttachmentDisplayItemActionButton = React.forwardRef<
733
+ NodesRef,
734
+ AttachmentDisplayItemActionButtonProps
735
+ >((props, ref) => {
736
+ const {
737
+ children,
738
+ className,
739
+ bindtap,
740
+ "main-thread:bindtap": mainThreadBindtap,
741
+ ...nativeProps
742
+ } = props;
743
+ const classes = useItemClassNames();
744
+ const context = useAttachmentDisplayContext();
745
+ const actionChildren = toArray(children).map((child, index) =>
746
+ typeof child === "string" || typeof child === "number" ? (
747
+ <text key={index} className={classes.actionLabel}>
748
+ {child}
749
+ </text>
750
+ ) : (
751
+ child
752
+ ),
753
+ );
754
+ return (
755
+ <IconSlotProvider
756
+ value={{
757
+ classNames: { icon: classes.actionIcon },
758
+ deps: [context.disabled, context.readOnly],
759
+ }}
760
+ >
761
+ <view
762
+ {...mergeProps(ref ? { ref } : {}, nativeProps, {
763
+ bindtap,
764
+ "main-thread:bindtap": mainThreadBindtap,
765
+ })}
766
+ className={clsx(classes.actionButton, className)}
767
+ >
768
+ {actionChildren}
769
+ </view>
770
+ </IconSlotProvider>
771
+ );
772
+ });
773
+ AttachmentDisplayItemActionButton.displayName = "AttachmentDisplayItemActionButton";
774
+
775
+ export interface AttachmentDisplayItemBackdropProps
776
+ extends Omit<LynxStyledElementProps, "children"> {
777
+ status: AttachmentDisplayEntry["status"];
778
+ children?: React.ReactNode | ((entry: AttachmentDisplayEntry) => React.ReactNode);
779
+ }
780
+ export const AttachmentDisplayItemBackdrop = React.forwardRef<
781
+ NodesRef,
782
+ AttachmentDisplayItemBackdropProps
783
+ >((props, ref) => {
784
+ const { status, children, className, ...nativeProps } = props;
785
+ const entry = useAttachmentDisplayItemContext();
786
+ const classes = useItemClassNames();
787
+ if (entry.status !== status) return null;
788
+ return (
789
+ <view
790
+ {...mergeProps(ref ? { ref } : {}, nativeProps)}
791
+ className={clsx(classes.backdrop, className)}
792
+ >
793
+ {typeof children === "function" ? children(entry) : children}
794
+ </view>
795
+ );
796
+ });
797
+ AttachmentDisplayItemBackdrop.displayName = "AttachmentDisplayItemBackdrop";
798
+
799
+ export interface AttachmentDisplayItemRemoveButtonProps
800
+ extends LynxStyledElementProps,
801
+ LynxPressableProps,
802
+ LynxAccessibilityProps {}
803
+ export const AttachmentDisplayItemRemoveButton = React.forwardRef<
804
+ NodesRef,
805
+ AttachmentDisplayItemRemoveButtonProps
806
+ >((props, ref) => {
807
+ const {
808
+ children,
809
+ className,
810
+ bindtap,
811
+ "main-thread:bindtap": mainThreadBindtap,
812
+ "accessibility-element": accessibilityElement = true,
813
+ "accessibility-label": accessibilityLabel,
814
+ "accessibility-role-description": accessibilityRoleDescription = "button",
815
+ "accessibility-traits": accessibilityTraits,
816
+ ...nativeProps
817
+ } = props;
818
+ const item = useAttachmentDisplayItemContext();
819
+ const context = useAttachmentDisplayContext();
820
+ const classes = useItemClassNames();
821
+ const press = usePressTap({
822
+ disabled: context.readOnly,
823
+ onTap: () => context.removeEntry(item.id),
824
+ mainThreadOnTap: mainThreadBindtap,
825
+ });
826
+ return (
827
+ <IconSlotProvider
828
+ value={{
829
+ classNames: { icon: classes.removeIcon },
830
+ deps: [context.disabled, context.readOnly],
831
+ }}
832
+ >
833
+ <view
834
+ {...mergeProps(
835
+ ref ? { ref } : {},
836
+ press,
837
+ { bindtap: context.readOnly ? undefined : bindtap },
838
+ nativeProps,
839
+ context.stateProps,
840
+ )}
841
+ accessibility-element={accessibilityElement}
842
+ accessibility-label={accessibilityLabel}
843
+ accessibility-role-description={accessibilityRoleDescription}
844
+ accessibility-traits={accessibilityTraits ?? (context.readOnly ? "disabled" : "button")}
845
+ flatten={false}
846
+ className={clsx(classes.removeButton, className)}
847
+ >
848
+ {children}
849
+ </view>
850
+ </IconSlotProvider>
851
+ );
852
+ });
853
+ AttachmentDisplayItemRemoveButton.displayName = "AttachmentDisplayItemRemoveButton";
854
+
855
+ export interface AttachmentDisplayContextProps {
856
+ children: (context: AttachmentDisplayContextValue) => React.ReactNode;
857
+ }
858
+ export const AttachmentDisplayContext = (props: AttachmentDisplayContextProps) =>
859
+ props.children(useAttachmentDisplayContext());
860
+
861
+ export const AttachmentDisplay = {
862
+ Root: AttachmentDisplayRoot,
863
+ Control: AttachmentDisplayControl,
864
+ Container: AttachmentDisplayContainer,
865
+ ItemGroup: AttachmentDisplayItemGroup,
866
+ Footer: AttachmentDisplayFooter,
867
+ Header: AttachmentDisplayHeader,
868
+ Label: AttachmentDisplayLabel,
869
+ IndicatorText: AttachmentDisplayIndicatorText,
870
+ RequiredIndicator: AttachmentDisplayRequiredIndicator,
871
+ Description: AttachmentDisplayDescription,
872
+ ErrorMessage: AttachmentDisplayErrorMessage,
873
+ Trigger: AttachmentDisplayTrigger,
874
+ TriggerIcon: AttachmentDisplayTriggerIcon,
875
+ TriggerItemCount: AttachmentDisplayTriggerItemCount,
876
+ Item: AttachmentDisplayItem,
877
+ ItemSurface: AttachmentDisplayItemSurface,
878
+ ItemImage: AttachmentDisplayItemImage,
879
+ ItemThumbnail: AttachmentDisplayItemThumbnail,
880
+ ItemMetadata: AttachmentDisplayItemMetadata,
881
+ ItemBadge: AttachmentDisplayItemBadge,
882
+ ItemActionButton: AttachmentDisplayItemActionButton,
883
+ ItemBackdrop: AttachmentDisplayItemBackdrop,
884
+ ItemRemoveButton: AttachmentDisplayItemRemoveButton,
885
+ Context: AttachmentDisplayContext,
886
+ };