@veevarts/design-system 1.12.7 → 1.13.0-alpha.1

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 (75) hide show
  1. package/dist/index.cjs +5 -14
  2. package/dist/index.js +8416 -10779
  3. package/dist/patterns/CashTenderForm/types.d.ts +10 -0
  4. package/dist/patterns/CatalogItemCard/CatalogItemCard.d.ts +7 -0
  5. package/dist/patterns/CatalogItemCard/index.d.ts +2 -0
  6. package/dist/patterns/CatalogItemCard/type.d.ts +82 -0
  7. package/dist/patterns/CheckTenderForm/types.d.ts +10 -0
  8. package/dist/patterns/CommitmentDetails/CommitmentDetails.d.ts +16 -0
  9. package/dist/patterns/CommitmentDetails/index.d.ts +2 -0
  10. package/dist/patterns/ConfirmationModal/ConfirmationModal.d.ts +22 -0
  11. package/dist/patterns/ConfirmationModal/index.d.ts +2 -0
  12. package/dist/patterns/EventDetails/EventDetails.d.ts +3 -1
  13. package/dist/patterns/FeedbackState/FeedbackState.d.ts +23 -0
  14. package/dist/patterns/FeedbackState/index.d.ts +2 -0
  15. package/dist/patterns/FeedbackState/type.d.ts +40 -0
  16. package/dist/patterns/FilterPopover/FilterPopover.d.ts +6 -0
  17. package/dist/patterns/FilterPopover/index.d.ts +2 -0
  18. package/dist/patterns/FilterPopover/type.d.ts +85 -0
  19. package/dist/patterns/InstallmentFundAssignment/InstallmentFundAssignment.d.ts +3 -0
  20. package/dist/patterns/InstallmentFundAssignment/InstallmentFundAssignmentSkeleton.d.ts +2 -0
  21. package/dist/patterns/InstallmentFundAssignment/index.d.ts +3 -0
  22. package/dist/patterns/InstallmentFundAssignment/types.d.ts +67 -0
  23. package/dist/patterns/InstallmentFundAssignment/utils.d.ts +12 -0
  24. package/dist/patterns/InstallmentSchedule/InstallmentSchedule.d.ts +3 -0
  25. package/dist/patterns/InstallmentSchedule/InstallmentScheduleSkeleton.d.ts +2 -0
  26. package/dist/patterns/InstallmentSchedule/InstallmentTable.d.ts +3 -0
  27. package/dist/patterns/InstallmentSchedule/index.d.ts +5 -0
  28. package/dist/patterns/InstallmentSchedule/types.d.ts +100 -0
  29. package/dist/patterns/InstallmentSchedule/utils.d.ts +3 -0
  30. package/dist/patterns/ItemCard/type.d.ts +52 -0
  31. package/dist/patterns/OfferCard/OfferCard.d.ts +1 -1
  32. package/dist/patterns/OfferCard/types.d.ts +93 -2
  33. package/dist/patterns/OfferCard/variants/OfferCardList.d.ts +2 -2
  34. package/dist/patterns/PaymentSubAmountInput/PaymentSubAmountInput.d.ts +11 -0
  35. package/dist/patterns/SessionTimeline/SessionTimeline.d.ts +7 -0
  36. package/dist/patterns/SessionTimeline/index.d.ts +2 -0
  37. package/dist/patterns/SessionTimeline/type.d.ts +76 -0
  38. package/dist/patterns/Summary/Summary.d.ts +4 -0
  39. package/dist/patterns/Summary/components/ActionBar.d.ts +17 -0
  40. package/dist/patterns/Summary/components/CartButton.d.ts +11 -0
  41. package/dist/patterns/Summary/components/CollapseHeader.d.ts +19 -0
  42. package/dist/patterns/Summary/components/GrandTotalRow.d.ts +11 -0
  43. package/dist/patterns/Summary/components/ItemRow.d.ts +9 -0
  44. package/dist/patterns/Summary/components/PrimaryCta.d.ts +11 -0
  45. package/dist/patterns/Summary/components/ServiceFeeRow.d.ts +8 -0
  46. package/dist/patterns/Summary/components/SummaryBody.d.ts +15 -0
  47. package/dist/patterns/Summary/components/TotalsLineRow.d.ts +8 -0
  48. package/dist/patterns/Summary/drag.d.ts +55 -0
  49. package/dist/patterns/Summary/fmt.d.ts +2 -0
  50. package/dist/patterns/Summary/index.d.ts +7 -0
  51. package/dist/patterns/Summary/types.d.ts +154 -0
  52. package/dist/patterns/Summary/useIsMobile.d.ts +17 -0
  53. package/dist/patterns/index.d.ts +18 -0
  54. package/package.json +2 -1
  55. package/dist/components/Button/Button.test.d.ts +0 -1
  56. package/dist/components/Select/Select.test.d.ts +0 -1
  57. package/dist/patterns/CashTenderForm/__test__/CashTenderForm.test.d.ts +0 -4
  58. package/dist/patterns/CheckTenderForm/__test__/CheckTenderForm.test.d.ts +0 -4
  59. package/dist/patterns/DonationAmounts/__test__/DonationAmounts.test.d.ts +0 -4
  60. package/dist/patterns/EventDetails/__test__/EventDetails.test.d.ts +0 -1
  61. package/dist/patterns/ExpireCartTimer/__test__/ExpireCartTimer.test.d.ts +0 -4
  62. package/dist/patterns/Footer/__test__/Footer.test.d.ts +0 -1
  63. package/dist/patterns/ItemCard/__test__/ItemCard.test.d.ts +0 -4
  64. package/dist/patterns/MembershipSelectCards/__test__/MembershipSelectCards.test.d.ts +0 -4
  65. package/dist/patterns/Multiselect/__test__/Multiselect.test.d.ts +0 -4
  66. package/dist/patterns/Navbar/__test__/Navbar.test.d.ts +0 -1
  67. package/dist/patterns/OfferCard/__test__/OfferCard.test.d.ts +0 -1
  68. package/dist/patterns/OtherTenderForm/__test__/OtherTenderForm.test.d.ts +0 -4
  69. package/dist/patterns/RevenueDistribution/__test__/RevenueDistributionCard.test.d.ts +0 -1
  70. package/dist/patterns/RichText/RichText.test.d.ts +0 -1
  71. package/dist/patterns/RichText/core/TipTapEditor.test.d.ts +0 -1
  72. package/dist/patterns/SplitPaymentSummary/__test__/SplitPaymentSummary.test.d.ts +0 -4
  73. package/dist/patterns/Stepper/Stepper.test.d.ts +0 -4
  74. package/dist/patterns/TicketSelection/__test__/TicketSelection.test.d.ts +0 -4
  75. package/dist/patterns/Toggle/__test__/Toggle.test.d.ts +0 -4
@@ -40,6 +40,29 @@ export interface Offer {
40
40
  * Position for sorting offers in a list
41
41
  */
42
42
  position?: number;
43
+ /**
44
+ * Explicit sold-out override for buyer-flow states.
45
+ * When true, the offer is considered unavailable regardless of numeric ticket fields.
46
+ */
47
+ isSoldOut?: boolean;
48
+ /**
49
+ * Explicit max reached override for buyer-flow states.
50
+ * When true, increments are disabled and the max-reached message is shown.
51
+ */
52
+ isMaxReached?: boolean;
53
+ /**
54
+ * Flag used for blocked states (adult-required, business-rule restrictions, etc.).
55
+ * Blocked offers are read-only and render an explanatory status message.
56
+ */
57
+ isRuleBlocked?: boolean;
58
+ /**
59
+ * Optional disabled reason shown when the offer is unavailable.
60
+ */
61
+ disabledReason?: string;
62
+ /**
63
+ * Optional compact rendering mode for list/item layouts.
64
+ */
65
+ compact?: boolean;
43
66
  }
44
67
  /**
45
68
  * Selection state for offers (map of offer ID to quantity)
@@ -69,6 +92,14 @@ export interface OfferCardLabels {
69
92
  * Message when maximum tickets reached (e.g., "Maximum number of tickets allowed reached")
70
93
  */
71
94
  maxReached?: string;
95
+ /**
96
+ * Message for rule-blocked/buying-rule disabled states
97
+ */
98
+ ruleBlocked?: string;
99
+ /**
100
+ * Generic disabled message fallback
101
+ */
102
+ disabled?: string;
72
103
  }
73
104
  /**
74
105
  * Labels for error state
@@ -131,6 +162,14 @@ export interface OfferCardClassNames {
131
162
  * Class for the card footer
132
163
  */
133
164
  footer?: string;
165
+ /**
166
+ * Class for compact mode container
167
+ */
168
+ compact?: string;
169
+ /**
170
+ * Class for compact quantity/status area
171
+ */
172
+ compactFooter?: string;
134
173
  }
135
174
  /**
136
175
  * Class names for OfferCardList
@@ -235,6 +274,10 @@ export interface OfferCardSlots {
235
274
  * Custom render for max reached alert
236
275
  */
237
276
  renderMaxReachedAlert?: (message: string) => React.ReactNode;
277
+ /**
278
+ * Custom render for disabled state (sold out / max reached / rule blocked)
279
+ */
280
+ renderDisabledState?: (kind: 'soldOut' | 'maxReached' | 'ruleBlocked' | 'disabled', label: string) => React.ReactNode;
238
281
  }
239
282
  /**
240
283
  * Props for the OfferCard component
@@ -323,15 +366,53 @@ export interface OfferCardProps {
323
366
  * Class names for styling different parts of the component
324
367
  */
325
368
  classNames?: OfferCardClassNames;
369
+ /**
370
+ * Render in compact visual density mode.
371
+ * @default false
372
+ */
373
+ compact?: boolean;
374
+ /**
375
+ * Explicit sold-out override for this specific card.
376
+ * @default false
377
+ */
378
+ isSoldOut?: boolean;
379
+ /**
380
+ * Explicit max-reached override for this specific card.
381
+ * @default false
382
+ */
383
+ isMaxReached?: boolean;
384
+ /**
385
+ * Rule-blocked state for this specific card.
386
+ * @default false
387
+ */
388
+ isRuleBlocked?: boolean;
389
+ /**
390
+ * Status/tone shown for rule-blocked or max-reached states.
391
+ * @default 'warning'
392
+ */
393
+ statusTone?: 'default' | 'warning' | 'danger';
394
+ /**
395
+ * Optional message to explain why interaction is blocked.
396
+ */
397
+ disabledReason?: string;
398
+ /**
399
+ * Optional override for the disabled state status label.
400
+ */
401
+ statusLabel?: string;
402
+ /**
403
+ * Optional disabled override used by OfferCardList or list-level controls.
404
+ * @default false
405
+ */
406
+ disabled?: boolean;
326
407
  }
327
408
  /**
328
409
  * Props for the OfferCardList component
329
410
  */
330
- export interface OfferCardListProps {
411
+ export interface OfferCardListProps<TOffer = Offer> {
331
412
  /**
332
413
  * Array of offers to display
333
414
  */
334
- offers: Offer[];
415
+ offers: TOffer[];
335
416
  /**
336
417
  * Currently selected quantities (controlled mode)
337
418
  * Map of offer ID to quantity
@@ -401,6 +482,16 @@ export interface OfferCardListProps {
401
482
  * Class names for styling different parts of the component
402
483
  */
403
484
  classNames?: OfferCardListClassNames;
485
+ /**
486
+ * Render the offer list in compact mode
487
+ * @default false
488
+ */
489
+ compact?: boolean;
490
+ /**
491
+ * Map incoming offer-like items to OfferCard props.
492
+ * This supports lightweight adapters for buyer-flow data shapes.
493
+ */
494
+ mapOffer?: (offer: TOffer) => Offer;
404
495
  }
405
496
  /**
406
497
  * Props for the OfferCardSkeleton component
@@ -1,12 +1,12 @@
1
1
  import { JSX } from 'react';
2
- import { OfferCardListProps } from '../types';
2
+ import { OfferCardListProps, Offer } from '../types';
3
3
  /**
4
4
  * OfferCardList component displays a collection of offer cards in a responsive grid.
5
5
  * It manages selection state internally or accepts external control via props.
6
6
  * When animated is true, cards animate in/out using Framer Motion variants.
7
7
  */
8
8
  export declare const OfferCardList: {
9
- ({ offers, selection: selectionProp, defaultSelection, onSelectionChange, onQuantityChange, currency, locale, labels, slots, isDisabled, buttonVariant, buttonColor, showCard, animated, gap, classNames, }: OfferCardListProps): JSX.Element;
9
+ <TOffer = Offer>({ offers, mapOffer, selection: selectionProp, defaultSelection, onSelectionChange, onQuantityChange, currency, locale, labels, slots, isDisabled, buttonVariant, buttonColor, showCard, animated, gap, compact, classNames, }: OfferCardListProps<TOffer>): JSX.Element;
10
10
  displayName: string;
11
11
  };
12
12
  export default OfferCardList;
@@ -38,6 +38,17 @@ export interface PaymentSubAmountInputProps {
38
38
  * step (e.g. opening Split, advancing to Payment #N).
39
39
  */
40
40
  autoFocus?: boolean;
41
+ /**
42
+ * Hard upper bound for the typed amount, in the same MAJOR-unit scale
43
+ * the host parses the emitted string with. A keystroke that would push
44
+ * the parsed value above this is REJECTED (the controlled `value` is
45
+ * left unchanged, so the input reverts the offending character). Keeps
46
+ * the cashier from entering an amount that overflows the PSP integer
47
+ * range downstream. A character `maxLength` can't enforce this (e.g.
48
+ * `99999999` is only 8 chars yet far over a $999,999.99 cap), so the
49
+ * guard is value-based. Omit for no cap.
50
+ */
51
+ maxAmount?: number;
41
52
  'data-testid'?: string;
42
53
  className?: string;
43
54
  }
@@ -0,0 +1,7 @@
1
+ import { JSX } from 'react';
2
+ import { SessionTimelineProps } from './type';
3
+ export declare const SessionTimeline: {
4
+ ({ heading, subheading, days, selectedDate, onDateSelect, quickDates, selectedSessionId, onSessionSelect, emptyStateMessage, statusLabel, statusTone, sessionAriaLabel, dayButtonClassName, calendarSlot, dayGroupAriaLabel, sessionGridAriaLabel, className, headingClassName, subheadingClassName, }: SessionTimelineProps): JSX.Element;
5
+ displayName: string;
6
+ };
7
+ export default SessionTimeline;
@@ -0,0 +1,2 @@
1
+ export { default as SessionTimeline } from './SessionTimeline';
2
+ export type * from './type';
@@ -0,0 +1,76 @@
1
+ export type SessionTimelineStatus = 'available' | 'limited' | 'sold-out' | 'closed';
2
+ export interface SessionTimelineSession {
3
+ /** Unique identifier for the session. */
4
+ id: string;
5
+ /** Human-readable start time text. */
6
+ startTime: string;
7
+ /** Human-readable end time text. */
8
+ endTime: string;
9
+ /** Remaining seats, if applicable. */
10
+ seatsRemaining?: number;
11
+ /** Status used for tone and accessibility text. */
12
+ status?: SessionTimelineStatus;
13
+ /** Whether this session has no capacity cap. */
14
+ isUnlimited?: boolean;
15
+ /** Force-disable regardless of status. */
16
+ isDisabled?: boolean;
17
+ }
18
+ export interface SessionTimelineDay {
19
+ /** Stable day key (ISO date or grouped value). */
20
+ date: string;
21
+ /** Optional custom label for quick controls and cards. */
22
+ label: string;
23
+ /** Sessions available for this day. */
24
+ sessions: SessionTimelineSession[];
25
+ }
26
+ export interface SessionTimelineQuickDate {
27
+ /** Day key from `SessionTimelineDay.date`. */
28
+ date: string;
29
+ /** Label shown for this quick button. */
30
+ label: string;
31
+ /** Disable quick button. */
32
+ isDisabled?: boolean;
33
+ }
34
+ export interface SessionTimelineProps {
35
+ /** Optional section heading. */
36
+ heading: string;
37
+ /** Optional section description. */
38
+ subheading?: string;
39
+ /** All available session days. */
40
+ days: readonly SessionTimelineDay[];
41
+ /** Currently selected day key. */
42
+ selectedDate: string | null;
43
+ /** Day selection callback. */
44
+ onDateSelect: (date: string) => void | Promise<void>;
45
+ /** Optional quick selector buttons rendered above the timeline. */
46
+ quickDates?: readonly SessionTimelineQuickDate[];
47
+ /** Currently selected session id. */
48
+ selectedSessionId?: string | null;
49
+ /** Session selection callback (toggle null to clear). */
50
+ onSessionSelect: (sessionId: string | null) => void | Promise<void>;
51
+ /** Text when the selected day has no sessions. */
52
+ emptyStateMessage?: string;
53
+ /** Custom status label factory. */
54
+ statusLabel?: (session: SessionTimelineSession) => string;
55
+ /** Custom session status tone. */
56
+ statusTone?: (session: SessionTimelineSession) => 'default' | 'success' | 'danger';
57
+ /** Custom session card accessible label factory. */
58
+ sessionAriaLabel?: (session: SessionTimelineSession, state: {
59
+ isSelected: boolean;
60
+ isUnavailable: boolean;
61
+ }) => string;
62
+ /** Custom day selection status class. */
63
+ dayButtonClassName?: string;
64
+ /** Optional additional control slot for a calendar trigger/popover. */
65
+ calendarSlot?: React.ReactNode;
66
+ /** Aria label for day quick switch group. */
67
+ dayGroupAriaLabel?: string;
68
+ /** Aria label for session grid region. */
69
+ sessionGridAriaLabel?: string;
70
+ /** Optional custom root class. */
71
+ className?: string;
72
+ /** Optional custom heading class. */
73
+ headingClassName?: string;
74
+ /** Optional custom subheading class. */
75
+ subheadingClassName?: string;
76
+ }
@@ -0,0 +1,4 @@
1
+ import { default as React } from 'react';
2
+ import { SummaryProps } from './types';
3
+ export declare const Summary: React.FC<SummaryProps>;
4
+ export default Summary;
@@ -0,0 +1,17 @@
1
+ import { default as React } from 'react';
2
+ import { SummaryClassNames, SummaryPrimaryAction, SummaryProps } from '../types';
3
+ export interface ActionBarProps {
4
+ open: boolean;
5
+ /** Open progress 0→1; drives the cross-fade opacity. */
6
+ progress: number;
7
+ /** True while a drag is in progress (disables the eased transition). */
8
+ dragging: boolean;
9
+ primaryAction?: SummaryPrimaryAction;
10
+ isLoading: boolean;
11
+ cart?: SummaryProps['cart'];
12
+ cartAriaLabel: string;
13
+ /** Expand the summary — the closed-bar cart button opens it on click. */
14
+ onToggleOpen?: () => void;
15
+ classNames: SummaryClassNames;
16
+ }
17
+ export declare const ActionBar: React.FC<ActionBarProps>;
@@ -0,0 +1,11 @@
1
+ import { default as React } from 'react';
2
+ import { SummaryProps } from '../types';
3
+ export interface CartButtonProps {
4
+ cart: NonNullable<SummaryProps['cart']>;
5
+ ariaLabel: string;
6
+ /** Click handler — wired by the action bar to open the summary (and still
7
+ * fire the consumer's `cart.onPress` if provided). */
8
+ onPress: () => void;
9
+ className?: string;
10
+ }
11
+ export declare const CartButton: React.FC<CartButtonProps>;
@@ -0,0 +1,19 @@
1
+ import { default as React } from 'react';
2
+ import { Money, SummaryClassNames } from '../types';
3
+ export interface CollapseHeaderProps {
4
+ title: React.ReactNode;
5
+ total: {
6
+ label?: React.ReactNode;
7
+ amount: Money;
8
+ };
9
+ locale: string;
10
+ open: boolean;
11
+ /** Open progress 0→1; drives the cross-fade opacity. */
12
+ progress: number;
13
+ /** True while a drag is in progress (disables the eased transition). */
14
+ dragging: boolean;
15
+ toggleAriaLabel: string;
16
+ onToggleOpen?: () => void;
17
+ classNames: SummaryClassNames;
18
+ }
19
+ export declare const CollapseHeader: React.FC<CollapseHeaderProps>;
@@ -0,0 +1,11 @@
1
+ import { default as React } from 'react';
2
+ import { Money } from '../types';
3
+ export interface GrandTotalRowProps {
4
+ total: {
5
+ label?: React.ReactNode;
6
+ amount: Money;
7
+ };
8
+ locale: string;
9
+ className?: string;
10
+ }
11
+ export declare const GrandTotalRow: React.FC<GrandTotalRowProps>;
@@ -0,0 +1,9 @@
1
+ import { default as React } from 'react';
2
+ import { SummaryLineItem } from '../types';
3
+ export interface ItemRowProps {
4
+ item: SummaryLineItem;
5
+ locale: string;
6
+ onRemove?: (id: string) => void;
7
+ removeAriaLabel: string;
8
+ }
9
+ export declare const ItemRow: React.FC<ItemRowProps>;
@@ -0,0 +1,11 @@
1
+ import { default as React } from 'react';
2
+ import { SummaryProps } from '../types';
3
+ export interface PrimaryCtaProps {
4
+ action: NonNullable<SummaryProps['primaryAction']>;
5
+ disabledByLoading: boolean;
6
+ className?: string;
7
+ /** Disambiguates the two cross-fade CTA layers. Default `summary-cta` (the
8
+ * open / desktop instance); the closed compact layer passes `summary-cta-compact`. */
9
+ testId?: string;
10
+ }
11
+ export declare const PrimaryCta: React.FC<PrimaryCtaProps>;
@@ -0,0 +1,8 @@
1
+ import { default as React } from 'react';
2
+ import { SummaryServiceFee } from '../types';
3
+ export interface ServiceFeeRowProps {
4
+ fee: SummaryServiceFee;
5
+ locale: string;
6
+ className?: string;
7
+ }
8
+ export declare const ServiceFeeRow: React.FC<ServiceFeeRowProps>;
@@ -0,0 +1,15 @@
1
+ import { default as React } from 'react';
2
+ import { SummaryClassNames, SummaryLineItem, SummaryServiceFee, SummaryTotalRow } from '../types';
3
+ export interface SummaryBodyProps {
4
+ pricesInLabel: React.ReactNode;
5
+ currency?: React.ReactNode;
6
+ items?: SummaryLineItem[];
7
+ serviceFee?: SummaryServiceFee;
8
+ rows?: SummaryTotalRow[];
9
+ locale: string;
10
+ onRemoveItem?: (id: string) => void;
11
+ removeAriaLabel: string;
12
+ emptyState?: React.ReactNode;
13
+ classNames: SummaryClassNames;
14
+ }
15
+ export declare const SummaryBody: React.FC<SummaryBodyProps>;
@@ -0,0 +1,8 @@
1
+ import { default as React } from 'react';
2
+ import { SummaryTotalRow } from '../types';
3
+ export interface TotalsLineRowProps {
4
+ row: SummaryTotalRow;
5
+ locale: string;
6
+ emphasized: boolean;
7
+ }
8
+ export declare const TotalsLineRow: React.FC<TotalsLineRowProps>;
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Drag/reveal gesture helpers for the collapsible `<Summary>`.
3
+ *
4
+ * Kept in their own module (not in `Summary.tsx`) so the component file only
5
+ * exports a component — the Design-System fast-refresh convention — and so the
6
+ * gesture math is pure and fully unit-tested (framer's drag `info` never fires
7
+ * under the test mock).
8
+ */
9
+ /**
10
+ * Minimum vertical drag distance (px) past which a collapsible summary toggles.
11
+ * Exported so the gesture threshold is testable and tunable.
12
+ */
13
+ export declare const DRAG_TOGGLE_THRESHOLD = 60;
14
+ /**
15
+ * Pure decision for the drag-to-toggle gesture: drag **up** (negative offset)
16
+ * while closed opens; drag **down** (positive offset) while open closes. A drag
17
+ * shorter than `threshold`, or in the wrong direction for the current state,
18
+ * does nothing.
19
+ */
20
+ export declare const shouldToggleOnDrag: (offsetY: number, open: boolean, threshold?: number) => boolean;
21
+ /** Clamp a proposed reveal height into `[0, fullHeight]`. */
22
+ export declare const clampRevealHeight: (proposed: number, fullHeight: number) => number;
23
+ /**
24
+ * Live reveal height while dragging: dragging **up** (negative `offsetY`) grows
25
+ * the panel from its `baseHeight`; dragging **down** shrinks it. Clamped to the
26
+ * panel's natural `fullHeight` so it tracks the finger 1:1 without overshooting.
27
+ */
28
+ export declare const revealHeightFromDrag: (baseHeight: number, offsetY: number, fullHeight: number) => number;
29
+ /**
30
+ * Resolve the reveal panel's current height. While dragging (`dragHeight` set)
31
+ * the finger drives it; otherwise it rests fully open (`fullHeight`) or fully
32
+ * collapsed (`0`).
33
+ */
34
+ export declare const currentRevealHeight: (dragHeight: number | null, open: boolean, fullHeight: number) => number;
35
+ /**
36
+ * The reveal panel animates its height smoothly at rest, but tracks the finger
37
+ * with no transition while dragging (so the drag feels 1:1, not laggy).
38
+ */
39
+ export declare const revealTransitionClass: (dragging: boolean) => string;
40
+ export interface DragInfo {
41
+ offset?: {
42
+ y?: number;
43
+ };
44
+ }
45
+ export interface DragHandlerDeps {
46
+ open: boolean;
47
+ fullHeight: number;
48
+ setDragHeight: (height: number | null) => void;
49
+ onToggleOpen?: () => void;
50
+ }
51
+ export interface DragHandlers {
52
+ onDrag: (event: unknown, info?: DragInfo) => void;
53
+ onDragEnd: (event: unknown, info?: DragInfo) => void;
54
+ }
55
+ export declare const createDragHandlers: (deps: DragHandlerDeps) => DragHandlers;
@@ -0,0 +1,2 @@
1
+ import { Money } from '../../utils/money';
2
+ export declare const fmt: (m: Money, locale: string) => string;
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Summary Pattern — pure-UI order summary (Figma node 12127-11831):
3
+ * header, flexible line items, service-fee toggle, totals, collapsible
4
+ * Total + CTA, and a compact mobile bottom-bar.
5
+ */
6
+ export { Summary } from './Summary';
7
+ export type { SummaryProps, SummaryLineItem, SummaryServiceFee, SummaryTotalRow, SummaryPrimaryAction, SummaryLabels, Money, } from './types';
@@ -0,0 +1,154 @@
1
+ import { ReactNode } from 'react';
2
+ import { Money } from '../../utils/money';
3
+ export type { Money } from '../../utils/money';
4
+ /**
5
+ * A single, flexible line item. The four Figma "types" (Ticket, Event,
6
+ * Membership, Donation) are compositions of this one shape — not rigid
7
+ * variants — honouring "grouping, but flexible".
8
+ */
9
+ export interface SummaryLineItem {
10
+ /** Stable id (keys, remove handler, and `data-testid`). */
11
+ id: string;
12
+ /** Display name (Ticket / Event title / Membership / Donation). */
13
+ name: ReactNode;
14
+ /** Quantity; renders a `{qty} x` prefix (Ticket / Adult / Children). */
15
+ quantity?: number;
16
+ /** Right-aligned price. Omit on an Event header that only groups children. */
17
+ amount?: Money;
18
+ /** Render the name in a heavier weight (Event / Membership / Donation titles). */
19
+ emphasis?: boolean;
20
+ /** Leading icon node (e.g. `lucide:ticket` for Event, `lucide:star` for Membership). */
21
+ leadingIcon?: ReactNode;
22
+ /** Calendar row, e.g. "March 26th, 2026 - 9:45 am - 09:45 pm" (Event). */
23
+ dateLabel?: ReactNode;
24
+ /** Date-range row joined by an arrow (Membership), e.g. Jan 26, 2026 → Jan 26, 2027. */
25
+ dateRange?: {
26
+ from: ReactNode;
27
+ to: ReactNode;
28
+ };
29
+ /** Nested rows, indented (Event's Adult / Children). */
30
+ children?: SummaryLineItem[];
31
+ }
32
+ /** The "Pay Service fee" radio-toggle row. */
33
+ export interface SummaryServiceFee {
34
+ label: ReactNode;
35
+ amount: Money;
36
+ /** Selected (filled radio) state. */
37
+ isSelected?: boolean;
38
+ /** Fires when the row/radio is toggled. */
39
+ onToggle?: () => void;
40
+ }
41
+ /** A plain totals row (Subtotal, Taxes). */
42
+ export interface SummaryTotalRow {
43
+ /** Stable key for `data-testid` (e.g. 'subtotal', 'taxes'). */
44
+ key: string;
45
+ label: ReactNode;
46
+ amount: Money;
47
+ }
48
+ /** The primary call-to-action (orange pill + arrow). */
49
+ export interface SummaryPrimaryAction {
50
+ label: ReactNode;
51
+ onPress: () => void;
52
+ isLoading?: boolean;
53
+ isDisabled?: boolean;
54
+ }
55
+ /** Overridable copy. */
56
+ export interface SummaryLabels {
57
+ /** Aria label for the per-item remove control. Default "Remove item". */
58
+ removeAriaLabel?: string;
59
+ /** Aria label for the collapse/expand press target. Default "Toggle summary". */
60
+ toggleAriaLabel?: string;
61
+ /** Aria label for the mobile cart button. Default "View cart". */
62
+ cartAriaLabel?: string;
63
+ }
64
+ /**
65
+ * Per-slot class overrides — the Design-System `classNames` convention (HeroUI
66
+ * `SlotsToClasses`). Each key targets one visual region and is merged AFTER the
67
+ * component's own classes via `cn`, so any Tailwind utility you pass wins. The
68
+ * root also accepts the plain `className`.
69
+ */
70
+ export interface SummaryClassNames {
71
+ /** Root `<section>` (applied alongside `className`). */
72
+ base?: string;
73
+ /** Header row (title + `×`). */
74
+ header?: string;
75
+ /** Title text. */
76
+ title?: string;
77
+ /** The header collapse/close (`×`) control. */
78
+ closeButton?: string;
79
+ /** "Prices are in / currency" row. */
80
+ prices?: string;
81
+ /** Line-items container. */
82
+ items?: string;
83
+ /** Service-fee row. */
84
+ serviceFee?: string;
85
+ /** Totals-rows container (Subtotal / Taxes). */
86
+ totalsRows?: string;
87
+ /** The Total row. */
88
+ total?: string;
89
+ /** Primary CTA button. */
90
+ cta?: string;
91
+ /** Mobile compact bottom-bar. */
92
+ mobileBar?: string;
93
+ /** Mobile cart button. */
94
+ cart?: string;
95
+ }
96
+ export interface SummaryProps {
97
+ /** Header title. Default "Summary". */
98
+ title?: ReactNode;
99
+ /** Left text of the prices row. Default "Prices are in". */
100
+ pricesInLabel?: ReactNode;
101
+ /** Right text of the prices row (currency code), e.g. "USD". */
102
+ currency?: ReactNode;
103
+ /** BCP-47 locale for money formatting. Default 'en-US'. */
104
+ locale?: string;
105
+ /** Flexible line items (flat or grouped via `children`). */
106
+ items?: SummaryLineItem[];
107
+ /** Optional "Pay Service fee" radio-toggle row. */
108
+ serviceFee?: SummaryServiceFee;
109
+ /** Plain totals rows rendered above the Total (Subtotal, Taxes). */
110
+ rows?: SummaryTotalRow[];
111
+ /** The emphasized Total row (label default "Total"). */
112
+ total: {
113
+ label?: ReactNode;
114
+ amount: Money;
115
+ };
116
+ /**
117
+ * Whether the summary can collapse — the header shows a `×` and the whole
118
+ * header toggles Open/Closed. Defaults to `variant === 'mobile'` (including
119
+ * the auto-detected mobile variant — see `variant`). Pass explicitly to
120
+ * override the automatic behaviour.
121
+ */
122
+ collapsible?: boolean;
123
+ /**
124
+ * Controlled open/closed state. Defaults to **closed** when collapsible (the
125
+ * mobile sheet rests collapsed) and always open on the non-collapsible card.
126
+ */
127
+ isOpen?: boolean;
128
+ /** Fires when the header (open) — or the closed bar's Total (closed) — is activated to toggle. */
129
+ onToggleOpen?: () => void;
130
+ /** The primary CTA. */
131
+ primaryAction?: SummaryPrimaryAction;
132
+ /** When provided, item rows show a red trash remove control. */
133
+ onRemoveItem?: (id: string) => void;
134
+ /**
135
+ * Layout: full card (`'main'`) or the bottom-sheet / compact bar (`'mobile'`).
136
+ * When OMITTED the layout is auto-detected from the viewport (below `md`
137
+ * → `'mobile'`, `md`+ → `'main'`). Pass explicitly to pin a layout.
138
+ */
139
+ variant?: 'main' | 'mobile';
140
+ /** Mobile bottom-bar cart button + badge count. */
141
+ cart?: {
142
+ count?: number;
143
+ onPress?: () => void;
144
+ };
145
+ /** Disables the CTA and signals recalculation. */
146
+ isLoading?: boolean;
147
+ /** Rendered when there are no items. */
148
+ emptyState?: ReactNode;
149
+ labels?: SummaryLabels;
150
+ 'data-testid'?: string;
151
+ className?: string;
152
+ /** Per-slot class overrides (Design-System `classNames` convention). */
153
+ classNames?: SummaryClassNames;
154
+ }
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Below Tailwind's `md` (768px): phones / small tablets get the bottom-sheet,
3
+ * everything `md`+ gets the bordered card. Exported so the threshold is shared
4
+ * and overridable.
5
+ */
6
+ export declare const MOBILE_MEDIA_QUERY = "(max-width: 767px)";
7
+ /**
8
+ * Pure, SSR-safe read of a media query. Returns `false` when `matchMedia` is
9
+ * unavailable (server / jsdom), so callers default to the non-mobile layout.
10
+ */
11
+ export declare const mediaMatches: (query: string) => boolean;
12
+ /**
13
+ * Subscribe to a media query and re-render on viewport changes. Initialises
14
+ * from `mediaMatches` (so the first paint already reflects the viewport on the
15
+ * client) and updates live as the screen crosses the breakpoint.
16
+ */
17
+ export declare const useIsMobile: (query?: string) => boolean;