Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/direct-stack-children.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@ankhorage/surface': patch
---

Preserve Stack child flex and min-size semantics by applying spacing with the container gap property instead of wrapper views.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

# @ankhorage/surface

![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)
![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)

Cross-platform UI foundation for React Native and React Native Web. Provides theming, layout primitives, and core building blocks for modern apps.

Expand Down
6 changes: 3 additions & 3 deletions paradox/badges/npm.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion paradox/components.md
Original file line number Diff line number Diff line change
Expand Up @@ -1289,7 +1289,7 @@ Export paths: `src/index.ts`

## Stack

Source: `src/layout/Stack.tsx:20:1`
Source: `src/layout/Stack.tsx:19:1`

Export paths: `src/index.ts`

Expand Down
4 changes: 2 additions & 2 deletions paradox/exports.json
Original file line number Diff line number Diff line change
Expand Up @@ -9373,7 +9373,7 @@
"modulePath": "src/layout/Stack.tsx",
"sourceLocation": {
"filePath": "src/layout/Stack.tsx",
"line": 20,
"line": 19,
"column": 1
},
"exportPaths": ["src/index.ts"],
Expand Down Expand Up @@ -9405,7 +9405,7 @@
"modulePath": "src/layout/Stack.tsx",
"sourceLocation": {
"filePath": "src/layout/Stack.tsx",
"line": 9,
"line": 8,
"column": 1
},
"exportPaths": ["src/index.ts"],
Expand Down
4 changes: 2 additions & 2 deletions paradox/exports.md
Original file line number Diff line number Diff line change
Expand Up @@ -2651,7 +2651,7 @@ Source: `src/layout/Spacer.tsx:6:1`

Kind: `function`
Module: `src/layout/Stack.tsx`
Source: `src/layout/Stack.tsx:20:1`
Source: `src/layout/Stack.tsx:19:1`

### Signatures

Expand Down Expand Up @@ -2679,7 +2679,7 @@ Source: `src/layout/Stack.tsx:20:1`

Kind: `type`
Module: `src/layout/Stack.tsx`
Source: `src/layout/Stack.tsx:9:1`
Source: `src/layout/Stack.tsx:8:1`

### Members

Expand Down
8 changes: 4 additions & 4 deletions paradox/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -17266,7 +17266,7 @@ <h3>src/layout/Stack.tsx</h3>
data-search="Stack function src/layout/Stack.tsx StackProps ({&#10; children,&#10; direction = &#39;column&#39;,&#10; gap = 0,&#10; align,&#10; justify,&#10; wrap,&#10; ...props&#10;}: StackProps) =&gt; React.JSX.Element"
>
<h4>Stack</h4>
<p class="muted">function • <code>src/layout/Stack.tsx:20:1</code></p>
<p class="muted">function • <code>src/layout/Stack.tsx:19:1</code></p>

<p><strong>Export paths:</strong> <code>src/index.ts</code></p>
<div>
Expand Down Expand Up @@ -17320,7 +17320,7 @@ <h5>Signature</h5>
data-search="StackProps type src/layout/Stack.tsx Responsive"
>
<h4>StackProps</h4>
<p class="muted">type • <code>src/layout/Stack.tsx:9:1</code></p>
<p class="muted">type • <code>src/layout/Stack.tsx:8:1</code></p>

<p><strong>Export paths:</strong> <code>src/index.ts</code></p>
<div>
Expand Down Expand Up @@ -27869,7 +27869,7 @@ <h3>Spacer</h3>
data-search="Stack src/layout/Stack.tsx accessibilityLabel ReactNativeViewProps[&#39;accessibilityLabel&#39;] | undefined accessibilityRole ReactNativeViewProps[&#39;accessibilityRole&#39;] | undefined accessibilityState ReactNativeViewProps[&#39;accessibilityState&#39;] | undefined accessible ReactNativeViewProps[&#39;accessible&#39;] | undefined align Responsive&lt;&#39;flex-start&#39; | &#39;center&#39; | &#39;flex-end&#39; | &#39;stretch&#39; | &#39;baseline&#39;&gt; | undefined alignSelf Responsive&lt;ViewStyle[&#39;alignSelf&#39;]&gt; | undefined bg Responsive&lt;ColorValue&gt; | undefined borderColor Responsive&lt;ColorValue&gt; | undefined borderWidth Responsive&lt;number&gt; | undefined bottom Responsive&lt;number&gt; | undefined children React.ReactNode | undefined direction Responsive&lt;&#39;row&#39; | &#39;column&#39;&gt; | undefined flex Responsive&lt;number&gt; | undefined flexBasis Responsive&lt;number | string&gt; | undefined flexGrow Responsive&lt;number&gt; | undefined flexShrink Responsive&lt;number&gt; | undefined gap Responsive&lt;SpaceValue&gt; | undefined height Responsive&lt;number | string&gt; | undefined justify Responsive&lt;&#10; &#39;flex-start&#39; | &#39;center&#39; | &#39;flex-end&#39; | &#39;space-between&#39; | &#39;space-around&#39; | &#39;space-evenly&#39;&#10; &gt; | undefined left Responsive&lt;number&gt; | undefined m Responsive&lt;SpaceValue&gt; | undefined maxHeight Responsive&lt;number | string&gt; | undefined maxWidth Responsive&lt;number | string&gt; | undefined mb Responsive&lt;SpaceValue&gt; | undefined minHeight Responsive&lt;number | string&gt; | undefined minWidth Responsive&lt;number | string&gt; | undefined ml Responsive&lt;SpaceValue&gt; | undefined mr Responsive&lt;SpaceValue&gt; | undefined mt Responsive&lt;SpaceValue&gt; | undefined mx Responsive&lt;SpaceValue&gt; | undefined my Responsive&lt;SpaceValue&gt; | undefined opacity Responsive&lt;number&gt; | undefined overflow Responsive&lt;ViewStyle[&#39;overflow&#39;]&gt; | undefined p Responsive&lt;SpaceValue&gt; | undefined pb Responsive&lt;SpaceValue&gt; | undefined pl Responsive&lt;SpaceValue&gt; | undefined pointerEvents ReactNativeViewProps[&#39;pointerEvents&#39;] | undefined position Responsive&lt;ViewStyle[&#39;position&#39;]&gt; | undefined pr Responsive&lt;SpaceValue&gt; | undefined pt Responsive&lt;SpaceValue&gt; | undefined px Responsive&lt;SpaceValue&gt; | undefined py Responsive&lt;SpaceValue&gt; | undefined radius Responsive&lt;RadiusValue&gt; | undefined right Responsive&lt;number&gt; | undefined style StyleProp&lt;ViewStyle&gt; | undefined testID string | undefined top Responsive&lt;number&gt; | undefined width Responsive&lt;number | string&gt; | undefined wrap Responsive&lt;&#39;nowrap&#39; | &#39;wrap&#39;&gt; | undefined zIndex Responsive&lt;number&gt; | undefined"
>
<h3>Stack</h3>
<p class="muted"><code>src/layout/Stack.tsx:20:1</code></p>
<p class="muted"><code>src/layout/Stack.tsx:19:1</code></p>

<p><strong>Export paths:</strong> <code>src/index.ts</code></p>
<table>
Expand Down Expand Up @@ -38919,7 +38919,7 @@ <h3>Spacer</h3>
<h2>src/layout/Stack.tsx</h2>
<article class="item" data-search="Stack src/layout/Stack.tsx ">
<h3>Stack</h3>
<p class="muted"><code>src/layout/Stack.tsx:20:1</code></p>
<p class="muted"><code>src/layout/Stack.tsx:19:1</code></p>
<p class="empty">No description available.</p>
</article>
</section>
Expand Down
18 changes: 6 additions & 12 deletions paradox/paradox.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
{
"id": "npm",
"label": "npm",
"value": "v2.1.1",
"value": "v2.2.0",
"color": "cb3837"
},
{
Expand Down Expand Up @@ -11106,7 +11106,7 @@
"modulePath": "src/layout/Stack.tsx",
"sourceLocation": {
"filePath": "src/layout/Stack.tsx",
"line": 20,
"line": 19,
"column": 1
},
"exportPaths": ["src/index.ts"],
Expand Down Expand Up @@ -11138,7 +11138,7 @@
"modulePath": "src/layout/Stack.tsx",
"sourceLocation": {
"filePath": "src/layout/Stack.tsx",
"line": 9,
"line": 8,
"column": 1
},
"exportPaths": ["src/index.ts"],
Expand Down Expand Up @@ -23116,7 +23116,7 @@
"modulePath": "src/layout/Stack.tsx",
"sourceLocation": {
"filePath": "src/layout/Stack.tsx",
"line": 20,
"line": 19,
"column": 1
},
"exportPaths": ["src/index.ts"],
Expand Down Expand Up @@ -27877,7 +27877,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/layout/Stack.tsx",
"line": 20,
"line": 19,
"column": 1
}
},
Expand Down Expand Up @@ -36383,13 +36383,7 @@
{
"fromComponent": "Stack",
"toComponent": "Box",
"jsxElement": "<Box\n {...props}\n style={[\n {\n flexDirection: activeDirection,\n alignItems: activeAlign,\n justifyContent: activeJustify,\n flexWrap: activeWrap,\n },\n props.style,\n ]}\n >",
"sourcePath": "src/layout/Stack.tsx"
},
{
"fromComponent": "Stack",
"toComponent": "View",
"jsxElement": "<View key={String(index)} style={spacing}>",
"jsxElement": "<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 >",
"sourcePath": "src/layout/Stack.tsx"
},
{
Expand Down
14 changes: 14 additions & 0 deletions src/layout/Stack.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { readFile } from 'node:fs/promises';

import { describe, expect, it } from 'bun:test';

describe('Stack layout contract', () => {
it('keeps authored children as direct flex items and applies spacing through gap', async () => {
const source = await readFile(new URL('./Stack.tsx', import.meta.url), 'utf8');

expect(source).toContain('gap: activeGap');
expect(source).toContain('{children}');
expect(source).not.toContain("from 'react-native'");
expect(source).not.toContain('React.Children');
});
});
20 changes: 3 additions & 17 deletions src/layout/Stack.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import React from 'react';
import { View } from 'react-native';
import type React from 'react';

import { resolveResponsive, type Responsive, useResponsiveRuntime } from '../core/responsive';
import { useTheme } from '../theme/ThemeContext';
Expand Down Expand Up @@ -34,34 +33,21 @@ export function Stack({
const activeJustify = resolveResponsive(justify, breakpoint);
const activeWrap = resolveResponsive(wrap, breakpoint);

const nodes = React.Children.toArray(children);

return (
<Box
{...props}
style={[
{
flexDirection: activeDirection,
gap: activeGap,
alignItems: activeAlign,
justifyContent: activeJustify,
flexWrap: activeWrap,
},
props.style,
]}
>
{nodes.map((node, index) => {
const spacing =
index === 0
? undefined
: activeDirection === 'row'
? { marginLeft: activeGap }
: { marginTop: activeGap };
return (
<View key={String(index)} style={spacing}>
{node}
</View>
);
})}
{children}
</Box>
);
}
Loading