@xaui/native 0.9.1-alpha.4 → 0.9.1-alpha.6

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.
@@ -3,8 +3,61 @@
3
3
 
4
4
  var _chunk3QBT3Q65cjs = require('./chunk-3QBT3Q65.cjs');
5
5
 
6
- // src/system/portal/portal.tsx
6
+ // src/system/icon/icon.tsx
7
7
  var _react = require('react');
8
+ var _reactnative = require('react-native');
9
+
10
+ // src/system/icon/icon-context.ts
11
+
12
+ var IconContext = _react.createContext.call(void 0, {});
13
+ IconContext.displayName = "XAUI.Icon.Context";
14
+ function useIconContext() {
15
+ return _react.useContext.call(void 0, IconContext);
16
+ }
17
+
18
+ // src/system/icon/icon.tsx
19
+ function Icon({
20
+ as: Component,
21
+ children,
22
+ source,
23
+ size,
24
+ color,
25
+ style
26
+ }) {
27
+ const inherited = useIconContext();
28
+ const theme = _chunk3QBT3Q65cjs.useXAUITheme.call(void 0, );
29
+ const resolvedSize = _nullishCoalesce(_nullishCoalesce(size, () => ( inherited.size)), () => ( theme.fontSizes.md));
30
+ const resolvedColor = _nullishCoalesce(_nullishCoalesce(color, () => ( inherited.color)), () => ( theme.colors.foreground));
31
+ if (Component) {
32
+ return /* @__PURE__ */ React.createElement(Component, { size: resolvedSize, color: resolvedColor });
33
+ }
34
+ if (_react.isValidElement.call(void 0, children)) {
35
+ return _react.cloneElement.call(void 0, children, {
36
+ width: resolvedSize,
37
+ height: resolvedSize,
38
+ color: resolvedColor
39
+ });
40
+ }
41
+ if (source) {
42
+ return /* @__PURE__ */ React.createElement(
43
+ _reactnative.Image,
44
+ {
45
+ source,
46
+ style: [
47
+ { width: resolvedSize, height: resolvedSize, tintColor: resolvedColor },
48
+ style
49
+ ]
50
+ }
51
+ );
52
+ }
53
+ throw new Error(
54
+ "XAUI: Icon needs one of `as` (an icon component), a raw SVG element as its child, or `source` (an image). It renders nothing on its own."
55
+ );
56
+ }
57
+ Icon.displayName = "XAUI.Icon";
58
+
59
+ // src/system/portal/portal.tsx
60
+
8
61
 
9
62
  // src/system/portal/portal-context.ts
10
63
 
@@ -26,7 +79,7 @@ Portal.displayName = "XAUI.Portal";
26
79
 
27
80
  // src/system/portal/portal-host.tsx
28
81
 
29
- var _reactnative = require('react-native');
82
+
30
83
  var styles = _reactnative.StyleSheet.create({
31
84
  container: { flex: 1 }
32
85
  });
@@ -685,4 +738,7 @@ function stringify(node) {
685
738
 
686
739
 
687
740
 
688
- exports.PortalContext = PortalContext; exports.Portal = Portal; exports.PortalHost = PortalHost; exports.createSlotContext = createSlotContext; exports.useFeedback = useFeedback; exports.PRESS_SCALE = PRESS_SCALE; exports.PRESS_DURATION = PRESS_DURATION; exports.RELEASE_DURATION = RELEASE_DURATION; exports.HIGHLIGHT_OPACITY = HIGHLIGHT_OPACITY; exports.RIPPLE_OPACITY = RIPPLE_OPACITY; exports.RIPPLE_DURATION = RIPPLE_DURATION; exports.RIPPLE_COVERAGE = RIPPLE_COVERAGE; exports.resolveAnimation = resolveAnimation; exports.resolveSlotAnimation = resolveSlotAnimation; exports.mergeRefs = mergeRefs; exports.mergeProps = mergeProps; exports.Slot = Slot; exports.PressableFeedback = PressableFeedback3; exports.createRecipe = createRecipe; exports.childrenToString = childrenToString;
741
+
742
+
743
+
744
+ exports.mergeRefs = mergeRefs; exports.IconContext = IconContext; exports.useIconContext = useIconContext; exports.Icon = Icon; exports.PortalContext = PortalContext; exports.Portal = Portal; exports.PortalHost = PortalHost; exports.createSlotContext = createSlotContext; exports.useFeedback = useFeedback; exports.PRESS_SCALE = PRESS_SCALE; exports.PRESS_DURATION = PRESS_DURATION; exports.RELEASE_DURATION = RELEASE_DURATION; exports.HIGHLIGHT_OPACITY = HIGHLIGHT_OPACITY; exports.RIPPLE_OPACITY = RIPPLE_OPACITY; exports.RIPPLE_DURATION = RIPPLE_DURATION; exports.RIPPLE_COVERAGE = RIPPLE_COVERAGE; exports.resolveAnimation = resolveAnimation; exports.resolveSlotAnimation = resolveSlotAnimation; exports.mergeProps = mergeProps; exports.Slot = Slot; exports.PressableFeedback = PressableFeedback3; exports.createRecipe = createRecipe; exports.childrenToString = childrenToString;
@@ -3,16 +3,69 @@ import {
3
3
  useXAUITheme
4
4
  } from "./chunk-X2K2FX3W.js";
5
5
 
6
+ // src/system/icon/icon.tsx
7
+ import { cloneElement, isValidElement } from "react";
8
+ import { Image } from "react-native";
9
+
10
+ // src/system/icon/icon-context.ts
11
+ import { createContext, useContext } from "react";
12
+ var IconContext = createContext({});
13
+ IconContext.displayName = "XAUI.Icon.Context";
14
+ function useIconContext() {
15
+ return useContext(IconContext);
16
+ }
17
+
18
+ // src/system/icon/icon.tsx
19
+ function Icon({
20
+ as: Component,
21
+ children,
22
+ source,
23
+ size,
24
+ color,
25
+ style
26
+ }) {
27
+ const inherited = useIconContext();
28
+ const theme = useXAUITheme();
29
+ const resolvedSize = size ?? inherited.size ?? theme.fontSizes.md;
30
+ const resolvedColor = color ?? inherited.color ?? theme.colors.foreground;
31
+ if (Component) {
32
+ return /* @__PURE__ */ React.createElement(Component, { size: resolvedSize, color: resolvedColor });
33
+ }
34
+ if (isValidElement(children)) {
35
+ return cloneElement(children, {
36
+ width: resolvedSize,
37
+ height: resolvedSize,
38
+ color: resolvedColor
39
+ });
40
+ }
41
+ if (source) {
42
+ return /* @__PURE__ */ React.createElement(
43
+ Image,
44
+ {
45
+ source,
46
+ style: [
47
+ { width: resolvedSize, height: resolvedSize, tintColor: resolvedColor },
48
+ style
49
+ ]
50
+ }
51
+ );
52
+ }
53
+ throw new Error(
54
+ "XAUI: Icon needs one of `as` (an icon component), a raw SVG element as its child, or `source` (an image). It renders nothing on its own."
55
+ );
56
+ }
57
+ Icon.displayName = "XAUI.Icon";
58
+
6
59
  // src/system/portal/portal.tsx
7
- import { useContext, useId, useLayoutEffect } from "react";
60
+ import { useContext as useContext2, useId, useLayoutEffect } from "react";
8
61
 
9
62
  // src/system/portal/portal-context.ts
10
- import { createContext } from "react";
11
- var PortalContext = createContext(null);
63
+ import { createContext as createContext2 } from "react";
64
+ var PortalContext = createContext2(null);
12
65
 
13
66
  // src/system/portal/portal.tsx
14
67
  function Portal({ children }) {
15
- const context = useContext(PortalContext);
68
+ const context = useContext2(PortalContext);
16
69
  const key = useId();
17
70
  useLayoutEffect(() => {
18
71
  context?.addPortal(key, children);
@@ -52,7 +105,7 @@ function PortalHost({ children }) {
52
105
  PortalHost.displayName = "XAUI.PortalHost";
53
106
 
54
107
  // src/system/pressable-feedback/pressable-feedback.tsx
55
- import { forwardRef as forwardRef2, useContext as useContext3, useEffect as useEffect2, useMemo as useMemo2 } from "react";
108
+ import { forwardRef as forwardRef2, useContext as useContext4, useEffect as useEffect2, useMemo as useMemo2 } from "react";
56
109
  import { Pressable } from "react-native";
57
110
  import Animated3, {
58
111
  useAnimatedStyle as useAnimatedStyle3,
@@ -61,15 +114,15 @@ import Animated3, {
61
114
  } from "react-native-reanimated";
62
115
 
63
116
  // src/system/pressable-feedback/pressable-feedback-context.ts
64
- import { createContext as createContext3 } from "react";
117
+ import { createContext as createContext4 } from "react";
65
118
 
66
119
  // src/system/slot/create-slot-context.ts
67
- import { createContext as createContext2, useContext as useContext2 } from "react";
120
+ import { createContext as createContext3, useContext as useContext3 } from "react";
68
121
  function createSlotContext(name) {
69
- const Context = createContext2(null);
122
+ const Context = createContext3(null);
70
123
  Context.displayName = `XAUI.${name}.Context`;
71
124
  function useSlotContext() {
72
- const value = useContext2(Context);
125
+ const value = useContext3(Context);
73
126
  if (value === null) {
74
127
  const error = new Error(
75
128
  `XAUI: use${name} must be called inside <${name}>. A slot reads the values its root resolved, so it can only be rendered as a child of one.`
@@ -87,7 +140,7 @@ function createSlotContext(name) {
87
140
 
88
141
  // src/system/pressable-feedback/pressable-feedback-context.ts
89
142
  var [FeedbackProvider, useFeedback] = createSlotContext("PressableFeedback");
90
- var DisableAllContext = createContext3(false);
143
+ var DisableAllContext = createContext4(false);
91
144
 
92
145
  // src/system/pressable-feedback/pressable-feedback-highlight.tsx
93
146
  import { useEffect } from "react";
@@ -323,7 +376,7 @@ function RippleWave({
323
376
  }
324
377
 
325
378
  // src/system/slot/slot.tsx
326
- import { cloneElement, forwardRef, isValidElement } from "react";
379
+ import { cloneElement as cloneElement2, forwardRef, isValidElement as isValidElement2 } from "react";
327
380
 
328
381
  // src/system/slot/merge-refs.ts
329
382
  function mergeRefs(...refs) {
@@ -381,7 +434,7 @@ function resolveStyle(style, state) {
381
434
 
382
435
  // src/system/slot/slot.tsx
383
436
  var Slot = forwardRef(function Slot2({ children, ...ours }, ref) {
384
- if (!isValidElement(children)) {
437
+ if (!isValidElement2(children)) {
385
438
  throw new Error(
386
439
  "XAUI: asChild expects exactly one React element as its child, and merges the component's props into it. Text, a fragment, several children or none give it nothing to merge into \u2014 drop `asChild` to render the component itself."
387
440
  );
@@ -389,7 +442,7 @@ var Slot = forwardRef(function Slot2({ children, ...ours }, ref) {
389
442
  const child = children;
390
443
  const merged = mergeProps(ours, child.props);
391
444
  merged.ref = mergeRefs(ref, refOf(child));
392
- return cloneElement(child, merged);
445
+ return cloneElement2(child, merged);
393
446
  });
394
447
  Slot.displayName = "XAUI.Slot";
395
448
  function refOf(element) {
@@ -403,7 +456,7 @@ var AnimatedPressable = Animated3.createAnimatedComponent(Pressable);
403
456
  var AnimatedSlot = Animated3.createAnimatedComponent(Slot);
404
457
  var PressableFeedback = forwardRef2(
405
458
  function PressableFeedback2({ animation, feedbackVariant = "scale-highlight", ...rest }, ref) {
406
- const inheritedDisableAll = useContext3(DisableAllContext);
459
+ const inheritedDisableAll = useContext4(DisableAllContext);
407
460
  const resolved = resolveAnimation(animation, inheritedDisableAll);
408
461
  const Feedback = resolved.none || feedbackVariant === "none" ? StaticFeedback : AnimatedFeedback;
409
462
  const body = /* @__PURE__ */ React.createElement(
@@ -642,7 +695,7 @@ function apply(fns, theme, colors) {
642
695
  }
643
696
 
644
697
  // src/system/slot/children-to-string.ts
645
- import { isValidElement as isValidElement2 } from "react";
698
+ import { isValidElement as isValidElement3 } from "react";
646
699
  function childrenToString(children) {
647
700
  const text = stringify(children);
648
701
  return text === null || text === "" ? null : text;
@@ -651,7 +704,7 @@ function stringify(node) {
651
704
  if (node === null || node === void 0 || typeof node === "boolean") return "";
652
705
  if (typeof node === "string") return node;
653
706
  if (typeof node === "number") return String(node);
654
- if (isValidElement2(node)) return null;
707
+ if (isValidElement3(node)) return null;
655
708
  if (Array.isArray(node)) {
656
709
  let text = "";
657
710
  for (const child of node) {
@@ -665,6 +718,10 @@ function stringify(node) {
665
718
  }
666
719
 
667
720
  export {
721
+ mergeRefs,
722
+ IconContext,
723
+ useIconContext,
724
+ Icon,
668
725
  PortalContext,
669
726
  Portal,
670
727
  PortalHost,
@@ -679,7 +736,6 @@ export {
679
736
  RIPPLE_COVERAGE,
680
737
  resolveAnimation,
681
738
  resolveSlotAnimation,
682
- mergeRefs,
683
739
  mergeProps,
684
740
  Slot,
685
741
  PressableFeedback3 as PressableFeedback,
package/dist/index.cjs CHANGED
@@ -1,4 +1,4 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true});
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
2
2
 
3
3
 
4
4
 
@@ -19,7 +19,10 @@
19
19
 
20
20
 
21
21
 
22
- var _chunkIYFGO523cjs = require('./chunk-IYFGO523.cjs');
22
+
23
+
24
+
25
+ var _chunk46M765BScjs = require('./chunk-46M765BS.cjs');
23
26
 
24
27
 
25
28
 
@@ -40,6 +43,90 @@ var _chunkAW63PTQ4cjs = require('./chunk-AW63PTQ4.cjs');
40
43
 
41
44
  var _chunk3QBT3Q65cjs = require('./chunk-3QBT3Q65.cjs');
42
45
 
46
+ // src/hooks/use-controllable-state.ts
47
+ var _react = require('react');
48
+
49
+ // src/utils/warn-dev.ts
50
+ function warnDev(message) {
51
+ if (typeof __DEV__ !== "undefined" && !__DEV__) return;
52
+ console.warn(`XAUI: ${message}`);
53
+ }
54
+
55
+ // src/hooks/use-controllable-state.ts
56
+ function useControllableState({
57
+ value,
58
+ defaultValue,
59
+ onChange
60
+ }) {
61
+ const [uncontrolled, setUncontrolled] = _react.useState.call(void 0, defaultValue);
62
+ const isControlled = value !== void 0;
63
+ const current = isControlled ? value : uncontrolled;
64
+ useControlWarning(isControlled);
65
+ const latest = _react.useRef.call(void 0, current);
66
+ latest.current = current;
67
+ const onChangeRef = _react.useRef.call(void 0, onChange);
68
+ onChangeRef.current = onChange;
69
+ const controlled = _react.useRef.call(void 0, isControlled);
70
+ controlled.current = isControlled;
71
+ const set = _react.useCallback.call(void 0, (next) => {
72
+ const resolved = typeof next === "function" ? next(latest.current) : next;
73
+ if (resolved === latest.current) return;
74
+ if (!controlled.current) setUncontrolled(resolved);
75
+ _optionalChain([onChangeRef, 'access', _ => _.current, 'optionalCall', _2 => _2(resolved)]);
76
+ }, []);
77
+ return [current, set];
78
+ }
79
+ function useControlWarning(isControlled) {
80
+ const wasControlled = _react.useRef.call(void 0, isControlled);
81
+ if (wasControlled.current !== isControlled) {
82
+ warnDev(
83
+ `a component switched from ${wasControlled.current ? "controlled" : "uncontrolled"} to ${isControlled ? "controlled" : "uncontrolled"}. Decide for the life of the component: pass \`value\` always, or never. Passing \`undefined\` for a value you do control reads as "uncontrolled" here.`
84
+ );
85
+ wasControlled.current = isControlled;
86
+ }
87
+ }
88
+
89
+ // src/hooks/use-merged-ref.ts
90
+
91
+ function useMergedRef(...refs) {
92
+ return _react.useMemo.call(void 0, () => _chunk46M765BScjs.mergeRefs.call(void 0, ...refs), refs);
93
+ }
94
+
95
+ // src/hooks/use-press-state.ts
96
+
97
+ function usePressState(handlers = {}) {
98
+ const [isPressed, setIsPressed] = _react.useState.call(void 0, false);
99
+ const latest = _react.useRef.call(void 0, handlers);
100
+ latest.current = handlers;
101
+ const onPressIn = _react.useCallback.call(void 0, (event) => {
102
+ setIsPressed(true);
103
+ _optionalChain([latest, 'access', _3 => _3.current, 'access', _4 => _4.onPressIn, 'optionalCall', _5 => _5(event)]);
104
+ }, []);
105
+ const onPressOut = _react.useCallback.call(void 0, (event) => {
106
+ setIsPressed(false);
107
+ _optionalChain([latest, 'access', _6 => _6.current, 'access', _7 => _7.onPressOut, 'optionalCall', _8 => _8(event)]);
108
+ }, []);
109
+ const press = _react.useRef.call(void 0, { onPressIn, onPressOut }).current;
110
+ return [isPressed, press];
111
+ }
112
+
113
+ // src/hooks/use-previous.ts
114
+
115
+ function usePrevious(value) {
116
+ const previous = _react.useRef.call(void 0, void 0);
117
+ _react.useEffect.call(void 0, () => {
118
+ previous.current = value;
119
+ }, [value]);
120
+ return previous.current;
121
+ }
122
+
123
+
124
+
125
+
126
+
127
+
128
+
129
+
43
130
 
44
131
 
45
132
 
@@ -75,4 +162,4 @@ var _chunk3QBT3Q65cjs = require('./chunk-3QBT3Q65.cjs');
75
162
 
76
163
 
77
164
 
78
- exports.HIGHLIGHT_OPACITY = _chunkIYFGO523cjs.HIGHLIGHT_OPACITY; exports.PRESS_DURATION = _chunkIYFGO523cjs.PRESS_DURATION; exports.PRESS_SCALE = _chunkIYFGO523cjs.PRESS_SCALE; exports.Portal = _chunkIYFGO523cjs.Portal; exports.PortalContext = _chunkIYFGO523cjs.PortalContext; exports.PortalHost = _chunkIYFGO523cjs.PortalHost; exports.PressableFeedback = _chunkIYFGO523cjs.PressableFeedback; exports.RELEASE_DURATION = _chunkIYFGO523cjs.RELEASE_DURATION; exports.RIPPLE_COVERAGE = _chunkIYFGO523cjs.RIPPLE_COVERAGE; exports.RIPPLE_DURATION = _chunkIYFGO523cjs.RIPPLE_DURATION; exports.RIPPLE_OPACITY = _chunkIYFGO523cjs.RIPPLE_OPACITY; exports.Slot = _chunkIYFGO523cjs.Slot; exports.ThemeContext = _chunk3QBT3Q65cjs.ThemeContext; exports.XAUIProvider = _chunkAW63PTQ4cjs.XAUIProvider; exports.buildRadius = _chunkAW63PTQ4cjs.buildRadius; exports.buildShadows = _chunkAW63PTQ4cjs.buildShadows; exports.childrenToString = _chunkIYFGO523cjs.childrenToString; exports.createRecipe = _chunkIYFGO523cjs.createRecipe; exports.createSlotContext = _chunkIYFGO523cjs.createSlotContext; exports.createTheme = _chunkAW63PTQ4cjs.createTheme; exports.defaultTheme = _chunkAW63PTQ4cjs.defaultTheme; exports.deriveColors = _chunkAW63PTQ4cjs.deriveColors; exports.deriveTint = _chunk3QBT3Q65cjs.deriveTint; exports.mergeProps = _chunkIYFGO523cjs.mergeProps; exports.mergeRefs = _chunkIYFGO523cjs.mergeRefs; exports.palette = _chunkAW63PTQ4cjs.palette; exports.primitives = _chunkAW63PTQ4cjs.primitives; exports.resolveAnimation = _chunkIYFGO523cjs.resolveAnimation; exports.resolveSlotAnimation = _chunkIYFGO523cjs.resolveSlotAnimation; exports.sourceKeys = _chunkAW63PTQ4cjs.sourceKeys; exports.tokens = _chunkAW63PTQ4cjs.tokens; exports.useColorMode = _chunk3QBT3Q65cjs.useColorMode; exports.useFeedback = _chunkIYFGO523cjs.useFeedback; exports.useThemeColor = _chunk3QBT3Q65cjs.useThemeColor; exports.useXAUITheme = _chunk3QBT3Q65cjs.useXAUITheme;
165
+ exports.HIGHLIGHT_OPACITY = _chunk46M765BScjs.HIGHLIGHT_OPACITY; exports.Icon = _chunk46M765BScjs.Icon; exports.IconContext = _chunk46M765BScjs.IconContext; exports.PRESS_DURATION = _chunk46M765BScjs.PRESS_DURATION; exports.PRESS_SCALE = _chunk46M765BScjs.PRESS_SCALE; exports.Portal = _chunk46M765BScjs.Portal; exports.PortalContext = _chunk46M765BScjs.PortalContext; exports.PortalHost = _chunk46M765BScjs.PortalHost; exports.PressableFeedback = _chunk46M765BScjs.PressableFeedback; exports.RELEASE_DURATION = _chunk46M765BScjs.RELEASE_DURATION; exports.RIPPLE_COVERAGE = _chunk46M765BScjs.RIPPLE_COVERAGE; exports.RIPPLE_DURATION = _chunk46M765BScjs.RIPPLE_DURATION; exports.RIPPLE_OPACITY = _chunk46M765BScjs.RIPPLE_OPACITY; exports.Slot = _chunk46M765BScjs.Slot; exports.ThemeContext = _chunk3QBT3Q65cjs.ThemeContext; exports.XAUIProvider = _chunkAW63PTQ4cjs.XAUIProvider; exports.buildRadius = _chunkAW63PTQ4cjs.buildRadius; exports.buildShadows = _chunkAW63PTQ4cjs.buildShadows; exports.childrenToString = _chunk46M765BScjs.childrenToString; exports.createRecipe = _chunk46M765BScjs.createRecipe; exports.createSlotContext = _chunk46M765BScjs.createSlotContext; exports.createTheme = _chunkAW63PTQ4cjs.createTheme; exports.defaultTheme = _chunkAW63PTQ4cjs.defaultTheme; exports.deriveColors = _chunkAW63PTQ4cjs.deriveColors; exports.deriveTint = _chunk3QBT3Q65cjs.deriveTint; exports.mergeProps = _chunk46M765BScjs.mergeProps; exports.mergeRefs = _chunk46M765BScjs.mergeRefs; exports.palette = _chunkAW63PTQ4cjs.palette; exports.primitives = _chunkAW63PTQ4cjs.primitives; exports.resolveAnimation = _chunk46M765BScjs.resolveAnimation; exports.resolveSlotAnimation = _chunk46M765BScjs.resolveSlotAnimation; exports.sourceKeys = _chunkAW63PTQ4cjs.sourceKeys; exports.tokens = _chunkAW63PTQ4cjs.tokens; exports.useColorMode = _chunk3QBT3Q65cjs.useColorMode; exports.useControllableState = useControllableState; exports.useFeedback = _chunk46M765BScjs.useFeedback; exports.useIconContext = _chunk46M765BScjs.useIconContext; exports.useMergedRef = useMergedRef; exports.usePressState = usePressState; exports.usePrevious = usePrevious; exports.useThemeColor = _chunk3QBT3Q65cjs.useThemeColor; exports.useXAUITheme = _chunk3QBT3Q65cjs.useXAUITheme;
package/dist/index.d.cts CHANGED
@@ -1,6 +1,64 @@
1
- export { AnimationConfig, AnimationProp, AsChildProps, Axes, CompoundVariant, FeedbackContext, FeedbackVariant, HIGHLIGHT_OPACITY, MergeableProps, PRESS_DURATION, PRESS_SCALE, Portal, PortalContext, PortalHost, PortalHostProps, PortalMethods, PortalProps, PossibleRef, PressableFeedback, PressableFeedbackHighlightProps, PressableFeedbackProps, PressableFeedbackRippleProps, RELEASE_DURATION, RIPPLE_COVERAGE, RIPPLE_DURATION, RIPPLE_OPACITY, Recipe, RecipeConfig, ResolveArgs, ResolvedAnimation, ResolvedSelection, ResolvedStyles, Selection, Slot, SlotAnimation, SlotProps, SlotStyle, SlotStyles, StateName, States, StyleFn, TintArgs, VariantColors, VariantRole, VariantTokens, childrenToString, createRecipe, createSlotContext, mergeProps, mergeRefs, resolveAnimation, resolveSlotAnimation, useFeedback } from './system/index.cjs';
1
+ import { RefCallback } from 'react';
2
+ import { PossibleRef } from './system/index.cjs';
3
+ export { AnimationConfig, AnimationProp, AsChildProps, Axes, CompoundVariant, FeedbackContext, FeedbackVariant, HIGHLIGHT_OPACITY, Icon, IconComponentProps, IconContext, IconContextValue, IconProps, MergeableProps, PRESS_DURATION, PRESS_SCALE, Portal, PortalContext, PortalHost, PortalHostProps, PortalMethods, PortalProps, PressableFeedback, PressableFeedbackHighlightProps, PressableFeedbackProps, PressableFeedbackRippleProps, RELEASE_DURATION, RIPPLE_COVERAGE, RIPPLE_DURATION, RIPPLE_OPACITY, Recipe, RecipeConfig, ResolveArgs, ResolvedAnimation, ResolvedSelection, ResolvedStyles, Selection, Slot, SlotAnimation, SlotProps, SlotStyle, SlotStyles, StateName, States, StyleFn, TintArgs, VariantColors, VariantRole, VariantTokens, childrenToString, createRecipe, createSlotContext, mergeProps, mergeRefs, resolveAnimation, resolveSlotAnimation, useFeedback, useIconContext } from './system/index.cjs';
4
+ import { GestureResponderEvent } from 'react-native';
2
5
  export { ColorModePreference, PaletteFamily, PaletteShade, ThemeContext, XAUIProvider, XAUIProviderProps, XAUITint, buildRadius, buildShadows, createTheme, defaultTheme, deriveColors, deriveTint, palette, primitives, sourceKeys, tokens, useColorMode, useThemeColor, useXAUITheme } from './theme/index.cjs';
3
6
  export { C as ColorMode, F as FontSizeKey, a as FontWeightKey, R as RadiusKey, S as Size, X as XAUIColors, b as XAUIDerivedColors, c as XAUIPrimitiveColors, d as XAUIRadius, e as XAUIShadow, f as XAUISourceColors, g as XAUITheme, h as XAUIThemeConfig, i as XAUIThemeSet } from './theme.type-C9bFJKFm.cjs';
4
- import 'react';
5
- import 'react-native';
6
7
  import 'react-native-reanimated';
8
+
9
+ type ControllableStateOptions<T> = {
10
+ /** Present means controlled: the caller owns the value and this never stores one. */
11
+ value?: T;
12
+ /** The starting value when uncontrolled. */
13
+ defaultValue: T;
14
+ /** Called with every new value, controlled or not. */
15
+ onChange?: (value: T) => void;
16
+ };
17
+ /**
18
+ * One state that works both ways, so a component never has two code paths for "the
19
+ * caller drives this" and "we do".
20
+ *
21
+ * The setter is stable across renders and reads the current value from a ref, so a
22
+ * handler built on it can be passed to a memoized child without rebuilding it on every
23
+ * render — which is the whole reason components reach for this rather than a local
24
+ * `useState` plus an `if`.
25
+ */
26
+ declare function useControllableState<T>({ value, defaultValue, onChange, }: ControllableStateOptions<T>): [T, (next: T | ((current: T) => T)) => void];
27
+
28
+ /**
29
+ * `mergeRefs` for a component that renders: memoized on the refs it was given, so React
30
+ * does not detach and reattach every one of them on each render — which it does whenever
31
+ * a ref callback changes identity, and which costs a node measurement every time.
32
+ */
33
+ declare function useMergedRef<T>(...refs: Array<PossibleRef<T>>): RefCallback<T>;
34
+
35
+ type PressHandlers = {
36
+ onPressIn?: (event: GestureResponderEvent) => void;
37
+ onPressOut?: (event: GestureResponderEvent) => void;
38
+ };
39
+ /**
40
+ * The press state a root owns, with the handlers that maintain it.
41
+ *
42
+ * It exists because every pressable component needs the same three things and gets one
43
+ * of them wrong on its own: the state has to be *up here* — the recipe resolves on it
44
+ * (R5) — the caller's handlers must be **composed, never replaced**, and the returned
45
+ * handlers must keep their identity so passing them down does not defeat a memo.
46
+ *
47
+ * ```tsx
48
+ * const [isPressed, pressHandlers] = usePressState(props)
49
+ * const styles = recipe.resolve({ theme, selection, states: { pressed: isPressed } })
50
+ * <PressableFeedback isPressed={isPressed} {...pressHandlers} />
51
+ * ```
52
+ */
53
+ declare function usePressState(handlers?: PressHandlers): [boolean, Required<PressHandlers>];
54
+
55
+ /**
56
+ * The value from the render before this one, `undefined` on the first.
57
+ *
58
+ * Written in an effect rather than during render on purpose: reading it mid-render would
59
+ * make "previous" mean something different depending on whether React re-ran the render,
60
+ * which under StrictMode it does.
61
+ */
62
+ declare function usePrevious<T>(value: T): T | undefined;
63
+
64
+ export { type ControllableStateOptions, PossibleRef, type PressHandlers, useControllableState, useMergedRef, usePressState, usePrevious };
package/dist/index.d.ts CHANGED
@@ -1,6 +1,64 @@
1
- export { AnimationConfig, AnimationProp, AsChildProps, Axes, CompoundVariant, FeedbackContext, FeedbackVariant, HIGHLIGHT_OPACITY, MergeableProps, PRESS_DURATION, PRESS_SCALE, Portal, PortalContext, PortalHost, PortalHostProps, PortalMethods, PortalProps, PossibleRef, PressableFeedback, PressableFeedbackHighlightProps, PressableFeedbackProps, PressableFeedbackRippleProps, RELEASE_DURATION, RIPPLE_COVERAGE, RIPPLE_DURATION, RIPPLE_OPACITY, Recipe, RecipeConfig, ResolveArgs, ResolvedAnimation, ResolvedSelection, ResolvedStyles, Selection, Slot, SlotAnimation, SlotProps, SlotStyle, SlotStyles, StateName, States, StyleFn, TintArgs, VariantColors, VariantRole, VariantTokens, childrenToString, createRecipe, createSlotContext, mergeProps, mergeRefs, resolveAnimation, resolveSlotAnimation, useFeedback } from './system/index.js';
1
+ import { RefCallback } from 'react';
2
+ import { PossibleRef } from './system/index.js';
3
+ export { AnimationConfig, AnimationProp, AsChildProps, Axes, CompoundVariant, FeedbackContext, FeedbackVariant, HIGHLIGHT_OPACITY, Icon, IconComponentProps, IconContext, IconContextValue, IconProps, MergeableProps, PRESS_DURATION, PRESS_SCALE, Portal, PortalContext, PortalHost, PortalHostProps, PortalMethods, PortalProps, PressableFeedback, PressableFeedbackHighlightProps, PressableFeedbackProps, PressableFeedbackRippleProps, RELEASE_DURATION, RIPPLE_COVERAGE, RIPPLE_DURATION, RIPPLE_OPACITY, Recipe, RecipeConfig, ResolveArgs, ResolvedAnimation, ResolvedSelection, ResolvedStyles, Selection, Slot, SlotAnimation, SlotProps, SlotStyle, SlotStyles, StateName, States, StyleFn, TintArgs, VariantColors, VariantRole, VariantTokens, childrenToString, createRecipe, createSlotContext, mergeProps, mergeRefs, resolveAnimation, resolveSlotAnimation, useFeedback, useIconContext } from './system/index.js';
4
+ import { GestureResponderEvent } from 'react-native';
2
5
  export { ColorModePreference, PaletteFamily, PaletteShade, ThemeContext, XAUIProvider, XAUIProviderProps, XAUITint, buildRadius, buildShadows, createTheme, defaultTheme, deriveColors, deriveTint, palette, primitives, sourceKeys, tokens, useColorMode, useThemeColor, useXAUITheme } from './theme/index.js';
3
6
  export { C as ColorMode, F as FontSizeKey, a as FontWeightKey, R as RadiusKey, S as Size, X as XAUIColors, b as XAUIDerivedColors, c as XAUIPrimitiveColors, d as XAUIRadius, e as XAUIShadow, f as XAUISourceColors, g as XAUITheme, h as XAUIThemeConfig, i as XAUIThemeSet } from './theme.type-C9bFJKFm.js';
4
- import 'react';
5
- import 'react-native';
6
7
  import 'react-native-reanimated';
8
+
9
+ type ControllableStateOptions<T> = {
10
+ /** Present means controlled: the caller owns the value and this never stores one. */
11
+ value?: T;
12
+ /** The starting value when uncontrolled. */
13
+ defaultValue: T;
14
+ /** Called with every new value, controlled or not. */
15
+ onChange?: (value: T) => void;
16
+ };
17
+ /**
18
+ * One state that works both ways, so a component never has two code paths for "the
19
+ * caller drives this" and "we do".
20
+ *
21
+ * The setter is stable across renders and reads the current value from a ref, so a
22
+ * handler built on it can be passed to a memoized child without rebuilding it on every
23
+ * render — which is the whole reason components reach for this rather than a local
24
+ * `useState` plus an `if`.
25
+ */
26
+ declare function useControllableState<T>({ value, defaultValue, onChange, }: ControllableStateOptions<T>): [T, (next: T | ((current: T) => T)) => void];
27
+
28
+ /**
29
+ * `mergeRefs` for a component that renders: memoized on the refs it was given, so React
30
+ * does not detach and reattach every one of them on each render — which it does whenever
31
+ * a ref callback changes identity, and which costs a node measurement every time.
32
+ */
33
+ declare function useMergedRef<T>(...refs: Array<PossibleRef<T>>): RefCallback<T>;
34
+
35
+ type PressHandlers = {
36
+ onPressIn?: (event: GestureResponderEvent) => void;
37
+ onPressOut?: (event: GestureResponderEvent) => void;
38
+ };
39
+ /**
40
+ * The press state a root owns, with the handlers that maintain it.
41
+ *
42
+ * It exists because every pressable component needs the same three things and gets one
43
+ * of them wrong on its own: the state has to be *up here* — the recipe resolves on it
44
+ * (R5) — the caller's handlers must be **composed, never replaced**, and the returned
45
+ * handlers must keep their identity so passing them down does not defeat a memo.
46
+ *
47
+ * ```tsx
48
+ * const [isPressed, pressHandlers] = usePressState(props)
49
+ * const styles = recipe.resolve({ theme, selection, states: { pressed: isPressed } })
50
+ * <PressableFeedback isPressed={isPressed} {...pressHandlers} />
51
+ * ```
52
+ */
53
+ declare function usePressState(handlers?: PressHandlers): [boolean, Required<PressHandlers>];
54
+
55
+ /**
56
+ * The value from the render before this one, `undefined` on the first.
57
+ *
58
+ * Written in an effect rather than during render on purpose: reading it mid-render would
59
+ * make "previous" mean something different depending on whether React re-ran the render,
60
+ * which under StrictMode it does.
61
+ */
62
+ declare function usePrevious<T>(value: T): T | undefined;
63
+
64
+ export { type ControllableStateOptions, PossibleRef, type PressHandlers, useControllableState, useMergedRef, usePressState, usePrevious };
package/dist/index.js CHANGED
@@ -1,5 +1,7 @@
1
1
  import {
2
2
  HIGHLIGHT_OPACITY,
3
+ Icon,
4
+ IconContext,
3
5
  PRESS_DURATION,
4
6
  PRESS_SCALE,
5
7
  Portal,
@@ -18,8 +20,9 @@ import {
18
20
  mergeRefs,
19
21
  resolveAnimation,
20
22
  resolveSlotAnimation,
21
- useFeedback
22
- } from "./chunk-ECDWSSHJ.js";
23
+ useFeedback,
24
+ useIconContext
25
+ } from "./chunk-GYK2CAX4.js";
23
26
  import {
24
27
  XAUIProvider,
25
28
  buildRadius,
@@ -39,8 +42,87 @@ import {
39
42
  useThemeColor,
40
43
  useXAUITheme
41
44
  } from "./chunk-X2K2FX3W.js";
45
+
46
+ // src/hooks/use-controllable-state.ts
47
+ import { useCallback, useRef, useState } from "react";
48
+
49
+ // src/utils/warn-dev.ts
50
+ function warnDev(message) {
51
+ if (typeof __DEV__ !== "undefined" && !__DEV__) return;
52
+ console.warn(`XAUI: ${message}`);
53
+ }
54
+
55
+ // src/hooks/use-controllable-state.ts
56
+ function useControllableState({
57
+ value,
58
+ defaultValue,
59
+ onChange
60
+ }) {
61
+ const [uncontrolled, setUncontrolled] = useState(defaultValue);
62
+ const isControlled = value !== void 0;
63
+ const current = isControlled ? value : uncontrolled;
64
+ useControlWarning(isControlled);
65
+ const latest = useRef(current);
66
+ latest.current = current;
67
+ const onChangeRef = useRef(onChange);
68
+ onChangeRef.current = onChange;
69
+ const controlled = useRef(isControlled);
70
+ controlled.current = isControlled;
71
+ const set = useCallback((next) => {
72
+ const resolved = typeof next === "function" ? next(latest.current) : next;
73
+ if (resolved === latest.current) return;
74
+ if (!controlled.current) setUncontrolled(resolved);
75
+ onChangeRef.current?.(resolved);
76
+ }, []);
77
+ return [current, set];
78
+ }
79
+ function useControlWarning(isControlled) {
80
+ const wasControlled = useRef(isControlled);
81
+ if (wasControlled.current !== isControlled) {
82
+ warnDev(
83
+ `a component switched from ${wasControlled.current ? "controlled" : "uncontrolled"} to ${isControlled ? "controlled" : "uncontrolled"}. Decide for the life of the component: pass \`value\` always, or never. Passing \`undefined\` for a value you do control reads as "uncontrolled" here.`
84
+ );
85
+ wasControlled.current = isControlled;
86
+ }
87
+ }
88
+
89
+ // src/hooks/use-merged-ref.ts
90
+ import { useMemo } from "react";
91
+ function useMergedRef(...refs) {
92
+ return useMemo(() => mergeRefs(...refs), refs);
93
+ }
94
+
95
+ // src/hooks/use-press-state.ts
96
+ import { useCallback as useCallback2, useRef as useRef2, useState as useState2 } from "react";
97
+ function usePressState(handlers = {}) {
98
+ const [isPressed, setIsPressed] = useState2(false);
99
+ const latest = useRef2(handlers);
100
+ latest.current = handlers;
101
+ const onPressIn = useCallback2((event) => {
102
+ setIsPressed(true);
103
+ latest.current.onPressIn?.(event);
104
+ }, []);
105
+ const onPressOut = useCallback2((event) => {
106
+ setIsPressed(false);
107
+ latest.current.onPressOut?.(event);
108
+ }, []);
109
+ const press = useRef2({ onPressIn, onPressOut }).current;
110
+ return [isPressed, press];
111
+ }
112
+
113
+ // src/hooks/use-previous.ts
114
+ import { useEffect, useRef as useRef3 } from "react";
115
+ function usePrevious(value) {
116
+ const previous = useRef3(void 0);
117
+ useEffect(() => {
118
+ previous.current = value;
119
+ }, [value]);
120
+ return previous.current;
121
+ }
42
122
  export {
43
123
  HIGHLIGHT_OPACITY,
124
+ Icon,
125
+ IconContext,
44
126
  PRESS_DURATION,
45
127
  PRESS_SCALE,
46
128
  Portal,
@@ -72,7 +154,12 @@ export {
72
154
  sourceKeys,
73
155
  tokens,
74
156
  useColorMode,
157
+ useControllableState,
75
158
  useFeedback,
159
+ useIconContext,
160
+ useMergedRef,
161
+ usePressState,
162
+ usePrevious,
76
163
  useThemeColor,
77
164
  useXAUITheme
78
165
  };
@@ -19,7 +19,10 @@
19
19
 
20
20
 
21
21
 
22
- var _chunkIYFGO523cjs = require('../chunk-IYFGO523.cjs');
22
+
23
+
24
+
25
+ var _chunk46M765BScjs = require('../chunk-46M765BS.cjs');
23
26
  require('../chunk-3QBT3Q65.cjs');
24
27
 
25
28
 
@@ -42,4 +45,7 @@ require('../chunk-3QBT3Q65.cjs');
42
45
 
43
46
 
44
47
 
45
- exports.HIGHLIGHT_OPACITY = _chunkIYFGO523cjs.HIGHLIGHT_OPACITY; exports.PRESS_DURATION = _chunkIYFGO523cjs.PRESS_DURATION; exports.PRESS_SCALE = _chunkIYFGO523cjs.PRESS_SCALE; exports.Portal = _chunkIYFGO523cjs.Portal; exports.PortalContext = _chunkIYFGO523cjs.PortalContext; exports.PortalHost = _chunkIYFGO523cjs.PortalHost; exports.PressableFeedback = _chunkIYFGO523cjs.PressableFeedback; exports.RELEASE_DURATION = _chunkIYFGO523cjs.RELEASE_DURATION; exports.RIPPLE_COVERAGE = _chunkIYFGO523cjs.RIPPLE_COVERAGE; exports.RIPPLE_DURATION = _chunkIYFGO523cjs.RIPPLE_DURATION; exports.RIPPLE_OPACITY = _chunkIYFGO523cjs.RIPPLE_OPACITY; exports.Slot = _chunkIYFGO523cjs.Slot; exports.childrenToString = _chunkIYFGO523cjs.childrenToString; exports.createRecipe = _chunkIYFGO523cjs.createRecipe; exports.createSlotContext = _chunkIYFGO523cjs.createSlotContext; exports.mergeProps = _chunkIYFGO523cjs.mergeProps; exports.mergeRefs = _chunkIYFGO523cjs.mergeRefs; exports.resolveAnimation = _chunkIYFGO523cjs.resolveAnimation; exports.resolveSlotAnimation = _chunkIYFGO523cjs.resolveSlotAnimation; exports.useFeedback = _chunkIYFGO523cjs.useFeedback;
48
+
49
+
50
+
51
+ exports.HIGHLIGHT_OPACITY = _chunk46M765BScjs.HIGHLIGHT_OPACITY; exports.Icon = _chunk46M765BScjs.Icon; exports.IconContext = _chunk46M765BScjs.IconContext; exports.PRESS_DURATION = _chunk46M765BScjs.PRESS_DURATION; exports.PRESS_SCALE = _chunk46M765BScjs.PRESS_SCALE; exports.Portal = _chunk46M765BScjs.Portal; exports.PortalContext = _chunk46M765BScjs.PortalContext; exports.PortalHost = _chunk46M765BScjs.PortalHost; exports.PressableFeedback = _chunk46M765BScjs.PressableFeedback; exports.RELEASE_DURATION = _chunk46M765BScjs.RELEASE_DURATION; exports.RIPPLE_COVERAGE = _chunk46M765BScjs.RIPPLE_COVERAGE; exports.RIPPLE_DURATION = _chunk46M765BScjs.RIPPLE_DURATION; exports.RIPPLE_OPACITY = _chunk46M765BScjs.RIPPLE_OPACITY; exports.Slot = _chunk46M765BScjs.Slot; exports.childrenToString = _chunk46M765BScjs.childrenToString; exports.createRecipe = _chunk46M765BScjs.createRecipe; exports.createSlotContext = _chunk46M765BScjs.createSlotContext; exports.mergeProps = _chunk46M765BScjs.mergeProps; exports.mergeRefs = _chunk46M765BScjs.mergeRefs; exports.resolveAnimation = _chunk46M765BScjs.resolveAnimation; exports.resolveSlotAnimation = _chunk46M765BScjs.resolveSlotAnimation; exports.useFeedback = _chunk46M765BScjs.useFeedback; exports.useIconContext = _chunk46M765BScjs.useIconContext;
@@ -1,10 +1,81 @@
1
1
  import * as react from 'react';
2
- import { ReactNode, Provider, Ref, RefCallback } from 'react';
2
+ import { Ref, ComponentType, ReactNode, Provider, RefCallback } from 'react';
3
3
  import * as react_native from 'react-native';
4
- import { PressableProps, StyleProp, ViewStyle, TextStyle } from 'react-native';
4
+ import { ImageSourcePropType, StyleProp, ImageStyle, PressableProps, ViewStyle, TextStyle } from 'react-native';
5
5
  import { SharedValue } from 'react-native-reanimated';
6
6
  import { g as XAUITheme, X as XAUIColors } from '../theme.type-C9bFJKFm.cjs';
7
7
 
8
+ /** Anything React accepts as a ref, plus the absence of one. */
9
+ type PossibleRef<T> = Ref<T> | undefined;
10
+ /**
11
+ * The props `mergeProps` knows how to combine. Deliberately loose: it merges whatever a
12
+ * root hands to whatever child it was given, and neither side is knowable from here.
13
+ */
14
+ type MergeableProps = Record<string, unknown>;
15
+ type AsChildProps = {
16
+ /**
17
+ * Merge this component's props into its single child instead of rendering an element
18
+ * of its own — a navigation `Link` as a `Button`, a bespoke trigger as a `Select`.
19
+ */
20
+ asChild?: boolean;
21
+ };
22
+
23
+ /**
24
+ * The props Lucide, Ionicons and `react-native-vector-icons` all accept — the shape
25
+ * `as` is handed. It is a convention rather than an interface anyone published, which is
26
+ * exactly why `Icon` exists: without it every call site computes the two values by hand.
27
+ */
28
+ type IconComponentProps = {
29
+ size?: number;
30
+ color?: string;
31
+ };
32
+ type IconProps = {
33
+ /** An icon component. `size` and `color` are injected into it. */
34
+ as?: ComponentType<IconComponentProps>;
35
+ /** A raw `react-native-svg` element, cloned with the resolved size and colour. */
36
+ children?: ReactNode;
37
+ /** An image, tinted with the resolved colour. */
38
+ source?: ImageSourcePropType;
39
+ /** Overrides what the surrounding slot asked for. */
40
+ size?: number;
41
+ /** A raw value (R7), never a token. Overrides the slot's. */
42
+ color?: string;
43
+ style?: StyleProp<ImageStyle>;
44
+ };
45
+ /** What a component root publishes so the icons inside it need no props at all. */
46
+ type IconContextValue = {
47
+ size?: number;
48
+ color?: string;
49
+ };
50
+
51
+ /**
52
+ * The gap nobody else closes: an icon is a third-party component, so a slot context does
53
+ * not reach it and every call site ends up computing the colour by hand.
54
+ *
55
+ * ```tsx
56
+ * <Button variant="danger">
57
+ * <Button.Icon as={TrashIcon} /> {/* colour and size inherited, nothing to pass *\/}
58
+ * <Button.Label>Supprimer</Button.Label>
59
+ * </Button>
60
+ * ```
61
+ *
62
+ * Three accepted forms — a component through `as`, a raw SVG as children, or an image
63
+ * through `source` — and the resolution is the same for all three: an explicit prop, else
64
+ * what the surrounding slot published, else the theme.
65
+ */
66
+ declare function Icon({ as: Component, children, source, size, color, style, }: IconProps): react.JSX.Element;
67
+ declare namespace Icon {
68
+ var displayName: string;
69
+ }
70
+
71
+ /**
72
+ * Not a `createSlotContext`: that one throws outside its parent, and an `Icon` has to
73
+ * work on its own as much as inside a `Button`. An empty context is the honest default —
74
+ * nothing inherited, so the theme decides.
75
+ */
76
+ declare const IconContext: react.Context<IconContextValue>;
77
+ declare function useIconContext(): IconContextValue;
78
+
8
79
  type PortalProps = {
9
80
  children: ReactNode;
10
81
  };
@@ -333,21 +404,6 @@ declare function childrenToString(children: ReactNode): string | null;
333
404
  */
334
405
  declare function createSlotContext<T>(name: string): readonly [Provider<T | null>, () => T];
335
406
 
336
- /** Anything React accepts as a ref, plus the absence of one. */
337
- type PossibleRef<T> = Ref<T> | undefined;
338
- /**
339
- * The props `mergeProps` knows how to combine. Deliberately loose: it merges whatever a
340
- * root hands to whatever child it was given, and neither side is knowable from here.
341
- */
342
- type MergeableProps = Record<string, unknown>;
343
- type AsChildProps = {
344
- /**
345
- * Merge this component's props into its single child instead of rendering an element
346
- * of its own — a navigation `Link` as a `Button`, a bespoke trigger as a `Select`.
347
- */
348
- asChild?: boolean;
349
- };
350
-
351
407
  /**
352
408
  * Merges a root's own props into the child it renders through `asChild` (R12). Four
353
409
  * rules, and the child wins wherever they do not apply — it is the more specific intent:
@@ -392,4 +448,4 @@ type SlotProps = MergeableProps & {
392
448
  */
393
449
  declare const Slot: react.ForwardRefExoticComponent<Omit<SlotProps, "ref"> & react.RefAttributes<unknown>>;
394
450
 
395
- export { type AnimationConfig, type AnimationProp, type AsChildProps, type Axes, type CompoundVariant, type FeedbackContext, type FeedbackVariant, HIGHLIGHT_OPACITY, type MergeableProps, PRESS_DURATION, PRESS_SCALE, Portal, PortalContext, PortalHost, type PortalHostProps, type PortalMethods, type PortalProps, type PossibleRef, PressableFeedback, type PressableFeedbackHighlightProps, type PressableFeedbackProps, type PressableFeedbackRippleProps, RELEASE_DURATION, RIPPLE_COVERAGE, RIPPLE_DURATION, RIPPLE_OPACITY, type Recipe, type RecipeConfig, type ResolveArgs, type ResolvedAnimation, type ResolvedSelection, type ResolvedStyles, type Selection, Slot, type SlotAnimation, type SlotProps, type SlotStyle, type SlotStyles, type StateName, type States, type StyleFn, type TintArgs, type VariantColors, type VariantRole, type VariantTokens, childrenToString, createRecipe, createSlotContext, mergeProps, mergeRefs, resolveAnimation, resolveSlotAnimation, useFeedback };
451
+ export { type AnimationConfig, type AnimationProp, type AsChildProps, type Axes, type CompoundVariant, type FeedbackContext, type FeedbackVariant, HIGHLIGHT_OPACITY, Icon, type IconComponentProps, IconContext, type IconContextValue, type IconProps, type MergeableProps, PRESS_DURATION, PRESS_SCALE, Portal, PortalContext, PortalHost, type PortalHostProps, type PortalMethods, type PortalProps, type PossibleRef, PressableFeedback, type PressableFeedbackHighlightProps, type PressableFeedbackProps, type PressableFeedbackRippleProps, RELEASE_DURATION, RIPPLE_COVERAGE, RIPPLE_DURATION, RIPPLE_OPACITY, type Recipe, type RecipeConfig, type ResolveArgs, type ResolvedAnimation, type ResolvedSelection, type ResolvedStyles, type Selection, Slot, type SlotAnimation, type SlotProps, type SlotStyle, type SlotStyles, type StateName, type States, type StyleFn, type TintArgs, type VariantColors, type VariantRole, type VariantTokens, childrenToString, createRecipe, createSlotContext, mergeProps, mergeRefs, resolveAnimation, resolveSlotAnimation, useFeedback, useIconContext };
@@ -1,10 +1,81 @@
1
1
  import * as react from 'react';
2
- import { ReactNode, Provider, Ref, RefCallback } from 'react';
2
+ import { Ref, ComponentType, ReactNode, Provider, RefCallback } from 'react';
3
3
  import * as react_native from 'react-native';
4
- import { PressableProps, StyleProp, ViewStyle, TextStyle } from 'react-native';
4
+ import { ImageSourcePropType, StyleProp, ImageStyle, PressableProps, ViewStyle, TextStyle } from 'react-native';
5
5
  import { SharedValue } from 'react-native-reanimated';
6
6
  import { g as XAUITheme, X as XAUIColors } from '../theme.type-C9bFJKFm.js';
7
7
 
8
+ /** Anything React accepts as a ref, plus the absence of one. */
9
+ type PossibleRef<T> = Ref<T> | undefined;
10
+ /**
11
+ * The props `mergeProps` knows how to combine. Deliberately loose: it merges whatever a
12
+ * root hands to whatever child it was given, and neither side is knowable from here.
13
+ */
14
+ type MergeableProps = Record<string, unknown>;
15
+ type AsChildProps = {
16
+ /**
17
+ * Merge this component's props into its single child instead of rendering an element
18
+ * of its own — a navigation `Link` as a `Button`, a bespoke trigger as a `Select`.
19
+ */
20
+ asChild?: boolean;
21
+ };
22
+
23
+ /**
24
+ * The props Lucide, Ionicons and `react-native-vector-icons` all accept — the shape
25
+ * `as` is handed. It is a convention rather than an interface anyone published, which is
26
+ * exactly why `Icon` exists: without it every call site computes the two values by hand.
27
+ */
28
+ type IconComponentProps = {
29
+ size?: number;
30
+ color?: string;
31
+ };
32
+ type IconProps = {
33
+ /** An icon component. `size` and `color` are injected into it. */
34
+ as?: ComponentType<IconComponentProps>;
35
+ /** A raw `react-native-svg` element, cloned with the resolved size and colour. */
36
+ children?: ReactNode;
37
+ /** An image, tinted with the resolved colour. */
38
+ source?: ImageSourcePropType;
39
+ /** Overrides what the surrounding slot asked for. */
40
+ size?: number;
41
+ /** A raw value (R7), never a token. Overrides the slot's. */
42
+ color?: string;
43
+ style?: StyleProp<ImageStyle>;
44
+ };
45
+ /** What a component root publishes so the icons inside it need no props at all. */
46
+ type IconContextValue = {
47
+ size?: number;
48
+ color?: string;
49
+ };
50
+
51
+ /**
52
+ * The gap nobody else closes: an icon is a third-party component, so a slot context does
53
+ * not reach it and every call site ends up computing the colour by hand.
54
+ *
55
+ * ```tsx
56
+ * <Button variant="danger">
57
+ * <Button.Icon as={TrashIcon} /> {/* colour and size inherited, nothing to pass *\/}
58
+ * <Button.Label>Supprimer</Button.Label>
59
+ * </Button>
60
+ * ```
61
+ *
62
+ * Three accepted forms — a component through `as`, a raw SVG as children, or an image
63
+ * through `source` — and the resolution is the same for all three: an explicit prop, else
64
+ * what the surrounding slot published, else the theme.
65
+ */
66
+ declare function Icon({ as: Component, children, source, size, color, style, }: IconProps): react.JSX.Element;
67
+ declare namespace Icon {
68
+ var displayName: string;
69
+ }
70
+
71
+ /**
72
+ * Not a `createSlotContext`: that one throws outside its parent, and an `Icon` has to
73
+ * work on its own as much as inside a `Button`. An empty context is the honest default —
74
+ * nothing inherited, so the theme decides.
75
+ */
76
+ declare const IconContext: react.Context<IconContextValue>;
77
+ declare function useIconContext(): IconContextValue;
78
+
8
79
  type PortalProps = {
9
80
  children: ReactNode;
10
81
  };
@@ -333,21 +404,6 @@ declare function childrenToString(children: ReactNode): string | null;
333
404
  */
334
405
  declare function createSlotContext<T>(name: string): readonly [Provider<T | null>, () => T];
335
406
 
336
- /** Anything React accepts as a ref, plus the absence of one. */
337
- type PossibleRef<T> = Ref<T> | undefined;
338
- /**
339
- * The props `mergeProps` knows how to combine. Deliberately loose: it merges whatever a
340
- * root hands to whatever child it was given, and neither side is knowable from here.
341
- */
342
- type MergeableProps = Record<string, unknown>;
343
- type AsChildProps = {
344
- /**
345
- * Merge this component's props into its single child instead of rendering an element
346
- * of its own — a navigation `Link` as a `Button`, a bespoke trigger as a `Select`.
347
- */
348
- asChild?: boolean;
349
- };
350
-
351
407
  /**
352
408
  * Merges a root's own props into the child it renders through `asChild` (R12). Four
353
409
  * rules, and the child wins wherever they do not apply — it is the more specific intent:
@@ -392,4 +448,4 @@ type SlotProps = MergeableProps & {
392
448
  */
393
449
  declare const Slot: react.ForwardRefExoticComponent<Omit<SlotProps, "ref"> & react.RefAttributes<unknown>>;
394
450
 
395
- export { type AnimationConfig, type AnimationProp, type AsChildProps, type Axes, type CompoundVariant, type FeedbackContext, type FeedbackVariant, HIGHLIGHT_OPACITY, type MergeableProps, PRESS_DURATION, PRESS_SCALE, Portal, PortalContext, PortalHost, type PortalHostProps, type PortalMethods, type PortalProps, type PossibleRef, PressableFeedback, type PressableFeedbackHighlightProps, type PressableFeedbackProps, type PressableFeedbackRippleProps, RELEASE_DURATION, RIPPLE_COVERAGE, RIPPLE_DURATION, RIPPLE_OPACITY, type Recipe, type RecipeConfig, type ResolveArgs, type ResolvedAnimation, type ResolvedSelection, type ResolvedStyles, type Selection, Slot, type SlotAnimation, type SlotProps, type SlotStyle, type SlotStyles, type StateName, type States, type StyleFn, type TintArgs, type VariantColors, type VariantRole, type VariantTokens, childrenToString, createRecipe, createSlotContext, mergeProps, mergeRefs, resolveAnimation, resolveSlotAnimation, useFeedback };
451
+ export { type AnimationConfig, type AnimationProp, type AsChildProps, type Axes, type CompoundVariant, type FeedbackContext, type FeedbackVariant, HIGHLIGHT_OPACITY, Icon, type IconComponentProps, IconContext, type IconContextValue, type IconProps, type MergeableProps, PRESS_DURATION, PRESS_SCALE, Portal, PortalContext, PortalHost, type PortalHostProps, type PortalMethods, type PortalProps, type PossibleRef, PressableFeedback, type PressableFeedbackHighlightProps, type PressableFeedbackProps, type PressableFeedbackRippleProps, RELEASE_DURATION, RIPPLE_COVERAGE, RIPPLE_DURATION, RIPPLE_OPACITY, type Recipe, type RecipeConfig, type ResolveArgs, type ResolvedAnimation, type ResolvedSelection, type ResolvedStyles, type Selection, Slot, type SlotAnimation, type SlotProps, type SlotStyle, type SlotStyles, type StateName, type States, type StyleFn, type TintArgs, type VariantColors, type VariantRole, type VariantTokens, childrenToString, createRecipe, createSlotContext, mergeProps, mergeRefs, resolveAnimation, resolveSlotAnimation, useFeedback, useIconContext };
@@ -1,5 +1,7 @@
1
1
  import {
2
2
  HIGHLIGHT_OPACITY,
3
+ Icon,
4
+ IconContext,
3
5
  PRESS_DURATION,
4
6
  PRESS_SCALE,
5
7
  Portal,
@@ -18,11 +20,14 @@ import {
18
20
  mergeRefs,
19
21
  resolveAnimation,
20
22
  resolveSlotAnimation,
21
- useFeedback
22
- } from "../chunk-ECDWSSHJ.js";
23
+ useFeedback,
24
+ useIconContext
25
+ } from "../chunk-GYK2CAX4.js";
23
26
  import "../chunk-X2K2FX3W.js";
24
27
  export {
25
28
  HIGHLIGHT_OPACITY,
29
+ Icon,
30
+ IconContext,
26
31
  PRESS_DURATION,
27
32
  PRESS_SCALE,
28
33
  Portal,
@@ -41,5 +46,6 @@ export {
41
46
  mergeRefs,
42
47
  resolveAnimation,
43
48
  resolveSlotAnimation,
44
- useFeedback
49
+ useFeedback,
50
+ useIconContext
45
51
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xaui/native",
3
- "version": "0.9.1-alpha.4",
3
+ "version": "0.9.1-alpha.6",
4
4
  "description": "Composition-first React Native UI components with native animations powered by Reanimated",
5
5
  "keywords": [
6
6
  "react-native",