@yahoo/uds-mobile 1.6.5 → 1.8.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -44,14 +44,14 @@ npm install @yahoo/uds-mobile
44
44
 
45
45
  | Dependency | Supported Version |
46
46
  | ----------------------- | ----------------- |
47
- | Expo SDK | 54 |
48
- | React Native | ≥ 0.81.0 |
47
+ | Expo SDK | 55 |
48
+ | React Native | ≥ 0.83.0 |
49
49
  | React | ≥ 19.0.0 |
50
- | react-native-unistyles | ≥ 3.0.20 |
51
- | react-native-reanimated | ~4.1.x |
50
+ | react-native-unistyles | ≥ 3.0.0 |
51
+ | react-native-reanimated | 4.0.0 |
52
52
 
53
53
  > [!NOTE]
54
- > This package is tested against Expo SDK 54. While it may work with other versions, we cannot guarantee compatibility. If you encounter issues on a different Expo SDK version, please check for peer dependency conflicts.
54
+ > This package is tested against Expo SDK 55. While it may work with other versions, we cannot guarantee compatibility. If you encounter issues on a different Expo SDK version, please check for peer dependency conflicts.
55
55
 
56
56
  ### Peer Dependencies
57
57
 
@@ -10,9 +10,25 @@ import { fontAliasToPostscript } from "@yahoo/uds-mobile/fonts";
10
10
  /**
11
11
  * Generate Unistyles theme from UDS tokens.
12
12
  *
13
- * Takes UniversalTokensConfig and generates theme objects for React Native Unistyles.
13
+ * Takes UniversalTokensConfigGeneric and generates theme objects for React Native Unistyles.
14
14
  */
15
15
  /**
16
+ * TEMPORARY: UDS-665 - Override YAS font with Yahoo Product Sans
17
+ * Remove this function when YAS font issue is resolved.
18
+ * Search for "UDS-665" to find all related code.
19
+ */
20
+ function applyYasFontOverride(fontId) {
21
+ if (fontId === "yas") return "yahoo-product-sans";
22
+ return fontId;
23
+ }
24
+ /**
25
+ * Extracts a space-separated "R G B" string from a SpectrumValueEntry.
26
+ */
27
+ function extractRgb(value) {
28
+ if (value?.rgb && typeof value.rgb === "object") return `${value.rgb.r} ${value.rgb.g} ${value.rgb.b}`;
29
+ return "0 0 0";
30
+ }
31
+ /**
16
32
  * Converts an array of BoxShadowValue objects to a CSS box-shadow string.
17
33
  * React Native's new architecture supports the CSS string syntax for boxShadow.
18
34
  *
@@ -72,11 +88,63 @@ function rgbStringToRgb(rgbString) {
72
88
  return `rgb(${parts.join(", ")})`;
73
89
  }
74
90
  /**
75
- * Generates elevation colors from config.
91
+ * Generates elevation border colors (for line palette) from config.
92
+ * Resolves the borderColor from each elevation preset to an RGB value.
93
+ */
94
+ function generateElevationBorderColors(config, colorMode) {
95
+ const result = {};
96
+ const palette = config.colorMode[colorMode].palette;
97
+ const spectrum = config.colorMode[colorMode].spectrum;
98
+ for (const level of Object.keys(config.elevation)) {
99
+ const borderColorDef = config.elevation[level][colorMode].borderColor;
100
+ let color = "transparent";
101
+ if (borderColorDef.type === "line") {
102
+ const colorDef = palette.line?.[borderColorDef.value];
103
+ if (colorDef) {
104
+ const rgbValue = spectrum[colorDef.hue]?.[colorDef.step];
105
+ if (rgbValue) {
106
+ const parts = extractRgb(rgbValue).trim().split(/\s+/);
107
+ color = colorDef.opacity !== void 0 ? `rgba(${parts.join(", ")}, ${parseInt(colorDef.opacity, 10) / 100})` : `rgb(${parts.join(", ")})`;
108
+ }
109
+ }
110
+ } else if (borderColorDef.type === "always") color = newAlwaysPalette[borderColorDef.value] ?? "transparent";
111
+ else if (borderColorDef.type === "spectrum") {
112
+ const spectrumValue = borderColorDef.value;
113
+ const rgbValue = spectrum[spectrumValue.hue]?.[spectrumValue.step];
114
+ if (rgbValue) color = `rgb(${extractRgb(rgbValue).trim().split(/\s+/).join(", ")})`;
115
+ }
116
+ result[`elevation-${level}`] = color;
117
+ }
118
+ return result;
119
+ }
120
+ /**
121
+ * Generates elevation background colors from config.
122
+ * Resolves backgroundFill from elevation preset through the background palette.
76
123
  */
77
- function generateElevationColors(elevation) {
124
+ function generateElevationBackgroundColors(config, colorMode) {
78
125
  const result = {};
79
- for (const level of Object.keys(elevation)) result[`elevation-${level}`] = "transparent";
126
+ const palette = config.colorMode[colorMode].palette;
127
+ const spectrum = config.colorMode[colorMode].spectrum;
128
+ for (const level of Object.keys(config.elevation)) {
129
+ const backgroundFill = config.elevation[level][colorMode].backgroundFill;
130
+ let color = "transparent";
131
+ if (backgroundFill.type === "background") {
132
+ const colorDef = palette.background?.[backgroundFill.value];
133
+ if (colorDef) {
134
+ const rgbValue = spectrum[colorDef.hue]?.[colorDef.step];
135
+ if (rgbValue) {
136
+ const parts = extractRgb(rgbValue).trim().split(/\s+/);
137
+ color = colorDef.opacity !== void 0 ? `rgba(${parts.join(", ")}, ${parseInt(colorDef.opacity, 10) / 100})` : `rgb(${parts.join(", ")})`;
138
+ }
139
+ }
140
+ } else if (backgroundFill.type === "always") color = newAlwaysPalette[backgroundFill.value] ?? "transparent";
141
+ else if (backgroundFill.type === "spectrum") {
142
+ const spectrumValue = backgroundFill.value;
143
+ const rgbValue = spectrum[spectrumValue.hue]?.[spectrumValue.step];
144
+ if (rgbValue) color = `rgb(${extractRgb(rgbValue).trim().split(/\s+/).join(", ")})`;
145
+ }
146
+ result[`elevation-${level}`] = color;
147
+ }
80
148
  return result;
81
149
  }
82
150
  /**
@@ -104,8 +172,8 @@ function resolveShadowColor(colorConfig, opacity, spectrum, palette) {
104
172
  if (colorConfig.type === "palette") {
105
173
  const colorDef = palette[colorConfig.value];
106
174
  if (colorDef) {
107
- const rgbValue = spectrum[colorDef.hue]?.[colorDef.step];
108
- if (rgbValue) return `rgba(${rgbValue.trim().split(/\s+/).join(", ")}, ${opacityValue})`;
175
+ const spectrumEntry = spectrum[colorDef.hue]?.[colorDef.step];
176
+ if (spectrumEntry) return `rgba(${extractRgb(spectrumEntry).trim().split(/\s+/).join(", ")}, ${opacityValue})`;
109
177
  }
110
178
  }
111
179
  return `rgba(0, 0, 0, ${opacityValue})`;
@@ -125,14 +193,15 @@ function convertShadowToBoxShadow(presets, spectrum, palette, inset = false) {
125
193
  }
126
194
  function generateSpectrum(spectrum) {
127
195
  const result = {};
128
- for (const [hue, steps] of Object.entries(spectrum)) for (const [step, rgbValue] of Object.entries(steps)) result[`${hue}-${step}`] = rgbStringToRgb(rgbValue);
196
+ for (const [hue, steps] of Object.entries(spectrum)) for (const [step, entry] of Object.entries(steps)) result[`${hue}-${step}`] = rgbStringToRgb(extractRgb(entry));
129
197
  return result;
130
198
  }
131
199
  function generatePalette(palette, spectrum) {
132
200
  const result = {};
133
201
  for (const [alias, { hue, step, opacity }] of Object.entries(palette)) {
134
- const rgbValue = spectrum[hue]?.[step];
135
- if (!rgbValue) continue;
202
+ const spectrumEntry = spectrum[hue]?.[step];
203
+ if (!spectrumEntry) continue;
204
+ const rgbValue = extractRgb(spectrumEntry);
136
205
  if (opacity !== void 0) {
137
206
  const opacityPercent = parseInt(opacity, 10) / 100;
138
207
  result[alias] = `rgba(${rgbValue.trim().split(/\s+/).join(", ")}, ${opacityPercent})`;
@@ -148,7 +217,7 @@ function generateTypography(typographyConfig, fontConfig) {
148
217
  const result = {};
149
218
  for (const [variant, style] of Object.entries(typographyConfig)) {
150
219
  const fontAlias = style.fontFamily.base;
151
- const fontId = fontConfig[fontAlias] ?? fontAlias;
220
+ const fontId = applyYasFontOverride(fontConfig[fontAlias] ?? fontAlias);
152
221
  const weight = Number(style.fontWeight.base.value);
153
222
  const postScriptName = isWebFontID(fontId) ? getPostScriptName(fontId, weight) : fontId;
154
223
  result[variant] = {
@@ -163,10 +232,13 @@ function generateTypography(typographyConfig, fontConfig) {
163
232
  }
164
233
  function generateFontAliases(fontConfig) {
165
234
  const result = {};
166
- for (const [alias, fontId] of Object.entries(fontConfig)) if (isWebFontID(fontId)) {
167
- const defaultWeight = FONT_DECLARATIONS_MAP[fontId].defaults.fontWeight;
168
- result[alias] = getPostScriptName(fontId, defaultWeight);
169
- } else result[alias] = fontId;
235
+ for (const [alias, rawFontId] of Object.entries(fontConfig)) {
236
+ const fontId = applyYasFontOverride(rawFontId);
237
+ if (isWebFontID(fontId)) {
238
+ const defaultWeight = FONT_DECLARATIONS_MAP[fontId].defaults.fontWeight;
239
+ result[alias] = getPostScriptName(fontId, defaultWeight);
240
+ } else result[alias] = fontId;
241
+ }
170
242
  result.icons = "uds-icons";
171
243
  return result;
172
244
  }
@@ -180,12 +252,65 @@ function generateShadows(config) {
180
252
  });
181
253
  return result;
182
254
  }
255
+ function isElevationCustomShadows(value) {
256
+ return Array.isArray(value);
257
+ }
258
+ /**
259
+ * Generates pre-computed boxShadow CSS strings for all shadow variants.
260
+ * Produces both drop and inset shadow maps keyed by variant name.
261
+ * Elevation levels resolve their dropShadow config (which may reference
262
+ * a ShadowVariant or provide custom ShadowPreset tuples).
263
+ */
264
+ function generateBoxShadows(config, colorMode) {
265
+ const colorsConfig = config.colorMode[colorMode];
266
+ const spectrum = colorsConfig.spectrum;
267
+ const palette = colorsConfig.palette.foreground;
268
+ const drop = {};
269
+ const inset = {};
270
+ for (const [variant, presets] of Object.entries(config.shadow.drop)) {
271
+ if (variant === "none" || !presets || presets.length === 0) {
272
+ drop[variant] = "";
273
+ continue;
274
+ }
275
+ drop[variant] = boxShadowToCssString(convertShadowToBoxShadow(presets, spectrum, palette));
276
+ }
277
+ for (const [level, modePresets] of Object.entries(config.elevation)) {
278
+ const preset = modePresets[colorMode];
279
+ const key = `elevation-${level}`;
280
+ if (!preset.dropShadow || preset.dropShadow === "none") {
281
+ drop[key] = "";
282
+ continue;
283
+ }
284
+ if (isElevationCustomShadows(preset.dropShadow)) {
285
+ const allPresets = [...preset.dropShadow];
286
+ if (allPresets.length > 0) drop[key] = boxShadowToCssString(convertShadowToBoxShadow(allPresets, spectrum, palette));
287
+ else drop[key] = "";
288
+ } else {
289
+ const refPresets = config.shadow.drop[preset.dropShadow];
290
+ if (refPresets && refPresets.length > 0) drop[key] = boxShadowToCssString(convertShadowToBoxShadow(refPresets, spectrum, palette));
291
+ else drop[key] = "";
292
+ }
293
+ }
294
+ for (const [variant, presets] of Object.entries(config.shadow.inset)) {
295
+ if (variant === "none" || !presets || presets.length === 0) {
296
+ inset[variant] = "";
297
+ continue;
298
+ }
299
+ inset[variant] = boxShadowToCssString(convertShadowToBoxShadow(presets, spectrum, palette, true));
300
+ }
301
+ drop["none"] = drop["none"] ?? "";
302
+ inset["none"] = inset["none"] ?? "";
303
+ return {
304
+ drop,
305
+ inset
306
+ };
307
+ }
183
308
  /**
184
309
  * Resolves a typography variant name to React Native text styles.
185
310
  * Looks up the typography config and converts to RN-compatible values.
186
311
  *
187
312
  * @param variantName - The typography variant name (e.g., 'body1', 'label4', 'ui2')
188
- * @param typography - The typography config from UniversalTokensConfig
313
+ * @param typography - The typography config from UniversalTokensConfigGeneric
189
314
  * @param config - The full config for resolving font family aliases
190
315
  * @returns Resolved typography styles (fontSize, lineHeight, letterSpacing, fontFamily)
191
316
  */
@@ -202,13 +327,13 @@ function resolveTypographyStyles(variantName, typography, config) {
202
327
  if (typeof lineHeight === "number") result.lineHeight = lineHeight;
203
328
  if (typeof letterSpacing === "number") result.letterSpacing = letterSpacing;
204
329
  if (typeof fontFamily === "string") {
205
- const fontId = config.font[fontFamily] ?? fontFamily;
330
+ const fontId = applyYasFontOverride(config.font[fontFamily] ?? fontFamily);
206
331
  if (isWebFontID(fontId)) result.fontFamily = getPostScriptName(fontId, typeof fontWeight === "number" ? fontWeight : 400);
207
332
  else result.fontFamily = fontId;
208
333
  }
209
334
  return result;
210
335
  }
211
- function resolveValue(variable, config, colorMode) {
336
+ function resolveValue(variable, config, colorMode, propName) {
212
337
  const { type, value } = variable;
213
338
  const palette = config.colorMode[colorMode].palette;
214
339
  const spectrum = config.colorMode[colorMode].spectrum;
@@ -216,9 +341,9 @@ function resolveValue(variable, config, colorMode) {
216
341
  if (type === "backgroundPaletteColors" || type === "foregroundPaletteColors" || type === "linePaletteColors") {
217
342
  const colorDef = palette[type.replace("PaletteColors", "")]?.[value];
218
343
  if (colorDef) {
219
- const rgbValue = spectrum[colorDef.hue]?.[colorDef.step];
220
- if (rgbValue) {
221
- const parts = rgbValue.trim().split(/\s+/);
344
+ const spectrumEntry = spectrum[colorDef.hue]?.[colorDef.step];
345
+ if (spectrumEntry) {
346
+ const parts = extractRgb(spectrumEntry).trim().split(/\s+/);
222
347
  if (colorDef.opacity !== void 0) return `rgba(${parts.join(", ")}, ${parseInt(colorDef.opacity, 10) / 100})`;
223
348
  return `rgb(${parts.join(", ")})`;
224
349
  }
@@ -232,8 +357,8 @@ function resolveValue(variable, config, colorMode) {
232
357
  if (lastDashIndex > 0) {
233
358
  const hue = colorStr.slice(0, lastDashIndex);
234
359
  const step = colorStr.slice(lastDashIndex + 1);
235
- const rgbValue = spectrum[hue]?.[step];
236
- if (rgbValue) return `rgb(${rgbValue.trim().split(/\s+/).join(", ")})`;
360
+ const spectrumEntry = spectrum[hue]?.[step];
361
+ if (spectrumEntry) return `rgb(${extractRgb(spectrumEntry).trim().split(/\s+/).join(", ")})`;
237
362
  }
238
363
  return;
239
364
  }
@@ -263,6 +388,69 @@ function resolveValue(variable, config, colorMode) {
263
388
  if (dropPresets && dropPresets.length > 0) return convertShadowToBoxShadow(dropPresets, spectrum, palette.foreground, true);
264
389
  return [];
265
390
  }
391
+ if (type === "elevationAliases") {
392
+ const level = value.replace("elevation-", "");
393
+ const elevationPreset = config.elevation[level];
394
+ if (!elevationPreset) return;
395
+ const preset = elevationPreset[colorMode];
396
+ if (propName === "backgroundColor") {
397
+ const backgroundFill = preset.backgroundFill;
398
+ if (backgroundFill.type === "background") {
399
+ const colorDef = palette.background?.[backgroundFill.value];
400
+ if (colorDef) {
401
+ const rgbValue = spectrum[colorDef.hue]?.[colorDef.step];
402
+ if (rgbValue) {
403
+ const parts = extractRgb(rgbValue).trim().split(/\s+/);
404
+ if (colorDef.opacity !== void 0) return `rgba(${parts.join(", ")}, ${parseInt(colorDef.opacity, 10) / 100})`;
405
+ return `rgb(${parts.join(", ")})`;
406
+ }
407
+ }
408
+ } else if (backgroundFill.type === "always") return newAlwaysPalette[backgroundFill.value] ?? "transparent";
409
+ else if (backgroundFill.type === "spectrum") {
410
+ const spectrumValue = backgroundFill.value;
411
+ const rgbValue = spectrum[spectrumValue.hue]?.[spectrumValue.step];
412
+ if (rgbValue) return `rgb(${extractRgb(rgbValue).trim().split(/\s+/).join(", ")})`;
413
+ }
414
+ return "transparent";
415
+ }
416
+ if (propName === "borderColor") {
417
+ const borderColorDef = preset.borderColor;
418
+ if (borderColorDef.type === "line") {
419
+ const colorDef = palette.line?.[borderColorDef.value];
420
+ if (colorDef) {
421
+ const rgbValue = spectrum[colorDef.hue]?.[colorDef.step];
422
+ if (rgbValue) {
423
+ const parts = extractRgb(rgbValue).trim().split(/\s+/);
424
+ if (colorDef.opacity !== void 0) return `rgba(${parts.join(", ")}, ${parseInt(colorDef.opacity, 10) / 100})`;
425
+ return `rgb(${parts.join(", ")})`;
426
+ }
427
+ }
428
+ } else if (borderColorDef.type === "always") return newAlwaysPalette[borderColorDef.value] ?? "transparent";
429
+ else if (borderColorDef.type === "spectrum") {
430
+ const spectrumValue = borderColorDef.value;
431
+ const rgbValue = spectrum[spectrumValue.hue]?.[spectrumValue.step];
432
+ if (rgbValue) return `rgb(${extractRgb(rgbValue).trim().split(/\s+/).join(", ")})`;
433
+ }
434
+ return "transparent";
435
+ }
436
+ if (propName === "borderWidth") {
437
+ const borderWidthKey = preset.borderWidth;
438
+ return scaleConfig.borderWidth[borderWidthKey] ?? 0;
439
+ }
440
+ if (propName === "shadow") {
441
+ const elevationPreset = config.elevation[level];
442
+ if (!elevationPreset) return [];
443
+ const preset = elevationPreset[colorMode];
444
+ if (!preset.dropShadow || preset.dropShadow === "none") return [];
445
+ if (isElevationCustomShadows(preset.dropShadow)) {
446
+ const allPresets = [...preset.dropShadow];
447
+ return allPresets.length > 0 ? convertShadowToBoxShadow(allPresets, spectrum, palette.foreground) : [];
448
+ }
449
+ const refPresets = config.shadow.drop[preset.dropShadow];
450
+ return refPresets && refPresets.length > 0 ? convertShadowToBoxShadow(refPresets, spectrum, palette.foreground) : [];
451
+ }
452
+ return;
453
+ }
266
454
  if (type === "textDecorationLines") return value;
267
455
  if (typeof value === "number") return value;
268
456
  }
@@ -296,7 +484,7 @@ function generateComponents(config, colorMode) {
296
484
  if (!rnProps) continue;
297
485
  const stateValue = states[state];
298
486
  if (!stateValue) continue;
299
- const resolvedValue = resolveValue(stateValue, config, colorMode);
487
+ const resolvedValue = resolveValue(stateValue, config, colorMode, propName);
300
488
  if (resolvedValue === void 0) continue;
301
489
  if (SHADOW_PROPS.has(propName)) {
302
490
  if (Array.isArray(resolvedValue)) shadowValues.push(...resolvedValue);
@@ -356,31 +544,40 @@ function generateComponents(config, colorMode) {
356
544
  function generateTheme(config, colorMode) {
357
545
  const colorsConfig = config.colorMode[colorMode];
358
546
  const scaleConfig = config.scaleMode[DEFAULT_SCALE_MODE];
359
- const elevationColors = generateElevationColors(config.elevation);
547
+ const elevationBackgroundColors = generateElevationBackgroundColors(config, colorMode);
548
+ const elevationBorderColors = generateElevationBorderColors(config, colorMode);
549
+ const boxShadows = generateBoxShadows(config, colorMode);
360
550
  return {
361
551
  colors: {
362
552
  spectrum: sortKeys(generateSpectrum(colorsConfig.spectrum)),
363
553
  background: sortKeys({
364
554
  ...generatePalette(colorsConfig.palette.background, colorsConfig.spectrum),
365
- ...elevationColors
555
+ ...elevationBackgroundColors
366
556
  }),
367
557
  foreground: sortKeys(generatePalette(colorsConfig.palette.foreground, colorsConfig.spectrum)),
368
558
  line: sortKeys({
369
559
  ...generatePalette(colorsConfig.palette.line, colorsConfig.spectrum),
370
- ...elevationColors
560
+ ...elevationBorderColors
371
561
  })
372
562
  },
373
563
  spacing: sortKeys({ ...spacingMap }),
374
564
  borderRadius: sortKeys({ ...scaleConfig.borderRadius }),
375
565
  borderWidth: sortKeys({
376
566
  ...scaleConfig.borderWidth,
377
- ...Object.fromEntries(Object.keys(config.elevation).map((level) => [`elevation-${level}`, parseInt(level, 10)]))
567
+ ...Object.fromEntries(Object.keys(config.elevation).map((level) => {
568
+ const borderWidthKey = config.elevation[level].light.borderWidth;
569
+ return [`elevation-${level}`, scaleConfig.borderWidth[borderWidthKey] ?? 0];
570
+ }))
378
571
  }),
379
572
  iconSize: sortKeys({ ...scaleConfig.iconSizes }),
380
573
  avatarSize: sortKeys({ ...scaleConfig.avatarSizes }),
381
574
  font: sortKeys(generateFontAliases(config.font)),
382
575
  typography: sortKeys(generateTypography(config.typography, config.font)),
383
576
  shadow: sortKeys(generateShadows(config)),
577
+ boxShadow: {
578
+ drop: sortKeys(boxShadows.drop),
579
+ inset: sortKeys(boxShadows.inset)
580
+ },
384
581
  components: generateComponents(config, colorMode)
385
582
  };
386
583
  }
@@ -4,6 +4,7 @@ const require_runtime = require('../_virtual/_rolldown/runtime.cjs');
4
4
  let react = require("react");
5
5
  let react_native = require("react-native");
6
6
  let generated_styles = require("../../generated/styles");
7
+ let react_native_unistyles = require("react-native-unistyles");
7
8
  let react_jsx_runtime = require("react/jsx-runtime");
8
9
 
9
10
  //#region src/components/Box.tsx
@@ -35,20 +36,21 @@ let react_jsx_runtime = require("react/jsx-runtime");
35
36
  * @see {@link HStack} for horizontal layouts
36
37
  * @see {@link VStack} for vertical layouts
37
38
  */
38
- const Box = (0, react.memo)(function Box({ backgroundColor, dangerouslySetBackgroundColor, borderRadius, borderTopStartRadius, borderTopEndRadius, borderBottomStartRadius, borderBottomEndRadius, borderColor, dangerouslySetBorderColor, borderStartColor, borderEndColor, borderTopColor, borderBottomColor, borderWidth, borderVerticalWidth, borderHorizontalWidth, borderStartWidth, borderEndWidth, borderTopWidth, borderBottomWidth, alignContent, alignItems, alignSelf, flex, flexDirection, flexGrow, flexShrink, flexWrap, justifyContent, display = "flex", overflow, spacing, spacingHorizontal, spacingVertical, spacingBottom, spacingEnd, spacingStart, spacingTop, offset, offsetVertical, offsetHorizontal, offsetBottom, offsetEnd, offsetStart, offsetTop, columnGap, rowGap, width, height, minWidth, maxWidth, minHeight, maxHeight, style, ref, ...props }) {
39
+ const Box = (0, react.memo)(function Box({ elevation, backgroundColor, dangerouslySetBackgroundColor, borderRadius, borderTopStartRadius, borderTopEndRadius, borderBottomStartRadius, borderBottomEndRadius, borderColor, dangerouslySetBorderColor, borderStartColor, borderEndColor, borderTopColor, borderBottomColor, borderWidth, borderVerticalWidth, borderHorizontalWidth, borderStartWidth, borderEndWidth, borderTopWidth, borderBottomWidth, alignContent, alignItems, alignSelf, flex, flexDirection, flexGrow, flexShrink, flexWrap, justifyContent, display = "flex", overflow, spacing, spacingHorizontal, spacingVertical, spacingBottom, spacingEnd, spacingStart, spacingTop, offset, offsetVertical, offsetHorizontal, offsetBottom, offsetEnd, offsetStart, offsetTop, columnGap, rowGap, width, height, minWidth, maxWidth, minHeight, maxHeight, dropShadow, insetShadow, style, ref, ...props }) {
40
+ const elevationAlias = elevation !== void 0 ? `elevation-${elevation}` : void 0;
39
41
  const variants = {
40
- backgroundColor,
42
+ backgroundColor: backgroundColor ?? elevationAlias,
41
43
  borderRadius,
42
44
  borderTopStartRadius,
43
45
  borderTopEndRadius,
44
46
  borderBottomStartRadius,
45
47
  borderBottomEndRadius,
46
- borderColor,
48
+ borderColor: borderColor ?? elevationAlias,
47
49
  borderStartColor,
48
50
  borderEndColor,
49
51
  borderTopColor,
50
52
  borderBottomColor,
51
- borderWidth,
53
+ borderWidth: borderWidth ?? elevationAlias,
52
54
  borderVerticalWidth,
53
55
  borderHorizontalWidth,
54
56
  borderStartWidth,
@@ -84,6 +86,8 @@ const Box = (0, react.memo)(function Box({ backgroundColor, dangerouslySetBackgr
84
86
  rowGap
85
87
  };
86
88
  generated_styles.styles.useVariants(variants);
89
+ const effectiveDropShadow = dropShadow ?? elevationAlias;
90
+ const shadowStyle = effectiveDropShadow || insetShadow ? shadowSheet.shadow(effectiveDropShadow, insetShadow) : void 0;
87
91
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, {
88
92
  ref,
89
93
  style: (0, react.useMemo)(() => [
@@ -95,6 +99,7 @@ const Box = (0, react.memo)(function Box({ backgroundColor, dangerouslySetBackgr
95
99
  maxWidth ? { maxWidth } : void 0,
96
100
  minHeight ? { minHeight } : void 0,
97
101
  maxHeight ? { maxHeight } : void 0,
102
+ shadowStyle,
98
103
  generated_styles.styles.foundation,
99
104
  style
100
105
  ], [
@@ -106,6 +111,7 @@ const Box = (0, react.memo)(function Box({ backgroundColor, dangerouslySetBackgr
106
111
  maxWidth,
107
112
  minHeight,
108
113
  maxHeight,
114
+ shadowStyle,
109
115
  generated_styles.styles.foundation,
110
116
  style
111
117
  ]),
@@ -113,6 +119,14 @@ const Box = (0, react.memo)(function Box({ backgroundColor, dangerouslySetBackgr
113
119
  });
114
120
  });
115
121
  Box.displayName = "Box";
122
+ /**
123
+ * Dynamic shadow stylesheet that merges drop and inset shadows into a single
124
+ * boxShadow CSS string. Theme-reactive so shadows update on color mode change.
125
+ */
126
+ const shadowSheet = react_native_unistyles.StyleSheet.create((theme) => ({ shadow: (drop, inset) => {
127
+ const parts = [drop ? theme.boxShadow.drop[drop] : "", inset ? theme.boxShadow.inset[inset] : ""].filter(Boolean);
128
+ return parts.length > 0 ? { boxShadow: parts.join(", ") } : {};
129
+ } }));
116
130
 
117
131
  //#endregion
118
132
  exports.Box = Box;
@@ -1,4 +1,5 @@
1
1
 
2
+ import { ElevationLevel } from "../types/dist/index.cjs";
2
3
  import { SizeProps } from "../types.cjs";
3
4
  import * as react from "react";
4
5
  import { Ref } from "react";
@@ -7,9 +8,8 @@ import { StyleProps } from "../../generated/styles";
7
8
 
8
9
  //#region src/components/Box.d.ts
9
10
  interface BoxProps extends ViewProps, SizeProps {
10
- /** Ref to the underlying View */
11
11
  ref?: Ref<View>;
12
- /** Background color from the theme palette */
12
+ elevation?: ElevationLevel;
13
13
  backgroundColor?: StyleProps['backgroundColor'];
14
14
  borderRadius?: StyleProps['borderRadius'];
15
15
  borderTopStartRadius?: StyleProps['borderTopStartRadius'];
@@ -55,6 +55,8 @@ interface BoxProps extends ViewProps, SizeProps {
55
55
  offsetTop?: StyleProps['offsetTop'];
56
56
  columnGap?: StyleProps['columnGap'];
57
57
  rowGap?: StyleProps['rowGap'];
58
+ dropShadow?: StyleProps['dropShadow'];
59
+ insetShadow?: StyleProps['insetShadow'];
58
60
  dangerouslySetBackgroundColor?: string;
59
61
  dangerouslySetBorderColor?: string;
60
62
  }
@@ -1 +1 @@
1
- {"version":3,"file":"Box.d.cts","names":[],"sources":["../../src/components/Box.tsx"],"mappings":";;;;;;;;UASU,QAAA,SAAiB,SAAA,EAAW,SAAA;;EAEpC,GAAA,GAAM,GAAA,CAAI,IAAA;EAFO;EAIjB,eAAA,GAAkB,UAAA;EAClB,YAAA,GAAe,UAAA;EACf,oBAAA,GAAuB,UAAA;EACvB,kBAAA,GAAqB,UAAA;EACrB,uBAAA,GAA0B,UAAA;EAC1B,qBAAA,GAAwB,UAAA;EACxB,WAAA,GAAc,UAAA;EACd,gBAAA,GAAmB,UAAA;EACnB,cAAA,GAAiB,UAAA;EACjB,cAAA,GAAiB,UAAA;EACjB,iBAAA,GAAoB,UAAA;EACpB,WAAA,GAAc,UAAA;EACd,mBAAA,GAAsB,UAAA;EACtB,qBAAA,GAAwB,UAAA;EACxB,gBAAA,GAAmB,UAAA;EACnB,cAAA,GAAiB,UAAA;EACjB,cAAA,GAAiB,UAAA;EACjB,iBAAA,GAAoB,UAAA;EACpB,YAAA,GAAe,UAAA;EACf,UAAA,GAAa,UAAA;EACb,SAAA,GAAY,UAAA;EACZ,IAAA,GAAO,UAAA;EACP,aAAA,GAAgB,UAAA;EAChB,QAAA,GAAW,UAAA;EACX,UAAA,GAAa,UAAA;EACb,QAAA,GAAW,UAAA;EACX,cAAA,GAAiB,UAAA;EAEjB,OAAA,GAAU,UAAA;EACV,QAAA,GAAW,UAAA;EAIX,OAAA,GAAU,UAAA;EACV,iBAAA,GAAoB,UAAA;EACpB,eAAA,GAAkB,UAAA;EAClB,aAAA,GAAgB,UAAA;EAChB,UAAA,GAAa,UAAA;EACb,YAAA,GAAe,UAAA;EACf,UAAA,GAAa,UAAA;EACb,MAAA,GAAS,UAAA;EACT,cAAA,GAAiB,UAAA;EACjB,gBAAA,GAAmB,UAAA;EACnB,YAAA,GAAe,UAAA;EACf,SAAA,GAAY,UAAA;EACZ,WAAA,GAAc,UAAA;EACd,SAAA,GAAY,UAAA;EACZ,SAAA,GAAY,UAAA;EACZ,MAAA,GAAS,UAAA;EACT,6BAAA;EACA,yBAAA;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cA+BI,GAAA,EAAG,KAAA,CAAA,oBAAA,CAAA,QAAA"}
1
+ {"version":3,"file":"Box.d.cts","names":[],"sources":["../../src/components/Box.tsx"],"mappings":";;;;;;;;;UAWU,QAAA,SAAiB,SAAA,EAAW,SAAA;EACpC,GAAA,GAAM,GAAA,CAAI,IAAA;EACV,SAAA,GAAY,cAAA;EACZ,eAAA,GAAkB,UAAA;EAClB,YAAA,GAAe,UAAA;EACf,oBAAA,GAAuB,UAAA;EACvB,kBAAA,GAAqB,UAAA;EACrB,uBAAA,GAA0B,UAAA;EAC1B,qBAAA,GAAwB,UAAA;EACxB,WAAA,GAAc,UAAA;EACd,gBAAA,GAAmB,UAAA;EACnB,cAAA,GAAiB,UAAA;EACjB,cAAA,GAAiB,UAAA;EACjB,iBAAA,GAAoB,UAAA;EACpB,WAAA,GAAc,UAAA;EACd,mBAAA,GAAsB,UAAA;EACtB,qBAAA,GAAwB,UAAA;EACxB,gBAAA,GAAmB,UAAA;EACnB,cAAA,GAAiB,UAAA;EACjB,cAAA,GAAiB,UAAA;EACjB,iBAAA,GAAoB,UAAA;EACpB,YAAA,GAAe,UAAA;EACf,UAAA,GAAa,UAAA;EACb,SAAA,GAAY,UAAA;EACZ,IAAA,GAAO,UAAA;EACP,aAAA,GAAgB,UAAA;EAChB,QAAA,GAAW,UAAA;EACX,UAAA,GAAa,UAAA;EACb,QAAA,GAAW,UAAA;EACX,cAAA,GAAiB,UAAA;EAEjB,OAAA,GAAU,UAAA;EACV,QAAA,GAAW,UAAA;EAIX,OAAA,GAAU,UAAA;EACV,iBAAA,GAAoB,UAAA;EACpB,eAAA,GAAkB,UAAA;EAClB,aAAA,GAAgB,UAAA;EAChB,UAAA,GAAa,UAAA;EACb,YAAA,GAAe,UAAA;EACf,UAAA,GAAa,UAAA;EACb,MAAA,GAAS,UAAA;EACT,cAAA,GAAiB,UAAA;EACjB,gBAAA,GAAmB,UAAA;EACnB,YAAA,GAAe,UAAA;EACf,SAAA,GAAY,UAAA;EACZ,WAAA,GAAc,UAAA;EACd,SAAA,GAAY,UAAA;EACZ,SAAA,GAAY,UAAA;EACZ,MAAA,GAAS,UAAA;EACT,UAAA,GAAa,UAAA;EACb,WAAA,GAAc,UAAA;EACd,6BAAA;EACA,yBAAA;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cA+BI,GAAA,EAAG,KAAA,CAAA,oBAAA,CAAA,QAAA"}
@@ -1,4 +1,5 @@
1
1
 
2
+ import { ElevationLevel } from "../types/dist/index.mjs";
2
3
  import { SizeProps } from "../types.mjs";
3
4
  import * as react from "react";
4
5
  import { Ref } from "react";
@@ -7,9 +8,8 @@ import { StyleProps } from "../../generated/styles";
7
8
 
8
9
  //#region src/components/Box.d.ts
9
10
  interface BoxProps extends ViewProps, SizeProps {
10
- /** Ref to the underlying View */
11
11
  ref?: Ref<View>;
12
- /** Background color from the theme palette */
12
+ elevation?: ElevationLevel;
13
13
  backgroundColor?: StyleProps['backgroundColor'];
14
14
  borderRadius?: StyleProps['borderRadius'];
15
15
  borderTopStartRadius?: StyleProps['borderTopStartRadius'];
@@ -55,6 +55,8 @@ interface BoxProps extends ViewProps, SizeProps {
55
55
  offsetTop?: StyleProps['offsetTop'];
56
56
  columnGap?: StyleProps['columnGap'];
57
57
  rowGap?: StyleProps['rowGap'];
58
+ dropShadow?: StyleProps['dropShadow'];
59
+ insetShadow?: StyleProps['insetShadow'];
58
60
  dangerouslySetBackgroundColor?: string;
59
61
  dangerouslySetBorderColor?: string;
60
62
  }
@@ -1 +1 @@
1
- {"version":3,"file":"Box.d.mts","names":[],"sources":["../../src/components/Box.tsx"],"mappings":";;;;;;;;UASU,QAAA,SAAiB,SAAA,EAAW,SAAA;;EAEpC,GAAA,GAAM,GAAA,CAAI,IAAA;EAFO;EAIjB,eAAA,GAAkB,UAAA;EAClB,YAAA,GAAe,UAAA;EACf,oBAAA,GAAuB,UAAA;EACvB,kBAAA,GAAqB,UAAA;EACrB,uBAAA,GAA0B,UAAA;EAC1B,qBAAA,GAAwB,UAAA;EACxB,WAAA,GAAc,UAAA;EACd,gBAAA,GAAmB,UAAA;EACnB,cAAA,GAAiB,UAAA;EACjB,cAAA,GAAiB,UAAA;EACjB,iBAAA,GAAoB,UAAA;EACpB,WAAA,GAAc,UAAA;EACd,mBAAA,GAAsB,UAAA;EACtB,qBAAA,GAAwB,UAAA;EACxB,gBAAA,GAAmB,UAAA;EACnB,cAAA,GAAiB,UAAA;EACjB,cAAA,GAAiB,UAAA;EACjB,iBAAA,GAAoB,UAAA;EACpB,YAAA,GAAe,UAAA;EACf,UAAA,GAAa,UAAA;EACb,SAAA,GAAY,UAAA;EACZ,IAAA,GAAO,UAAA;EACP,aAAA,GAAgB,UAAA;EAChB,QAAA,GAAW,UAAA;EACX,UAAA,GAAa,UAAA;EACb,QAAA,GAAW,UAAA;EACX,cAAA,GAAiB,UAAA;EAEjB,OAAA,GAAU,UAAA;EACV,QAAA,GAAW,UAAA;EAIX,OAAA,GAAU,UAAA;EACV,iBAAA,GAAoB,UAAA;EACpB,eAAA,GAAkB,UAAA;EAClB,aAAA,GAAgB,UAAA;EAChB,UAAA,GAAa,UAAA;EACb,YAAA,GAAe,UAAA;EACf,UAAA,GAAa,UAAA;EACb,MAAA,GAAS,UAAA;EACT,cAAA,GAAiB,UAAA;EACjB,gBAAA,GAAmB,UAAA;EACnB,YAAA,GAAe,UAAA;EACf,SAAA,GAAY,UAAA;EACZ,WAAA,GAAc,UAAA;EACd,SAAA,GAAY,UAAA;EACZ,SAAA,GAAY,UAAA;EACZ,MAAA,GAAS,UAAA;EACT,6BAAA;EACA,yBAAA;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cA+BI,GAAA,EAAG,KAAA,CAAA,oBAAA,CAAA,QAAA"}
1
+ {"version":3,"file":"Box.d.mts","names":[],"sources":["../../src/components/Box.tsx"],"mappings":";;;;;;;;;UAWU,QAAA,SAAiB,SAAA,EAAW,SAAA;EACpC,GAAA,GAAM,GAAA,CAAI,IAAA;EACV,SAAA,GAAY,cAAA;EACZ,eAAA,GAAkB,UAAA;EAClB,YAAA,GAAe,UAAA;EACf,oBAAA,GAAuB,UAAA;EACvB,kBAAA,GAAqB,UAAA;EACrB,uBAAA,GAA0B,UAAA;EAC1B,qBAAA,GAAwB,UAAA;EACxB,WAAA,GAAc,UAAA;EACd,gBAAA,GAAmB,UAAA;EACnB,cAAA,GAAiB,UAAA;EACjB,cAAA,GAAiB,UAAA;EACjB,iBAAA,GAAoB,UAAA;EACpB,WAAA,GAAc,UAAA;EACd,mBAAA,GAAsB,UAAA;EACtB,qBAAA,GAAwB,UAAA;EACxB,gBAAA,GAAmB,UAAA;EACnB,cAAA,GAAiB,UAAA;EACjB,cAAA,GAAiB,UAAA;EACjB,iBAAA,GAAoB,UAAA;EACpB,YAAA,GAAe,UAAA;EACf,UAAA,GAAa,UAAA;EACb,SAAA,GAAY,UAAA;EACZ,IAAA,GAAO,UAAA;EACP,aAAA,GAAgB,UAAA;EAChB,QAAA,GAAW,UAAA;EACX,UAAA,GAAa,UAAA;EACb,QAAA,GAAW,UAAA;EACX,cAAA,GAAiB,UAAA;EAEjB,OAAA,GAAU,UAAA;EACV,QAAA,GAAW,UAAA;EAIX,OAAA,GAAU,UAAA;EACV,iBAAA,GAAoB,UAAA;EACpB,eAAA,GAAkB,UAAA;EAClB,aAAA,GAAgB,UAAA;EAChB,UAAA,GAAa,UAAA;EACb,YAAA,GAAe,UAAA;EACf,UAAA,GAAa,UAAA;EACb,MAAA,GAAS,UAAA;EACT,cAAA,GAAiB,UAAA;EACjB,gBAAA,GAAmB,UAAA;EACnB,YAAA,GAAe,UAAA;EACf,SAAA,GAAY,UAAA;EACZ,WAAA,GAAc,UAAA;EACd,SAAA,GAAY,UAAA;EACZ,SAAA,GAAY,UAAA;EACZ,MAAA,GAAS,UAAA;EACT,UAAA,GAAa,UAAA;EACb,WAAA,GAAc,UAAA;EACd,6BAAA;EACA,yBAAA;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cA+BI,GAAA,EAAG,KAAA,CAAA,oBAAA,CAAA,QAAA"}
@@ -2,6 +2,7 @@
2
2
  import { memo, useMemo } from "react";
3
3
  import { View } from "react-native";
4
4
  import { styles } from "../../generated/styles";
5
+ import { StyleSheet } from "react-native-unistyles";
5
6
  import { jsx } from "react/jsx-runtime";
6
7
 
7
8
  //#region src/components/Box.tsx
@@ -33,20 +34,21 @@ import { jsx } from "react/jsx-runtime";
33
34
  * @see {@link HStack} for horizontal layouts
34
35
  * @see {@link VStack} for vertical layouts
35
36
  */
36
- const Box = memo(function Box({ backgroundColor, dangerouslySetBackgroundColor, borderRadius, borderTopStartRadius, borderTopEndRadius, borderBottomStartRadius, borderBottomEndRadius, borderColor, dangerouslySetBorderColor, borderStartColor, borderEndColor, borderTopColor, borderBottomColor, borderWidth, borderVerticalWidth, borderHorizontalWidth, borderStartWidth, borderEndWidth, borderTopWidth, borderBottomWidth, alignContent, alignItems, alignSelf, flex, flexDirection, flexGrow, flexShrink, flexWrap, justifyContent, display = "flex", overflow, spacing, spacingHorizontal, spacingVertical, spacingBottom, spacingEnd, spacingStart, spacingTop, offset, offsetVertical, offsetHorizontal, offsetBottom, offsetEnd, offsetStart, offsetTop, columnGap, rowGap, width, height, minWidth, maxWidth, minHeight, maxHeight, style, ref, ...props }) {
37
+ const Box = memo(function Box({ elevation, backgroundColor, dangerouslySetBackgroundColor, borderRadius, borderTopStartRadius, borderTopEndRadius, borderBottomStartRadius, borderBottomEndRadius, borderColor, dangerouslySetBorderColor, borderStartColor, borderEndColor, borderTopColor, borderBottomColor, borderWidth, borderVerticalWidth, borderHorizontalWidth, borderStartWidth, borderEndWidth, borderTopWidth, borderBottomWidth, alignContent, alignItems, alignSelf, flex, flexDirection, flexGrow, flexShrink, flexWrap, justifyContent, display = "flex", overflow, spacing, spacingHorizontal, spacingVertical, spacingBottom, spacingEnd, spacingStart, spacingTop, offset, offsetVertical, offsetHorizontal, offsetBottom, offsetEnd, offsetStart, offsetTop, columnGap, rowGap, width, height, minWidth, maxWidth, minHeight, maxHeight, dropShadow, insetShadow, style, ref, ...props }) {
38
+ const elevationAlias = elevation !== void 0 ? `elevation-${elevation}` : void 0;
37
39
  const variants = {
38
- backgroundColor,
40
+ backgroundColor: backgroundColor ?? elevationAlias,
39
41
  borderRadius,
40
42
  borderTopStartRadius,
41
43
  borderTopEndRadius,
42
44
  borderBottomStartRadius,
43
45
  borderBottomEndRadius,
44
- borderColor,
46
+ borderColor: borderColor ?? elevationAlias,
45
47
  borderStartColor,
46
48
  borderEndColor,
47
49
  borderTopColor,
48
50
  borderBottomColor,
49
- borderWidth,
51
+ borderWidth: borderWidth ?? elevationAlias,
50
52
  borderVerticalWidth,
51
53
  borderHorizontalWidth,
52
54
  borderStartWidth,
@@ -82,6 +84,8 @@ const Box = memo(function Box({ backgroundColor, dangerouslySetBackgroundColor,
82
84
  rowGap
83
85
  };
84
86
  styles.useVariants(variants);
87
+ const effectiveDropShadow = dropShadow ?? elevationAlias;
88
+ const shadowStyle = effectiveDropShadow || insetShadow ? shadowSheet.shadow(effectiveDropShadow, insetShadow) : void 0;
85
89
  return /* @__PURE__ */ jsx(View, {
86
90
  ref,
87
91
  style: useMemo(() => [
@@ -93,6 +97,7 @@ const Box = memo(function Box({ backgroundColor, dangerouslySetBackgroundColor,
93
97
  maxWidth ? { maxWidth } : void 0,
94
98
  minHeight ? { minHeight } : void 0,
95
99
  maxHeight ? { maxHeight } : void 0,
100
+ shadowStyle,
96
101
  styles.foundation,
97
102
  style
98
103
  ], [
@@ -104,6 +109,7 @@ const Box = memo(function Box({ backgroundColor, dangerouslySetBackgroundColor,
104
109
  maxWidth,
105
110
  minHeight,
106
111
  maxHeight,
112
+ shadowStyle,
107
113
  styles.foundation,
108
114
  style
109
115
  ]),
@@ -111,6 +117,14 @@ const Box = memo(function Box({ backgroundColor, dangerouslySetBackgroundColor,
111
117
  });
112
118
  });
113
119
  Box.displayName = "Box";
120
+ /**
121
+ * Dynamic shadow stylesheet that merges drop and inset shadows into a single
122
+ * boxShadow CSS string. Theme-reactive so shadows update on color mode change.
123
+ */
124
+ const shadowSheet = StyleSheet.create((theme) => ({ shadow: (drop, inset) => {
125
+ const parts = [drop ? theme.boxShadow.drop[drop] : "", inset ? theme.boxShadow.inset[inset] : ""].filter(Boolean);
126
+ return parts.length > 0 ? { boxShadow: parts.join(", ") } : {};
127
+ } }));
114
128
 
115
129
  //#endregion
116
130
  export { Box };