# Core Utilities and Helpers

These utilities are imported from `@limio/sdk` (or its subpaths) and are available in any custom component. They are ordered below roughly by how commonly they are used across production components.

{% hint style="info" %}
Offer-specific helpers (`useOfferInfo`, `checkActiveOffers`, `groupOffers`) are documented on the [Page, Offers & Add-Ons](https://docs.limio.com/developers/limio-sdk/page) page. Invoice fetching (`LimioFetchers.invoiceFetch`) is documented on the [Billing & Account](https://docs.limio.com/developers/limio-sdk/billing-account) page.
{% endhint %}

***

## sanitiseHTML

An HTML sanitisation function that should be used whenever rendering content from offers or CMS fields via `dangerouslySetInnerHTML`. It uses [DOMPurify](https://github.com/cure53/DOMPurify) under the hood and automatically adds security attributes to links.

Most offer attributes that contain rich text — such as `offer_features__limio`, `display_description__limio`, or any `__limio_richtext` prop — should be passed through `sanitiseHTML` before rendering.

```typescript
function sanitiseHTML(dirty?: string): string
```

```tsx
import { sanitiseHTML } from "@limio/sdk"

const OfferFeatures = ({ offer }) => {
  const featuresHtml = offer.data.attributes.offer_features__limio

  return (
    <div dangerouslySetInnerHTML={{ __html: sanitiseHTML(featuresHtml) }} />
  )
}
```

**Behaviour:**

1. Strips all non-HTML-safe tags and attributes.
2. Preserves the `target` attribute on links.
3. Automatically adds `rel="noopener noreferrer"` to links with `target="_blank"`, and `rel="noopener"` to links with other target values.
4. Throws an error if called in a non-browser environment without DOM support (a Node.js version is available internally for SSR).

> **Important:** Always use `sanitiseHTML` when rendering user-controlled or offer-sourced HTML with `dangerouslySetInnerHTML`. This prevents XSS attacks from malicious content in offer attributes.

***

## ErrorBoundary

A React error boundary component that catches JavaScript errors in its child component tree and displays a fallback UI. Errors are automatically reported to Sentry.

Limio wraps individual components in an error boundary as part of the build step, so it is **not necessary to use at the top level**. However, `ErrorBoundary` is useful for wrapping specific children that may error where the parent component should remain functional — for example, a subscription details panel that fetches external data.

**Props:**

| Prop       | Type                                    | Description                        |
| ---------- | --------------------------------------- | ---------------------------------- |
| `children` | `React.ReactNode`                       | The component tree to wrap         |
| `ErrorUI`  | `React.ComponentType<{ error: Error }>` | Optional custom fallback component |

```tsx
import { ErrorBoundary } from "@limio/sdk"

const ParentComponent = ({ offer }) => {
  return (
    <div>
      <h1>This will always render</h1>
      <ErrorBoundary>
        <ChildThatMayError offer={offer} />
      </ErrorBoundary>
    </div>
  )
}
```

With a custom error UI:

```tsx
import { ErrorBoundary } from "@limio/sdk"

const MyErrorFallback = ({ error }) => (
  <p>Something went wrong: {error.message}</p>
)

const Component = () => (
  <ErrorBoundary ErrorUI={MyErrorFallback}>
    <RiskyComponent />
  </ErrorBoundary>
)
```

**Behaviour:**

1. Catches errors during rendering, in lifecycle methods, and in constructors of child components.
2. Does **not** catch errors in event handlers — use try/catch for those.
3. Logs all caught errors to Sentry with component stack info.
4. A HOC version is also available: `withErrorBoundary(Component, ErrorUI)`.

***

## Formatters

### formatCurrency

Formats a numeric amount with a currency code and optional locale. This is the most commonly used price formatter — use it in subscription tables, invoice lists, and anywhere you display monetary values.

```typescript
import { formatCurrency } from "@limio/sdk"

formatCurrency(amount: string | number, currencyCode: string, locality?: string): string
```

```javascript
formatCurrency(29.00, "USD")       // "$29.00"
formatCurrency(29.00, "GBP", "en") // "£29.00"
```

**Parameters:**

* `amount`: `string | number` — The amount to format.
* `currencyCode`: `string` — ISO 4217 currency code (e.g. `"USD"`, `"EUR"`).
* `locality` (optional): `string` — Locale for formatting.

### formatCurrencyForCurrentLocale

A convenience wrapper around `formatCurrency` that automatically resolves the locale from the `limio-country` cookie. Use this when you want locale-aware formatting without manually specifying a locale — common in cart summaries and checkout components.

```typescript
import { formatCurrencyForCurrentLocale } from "@limio/sdk"

formatCurrencyForCurrentLocale(amount: number | string, currency: string): string
```

```javascript
// UK user: formatCurrencyForCurrentLocale(10.99, "GBP") → "£10.99"
// US user: formatCurrencyForCurrentLocale(10.99, "USD") → "$10.99"
```

**Parameters:**

* `amount`: `number | string` — The amount to format.
* `currency`: `string` — The ISO 4217 currency code.

**Returns:** A formatted currency string using the browser's `Intl.NumberFormat` API.

> Use `formatCurrency` if you need to specify a locale explicitly.

### formatDate

Formats an ISO date string into a human-readable date. Use this when displaying subscription start/end dates, invoice dates, or billing cycle information.

```typescript
import { formatDate } from "@limio/sdk/date"

formatDate(date: string, format?: string): string
```

```javascript
formatDate("2023-12-14T11:19:29.442Z", "DATE_EN")   // "14 Dec 2023"
formatDate("2023-12-14T11:19:29.442Z", "DATE_FULL")  // "December 14, 2023"
formatDate("2023-12-14T11:19:29.442Z", "DATE_SHORT") // "14/12/2023"
formatDate("2023-12-14T11:19:29.442Z", "DATE_MED")   // "Dec 14, 2023"
```

**Parameters:**

* `date`: `string` — An ISO 8601 date string.
* `format` (optional): `string` — One of `"DATE_EN"`, `"DATE_FULL"`, `"DATE_SHORT"`, `"DATE_MED"`. If omitted, defaults to the Limio app locale settings.

### formatDisplayPrice

Formats a template string by replacing placeholders with values from a price object. Useful for rendering configurable price display strings that include currency symbols and amounts.

```typescript
import { formatDisplayPrice } from "@limio/sdk/price"

formatDisplayPrice(template: string, offerPrice: LimioPrice[]): string
```

```javascript
const priceString = "The price is {{currencySymbol}}{{amount}}."
const offerPrice = [{ currencyCode: "USD", value: "10.99" }]

formatDisplayPrice(priceString, offerPrice) // "The price is $10.99."
```

**Parameters:**

* `template`: `string` — A string containing placeholders (e.g. `{{currencyCode}}`, `{{amount}}`).
* `offerPrice`: `Array<LimioPrice>` — Array of price objects; the first element is used.

***

## Component Props

`useComponentProps` and `getPropsFromPackageJson` are the standard way to load the configurable props defined in your component's `package.json`. Almost every custom component uses this pattern to read the values that content editors set in the Page Builder.

```tsx
import packageData from "./package.json"
import { useComponentProps, getPropsFromPackageJson } from "@limio/sdk"

export function useComponentStaticProps() {
  const defaultComponentProps = getPropsFromPackageJson(packageData)
  const componentProps = useComponentProps(defaultComponentProps)
  return componentProps
}

function Component() {
  const { title, showFeatures, ctaColor } = useComponentStaticProps()
  // Use title, showFeatures, ctaColor in your component
}
```

For full details on defining `limioProps` in your package.json, see [Prop Types](https://docs.limio.com/developers/custom-components/prop-types) and [Development Guidelines](https://docs.limio.com/developers/custom-components/development-guidelines).

***

## Address Helpers

Utilities for working with addresses — formatting, metadata lookups, and country-specific form configuration. Import from `@limio/sdk/address`. These are primarily used in account management and checkout components that collect or display delivery and billing addresses.

### addressSummary

Takes a Limio address object and returns a formatted single-line string. Returns `"N/A"` if the address is empty. Use this in subscription detail tables and payment method displays.

```typescript
import { addressSummary } from "@limio/sdk/address"

addressSummary(customerDetails.deliveryAddress)
// "123 John Street, London, EC1 25X"
```

### formatCountry

Converts an alpha-2 country code into the full country name.

```typescript
import { formatCountry } from "@limio/sdk/address"

formatCountry("GB") // "United Kingdom"
formatCountry("US") // "United States"
```

### getAddressMetadata

Returns which address fields are required and which should be rendered for a given country. Use this to build dynamic address forms that adjust their inputs based on the selected country — for example, showing a "State" field for US/CA but not for UK addresses.

```typescript
import { getAddressMetadata } from "@limio/sdk/address"

const { requiredAddressFields, addressFieldsToRender } = getAddressMetadata("CA")

// requiredAddressFields: ["address1", "state", "postalCode", "country"]
// addressFieldsToRender: ["address1", "address2", "city", "state", "postalCode", "country"]
```

**Returns:**

* `requiredAddressFields`: `string[]` — Fields that must be filled in.
* `addressFieldsToRender`: `string[]` — Fields that should appear in the form.

### getCountryMetadata

Returns metadata for a country including its full name and ISO codes.

```typescript
import { getCountryMetadata } from "@limio/sdk/address"

getCountryMetadata("GB")
// { name: "United Kingdom", "alpha-2": "GB", "alpha-3": "GBR", "country-code": "826" }
```

***

## DateTime

Limio re-exports `DateTime` from [Luxon](https://moment.github.io/luxon/) for date handling. Use it when `formatDate` isn't flexible enough — for example, when calculating days until renewal or comparing subscription periods.

```typescript
import { DateTime } from "@limio/sdk"

const now = DateTime.local()
const nextBilling = DateTime.fromISO(subscription.data.end)
const daysUntilRenewal = nextBilling.diff(now, "days").days
```

***

## LimioAppSettings

Provides access to global application settings configured in Limio. Currently exposes the configured date format.

```typescript
import { LimioAppSettings } from "@limio/sdk"

const dateFormat = LimioAppSettings.getDateFormat()
```

**Available methods:**

| Method            | Returns  | Description                                                  |
| ----------------- | -------- | ------------------------------------------------------------ |
| `getDateFormat()` | `string` | The date format configured for the current Limio environment |
