@multiplatform.one/forms 7.65.0 → 7.65.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 (227) hide show
  1. package/dist/cjs/AdaptivePopup/index.native.js +1 -1
  2. package/dist/cjs/AdaptivePopup/index.native.js.map +1 -1
  3. package/dist/cjs/Button/index.native.js +2 -2
  4. package/dist/cjs/Button/index.native.js.map +1 -1
  5. package/dist/cjs/Chip/index.native.js.map +1 -1
  6. package/dist/cjs/ContextualSaveBar/UnsavedChangesDialog.native.js +1 -1
  7. package/dist/cjs/ContextualSaveBar/UnsavedChangesDialog.native.js.map +1 -1
  8. package/dist/cjs/ContextualSaveBar/clientKnownIdentity.native.js.map +1 -1
  9. package/dist/cjs/ContextualSaveBar/commitImmediateField.native.js.map +1 -1
  10. package/dist/cjs/ContextualSaveBar/index.native.js +3 -3
  11. package/dist/cjs/ContextualSaveBar/index.native.js.map +1 -1
  12. package/dist/cjs/ContextualSaveBar/useUnsavedChangesGuard.native.js.map +1 -1
  13. package/dist/cjs/ControlGroup/index.native.js +1 -1
  14. package/dist/cjs/ControlGroup/index.native.js.map +1 -1
  15. package/dist/cjs/DescriptionList/index.native.js +2 -2
  16. package/dist/cjs/DescriptionList/index.native.js.map +1 -1
  17. package/dist/cjs/ErrorSummary.native.js.map +1 -1
  18. package/dist/cjs/FieldDisplay/editMode.native.js.map +1 -1
  19. package/dist/cjs/FieldDisplay/formatters.native.js.map +1 -1
  20. package/dist/cjs/FieldDisplay/index.native.js +1 -1
  21. package/dist/cjs/FieldDisplay/index.native.js.map +1 -1
  22. package/dist/cjs/FieldGroup.native.js.map +1 -1
  23. package/dist/cjs/FloatingPanel/compactFace.native.js.map +1 -1
  24. package/dist/cjs/FloatingPanel/nestedAction.native.js.map +1 -1
  25. package/dist/cjs/FloatingPanel/pointAnchor.native.js.map +1 -1
  26. package/dist/cjs/FloatingPanel/trailingAction.native.js +1 -1
  27. package/dist/cjs/FloatingPanel/trailingAction.native.js.map +1 -1
  28. package/dist/cjs/FloatingPanel/useFloatingPanel.native.js.map +1 -1
  29. package/dist/cjs/Form/index.native.js +1 -1
  30. package/dist/cjs/Form/index.native.js.map +1 -1
  31. package/dist/cjs/Form/submissionController.native.js.map +1 -1
  32. package/dist/cjs/Form/validateOn.native.js.map +1 -1
  33. package/dist/cjs/FormGrid.native.js.map +1 -1
  34. package/dist/cjs/FormSection.native.js.map +1 -1
  35. package/dist/cjs/InputParts/PasswordReveal.native.js.map +1 -1
  36. package/dist/cjs/InputParts/index.cjs +74 -5
  37. package/dist/cjs/InputParts/index.native.js +99 -5
  38. package/dist/cjs/InputParts/index.native.js.map +1 -1
  39. package/dist/cjs/Label/index.native.js.map +1 -1
  40. package/dist/cjs/MediaPicker/base64.native.js.map +1 -1
  41. package/dist/cjs/MediaPicker/payload.native.js.map +1 -1
  42. package/dist/cjs/MediaPicker/types.native.js.map +1 -1
  43. package/dist/cjs/MediaPicker/useMediaPicker.native.js.map +1 -1
  44. package/dist/cjs/Skeleton/index.native.js.map +1 -1
  45. package/dist/cjs/Spinner/SpinnerGlyph.native.js.map +1 -1
  46. package/dist/cjs/Spinner/spinnerSize.native.js.map +1 -1
  47. package/dist/cjs/Table/index.native.js.map +1 -1
  48. package/dist/cjs/Wheel/haptic.native.js.map +1 -1
  49. package/dist/cjs/Wheel/index.native.js.map +1 -1
  50. package/dist/cjs/Wheel/wheelShared.native.js.map +1 -1
  51. package/dist/cjs/actionLabel.native.js.map +1 -1
  52. package/dist/cjs/fieldDefaults.native.js.map +1 -1
  53. package/dist/cjs/fieldLayout.native.js +1 -1
  54. package/dist/cjs/fieldLayout.native.js.map +1 -1
  55. package/dist/cjs/fields/Barcode/BarcodePreview.native.js.map +1 -1
  56. package/dist/cjs/fields/Barcode/BarcodeScanner.native.js +1 -1
  57. package/dist/cjs/fields/Barcode/code128.native.js.map +1 -1
  58. package/dist/cjs/fields/Barcode/index.native.js +2 -2
  59. package/dist/cjs/fields/Barcode/index.native.js.map +1 -1
  60. package/dist/cjs/fields/Barcode/qr.native.js.map +1 -1
  61. package/dist/cjs/fields/Barcode/scannerTypes.native.js.map +1 -1
  62. package/dist/cjs/fields/Checkbox/Checkbox.native.js +1 -1
  63. package/dist/cjs/fields/Checkbox/Checkbox.native.js.map +1 -1
  64. package/dist/cjs/fields/Checkbox/CheckboxBox.native.js.map +1 -1
  65. package/dist/cjs/fields/Checkbox/CheckboxCard.native.js.map +1 -1
  66. package/dist/cjs/fields/Checkbox/CheckboxFieldFrame.native.js.map +1 -1
  67. package/dist/cjs/fields/Checkbox/CheckboxGroup.native.js +1 -1
  68. package/dist/cjs/fields/Checkbox/CheckboxGroup.native.js.map +1 -1
  69. package/dist/cjs/fields/Checkbox/checkboxGroupContext.native.js.map +1 -1
  70. package/dist/cjs/fields/Checkbox/index.native.js.map +1 -1
  71. package/dist/cjs/fields/ColorPicker/SystemColorField.native.js.map +1 -1
  72. package/dist/cjs/fields/ColorPicker/index.native.js +2 -2
  73. package/dist/cjs/fields/ColorPicker/index.native.js.map +1 -1
  74. package/dist/cjs/fields/ColorPicker/parts.native.js +2 -2
  75. package/dist/cjs/fields/ColorPicker/parts.native.js.map +1 -1
  76. package/dist/cjs/fields/ColorPicker/systemColorWell.gnome.native.js.map +1 -1
  77. package/dist/cjs/fields/Combobox/authorOptions.native.js.map +1 -1
  78. package/dist/cjs/fields/Combobox/index.native.js +5 -5
  79. package/dist/cjs/fields/Combobox/index.native.js.map +1 -1
  80. package/dist/cjs/fields/DatePicker/Calendar.native.js.map +1 -1
  81. package/dist/cjs/fields/DatePicker/DateRangePicker.native.js +2 -2
  82. package/dist/cjs/fields/DatePicker/DateRangePicker.native.js.map +1 -1
  83. package/dist/cjs/fields/DatePicker/DatetimePicker.catalog.native.js +3 -3
  84. package/dist/cjs/fields/DatePicker/DatetimePicker.catalog.native.js.map +1 -1
  85. package/dist/cjs/fields/DatePicker/DatetimePicker.native.js +2 -2
  86. package/dist/cjs/fields/DatePicker/MonthPicker.native.js +2 -2
  87. package/dist/cjs/fields/DatePicker/MonthPicker.native.js.map +1 -1
  88. package/dist/cjs/fields/DatePicker/MultiDatePicker.native.js +2 -2
  89. package/dist/cjs/fields/DatePicker/MultiDatePicker.native.js.map +1 -1
  90. package/dist/cjs/fields/DatePicker/catalog.native.js +2 -2
  91. package/dist/cjs/fields/DatePicker/catalog.native.js.map +1 -1
  92. package/dist/cjs/fields/DatePicker/fieldValueSync.native.js.map +1 -1
  93. package/dist/cjs/fields/DatePicker/index.native.js +2 -2
  94. package/dist/cjs/fields/DatePicker/parts.native.js +2 -2
  95. package/dist/cjs/fields/DatePicker/parts.native.js.map +1 -1
  96. package/dist/cjs/fields/DatePicker/utils.native.js.map +1 -1
  97. package/dist/cjs/fields/Duration/durationMath.native.js.map +1 -1
  98. package/dist/cjs/fields/Duration/index.native.js +3 -3
  99. package/dist/cjs/fields/Duration/index.native.js.map +1 -1
  100. package/dist/cjs/fields/FileUpload/filePickerTypes.native.js.map +1 -1
  101. package/dist/cjs/fields/FileUpload/index.native.js +2 -2
  102. package/dist/cjs/fields/FileUpload/index.native.js.map +1 -1
  103. package/dist/cjs/fields/FileUpload/nativePickerLoader.native.js.map +1 -1
  104. package/dist/cjs/fields/Geolocation/expoMapsLoader.native.js.map +1 -1
  105. package/dist/cjs/fields/Geolocation/geoValue.native.js.map +1 -1
  106. package/dist/cjs/fields/Geolocation/geocoder.native.js.map +1 -1
  107. package/dist/cjs/fields/Geolocation/geocoderContext.native.js.map +1 -1
  108. package/dist/cjs/fields/Geolocation/index.native.js +5 -5
  109. package/dist/cjs/fields/Geolocation/index.native.js.map +1 -1
  110. package/dist/cjs/fields/Geolocation/mapMath.native.js.map +1 -1
  111. package/dist/cjs/fields/Geolocation/mapTypes.native.js.map +1 -1
  112. package/dist/cjs/fields/Geolocation/nativeSearchFocus.native.js.map +1 -1
  113. package/dist/cjs/fields/Geolocation/photonGeocoder.native.js.map +1 -1
  114. package/dist/cjs/fields/Icon/drawnSet.native.js.map +1 -1
  115. package/dist/cjs/fields/Icon/index.native.js +3 -3
  116. package/dist/cjs/fields/Icon/index.native.js.map +1 -1
  117. package/dist/cjs/fields/ImageField/index.native.js +2 -2
  118. package/dist/cjs/fields/ImageField/index.native.js.map +1 -1
  119. package/dist/cjs/fields/Input/index.native.js +3 -3
  120. package/dist/cjs/fields/Input/index.native.js.map +1 -1
  121. package/dist/cjs/fields/MentionInput/index.native.js +3 -3
  122. package/dist/cjs/fields/MentionInput/index.native.js.map +1 -1
  123. package/dist/cjs/fields/OTPInput/index.native.js +3 -3
  124. package/dist/cjs/fields/OTPInput/index.native.js.map +1 -1
  125. package/dist/cjs/fields/OTPInput/otpCellCss.native.js.map +1 -1
  126. package/dist/cjs/fields/PhoneInput/dialCodes.native.js.map +1 -1
  127. package/dist/cjs/fields/PhoneInput/index.native.js +3 -3
  128. package/dist/cjs/fields/PhoneInput/index.native.js.map +1 -1
  129. package/dist/cjs/fields/PhoneInput/phone.native.js.map +1 -1
  130. package/dist/cjs/fields/PhoneInput/regionNames.native.js.map +1 -1
  131. package/dist/cjs/fields/Progress/index.native.js +1 -1
  132. package/dist/cjs/fields/Progress/index.native.js.map +1 -1
  133. package/dist/cjs/fields/RadioGroup/index.native.js +1 -1
  134. package/dist/cjs/fields/RadioGroup/index.native.js.map +1 -1
  135. package/dist/cjs/fields/Rating/index.native.js +1 -1
  136. package/dist/cjs/fields/Rating/index.native.js.map +1 -1
  137. package/dist/cjs/fields/Rating/ratingMath.native.js.map +1 -1
  138. package/dist/cjs/fields/Rating/types.native.js.map +1 -1
  139. package/dist/cjs/fields/SearchInput/index.native.js +2 -2
  140. package/dist/cjs/fields/SearchInput/index.native.js.map +1 -1
  141. package/dist/cjs/fields/Select/InlineChoices.native.js.map +1 -1
  142. package/dist/cjs/fields/Select/index.native.js +4 -4
  143. package/dist/cjs/fields/Select/index.native.js.map +1 -1
  144. package/dist/cjs/fields/Select/shouldInlineChoices.native.js.map +1 -1
  145. package/dist/cjs/fields/Signature/index.native.js +2 -2
  146. package/dist/cjs/fields/Signature/index.native.js.map +1 -1
  147. package/dist/cjs/fields/Slider/index.native.js +1 -1
  148. package/dist/cjs/fields/Slider/index.native.js.map +1 -1
  149. package/dist/cjs/fields/Slider/jumpMotion.native.js.map +1 -1
  150. package/dist/cjs/fields/Stepper/index.native.js +2 -2
  151. package/dist/cjs/fields/Stepper/index.native.js.map +1 -1
  152. package/dist/cjs/fields/Stepper/resolveStepperPlacement.native.js.map +1 -1
  153. package/dist/cjs/fields/Switch/footprint.native.js.map +1 -1
  154. package/dist/cjs/fields/Switch/index.native.js +2 -2
  155. package/dist/cjs/fields/Switch/index.native.js.map +1 -1
  156. package/dist/cjs/fields/TextArea/index.native.js +2 -2
  157. package/dist/cjs/fields/TextArea/index.native.js.map +1 -1
  158. package/dist/cjs/fields/TimePicker/catalog.native.js +3 -3
  159. package/dist/cjs/fields/TimePicker/catalog.native.js.map +1 -1
  160. package/dist/cjs/fields/TimePicker/index.native.js +2 -2
  161. package/dist/cjs/fields/TimePicker/parts.native.js +1 -1
  162. package/dist/cjs/fields/TimePicker/parts.native.js.map +1 -1
  163. package/dist/cjs/fields/TimeRangeScrubber/geometry.native.js.map +1 -1
  164. package/dist/cjs/fields/TimeRangeScrubber/index.native.js +2 -2
  165. package/dist/cjs/fields/TimeRangeScrubber/index.native.js.map +1 -1
  166. package/dist/cjs/fields/ToggleGroup/index.native.js +1 -1
  167. package/dist/cjs/fields/ToggleGroup/index.native.js.map +1 -1
  168. package/dist/cjs/fields/nativeDateTime/OsDateTimeSheet.native.js.map +1 -1
  169. package/dist/cjs/fields/nativeDateTime/dateTimePickerLoader.native.js.map +1 -1
  170. package/dist/cjs/fields/nativeDateTime/osDateTimeIosDisplay.native.js.map +1 -1
  171. package/dist/cjs/fields/nativeSelect.native.js.map +1 -1
  172. package/dist/cjs/fields/selectedOrder.native.js.map +1 -1
  173. package/dist/cjs/formSpacing.native.js.map +1 -1
  174. package/dist/cjs/hooks/useFocusManagement.native.js.map +1 -1
  175. package/dist/cjs/index.native.js +45 -45
  176. package/dist/cjs/index.native.js.map +1 -1
  177. package/dist/cjs/keyboard/KeyboardDoneBar.native.js +1 -1
  178. package/dist/cjs/keyboard/chain.native.js.map +1 -1
  179. package/dist/cjs/keyboard/index.native.js.map +1 -1
  180. package/dist/cjs/keyboard/types.native.js.map +1 -1
  181. package/dist/cjs/requiredMarking.native.js.map +1 -1
  182. package/dist/cjs/shared/TimeColumn.native.js +1 -1
  183. package/dist/cjs/shared/TimeColumn.native.js.map +1 -1
  184. package/dist/cjs/shared/capabilityPreflight.native.js.map +1 -1
  185. package/dist/cjs/shared/choiceRowPress.native.js.map +1 -1
  186. package/dist/cjs/shared/colorRamps.native.js.map +1 -1
  187. package/dist/cjs/shared/devWarn.native.js.map +1 -1
  188. package/dist/cjs/shared/floatingList.native.js +1 -1
  189. package/dist/cjs/shared/floatingList.native.js.map +1 -1
  190. package/dist/cjs/shared/focusManagement.native.js.map +1 -1
  191. package/dist/cjs/shared/groupContext.native.js.map +1 -1
  192. package/dist/cjs/shared/i18n.native.js.map +1 -1
  193. package/dist/cjs/shared/instantMotion.native.js.map +1 -1
  194. package/dist/cjs/shared/nativeA11y.native.js.map +1 -1
  195. package/dist/cjs/shared/nativeAutoFocus.native.js.map +1 -1
  196. package/dist/cjs/shared/overlayStack.native.js.map +1 -1
  197. package/dist/cjs/shared/panelPortal.native.js.map +1 -1
  198. package/dist/cjs/shared/pickerTriggerContract.native.js.map +1 -1
  199. package/dist/cjs/shared/pressSlopProps.native.js.map +1 -1
  200. package/dist/cjs/shared/restoreRetries.native.js.map +1 -1
  201. package/dist/cjs/shared/t.native.js.map +1 -1
  202. package/dist/cjs/shared/tableCellContext.native.js.map +1 -1
  203. package/dist/cjs/shared/touchWebPicker.native.js.map +1 -1
  204. package/dist/cjs/shared/useDragScroll.native.js.map +1 -1
  205. package/dist/cjs/shared/useKeyboardInset.native.js.map +1 -1
  206. package/dist/cjs/shared/useSheetEscapeDismiss.native.js.map +1 -1
  207. package/dist/cjs/shared/useWheelIncrement.native.js.map +1 -1
  208. package/dist/cjs/shared/utils.native.js +1 -1
  209. package/dist/cjs/shared/utils.native.js.map +1 -1
  210. package/dist/cjs/shared/zIndex.native.js.map +1 -1
  211. package/dist/cjs/themedPrimitives.native.js.map +1 -1
  212. package/dist/cjs/types.native.js.map +1 -1
  213. package/dist/cjs/utils/LinkCell.native.js.map +1 -1
  214. package/dist/esm/InputParts/index.mjs +75 -7
  215. package/dist/esm/InputParts/index.mjs.map +1 -1
  216. package/dist/esm/InputParts/index.native.js +100 -7
  217. package/dist/esm/InputParts/index.native.js.map +1 -1
  218. package/dist/jsx/InputParts/index.mjs +75 -7
  219. package/dist/jsx/InputParts/index.mjs.map +1 -1
  220. package/dist/jsx/InputParts/index.native.js +99 -5
  221. package/dist/jsx/InputParts/index.native.js.map +1 -1
  222. package/package.json +8 -8
  223. package/src/InputParts/index.tsx +114 -3
  224. package/src/InputParts/placeholderOverlay.native.spec.tsx +229 -0
  225. package/src/fields/Input/Input.stories.tsx +36 -0
  226. package/types/InputParts/index.d.ts +8 -0
  227. package/types/InputParts/index.d.ts.map +1 -1
@@ -0,0 +1,229 @@
1
+ import { renderWithProviders } from "@multiplatform.one/test-utils";
2
+ import { act, fireEvent } from "@testing-library/react";
3
+ import { useState } from "react";
4
+ import type { ColorTokens } from "tamagui";
5
+ import { Platform } from "react-native";
6
+ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
7
+ import { Input, areaPaintsPlaceholderOverlay } from "./index";
8
+
9
+ const env = vi.hoisted(() => ({ isWeb: false }));
10
+
11
+ vi.mock("tamagui", async (importOriginal) => {
12
+ const original = await importOriginal<typeof import("tamagui")>();
13
+ return Object.defineProperty({ ...original }, "isWeb", { get: () => env.isWeb });
14
+ });
15
+
16
+ const platform = Platform as { OS: string };
17
+ const webOS = platform.OS;
18
+ const overlayId = "mp-placeholder-overlay";
19
+ const hint = "8080=web, 8443=api, 9000=minio";
20
+
21
+ function field(container: HTMLElement): HTMLInputElement {
22
+ const input = container.querySelector("input");
23
+ if (!input) throw new Error("no input rendered");
24
+ return input;
25
+ }
26
+
27
+ function nativePlaceholderColor(container: HTMLElement): string {
28
+ return field(container).style.getPropertyValue("--t_placeholderColor").trim();
29
+ }
30
+
31
+ function Controlled({ initial = "" }: { initial?: string }) {
32
+ const [value, setValue] = useState(initial);
33
+ return (
34
+ <Input size="$3">
35
+ <Input.Area placeholder={hint} value={value} onChangeText={setValue} />
36
+ <button type="button" onClick={() => setValue("")}>
37
+ reset
38
+ </button>
39
+ </Input>
40
+ );
41
+ }
42
+
43
+ beforeEach(() => {
44
+ env.isWeb = false;
45
+ platform.OS = "ios";
46
+ });
47
+
48
+ afterEach(() => {
49
+ platform.OS = webOS;
50
+ env.isWeb = true;
51
+ });
52
+
53
+ describe("FZ-8144 iOS placeholder on the typed line", () => {
54
+ it("paints only on iOS, single-line, never on web or Android", () => {
55
+ expect(areaPaintsPlaceholderOverlay()).toBe(true);
56
+ expect(areaPaintsPlaceholderOverlay(true)).toBe(false);
57
+ platform.OS = "android";
58
+ expect(areaPaintsPlaceholderOverlay()).toBe(false);
59
+ platform.OS = "ios";
60
+ env.isWeb = true;
61
+ expect(areaPaintsPlaceholderOverlay()).toBe(false);
62
+ });
63
+
64
+ it("an empty Area draws the overlay and keeps the native placeholder transparent for VoiceOver", () => {
65
+ const { container, getByTestId } = renderWithProviders(
66
+ <Input size="$3">
67
+ <Input.Area placeholder={hint} />
68
+ </Input>,
69
+ );
70
+ const overlay = getByTestId(overlayId);
71
+ expect(overlay.textContent).toBe(hint);
72
+ expect(nativePlaceholderColor(container)).toBe("transparent");
73
+ expect(field(container).getAttribute("placeholder")).toBe(hint);
74
+ });
75
+
76
+ it("the overlay is hidden from accessibility and takes no touches", () => {
77
+ const { getByTestId, queryByText } = renderWithProviders(
78
+ <Input size="$3">
79
+ <Input.Area placeholder={hint} />
80
+ </Input>,
81
+ );
82
+ const overlay = getByTestId(overlayId);
83
+ expect(overlay.getAttribute("aria-hidden")).toBe("true");
84
+ expect(getComputedStyle(overlay).pointerEvents).toBe("none");
85
+ expect(getComputedStyle(overlay).position).toBe("absolute");
86
+ expect(queryByText(hint, { ignore: "[aria-hidden] *, [aria-hidden]" })).toBeNull();
87
+ });
88
+
89
+ it("follows the consumer's placeholder colour, the native one stays transparent", () => {
90
+ const { container, getByTestId } = renderWithProviders(
91
+ <Input size="$3">
92
+ <Input.Area placeholder={hint} placeholderTextColor={"rgb(1, 2, 3)" as ColorTokens} />
93
+ </Input>,
94
+ );
95
+ expect(nativePlaceholderColor(container)).toBe("transparent");
96
+ const text = getByTestId(overlayId).firstElementChild as HTMLElement;
97
+ expect(getComputedStyle(text).color).toBe("rgb(1, 2, 3)");
98
+ });
99
+
100
+ it("a filled Area renders no overlay", () => {
101
+ const { queryByTestId } = renderWithProviders(
102
+ <Input size="$3">
103
+ <Input.Area placeholder={hint} defaultValue="app.example.com" />
104
+ </Input>,
105
+ );
106
+ expect(queryByTestId(overlayId)).toBeNull();
107
+ });
108
+
109
+ it("hides on the first typed character and returns when the field empties", () => {
110
+ const { container, queryByTestId } = renderWithProviders(
111
+ <Input size="$3">
112
+ <Input.Area placeholder={hint} />
113
+ </Input>,
114
+ );
115
+ expect(queryByTestId(overlayId)).not.toBeNull();
116
+ act(() => {
117
+ fireEvent.change(field(container), { target: { value: "a" } });
118
+ });
119
+ expect(queryByTestId(overlayId)).toBeNull();
120
+ act(() => {
121
+ fireEvent.change(field(container), { target: { value: "" } });
122
+ });
123
+ expect(queryByTestId(overlayId)).not.toBeNull();
124
+ });
125
+
126
+ it("hides while an IME composes, before any character commits", () => {
127
+ const { container, queryByTestId } = renderWithProviders(<Controlled />);
128
+ act(() => {
129
+ fireEvent.change(field(container), { target: { value: "か" } });
130
+ });
131
+ expect(queryByTestId(overlayId)).toBeNull();
132
+ });
133
+
134
+ it("tracks a controlled value both ways", () => {
135
+ const { container, getByText, queryByTestId } = renderWithProviders(
136
+ <Controlled initial="web" />,
137
+ );
138
+ expect(queryByTestId(overlayId)).toBeNull();
139
+ act(() => {
140
+ fireEvent.click(getByText("reset"));
141
+ });
142
+ expect(queryByTestId(overlayId)).not.toBeNull();
143
+ act(() => {
144
+ fireEvent.change(field(container), { target: { value: "x" } });
145
+ });
146
+ expect(queryByTestId(overlayId)).toBeNull();
147
+ });
148
+
149
+ it("multiline keeps the native placeholder, which RN draws itself", () => {
150
+ const { container, queryByTestId } = renderWithProviders(
151
+ <Input size="$3">
152
+ <Input.Area placeholder={hint} multiline />
153
+ </Input>,
154
+ );
155
+ expect(queryByTestId(overlayId)).toBeNull();
156
+ expect(nativePlaceholderColor(container)).not.toBe("transparent");
157
+ });
158
+
159
+ it("Android and web keep the native placeholder", () => {
160
+ platform.OS = "android";
161
+ const android = renderWithProviders(
162
+ <Input size="$3">
163
+ <Input.Area placeholder={hint} />
164
+ </Input>,
165
+ );
166
+ expect(android.queryByTestId(overlayId)).toBeNull();
167
+ expect(nativePlaceholderColor(android.container)).not.toBe("transparent");
168
+ android.unmount();
169
+ platform.OS = "ios";
170
+ env.isWeb = true;
171
+ const web = renderWithProviders(
172
+ <Input size="$3">
173
+ <Input.Area placeholder={hint} />
174
+ </Input>,
175
+ );
176
+ expect(web.queryByTestId(overlayId)).toBeNull();
177
+ expect(nativePlaceholderColor(web.container)).not.toBe("transparent");
178
+ });
179
+
180
+ it("sits on the typed line: fills the Area, centred, in the field's own font and size", () => {
181
+ for (const size of ["$3", "$4"] as const) {
182
+ const { container, getByTestId, unmount } = renderWithProviders(
183
+ <Input size={size}>
184
+ <Input.Area placeholder={hint} />
185
+ </Input>,
186
+ );
187
+ const overlay = getByTestId(overlayId);
188
+ const box = getComputedStyle(overlay);
189
+ expect(box.position).toBe("absolute");
190
+ for (const edge of ["top", "bottom", "left", "right"] as const) {
191
+ expect(box[edge]).toBe("0px");
192
+ }
193
+ expect(box.justifyContent).toBe("center");
194
+ const typed = getComputedStyle(field(container));
195
+ const text = getComputedStyle(overlay.firstElementChild as HTMLElement);
196
+ expect(text.fontSize).not.toBe("");
197
+ expect(text.fontSize).toBe(typed.fontSize);
198
+ expect(text.fontFamily).toBe(typed.fontFamily);
199
+ expect(text.fontWeight).toBe(typed.fontWeight);
200
+ expect(text.lineHeight).toBe(typed.lineHeight);
201
+ unmount();
202
+ }
203
+ });
204
+
205
+ it("follows the Area's inset and RTL alignment", () => {
206
+ const { getByTestId } = renderWithProviders(
207
+ <Input size="$3">
208
+ <Input.Area placeholder={hint} paddingHorizontal={12} textAlign="right" />
209
+ </Input>,
210
+ );
211
+ const overlay = getByTestId(overlayId);
212
+ expect(getComputedStyle(overlay).paddingLeft).toBe("12px");
213
+ expect(getComputedStyle(overlay).paddingRight).toBe("12px");
214
+ const text = getComputedStyle(overlay.firstElementChild as HTMLElement);
215
+ expect(text.textAlign).toBe("right");
216
+ });
217
+
218
+ it("the overlay text truncates to one line with a tail ellipsis", () => {
219
+ const { getByTestId } = renderWithProviders(
220
+ <Input size="$3">
221
+ <Input.Area placeholder={hint} />
222
+ </Input>,
223
+ );
224
+ const text = getByTestId(overlayId).firstElementChild as HTMLElement;
225
+ const style = getComputedStyle(text);
226
+ expect(style.whiteSpace).toBe("nowrap");
227
+ expect(style.textOverflow).toBe("ellipsis");
228
+ });
229
+ });
@@ -7,6 +7,7 @@ import { useState } from "react";
7
7
  import { Input as TamaguiInput, XStack, YStack } from "tamagui";
8
8
  import { Button } from "../../Button";
9
9
  import { Form } from "../../Form";
10
+ import { SearchInput } from "../SearchInput";
10
11
  import { Input } from "./index";
11
12
  import { Paragraph } from "@multiplatform.one/theme";
12
13
 
@@ -114,6 +115,41 @@ export const Sizes: Story = {
114
115
  ),
115
116
  };
116
117
 
118
+ /** FZ-8144: each row pairs an empty field with a typed one; the placeholder sits on the typed line. */
119
+ export const PlaceholderOnTypedLine: Story = {
120
+ name: "Placeholder on the typed line",
121
+ render: () => (
122
+ <YStack gap="$3" maxWidth={400}>
123
+ {(["$3", "$4"] as const).map((size) => (
124
+ <XStack key={`input${size}`} gap="$2">
125
+ <YStack flex={1}>
126
+ <Input size={size} label={`Empty ${size}`} labelHidden placeholder="8080=web" />
127
+ </YStack>
128
+ <YStack flex={1}>
129
+ <Input size={size} label={`Typed ${size}`} labelHidden defaultValue="8080=web" />
130
+ </YStack>
131
+ </XStack>
132
+ ))}
133
+ {(["$3", "$4"] as const).map((size) => (
134
+ <XStack key={`search${size}`} gap="$2">
135
+ <YStack flex={1}>
136
+ <SearchInput size={size} placeholder="8080=web" clearable={false} />
137
+ </YStack>
138
+ <YStack flex={1}>
139
+ <SearchInput size={size} defaultValue="8080=web" clearable={false} />
140
+ </YStack>
141
+ </XStack>
142
+ ))}
143
+ <Input
144
+ size="$3"
145
+ label="Long placeholder"
146
+ labelHidden
147
+ placeholder="8080=web, 8443=api, 9000=minio, 5432=postgres, 6379=redis"
148
+ />
149
+ </YStack>
150
+ ),
151
+ };
152
+
117
153
  export const ReadOnly: Story = {
118
154
  args: {
119
155
  label: "Account id",
@@ -111,6 +111,14 @@ export type InputModeValue = ComponentProps<typeof TInput>["inputMode"];
111
111
  export declare function mapKeyboardTypeToInputMode(keyboardType?: string): MappedInputMode | undefined;
112
112
  export declare function mapInputModeToKeyboardType(inputMode?: string): MappedKeyboardType | undefined;
113
113
  export declare const inputSizeVariant: SizeVariantSpreadFunction<any>;
114
+ /**
115
+ * FZ-8144: an iOS update moved UIKit's own placeholder 3pt below the typed
116
+ * line on Clay's phone, while RN Text stayed put. On iOS a single-line Area
117
+ * paints its visible placeholder as Text centred like the typed line, and
118
+ * keeps the native one transparent so VoiceOver still reads it. Multiline
119
+ * stays native: RN draws that placeholder itself, not UIKit.
120
+ */
121
+ export declare function areaPaintsPlaceholderOverlay(multiline?: boolean): boolean;
114
122
  export interface InputActionProps {
115
123
  /** Accessible name; the glyph is decorative. */
116
124
  label: string;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/InputParts/index.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/InputParts/index.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,cAAc,CAAC;AAC9D,OAAO,EAOL,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AACf,OAAO,KAAK,EAAE,cAAc,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAE5D,OAAO,KAAK,EACV,WAAW,EACX,cAAc,EACd,iBAAiB,EACjB,oBAAoB,EACpB,UAAU,EACV,cAAc,EACf,MAAM,SAAS,CAAC;AACjB,OAAO,EAEL,KAAK,IAAI,MAAM,EAWhB,MAAM,SAAS,CAAC;AACjB,OAAO,EAoBL,KAAK,gBAAgB,EACtB,MAAM,0BAA0B,CAAC;AAkClC,eAAO,MAAM,YAAY;UACjB,cAAc;eACT,MAAM;WACV,OAAO;YACN,WAAW,GAAG,MAAM;EACN,CAAC;AAmDzB,eAAO,MAAM,YAAY;uBACJ,OAAO;;EAE1B,CAAC;AAEH,wEAAwE;AACxE,eAAO,MAAM,eAAe,GAAI,QAAQ,SAAS,CAAC,cAAc,GAAG,IAAI,CAAC;;;;CAYvE,CAAC;AAsBF,eAAO,MAAM,iBAAiB,QAgB5B,CAAC;AAIH,wBAAgB,yBAAyB,IAAI,IAAI,CAOhD;AAuBD,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0B1B,CAAC;AAyCX,wBAAgB,oBAAoB,CAAC,EACnC,MAAM,EACN,QAAQ,GACT,EAAE;IACD,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,SAAS,CAAC;CACrB,2CAMA;AAqTD,eAAO,MAAM,sBAAsB;;;;;;CAMzB,CAAC;AAEX,eAAO,MAAM,sBAAsB;;;;;CAKzB,CAAC;AAEX;;;GAGG;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,sBAAsB,CAAC,CAAC,MAAM,OAAO,sBAAsB,CAAC,CAAC;AAEnG,sFAAsF;AACtF,MAAM,MAAM,kBAAkB,GAC5B,CAAC,OAAO,sBAAsB,CAAC,CAAC,MAAM,OAAO,sBAAsB,CAAC,CAAC;AAEvE;;;;;GAKG;AACH,MAAM,MAAM,cAAc,GAAG,cAAc,CAAC,OAAO,MAAM,CAAC,CAAC,WAAW,CAAC,CAAC;AAExE,wBAAgB,0BAA0B,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS,CAG7F;AAED,wBAAgB,0BAA0B,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,kBAAkB,GAAG,SAAS,CAG7F;AAED,eAAO,MAAM,gBAAgB,EAAE,yBAAyB,CAAC,GAAG,CAS3D,CAAC;AAqDF;;;;;;GAMG;AACH,wBAAgB,4BAA4B,CAAC,SAAS,CAAC,EAAE,OAAO,GAAG,OAAO,CAEzE;AAodD,MAAM,WAAW,gBAAgB;IAC/B,gDAAgD;IAChD,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,gFAAgF;IAChF,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,0DAA0D;IAC1D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,UAAU,GAAG,cAAc,CAAC;IACnC;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iEAAiE;IACjE,WAAW,CAAC,EAAE,CAAC,CAAC,EAAE;QAAE,eAAe,EAAE,MAAM,IAAI,CAAC;QAAC,cAAc,EAAE,MAAM,IAAI,CAAA;KAAE,KAAK,IAAI,CAAC;IACvF,CAAC,IAAI,EAAE,QAAQ,MAAM,EAAE,GAAG,MAAM,GAAG,SAAS,CAAC;IAC7C,QAAQ,EAAE,SAAS,CAAC;CACrB;AAkED,eAAO,MAAM,cAAc;;;;;6CAoBzB,CAAC;AA0CH,eAAO,MAAM,mBAAmB;;;;;;6CAyB9B,CAAC;AAwCH,eAAO,MAAM,UAAU;;;;;;;;;;6CAKrB,CAAC;AAqCH,eAAO,MAAM,SAAS;;;;;;;;;;6CAGpB,CAAC;AAEH;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,EAC7B,UAAU,EACV,YAAY,GACb,EAAE;IACD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;CACjC,kDAcA;AAwBD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAErD,KAAK,oBAAoB,GAAG,cAAc,CAAC,OAAO,cAAc,CAAC,CAAC;AAElE,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,oBAAoB,GAAG;IAAE,QAAQ,CAAC,EAAE,GAAG,CAAC,GAAG,CAAC,CAAA;CAAE,2CAoDvF;AAoBD,eAAO,MAAM,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAhuChB;;;;WAIG;4BACiB,OAAO;QAC3B;;;WAGG;uBACY,gBAAgB;QAC/B;;;;WAIG;2BACgB,MAAM;;;;QAhBzB;;;;WAIG;4BACiB,OAAO;QAC3B;;;WAGG;uBACY,gBAAgB;QAC/B;;;;WAIG;2BACgB,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;eAQR,CAAC;;;;;;;;;;;;;;;;;;;;;;;;0BAsZA,OAAO;uBACV,iBAAiB;0BACd,oBAAoB;uBACvB,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;eAzZpB,CAAC;;;;;;;;;;;;0BAsZA,OAAO;uBACV,iBAAiB;0BACd,oBAAoB;uBACvB,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;oBAgTqB,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;oBAAP,OAAO;;;;;;;;;;;;;;;;;;;oBA2OrD,MAAM;gBACV,WAAW,GAAG,MAAM;oBAChB,SAAS,GAAG,UAAU;;oBAFtB,MAAM;gBACV,WAAW,GAAG,MAAM;oBAChB,SAAS,GAAG,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkRF,CAAC"}