@retray-dev/ui-kit 10.0.0 → 10.1.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.
package/COMPONENTS.md CHANGED
@@ -1,4 +1,4 @@
1
- # @retray-dev/ui-kit — Component Reference (v10.0.0)
1
+ # @retray-dev/ui-kit — Component Reference (v10.1.0)
2
2
 
3
3
  This file is the AI reference for this package. Add all three lines below to your project's `CLAUDE.md` to give Claude full context — components, setup guide, and usage examples:
4
4
 
@@ -252,19 +252,19 @@ These are the only values you need to supply when customizing the theme. The lib
252
252
  | Token | Light Default | Dark Default | Semantic Role |
253
253
  |-------|--------------|--------------|---------------|
254
254
  | `background` | `#ffffff` | `#0f0f0f` | Screen / page background |
255
- | `foreground` | `#222222` | `#fafafa` | Primary text — deep near-black, not pure black |
255
+ | `foreground` | `#1a1a1a` | `#fafafa` | Primary text — deep near-black, not pure black |
256
256
  | `card` | `#ffffff` | `#1c1c1c` | Card / elevated surface background |
257
257
  | `primary` | `#1a1a1a` | `#fafafa` | Primary action (buttons, selected states, active indicators) |
258
258
  | `primaryForeground` | `#ffffff` | `#0f0f0f` | Text/icon placed on primary-colored backgrounds |
259
259
  | `border` | `#dddddd` | `#303030` | Borders, dividers, input outlines |
260
- | `destructive` | `#e53935` | `#ef5350` | Error / danger / delete actions |
260
+ | `destructive` | `#c72828` | `#ef5350` | Error / danger / delete actions |
261
261
  | `destructiveForeground` | `#ffffff` | `#ffffff` | Text/icon on destructive backgrounds |
262
262
  | `success` | `#1a7a45` | `#2e7d52` | Success / confirmation states |
263
263
  | `successForeground` | `#ffffff` | `#ffffff` | Text/icon on success backgrounds |
264
- | `warning` | `#e67e00` | `#f57c00` | Warning / caution states |
265
- | `warningForeground` | `#ffffff` | `#ffffff` | Text/icon on warning backgrounds |
264
+ | `warning` | `#9a5200` | `#f5a623` | Warning / caution states |
265
+ | `warningForeground` | `#ffffff` | `#0f0f0f` | Text/icon on warning backgrounds |
266
266
  | `overlay` *(optional)* | `rgba(0,0,0,0.45)` | `rgba(0,0,0,0.45)` | Backdrop/overlay color behind sheets and dialogs |
267
- | `accent` *(optional)* | same as `primary` | same as `primary` | Secondary brand accent (e.g. Airbnb coral). Falls back to `primary` |
267
+ | `accent` *(optional)* | `#d4561d` | `#e87645` | Secondary brand accent (e.g. Airbnb coral). Falls back to `primary` |
268
268
  | `accentForeground` *(optional)* | same as `primaryForeground` | same as `primaryForeground` | Text/icon on accent backgrounds. Falls back to `primaryForeground` |
269
269
 
270
270
  ### Derived Tokens (ResolvedColors) — read-only via useTheme().colors
@@ -273,8 +273,8 @@ The full palette components consume. Never supply these directly — they are co
273
273
 
274
274
  | Token | Derived From | Purpose |
275
275
  |-------|-------------|---------|
276
- | `foregroundSubtle` | `foreground` @ ~55% | Body text, subtitles, secondary content |
277
- | `foregroundMuted` | `foreground` @ ~38% | Captions, timestamps, placeholders |
276
+ | `foregroundSubtle` | `foreground` @ ~70% | Body text, subtitles, secondary content |
277
+ | `foregroundMuted` | `foreground` @ ~62% | Captions, timestamps, placeholders |
278
278
  | `surface` | `background` slightly off-canvas | Chip backgrounds, input fills, tag backgrounds, skeleton |
279
279
  | `surfaceStrong` | `background` stronger offset | Pressed/hover fill states |
280
280
  | `destructiveTint` | `destructive` blended to bg | Alert banner background, toast background |
@@ -1926,7 +1926,7 @@ const [accepted, setAccepted] = useState(false)
1926
1926
 
1927
1927
  **Dimensions:** Track 52×30px (pill), Thumb 24×24px with 3px offset.
1928
1928
 
1929
- **Animation:** Thumb translates via spring; track color transitions via opacity (150ms).
1929
+ **Animation:** Thumb translates via spring (`SPRINGS.elastic`); track color and border animate via `EaseView` `COLOR_TRANSITION`; icons crossfade via `OPACITY_TRANSITION`. All declarative — UI thread.
1930
1930
 
1931
1931
  **Haptics:** `selectionAsync` on toggle.
1932
1932
 
@@ -2277,7 +2277,7 @@ const [tab, setTab] = useState('profile')
2277
2277
  ```ts
2278
2278
  {
2279
2279
  value: string
2280
- trigger: string
2280
+ trigger: string | ReactNode
2281
2281
  content: ReactNode
2282
2282
  iconName?: string // Icon name from @expo/vector-icons
2283
2283
  icon?: ReactNode // Custom icon node
@@ -2285,7 +2285,7 @@ const [tab, setTab] = useState('profile')
2285
2285
  }
2286
2286
  ```
2287
2287
 
2288
- **Animation:** `react-native-reanimated` `withTiming` (220ms) for height and chevron rotation (180°). Press scale uses `withSpring`. Runs on UI thread at 60fps.
2288
+ **Animation:** `react-native-reanimated` `withTiming` (240ms expand / 200ms collapse) for height and chevron rotation (180°). Runs on UI thread at 60fps.
2289
2289
 
2290
2290
  **Haptics:** `selectionAsync` on toggle.
2291
2291
 
@@ -2693,11 +2693,13 @@ dismiss(id)
2693
2693
  |------|------|---------|-------|
2694
2694
  | visible | `boolean` | required | Controls dialog visibility |
2695
2695
  | title | `string` | required | Dialog heading |
2696
- | description | `string` | — | Supporting text describe what exactly will happen |
2696
+ | subtitle | `string` | — | Secondary text below title |
2697
+ | description | `string` | — | **Deprecated** — use `subtitle` instead |
2697
2698
  | confirmLabel | `string` | `'Confirm'` | Confirm button text |
2698
2699
  | cancelLabel | `string` | `'Cancel'` | Cancel button text |
2699
2700
  | confirmVariant | `'primary' \| 'destructive'` | `'primary'` | Use `'destructive'` for delete/remove actions |
2700
2701
  | loading | `boolean` | `false` | Show spinner in confirm button and disable it (for async `onConfirm`) |
2702
+ | showCloseButton | `boolean` | `false` | Show an X close button in the top-right corner |
2701
2703
  | onConfirm | `() => void` | required | Called when confirm is tapped |
2702
2704
  | onCancel | `() => void` | required | Called when cancel is tapped or backdrop pressed |
2703
2705
 
@@ -3766,7 +3768,7 @@ export default function TabLayout() {
3766
3768
  | onClose | `() => void` | required | — |
3767
3769
  | initialIndex | `number` | `0` | Page to open on |
3768
3770
 
3769
- **Behavior:** pinch to zoom (max 3×), double-tap to toggle 2.5× zoom, pan while zoomed. Paging locks automatically while a page is zoomed in. `PagerDots` shown when there is more than one image.
3771
+ **Behavior:** pinch to zoom (max 3×), double-tap to toggle 2.5× zoom, pan while zoomed. Paging locks automatically while a page is zoomed in. Swipe down to dismiss (drag down or fling; backdrop fades proportionally). `PagerDots` shown when there is more than one image.
3770
3772
 
3771
3773
  **Example:**
3772
3774
  ```tsx
package/CONSUMER.md CHANGED
@@ -1,4 +1,4 @@
1
- # @retray-dev/ui-kit — Consumer Setup Guide (v9.2.0)
1
+ # @retray-dev/ui-kit — Consumer Setup Guide (v10.1.0)
2
2
 
3
3
  > **For AI assistants (Claude Code):** Add all three lines below to your project's `CLAUDE.md` so Claude has full context about this UI kit:
4
4
  > ```markdown
@@ -3,7 +3,7 @@ import { ViewStyle } from 'react-native';
3
3
 
4
4
  interface AccordionItem {
5
5
  value: string;
6
- trigger: string;
6
+ trigger: string | React.ReactNode;
7
7
  content: React.ReactNode;
8
8
  /** Icon name from @expo/vector-icons rendered left of trigger. */
9
9
  iconName?: string;
@@ -3,7 +3,7 @@ import { ViewStyle } from 'react-native';
3
3
 
4
4
  interface AccordionItem {
5
5
  value: string;
6
- trigger: string;
6
+ trigger: string | React.ReactNode;
7
7
  content: React.ReactNode;
8
8
  /** Icon name from @expo/vector-icons rendered left of trigger. */
9
9
  iconName?: string;
package/dist/Accordion.js CHANGED
@@ -302,9 +302,9 @@ function AccordionItemComponent({
302
302
  },
303
303
  accessibilityRole: "button",
304
304
  accessibilityState: { expanded: isOpen },
305
- accessibilityLabel: item.trigger
305
+ accessibilityLabel: typeof item.trigger === "string" ? item.trigger : void 0
306
306
  },
307
- /* @__PURE__ */ React3__default.default.createElement(reactNative.View, { style: styles.triggerContent }, resolvedIcon ? /* @__PURE__ */ React3__default.default.createElement(reactNative.View, { style: styles.icon }, resolvedIcon) : null, /* @__PURE__ */ React3__default.default.createElement(reactNative.Text, { style: [styles.triggerText, { color: colors.foreground }], allowFontScaling: true }, item.trigger)),
307
+ /* @__PURE__ */ React3__default.default.createElement(reactNative.View, { style: styles.triggerContent }, resolvedIcon ? /* @__PURE__ */ React3__default.default.createElement(reactNative.View, { style: styles.icon }, resolvedIcon) : null, typeof item.trigger === "string" ? /* @__PURE__ */ React3__default.default.createElement(reactNative.Text, { style: [styles.triggerText, { color: colors.foreground }], allowFontScaling: true }, item.trigger) : item.trigger),
308
308
  /* @__PURE__ */ React3__default.default.createElement(Animated__default.default.View, { style: [styles.chevron, rotationStyle] }, /* @__PURE__ */ React3__default.default.createElement(vectorIcons.Entypo, { name: "chevron-down", size: 18, color: colors.foregroundMuted }))
309
309
  ), /* @__PURE__ */ React3__default.default.createElement(Animated__default.default.View, { style: bodyStyle }, /* @__PURE__ */ React3__default.default.createElement(
310
310
  reactNative.View,
@@ -1,4 +1,4 @@
1
- export { Accordion } from './chunk-O3HA6TYM.mjs';
1
+ export { Accordion } from './chunk-DJ7RN37L.mjs';
2
2
  import './chunk-EJ7ZPXOH.mjs';
3
3
  import './chunk-DVK4G2GT.mjs';
4
4
  import './chunk-T7XZ7H7Y.mjs';
@@ -3,15 +3,20 @@ import React from 'react';
3
3
  interface ConfirmDialogProps {
4
4
  visible: boolean;
5
5
  title: string;
6
+ /** Secondary text below title. */
7
+ subtitle?: string;
8
+ /** @deprecated Use `subtitle` instead. */
6
9
  description?: string;
7
10
  confirmLabel?: string;
8
11
  cancelLabel?: string;
9
12
  confirmVariant?: 'primary' | 'destructive';
10
13
  /** Show a loading spinner in the confirm button (e.g. while async action completes). */
11
14
  loading?: boolean;
15
+ /** Show an X close button in the top-right corner. */
16
+ showCloseButton?: boolean;
12
17
  onConfirm: () => void;
13
18
  onCancel: () => void;
14
19
  }
15
- declare function ConfirmDialog({ visible, title, description, confirmLabel, cancelLabel, confirmVariant, loading, onConfirm, onCancel, }: ConfirmDialogProps): React.JSX.Element;
20
+ declare function ConfirmDialog({ visible, title, subtitle, description, confirmLabel, cancelLabel, confirmVariant, loading, showCloseButton, onConfirm, onCancel, }: ConfirmDialogProps): React.JSX.Element;
16
21
 
17
22
  export { ConfirmDialog, type ConfirmDialogProps };
@@ -3,15 +3,20 @@ import React from 'react';
3
3
  interface ConfirmDialogProps {
4
4
  visible: boolean;
5
5
  title: string;
6
+ /** Secondary text below title. */
7
+ subtitle?: string;
8
+ /** @deprecated Use `subtitle` instead. */
6
9
  description?: string;
7
10
  confirmLabel?: string;
8
11
  cancelLabel?: string;
9
12
  confirmVariant?: 'primary' | 'destructive';
10
13
  /** Show a loading spinner in the confirm button (e.g. while async action completes). */
11
14
  loading?: boolean;
15
+ /** Show an X close button in the top-right corner. */
16
+ showCloseButton?: boolean;
12
17
  onConfirm: () => void;
13
18
  onCancel: () => void;
14
19
  }
15
- declare function ConfirmDialog({ visible, title, description, confirmLabel, cancelLabel, confirmVariant, loading, onConfirm, onCancel, }: ConfirmDialogProps): React.JSX.Element;
20
+ declare function ConfirmDialog({ visible, title, subtitle, description, confirmLabel, cancelLabel, confirmVariant, loading, showCloseButton, onConfirm, onCancel, }: ConfirmDialogProps): React.JSX.Element;
16
21
 
17
22
  export { ConfirmDialog, type ConfirmDialogProps };
@@ -2,7 +2,7 @@
2
2
 
3
3
  var React3 = require('react');
4
4
  var reactNative = require('react-native');
5
- var bottomSheet = require('@gorhom/bottom-sheet');
5
+ var BottomSheet = require('@gorhom/bottom-sheet');
6
6
  var vectorIcons = require('@expo/vector-icons');
7
7
  var reactNativeSizeMatters = require('react-native-size-matters');
8
8
  var AntDesign = require('@expo/vector-icons/AntDesign');
@@ -17,6 +17,7 @@ var reactNativeReanimated = require('react-native-reanimated');
17
17
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
18
18
 
19
19
  var React3__default = /*#__PURE__*/_interopDefault(React3);
20
+ var BottomSheet__default = /*#__PURE__*/_interopDefault(BottomSheet);
20
21
  var AntDesign__default = /*#__PURE__*/_interopDefault(AntDesign);
21
22
  var Entypo__default = /*#__PURE__*/_interopDefault(Entypo);
22
23
  var Feather__default = /*#__PURE__*/_interopDefault(Feather);
@@ -455,26 +456,29 @@ var styles = reactNative.StyleSheet.create({
455
456
  function ConfirmDialog({
456
457
  visible,
457
458
  title,
459
+ subtitle,
458
460
  description,
459
461
  confirmLabel = "Confirm",
460
462
  cancelLabel = "Cancel",
461
463
  confirmVariant = "primary",
462
464
  loading = false,
465
+ showCloseButton = false,
463
466
  onConfirm,
464
467
  onCancel
465
468
  }) {
466
469
  const { colors } = useTheme();
467
470
  const ref = React3.useRef(null);
471
+ const effectiveSubtitle = subtitle ?? description;
468
472
  React3.useEffect(() => {
469
473
  if (visible) {
470
474
  impactMedium();
471
- ref.current?.present();
475
+ ref.current?.snapToIndex(0);
472
476
  } else {
473
- ref.current?.dismiss();
477
+ ref.current?.close();
474
478
  }
475
479
  }, [visible]);
476
480
  const renderBackdrop = (props) => /* @__PURE__ */ React3__default.default.createElement(
477
- bottomSheet.BottomSheetBackdrop,
481
+ BottomSheet.BottomSheetBackdrop,
478
482
  {
479
483
  ...props,
480
484
  disappearsOnIndex: -1,
@@ -483,17 +487,30 @@ function ConfirmDialog({
483
487
  }
484
488
  );
485
489
  return /* @__PURE__ */ React3__default.default.createElement(
486
- bottomSheet.BottomSheetModal,
490
+ BottomSheet__default.default,
487
491
  {
488
492
  ref,
493
+ index: -1,
494
+ onClose: onCancel,
489
495
  enableDynamicSizing: true,
490
- onDismiss: onCancel,
491
496
  backdropComponent: renderBackdrop,
492
497
  backgroundStyle: [styles2.background, { backgroundColor: colors.card }],
493
498
  handleIndicatorStyle: [styles2.handle, { backgroundColor: colors.border }],
494
499
  enablePanDownToClose: true
495
500
  },
496
- /* @__PURE__ */ React3__default.default.createElement(bottomSheet.BottomSheetView, { style: styles2.content }, /* @__PURE__ */ React3__default.default.createElement(reactNative.Text, { style: [styles2.title, { color: colors.foreground }], allowFontScaling: true }, title), description ? /* @__PURE__ */ React3__default.default.createElement(reactNative.Text, { style: [styles2.description, { color: colors.foregroundMuted }], allowFontScaling: true }, description) : null, /* @__PURE__ */ React3__default.default.createElement(reactNative.View, { style: styles2.actions }, /* @__PURE__ */ React3__default.default.createElement(
501
+ /* @__PURE__ */ React3__default.default.createElement(BottomSheet.BottomSheetView, { style: styles2.content }, /* @__PURE__ */ React3__default.default.createElement(reactNative.View, { style: styles2.header, accessibilityRole: "header" }, /* @__PURE__ */ React3__default.default.createElement(reactNative.View, { style: styles2.headerRow }, /* @__PURE__ */ React3__default.default.createElement(reactNative.Text, { style: [styles2.title, { color: colors.foreground }], allowFontScaling: true }, title), showCloseButton ? /* @__PURE__ */ React3__default.default.createElement(
502
+ reactNative.TouchableOpacity,
503
+ {
504
+ onPress: onCancel,
505
+ style: styles2.closeButton,
506
+ activeOpacity: 0.6,
507
+ touchSoundDisabled: true,
508
+ accessibilityRole: "button",
509
+ accessibilityLabel: "Close",
510
+ hitSlop: { top: 12, bottom: 12, left: 12, right: 12 }
511
+ },
512
+ /* @__PURE__ */ React3__default.default.createElement(vectorIcons.Feather, { name: "x", size: ms(18), color: colors.foregroundMuted })
513
+ ) : null), effectiveSubtitle ? /* @__PURE__ */ React3__default.default.createElement(reactNative.Text, { style: [styles2.subtitle, { color: colors.foregroundMuted }], allowFontScaling: true }, effectiveSubtitle) : null), /* @__PURE__ */ React3__default.default.createElement(reactNative.View, { style: styles2.actions }, /* @__PURE__ */ React3__default.default.createElement(
497
514
  Button,
498
515
  {
499
516
  label: confirmLabel,
@@ -540,19 +557,32 @@ var styles2 = reactNative.StyleSheet.create({
540
557
  borderRadius: ms(2)
541
558
  },
542
559
  content: {
543
- paddingHorizontal: s(24),
544
- paddingBottom: vs(32),
545
- gap: vs(12)
560
+ paddingHorizontal: s(16),
561
+ paddingBottom: vs(32)
562
+ },
563
+ header: {
564
+ paddingTop: vs(4),
565
+ paddingBottom: vs(12),
566
+ gap: vs(4)
567
+ },
568
+ headerRow: {
569
+ flexDirection: "row",
570
+ alignItems: "center",
571
+ justifyContent: "space-between"
546
572
  },
547
573
  title: {
548
574
  fontFamily: "Sohne-SemiBold",
549
575
  fontSize: ms(18),
550
- lineHeight: mvs(26)
576
+ flex: 1
577
+ },
578
+ closeButton: {
579
+ padding: s(4),
580
+ marginLeft: s(8)
551
581
  },
552
- description: {
582
+ subtitle: {
553
583
  fontFamily: "Sohne-Regular",
554
- fontSize: ms(15),
555
- lineHeight: mvs(22)
584
+ fontSize: ms(14),
585
+ lineHeight: mvs(20)
556
586
  },
557
587
  actions: {
558
588
  gap: vs(10),
@@ -1,4 +1,4 @@
1
- export { ConfirmDialog } from './chunk-FZZLPJ6B.mjs';
1
+ export { ConfirmDialog } from './chunk-KZL5VTYK.mjs';
2
2
  import './chunk-2TFTAWVJ.mjs';
3
3
  import './chunk-3DKJ2GIC.mjs';
4
4
  import './chunk-EJ7ZPXOH.mjs';