@ankhorage/surface 2.2.0 → 2.2.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/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @ankhorage/surface
2
2
 
3
+ ## 2.2.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 7f410d4: Preserve Stack child flex and min-size semantics by applying spacing with the container gap property instead of wrapper views.
8
+
3
9
  ## 2.2.0
4
10
 
5
11
  ### Minor Changes
package/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
 
4
4
  # @ankhorage/surface
5
5
 
6
- ![license: MIT](././paradox/badges/license.svg) ![npm: v2.1.1](././paradox/badges/npm.svg) ![runtime: bun](././paradox/badges/runtime.svg) ![typescript: strict](././paradox/badges/typescript.svg) ![eslint: checked](././paradox/badges/eslint.svg) ![prettier: checked](././paradox/badges/prettier.svg) ![build: checked](././paradox/badges/build.svg) ![tests: checked](././paradox/badges/tests.svg) ![docs: paradox](././paradox/badges/docs.svg)
6
+ ![license: MIT](././paradox/badges/license.svg) ![npm: v2.2.0](././paradox/badges/npm.svg) ![runtime: bun](././paradox/badges/runtime.svg) ![typescript: strict](././paradox/badges/typescript.svg) ![eslint: checked](././paradox/badges/eslint.svg) ![prettier: checked](././paradox/badges/prettier.svg) ![build: checked](././paradox/badges/build.svg) ![tests: checked](././paradox/badges/tests.svg) ![docs: paradox](././paradox/badges/docs.svg)
7
7
 
8
8
  Cross-platform UI foundation for React Native and React Native Web. Provides theming, layout primitives, and core building blocks for modern apps.
9
9
 
@@ -1,4 +1,4 @@
1
- import React from 'react';
1
+ import type React from 'react';
2
2
  import { type Responsive } from '../core/responsive';
3
3
  import { type BoxProps } from './Box';
4
4
  import { type SpaceValue } from './helpers';
@@ -1 +1 @@
1
- {"version":3,"file":"Stack.d.ts","sourceRoot":"","sources":["../../src/layout/Stack.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,OAAO,EAAqB,KAAK,UAAU,EAAwB,MAAM,oBAAoB,CAAC;AAE9F,OAAO,EAAO,KAAK,QAAQ,EAAE,MAAM,OAAO,CAAC;AAC3C,OAAO,EAAkB,KAAK,UAAU,EAAE,MAAM,WAAW,CAAC;AAE5D,MAAM,WAAW,UAAW,SAAQ,IAAI,CAAC,QAAQ,EAAE,UAAU,CAAC;IAC5D,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,SAAS,CAAC,EAAE,UAAU,CAAC,KAAK,GAAG,QAAQ,CAAC,CAAC;IACzC,GAAG,CAAC,EAAE,UAAU,CAAC,UAAU,CAAC,CAAC;IAC7B,KAAK,CAAC,EAAE,UAAU,CAAC,YAAY,GAAG,QAAQ,GAAG,UAAU,GAAG,SAAS,GAAG,UAAU,CAAC,CAAC;IAClF,OAAO,CAAC,EAAE,UAAU,CAClB,YAAY,GAAG,QAAQ,GAAG,UAAU,GAAG,eAAe,GAAG,cAAc,GAAG,cAAc,CACzF,CAAC;IACF,IAAI,CAAC,EAAE,UAAU,CAAC,QAAQ,GAAG,MAAM,CAAC,CAAC;CACtC;AAED,wBAAgB,KAAK,CAAC,EACpB,QAAQ,EACR,SAAoB,EACpB,GAAO,EACP,KAAK,EACL,OAAO,EACP,IAAI,EACJ,GAAG,KAAK,EACT,EAAE,UAAU,qBAuCZ"}
1
+ {"version":3,"file":"Stack.d.ts","sourceRoot":"","sources":["../../src/layout/Stack.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,EAAqB,KAAK,UAAU,EAAwB,MAAM,oBAAoB,CAAC;AAE9F,OAAO,EAAO,KAAK,QAAQ,EAAE,MAAM,OAAO,CAAC;AAC3C,OAAO,EAAkB,KAAK,UAAU,EAAE,MAAM,WAAW,CAAC;AAE5D,MAAM,WAAW,UAAW,SAAQ,IAAI,CAAC,QAAQ,EAAE,UAAU,CAAC;IAC5D,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,SAAS,CAAC,EAAE,UAAU,CAAC,KAAK,GAAG,QAAQ,CAAC,CAAC;IACzC,GAAG,CAAC,EAAE,UAAU,CAAC,UAAU,CAAC,CAAC;IAC7B,KAAK,CAAC,EAAE,UAAU,CAAC,YAAY,GAAG,QAAQ,GAAG,UAAU,GAAG,SAAS,GAAG,UAAU,CAAC,CAAC;IAClF,OAAO,CAAC,EAAE,UAAU,CAClB,YAAY,GAAG,QAAQ,GAAG,UAAU,GAAG,eAAe,GAAG,cAAc,GAAG,cAAc,CACzF,CAAC;IACF,IAAI,CAAC,EAAE,UAAU,CAAC,QAAQ,GAAG,MAAM,CAAC,CAAC;CACtC;AAED,wBAAgB,KAAK,CAAC,EACpB,QAAQ,EACR,SAAoB,EACpB,GAAO,EACP,KAAK,EACL,OAAO,EACP,IAAI,EACJ,GAAG,KAAK,EACT,EAAE,UAAU,qBA0BZ"}
@@ -1,5 +1,3 @@
1
- import React from 'react';
2
- import { View } from 'react-native';
3
1
  import { resolveResponsive, useResponsiveRuntime } from '../core/responsive';
4
2
  import { useTheme } from '../theme/ThemeContext';
5
3
  import { Box } from './Box';
@@ -12,26 +10,17 @@ export function Stack({ children, direction = 'column', gap = 0, align, justify,
12
10
  const activeAlign = resolveResponsive(align, breakpoint);
13
11
  const activeJustify = resolveResponsive(justify, breakpoint);
14
12
  const activeWrap = resolveResponsive(wrap, breakpoint);
15
- const nodes = React.Children.toArray(children);
16
13
  return (<Box {...props} style={[
17
14
  {
18
15
  flexDirection: activeDirection,
16
+ gap: activeGap,
19
17
  alignItems: activeAlign,
20
18
  justifyContent: activeJustify,
21
19
  flexWrap: activeWrap,
22
20
  },
23
21
  props.style,
24
22
  ]}>
25
- {nodes.map((node, index) => {
26
- const spacing = index === 0
27
- ? undefined
28
- : activeDirection === 'row'
29
- ? { marginLeft: activeGap }
30
- : { marginTop: activeGap };
31
- return (<View key={String(index)} style={spacing}>
32
- {node}
33
- </View>);
34
- })}
23
+ {children}
35
24
  </Box>);
36
25
  }
37
26
  //# sourceMappingURL=Stack.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Stack.js","sourceRoot":"","sources":["../../src/layout/Stack.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAEpC,OAAO,EAAE,iBAAiB,EAAmB,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC9F,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,EAAE,GAAG,EAAiB,MAAM,OAAO,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAmB,MAAM,WAAW,CAAC;AAa5D,MAAM,UAAU,KAAK,CAAC,EACpB,QAAQ,EACR,SAAS,GAAG,QAAQ,EACpB,GAAG,GAAG,CAAC,EACP,KAAK,EACL,OAAO,EACP,IAAI,EACJ,GAAG,KAAK,EACG;IACX,MAAM,EAAE,KAAK,EAAE,GAAG,QAAQ,EAAE,CAAC;IAC7B,MAAM,EAAE,UAAU,EAAE,GAAG,oBAAoB,EAAE,CAAC;IAC9C,MAAM,eAAe,GAAG,iBAAiB,CAAC,SAAS,EAAE,UAAU,CAAC,IAAI,QAAQ,CAAC;IAC7E,MAAM,SAAS,GAAG,cAAc,CAAC,KAAK,EAAE,iBAAiB,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC,IAAI,CAAC,CAAC;IACjF,MAAM,WAAW,GAAG,iBAAiB,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;IACzD,MAAM,aAAa,GAAG,iBAAiB,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;IAC7D,MAAM,UAAU,GAAG,iBAAiB,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;IAEvD,MAAM,KAAK,GAAG,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IAE/C,OAAO,CACL,CAAC,GAAG,CACF,IAAI,KAAK,CAAC,CACV,KAAK,CAAC,CAAC;YACL;gBACE,aAAa,EAAE,eAAe;gBAC9B,UAAU,EAAE,WAAW;gBACvB,cAAc,EAAE,aAAa;gBAC7B,QAAQ,EAAE,UAAU;aACrB;YACD,KAAK,CAAC,KAAK;SACZ,CAAC,CAEF;MAAA,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;YACzB,MAAM,OAAO,GACX,KAAK,KAAK,CAAC;gBACT,CAAC,CAAC,SAAS;gBACX,CAAC,CAAC,eAAe,KAAK,KAAK;oBACzB,CAAC,CAAC,EAAE,UAAU,EAAE,SAAS,EAAE;oBAC3B,CAAC,CAAC,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC;YACjC,OAAO,CACL,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CACvC;YAAA,CAAC,IAAI,CACP;UAAA,EAAE,IAAI,CAAC,CACR,CAAC;QACJ,CAAC,CAAC,CACJ;IAAA,EAAE,GAAG,CAAC,CACP,CAAC;AACJ,CAAC","sourcesContent":["import React from 'react';\nimport { View } from 'react-native';\n\nimport { resolveResponsive, type Responsive, useResponsiveRuntime } from '../core/responsive';\nimport { useTheme } from '../theme/ThemeContext';\nimport { Box, type BoxProps } from './Box';\nimport { resolveSpacing, type SpaceValue } from './helpers';\n\nexport interface StackProps extends Omit<BoxProps, 'children'> {\n children?: React.ReactNode;\n direction?: Responsive<'row' | 'column'>;\n gap?: Responsive<SpaceValue>;\n align?: Responsive<'flex-start' | 'center' | 'flex-end' | 'stretch' | 'baseline'>;\n justify?: Responsive<\n 'flex-start' | 'center' | 'flex-end' | 'space-between' | 'space-around' | 'space-evenly'\n >;\n wrap?: Responsive<'nowrap' | 'wrap'>;\n}\n\nexport function Stack({\n children,\n direction = 'column',\n gap = 0,\n align,\n justify,\n wrap,\n ...props\n}: StackProps) {\n const { theme } = useTheme();\n const { breakpoint } = useResponsiveRuntime();\n const activeDirection = resolveResponsive(direction, breakpoint) ?? 'column';\n const activeGap = resolveSpacing(theme, resolveResponsive(gap, breakpoint)) ?? 0;\n const activeAlign = resolveResponsive(align, breakpoint);\n const activeJustify = resolveResponsive(justify, breakpoint);\n const activeWrap = resolveResponsive(wrap, breakpoint);\n\n const nodes = React.Children.toArray(children);\n\n return (\n <Box\n {...props}\n style={[\n {\n flexDirection: activeDirection,\n alignItems: activeAlign,\n justifyContent: activeJustify,\n flexWrap: activeWrap,\n },\n props.style,\n ]}\n >\n {nodes.map((node, index) => {\n const spacing =\n index === 0\n ? undefined\n : activeDirection === 'row'\n ? { marginLeft: activeGap }\n : { marginTop: activeGap };\n return (\n <View key={String(index)} style={spacing}>\n {node}\n </View>\n );\n })}\n </Box>\n );\n}\n"]}
1
+ {"version":3,"file":"Stack.js","sourceRoot":"","sources":["../../src/layout/Stack.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAmB,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC9F,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,EAAE,GAAG,EAAiB,MAAM,OAAO,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAmB,MAAM,WAAW,CAAC;AAa5D,MAAM,UAAU,KAAK,CAAC,EACpB,QAAQ,EACR,SAAS,GAAG,QAAQ,EACpB,GAAG,GAAG,CAAC,EACP,KAAK,EACL,OAAO,EACP,IAAI,EACJ,GAAG,KAAK,EACG;IACX,MAAM,EAAE,KAAK,EAAE,GAAG,QAAQ,EAAE,CAAC;IAC7B,MAAM,EAAE,UAAU,EAAE,GAAG,oBAAoB,EAAE,CAAC;IAC9C,MAAM,eAAe,GAAG,iBAAiB,CAAC,SAAS,EAAE,UAAU,CAAC,IAAI,QAAQ,CAAC;IAC7E,MAAM,SAAS,GAAG,cAAc,CAAC,KAAK,EAAE,iBAAiB,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC,IAAI,CAAC,CAAC;IACjF,MAAM,WAAW,GAAG,iBAAiB,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;IACzD,MAAM,aAAa,GAAG,iBAAiB,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;IAC7D,MAAM,UAAU,GAAG,iBAAiB,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;IAEvD,OAAO,CACL,CAAC,GAAG,CACF,IAAI,KAAK,CAAC,CACV,KAAK,CAAC,CAAC;YACL;gBACE,aAAa,EAAE,eAAe;gBAC9B,GAAG,EAAE,SAAS;gBACd,UAAU,EAAE,WAAW;gBACvB,cAAc,EAAE,aAAa;gBAC7B,QAAQ,EAAE,UAAU;aACrB;YACD,KAAK,CAAC,KAAK;SACZ,CAAC,CAEF;MAAA,CAAC,QAAQ,CACX;IAAA,EAAE,GAAG,CAAC,CACP,CAAC;AACJ,CAAC","sourcesContent":["import type React from 'react';\n\nimport { resolveResponsive, type Responsive, useResponsiveRuntime } from '../core/responsive';\nimport { useTheme } from '../theme/ThemeContext';\nimport { Box, type BoxProps } from './Box';\nimport { resolveSpacing, type SpaceValue } from './helpers';\n\nexport interface StackProps extends Omit<BoxProps, 'children'> {\n children?: React.ReactNode;\n direction?: Responsive<'row' | 'column'>;\n gap?: Responsive<SpaceValue>;\n align?: Responsive<'flex-start' | 'center' | 'flex-end' | 'stretch' | 'baseline'>;\n justify?: Responsive<\n 'flex-start' | 'center' | 'flex-end' | 'space-between' | 'space-around' | 'space-evenly'\n >;\n wrap?: Responsive<'nowrap' | 'wrap'>;\n}\n\nexport function Stack({\n children,\n direction = 'column',\n gap = 0,\n align,\n justify,\n wrap,\n ...props\n}: StackProps) {\n const { theme } = useTheme();\n const { breakpoint } = useResponsiveRuntime();\n const activeDirection = resolveResponsive(direction, breakpoint) ?? 'column';\n const activeGap = resolveSpacing(theme, resolveResponsive(gap, breakpoint)) ?? 0;\n const activeAlign = resolveResponsive(align, breakpoint);\n const activeJustify = resolveResponsive(justify, breakpoint);\n const activeWrap = resolveResponsive(wrap, breakpoint);\n\n return (\n <Box\n {...props}\n style={[\n {\n flexDirection: activeDirection,\n gap: activeGap,\n alignItems: activeAlign,\n justifyContent: activeJustify,\n flexWrap: activeWrap,\n },\n props.style,\n ]}\n >\n {children}\n </Box>\n );\n}\n"]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@ankhorage/surface",
3
3
  "type": "module",
4
- "version": "2.2.0",
4
+ "version": "2.2.1",
5
5
  "description": "Stable UI foundation for React Native and React Native Web.",
6
6
  "homepage": "https://github.com/ankhorage/surface#readme",
7
7
  "bugs": {
@@ -0,0 +1,14 @@
1
+ import { readFile } from 'node:fs/promises';
2
+
3
+ import { describe, expect, it } from 'bun:test';
4
+
5
+ describe('Stack layout contract', () => {
6
+ it('keeps authored children as direct flex items and applies spacing through gap', async () => {
7
+ const source = await readFile(new URL('./Stack.tsx', import.meta.url), 'utf8');
8
+
9
+ expect(source).toContain('gap: activeGap');
10
+ expect(source).toContain('{children}');
11
+ expect(source).not.toContain("from 'react-native'");
12
+ expect(source).not.toContain('React.Children');
13
+ });
14
+ });
@@ -1,5 +1,4 @@
1
- import React from 'react';
2
- import { View } from 'react-native';
1
+ import type React from 'react';
3
2
 
4
3
  import { resolveResponsive, type Responsive, useResponsiveRuntime } from '../core/responsive';
5
4
  import { useTheme } from '../theme/ThemeContext';
@@ -34,14 +33,13 @@ export function Stack({
34
33
  const activeJustify = resolveResponsive(justify, breakpoint);
35
34
  const activeWrap = resolveResponsive(wrap, breakpoint);
36
35
 
37
- const nodes = React.Children.toArray(children);
38
-
39
36
  return (
40
37
  <Box
41
38
  {...props}
42
39
  style={[
43
40
  {
44
41
  flexDirection: activeDirection,
42
+ gap: activeGap,
45
43
  alignItems: activeAlign,
46
44
  justifyContent: activeJustify,
47
45
  flexWrap: activeWrap,
@@ -49,19 +47,7 @@ export function Stack({
49
47
  props.style,
50
48
  ]}
51
49
  >
52
- {nodes.map((node, index) => {
53
- const spacing =
54
- index === 0
55
- ? undefined
56
- : activeDirection === 'row'
57
- ? { marginLeft: activeGap }
58
- : { marginTop: activeGap };
59
- return (
60
- <View key={String(index)} style={spacing}>
61
- {node}
62
- </View>
63
- );
64
- })}
50
+ {children}
65
51
  </Box>
66
52
  );
67
53
  }