@xaui/native 0.0.21 → 0.0.24

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 (113) hide show
  1. package/README.md +195 -2
  2. package/dist/alert/index.js +1 -2
  3. package/dist/app-bar/index.cjs +217 -0
  4. package/dist/app-bar/index.d.cts +52 -0
  5. package/dist/app-bar/index.d.ts +52 -0
  6. package/dist/app-bar/index.js +142 -0
  7. package/dist/autocomplete/index.js +48 -36
  8. package/dist/avatar/index.js +1 -2
  9. package/dist/badge/index.js +1 -2
  10. package/dist/bottom-sheet/index.js +1 -2
  11. package/dist/bottom-tab-bar/index.cjs +571 -0
  12. package/dist/bottom-tab-bar/index.d.cts +211 -0
  13. package/dist/bottom-tab-bar/index.d.ts +211 -0
  14. package/dist/bottom-tab-bar/index.js +497 -0
  15. package/dist/button/index.d.cts +102 -5
  16. package/dist/button/index.d.ts +102 -5
  17. package/dist/button/index.js +2 -3
  18. package/dist/button.type-j1ZdkkSl.d.cts +4 -0
  19. package/dist/button.type-j1ZdkkSl.d.ts +4 -0
  20. package/dist/card/index.cjs +2 -0
  21. package/dist/card/index.d.cts +6 -1
  22. package/dist/card/index.d.ts +6 -1
  23. package/dist/card/index.js +4 -2
  24. package/dist/carousel/index.js +1 -1
  25. package/dist/chart/index.cjs +1067 -0
  26. package/dist/chart/index.d.cts +218 -0
  27. package/dist/chart/index.d.ts +218 -0
  28. package/dist/chart/index.js +1026 -0
  29. package/dist/checkbox/index.js +1 -2
  30. package/dist/chip/index.js +1 -2
  31. package/dist/chunk-3XSXTM3G.js +661 -0
  32. package/dist/chunk-4KSZLONZ.js +79 -0
  33. package/dist/{chunk-DXXNBF5P.js → chunk-CZFDZPAS.js} +0 -5
  34. package/dist/{chunk-LTKYHG5V.js → chunk-GHCVNQET.js} +12 -5
  35. package/dist/chunk-I4V5Y5GD.js +76 -0
  36. package/dist/{chunk-F7WH4DMG.js → chunk-UI5L26KD.js} +1 -1
  37. package/dist/{chunk-LUBWRVI2.js → chunk-ULJSCNPE.js} +1 -1
  38. package/dist/chunk-URBEEDFX.js +79 -0
  39. package/dist/core/index.js +3 -5
  40. package/dist/datepicker/index.js +1 -2
  41. package/dist/divider/index.js +2 -3
  42. package/dist/drawer/index.cjs +310 -0
  43. package/dist/drawer/index.d.cts +58 -0
  44. package/dist/drawer/index.d.ts +58 -0
  45. package/dist/drawer/index.js +236 -0
  46. package/dist/{accordion → expansion-panel}/index.cjs +45 -45
  47. package/dist/{accordion → expansion-panel}/index.d.cts +30 -30
  48. package/dist/{accordion → expansion-panel}/index.d.ts +30 -30
  49. package/dist/{accordion → expansion-panel}/index.js +40 -41
  50. package/dist/fab/index.d.cts +3 -3
  51. package/dist/fab/index.d.ts +3 -3
  52. package/dist/fab/index.js +3 -4
  53. package/dist/fab-menu/index.d.cts +2 -2
  54. package/dist/fab-menu/index.d.ts +2 -2
  55. package/dist/fab-menu/index.js +3 -4
  56. package/dist/{fab.type-Ba0QMprb.d.ts → fab.type-CgIYqQlT.d.ts} +1 -1
  57. package/dist/{fab.type-U09H8B7D.d.cts → fab.type-l2vjG8-p.d.cts} +1 -1
  58. package/dist/feature-discovery/index.cjs +531 -0
  59. package/dist/feature-discovery/index.d.cts +82 -0
  60. package/dist/feature-discovery/index.d.ts +82 -0
  61. package/dist/feature-discovery/index.js +464 -0
  62. package/dist/indicator/index.js +2 -3
  63. package/dist/input/index.cjs +258 -164
  64. package/dist/input/index.d.cts +15 -1
  65. package/dist/input/index.d.ts +15 -1
  66. package/dist/input/index.js +219 -126
  67. package/dist/list/index.js +1 -2
  68. package/dist/menu/index.js +2 -2
  69. package/dist/menubox/index.cjs +369 -0
  70. package/dist/menubox/index.d.cts +98 -0
  71. package/dist/menubox/index.d.ts +98 -0
  72. package/dist/menubox/index.js +296 -0
  73. package/dist/pager/index.cjs +243 -0
  74. package/dist/pager/index.d.cts +93 -0
  75. package/dist/pager/index.d.ts +93 -0
  76. package/dist/pager/index.js +205 -0
  77. package/dist/progress/index.js +1 -2
  78. package/dist/radio/index.cjs +537 -0
  79. package/dist/radio/index.d.cts +145 -0
  80. package/dist/radio/index.d.ts +145 -0
  81. package/dist/radio/index.js +464 -0
  82. package/dist/segment-button/index.js +2 -2
  83. package/dist/select/index.js +22 -10
  84. package/dist/skeleton/index.js +2 -2
  85. package/dist/slider/index.cjs +655 -0
  86. package/dist/slider/index.d.cts +171 -0
  87. package/dist/slider/index.d.ts +171 -0
  88. package/dist/slider/index.js +575 -0
  89. package/dist/stepper/index.cjs +624 -0
  90. package/dist/stepper/index.d.cts +137 -0
  91. package/dist/stepper/index.d.ts +137 -0
  92. package/dist/stepper/index.js +549 -0
  93. package/dist/switch/index.js +1 -2
  94. package/dist/tabs/index.cjs +523 -0
  95. package/dist/tabs/index.d.cts +176 -0
  96. package/dist/tabs/index.d.ts +176 -0
  97. package/dist/tabs/index.js +438 -0
  98. package/dist/timepicker/index.cjs +1280 -0
  99. package/dist/timepicker/index.d.cts +215 -0
  100. package/dist/timepicker/index.d.ts +215 -0
  101. package/dist/timepicker/index.js +1181 -0
  102. package/dist/toolbar/index.cjs +395 -0
  103. package/dist/toolbar/index.d.cts +100 -0
  104. package/dist/toolbar/index.d.ts +100 -0
  105. package/dist/toolbar/index.js +325 -0
  106. package/dist/typography/index.js +1 -2
  107. package/dist/view/index.cjs +16 -2
  108. package/dist/view/index.js +16 -2
  109. package/package.json +73 -8
  110. package/dist/button.type-D8tzEBo7.d.ts +0 -104
  111. package/dist/button.type-ikaWzhIg.d.cts +0 -104
  112. package/dist/chunk-GBHQCAKW.js +0 -19
  113. package/dist/chunk-JEGEPGVU.js +0 -287
@@ -0,0 +1,531 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/components/feature-discovery/index.ts
31
+ var feature_discovery_exports = {};
32
+ __export(feature_discovery_exports, {
33
+ FeatureDiscovery: () => FeatureDiscovery
34
+ });
35
+ module.exports = __toCommonJS(feature_discovery_exports);
36
+
37
+ // src/components/feature-discovery/feature-discovery.tsx
38
+ var import_react7 = __toESM(require("react"), 1);
39
+ var import_react_native6 = require("react-native");
40
+ var import_core3 = require("@xaui/core");
41
+
42
+ // src/components/feature-discovery/feature-discovery.style.ts
43
+ var import_react_native = require("react-native");
44
+ var styles = import_react_native.StyleSheet.create({
45
+ root: {
46
+ flex: 1
47
+ },
48
+ absoluteFill: {
49
+ ...import_react_native.StyleSheet.absoluteFillObject
50
+ },
51
+ circle: {
52
+ position: "absolute"
53
+ },
54
+ spotlightHalo: {
55
+ position: "absolute",
56
+ borderWidth: 1,
57
+ borderColor: "rgba(255, 255, 255, 0.35)"
58
+ },
59
+ highlightContainer: {
60
+ position: "absolute",
61
+ alignItems: "center",
62
+ justifyContent: "center"
63
+ },
64
+ messageContainer: {
65
+ position: "absolute",
66
+ gap: 10,
67
+ paddingVertical: 16,
68
+ paddingHorizontal: 16,
69
+ borderRadius: 12
70
+ },
71
+ messageHeader: {
72
+ flexDirection: "row",
73
+ alignItems: "flex-start",
74
+ justifyContent: "space-between",
75
+ gap: 8
76
+ },
77
+ messageTitleWrapper: {
78
+ flex: 1
79
+ },
80
+ title: {
81
+ fontSize: 24,
82
+ fontWeight: "700"
83
+ },
84
+ closeButton: {
85
+ padding: 4
86
+ },
87
+ closeIcon: {
88
+ fontSize: 18,
89
+ fontWeight: "600"
90
+ },
91
+ description: {
92
+ fontSize: 16,
93
+ fontWeight: "400",
94
+ opacity: 0.86,
95
+ lineHeight: 22
96
+ },
97
+ actionPressable: {
98
+ alignSelf: "flex-start"
99
+ },
100
+ actionText: {
101
+ fontSize: 14,
102
+ fontWeight: "600",
103
+ textDecorationLine: "underline"
104
+ }
105
+ });
106
+
107
+ // src/components/feature-discovery/feature-discovery.hook.ts
108
+ var import_react6 = require("react");
109
+ var import_react_native5 = require("react-native");
110
+ var import_core = require("@xaui/core");
111
+
112
+ // src/core/theme-context.tsx
113
+ var import_react4 = __toESM(require("react"), 1);
114
+ var import_react_native3 = require("react-native");
115
+ var import_theme = require("@xaui/core/theme");
116
+ var import_palette = require("@xaui/core/palette");
117
+
118
+ // src/core/portal/portal.tsx
119
+ var import_react2 = require("react");
120
+
121
+ // src/core/portal/portal-context.ts
122
+ var import_react = require("react");
123
+ var PortalContext = (0, import_react.createContext)(null);
124
+
125
+ // src/core/portal/portal-host.tsx
126
+ var import_react3 = __toESM(require("react"), 1);
127
+ var import_react_native2 = require("react-native");
128
+ var hostStyles = import_react_native2.StyleSheet.create({
129
+ container: {
130
+ flex: 1
131
+ }
132
+ });
133
+
134
+ // src/core/theme-context.tsx
135
+ var XUIThemeContext = (0, import_react4.createContext)(null);
136
+
137
+ // src/core/theme-hooks.ts
138
+ var import_react5 = require("react");
139
+ var import_react_native4 = require("react-native");
140
+ function useXUITheme() {
141
+ const theme = (0, import_react5.useContext)(XUIThemeContext);
142
+ if (!theme) {
143
+ throw new Error("useXUITheme must be used within XUIProvider");
144
+ }
145
+ return theme;
146
+ }
147
+
148
+ // src/core/index.ts
149
+ var import_theme2 = require("@xaui/core/theme");
150
+
151
+ // src/components/feature-discovery/feature-discovery.hook.ts
152
+ var useFeatureDiscoveryAnimations = () => {
153
+ const backdropOpacity = (0, import_react6.useRef)(new import_react_native5.Animated.Value(0)).current;
154
+ const circleAnimScale = (0, import_react6.useRef)(new import_react_native5.Animated.Value(0.2)).current;
155
+ const contentOpacity = (0, import_react6.useRef)(new import_react_native5.Animated.Value(0)).current;
156
+ const haloScale = (0, import_react6.useRef)(new import_react_native5.Animated.Value(0.8)).current;
157
+ const startAnimations = (0, import_react6.useCallback)(() => {
158
+ import_react_native5.Animated.parallel([
159
+ import_react_native5.Animated.timing(backdropOpacity, {
160
+ toValue: 1,
161
+ duration: 220,
162
+ useNativeDriver: true
163
+ }),
164
+ import_react_native5.Animated.spring(circleAnimScale, {
165
+ toValue: 1,
166
+ friction: 8,
167
+ tension: 80,
168
+ useNativeDriver: true
169
+ }),
170
+ import_react_native5.Animated.timing(contentOpacity, {
171
+ toValue: 1,
172
+ duration: 260,
173
+ useNativeDriver: true
174
+ }),
175
+ import_react_native5.Animated.spring(haloScale, {
176
+ toValue: 1,
177
+ friction: 8,
178
+ tension: 80,
179
+ useNativeDriver: true
180
+ })
181
+ ]).start();
182
+ }, [backdropOpacity, circleAnimScale, contentOpacity, haloScale]);
183
+ const resetAnimations = (0, import_react6.useCallback)(() => {
184
+ backdropOpacity.setValue(0);
185
+ circleAnimScale.setValue(0.2);
186
+ contentOpacity.setValue(0);
187
+ haloScale.setValue(0.8);
188
+ }, [backdropOpacity, circleAnimScale, contentOpacity, haloScale]);
189
+ return {
190
+ backdropOpacity,
191
+ circleAnimScale,
192
+ contentOpacity,
193
+ haloScale,
194
+ startAnimations,
195
+ resetAnimations
196
+ };
197
+ };
198
+ var useFeatureDiscoveryLayout = (targetRef) => {
199
+ const { width: viewportWidth, height: viewportHeight } = (0, import_react_native5.useWindowDimensions)();
200
+ const [targetLayout, setTargetLayout] = (0, import_react6.useState)(null);
201
+ const measureTarget = (0, import_react6.useCallback)(() => {
202
+ targetRef.current?.measureInWindow((x, y, width, height) => {
203
+ if (!width && !height) {
204
+ setTargetLayout({
205
+ x: viewportWidth / 2 - 28,
206
+ y: viewportHeight / 2 - 28,
207
+ width: 56,
208
+ height: 56
209
+ });
210
+ return;
211
+ }
212
+ setTargetLayout({ x, y, width, height });
213
+ });
214
+ }, [targetRef, viewportHeight, viewportWidth]);
215
+ const fallbackTarget = (0, import_react6.useMemo)(
216
+ () => ({
217
+ x: viewportWidth / 2 - 28,
218
+ y: viewportHeight / 2 - 28,
219
+ width: 56,
220
+ height: 56
221
+ }),
222
+ [viewportWidth, viewportHeight]
223
+ );
224
+ const target = targetLayout ?? fallbackTarget;
225
+ return {
226
+ targetLayout,
227
+ target,
228
+ measureTarget,
229
+ setTargetLayout,
230
+ viewportWidth,
231
+ viewportHeight
232
+ };
233
+ };
234
+ var useFeatureDiscoveryGeometry = (target, viewportWidth, viewportHeight, spotlightPadding, circleScale) => {
235
+ const HIGHLIGHT_EDGE_INSET = 16;
236
+ const maxTargetX = Math.max(
237
+ HIGHLIGHT_EDGE_INSET,
238
+ viewportWidth - target.width - HIGHLIGHT_EDGE_INSET
239
+ );
240
+ const maxTargetY = Math.max(
241
+ HIGHLIGHT_EDGE_INSET,
242
+ viewportHeight - target.height - HIGHLIGHT_EDGE_INSET
243
+ );
244
+ const clampedTargetX = Math.min(
245
+ Math.max(target.x, HIGHLIGHT_EDGE_INSET),
246
+ maxTargetX
247
+ );
248
+ const clampedTargetY = Math.min(
249
+ Math.max(target.y, HIGHLIGHT_EDGE_INSET),
250
+ maxTargetY
251
+ );
252
+ const targetCenterX = clampedTargetX + target.width / 2;
253
+ const targetCenterY = clampedTargetY + target.height / 2;
254
+ const spotlightSize = Math.max(target.width, target.height) + spotlightPadding * 2;
255
+ const circleDiameter = (0, import_react6.useMemo)(() => {
256
+ return viewportWidth * circleScale;
257
+ }, [circleScale, viewportWidth]);
258
+ const circleRadius = circleDiameter / 2;
259
+ const TEXT_PADDING = 24;
260
+ const TARGET_GAP = 30;
261
+ const MIN_MESSAGE_HEIGHT = 140;
262
+ const MIN_MESSAGE_WIDTH = 280;
263
+ const MESSAGE_VERTICAL_OFFSET = 14;
264
+ const isTargetInTopHalf = targetCenterY < viewportHeight * 0.55;
265
+ const baseMessageTop = isTargetInTopHalf ? Math.min(viewportHeight - 200, clampedTargetY + target.height + TARGET_GAP) : Math.max(TEXT_PADDING, clampedTargetY - 150);
266
+ const messageTop = Math.max(TEXT_PADDING, baseMessageTop - MESSAGE_VERTICAL_OFFSET);
267
+ const textDy = messageTop - targetCenterY;
268
+ const textHalfChord = Math.abs(textDy) < circleRadius ? Math.sqrt(circleRadius ** 2 - textDy ** 2) : 0;
269
+ const baseMsgLeft = Math.max(
270
+ TEXT_PADDING,
271
+ targetCenterX - textHalfChord + TEXT_PADDING
272
+ );
273
+ const baseMsgRight = Math.max(
274
+ TEXT_PADDING,
275
+ viewportWidth - (targetCenterX + textHalfChord - TEXT_PADDING)
276
+ );
277
+ const baseMsgWidth = viewportWidth - baseMsgLeft - baseMsgRight;
278
+ const clampedMinMessageWidth = Math.min(
279
+ MIN_MESSAGE_WIDTH,
280
+ viewportWidth - TEXT_PADDING * 2
281
+ );
282
+ const isTargetOnLeft = targetCenterX < viewportWidth / 2;
283
+ const shouldUseSideAnchoredLayout = baseMsgWidth < clampedMinMessageWidth;
284
+ const msgLeft = shouldUseSideAnchoredLayout ? isTargetOnLeft ? TEXT_PADDING : viewportWidth - TEXT_PADDING - clampedMinMessageWidth : baseMsgLeft;
285
+ const msgRight = shouldUseSideAnchoredLayout ? isTargetOnLeft ? viewportWidth - TEXT_PADDING - clampedMinMessageWidth : TEXT_PADDING : baseMsgRight;
286
+ const circleBottomY = targetCenterY + circleRadius - TEXT_PADDING;
287
+ const msgMaxHeight = Math.max(MIN_MESSAGE_HEIGHT, circleBottomY - messageTop);
288
+ return {
289
+ targetCenterX,
290
+ targetCenterY,
291
+ spotlightSize,
292
+ circleDiameter,
293
+ circleRadius,
294
+ messageTop,
295
+ msgLeft,
296
+ msgRight,
297
+ msgMaxHeight,
298
+ isTargetOnLeft,
299
+ highlightX: clampedTargetX,
300
+ highlightY: clampedTargetY
301
+ };
302
+ };
303
+ var useFeatureDiscoveryTheme = (themeColor, overlayColor) => {
304
+ const theme = useXUITheme();
305
+ const colorScheme = theme.colors[(0, import_core.getSafeThemeColor)(themeColor)];
306
+ const resolvedOverlayColor = (0, import_react6.useMemo)(
307
+ () => overlayColor ?? (0, import_core.withOpacity)(theme.colors.foreground, 0.42),
308
+ [overlayColor, theme.colors.foreground]
309
+ );
310
+ return {
311
+ colorScheme,
312
+ resolvedOverlayColor
313
+ };
314
+ };
315
+
316
+ // src/components/feature-discovery/feature-discovery.tsx
317
+ var DEFAULT_SPOTLIGHT_PADDING = 14;
318
+ var DEFAULT_CIRCLE_SCALE = 1.65;
319
+ var FeatureDiscovery = ({
320
+ isVisible,
321
+ targetRef,
322
+ title,
323
+ description,
324
+ actionText,
325
+ onActionPress,
326
+ onDismiss,
327
+ dismissOnBackdropPress = true,
328
+ themeColor = "primary",
329
+ overlayColor,
330
+ spotlightPadding = DEFAULT_SPOTLIGHT_PADDING,
331
+ circleScale = DEFAULT_CIRCLE_SCALE,
332
+ highlightContent,
333
+ customAppearance
334
+ }) => {
335
+ const {
336
+ backdropOpacity,
337
+ circleAnimScale,
338
+ contentOpacity,
339
+ haloScale,
340
+ startAnimations,
341
+ resetAnimations
342
+ } = useFeatureDiscoveryAnimations();
343
+ const { target, measureTarget, setTargetLayout, viewportWidth, viewportHeight } = useFeatureDiscoveryLayout(targetRef);
344
+ const {
345
+ targetCenterX,
346
+ targetCenterY,
347
+ spotlightSize,
348
+ circleDiameter,
349
+ messageTop,
350
+ msgLeft,
351
+ msgRight,
352
+ msgMaxHeight,
353
+ isTargetOnLeft,
354
+ highlightX,
355
+ highlightY
356
+ } = useFeatureDiscoveryGeometry(
357
+ target,
358
+ viewportWidth,
359
+ viewportHeight,
360
+ spotlightPadding,
361
+ circleScale
362
+ );
363
+ const { colorScheme, resolvedOverlayColor } = useFeatureDiscoveryTheme(
364
+ themeColor,
365
+ overlayColor
366
+ );
367
+ (0, import_react7.useEffect)(() => {
368
+ if (!isVisible) {
369
+ setTargetLayout(null);
370
+ return;
371
+ }
372
+ resetAnimations();
373
+ const timer = setTimeout(() => {
374
+ measureTarget();
375
+ startAnimations();
376
+ }, 0);
377
+ return () => clearTimeout(timer);
378
+ }, [isVisible, measureTarget, resetAnimations, setTargetLayout, startAnimations]);
379
+ if (!isVisible) return null;
380
+ const renderContent = (content, textStyle) => {
381
+ if (typeof content === "string" || typeof content === "number") {
382
+ return /* @__PURE__ */ import_react7.default.createElement(import_react_native6.Text, { style: textStyle }, content);
383
+ }
384
+ return content;
385
+ };
386
+ return /* @__PURE__ */ import_react7.default.createElement(
387
+ import_react_native6.Modal,
388
+ {
389
+ visible: isVisible,
390
+ transparent: true,
391
+ animationType: "none",
392
+ statusBarTranslucent: true,
393
+ onRequestClose: onDismiss
394
+ },
395
+ /* @__PURE__ */ import_react7.default.createElement(
396
+ import_react_native6.View,
397
+ {
398
+ style: [styles.root, customAppearance?.root, customAppearance?.container]
399
+ },
400
+ /* @__PURE__ */ import_react7.default.createElement(
401
+ import_react_native6.Pressable,
402
+ {
403
+ style: styles.absoluteFill,
404
+ onPress: dismissOnBackdropPress ? onDismiss : void 0
405
+ },
406
+ /* @__PURE__ */ import_react7.default.createElement(
407
+ import_react_native6.Animated.View,
408
+ {
409
+ style: [
410
+ styles.absoluteFill,
411
+ {
412
+ backgroundColor: resolvedOverlayColor,
413
+ opacity: backdropOpacity
414
+ }
415
+ ]
416
+ }
417
+ )
418
+ ),
419
+ /* @__PURE__ */ import_react7.default.createElement(
420
+ import_react_native6.Animated.View,
421
+ {
422
+ style: [
423
+ styles.circle,
424
+ {
425
+ width: circleDiameter,
426
+ height: circleDiameter,
427
+ borderRadius: circleDiameter / 2,
428
+ left: targetCenterX - circleDiameter / 2,
429
+ top: targetCenterY - circleDiameter / 2,
430
+ backgroundColor: colorScheme.main,
431
+ opacity: contentOpacity,
432
+ transform: [{ scale: circleAnimScale }]
433
+ }
434
+ ]
435
+ }
436
+ ),
437
+ /* @__PURE__ */ import_react7.default.createElement(
438
+ import_react_native6.Animated.View,
439
+ {
440
+ style: [
441
+ styles.spotlightHalo,
442
+ {
443
+ width: spotlightSize,
444
+ height: spotlightSize,
445
+ borderRadius: spotlightSize / 2,
446
+ left: targetCenterX - spotlightSize / 2,
447
+ top: targetCenterY - spotlightSize / 2,
448
+ opacity: contentOpacity,
449
+ transform: [{ scale: haloScale }]
450
+ }
451
+ ]
452
+ }
453
+ ),
454
+ highlightContent && /* @__PURE__ */ import_react7.default.createElement(
455
+ import_react_native6.Animated.View,
456
+ {
457
+ style: [
458
+ styles.highlightContainer,
459
+ {
460
+ left: highlightX,
461
+ top: highlightY,
462
+ width: target.width,
463
+ height: target.height,
464
+ opacity: contentOpacity
465
+ },
466
+ customAppearance?.highlightContainer
467
+ ],
468
+ pointerEvents: "none"
469
+ },
470
+ highlightContent
471
+ ),
472
+ /* @__PURE__ */ import_react7.default.createElement(
473
+ import_react_native6.Animated.View,
474
+ {
475
+ style: [
476
+ styles.messageContainer,
477
+ {
478
+ top: messageTop,
479
+ left: msgLeft,
480
+ right: msgRight,
481
+ maxHeight: msgMaxHeight,
482
+ opacity: contentOpacity
483
+ },
484
+ customAppearance?.messageContainer
485
+ ],
486
+ pointerEvents: "box-none"
487
+ },
488
+ /* @__PURE__ */ import_react7.default.createElement(import_react_native6.View, { style: styles.messageHeader }, /* @__PURE__ */ import_react7.default.createElement(import_react_native6.View, { style: styles.messageTitleWrapper }, renderContent(title, [
489
+ styles.title,
490
+ { color: colorScheme.foreground },
491
+ { textAlign: isTargetOnLeft ? "left" : "right" },
492
+ customAppearance?.title
493
+ ])), /* @__PURE__ */ import_react7.default.createElement(
494
+ import_react_native6.Pressable,
495
+ {
496
+ onPress: onDismiss,
497
+ style: styles.closeButton,
498
+ accessibilityRole: "button"
499
+ },
500
+ /* @__PURE__ */ import_react7.default.createElement(import_react_native6.Text, { style: [styles.closeIcon, { color: colorScheme.foreground }] }, "\u2715")
501
+ )),
502
+ description ? renderContent(description, [
503
+ styles.description,
504
+ { color: (0, import_core3.withOpacity)(colorScheme.foreground, 0.9) },
505
+ { textAlign: isTargetOnLeft ? "left" : "right" },
506
+ customAppearance?.description
507
+ ]) : null,
508
+ actionText ? /* @__PURE__ */ import_react7.default.createElement(
509
+ import_react_native6.Pressable,
510
+ {
511
+ onPress: onActionPress,
512
+ style: [
513
+ styles.actionPressable,
514
+ { alignSelf: isTargetOnLeft ? "flex-start" : "flex-end" }
515
+ ],
516
+ accessibilityRole: "button"
517
+ },
518
+ renderContent(actionText, [
519
+ styles.actionText,
520
+ { color: colorScheme.foreground },
521
+ customAppearance?.actionText
522
+ ])
523
+ ) : null
524
+ )
525
+ )
526
+ );
527
+ };
528
+ // Annotate the CommonJS export names for ESM import in node:
529
+ 0 && (module.exports = {
530
+ FeatureDiscovery
531
+ });
@@ -0,0 +1,82 @@
1
+ import React, { RefObject, ReactNode } from 'react';
2
+ import { ViewStyle, TextStyle } from 'react-native';
3
+ import { T as ThemeColor } from '../index-BOw6tbkc.cjs';
4
+
5
+ type MeasurableNode = {
6
+ measureInWindow: (callback: (x: number, y: number, width: number, height: number) => void) => void;
7
+ };
8
+ type FeatureDiscoveryCustomAppearance = {
9
+ root?: ViewStyle;
10
+ container?: ViewStyle;
11
+ title?: TextStyle;
12
+ description?: TextStyle;
13
+ actionText?: TextStyle;
14
+ highlightContainer?: ViewStyle;
15
+ messageContainer?: ViewStyle;
16
+ };
17
+ type FeatureDiscoveryProps = {
18
+ /**
19
+ * Whether the discovery overlay is visible.
20
+ */
21
+ isVisible: boolean;
22
+ /**
23
+ * Ref to the target element to highlight.
24
+ */
25
+ targetRef: RefObject<MeasurableNode | null>;
26
+ /**
27
+ * Discovery title.
28
+ */
29
+ title: ReactNode;
30
+ /**
31
+ * Optional discovery description.
32
+ */
33
+ description?: ReactNode;
34
+ /**
35
+ * Optional action label displayed under the text.
36
+ */
37
+ actionText?: ReactNode;
38
+ /**
39
+ * Called when action text is pressed.
40
+ */
41
+ onActionPress?: () => void;
42
+ /**
43
+ * Called when overlay should close.
44
+ */
45
+ onDismiss?: () => void;
46
+ /**
47
+ * Whether tapping outside dismisses the overlay.
48
+ * @default true
49
+ */
50
+ dismissOnBackdropPress?: boolean;
51
+ /**
52
+ * Accent color for the discovery circle.
53
+ * @default 'primary'
54
+ */
55
+ themeColor?: ThemeColor;
56
+ /**
57
+ * Backdrop color.
58
+ */
59
+ overlayColor?: string;
60
+ /**
61
+ * Extra spacing around target highlight.
62
+ * @default 14
63
+ */
64
+ spotlightPadding?: number;
65
+ /**
66
+ * Scale multiplier for discovery circle diameter.
67
+ * @default 1.65
68
+ */
69
+ circleScale?: number;
70
+ /**
71
+ * Optional custom content rendered over the highlighted target.
72
+ */
73
+ highlightContent?: ReactNode;
74
+ /**
75
+ * Optional style overrides.
76
+ */
77
+ customAppearance?: FeatureDiscoveryCustomAppearance;
78
+ };
79
+
80
+ declare const FeatureDiscovery: React.FC<FeatureDiscoveryProps>;
81
+
82
+ export { FeatureDiscovery, type FeatureDiscoveryCustomAppearance, type FeatureDiscoveryProps };
@@ -0,0 +1,82 @@
1
+ import React, { RefObject, ReactNode } from 'react';
2
+ import { ViewStyle, TextStyle } from 'react-native';
3
+ import { T as ThemeColor } from '../index-BOw6tbkc.js';
4
+
5
+ type MeasurableNode = {
6
+ measureInWindow: (callback: (x: number, y: number, width: number, height: number) => void) => void;
7
+ };
8
+ type FeatureDiscoveryCustomAppearance = {
9
+ root?: ViewStyle;
10
+ container?: ViewStyle;
11
+ title?: TextStyle;
12
+ description?: TextStyle;
13
+ actionText?: TextStyle;
14
+ highlightContainer?: ViewStyle;
15
+ messageContainer?: ViewStyle;
16
+ };
17
+ type FeatureDiscoveryProps = {
18
+ /**
19
+ * Whether the discovery overlay is visible.
20
+ */
21
+ isVisible: boolean;
22
+ /**
23
+ * Ref to the target element to highlight.
24
+ */
25
+ targetRef: RefObject<MeasurableNode | null>;
26
+ /**
27
+ * Discovery title.
28
+ */
29
+ title: ReactNode;
30
+ /**
31
+ * Optional discovery description.
32
+ */
33
+ description?: ReactNode;
34
+ /**
35
+ * Optional action label displayed under the text.
36
+ */
37
+ actionText?: ReactNode;
38
+ /**
39
+ * Called when action text is pressed.
40
+ */
41
+ onActionPress?: () => void;
42
+ /**
43
+ * Called when overlay should close.
44
+ */
45
+ onDismiss?: () => void;
46
+ /**
47
+ * Whether tapping outside dismisses the overlay.
48
+ * @default true
49
+ */
50
+ dismissOnBackdropPress?: boolean;
51
+ /**
52
+ * Accent color for the discovery circle.
53
+ * @default 'primary'
54
+ */
55
+ themeColor?: ThemeColor;
56
+ /**
57
+ * Backdrop color.
58
+ */
59
+ overlayColor?: string;
60
+ /**
61
+ * Extra spacing around target highlight.
62
+ * @default 14
63
+ */
64
+ spotlightPadding?: number;
65
+ /**
66
+ * Scale multiplier for discovery circle diameter.
67
+ * @default 1.65
68
+ */
69
+ circleScale?: number;
70
+ /**
71
+ * Optional custom content rendered over the highlighted target.
72
+ */
73
+ highlightContent?: ReactNode;
74
+ /**
75
+ * Optional style overrides.
76
+ */
77
+ customAppearance?: FeatureDiscoveryCustomAppearance;
78
+ };
79
+
80
+ declare const FeatureDiscovery: React.FC<FeatureDiscoveryProps>;
81
+
82
+ export { FeatureDiscovery, type FeatureDiscoveryCustomAppearance, type FeatureDiscoveryProps };