# Changelog

All notable changes to @zenskar/ui-kit will be documented in this file.

## Versioning

- **MAJOR** (X.0.0) - Breaking changes
- **MINOR** (0.X.0) - New features, backward compatible
- **PATCH** (0.0.X) - Bug fixes

### JSON Stability

- **Patch**: No JSON changes
- **Minor**: Only new optional fields
- **Major**: Breaking changes to JSON

**Tip**: Pin exact versions in production: `"@zenskar/ui-kit": "0.1.21"`

---

## [0.1.21] - 2025-01-05

### New Features

**Custom Font Support for AddPaymentMethod Element**

Added `elementFonts` prop to load custom fonts into payment forms. Supports both CSS stylesheets (Google Fonts, Adobe Fonts) and custom font files for brand consistency.

```typescript
// Load fonts from Google Fonts or custom URLs
<AddPaymentMethod
  elementFonts={[
    { cssSrc: 'https://fonts.googleapis.com/css2?family=Poppins:wght@400;600&display=swap' }
  ]}
  elementAppearance={{
    variables: { fontFamily: 'Poppins, sans-serif' }
  }}
/>
```

**New Type Exports:**
- `PaymentElementFonts` - Array of font sources
- `CssFontSource` - CSS stylesheet font (uses `cssSrc` property)
- `CustomFontSource` - Custom font file (uses `family`, `src`, `weight`, `style`, `display`, `unicodeRange`)

**Features:**
- Load fonts from CSS stylesheets or custom font files
- Support for multiple font sources in a single component
- Full TypeScript support with type definitions
- Enhanced brand consistency across payment forms

### Migration Notes

No breaking changes. The `elementFonts` prop is optional and backward compatible.

---

## [0.1.20] - 2025-01-03

### New Features

**confirmParams Prop for Hidden Billing Fields**

Added `confirmParams` prop to AddPaymentMethod element for providing billing data programmatically when UI fields are hidden.

```typescript
<AddPaymentMethod
  elementOptions={{
    fields: {
      billingDetails: {
        address: {
          country: 'never', // Hide country field from UI
        },
      },
    },
  }}
  confirmParams={{
    payment_method_data: {
      billing_details: {
        address: {
          country: 'US', // Provide country programmatically
        },
      },
    },
  }}
/>
```

**Use Cases:**
- Simplify payment forms by hiding fields you already know
- Set billing information based on user account data
- Create streamlined checkout experiences

---

## [0.1.19] - 2025-12-19

### New Features

**Quantity Update Checkout**

Update quantities on existing contracts with the new `createQuantityUpdateCheckout` method. Includes invoice estimates showing the billing impact of changes.

```typescript
const { createQuantityUpdateCheckout, confirmCheckout } = useCheckout()

// Update quantities on an existing contract
const { data: session } = await createQuantityUpdateCheckout({
  contract_id: 'contract-uuid',
  product_quantities: [{
    line_item_id: 'line-item-uuid',
    quantity_value: 15,
    effective_from:'2025-01-10'
  }],
})

// Preview the billing impact
console.log(session.estimates?.current_invoice)
console.log(session.estimates?.next_invoice)

// Confirm to apply the change
await confirmCheckout(session.id)
```

**Preview Checkout (Dry Run)**

Preview billing estimates without creating any records using the new `previewCheckout` method.

```typescript
const { previewCheckout } = useCheckout()

// Preview a new subscription
const { data } = await previewCheckout({
  plan_id: 'plan-uuid',
  start_date: '2025-01-01',
  product_quantities: [
    { pricing_id: 'pricing-uuid', quantity_value: 10 }
  ],
})

// Access estimates
console.log(data.estimates.current_invoice)
console.log(data.estimates.next_invoice)
```

**Pricing Schedule API**

Retrieve product/pricing schedules for a customer's contract with the new `getPricingSchedule` method.

```typescript
const { getPricingSchedule } = useCheckout()

// Get all schedules for active contract
const { data } = await getPricingSchedule()

// Get schedules active on a specific date
const { data } = await getPricingSchedule({
  effective_date: '2025-06-01',
})

// Get schedules for a specific contract
const { data } = await getPricingSchedule({
  contract_id: 'contract-uuid',
})

// Access schedule details
data.schedules.forEach(schedule => {
  console.log(schedule.product.name, schedule.pricing.name)
  console.log(schedule.line_item_id) // For quantity updates
})
```

**New Type Exports**

```typescript
import type {
  // Request types
  CreateCheckoutRequest,
  CheckoutConfirmRequest,
  QuantityUpdateCheckoutRequest,
  PreviewCheckoutRequest,
  GetPricingScheduleRequest,

  // Response types
  CheckoutResponse,
  ConfirmCheckoutResponse,
  CheckoutPreviewResponse,
  ContractSchedulesResponse,

  // Nested types
  CreateCheckoutQuantityOverride,
  QuantityUpdateItem,
  ScheduleItem,
  ScheduleProductInfo,
  SchedulePricingInfo,
} from '@zenskar/ui-kit'
```

### Breaking Changes

**Type Renames: Removed "Schema" Suffix**

All Checkout V2 types have been renamed for consistency:

| Old Name | New Name |
|----------|----------|
| `CheckoutCreateRequestSchema` | `CreateCheckoutRequest` |
| `CheckoutConfirmRequestSchema` | `CheckoutConfirmRequest` |
| `CheckoutResponseSchema` | `CheckoutResponse` |
| `ConfirmCheckoutResponseSchema` | `ConfirmCheckoutResponse` |
| `CheckoutPreviewResponseSchema` | `CheckoutPreviewResponse` |

```typescript
// Before (0.1.18)
import type {
  CheckoutResponseSchema,
  ConfirmCheckoutResponseSchema,
} from '@zenskar/ui-kit'

// After (0.1.19)
import type {
  CheckoutResponse,
  ConfirmCheckoutResponse,
} from '@zenskar/ui-kit'
```

**Removed Guest Checkout Support**

Guest checkout functionality has been removed due to downstream complications. The `isGuestCustomer` context property is no longer used by checkout methods.

**`plan_id` Required for Preview**

The `previewCheckout` method now requires `plan_id` as a mandatory field. Contract-based preview is not yet supported.

```typescript
// Before (no longer works)
await previewCheckout({ contract_id: 'contract-uuid', ... })

// After (required)
await previewCheckout({ plan_id: 'plan-uuid', ... })
```

### Validation Improvements

- Added runtime validation for `line_item_id` in `createQuantityUpdateCheckout` - each product quantity must have a non-empty `line_item_id`
- Improved error messages for missing required fields

---

## [0.1.18] - 2025-12-17

### New Features

**Checkout V2 API Integration**

The SDK now includes core checkout functionality with the new `useCheckout` hook, enabling plan subscription flows with invoice estimates and payment method integration.

```typescript
import { useCheckout } from '@zenskar/ui-kit'

function CheckoutFlow() {
  const { createCheckout, confirmCheckout } = useCheckout()

  // Step 1: Create a checkout session
  const handleCreateCheckout = async () => {
    try {
      const { data } = await createCheckout({
        customer_id: 'cust_123',
        plan_id: 'plan_456',
        product_quantities: [
          { pricing_id: 'prod_789', quantity_value: 5 }
        ]
      })

      console.log('Checkout created:', data.id)
      console.log('Invoice estimate:', data.estimates)
    } catch (error) {
      console.error('Checkout creation failed:', error)
    }
  }

  // Step 2: Confirm the checkout
  const handleConfirmCheckout = async (checkoutId: string) => {
    try {
      const { data } = await confirmCheckout(checkoutId, {
        payment_method_id: 'pm_xyz'
      })

      console.log('Contract ID:', data.contract_id)
    } catch (error) {
      console.error('Checkout confirmation failed:', error)
    }
  }

  return (
    // Your checkout UI
  )
}
```

**New Type Exports**

```typescript
import type {
  // Request/Response types
  CheckoutCreateRequestSchema,
  CheckoutResponseSchema,
  CheckoutConfirmRequestSchema,
  ConfirmCheckoutResponseSchema,

  // Checkout data types
  CheckoutEstimates,
  CheckoutStatus,

  // Product override types
  ProductQuantityOverride,
  ProductQuantityResponse,
} from '@zenskar/ui-kit'
```

**Checkout Status Lifecycle**

The checkout process tracks through these statuses:

```typescript
enum CheckoutStatus {
  PENDING = 'pending',                       // Checkout created
  PAYMENT_INITIATED = 'payment_initiated',   // Payment started
  PAYMENT_SUCCEEDED = 'payment_succeeded',   // Payment completed
  PAYMENT_FAILED = 'payment_failed',         // Payment failed
  CONFIRMED = 'confirmed',                   // Checkout confirmed
  CONTRACT_CREATED = 'contract_created',     // Contract generated
  CANCELLED = 'cancelled',                   // User cancelled
  EXPIRED = 'expired',                       // Checkout expired
}
```

**Key Features:**

- Create checkout sessions for plan subscriptions
- Preview invoice estimates (current and next period)
- Attach payment methods to checkout
- Guest checkout support (prepared for future activation)
- Product quantity overrides for custom pricing
- Full TypeScript support with comprehensive type definitions

**Note:** Only checkout creation (`createCheckout`) and confirmation (`confirmCheckout`) are currently available. Additional methods (preview, update, cancel) are not yet implemented in the backend.

**Use Cases:**

- Self-service plan subscription flows
- Invoice preview before commitment
- Custom product quantity pricing
- Payment method collection during checkout
- Contract creation via checkout confirmation

### Development & Infrastructure

**Environment-Specific Storybook Scripts**

Enhanced development workflow with environment-specific Storybook configurations:

```bash
# Development environment
npm run storybook:dev

# Staging environment
npm run storybook:staging

# Production environment
npm run storybook:production
```

**Changes:**
- Added environment-specific npm scripts for Storybook
- Enhanced Storybook configuration for dynamic environment selection
- Updated environment variables structure
- Improved development and testing workflow

---

## [0.1.17]

### TypeScript Improvements

**Type-Safe Element Retrieval with Automatic Type Narrowing**

The `useZenskarElements()` hook's `getElement()` method now provides automatic TypeScript type narrowing based on the element type parameter. This eliminates the need for manual type assertions and provides better IntelliSense support.

### New Features

**AddPaymentMethod Element `reset()` Method**

The AddPaymentMethod element now includes a `reset()` method that creates a fresh SetupIntent and clears the payment form. This is particularly useful after successful payment submission when you want to allow users to add another payment method without remounting the component.

```typescript
const addPaymentElement = elements?.getElement('add-payment-method')

// After successful payment addition
const { data, error } = await zenskar.addPaymentMethod()
if (!error) {
  // Reset the form to allow adding another payment method
  addPaymentElement?.reset()
}
```

**Use cases:**
- Allow users to add multiple payment methods in succession
- Clear sensitive payment data after successful submission
- Refresh the form without unmounting/remounting the component
- Provide a better UX for "Add Another Payment Method" flows

**Before:**
```typescript
const elements = useZenskarElements()
const element = elements?.getElement('add-payment-method')
// Type: ZenskarElementInstance | null | undefined
// Had to use type assertion:
const paymentElement = element as AddPaymentMethodElementInstance
```

**After:**
```typescript
const elements = useZenskarElements()
const element = elements?.getElement('add-payment-method')
// Type: AddPaymentMethodElementInstance | null (automatically narrowed!)

if (element) {
  // TypeScript knows these methods exist - no casting needed:
  await element.submit()
  element.reset()
  const isEmpty = element.isEmpty
}
```

### Technical Details

- Added `ElementTypeMap` type helper using TypeScript's `Extract` utility
- Implemented function overloads for `getElement()` method
- Each element type (`'add-payment-method'`, `'manage-billing-information'`) now returns its specific instance type
- Full IntelliSense and compile-time type checking for element-specific methods

### Benefits

- ✅ **Zero Runtime Impact** - Pure type-level changes
- ✅ **Better Developer Experience** - Auto-completion shows correct methods
- ✅ **Type Safety** - Eliminates need for type assertions (`as`)
- ✅ **Compile-Time Errors** - Catch incorrect method calls immediately
- ✅ **Backward Compatible** - Existing code continues to work

### Migration Notes

No breaking changes. This is a pure TypeScript improvement that enhances existing functionality.

If you were using type assertions:
```typescript
// Before - manual type assertion
const element = elements?.getElement('add-payment-method') as AddPaymentMethodElementInstance

// After - automatic type narrowing (type assertion no longer needed)
const element = elements?.getElement('add-payment-method')
```

---

## [0.1.16]

### Bug Fixes

**Fixed: PaymentElement Types Resolving to `any` for Consumers**

Types like `PaymentElementAppearance`, `PaymentElementOptions`, and `PaymentElementLocale` were showing as `any` in consumer IDEs. This was because the types were defined as indexed access types from `@stripe/stripe-js`, which consumers didn't have installed.

**Before:**
```typescript
// In consumer's IDE
PaymentElementAppearance = any
elementAppearance?: any
elementOptions?: any
```

**After:**
```typescript
// In consumer's IDE - proper type definitions
PaymentElementAppearance = { theme?: 'stripe' | 'night' | 'flat'; variables?: {...}; ... }
elementAppearance?: PaymentElementAppearance
elementOptions?: PaymentElementOptions
```

### Technical Details

- Created new `src/types/stripe-element.types.ts` with inlined Stripe type definitions
- Types are now self-contained and don't require consumers to install `@stripe/stripe-js`
- Full IDE autocomplete and type checking now works for all payment element props

### Migration Notes

No breaking changes. This is a fix for existing functionality - types that were previously `any` now resolve correctly.

---

## [0.1.15]

### What's New

**TypeScript Types for AddPaymentMethod Element**

We've added TypeScript type exports for the AddPaymentMethod element to improve developer experience and type safety:

```tsx
import type {
  PaymentElementAppearance,
  PaymentElementOptions,
  PaymentElementLocale,
  PaymentElementFormResult,
} from '@zenskar/ui-kit'

// Or from the specific element export
import type {
  PaymentElementAppearance,
  PaymentElementOptions,
  PaymentElementLocale,
  PaymentElementFormResult,
} from '@zenskar/ui-kit/AddPaymentMethodElement'

// Use in your components
const customAppearance: PaymentElementAppearance = {
  theme: 'night',
  variables: {
    colorPrimary: '#635bff',
  },
}

const options: PaymentElementOptions = {
  layout: { type: 'tabs' },
  fields: { billingDetails: 'auto' },
}
```

**Payment Method Type Control**

You can now control which payment methods are available without fetching organization config:

```tsx
// Card only (skips org config fetch)
<AddPaymentMethod paymentMethodTypes={['card']} />

// Both card and US bank account
<AddPaymentMethod paymentMethodTypes={['card', 'us_bank_account']} />

// Use organization config (default behavior)
<AddPaymentMethod paymentMethodTypes={[]} />
// or simply
<AddPaymentMethod />
```

**Automatic Locale Detection**

The `elementLocale` prop now defaults to `'auto'`, which automatically detects the user's browser language:

```tsx
// Automatic detection (new default)
<AddPaymentMethod />

// Explicit locale
<AddPaymentMethod elementLocale="fr" />

// All available locales
<AddPaymentMethod elementLocale="en" /> // English
<AddPaymentMethod elementLocale="es" /> // Spanish
<AddPaymentMethod elementLocale="de" /> // German
// ... and many more
```

### New Features

- **Type Exports**: `PaymentElementAppearance`, `PaymentElementOptions`, `PaymentElementLocale`, `PaymentElementFormResult` are now exported from the package
- **Payment Method Control**: New `paymentMethodTypes` prop to control available payment methods
- **Auto Locale**: `elementLocale` defaults to `'auto'` for automatic language detection

**Customer Contracts API Methods**

- **`customer.contracts(params)`**: Fetch paginated list of customer contracts
  - Returns only contracts with `ACTIVE` or `PAUSED` status
  - Supports cursor-based pagination and sorting
  
- **`customer.contractById(contractId)`**: Fetch a specific contract by ID
  - Returns contract details only if it belongs to the authenticated customer
  - Returns 404 error if contract doesn't exist or doesn't belong to the customer
  - Parameter: `contractId` (string, required)

### Behavior Changes

- **Locale Default**: `elementLocale` now defaults to `'auto'` instead of `undefined`
- **Conditional Org Fetch**: Organization details are only fetched when `paymentMethodTypes` is not provided or is an empty array

### Migration Notes

No breaking changes. All new features are opt-in.

**Using Type Exports:**
```tsx
// Before - had to manually type or use 'any'
const appearance: any = { theme: 'night' }

// After - proper type safety
import type { PaymentElementAppearance } from '@zenskar/ui-kit'
const appearance: PaymentElementAppearance = { theme: 'night' }
```

**Controlling Payment Methods:**
```tsx
// Before - always used organization config
<AddPaymentMethod />

// After - can specify directly
<AddPaymentMethod paymentMethodTypes={['card']} />
```

---

## [0.1.14]

### What's New

**PaymentHistory Component**
```tsx
// Old
import { TransactionHistory } from '@zenskar/ui-kit'

// New (recommended)
import { PaymentHistory } from '@zenskar/ui-kit'
```

**customer.payments() Method**
```tsx
// Old
const { data } = await zenskar.customer.transactions()

// New (recommended)
const { data } = await zenskar.customer.payments()
```

**New Type Exports**
```tsx
import type {
  Payment,        // Replaces Transaction
  PaymentsList,   // Replaces TransactionsList
  EPaymentType,
  EPaymentStatusType
} from '@zenskar/ui-kit'
```

### Bug Fixes

**AddPaymentMethod Customization Now Works**
- ✅ `elementOptions.layout` is no longer ignored
- ✅ `elementAppearance.theme` is no longer hardcoded to 'stripe'
- ✅ Custom `rules` and `variables` now merge properly

```tsx
// This now works!
<AddPaymentMethod
  elementOptions={{
    layout: { type: 'accordion', defaultCollapsed: true }
  }}
  elementAppearance={{
    theme: 'night', // Works now!
    rules: { '.Input': { border: '1px solid red' } }
  }}
/>
```

### Deprecated (Will be Removed in v1.0.0)

Old names still work but show deprecation warnings:
- `TransactionHistory` → use `PaymentHistory`
- `customer.transactions()` → use `customer.payments()`
- `Transaction` type → use `Payment`
- `TransactionsList` type → use `PaymentsList`

### Why the Rename?

The old names were confusing. The data is actually **payment objects** that contain nested transaction events:

```tsx
const { data } = await zenskar.customer.payments()

data.results.forEach(payment => {
  console.log(payment.id)      // Payment ID
  console.log(payment.amount)  // Payment amount

  // Each payment has transaction events
  payment.transactions.forEach(txn => {
    console.log(txn.timestamp)
  })
})
```

## Migration Guide

### Migrating from Old API

**Step 1: Update Imports**
```tsx
// Before
import { TransactionHistory } from '@zenskar/ui-kit'
import type { Transaction, TransactionsList } from '@zenskar/ui-kit'

// After
import { PaymentHistory } from '@zenskar/ui-kit'
import type { Payment, PaymentsList } from '@zenskar/ui-kit'
```

**Step 2: Update Service Calls**
```tsx
// Before
const { data } = await zenskar.customer.transactions({ limit: 10 })

// After
const { data } = await zenskar.customer.payments({ limit: 10 })
```

**Step 3: Update Component Usage**
```tsx
// Before
<TransactionHistory title="Transaction History" />

// After
<PaymentHistory title="Payment History" />
```

**No rush!** Old names work until v1.0.0.

---
