react-native-ui-lib 8.3.4-snapshot.7786 → 8.3.4-snapshot.7802

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-ui-lib",
3
- "version": "8.3.4-snapshot.7786",
3
+ "version": "8.3.4-snapshot.7802",
4
4
  "main": "src/index.js",
5
5
  "types": "src/index.d.ts",
6
6
  "author": "Ethan Sharabi <ethan.shar@gmail.com>",
@@ -9,6 +9,10 @@ import { ButtonDriver } from "../button/Button.driver.new";
9
9
  import { ViewDriver } from "../view/View.driver.new";
10
10
  export const TextFieldDriver = (props, options) => {
11
11
  const driver = usePressableDriver(useComponentDriver(props, options));
12
+ const inputDriver = useComponentDriver({
13
+ renderTree: props.renderTree,
14
+ testID: `${props.testID}.input`
15
+ }, options);
12
16
  const floatingPlaceholderDriver = TextDriver({
13
17
  renderTree: props.renderTree,
14
18
  testID: `${props.testID}.floatingPlaceholder`
@@ -41,30 +45,31 @@ export const TextFieldDriver = (props, options) => {
41
45
  renderTree: props.renderTree,
42
46
  testID: `${props.testID}.clearButton.container`
43
47
  });
48
+ const getInputElement = () => inputDriver.queryElement() ?? driver.getElement();
44
49
  const getValue = () => {
45
- return driver.getElement().props.value ?? driver.getElement().props.defaultValue;
50
+ return getInputElement().props.value ?? getInputElement().props.defaultValue;
46
51
  };
47
52
  const changeText = text => {
48
- fireEvent.changeText(driver.getElement(), text);
53
+ fireEvent.changeText(getInputElement(), text);
49
54
  };
50
55
  const focus = () => {
51
- fireEvent(driver.getElement(), 'focus');
56
+ fireEvent(getInputElement(), 'focus');
52
57
  };
53
58
  const blur = () => {
54
- fireEvent(driver.getElement(), 'blur');
59
+ fireEvent(getInputElement(), 'blur');
55
60
  };
56
61
  const isEnabled = () => {
57
- return !driver.getElement().props.accessibilityState?.disabled;
62
+ return !getInputElement().props.accessibilityState?.disabled;
58
63
  };
59
64
  const getPlaceholder = () => {
60
65
  const exists = () => {
61
- const hasPlaceholder = !!driver.getElement().props.placeholder;
66
+ const hasPlaceholder = !!getInputElement().props.placeholder;
62
67
  const hasText = !!getValue();
63
68
  return hasPlaceholder && (!hasText || hasText && floatingPlaceholderDriver.exists());
64
69
  };
65
70
  const getText = () => {
66
71
  if (exists()) {
67
- return driver.getElement().props.placeholder;
72
+ return getInputElement().props.placeholder;
68
73
  }
69
74
  };
70
75
  return {
@@ -78,6 +78,8 @@ const TextField = props => {
78
78
  readonly = false,
79
79
  showMandatoryIndication,
80
80
  clearButtonStyle,
81
+ testID,
82
+ accessibilityLabel: accessibilityLabelProp,
81
83
  ...others
82
84
  } = usePreset(props);
83
85
  const {
@@ -135,11 +137,31 @@ const TextField = props => {
135
137
  const hasValue = fieldState.value !== undefined; // NOTE: not pressable if centered without a value (so can't center placeholder)
136
138
  const inputStyle = useMemo(() => [typographyStyle, colorStyle, others.style, hasValue && centeredTextStyle], [typographyStyle, colorStyle, others.style, centeredTextStyle, hasValue]);
137
139
  const dummyPlaceholderStyle = useMemo(() => [inputStyle, styles.dummyPlaceholder], [inputStyle]);
140
+ const defaultAccessibilityLabel = useMemo(() => {
141
+ const parts = [];
142
+ if (label) {
143
+ parts.push(label);
144
+ }
145
+ if (context.isMandatory) {
146
+ parts.push('required');
147
+ }
148
+ parts.push('textField');
149
+ if (helperText) {
150
+ parts.push(helperText);
151
+ } else if (placeholder) {
152
+ parts.push(placeholder);
153
+ }
154
+ if (showCharCounter && others.maxLength) {
155
+ parts.push(`you can enter up to ${others.maxLength} characters`);
156
+ }
157
+ return parts.join(', ');
158
+ }, [label, context.isMandatory, helperText, placeholder, showCharCounter, others.maxLength]);
159
+ const accessibilityLabel = accessibilityLabelProp ?? defaultAccessibilityLabel;
138
160
  return <FieldContext.Provider value={context}>
139
- <View {...containerProps} style={[margins, positionStyle, containerStyle, centeredContainerStyle]}>
161
+ <View {...containerProps} testID={testID} accessible accessibilityLabel={accessibilityLabel} style={[margins, positionStyle, containerStyle, centeredContainerStyle]}>
140
162
  <View row spread style={centeredContainerStyle}>
141
- <Label label={label} labelColor={labelColor} labelStyle={_labelStyle} labelProps={labelProps} floatingPlaceholder={floatingPlaceholder} validationMessagePosition={validationMessagePosition} testID={`${props.testID}.label`} showMandatoryIndication={showMandatoryIndication} enableErrors={enableErrors} />
142
- {validationMessagePosition === ValidationMessagePosition.TOP && <ValidationMessage enableErrors={enableErrors} validate={others.validate} validationMessage={others.validationMessage} validationMessageStyle={_validationMessageStyle} retainValidationSpace={retainValidationSpace && retainTopMessageSpace} testID={`${props.testID}.validationMessage`} />}
163
+ <Label label={label} labelColor={labelColor} labelStyle={_labelStyle} labelProps={labelProps} floatingPlaceholder={floatingPlaceholder} validationMessagePosition={validationMessagePosition} testID={`${testID}.label`} showMandatoryIndication={showMandatoryIndication} enableErrors={enableErrors} />
164
+ {validationMessagePosition === ValidationMessagePosition.TOP && <ValidationMessage enableErrors={enableErrors} validate={others.validate} validationMessage={others.validationMessage} validationMessageStyle={_validationMessageStyle} retainValidationSpace={retainValidationSpace && retainTopMessageSpace} testID={`${testID}.validationMessage`} />}
143
165
  {topTrailingAccessory && <View>{topTrailingAccessory}</View>}
144
166
  </View>
145
167
  <View style={[paddings, fieldStyle]} row centerV centerH={centered}>
@@ -158,26 +180,26 @@ const TextField = props => {
158
180
  {Constants.isAndroid && centered && <Text marginR-s1 style={dummyPlaceholderStyle}>
159
181
  {placeholder}
160
182
  </Text>}
161
- {floatingPlaceholder && <FloatingPlaceholder defaultValue={others.defaultValue} placeholder={placeholder} floatingPlaceholderStyle={_floatingPlaceholderStyle} floatingPlaceholderColor={floatingPlaceholderColor} floatOnFocus={floatOnFocus} validationMessagePosition={validationMessagePosition} extraOffset={leadingAccessoryMeasurements?.width} testID={`${props.testID}.floatingPlaceholder`} showMandatoryIndication={showMandatoryIndication} />}
183
+ {floatingPlaceholder && <FloatingPlaceholder defaultValue={others.defaultValue} placeholder={placeholder} floatingPlaceholderStyle={_floatingPlaceholderStyle} floatingPlaceholderColor={floatingPlaceholderColor} floatOnFocus={floatOnFocus} validationMessagePosition={validationMessagePosition} extraOffset={leadingAccessoryMeasurements?.width} testID={`${testID}.floatingPlaceholder`} showMandatoryIndication={showMandatoryIndication} />}
162
184
  <Input hitSlop={{
163
185
  top: 20,
164
186
  bottom: 20
165
- }} placeholderTextColor={hidePlaceholder ? 'transparent' : placeholderTextColor} value={fieldState.value} {...others} readonly={readonly} style={inputStyle} onFocus={onFocus} onBlur={onBlur} onChangeText={onChangeText} placeholder={placeholder} hint={hint} showMandatoryIndication={showMandatoryIndication && !label} />
187
+ }} placeholderTextColor={hidePlaceholder ? 'transparent' : placeholderTextColor} value={fieldState.value} {...others} testID={`${testID}.input`} readonly={readonly} style={inputStyle} onFocus={onFocus} onBlur={onBlur} onChangeText={onChangeText} placeholder={placeholder} hint={hint} showMandatoryIndication={showMandatoryIndication && !label} />
166
188
  </View>}
167
- {showClearButton && <ClearButton onClear={onClear} testID={`${props.testID}.clearButton`} onChangeText={onChangeText} clearButtonStyle={clearButtonStyle} />}
189
+ {showClearButton && <ClearButton onClear={onClear} testID={`${testID}.clearButton`} onChangeText={onChangeText} clearButtonStyle={clearButtonStyle} />}
168
190
  {trailingAccessory}
169
191
  {/* </View> */}
170
192
  </View>
171
193
  <View row spread center={centered}>
172
194
  <View flex={!centered} flexG={centered} marginR-s4={showCharCounter}>
173
- {validationMessagePosition === ValidationMessagePosition.BOTTOM && <ValidationMessage enableErrors={enableErrors} validate={others.validate} validationMessage={others.validationMessage} validationIcon={validationIcon} validationMessageStyle={_validationMessageStyle} retainValidationSpace={retainValidationSpace} testID={`${props.testID}.validationMessage`} />}
174
- {helperText && <Text $textNeutralHeavy subtext marginT-s1 testID={`${props.testID}.helperText`}>
195
+ {validationMessagePosition === ValidationMessagePosition.BOTTOM && <ValidationMessage enableErrors={enableErrors} validate={others.validate} validationMessage={others.validationMessage} validationIcon={validationIcon} validationMessageStyle={_validationMessageStyle} retainValidationSpace={retainValidationSpace} testID={`${testID}.validationMessage`} />}
196
+ {helperText && <Text $textNeutralHeavy subtext marginT-s1 testID={`${testID}.helperText`}>
175
197
  {helperText}
176
198
  </Text>}
177
199
  {bottomAccessory}
178
200
  </View>
179
201
  <View>
180
- {showCharCounter && <CharCounter maxLength={others.maxLength} charCounterStyle={charCounterStyle} testID={`${props.testID}.charCounter`} />}
202
+ {showCharCounter && <CharCounter maxLength={others.maxLength} charCounterStyle={charCounterStyle} testID={`${testID}.charCounter`} />}
181
203
  </View>
182
204
  </View>
183
205
  </View>
@@ -19,15 +19,11 @@ export type GetColorByHexOptions = {
19
19
  export type GeneratePaletteOptions = {
20
20
  /** Whether to adjust the lightness of very light colors (generating darker palette) */
21
21
  adjustLightness?: boolean;
22
- /** Whether to apply the saturation curve to unify saturation levels throughout the palette */
22
+ /** Whether to adjust the saturation of colors with high lightness and saturation (unifying saturation level throughout palette) */
23
23
  adjustSaturation?: boolean;
24
- /** Percentage-based saturation curve indexed by distance from base color.
25
- * When provided, applies proportional saturation reduction outward from the base color */
26
- saturationCurve?: number[];
27
- /** Base saturation threshold below which the saturation curve is not applied (default: 50) */
28
- saturationThreshold?: number;
29
- /** Minimum saturation value when applying the curve (default: 20) */
30
- saturationFloor?: number;
24
+ /** Array of saturation adjustments to apply on the color's tints array (from darkest to lightest).
25
+ * The 'adjustSaturation' option must be true */
26
+ saturationLevels?: number[];
31
27
  /** Whether to add two extra dark colors usually used for dark mode (generating a palette of 10 instead of 8 colors) */
32
28
  addDarkestTints?: boolean;
33
29
  /** Whether to reverse the color palette to generate dark mode palette (pass 'true' to generate the same palette for both light and dark modes) */
@@ -95,9 +91,7 @@ export declare class Colors {
95
91
  adjustSaturation: boolean;
96
92
  addDarkestTints: boolean;
97
93
  avoidReverseOnDark: boolean;
98
- saturationCurve: number[];
99
- saturationThreshold: number;
100
- saturationFloor: number;
94
+ saturationLevels: undefined;
101
95
  };
102
96
  generateColorPalette: ((color: string, options?: GeneratePaletteOptions) => string[]) & _.MemoizedFunction;
103
97
  private generateDesignTokens;
@@ -150,7 +144,7 @@ declare const colorObject: Colors & {
150
144
  green70: string;
151
145
  green80: string;
152
146
  yellow1: string;
153
- yellow5: string; /** Whether to apply the saturation curve to unify saturation levels throughout the palette */
147
+ yellow5: string; /** Whether to adjust the saturation of colors with high lightness and saturation (unifying saturation level throughout palette) */
154
148
  yellow10: string;
155
149
  yellow20: string;
156
150
  yellow30: string;
@@ -170,7 +164,6 @@ declare const colorObject: Colors & {
170
164
  orange70: string;
171
165
  orange80: string;
172
166
  red1: string;
173
- /** Minimum saturation value when applying the curve (default: 20) */
174
167
  red5: string;
175
168
  red10: string;
176
169
  red20: string;
@@ -265,10 +258,16 @@ declare const colorObject: Colors & {
265
258
  $outlineNeutralHeavy: string;
266
259
  $outlinePrimary: string;
267
260
  $outlinePrimaryMedium: string;
268
- $outlineGeneral: string;
261
+ $outlineGeneral: string; /**
262
+ * Get app's current color scheme
263
+ */
269
264
  $outlineWarning: string;
270
265
  $outlineDanger: string;
271
- $outlineInverted: string;
266
+ $outlineInverted: string; /**
267
+ * Set color scheme for app
268
+ * arguments:
269
+ * scheme - color scheme e.g light/dark/default
270
+ */
272
271
  $black: string;
273
272
  $white: string;
274
273
  };
@@ -1,3 +1,5 @@
1
+ import _map from "lodash/map";
2
+ import _clamp from "lodash/clamp";
1
3
  import _toLower from "lodash/toLower";
2
4
  import _toUpper from "lodash/toUpper";
3
5
  import _inRange from "lodash/inRange";
@@ -227,7 +229,7 @@ export class Colors {
227
229
  const start = options?.addDarkestTints && colorLightness > 10 ? -size : 0;
228
230
  const end = options?.addDarkestTints && colorLightness > 10 ? undefined : size;
229
231
  const sliced = tints.slice(start, end);
230
- const adjusted = options?.adjustSaturation && adjustSaturationWithCurve(sliced, color, options);
232
+ const adjusted = options?.adjustSaturation && adjustSaturation(sliced, color, options?.saturationLevels);
231
233
  return adjusted || sliced;
232
234
  }, generatePaletteCacheResolver);
233
235
  defaultPaletteOptions = {
@@ -235,9 +237,7 @@ export class Colors {
235
237
  adjustSaturation: true,
236
238
  addDarkestTints: false,
237
239
  avoidReverseOnDark: false,
238
- saturationCurve: [1.0, 0.89, 0.77, 0.65, 0.55, 0.47, 0.42, 0.38, 0.34, 0.30],
239
- saturationThreshold: 50,
240
- saturationFloor: 20
240
+ saturationLevels: undefined
241
241
  };
242
242
  generateColorPalette = _memoize((color, options) => {
243
243
  const _options = {
@@ -308,33 +308,46 @@ export class Colors {
308
308
  function colorStringValue(color) {
309
309
  return color?.toString();
310
310
  }
311
- function adjustSaturationWithCurve(colors, baseColor, options) {
312
- const {
313
- saturationCurve: curve,
314
- saturationThreshold: threshold = 50,
315
- saturationFloor: floor = 20
316
- } = options ?? {};
317
- if (!curve) {
318
- return null;
319
- }
320
- const baseSaturation = Color(baseColor).hsl().color[1];
321
- if (baseSaturation <= threshold) {
322
- return null;
323
- }
324
- const baseIndex = colors.indexOf(baseColor.toUpperCase());
325
- if (baseIndex === -1) {
326
- return null;
327
- }
328
- return colors.map((hex, i) => {
329
- if (i === baseIndex) {
330
- return hex;
311
+ function adjustAllSaturations(colors, baseColor, levels) {
312
+ const array = [];
313
+ _forEach(colors, (c, index) => {
314
+ if (c === baseColor) {
315
+ array[index] = baseColor;
316
+ } else {
317
+ const hsl = Color(c).hsl();
318
+ const saturation = hsl.color[1];
319
+ const level = levels[index];
320
+ if (level !== undefined) {
321
+ const saturationLevel = saturation + level;
322
+ const clampedLevel = _clamp(saturationLevel, 0, 100);
323
+ const adjusted = setSaturation(c, clampedLevel);
324
+ array[index] = adjusted;
325
+ }
331
326
  }
332
- const hsl = Color(hex).hsl();
333
- const distance = Math.abs(i - baseIndex);
334
- const percentage = curve[Math.min(distance, curve.length - 1)];
335
- const newSaturation = Math.max(floor, Math.ceil(baseSaturation * percentage));
336
- return Color.hsl(hsl.color[0], newSaturation, hsl.color[2]).hex();
337
327
  });
328
+ return array;
329
+ }
330
+ function adjustSaturation(colors, baseColor, levels) {
331
+ if (levels) {
332
+ return adjustAllSaturations(colors, baseColor, levels);
333
+ }
334
+ let array;
335
+ const lightnessLevel = 80;
336
+ const saturationLevel = 60;
337
+ const hsl = Color(baseColor).hsl();
338
+ const lightness = Math.round(hsl.color[2]);
339
+ if (lightness > lightnessLevel) {
340
+ const saturation = Math.round(hsl.color[1]);
341
+ if (saturation > saturationLevel) {
342
+ array = _map(colors, e => e !== baseColor ? setSaturation(e, saturationLevel) : e);
343
+ }
344
+ }
345
+ return array;
346
+ }
347
+ function setSaturation(color, saturation) {
348
+ const hsl = Color(color).hsl();
349
+ hsl.color[1] = saturation;
350
+ return hsl.hex();
338
351
  }
339
352
  function generateColorTint(color, tintLevel) {
340
353
  const hsl = Color(color).hsl();