@webority-technologies/mobile 0.0.9 → 0.0.10

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.
@@ -59,7 +59,8 @@ const Input = exports.Input = /*#__PURE__*/(0, _react.forwardRef)((props, ref) =
59
59
  leftIcon,
60
60
  rightIcon,
61
61
  size = 'md',
62
- variant = 'outlined',
62
+ variant: variantProp,
63
+ labelMode: labelModeProp,
63
64
  required = false,
64
65
  maxLength,
65
66
  format,
@@ -80,13 +81,20 @@ const Input = exports.Input = /*#__PURE__*/(0, _react.forwardRef)((props, ref) =
80
81
  ...sizeMap[size],
81
82
  ...(theme.components.input?.[size] ?? {})
82
83
  };
84
+
85
+ // Per-call-site prop wins; otherwise theme defaults; otherwise library defaults.
86
+ const variant = variantProp ?? theme.components.input?.defaultVariant ?? 'outlined';
87
+ const labelMode = labelModeProp ?? theme.components.input?.defaultLabelMode ?? 'float';
83
88
  const [isFocused, setIsFocused] = (0, _react.useState)(false);
84
89
  const [isPasswordVisible, setIsPasswordVisible] = (0, _react.useState)(false);
85
90
  const hasValue = typeof value === 'string' && value.length > 0;
86
91
  const hasError = typeof error === 'string' && error.length > 0;
87
92
  const isEditable = !disabled && editable !== false;
88
93
  const shouldFloat = isFocused || hasValue;
89
- const showFloatingLabel = Boolean(label) && !multiline;
94
+ // Floating label only when explicitly opted into via labelMode='float' AND the
95
+ // field is single-line. labelMode='top' OR multiline both force a static label
96
+ // above the field — the staticLabel branch below handles both.
97
+ const showFloatingLabel = Boolean(label) && !multiline && labelMode === 'float';
90
98
 
91
99
  // Animations
92
100
  const focusAnim = (0, _react.useRef)((0, _index.createAnimatedValue)(0)).current;
@@ -52,7 +52,8 @@ const Input = /*#__PURE__*/forwardRef((props, ref) => {
52
52
  leftIcon,
53
53
  rightIcon,
54
54
  size = 'md',
55
- variant = 'outlined',
55
+ variant: variantProp,
56
+ labelMode: labelModeProp,
56
57
  required = false,
57
58
  maxLength,
58
59
  format,
@@ -73,13 +74,20 @@ const Input = /*#__PURE__*/forwardRef((props, ref) => {
73
74
  ...sizeMap[size],
74
75
  ...(theme.components.input?.[size] ?? {})
75
76
  };
77
+
78
+ // Per-call-site prop wins; otherwise theme defaults; otherwise library defaults.
79
+ const variant = variantProp ?? theme.components.input?.defaultVariant ?? 'outlined';
80
+ const labelMode = labelModeProp ?? theme.components.input?.defaultLabelMode ?? 'float';
76
81
  const [isFocused, setIsFocused] = useState(false);
77
82
  const [isPasswordVisible, setIsPasswordVisible] = useState(false);
78
83
  const hasValue = typeof value === 'string' && value.length > 0;
79
84
  const hasError = typeof error === 'string' && error.length > 0;
80
85
  const isEditable = !disabled && editable !== false;
81
86
  const shouldFloat = isFocused || hasValue;
82
- const showFloatingLabel = Boolean(label) && !multiline;
87
+ // Floating label only when explicitly opted into via labelMode='float' AND the
88
+ // field is single-line. labelMode='top' OR multiline both force a static label
89
+ // above the field — the staticLabel branch below handles both.
90
+ const showFloatingLabel = Boolean(label) && !multiline && labelMode === 'float';
83
91
 
84
92
  // Animations
85
93
  const focusAnim = useRef(createAnimatedValue(0)).current;
@@ -3,6 +3,7 @@ import { TextInput } from 'react-native';
3
3
  import type { BlurEvent, FocusEvent, StyleProp, TextInputProps, TextStyle, ViewStyle } from 'react-native';
4
4
  export type InputSize = 'sm' | 'md' | 'lg';
5
5
  export type InputVariant = 'outlined' | 'filled';
6
+ export type InputLabelMode = 'float' | 'top';
6
7
  export interface InputProps extends Omit<TextInputProps, 'style'> {
7
8
  label?: string;
8
9
  placeholder?: string;
@@ -18,6 +19,15 @@ export interface InputProps extends Omit<TextInputProps, 'style'> {
18
19
  rightIcon?: React.ReactNode;
19
20
  size?: InputSize;
20
21
  variant?: InputVariant;
22
+ /**
23
+ * - `'float'` (default): Material-Design floating label that animates from
24
+ * inside the field to the top border on focus / when there's a value.
25
+ * - `'top'`: classic static label rendered above the field with no animation.
26
+ * Use for forms that want the label permanently visible.
27
+ *
28
+ * Theme override: `theme.components.input.defaultLabelMode`.
29
+ */
30
+ labelMode?: InputLabelMode;
21
31
  required?: boolean;
22
32
  maxLength?: number;
23
33
  /**
@@ -295,9 +295,15 @@ export interface RadioTokens extends Partial<Record<ComponentSizeKey, RadioSizeT
295
295
  borderWidth?: number;
296
296
  labelGap?: number;
297
297
  }
298
+ export interface InputComponentTokens extends Partial<Record<ComponentSizeKey, InputSizeTokens>> {
299
+ /** Default `variant` when caller doesn't pass one. Library default: 'outlined'. */
300
+ defaultVariant?: 'outlined' | 'filled';
301
+ /** Default `labelMode` when caller doesn't pass one. Library default: 'float'. */
302
+ defaultLabelMode?: 'float' | 'top';
303
+ }
298
304
  export interface ComponentTokens {
299
305
  button?: Partial<Record<ComponentSizeKey, ButtonSizeTokens>>;
300
- input?: Partial<Record<ComponentSizeKey, InputSizeTokens>>;
306
+ input?: InputComponentTokens;
301
307
  searchBar?: Partial<Record<ComponentSizeKey, SearchBarSizeTokens>> & {
302
308
  cancelButtonWidth?: number;
303
309
  };
@@ -3,6 +3,7 @@ import { TextInput } from 'react-native';
3
3
  import type { BlurEvent, FocusEvent, StyleProp, TextInputProps, TextStyle, ViewStyle } from 'react-native';
4
4
  export type InputSize = 'sm' | 'md' | 'lg';
5
5
  export type InputVariant = 'outlined' | 'filled';
6
+ export type InputLabelMode = 'float' | 'top';
6
7
  export interface InputProps extends Omit<TextInputProps, 'style'> {
7
8
  label?: string;
8
9
  placeholder?: string;
@@ -18,6 +19,15 @@ export interface InputProps extends Omit<TextInputProps, 'style'> {
18
19
  rightIcon?: React.ReactNode;
19
20
  size?: InputSize;
20
21
  variant?: InputVariant;
22
+ /**
23
+ * - `'float'` (default): Material-Design floating label that animates from
24
+ * inside the field to the top border on focus / when there's a value.
25
+ * - `'top'`: classic static label rendered above the field with no animation.
26
+ * Use for forms that want the label permanently visible.
27
+ *
28
+ * Theme override: `theme.components.input.defaultLabelMode`.
29
+ */
30
+ labelMode?: InputLabelMode;
21
31
  required?: boolean;
22
32
  maxLength?: number;
23
33
  /**
@@ -295,9 +295,15 @@ export interface RadioTokens extends Partial<Record<ComponentSizeKey, RadioSizeT
295
295
  borderWidth?: number;
296
296
  labelGap?: number;
297
297
  }
298
+ export interface InputComponentTokens extends Partial<Record<ComponentSizeKey, InputSizeTokens>> {
299
+ /** Default `variant` when caller doesn't pass one. Library default: 'outlined'. */
300
+ defaultVariant?: 'outlined' | 'filled';
301
+ /** Default `labelMode` when caller doesn't pass one. Library default: 'float'. */
302
+ defaultLabelMode?: 'float' | 'top';
303
+ }
298
304
  export interface ComponentTokens {
299
305
  button?: Partial<Record<ComponentSizeKey, ButtonSizeTokens>>;
300
- input?: Partial<Record<ComponentSizeKey, InputSizeTokens>>;
306
+ input?: InputComponentTokens;
301
307
  searchBar?: Partial<Record<ComponentSizeKey, SearchBarSizeTokens>> & {
302
308
  cancelButtonWidth?: number;
303
309
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webority-technologies/mobile",
3
- "version": "0.0.9",
3
+ "version": "0.0.10",
4
4
  "description": "Beautiful, animated, accessible React Native components plus API/auth/logging/network/storage utilities for Webority projects.",
5
5
  "keywords": [
6
6
  "react-native",