@hanzogui/web 8.3.5 → 8.4.0

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.
Files changed (64) hide show
  1. package/LICENSE +26 -0
  2. package/NOTICE +60 -0
  3. package/dist/cjs/createComponent.js +26 -5
  4. package/dist/cjs/createComponent.js.map +1 -1
  5. package/dist/cjs/helpers/createDesignSystem.js +1 -0
  6. package/dist/cjs/helpers/createDesignSystem.js.map +1 -1
  7. package/dist/cjs/helpers/expandStyle.js +54 -2
  8. package/dist/cjs/helpers/expandStyle.js.map +1 -1
  9. package/dist/cjs/helpers/getSplitStyles.js +14 -0
  10. package/dist/cjs/helpers/getSplitStyles.js.map +1 -1
  11. package/dist/cjs/helpers/propMapper.js +7 -0
  12. package/dist/cjs/helpers/propMapper.js.map +1 -1
  13. package/dist/cjs/helpers/skipProps.js +1 -0
  14. package/dist/cjs/helpers/skipProps.js.map +1 -1
  15. package/dist/cjs/helpers/tracks.js +209 -0
  16. package/dist/cjs/helpers/tracks.js.map +1 -0
  17. package/dist/esm/createComponent.js +26 -5
  18. package/dist/esm/createComponent.js.map +1 -1
  19. package/dist/esm/helpers/createDesignSystem.js +1 -0
  20. package/dist/esm/helpers/createDesignSystem.js.map +1 -1
  21. package/dist/esm/helpers/expandStyle.js +54 -2
  22. package/dist/esm/helpers/expandStyle.js.map +1 -1
  23. package/dist/esm/helpers/getSplitStyles.js +14 -0
  24. package/dist/esm/helpers/getSplitStyles.js.map +1 -1
  25. package/dist/esm/helpers/propMapper.js +7 -0
  26. package/dist/esm/helpers/propMapper.js.map +1 -1
  27. package/dist/esm/helpers/skipProps.js +1 -0
  28. package/dist/esm/helpers/skipProps.js.map +1 -1
  29. package/dist/esm/helpers/tracks.js +200 -0
  30. package/dist/esm/helpers/tracks.js.map +1 -0
  31. package/dist/native/createComponent.js +26 -5
  32. package/dist/native/createComponent.js.map +1 -1
  33. package/dist/native/helpers/createDesignSystem.js +1 -0
  34. package/dist/native/helpers/createDesignSystem.js.map +1 -1
  35. package/dist/native/helpers/expandStyle.js +54 -2
  36. package/dist/native/helpers/expandStyle.js.map +1 -1
  37. package/dist/native/helpers/getSplitStyles.js +14 -0
  38. package/dist/native/helpers/getSplitStyles.js.map +1 -1
  39. package/dist/native/helpers/propMapper.js +7 -0
  40. package/dist/native/helpers/propMapper.js.map +1 -1
  41. package/dist/native/helpers/skipProps.js +1 -0
  42. package/dist/native/helpers/skipProps.js.map +1 -1
  43. package/dist/native/helpers/tracks.js +200 -0
  44. package/dist/native/helpers/tracks.js.map +1 -0
  45. package/package.json +15 -16
  46. package/src/createComponent.tsx +36 -4
  47. package/src/helpers/createDesignSystem.ts +1 -0
  48. package/src/helpers/expandStyle.ts +57 -2
  49. package/src/helpers/getSplitStyles.tsx +16 -0
  50. package/src/helpers/propMapper.ts +8 -0
  51. package/src/helpers/skipProps.ts +1 -0
  52. package/src/helpers/tracks.ts +206 -0
  53. package/src/types.tsx +27 -1
  54. package/types/createComponent.d.ts.map +1 -1
  55. package/types/helpers/createDesignSystem.d.ts.map +1 -1
  56. package/types/helpers/expandStyle.d.ts.map +1 -1
  57. package/types/helpers/getSplitStyles.d.ts.map +1 -1
  58. package/types/helpers/propMapper.d.ts.map +1 -1
  59. package/types/helpers/skipProps.d.ts +1 -0
  60. package/types/helpers/skipProps.d.ts.map +1 -1
  61. package/types/helpers/tracks.d.ts +87 -0
  62. package/types/helpers/tracks.d.ts.map +1 -0
  63. package/types/types.d.ts +25 -1
  64. package/types/types.d.ts.map +1 -1
@@ -34,6 +34,7 @@ import {
34
34
  import { setElementProps } from './helpers/setElementProps.tsx'
35
35
  import { subscribeToContextGroup } from './helpers/subscribeToContextGroup.tsx'
36
36
  import { themeable } from './helpers/themeable.tsx'
37
+ import { axisOf, place } from './helpers/tracks.ts'
37
38
  import { getStyleTags } from './helpers/wrapStyleTags.tsx'
38
39
  import { useComponentState } from './hooks/useComponentState.ts'
39
40
  import { setMediaShouldUpdate, useMedia } from './hooks/useMedia.tsx'
@@ -1042,7 +1043,7 @@ export function createComponent<
1042
1043
 
1043
1044
  const {
1044
1045
  asChild,
1045
- children,
1046
+ children: childrenIn,
1046
1047
  themeShallow,
1047
1048
  spaceDirection: _spaceDirection,
1048
1049
  onPress,
@@ -1068,6 +1069,25 @@ export function createComponent<
1068
1069
  ...nonGuiProps
1069
1070
  } = viewPropsIn || {}
1070
1071
 
1072
+ // a tracks stack (helpers/tracks.ts): on native the stack stays flex and
1073
+ // each child takes its track as a flex style; on web its children learn
1074
+ // its axis through ComponentContext, and a direct child clears it for its own
1075
+ const tracksIn = (props as { tracks?: unknown }).tracks
1076
+ const tracks =
1077
+ !isHOC && !isText && !asChild && typeof tracksIn === 'string' ? tracksIn : null
1078
+ const children =
1079
+ process.env.GUI_TARGET === 'native' && tracks
1080
+ ? place(childrenIn, tracks)
1081
+ : childrenIn
1082
+ const childTracks = tracks ? axisOf(props) : null
1083
+ const tracksScope =
1084
+ process.env.GUI_TARGET === 'web' &&
1085
+ !isHOC &&
1086
+ !asChild &&
1087
+ childTracks !== (componentContext.tracks ?? null)
1088
+ ? { tracks: childTracks }
1089
+ : null
1090
+
1071
1091
  // these can ultimately be for DOM, react-native-web views, or animated views
1072
1092
  // so the type is pretty loose
1073
1093
  let viewProps = nonGuiProps
@@ -1696,11 +1716,13 @@ export function createComponent<
1696
1716
 
1697
1717
  if (process.env.NODE_ENV === 'development' && time) time`create-element`
1698
1718
 
1699
- if ('focusWithinStyle' in propsIn || pseudos?.focusWithinStyle) {
1719
+ const focusWithin = 'focusWithinStyle' in propsIn || !!pseudos?.focusWithinStyle
1720
+ if (focusWithin) {
1700
1721
  content = (
1701
1722
  <ComponentContext.Provider
1702
1723
  {...componentContext}
1703
1724
  setParentFocusState={setStateShallow}
1725
+ {...tracksScope}
1704
1726
  >
1705
1727
  {content}
1706
1728
  </ComponentContext.Provider>
@@ -1714,9 +1736,19 @@ export function createComponent<
1714
1736
  }
1715
1737
 
1716
1738
  // Text components set inText context for children so nested Text can inherit styles
1717
- if (process.env.GUI_TARGET === 'web' && !asChild && isText && !hasTextAncestor) {
1739
+ const textScope =
1740
+ process.env.GUI_TARGET === 'web' && !asChild && isText && !hasTextAncestor
1741
+ if (textScope) {
1742
+ content = (
1743
+ <ComponentContext.Provider {...componentContext} inText={true} {...tracksScope}>
1744
+ {content}
1745
+ </ComponentContext.Provider>
1746
+ )
1747
+ }
1748
+
1749
+ if (tracksScope && !focusWithin && !textScope) {
1718
1750
  content = (
1719
- <ComponentContext.Provider {...componentContext} inText={true}>
1751
+ <ComponentContext.Provider {...componentContext} {...tracksScope}>
1720
1752
  {content}
1721
1753
  </ComponentContext.Provider>
1722
1754
  )
@@ -252,6 +252,7 @@ export function getCSS(
252
252
  .is_Text { display: inline; box-sizing: border-box; word-wrap: break-word; white-space: pre-wrap; margin: 0; }
253
253
  @scope (.is_Text) to (.is_View) { .is_Text { white-space: inherit; word-wrap: inherit; } }
254
254
  ._dsp_contents {display:contents;}
255
+ [data-i18n-mirror]:dir(rtl) {transform:scaleX(-1);}
255
256
  ._no_backdrop::backdrop {display: none;}
256
257
  .is_Input::selection, .is_TextArea::selection {background-color: var(--t_selectionColor);}
257
258
  .is_Input::placeholder, .is_TextArea::placeholder {color: var(--t_placeholderColor);}
@@ -78,6 +78,19 @@ export function expandStyle(
78
78
  return expandFlex(value, styleCompat)
79
79
  }
80
80
 
81
+ // react-native's direction-relative names are not CSS: `paddingStart`
82
+ // hyphenates to `padding-start`, which no browser parses, so the rule was
83
+ // dropped and the element laid out as if the prop were absent. They land on
84
+ // the CSS logical property that follows the writing direction.
85
+ if (key in webInlineNames) {
86
+ return [[webInlineNames[key], value]]
87
+ }
88
+ // two-sided inline shorthands split into the longhands above, so a later
89
+ // `paddingInlineEnd` replaces one side instead of racing the shorthand
90
+ if (key in webInlineExpansions) {
91
+ return webInlineExpansions[key].map((k) => [k, value])
92
+ }
93
+
81
94
  switch (key) {
82
95
  case 'writingDirection': {
83
96
  return [['direction', value]]
@@ -166,6 +179,18 @@ export function expandStyle(
166
179
  }
167
180
  return
168
181
  }
182
+ case 'textAlign': {
183
+ // react-native has no start/end alignment; its left/right already
184
+ // swap under RTL (I18nManager.doLeftAndRightSwapInRTL), so they are
185
+ // the direction-relative values there
186
+ if (value === 'start') {
187
+ return [['textAlign', 'left']]
188
+ }
189
+ if (value === 'end') {
190
+ return [['textAlign', 'right']]
191
+ }
192
+ return
193
+ }
169
194
  }
170
195
 
171
196
  // native-only logical expansions (RTL-aware inline props output RN-style
@@ -295,6 +320,36 @@ const nativeInlineExpansions: Record<string, string[]> = {
295
320
  paddingInline: ['paddingEnd', 'paddingStart'],
296
321
  paddingInlineStart: ['paddingStart'],
297
322
  paddingInlineEnd: ['paddingEnd'],
298
- insetInlineStart: ['left'],
299
- insetInlineEnd: ['right'],
323
+ // start/end follow the layout direction on native; left/right do not
324
+ insetInline: ['start', 'end'],
325
+ insetInlineStart: ['start'],
326
+ insetInlineEnd: ['end'],
327
+ }
328
+
329
+ // react-native's direction-relative names -> the CSS logical property each one
330
+ // means. Radii read block-then-inline: top-start is start-start.
331
+ const webInlineNames: Record<string, string> = {
332
+ start: 'insetInlineStart',
333
+ end: 'insetInlineEnd',
334
+ marginStart: 'marginInlineStart',
335
+ marginEnd: 'marginInlineEnd',
336
+ paddingStart: 'paddingInlineStart',
337
+ paddingEnd: 'paddingInlineEnd',
338
+ borderStartColor: 'borderInlineStartColor',
339
+ borderEndColor: 'borderInlineEndColor',
340
+ borderStartWidth: 'borderInlineStartWidth',
341
+ borderEndWidth: 'borderInlineEndWidth',
342
+ borderTopStartRadius: 'borderStartStartRadius',
343
+ borderTopEndRadius: 'borderStartEndRadius',
344
+ borderBottomStartRadius: 'borderEndStartRadius',
345
+ borderBottomEndRadius: 'borderEndEndRadius',
346
+ }
347
+
348
+ const webInlineExpansions: Record<string, string[]> = {
349
+ insetInline: ['insetInlineStart', 'insetInlineEnd'],
350
+ marginInline: ['marginInlineStart', 'marginInlineEnd'],
351
+ paddingInline: ['paddingInlineStart', 'paddingInlineEnd'],
352
+ borderInlineColor: ['borderInlineStartColor', 'borderInlineEndColor'],
353
+ borderInlineWidth: ['borderInlineStartWidth', 'borderInlineEndWidth'],
354
+ borderInlineStyle: ['borderInlineStartStyle', 'borderInlineEndStyle'],
300
355
  }
@@ -80,6 +80,7 @@ import { sortString } from './sortString.ts'
80
80
  import { styleOriginalValues } from './styleOriginalValues.ts'
81
81
  import { type StyleTokenProvenance, setStyleTokenProvenance } from './styleProvenance.ts'
82
82
  import { transformsToString } from './transformsToString.ts'
83
+ import { axisOf, gridOf, renamesOf } from './tracks.ts'
83
84
 
84
85
  export { styleOriginalValues }
85
86
  export { getStyleTokenProvenance, STYLE_TOKEN_PROVENANCE_KEY } from './styleProvenance.ts'
@@ -274,6 +275,15 @@ export const getSplitStyles: StyleSplitter = (
274
275
  animationDriver: driver,
275
276
  }
276
277
 
278
+ // a stack that lays its children on grid tracks (helpers/tracks.ts). an HOC
279
+ // passes the prop to the component it wraps, which does the work.
280
+ const tracks =
281
+ !isHOC && !isText && typeof props.tracks === 'string' ? props.tracks : null
282
+ const tracksAxis = tracks ? axisOf(props) : null
283
+ if (process.env.GUI_TARGET === 'web' && !isHOC) {
284
+ styleState.renames = renamesOf(tracksAxis, componentContext?.tracks)
285
+ }
286
+
277
287
  // only used by compiler
278
288
  if (process.env.IS_STATIC === 'is_static') {
279
289
  const { fallbackProps } = styleProps
@@ -1217,6 +1227,12 @@ export const getSplitStyles: StyleSplitter = (
1217
1227
  time`split-styles-propsend`
1218
1228
  }
1219
1229
 
1230
+ // the grid a tracks stack is, under any of these the author named themselves
1231
+ if (process.env.GUI_TARGET === 'web' && tracks) {
1232
+ const grid = gridOf(tracks, tracksAxis!)
1233
+ for (const key in grid) mergeStyle(styleState, key, grid[key], 0)
1234
+ }
1235
+
1220
1236
  // style prop after:
1221
1237
 
1222
1238
  const avoidNormalize = styleProps.noNormalize === false
@@ -29,6 +29,14 @@ import { styleOriginalValues } from './styleOriginalValues.ts'
29
29
  export { getTokenForKey } from './getTokenForKey.ts'
30
30
 
31
31
  export const propMapper: PropMapper = (key, value, styleState, disabled, map) => {
32
+ // a vertical tracks stack and its direct children read alignment across
33
+ // (helpers/tracks.ts); every key this call emits passes through the rename
34
+ const { renames } = styleState
35
+ if (renames) {
36
+ const emit = map
37
+ map = (k, v, o) => emit(renames[k] || k, v, o)
38
+ }
39
+
32
40
  if (disabled) {
33
41
  return map(key, value)
34
42
  }
@@ -17,6 +17,7 @@ export const skipProps = {
17
17
  render: 1,
18
18
  style: 1, // handled after loop so pseudos set usedKeys and override it if necessary
19
19
  group: 1,
20
+ tracks: 1, // read by getSplitStyles and createComponent (helpers/tracks.ts)
20
21
  animatePresence: 1,
21
22
  }
22
23
 
@@ -0,0 +1,206 @@
1
+ /**
2
+ * `tracks`: a stack that lays its children on CSS grid tracks along its own
3
+ * axis, so the parent sizes them and the children carry no flex props.
4
+ *
5
+ * <YStack tracks="auto 1fr auto"> header, body that fills, footer
6
+ * <XStack tracks="240px 1fr"> a fixed rail and the page beside it
7
+ *
8
+ * The axis is the stack's own flexDirection: `row` and `row-reverse` run across
9
+ * (x), everything else runs down (y). A reverse direction is not mirrored —
10
+ * grid has no reverse flow — so the children sit on the tracks in source order.
11
+ *
12
+ * WEB is the browser's grid:
13
+ *
14
+ * y (YStack) x (XStack)
15
+ * display grid grid
16
+ * flow grid-auto-flow: row grid-auto-flow: column
17
+ * tracks grid-template-rows grid-template-columns
18
+ * cross axis grid-auto-columns: grid-auto-rows:
19
+ * minmax(0, 1fr) minmax(0, 1fr)
20
+ *
21
+ * The cross-axis track is one that fills the stack and has no content floor,
22
+ * which is what a flex line's cross size is: a child stretched across a column
23
+ * is exactly as wide as the column, however wide its content.
24
+ *
25
+ * A prop the author names on the stack wins over all of these, so
26
+ * `display="none"` still hides it and an explicit `gridAutoFlow` stays.
27
+ *
28
+ * ALIGNMENT KEEPS ITS FLEX MEANING. On x, grid's block axis is the row's cross
29
+ * axis and its inline axis the main axis, so `items`, `justify` and `self` mean
30
+ * what they meant and pass through. On y the two axes swap, so they are
31
+ * renamed:
32
+ *
33
+ * on the stack items (alignItems) -> justifyItems
34
+ * justify (justifyContent) -> alignContent
35
+ * content (alignContent) -> justifyContent
36
+ * on a child self (alignSelf) -> justifySelf
37
+ *
38
+ * The rename happens where every style key is mapped (propMapper), so it holds
39
+ * for a key written in a media query, a pseudo style or a variant as well as a
40
+ * plain prop. A child learns that it sits in a vertical stack from
41
+ * ComponentContext; the context reaches only the stack's direct children, and
42
+ * each of them clears it for its own.
43
+ *
44
+ * NATIVE falls back to flex: the stack stays the flex column or row it is, and
45
+ * each child takes the track at its position as its flex style. Every child
46
+ * gets one, written as longhands, so a flex prop the child set on itself does
47
+ * not combine with it: the track wins, as it does on web.
48
+ *
49
+ * Nfr, minmax(_, Nfr) flexGrow N, flexShrink 1, flexBasis 0 (flex: N)
50
+ * Npx, N%, 0 flexGrow 0, flexShrink 0, flexBasis N (px as a number)
51
+ * repeat(K, list) the list written out K times
52
+ * anything else, and every flexGrow 0, flexShrink 0, flexBasis auto
53
+ * child past the list (content-sized, as an auto track is)
54
+ *
55
+ * `repeat(auto-fill, …)` and `repeat(auto-fit, …)` need the stack's measured
56
+ * size, so the list ends there and the children from that position on are
57
+ * content-sized.
58
+ *
59
+ * Positions count each child that renders, through fragments, and skip a child
60
+ * whose `position` prop is absolute or fixed, as grid does. A gui child takes
61
+ * the style as props; any other element as a `style` entry after its own, which
62
+ * a custom component has to pass to its root. Alignment is not renamed on
63
+ * native: the stack is still flex there.
64
+ */
65
+ import React from 'react'
66
+
67
+ import { isGuiComponent } from './isGuiComponent.tsx'
68
+
69
+ export type Axis = 'x' | 'y'
70
+
71
+ /** The axis a stack lays its tracks on, from its own flexDirection. */
72
+ export const axisOf = (props: Record<string, any>): Axis =>
73
+ props.flexDirection === 'row' || props.flexDirection === 'row-reverse' ? 'x' : 'y'
74
+
75
+ /** Grid styles for a tracks stack on web. */
76
+ export const gridOf = (tracks: string, axis: Axis): Record<string, string> =>
77
+ axis === 'x'
78
+ ? {
79
+ display: 'grid',
80
+ gridAutoFlow: 'column',
81
+ gridTemplateColumns: tracks,
82
+ gridAutoRows: 'minmax(0, 1fr)',
83
+ }
84
+ : {
85
+ display: 'grid',
86
+ gridAutoFlow: 'row',
87
+ gridTemplateRows: tracks,
88
+ gridAutoColumns: 'minmax(0, 1fr)',
89
+ }
90
+
91
+ const STACK: Record<string, string> = {
92
+ alignItems: 'justifyItems',
93
+ justifyContent: 'alignContent',
94
+ alignContent: 'justifyContent',
95
+ }
96
+ const ITEM: Record<string, string> = { alignSelf: 'justifySelf' }
97
+ const BOTH: Record<string, string> = { ...STACK, ...ITEM }
98
+
99
+ /**
100
+ * The renames for one component on web: as a vertical tracks stack, as a
101
+ * direct child of one, or both. Undefined when neither, which is every
102
+ * component that does not opt in.
103
+ */
104
+ export function renamesOf(
105
+ own: Axis | null,
106
+ parent: Axis | null | undefined
107
+ ): Record<string, string> | undefined {
108
+ if (own === 'y') return parent === 'y' ? BOTH : STACK
109
+ return parent === 'y' ? ITEM : undefined
110
+ }
111
+
112
+ type Flex = { flexGrow: number; flexShrink: number; flexBasis: number | string }
113
+
114
+ const CONTENT: Flex = { flexGrow: 0, flexShrink: 0, flexBasis: 'auto' }
115
+
116
+ const FR = /^(\d*\.?\d+)fr$/
117
+ const PX = /^(\d*\.?\d+)px$/
118
+ const PERCENT = /^\d*\.?\d+%$/
119
+
120
+ /** One track as a child's flex style. */
121
+ function flexOf(track: string): Flex {
122
+ const fr = FR.exec(track)
123
+ if (fr) return { flexGrow: Number(fr[1]), flexShrink: 1, flexBasis: 0 }
124
+ const px = PX.exec(track)
125
+ if (px) return { flexGrow: 0, flexShrink: 0, flexBasis: Number(px[1]) }
126
+ if (track === '0') return { flexGrow: 0, flexShrink: 0, flexBasis: 0 }
127
+ if (PERCENT.test(track)) return { flexGrow: 0, flexShrink: 0, flexBasis: track }
128
+ if (track.startsWith('minmax(')) {
129
+ const max = split(track.slice(7, -1), ',')[1]
130
+ if (max && FR.test(max)) return flexOf(max)
131
+ }
132
+ return CONTENT
133
+ }
134
+
135
+ /** Split at the top level only, so `minmax(0, 1fr)` stays one piece. */
136
+ function split(list: string, at: ' ' | ','): string[] {
137
+ const out: string[] = []
138
+ let depth = 0
139
+ let part = ''
140
+ for (const c of list) {
141
+ if (c === '(') depth++
142
+ if (c === ')') depth--
143
+ if (depth === 0 && (at === ' ' ? /\s/.test(c) : c === ',')) {
144
+ if (part.trim()) out.push(part.trim())
145
+ part = ''
146
+ } else {
147
+ part += c
148
+ }
149
+ }
150
+ if (part.trim()) out.push(part.trim())
151
+ return out
152
+ }
153
+
154
+ const REPEAT = /^repeat\(\s*(\d+)\s*,([\s\S]*)\)$/
155
+
156
+ const cache = new Map<string, Flex[]>()
157
+
158
+ /** The flex style for each position, read once per distinct track list. */
159
+ export function flexesOf(tracks: string): Flex[] {
160
+ let flexes = cache.get(tracks)
161
+ if (flexes) return flexes
162
+ flexes = []
163
+ for (const part of split(tracks, ' ')) {
164
+ if (!part.startsWith('repeat(')) {
165
+ flexes.push(flexOf(part))
166
+ continue
167
+ }
168
+ const fixed = REPEAT.exec(part)
169
+ if (!fixed) break
170
+ const inner = split(fixed[2], ' ').map(flexOf)
171
+ for (let i = 0; i < Number(fixed[1]); i++) flexes.push(...inner)
172
+ }
173
+ cache.set(tracks, flexes)
174
+ return flexes
175
+ }
176
+
177
+ const placed = (child: React.ReactElement<any>) => {
178
+ const position = child.props?.position
179
+ return position !== 'absolute' && position !== 'fixed'
180
+ }
181
+
182
+ /** Native: each child takes the flex style of the track at its position. */
183
+ export function place(children: React.ReactNode, tracks: string): React.ReactNode {
184
+ const flexes = flexesOf(tracks)
185
+ const at = { i: 0 }
186
+ const walk = (list: React.ReactNode): React.ReactNode =>
187
+ React.Children.map(list, (node) => {
188
+ if (node == null || typeof node === 'boolean') return node
189
+ if (!React.isValidElement(node)) {
190
+ at.i++
191
+ return node
192
+ }
193
+ const child = node as React.ReactElement<any>
194
+ if (child.type === React.Fragment) {
195
+ return React.cloneElement(child, undefined, walk(child.props.children))
196
+ }
197
+ if (!placed(child)) return child
198
+ const flex = flexes[at.i++] ?? CONTENT
199
+ if (isGuiComponent(child.type)) return React.cloneElement(child, flex)
200
+ const own = child.props.style
201
+ return React.cloneElement(child, {
202
+ style: own == null ? flex : [...(Array.isArray(own) ? own : [own]), flex],
203
+ })
204
+ })
205
+ return walk(children)
206
+ }
package/src/types.tsx CHANGED
@@ -588,6 +588,11 @@ export type ComponentContextI = {
588
588
  mediaEmit?: (state: UseMediaState) => void
589
589
  mediaEmitListeners?: Set<(state: UseMediaState) => void>
590
590
  insets?: { top: number; right: number; bottom: number; left: number } | null
591
+ /**
592
+ * The axis of the `tracks` stack this component sits in directly, on web.
593
+ * A direct child of a vertical one reads `self` across (helpers/tracks.ts).
594
+ */
595
+ tracks?: 'x' | 'y' | null
591
596
  }
592
597
 
593
598
  export type GuiComponentStateRef = {
@@ -2646,7 +2651,12 @@ export interface StackStyleBase
2646
2651
  extends Omit<ViewStyle, keyof ExtendedBaseProps | 'elevation'>, ExtendedBaseProps {}
2647
2652
 
2648
2653
  export interface TextStylePropsBase
2649
- extends Omit<RNTextStyle, keyof ExtendedBaseProps>, ExtendedBaseProps {
2654
+ extends Omit<RNTextStyle, keyof ExtendedBaseProps | 'textAlign'>, ExtendedBaseProps {
2655
+ /**
2656
+ * `start` and `end` follow the writing direction: the CSS logical values on
2657
+ * web, and on native the left/right react-native swaps under RTL.
2658
+ */
2659
+ textAlign?: RNTextStyle['textAlign'] | 'start' | 'end'
2650
2660
  ellipsis?: boolean
2651
2661
  numberOfLines?: number
2652
2662
  textDecorationDistance?: number
@@ -2704,6 +2714,20 @@ export interface StackNonStyleProps
2704
2714
  GuiComponentPropsBase {
2705
2715
  // we allow either RN or web style props, of course only web css props only works on web
2706
2716
  style?: StyleProp<LooseCombinedObjects<React.CSSProperties, ViewStyle>>
2717
+
2718
+ /**
2719
+ * Lays the children on grid tracks along the stack's axis, sized by the
2720
+ * stack: a CSS track list, one track per child in order.
2721
+ *
2722
+ * On web the stack becomes a grid: an XStack's tracks are its columns, a
2723
+ * YStack's its rows, and `items`, `justify` and a child's `self` keep their
2724
+ * flex meaning. On native it stays flex and each child takes its track as a
2725
+ * flex style (`1fr` is `flex: 1`). The full mapping is helpers/tracks.ts.
2726
+ *
2727
+ * @example <YStack tracks="auto 1fr auto">
2728
+ * @example <XStack tracks="240px 1fr" gap="$4">
2729
+ */
2730
+ tracks?: string
2707
2731
  }
2708
2732
 
2709
2733
  export type StackStyle = WithThemeShorthandsPseudosMedia<StackStyleBase>
@@ -2948,6 +2972,8 @@ export type GetStyleState = {
2948
2972
  pseudoTransitions?: PseudoTransitions | null
2949
2973
  // Resolved animation driver (respects animatedBy prop)
2950
2974
  animationDriver?: AnimationDriver | null
2975
+ // style keys renamed for a vertical `tracks` stack and its direct children (helpers/tracks.ts)
2976
+ renames?: Record<string, string>
2951
2977
  }
2952
2978
 
2953
2979
  export type StyleResolver<Response = PropMappedValue> = (
@@ -1 +1 @@
1
- {"version":3,"file":"createComponent.d.ts","sourceRoot":"","sources":["../src/createComponent.tsx"],"names":[],"mappings":"AAaA,OAAO,KAA2C,MAAM,OAAO,CAAA;AA6B/D,OAAO,KAAK,EAQV,YAAY,EAEZ,YAAY,EACZ,iBAAiB,EACjB,UAAU,EAOX,MAAM,aAAa,CAAA;AAkCpB,KAAK,iBAAiB,GAAG,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,iBAAiB,CAAC,CAAC,CAAA;AAEhF,eAAO,MAAM,kBAAkB,wBAA+B,CAAA;AAwK9D,wBAAgB,eAAe,CAC7B,kBAAkB,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,EAAE,EACnD,GAAG,SAAS,UAAU,GAAG,UAAU,EACnC,SAAS,GAAG,KAAK,EACjB,UAAU,SAAS,MAAM,GAAG,KAAK,EACjC,YAAY,EAAE,YAAY,oEAyoD3B"}
1
+ {"version":3,"file":"createComponent.d.ts","sourceRoot":"","sources":["../src/createComponent.tsx"],"names":[],"mappings":"AAaA,OAAO,KAA2C,MAAM,OAAO,CAAA;AA8B/D,OAAO,KAAK,EAQV,YAAY,EAEZ,YAAY,EACZ,iBAAiB,EACjB,UAAU,EAOX,MAAM,aAAa,CAAA;AAkCpB,KAAK,iBAAiB,GAAG,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,iBAAiB,CAAC,CAAC,CAAA;AAEhF,eAAO,MAAM,kBAAkB,wBAA+B,CAAA;AAwK9D,wBAAgB,eAAe,CAC7B,kBAAkB,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,EAAE,EACnD,GAAG,SAAS,UAAU,GAAG,UAAU,EACnC,SAAS,GAAG,KAAK,EACjB,UAAU,SAAS,MAAM,GAAG,KAAK,EACjC,YAAY,EAAE,YAAY,oEAwqD3B"}
@@ -1 +1 @@
1
- {"version":3,"file":"createDesignSystem.d.ts","sourceRoot":"","sources":["../../src/helpers/createDesignSystem.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAU5D,KAAK,WAAW,GAAG;IACjB,WAAW,EAAE,MAAM,EAAE,CAAA;IACrB,iBAAiB,EAAE,MAAM,MAAM,EAAE,CAAA;CAClC,CAAA;AAGD,iBAAS,2BAA2B,CAClC,UAAU,EAAE,GAAG,EACf,QAAQ,GAAE,MAAgB,GACzB,MAAM,EAAE,CAwBV;AAED,OAAO,EAAE,2BAA2B,EAAE,CAAA;AAEtC;;GAEG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,EAChD,4BAA4B,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,GAC1D,MAAM,EAAE,CAuBV;AAED;;GAEG;AACH,wBAAgB,aAAa,CAC3B,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,SAAS,EAC5C,qBAAqB,EAAE,CAAC,UAAU,EAAE,GAAG,KAAK,MAAM,EAAE,GACnD,MAAM,CACP,MAAM,EACN;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,EAAE,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,GAAG,CAAA;CAAE,CAC7E,CAyBA;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,YAAY,EAAE,MAAM,EAAE,EACtB,gBAAgB,EAAE,MAAM,CACtB,MAAM,EACN;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,EAAE,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,GAAG,CAAA;CAAE,CAC7E,EACD,gBAAgB,GAAE,MAAgB,GACjC,MAAM,EAAE,CA6CV;AAED;;GAEG;AACH,wBAAgB,cAAc,CAC5B,aAAa,EAAE,KAAK,CAAC;IAAE,KAAK,EAAE,MAAM,EAAE,CAAC;IAAC,KAAK,EAAE,GAAG,CAAA;CAAE,CAAC,EACrD,QAAQ,EAAE,cAAc,GACvB,MAAM,EAAE,CAmBV;AAED;;GAEG;AACH,wBAAgB,MAAM,CACpB,WAAW,EAAE,WAAW,EACxB,IAAI,EAAE;IACJ,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,OAAO,CAAC,EAAE,QAAQ,GAAG,eAAe,GAAG,MAAM,GAAG,IAAI,CAAA;CACrD,YAAK,EACN,SAAS,EAAE;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,GAC3B,MAAM,CAyDR"}
1
+ {"version":3,"file":"createDesignSystem.d.ts","sourceRoot":"","sources":["../../src/helpers/createDesignSystem.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAU5D,KAAK,WAAW,GAAG;IACjB,WAAW,EAAE,MAAM,EAAE,CAAA;IACrB,iBAAiB,EAAE,MAAM,MAAM,EAAE,CAAA;CAClC,CAAA;AAGD,iBAAS,2BAA2B,CAClC,UAAU,EAAE,GAAG,EACf,QAAQ,GAAE,MAAgB,GACzB,MAAM,EAAE,CAwBV;AAED,OAAO,EAAE,2BAA2B,EAAE,CAAA;AAEtC;;GAEG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,EAChD,4BAA4B,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,GAC1D,MAAM,EAAE,CAuBV;AAED;;GAEG;AACH,wBAAgB,aAAa,CAC3B,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,SAAS,EAC5C,qBAAqB,EAAE,CAAC,UAAU,EAAE,GAAG,KAAK,MAAM,EAAE,GACnD,MAAM,CACP,MAAM,EACN;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,EAAE,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,GAAG,CAAA;CAAE,CAC7E,CAyBA;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,YAAY,EAAE,MAAM,EAAE,EACtB,gBAAgB,EAAE,MAAM,CACtB,MAAM,EACN;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,EAAE,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,GAAG,CAAA;CAAE,CAC7E,EACD,gBAAgB,GAAE,MAAgB,GACjC,MAAM,EAAE,CA6CV;AAED;;GAEG;AACH,wBAAgB,cAAc,CAC5B,aAAa,EAAE,KAAK,CAAC;IAAE,KAAK,EAAE,MAAM,EAAE,CAAC;IAAC,KAAK,EAAE,GAAG,CAAA;CAAE,CAAC,EACrD,QAAQ,EAAE,cAAc,GACvB,MAAM,EAAE,CAmBV;AAED;;GAEG;AACH,wBAAgB,MAAM,CACpB,WAAW,EAAE,WAAW,EACxB,IAAI,EAAE;IACJ,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,OAAO,CAAC,EAAE,QAAQ,GAAG,eAAe,GAAG,MAAM,GAAG,IAAI,CAAA;CACrD,YAAK,EACN,SAAS,EAAE;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,GAC3B,MAAM,CA0DR"}
@@ -1 +1 @@
1
- {"version":3,"file":"expandStyle.d.ts","sourceRoot":"","sources":["../../src/helpers/expandStyle.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,EAAkB,KAAK,WAAW,EAAE,MAAM,cAAc,CAAA;AAC/D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AA8DnD,wBAAgB,WAAW,CACzB,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,GAAG,EACV,WAAW,GAAE,WAA8B,GAC1C,eAAe,CAkHjB"}
1
+ {"version":3,"file":"expandStyle.d.ts","sourceRoot":"","sources":["../../src/helpers/expandStyle.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,EAAkB,KAAK,WAAW,EAAE,MAAM,cAAc,CAAA;AAC/D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AA8DnD,wBAAgB,WAAW,CACzB,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,GAAG,EACV,WAAW,GAAE,WAA8B,GAC1C,eAAe,CA2IjB"}
@@ -1 +1 @@
1
- {"version":3,"file":"getSplitStyles.d.ts","sourceRoot":"","sources":["../../src/helpers/getSplitStyles.tsx"],"names":[],"mappings":"AA8BA,OAAO,KAAK,EACV,gBAAgB,EAChB,eAAe,EAEf,iBAAiB,EACjB,SAAS,EACT,cAAc,EACd,aAAa,EAIb,eAAe,EACf,YAAY,EAEZ,iBAAiB,EAEjB,SAAS,EACT,WAAW,EAEZ,MAAM,cAAc,CAAA;AA8BrB,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAA;AAI9D,OAAO,EAAE,mBAAmB,EAAE,CAAA;AAC9B,OAAO,EAAE,uBAAuB,EAAE,0BAA0B,EAAE,MAAM,sBAAsB,CAAA;AAC1F,YAAY,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAA;AAEnF,MAAM,MAAM,WAAW,GAAG,UAAU,CAAC,OAAO,cAAc,CAAC,CAAA;AAM3D,MAAM,MAAM,gBAAgB,GAAG,UAAU,CAAC,OAAO,cAAc,CAAC,CAAA;AAIhE,KAAK,aAAa,GAAG,CACnB,KAAK,EAAE;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;CAAE,EAC7B,YAAY,EAAE,YAAY,EAC1B,KAAK,EAAE,WAAW,EAClB,SAAS,EAAE,MAAM,EACjB,cAAc,EAAE,iBAAiB,EACjC,UAAU,EAAE,eAAe,EAC3B,iBAAiB,CAAC,EAAE,cAAc,GAAG,IAAI,EACzC,OAAO,CAAC,EAAE,iBAAiB,EAC3B,YAAY,CAAC,EAAE,gBAAgB,GAAG,IAAI,EAEtC,WAAW,CAAC,EAAE,MAAM,EACpB,iBAAiB,CAAC,EAAE,OAAO,EAC3B,KAAK,CAAC,EAAE,SAAS,EAEjB,eAAe,CAAC,EAAE,eAAe,GAAG,IAAI,KACrC,IAAI,GAAG,cAAc,CAAA;AAE1B,eAAO,MAAM,UAAU,MAAM,CAAA;AA8D7B,eAAO,MAAM,cAAc,EAAE,aA63C5B,CAAA;AAqFD,eAAO,MAAM,WAAW,eACV,aAAa,UACjB,MAAM,WACL,MAAM,wBACO,OAAO,KAC5B,SA6HF,CAAA;AAQD,eAAO,MAAM,cAAc,EAAE,aAc5B,CAAA"}
1
+ {"version":3,"file":"getSplitStyles.d.ts","sourceRoot":"","sources":["../../src/helpers/getSplitStyles.tsx"],"names":[],"mappings":"AA8BA,OAAO,KAAK,EACV,gBAAgB,EAChB,eAAe,EAEf,iBAAiB,EACjB,SAAS,EACT,cAAc,EACd,aAAa,EAIb,eAAe,EACf,YAAY,EAEZ,iBAAiB,EAEjB,SAAS,EACT,WAAW,EAEZ,MAAM,cAAc,CAAA;AA8BrB,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAA;AAK9D,OAAO,EAAE,mBAAmB,EAAE,CAAA;AAC9B,OAAO,EAAE,uBAAuB,EAAE,0BAA0B,EAAE,MAAM,sBAAsB,CAAA;AAC1F,YAAY,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAA;AAEnF,MAAM,MAAM,WAAW,GAAG,UAAU,CAAC,OAAO,cAAc,CAAC,CAAA;AAM3D,MAAM,MAAM,gBAAgB,GAAG,UAAU,CAAC,OAAO,cAAc,CAAC,CAAA;AAIhE,KAAK,aAAa,GAAG,CACnB,KAAK,EAAE;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;CAAE,EAC7B,YAAY,EAAE,YAAY,EAC1B,KAAK,EAAE,WAAW,EAClB,SAAS,EAAE,MAAM,EACjB,cAAc,EAAE,iBAAiB,EACjC,UAAU,EAAE,eAAe,EAC3B,iBAAiB,CAAC,EAAE,cAAc,GAAG,IAAI,EACzC,OAAO,CAAC,EAAE,iBAAiB,EAC3B,YAAY,CAAC,EAAE,gBAAgB,GAAG,IAAI,EAEtC,WAAW,CAAC,EAAE,MAAM,EACpB,iBAAiB,CAAC,EAAE,OAAO,EAC3B,KAAK,CAAC,EAAE,SAAS,EAEjB,eAAe,CAAC,EAAE,eAAe,GAAG,IAAI,KACrC,IAAI,GAAG,cAAc,CAAA;AAE1B,eAAO,MAAM,UAAU,MAAM,CAAA;AA8D7B,eAAO,MAAM,cAAc,EAAE,aA44C5B,CAAA;AAqFD,eAAO,MAAM,WAAW,eACV,aAAa,UACjB,MAAM,WACL,MAAM,wBACO,OAAO,KAC5B,SA6HF,CAAA;AAQD,eAAO,MAAM,cAAc,EAAE,aAc5B,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"propMapper.d.ts","sourceRoot":"","sources":["../../src/helpers/propMapper.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAEV,UAAU,EAGV,iBAAiB,EAGlB,MAAM,cAAc,CAAA;AAkBrB,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AAEpD,eAAO,MAAM,UAAU,EAAE,UAqHxB,CAAA;AAqGD,wBAAgB,+BAA+B,CAAC,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,iBAAiB,sBAkBlF"}
1
+ {"version":3,"file":"propMapper.d.ts","sourceRoot":"","sources":["../../src/helpers/propMapper.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAEV,UAAU,EAGV,iBAAiB,EAGlB,MAAM,cAAc,CAAA;AAkBrB,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AAEpD,eAAO,MAAM,UAAU,EAAE,UA6HxB,CAAA;AAqGD,wBAAgB,+BAA+B,CAAC,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,iBAAiB,sBAkBlF"}
@@ -14,6 +14,7 @@ export declare const skipProps: {
14
14
  render: number;
15
15
  style: number;
16
16
  group: number;
17
+ tracks: number;
17
18
  animatePresence: number;
18
19
  };
19
20
  //# sourceMappingURL=skipProps.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"skipProps.d.ts","sourceRoot":"","sources":["../../src/helpers/skipProps.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,eAAO,MAAM,SAAS;IACpB,aAAa;IACb,UAAU;IACV,KAAK;IACL,WAAW;IACX,UAAU;IACV,gBAAgB;IAChB,KAAK;IACL,aAAa;IACb,mBAAmB;IACnB,MAAM;IACN,KAAK;IACL,KAAK;IACL,eAAe;CAChB,CAAA"}
1
+ {"version":3,"file":"skipProps.d.ts","sourceRoot":"","sources":["../../src/helpers/skipProps.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,eAAO,MAAM,SAAS;IACpB,aAAa;IACb,UAAU;IACV,KAAK;IACL,WAAW;IACX,UAAU;IACV,gBAAgB;IAChB,KAAK;IACL,aAAa;IACb,mBAAmB;IACnB,MAAM;IACN,KAAK;IACL,KAAK;IACL,MAAM;IACN,eAAe;CAChB,CAAA"}
@@ -0,0 +1,87 @@
1
+ /**
2
+ * `tracks`: a stack that lays its children on CSS grid tracks along its own
3
+ * axis, so the parent sizes them and the children carry no flex props.
4
+ *
5
+ * <YStack tracks="auto 1fr auto"> header, body that fills, footer
6
+ * <XStack tracks="240px 1fr"> a fixed rail and the page beside it
7
+ *
8
+ * The axis is the stack's own flexDirection: `row` and `row-reverse` run across
9
+ * (x), everything else runs down (y). A reverse direction is not mirrored —
10
+ * grid has no reverse flow — so the children sit on the tracks in source order.
11
+ *
12
+ * WEB is the browser's grid:
13
+ *
14
+ * y (YStack) x (XStack)
15
+ * display grid grid
16
+ * flow grid-auto-flow: row grid-auto-flow: column
17
+ * tracks grid-template-rows grid-template-columns
18
+ * cross axis grid-auto-columns: grid-auto-rows:
19
+ * minmax(0, 1fr) minmax(0, 1fr)
20
+ *
21
+ * The cross-axis track is one that fills the stack and has no content floor,
22
+ * which is what a flex line's cross size is: a child stretched across a column
23
+ * is exactly as wide as the column, however wide its content.
24
+ *
25
+ * A prop the author names on the stack wins over all of these, so
26
+ * `display="none"` still hides it and an explicit `gridAutoFlow` stays.
27
+ *
28
+ * ALIGNMENT KEEPS ITS FLEX MEANING. On x, grid's block axis is the row's cross
29
+ * axis and its inline axis the main axis, so `items`, `justify` and `self` mean
30
+ * what they meant and pass through. On y the two axes swap, so they are
31
+ * renamed:
32
+ *
33
+ * on the stack items (alignItems) -> justifyItems
34
+ * justify (justifyContent) -> alignContent
35
+ * content (alignContent) -> justifyContent
36
+ * on a child self (alignSelf) -> justifySelf
37
+ *
38
+ * The rename happens where every style key is mapped (propMapper), so it holds
39
+ * for a key written in a media query, a pseudo style or a variant as well as a
40
+ * plain prop. A child learns that it sits in a vertical stack from
41
+ * ComponentContext; the context reaches only the stack's direct children, and
42
+ * each of them clears it for its own.
43
+ *
44
+ * NATIVE falls back to flex: the stack stays the flex column or row it is, and
45
+ * each child takes the track at its position as its flex style. Every child
46
+ * gets one, written as longhands, so a flex prop the child set on itself does
47
+ * not combine with it: the track wins, as it does on web.
48
+ *
49
+ * Nfr, minmax(_, Nfr) flexGrow N, flexShrink 1, flexBasis 0 (flex: N)
50
+ * Npx, N%, 0 flexGrow 0, flexShrink 0, flexBasis N (px as a number)
51
+ * repeat(K, list) the list written out K times
52
+ * anything else, and every flexGrow 0, flexShrink 0, flexBasis auto
53
+ * child past the list (content-sized, as an auto track is)
54
+ *
55
+ * `repeat(auto-fill, …)` and `repeat(auto-fit, …)` need the stack's measured
56
+ * size, so the list ends there and the children from that position on are
57
+ * content-sized.
58
+ *
59
+ * Positions count each child that renders, through fragments, and skip a child
60
+ * whose `position` prop is absolute or fixed, as grid does. A gui child takes
61
+ * the style as props; any other element as a `style` entry after its own, which
62
+ * a custom component has to pass to its root. Alignment is not renamed on
63
+ * native: the stack is still flex there.
64
+ */
65
+ import React from 'react';
66
+ export type Axis = 'x' | 'y';
67
+ /** The axis a stack lays its tracks on, from its own flexDirection. */
68
+ export declare const axisOf: (props: Record<string, any>) => Axis;
69
+ /** Grid styles for a tracks stack on web. */
70
+ export declare const gridOf: (tracks: string, axis: Axis) => Record<string, string>;
71
+ /**
72
+ * The renames for one component on web: as a vertical tracks stack, as a
73
+ * direct child of one, or both. Undefined when neither, which is every
74
+ * component that does not opt in.
75
+ */
76
+ export declare function renamesOf(own: Axis | null, parent: Axis | null | undefined): Record<string, string> | undefined;
77
+ type Flex = {
78
+ flexGrow: number;
79
+ flexShrink: number;
80
+ flexBasis: number | string;
81
+ };
82
+ /** The flex style for each position, read once per distinct track list. */
83
+ export declare function flexesOf(tracks: string): Flex[];
84
+ /** Native: each child takes the flex style of the track at its position. */
85
+ export declare function place(children: React.ReactNode, tracks: string): React.ReactNode;
86
+ export {};
87
+ //# sourceMappingURL=tracks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tracks.d.ts","sourceRoot":"","sources":["../../src/helpers/tracks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+DG;AACH,OAAO,KAAK,MAAM,OAAO,CAAA;AAIzB,MAAM,MAAM,IAAI,GAAG,GAAG,GAAG,GAAG,CAAA;AAE5B,uEAAuE;AACvE,eAAO,MAAM,MAAM,UAAW,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAG,IACgC,CAAA;AAEpF,6CAA6C;AAC7C,eAAO,MAAM,MAAM,WAAY,MAAM,QAAQ,IAAI,KAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAalE,CAAA;AAUP;;;;GAIG;AACH,wBAAgB,SAAS,CACvB,GAAG,EAAE,IAAI,GAAG,IAAI,EAChB,MAAM,EAAE,IAAI,GAAG,IAAI,GAAG,SAAS,GAC9B,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CAGpC;AAED,KAAK,IAAI,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAAA;CAAE,CAAA;AA8ChF,2EAA2E;AAC3E,wBAAgB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,EAAE,CAgB/C;AAOD,4EAA4E;AAC5E,wBAAgB,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,GAAG,KAAK,CAAC,SAAS,CAuBhF"}