@krapwoo/ds-viewer 0.2.0 → 0.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 (52) hide show
  1. package/README.md +151 -0
  2. package/config/index.ts +4 -2
  3. package/dist/cli/agentsFile.js +31 -0
  4. package/dist/cli/dev.js +312 -15
  5. package/dist/cli/doctor.js +502 -0
  6. package/dist/cli/endpoint.js +142 -0
  7. package/dist/cli/explain.js +151 -0
  8. package/dist/cli/githubAction.js +65 -0
  9. package/dist/cli/init.js +9 -5
  10. package/dist/cli/kitDiff.js +132 -0
  11. package/dist/cli/kitRoot.js +20 -0
  12. package/dist/cli/main.js +123 -15
  13. package/dist/cli/migrate.js +30 -0
  14. package/dist/cli/migrateEntry.js +19 -0
  15. package/dist/cli/migrations/index.js +14 -0
  16. package/dist/cli/migrations/types.js +9 -0
  17. package/dist/cli/packageManager.js +29 -0
  18. package/dist/cli/packageVersion.js +24 -0
  19. package/dist/cli/pageIndex.js +27 -1
  20. package/dist/cli/props.js +4 -3
  21. package/dist/cli/semver.js +26 -0
  22. package/dist/cli/staticPage.js +356 -0
  23. package/dist/cli/sync.js +11 -4
  24. package/dist/cli/update.js +93 -0
  25. package/dist/cli/updateCheck.js +143 -0
  26. package/dist/cli/updatePlan.js +202 -0
  27. package/dist/cli/workspace.js +10 -5
  28. package/dist/native/catalog/catalogNavigation.js +129 -0
  29. package/dist/native/catalog/comparison.js +283 -0
  30. package/dist/native/catalog/tokens.js +134 -0
  31. package/dist/native/catalog/types.js +1 -0
  32. package/native/catalog/CatalogShell.tsx +105 -11
  33. package/native/catalog/CatalogSidebar.tsx +58 -2
  34. package/native/catalog/ComparisonGrid.tsx +9 -7
  35. package/native/catalog/SectionBlock.tsx +5 -0
  36. package/native/catalog/SpacingScaleGallery.tsx +1 -1
  37. package/native/catalog/UpdatePanel.tsx +556 -0
  38. package/native/catalog/catalogNavigation.ts +70 -1
  39. package/native/catalog/comparison.ts +63 -5
  40. package/native/catalog/index.ts +5 -1
  41. package/native/catalog/pageApi.ts +11 -2
  42. package/native/catalog/tokens.ts +15 -0
  43. package/native/catalog/types.ts +19 -5
  44. package/native/catalog/updatePanelState.ts +74 -0
  45. package/package.json +5 -1
  46. package/starter-kit/components/Avatar/Avatar.catalog.tsx +4 -22
  47. package/starter-kit/components/Badge/Badge.catalog.tsx +15 -23
  48. package/starter-kit/components/Banner/Banner.tsx +1 -1
  49. package/starter-kit/components/BottomSheet/BottomSheet.tsx +2 -2
  50. package/starter-kit/components/Button/Button.catalog.tsx +15 -29
  51. package/starter-kit/components/Dialog/Dialog.tsx +2 -2
  52. package/starter-kit/components/Pill/Pill.catalog.tsx +12 -26
@@ -3,7 +3,7 @@ import { View, Text, ScrollView, Pressable, StyleSheet, Image } from 'react-nati
3
3
  import type { ImageSourcePropType, LayoutChangeEvent, NativeSyntheticEvent, ImageLoadEventData } from 'react-native';
4
4
  import { CATALOG_COLOR, CATALOG_LAYOUT, CATALOG_RADIUS, CATALOG_SPACE, CATALOG_TYPE } from './tokens';
5
5
  import { logoLayout } from './logoLayout';
6
- import { filterGroups, hashForId } from './catalogNavigation';
6
+ import { filterGroups, hashForId, UPDATE_PAGE_ID } from './catalogNavigation';
7
7
  import type { NavGroup } from './types';
8
8
  import { CatalogSearchInput } from './CatalogSearchInput';
9
9
 
@@ -43,6 +43,32 @@ function NavItem<TId extends string>({ id, active, onPress }: { id: TId; active:
43
43
  );
44
44
  }
45
45
 
46
+ function FooterLink({ label, active, onPress }: { label: string; active: boolean; onPress: () => void }) {
47
+ const [hovered, setHovered] = useState(false);
48
+ const [focused, setFocused] = useState(false);
49
+ return (
50
+ <Pressable
51
+ onPress={onPress}
52
+ onHoverIn={() => setHovered(true)}
53
+ onHoverOut={() => setHovered(false)}
54
+ onFocus={() => setFocused(true)}
55
+ onBlur={() => setFocused(false)}
56
+ accessibilityRole="link"
57
+ accessibilityState={{ selected: active }}
58
+ {...({ href: hashForId(UPDATE_PAGE_ID), ...(active ? { 'aria-current': 'page' } : null) } as Record<string, unknown>)}
59
+ style={({ pressed }) => [
60
+ styles.footerLink,
61
+ (pressed || hovered) && styles.footerLinkHover,
62
+ active && styles.footerLinkActive,
63
+ focused && styles.focusRing,
64
+ ]}
65
+ >
66
+ <View style={styles.footerDot} />
67
+ <Text style={[styles.footerLabel, active && styles.footerLabelActive]}>{label}</Text>
68
+ </Pressable>
69
+ );
70
+ }
71
+
46
72
  /**
47
73
  * Catalog navigation: app name, caption, a filter field, and one link per page under grouped
48
74
  * headings. Selecting a link opens that page (CatalogShell owns which page is shown). The filter
@@ -55,6 +81,7 @@ export function CatalogSidebar<TId extends string>({
55
81
  groups,
56
82
  active,
57
83
  onPress,
84
+ footer,
58
85
  }: {
59
86
  logo: string;
60
87
  /** Optional logo image, validated and bundled by `cli/workspace.ts` from the project's `logo`
@@ -64,8 +91,12 @@ export function CatalogSidebar<TId extends string>({
64
91
  logoImageSource?: ImageSourcePropType;
65
92
  caption: string;
66
93
  groups: NavGroup<TId>[];
67
- active: TId | undefined;
94
+ active: string | undefined;
68
95
  onPress: (id: TId) => void;
96
+ /** The quiet update-notice link below the nav list (design §5's footer line), or `undefined`
97
+ * when there is no update to show. `active` is true while the update page itself is open — it
98
+ * gets the same active styling a selected nav item would. */
99
+ footer?: { label: string; active: boolean; onPress: () => void };
69
100
  }) {
70
101
  const [query, setQuery] = useState('');
71
102
  // A bundled local image (the only kind `cli/workspace.ts` ever produces — see its doc comment
@@ -165,6 +196,11 @@ export function CatalogSidebar<TId extends string>({
165
196
  </View>
166
197
  ))}
167
198
  </ScrollView>
199
+ {footer && (
200
+ <View style={styles.footerContainer}>
201
+ <FooterLink label={footer.label} active={footer.active} onPress={footer.onPress} />
202
+ </View>
203
+ )}
168
204
  </View>
169
205
  );
170
206
  }
@@ -193,6 +229,26 @@ const styles = StyleSheet.create({
193
229
  inlineHeaderTop: { alignItems: 'flex-start' },
194
230
  inlineText: { flex: 1, minWidth: 0 },
195
231
  empty: { fontSize: CATALOG_TYPE.sm, color: CATALOG_COLOR.textMuted, paddingHorizontal: CATALOG_LAYOUT.navItemPaddingX, paddingVertical: 8 },
232
+ footerContainer: {
233
+ borderTopWidth: 1,
234
+ borderTopColor: CATALOG_COLOR.borderHairline,
235
+ paddingHorizontal: CATALOG_LAYOUT.sidebarPaddingX,
236
+ paddingTop: 10,
237
+ paddingBottom: 14,
238
+ },
239
+ footerLink: {
240
+ flexDirection: 'row',
241
+ alignItems: 'center',
242
+ gap: CATALOG_SPACE.sm,
243
+ minHeight: CATALOG_LAYOUT.controlSize,
244
+ paddingHorizontal: 10,
245
+ borderRadius: CATALOG_RADIUS.sm,
246
+ },
247
+ footerLinkHover: { backgroundColor: CATALOG_COLOR.surfacePressed },
248
+ footerLinkActive: { backgroundColor: CATALOG_COLOR.accentSubtle },
249
+ footerDot: { width: 8, height: 8, borderRadius: 4, backgroundColor: CATALOG_COLOR.accent, flexShrink: 0 },
250
+ footerLabel: { fontSize: CATALOG_TYPE.sm, color: CATALOG_COLOR.textMuted },
251
+ footerLabelActive: { color: CATALOG_COLOR.accent, fontWeight: '700' },
196
252
  groupLabel: {
197
253
  fontSize: CATALOG_TYPE.xs,
198
254
  fontWeight: '800',
@@ -1,7 +1,7 @@
1
1
  import React from 'react';
2
2
  import { View, Text, ScrollView, StyleSheet } from 'react-native';
3
3
  import { CATALOG_COLOR, CATALOG_RADIUS, CATALOG_TYPE } from './tokens';
4
- import { COLUMN_MIN_WIDTH, MATRIX_LAYOUT, cellKey, gridWidthBounds, indexCells, validateComparison } from './comparison';
4
+ import { COLUMN_MIN_WIDTH, MATRIX_LAYOUT, axisItems, cellKey, gridWidthBounds, indexCells, validateComparison } from './comparison';
5
5
  import type { ComparisonDef, SpecimenSize } from './types';
6
6
 
7
7
  /**
@@ -14,7 +14,9 @@ export function ComparisonGrid({ def, size, sectionId }: { def: ComparisonDef; s
14
14
  for (const issue of validateComparison({ ...def, size })) console.warn(`[Catalog] ${sectionId}: ${issue}`);
15
15
  }
16
16
  const cells = indexCells(def);
17
- const bounds = gridWidthBounds(def.columns.length, size);
17
+ const rows = axisItems(def.rows);
18
+ const columns = axisItems(def.columns);
19
+ const bounds = gridWidthBounds(columns.length, size);
18
20
  const column = {
19
21
  flexGrow: 1,
20
22
  flexShrink: 1,
@@ -22,7 +24,7 @@ export function ComparisonGrid({ def, size, sectionId }: { def: ComparisonDef; s
22
24
  minWidth: COLUMN_MIN_WIDTH[size],
23
25
  maxWidth: MATRIX_LAYOUT.columnMaxWidth,
24
26
  };
25
- const lastColumn = def.columns.length - 1;
27
+ const lastColumn = columns.length - 1;
26
28
 
27
29
  return (
28
30
  <ScrollView horizontal style={styles.scroller} contentContainerStyle={styles.scrollContent}>
@@ -35,18 +37,18 @@ export function ComparisonGrid({ def, size, sectionId }: { def: ComparisonDef; s
35
37
  <View role="columnheader" style={[styles.cell, styles.rowHeader, styles.headerCell]}>
36
38
  <Text style={styles.headerText}>{def.rowLabel}</Text>
37
39
  </View>
38
- {def.columns.map((c, ci) => (
40
+ {columns.map((c, ci) => (
39
41
  <View key={c.key} role="columnheader" style={[styles.cell, column, styles.headerCell, ci === lastColumn && styles.lastColumn]}>
40
42
  <Text style={styles.headerText}>{c.label}</Text>
41
43
  </View>
42
44
  ))}
43
45
  </View>
44
- {def.rows.map((row, ri) => (
45
- <View key={row.key} role="row" style={[styles.row, ri === def.rows.length - 1 && styles.lastRow]}>
46
+ {rows.map((row, ri) => (
47
+ <View key={row.key} role="row" style={[styles.row, ri === rows.length - 1 && styles.lastRow]}>
46
48
  <View role="rowheader" style={[styles.cell, styles.rowHeader, styles.bodyRow]}>
47
49
  <Text style={styles.rowHeaderText}>{row.label}</Text>
48
50
  </View>
49
- {def.columns.map((c, ci) => {
51
+ {columns.map((c, ci) => {
50
52
  const cell = cells.get(cellKey(row.key, c.key));
51
53
  return (
52
54
  <View key={c.key} role="cell" style={[styles.cell, column, styles.bodyRow, styles.specimenCell, ci === lastColumn && styles.lastColumn]}>
@@ -213,6 +213,7 @@ export function SectionBlock<TId extends string>({
213
213
  def,
214
214
  groupLabel,
215
215
  breadcrumbRoot,
216
+ banner,
216
217
  pager,
217
218
  headingRef,
218
219
  headingLevel = 1,
@@ -221,6 +222,9 @@ export function SectionBlock<TId extends string>({
221
222
  def: SectionDef<TId>;
222
223
  groupLabel?: string;
223
224
  breadcrumbRoot?: string;
225
+ /** The major-update banner (`CatalogShell`'s own `MajorBanner`), rendered between the breadcrumb
226
+ * and the title — the approved mockup's own `PAGE_BG` order: crumb, then banner, then title. */
227
+ banner?: React.ReactNode;
224
228
  pager?: SectionPager<TId>;
225
229
  headingRef?: React.Ref<View>;
226
230
  headingLevel?: 1 | 2;
@@ -238,6 +242,7 @@ export function SectionBlock<TId extends string>({
238
242
  {groupLabel && (
239
243
  <Text style={styles.breadcrumb}>{breadcrumbRoot ? `${breadcrumbRoot} / ${groupLabel}` : groupLabel}</Text>
240
244
  )}
245
+ {banner}
241
246
  <View style={styles.titlebar}>
242
247
  <View style={styles.titleText}>
243
248
  {/* The focus target is the heading itself, so assistive tech announces its role and level. */}
@@ -8,7 +8,7 @@ import { CATALOG_TYPE, CATALOG_COLOR, CATALOG_SPACE, CATALOG_RADIUS } from './to
8
8
  * framework's own, and any host app's). Generic over the step-name type so it works for any scale
9
9
  * (the host app's `DS_SPACING`, this framework's own `CATALOG_SPACE`, or a third-party one).
10
10
  */
11
- export function SpacingScaleGallery<TStep extends string>({
11
+ export function SpacingScaleGallery<TStep extends string | number>({
12
12
  steps,
13
13
  values,
14
14
  useNotes,