@duro-app/ui 0.34.4 → 0.34.6

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.
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Native (React Native / Expo) entry — resolved via the `react-native` export
3
+ * condition (see package.json). Metro reads THIS instead of the web `index.ts`.
4
+ *
5
+ * Why a separate barrel: the web `index.ts` re-exports interactive/overlay
6
+ * components (Dialog, Drawer, Menu, Tabs, Select, Combobox, Form, ScrollArea,
7
+ * TagGroup, ThemeProvider's portal) that use web-only DOM APIs — and Combobox
8
+ * imports `react-dom`, so pulling the full barrel crashes on Metro. This barrel
9
+ * re-exports ONLY the components whose source is RN-safe (pure react-strict-dom
10
+ * `html` + `css`, audited 2026-06-02). The rest get RN variants in a later pass.
11
+ *
12
+ * Tokens resolve fine on native already: @duro-app/tokens's subpath exports
13
+ * (`./tokens/*.css`, `./themes/*.css`) point straight at their `.css.ts`
14
+ * source, so Metro/StyleX-native compile them directly.
15
+ */
16
+ export { Badge, type BadgeVariant, type BadgeSize } from './components/Badge/Badge';
17
+ export { Button, type ButtonVariant, type ButtonSize } from './components/Button/Button';
18
+ export { Card, type CardVariant, type CardSize } from './components/Card/Card';
19
+ export { Checkbox } from './components/Checkbox/Checkbox';
20
+ export { Heading, type HeadingVariant } from './components/Heading/Heading';
21
+ export { Input, type InputVariant } from './components/Input/Input';
22
+ export { Switch } from './components/Switch/Switch';
23
+ export { Text, type TextVariant, type TextColor } from './components/Text/Text';
24
+ export { Textarea, type TextareaVariant } from './components/Textarea/Textarea';
25
+ export { Field } from './components/Field/Field';
26
+ export { InputGroup } from './components/InputGroup/InputGroup';
27
+ export { Stack, type SpacingKey } from './components/Stack/Stack';
28
+ export { Inline } from './components/Inline/Inline';
29
+ export { Cluster } from './components/Cluster/Cluster';
30
+ export { Grid } from './components/Grid/Grid';
31
+ //# sourceMappingURL=index.native.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.native.d.ts","sourceRoot":"","sources":["../src/index.native.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,OAAO,EAAC,KAAK,EAAE,KAAK,YAAY,EAAE,KAAK,SAAS,EAAC,MAAM,0BAA0B,CAAA;AACjF,OAAO,EAAC,MAAM,EAAE,KAAK,aAAa,EAAE,KAAK,UAAU,EAAC,MAAM,4BAA4B,CAAA;AACtF,OAAO,EAAC,IAAI,EAAE,KAAK,WAAW,EAAE,KAAK,QAAQ,EAAC,MAAM,wBAAwB,CAAA;AAC5E,OAAO,EAAC,QAAQ,EAAC,MAAM,gCAAgC,CAAA;AACvD,OAAO,EAAC,OAAO,EAAE,KAAK,cAAc,EAAC,MAAM,8BAA8B,CAAA;AACzE,OAAO,EAAC,KAAK,EAAE,KAAK,YAAY,EAAC,MAAM,0BAA0B,CAAA;AACjE,OAAO,EAAC,MAAM,EAAC,MAAM,4BAA4B,CAAA;AACjD,OAAO,EAAC,IAAI,EAAE,KAAK,WAAW,EAAE,KAAK,SAAS,EAAC,MAAM,wBAAwB,CAAA;AAC7E,OAAO,EAAC,QAAQ,EAAE,KAAK,eAAe,EAAC,MAAM,gCAAgC,CAAA;AAG7E,OAAO,EAAC,KAAK,EAAC,MAAM,0BAA0B,CAAA;AAC9C,OAAO,EAAC,UAAU,EAAC,MAAM,oCAAoC,CAAA;AAG7D,OAAO,EAAC,KAAK,EAAE,KAAK,UAAU,EAAC,MAAM,0BAA0B,CAAA;AAC/D,OAAO,EAAC,MAAM,EAAC,MAAM,4BAA4B,CAAA;AACjD,OAAO,EAAC,OAAO,EAAC,MAAM,8BAA8B,CAAA;AACpD,OAAO,EAAC,IAAI,EAAC,MAAM,wBAAwB,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@duro-app/ui",
3
- "version": "0.34.4",
3
+ "version": "0.34.6",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -24,6 +24,7 @@
24
24
  "types": "dist/index.d.ts",
25
25
  "exports": {
26
26
  ".": {
27
+ "react-native": "./src/index.native.ts",
27
28
  "source": "./src/index.ts",
28
29
  "import": "./dist/index.js",
29
30
  "types": "./dist/index.d.ts"
@@ -53,7 +54,7 @@
53
54
  }
54
55
  },
55
56
  "dependencies": {
56
- "@duro-app/tokens": "^0.34.4"
57
+ "@duro-app/tokens": "^0.34.6"
57
58
  },
58
59
  "devDependencies": {
59
60
  "@babel/preset-typescript": "^7.28.0",
@@ -107,8 +107,13 @@ function unwrapElementType(t: unknown): unknown {
107
107
  return current
108
108
  }
109
109
 
110
- function extractColumnMeta(children: ReactNode): {template: string; labels: string[]} {
110
+ function extractColumnMeta(children: ReactNode): {
111
+ template: string
112
+ compactTemplate: string
113
+ labels: string[]
114
+ } {
111
115
  const widths: string[] = []
116
+ const compactWidths: string[] = []
112
117
  const labels: string[] = []
113
118
 
114
119
  function walk(node: ReactNode) {
@@ -128,7 +133,13 @@ function extractColumnMeta(children: ReactNode): {template: string; labels: stri
128
133
  // cell's text is wider than 1/N of the container. With minmax(0,
129
134
  // 1fr), the cell's compact-mode `min-width: 0` + `overflow:
130
135
  // hidden` + `text-overflow: ellipsis` can actually truncate.
131
- widths.push(props.width || 'minmax(0, 1fr)')
136
+ const width = props.width || 'minmax(0, 1fr)'
137
+ widths.push(width)
138
+ // `compactWidth` lets the consumer switch to a content-aware
139
+ // layout in the compact band while staying evenly distributed
140
+ // at desktop. Falls back to `width` so columns that don't opt
141
+ // in keep one template across both breakpoints.
142
+ compactWidths.push(props.compactWidth || width)
132
143
  const explicit = typeof props.label === 'string' ? props.label : undefined
133
144
  const fallback = extractText(props.children).trim()
134
145
  const label = explicit ?? fallback
@@ -148,7 +159,11 @@ function extractColumnMeta(children: ReactNode): {template: string; labels: stri
148
159
  }
149
160
 
150
161
  walk(children)
151
- return {template: widths.join(' '), labels}
162
+ return {
163
+ template: widths.join(' '),
164
+ compactTemplate: compactWidths.join(' '),
165
+ labels,
166
+ }
152
167
  }
153
168
 
154
169
  // --- Root ---
@@ -181,7 +196,7 @@ export function Root({
181
196
  pagination,
182
197
  }: RootProps) {
183
198
  const inferredTemplateRef = useRef<string | null>(null)
184
- const {template, labels} = extractColumnMeta(children)
199
+ const {template, compactTemplate, labels} = extractColumnMeta(children)
185
200
  if (template) {
186
201
  inferredTemplateRef.current = template
187
202
  }
@@ -199,7 +214,7 @@ export function Root({
199
214
  // always wins as the later entry in the array.
200
215
  template
201
216
  ? responsive
202
- ? styles.gridColumnsResponsive(template)
217
+ ? styles.gridColumnsResponsive(template, compactTemplate)
203
218
  : styles.gridColumns(template)
204
219
  : undefined,
205
220
  responsive && styles.rootResponsive,
@@ -362,13 +377,24 @@ const CellIndexContext = createContext<{index: number; total: number}>({index: 0
362
377
  export function HeaderCell({
363
378
  children,
364
379
  width: _width,
380
+ compactWidth: _compactWidth,
365
381
  label: _label,
366
382
  isActions,
367
383
  'aria-label': ariaLabel,
368
384
  }: {
369
385
  children?: ReactNode
370
- /** Column width: CSS value like '40px', '2fr', 'max-content'. Defaults to '1fr'. */
386
+ /** Column width at default (wide) viewport. CSS grid-template-columns
387
+ * track value — e.g. '40px', '2fr', 'max-content'. Defaults to
388
+ * 'minmax(0, 1fr)' so each column shares the row evenly and is free
389
+ * to shrink below its content's intrinsic size. */
371
390
  width?: string
391
+ /** Column width when the table's container drops into compact mode
392
+ * (≤720px container). Use this to switch to a content-aware layout
393
+ * at narrow widths — e.g. give a status badge `max-content` and the
394
+ * action column `minmax(0, 2fr)` so it absorbs the slack — while
395
+ * keeping evenly-distributed columns on wide screens. Defaults to the
396
+ * same value as `width`. */
397
+ compactWidth?: string
372
398
  /** Stack-mode label string. Optional when children is a plain string — the
373
399
  * text content is used as the label automatically. Required when children
374
400
  * contain JSX (icon + text, sort indicator, etc.). */
@@ -308,15 +308,22 @@ export const styles = css.create({
308
308
  gridTemplateColumns: template,
309
309
  }),
310
310
 
311
- // Dynamic: grid columns + stack-mode collapse in one style.
312
- // Used instead of gridColumns() when responsive=true so that both the
313
- // explicit column template and the @container override live in the same
314
- // StyleX style object. If they were in separate styles (gridColumns +
315
- // rootResponsive), StyleX conflict resolution would keep only the LAST
316
- // style's gridTemplateColumns class and silently discard the earlier one.
317
- gridColumnsResponsive: (template: string) => ({
311
+ // Dynamic: grid columns at three tiers (default / compact / stack) in
312
+ // one style. Used instead of gridColumns() when responsive=true so that
313
+ // every gridTemplateColumns rule lives in the same StyleX style object —
314
+ // splitting them would let StyleX's conflict resolution drop the
315
+ // earlier classes (the LAST style wins per property key).
316
+ //
317
+ // - default: balanced multi-column layout for desktop widths
318
+ // - @container (max-width: COMPACT_BP): consumer-supplied "compact"
319
+ // template, e.g. give a badge column max-content and let the action
320
+ // column absorb the slack so its hint text fits on one line
321
+ // - @container (max-width: STACK_BP): collapse to a single column so
322
+ // each row becomes a card
323
+ gridColumnsResponsive: (template: string, compactTemplate: string) => ({
318
324
  gridTemplateColumns: {
319
325
  default: template,
326
+ [`@container (max-width: ${COMPACT_BP})`]: compactTemplate,
320
327
  [`@container (max-width: ${STACK_BP})`]: '1fr',
321
328
  },
322
329
  }),
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Native (React Native / Expo) entry — resolved via the `react-native` export
3
+ * condition (see package.json). Metro reads THIS instead of the web `index.ts`.
4
+ *
5
+ * Why a separate barrel: the web `index.ts` re-exports interactive/overlay
6
+ * components (Dialog, Drawer, Menu, Tabs, Select, Combobox, Form, ScrollArea,
7
+ * TagGroup, ThemeProvider's portal) that use web-only DOM APIs — and Combobox
8
+ * imports `react-dom`, so pulling the full barrel crashes on Metro. This barrel
9
+ * re-exports ONLY the components whose source is RN-safe (pure react-strict-dom
10
+ * `html` + `css`, audited 2026-06-02). The rest get RN variants in a later pass.
11
+ *
12
+ * Tokens resolve fine on native already: @duro-app/tokens's subpath exports
13
+ * (`./tokens/*.css`, `./themes/*.css`) point straight at their `.css.ts`
14
+ * source, so Metro/StyleX-native compile them directly.
15
+ */
16
+
17
+ // Leaf primitives
18
+ export {Badge, type BadgeVariant, type BadgeSize} from './components/Badge/Badge'
19
+ export {Button, type ButtonVariant, type ButtonSize} from './components/Button/Button'
20
+ export {Card, type CardVariant, type CardSize} from './components/Card/Card'
21
+ export {Checkbox} from './components/Checkbox/Checkbox'
22
+ export {Heading, type HeadingVariant} from './components/Heading/Heading'
23
+ export {Input, type InputVariant} from './components/Input/Input'
24
+ export {Switch} from './components/Switch/Switch'
25
+ export {Text, type TextVariant, type TextColor} from './components/Text/Text'
26
+ export {Textarea, type TextareaVariant} from './components/Textarea/Textarea'
27
+
28
+ // Form field wrappers (RN-safe — used by Input/Textarea/Checkbox)
29
+ export {Field} from './components/Field/Field'
30
+ export {InputGroup} from './components/InputGroup/InputGroup'
31
+
32
+ // Layout primitives
33
+ export {Stack, type SpacingKey} from './components/Stack/Stack'
34
+ export {Inline} from './components/Inline/Inline'
35
+ export {Cluster} from './components/Cluster/Cluster'
36
+ export {Grid} from './components/Grid/Grid'