@krapwoo/ds-viewer 0.9.0 → 0.10.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.
@@ -1,6 +1,6 @@
1
1
  import React, { useState } from 'react';
2
2
  import { View, Text, StyleSheet, type LayoutChangeEvent, type TextStyle } from 'react-native';
3
- import { CATALOG_COLOR, CATALOG_LAYOUT, CATALOG_RADIUS, CATALOG_SPACE, CATALOG_TYPE } from './tokens';
3
+ import { CATALOG_COLOR, CATALOG_LAYOUT, CATALOG_RADIUS, CATALOG_SPACE, CATALOG_TEXT } from './tokens';
4
4
  import { PropsTable } from './PropsTable';
5
5
  import { propsColumns, referenceColumns } from './comparison';
6
6
  import type { ComposedOfEntry, SectionDef } from './types';
@@ -8,9 +8,12 @@ import type { ComposedOfEntry, SectionDef } from './types';
8
8
  // react-native-web reads `aria-level`; React Native's prop types do not declare it.
9
9
  const HEADING_LEVEL_2 = { 'aria-level': 2 } as Record<string, unknown>;
10
10
 
11
- function Fact({ label, value, mono = false }: { label: string; value: string; mono?: boolean }) {
11
+ /** `last` drops the trailing divider and its padding, the same convention `TokenRow`'s `last` and
12
+ * `PropsTable`'s `rowLast` already use. Without it the final fact's bottom padding stacks on the
13
+ * card's own `panelPadding`, so a card's contents sat ~10px lower than centred. */
14
+ function Fact({ label, value, mono = false, last = false }: { label: string; value: string; mono?: boolean; last?: boolean }) {
12
15
  return (
13
- <View style={styles.fact}>
16
+ <View style={[styles.fact, last && styles.factLast]}>
14
17
  <Text style={styles.factLabel}>{label}</Text>
15
18
  <Text style={[styles.factValue, mono && styles.mono]}>{value}</Text>
16
19
  </View>
@@ -47,11 +50,16 @@ function compositionLabel(entry: ComposedOfEntry): string {
47
50
  return entry.relationship === 'built-in' ? entry.component : `${entry.component} · ${entry.relationship}`;
48
51
  }
49
52
 
50
- function CompositionFacts({ composedOf }: { composedOf: ComposedOfEntry[] }) {
53
+ function CompositionFacts({ composedOf, lastIsFlush = false }: { composedOf: ComposedOfEntry[]; lastIsFlush?: boolean }) {
51
54
  return (
52
55
  <>
53
56
  {composedOf.map((entry, i) => (
54
- <Fact key={`${entry.component}-${entry.relationship}-${i}`} label={compositionLabel(entry)} value={entry.role} />
57
+ <Fact
58
+ key={`${entry.component}-${entry.relationship}-${i}`}
59
+ label={compositionLabel(entry)}
60
+ value={entry.role}
61
+ last={lastIsFlush && i === composedOf.length - 1}
62
+ />
55
63
  ))}
56
64
  </>
57
65
  );
@@ -91,11 +99,11 @@ export function ReferenceDetails<TId extends string>({ def }: { def: SectionDef<
91
99
  return (
92
100
  <View style={styles.card}>
93
101
  <Text role="heading" {...HEADING_LEVEL_2} style={styles.heading}>Quick reference</Text>
94
- {def.path && <Fact label="Source" value={def.path} mono />}
102
+ {def.path && <Fact label="Source" value={def.path} mono last={!(def.composedOf && def.composedOf.length > 0)} />}
95
103
  {def.composedOf && def.composedOf.length > 0 && (
96
104
  <>
97
105
  <Text style={styles.subheading}>Composition</Text>
98
- <CompositionFacts composedOf={def.composedOf} />
106
+ <CompositionFacts composedOf={def.composedOf} lastIsFlush />
99
107
  </>
100
108
  )}
101
109
  </View>
@@ -117,19 +125,25 @@ export function ReferenceDetails<TId extends string>({ def }: { def: SectionDef<
117
125
  </View>
118
126
  <View style={columnStyle}>
119
127
  <Text role="heading" {...HEADING_LEVEL_2} style={styles.heading}>Quick reference</Text>
120
- {def.path && <Fact label="Source" value={def.path} mono />}
121
- {!hide.accessibility && <Fact label="Accessibility" value={def.a11y ?? 'No accessibility notes documented.'} />}
128
+ {def.path && <Fact label="Source" value={def.path} mono last={hide.accessibility && !(!compositionIsOwnColumn && hasComposition)} />}
129
+ {!hide.accessibility && (
130
+ <Fact
131
+ label="Accessibility"
132
+ value={def.a11y ?? 'No accessibility notes documented.'}
133
+ last={!(!compositionIsOwnColumn && hasComposition)}
134
+ />
135
+ )}
122
136
  {!compositionIsOwnColumn && hasComposition && def.composedOf && (
123
137
  <>
124
138
  <Text style={styles.subheading}>Composition</Text>
125
- <CompositionFacts composedOf={def.composedOf} />
139
+ <CompositionFacts composedOf={def.composedOf} lastIsFlush />
126
140
  </>
127
141
  )}
128
142
  </View>
129
143
  {compositionIsOwnColumn && def.composedOf && (
130
144
  <View style={columnStyle}>
131
145
  <Text role="heading" {...HEADING_LEVEL_2} style={styles.heading}>Composition</Text>
132
- <CompositionFacts composedOf={def.composedOf} />
146
+ <CompositionFacts composedOf={def.composedOf} lastIsFlush />
133
147
  </View>
134
148
  )}
135
149
  </View>
@@ -153,17 +167,13 @@ const styles = StyleSheet.create({
153
167
  column: { flex: 1, minWidth: 0 },
154
168
  columnStacked: { minWidth: 0 },
155
169
  heading: {
156
- fontSize: CATALOG_TYPE.panelHeading,
157
- fontWeight: '700',
158
- letterSpacing: 0.52,
159
- textTransform: 'uppercase',
170
+ ...CATALOG_TEXT.label,
160
171
  color: CATALOG_COLOR.text,
161
172
  marginBottom: 10,
162
173
  },
163
- body: { fontSize: CATALOG_TYPE.md, lineHeight: 20, color: CATALOG_COLOR.textMuted },
174
+ body: { ...CATALOG_TEXT.body, color: CATALOG_COLOR.textMuted },
164
175
  subheading: {
165
- fontSize: CATALOG_TYPE.sm,
166
- fontWeight: '700',
176
+ ...CATALOG_TEXT.captionStrong,
167
177
  color: CATALOG_COLOR.text,
168
178
  marginTop: CATALOG_SPACE.md,
169
179
  marginBottom: CATALOG_SPACE.xs,
@@ -175,14 +185,15 @@ const styles = StyleSheet.create({
175
185
  borderBottomWidth: 1,
176
186
  borderBottomColor: CATALOG_COLOR.borderSubtle,
177
187
  },
178
- factLabel: { flexShrink: 1, minWidth: 0, fontSize: CATALOG_TYPE.md, fontWeight: '700', color: CATALOG_COLOR.text },
179
- factValue: { minWidth: 0, fontSize: CATALOG_TYPE.md, lineHeight: 20, textAlign: 'left', color: CATALOG_COLOR.textMuted },
188
+ factLast: { paddingBottom: 0, borderBottomWidth: 0 },
189
+ factLabel: { flexShrink: 1, minWidth: 0, ...CATALOG_TEXT.bodyStrong, color: CATALOG_COLOR.text },
190
+ factValue: { minWidth: 0, ...CATALOG_TEXT.body, textAlign: 'left', color: CATALOG_COLOR.textMuted },
180
191
  // `wordBreak` isn't in the installed `TextStyle` type (RN's own, not RNW's — RNW's own
181
192
  // `Text/types.js` declares it; a browser applies any valid CSS property name it recognizes
182
193
  // regardless), so a bare literal here would report an unknown property under `--noEmit` even
183
194
  // though it genuinely works: a long unbroken token (a source path with no spaces, e.g.
184
195
  // `AnimatedChevron.tsx`) has no space for the browser's default line-breaking to use, so without
185
196
  // this it stays one unbroken run and overflows a narrow card instead of wrapping at its '/'s.
186
- mono: { fontFamily: CATALOG_COLOR.code, wordBreak: 'break-word' } as TextStyle,
187
- empty: { fontSize: CATALOG_TYPE.sm, fontStyle: 'italic', color: CATALOG_COLOR.textMuted },
197
+ mono: { ...CATALOG_TEXT.code, wordBreak: 'break-word' } as TextStyle,
198
+ empty: { ...CATALOG_TEXT.caption, color: CATALOG_COLOR.textMuted },
188
199
  });
@@ -1,6 +1,6 @@
1
1
  import React, { useEffect, useMemo, useState } from 'react';
2
2
  import { View, Text, Pressable, StyleSheet, type LayoutChangeEvent } from 'react-native';
3
- import { CATALOG_COLOR, CATALOG_LAYOUT, CATALOG_RADIUS, CATALOG_SPACE, CATALOG_TYPE } from './tokens';
3
+ import { CATALOG_COLOR, CATALOG_LAYOUT, CATALOG_RADIUS, CATALOG_SPACE, CATALOG_TEXT } from './tokens';
4
4
  import { ComparisonGrid } from './ComparisonGrid';
5
5
  import { ComparisonGroups } from './ComparisonGroups';
6
6
  import { ComparisonList } from './ComparisonList';
@@ -334,7 +334,7 @@ export function SectionBlock<TId extends string>({
334
334
  }
335
335
 
336
336
  const styles = StyleSheet.create({
337
- breadcrumb: { fontSize: CATALOG_TYPE.sm, color: CATALOG_COLOR.textMuted },
337
+ breadcrumb: { ...CATALOG_TEXT.caption, color: CATALOG_COLOR.textMuted },
338
338
  titlebar: {
339
339
  flexDirection: 'row',
340
340
  alignItems: 'flex-start',
@@ -355,9 +355,9 @@ const styles = StyleSheet.create({
355
355
  borderColor: CATALOG_COLOR.borderStrong,
356
356
  backgroundColor: CATALOG_COLOR.surface,
357
357
  },
358
- osBadgeText: { fontSize: CATALOG_TYPE.xs, fontWeight: '700', letterSpacing: 0.4, color: CATALOG_COLOR.text },
359
- title: { fontSize: CATALOG_TYPE.pageTitle, fontWeight: '700', color: CATALOG_COLOR.text, marginBottom: 5 },
360
- desc: { fontSize: CATALOG_TYPE.md, lineHeight: 20, color: CATALOG_COLOR.textMuted, maxWidth: 700 },
358
+ osBadgeText: { ...CATALOG_TEXT.microLabel, color: CATALOG_COLOR.text },
359
+ title: { ...CATALOG_TEXT.pageTitle, color: CATALOG_COLOR.text, marginBottom: 5 },
360
+ desc: { ...CATALOG_TEXT.body, color: CATALOG_COLOR.textMuted, maxWidth: 700 },
361
361
  pager: { flexDirection: 'row', gap: 6, flexShrink: 0 },
362
362
  pagerButton: {
363
363
  width: CATALOG_LAYOUT.controlSize,
@@ -372,7 +372,7 @@ const styles = StyleSheet.create({
372
372
  pagerButtonActive: { backgroundColor: CATALOG_COLOR.surfacePressed },
373
373
  pagerButtonDisabled: { backgroundColor: CATALOG_COLOR.pageBackground },
374
374
  focusRing: { outlineWidth: CATALOG_LAYOUT.focusRingWidth, outlineStyle: 'solid', outlineColor: CATALOG_COLOR.focusRing },
375
- pagerGlyph: { fontSize: CATALOG_TYPE.lg, color: CATALOG_COLOR.text },
375
+ pagerGlyph: { ...CATALOG_TEXT.icon, color: CATALOG_COLOR.text },
376
376
  pagerGlyphDisabled: { color: CATALOG_COLOR.textMuted },
377
377
  blocks: { gap: CATALOG_LAYOUT.blockGap, marginBottom: CATALOG_LAYOUT.blockGap },
378
378
  blocksSide: { flexDirection: 'row', alignItems: 'flex-start' },
@@ -381,17 +381,11 @@ const styles = StyleSheet.create({
381
381
  frames: { flexDirection: 'row', flexWrap: 'wrap', gap: CATALOG_SPACE.xl, alignItems: 'flex-start', justifyContent: 'center' },
382
382
  frame: { maxWidth: '100%', gap: CATALOG_SPACE.sm },
383
383
  frameLabel: {
384
- fontSize: CATALOG_TYPE.tableHeader,
385
- fontWeight: '800',
386
- letterSpacing: 0.44,
387
- textTransform: 'uppercase',
384
+ ...CATALOG_TEXT.label,
388
385
  color: CATALOG_COLOR.textMuted,
389
386
  },
390
387
  blockLabel: {
391
- fontSize: CATALOG_TYPE.sm,
392
- fontWeight: '700',
393
- letterSpacing: 0.72,
394
- textTransform: 'uppercase',
388
+ ...CATALOG_TEXT.label,
395
389
  color: CATALOG_COLOR.text,
396
390
  marginBottom: CATALOG_LAYOUT.blockLabelGap,
397
391
  },
@@ -423,10 +417,10 @@ const styles = StyleSheet.create({
423
417
  borderBottomWidth: 1,
424
418
  borderBottomColor: CATALOG_COLOR.border,
425
419
  },
426
- tableCaptionText: { fontSize: CATALOG_TYPE.tableHeader, fontWeight: '800', letterSpacing: 0.44, color: CATALOG_COLOR.text },
420
+ tableCaptionText: { ...CATALOG_TEXT.captionStrong, color: CATALOG_COLOR.text },
427
421
  // Same cell padding `ComparisonList` uses: the requested width instead reaches the live demo
428
422
  // untouched through `tableBodyViewport`, the inner width-qualified group nested inside this body.
429
423
  tableBody: { padding: MATRIX_LAYOUT.cellPadding, flexGrow: 1, alignItems: 'center', justifyContent: 'flex-start' },
430
424
  tableBodyViewport: { maxWidth: '100%' },
431
- emptyText: { fontSize: CATALOG_TYPE.sm, fontStyle: 'italic', color: CATALOG_COLOR.textMuted },
425
+ emptyText: { ...CATALOG_TEXT.caption, color: CATALOG_COLOR.textMuted },
432
426
  });
@@ -1,6 +1,6 @@
1
1
  import { View, Text, StyleSheet } from 'react-native';
2
2
  import { TokenRow, TokenRowGroup } from './TokenRow';
3
- import { CATALOG_TYPE, CATALOG_COLOR, CATALOG_SPACE, CATALOG_RADIUS } from './tokens';
3
+ import { CATALOG_TEXT, CATALOG_COLOR, CATALOG_SPACE, CATALOG_RADIUS } from './tokens';
4
4
 
5
5
  /**
6
6
  * Renders a spacing scale as a stack of `TokenRow`s, each showing a step's name, a bar sized to its
@@ -39,7 +39,7 @@ const styles = StyleSheet.create({
39
39
  // Wider gap than a plain gap-only stack — one row's use-note shouldn't crowd the next row's label.
40
40
  tokenStack: { gap: CATALOG_SPACE.lg },
41
41
  row: { flexDirection: 'row', alignItems: 'center', gap: CATALOG_SPACE.md },
42
- label: { width: 48, fontSize: CATALOG_TYPE.sm, fontWeight: '700', color: CATALOG_COLOR.text },
42
+ label: { width: 48, ...CATALOG_TEXT.captionStrong, color: CATALOG_COLOR.text },
43
43
  bar: { height: 12, borderRadius: CATALOG_RADIUS.sm, backgroundColor: CATALOG_COLOR.accent },
44
- value: { fontSize: CATALOG_TYPE.xs, color: CATALOG_COLOR.textMuted },
44
+ value: { ...CATALOG_TEXT.micro, color: CATALOG_COLOR.textMuted },
45
45
  });
@@ -1,5 +1,5 @@
1
1
  import { View, Text, StyleSheet } from 'react-native';
2
- import { CATALOG_TYPE, CATALOG_COLOR, CATALOG_SPACE, CATALOG_RADIUS } from './tokens';
2
+ import { CATALOG_TEXT, CATALOG_COLOR, CATALOG_SPACE, CATALOG_RADIUS } from './tokens';
3
3
 
4
4
  /** One token swatch: its rendered value (a colour chip) plus name/value as data — the shared shape
5
5
  * behind every Colors gallery (this framework's own, and any host app's, e.g. the Native App DS
@@ -35,6 +35,6 @@ const styles = StyleSheet.create({
35
35
  borderWidth: StyleSheet.hairlineWidth,
36
36
  borderColor: CATALOG_COLOR.border,
37
37
  },
38
- name: { fontSize: CATALOG_TYPE.sm, fontWeight: '700', color: CATALOG_COLOR.text },
39
- value: { fontSize: CATALOG_TYPE.xs, color: CATALOG_COLOR.textMuted },
38
+ name: { ...CATALOG_TEXT.captionStrong, color: CATALOG_COLOR.text },
39
+ value: { ...CATALOG_TEXT.micro, color: CATALOG_COLOR.textMuted },
40
40
  });
@@ -1,6 +1,6 @@
1
1
  import React, { useRef, useState } from 'react';
2
2
  import { View, Text, StyleSheet, type LayoutChangeEvent } from 'react-native';
3
- import { CATALOG_COLOR, CATALOG_LAYOUT, CATALOG_RADIUS, CATALOG_SPACE, CATALOG_TYPE } from './tokens';
3
+ import { CATALOG_COLOR, CATALOG_LAYOUT, CATALOG_RADIUS, CATALOG_SPACE, CATALOG_TEXT } from './tokens';
4
4
  import { sectionColumns, tileGeometry, TOKEN_LAYOUT_GAP, TOKEN_SECTION_MIN_WIDTH } from './tokenLayout';
5
5
  import type { TokenSection } from './types';
6
6
 
@@ -78,13 +78,10 @@ export function TokenTile({ name, value, note, children }: { name: string; value
78
78
  const styles = StyleSheet.create({
79
79
  sections: { flexDirection: 'row', flexWrap: 'wrap', gap: TOKEN_LAYOUT_GAP, rowGap: CATALOG_LAYOUT.blockGap, alignItems: 'flex-start' },
80
80
  sectionLabel: {
81
- fontSize: CATALOG_TYPE.sm,
82
- fontWeight: '700',
83
- letterSpacing: 0.72,
84
- textTransform: 'uppercase',
81
+ ...CATALOG_TEXT.label,
85
82
  color: CATALOG_COLOR.text,
86
83
  },
87
- sectionDesc: { fontSize: CATALOG_TYPE.sm, color: CATALOG_COLOR.textMuted, marginTop: CATALOG_SPACE.xs },
84
+ sectionDesc: { ...CATALOG_TEXT.caption, color: CATALOG_COLOR.textMuted, marginTop: CATALOG_SPACE.xs },
88
85
  card: {
89
86
  marginTop: CATALOG_LAYOUT.blockLabelGap,
90
87
  backgroundColor: CATALOG_COLOR.surface,
@@ -97,7 +94,7 @@ const styles = StyleSheet.create({
97
94
  grid: { flexDirection: 'row', flexWrap: 'wrap', gap: TOKEN_LAYOUT_GAP },
98
95
  tile: { gap: CATALOG_SPACE.xs },
99
96
  tilePreview: { minHeight: 56, justifyContent: 'center', marginBottom: CATALOG_SPACE.xs },
100
- tileName: { fontSize: CATALOG_TYPE.sm, fontWeight: '700', color: CATALOG_COLOR.text },
101
- tileValue: { fontSize: CATALOG_TYPE.xs, color: CATALOG_COLOR.textMuted },
102
- tileNote: { fontSize: CATALOG_TYPE.xs, color: CATALOG_COLOR.textMuted, lineHeight: 16 },
97
+ tileName: { ...CATALOG_TEXT.captionStrong, color: CATALOG_COLOR.text },
98
+ tileValue: { ...CATALOG_TEXT.micro, color: CATALOG_COLOR.textMuted },
99
+ tileNote: { ...CATALOG_TEXT.micro, color: CATALOG_COLOR.textMuted },
103
100
  });
@@ -1,6 +1,6 @@
1
1
  import React, { createContext, useCallback, useContext, useMemo, useState } from 'react';
2
2
  import { View, Text, StyleSheet, type LayoutChangeEvent } from 'react-native';
3
- import { CATALOG_TYPE, CATALOG_COLOR, CATALOG_SPACE } from './tokens';
3
+ import { CATALOG_TEXT, CATALOG_COLOR, CATALOG_SPACE } from './tokens';
4
4
 
5
5
  type Lane = { width: number; report: (width: number) => void };
6
6
 
@@ -104,5 +104,5 @@ const styles = StyleSheet.create({
104
104
  borderBottomWidth: 1,
105
105
  borderBottomColor: CATALOG_COLOR.border,
106
106
  },
107
- use: { fontSize: CATALOG_TYPE.sm, color: CATALOG_COLOR.textMuted },
107
+ use: { ...CATALOG_TEXT.caption, color: CATALOG_COLOR.textMuted },
108
108
  });
@@ -1,6 +1,6 @@
1
1
  import { View, Text, StyleSheet, type TextStyle } from 'react-native';
2
2
  import { TokenRow, TokenRowGroup } from './TokenRow';
3
- import { CATALOG_TYPE, CATALOG_COLOR, CATALOG_SPACE } from './tokens';
3
+ import { CATALOG_TEXT, CATALOG_COLOR, CATALOG_SPACE } from './tokens';
4
4
 
5
5
  /**
6
6
  * Renders a type scale as a stack of `TokenRow`s, each showing a step's name (rendered at its own
@@ -44,5 +44,5 @@ const styles = StyleSheet.create({
44
44
  // two read as one unit at a glance.
45
45
  row: { flexDirection: 'row', alignItems: 'baseline', gap: CATALOG_SPACE.sm },
46
46
  sample: { color: CATALOG_COLOR.text },
47
- meta: { fontSize: CATALOG_TYPE.xs, color: CATALOG_COLOR.textMuted },
47
+ meta: { ...CATALOG_TEXT.micro, color: CATALOG_COLOR.textMuted },
48
48
  });