# @mirai/core

# 1. Installation

Installing Mirai's new core is straightforward. You'll only need to include two files in your HTML page.

## 1.1 Requirements

The first file is the stylesheet for the default theme. This file contains only CSS variable assignments, ensuring that it won't conflict with any existing styles in your project. Here’s how to include it:

```html
<head>
  <link
    rel="preload"
    as="style"
    href="https://static.mirai.com/core/index.css"
    onload="this.onload=null;this.rel='stylesheet'"
  />
  ...
</head>
```

The second file is the component repository JavaScript. This file provides an asynchronous loading system for the components, so it minimally impacts your page’s loading performance. Here’s an example:

```html
  ...
  <script async type="module" defer src="https://static.mirai.com/core/index.js"></script>
</body>
```

## 1.2 Creating a data repository instance

Once the two core files are included, you’ll need to specify the data repository you want to load. This is done by adding an HTML element to your page:

```html
<body>
  <div data-mirai-id="501404"></div>
  ...
</body>
```

You can configure this instance with the following attributes:

- `data-mirai-id`: The hotel or chain identifier.
- `data-type`: Type of instance (default is `hotel`)
- `data-hotel`: Hotel identifier (only used when `data-type=chain`)
- `data-locale`: Specify a locale if different from the default language.
- `data-currency`: Specify a currency if different from the default.

Here’s a complete example with all the attributes:

```html
<body>
  <div data-mirai-id="500255" data-type="chain" data-currency="JPY" data-locale="ja-JA"></div>
  ...
</body>
```

For testing, you can also hydrate the instance using URL parameters. Here’s an example:

```
https://hotel.com/endpoint?miraiId=10030559&type=chain&hotel=100376545
```

## 1.3 Environments

Mirai’s new core supports multiple execution environments, primarily differing in how the code is compiled:

- `Production` (https://static.mirai.com) This bundle is optimized, with code minified and obfuscated for maximum performance.
- `Development` (https://static.mirai-int.io) This bundle is generated in development mode with source maps, and services are also in development mode.

# 2. Components

To instantiate any component from the core repository, there are a few common properties you need to be aware of:

- `data-mirai-component:string`: Specifies the name of the component to instantiate.
- `data-mobile:bool`: Indicates if the component should only be instantiated in a mobile environment.
- `data-desktop:bool`: Indicates if the component should only be instantiated in a non-mobile environment.

Here’s an example of how to instantiate a component:

```html
<div data-mirai-component="finder" data-mobile="true"></div>
```

### Ghosting & Bindings

Some components support a ghosting system, which allows them to receive different HTML markup than their default configuration. To enable this, you must set the data-ghost attribute.

Additionally, the bracket binding system provides two different functionalities:

- **Single brackets**: Used for binding component state variables, allowing dynamic values to be inserted into UI elements.
- **Double brackets**: Used to bind dictionary keys, making it easy to inject structured data, such as predefined text, into templates or UI components.

This system is useful for separating presentation logic from data and allows for more flexibility when developing components.

Example of bracket binding:

```html
"[[common.label.greetings]], [firstName]! Welcome to our hotel."
```

In this example, `[[common.label.greetings]]` will be replaced by the value from the dictionary associated with the key common.label.greetings, while `[firstName]` will be replaced by the component’s state variable firstName.

## 2.1 `<Booking>`

The `<Booking>` component provides a summary view of a specific reservation. Its implementation is very simple. You only need to add the following to your webpage:

```html
<div data-mirai-component="booking"></div>
```

## 2.2 `<BookingQuery>`

The `<BookingQuery>` component displays a modal where the user is prompted to enter a `bookingId` and `pinCode`. If both fields are correct, the user is redirected to the reservation management page.

```html
<div data-mirai-component="bookingQuery"></div>
```

This component supports _ghosting_, allowing you to customize the HTML structure.

Here’s a simple example:

```html
<div data-mirai-component="bookingQuery">
  <button data-ghost>Booking Query</button>
</div>
```

## 2.3 `<ButtonFinder>`

The `<ButtonFinder>` component encapsulates the finder component within a modal, which becomes visible when the button is pressed. This is ideal for scenarios where you want to display a search interface only when necessary, keeping the main interface clean and uncluttered.

```html
<div data-mirai-component="button-finder"></div>
```

Like other components, it supports ghosting, allowing customization of the button or other UI elements.

Here’s an example:

```html
<div data-mirai-component="session">
  <div data-ghost>
    <button data-ghost>[[common.action.reserve]]</button>
  </div>
</div>
```

Additionally, the data-text property lets you customize the button’s label, offering flexibility to adapt the button text to your needs.

```html
<div data-mirai-component="button-finder" data-text="Start Search"></div>
```

## 2.4 `<Chat>`

The `<Chat>` component is one of the new additions to the Mirai library. It allows you to instantiate a chat system powered by a virtual agent using artificial intelligence. This assistant can handle most of the Mirai suite's functionalities through conversational interactions.

```html
<div data-mirai-component="chat"></div>
```

At Mirai, we prioritize the customization of our components to ensure they seamlessly integrate with your website's design. To facilitate this, we provide a set of CSS variables that allow you to modify most visual aspects of the `<Chat>` component.

Here’s an example of the CSS variables available for customization:

```css
--mirai-chat-accent: var(--mirai-ui-accent);
--mirai-chat-border-color: var(--mirai-ui-content-border);
--mirai-chat-border-radius: var(--mirai-ui-space-S);
--mirai-chat-border-size: 1px;
--mirai-chat-space: var(--mirai-ui-space-M);
--mirai-chat-motion-collapse: 200ms;
--mirai-chat-motion-expand: 300ms;
--mirai-chat-motion-easing: cubic-bezier(0.1, 0.1, 0.25, 0.9);
--mirai-chat-text-accent-color: rgba(255, 255, 255, 0.95);
--mirai-chat-text-color: var(--mirai-ui-content);
--mirai-chat-text-color-light: var(--mirai-ui-content-light);
--mirai-chat-text-font: var(--mirai-ui-font-medium);
--mirai-chat-text-font-size: var(--mirai-ui-font-size-action);
--mirai-chat-text-font-weight: var(--mirai-ui-font-medium-weight);
--mirai-chat-text-line-height: var(--mirai-ui-line-height-action);
--mirai-chat-base: var(--mirai-ui-base);
--mirai-chat-base-opacity: rgba(255, 255, 255, 0.8);
--mirai-chat-box-shadow: var(--mirai-ui-shadow);
--mirai-chat-height: 70svh;
--mirai-chat-max-height: calc(100svh - calc(var(--mirai-chat-space) * 2));
--mirai-chat-min-height: 640px;
--mirai-chat-layer: var(--mirai-ui-layer-XL);
--mirai-chat-width: calc(var(--mirai-ui-breakpoint-S) - var(--mirai-ui-space-XXL));
--mirai-chat-header-height: calc(var(--mirai-ui-space-M) * 4);
--mirai-chat-header-background: linear-gradient(0deg, var(--mirai-chat-base-opacity) 0%, var(--mirai-chat-base) 100%);
--mirai-chat-input-background: var(--mirai-ui-content-background);
--mirai-chat-input-border-color: var(--mirai-chat-border-color);
--mirai-chat-input-border-color: transparent;
--mirai-chat-message-background: transparent;
--mirai-chat-message-offset: calc(var(--mirai-chat-space) / 1.5) var(--mirai-chat-space);
--mirai-chat-avatar-background: rgba(0, 0, 0, 0.66);
--mirai-chat-avatar-color-1: var(--mirai-ui-accent);
--mirai-chat-avatar-color-2: var(--mirai-ui-accent-dark);
--mirai-chat-avatar-color-3: var(--mirai-ui-accent-border);
--mirai-chat-avatar-color-4: var(--mirai-ui-accent-background);
--mirai-chat-avatar-border-radius: 40%;
--mirai-chat-avatar-size: 72px;
```

These CSS variables offer a wide range of customization options, from changing colors and borders to adjusting text and layout. By using them, you can tailor the `<Chat>` component to fit perfectly within the design of your website.

## 2.5 `<Checkout>`

The `<Checkout>` component is the main reservation window, where users can enter their personal details, choose payment methods, and set notifications for the hotel. It also provides a summary of the reservation before the user proceeds with the booking process.

```html
<div data-mirai-component="checkout"></div>
```

## 2.6 `<Deals>`

The `<Deals>` component displays a form that allows users to search for rooms with a specific offer. This form contains three fields:

- `calendar` (check-in & check-out dates)
- `occupation` (number of guests)
- `promocode` (optional promotional code)

```html
<div data-mirai-component="deals" data-id="293842"></div>
```

This component requires a data-id attribute, which contains the ID of the offer to be displayed.

Additionally, like other components, the `<Deals>` component offers some light visual customization through CSS variables:

```css
--mirai-deals-notification-max-width: calc(var(--mirai-ui-calendar-cell) * 14 + var(--mirai-ui-calendar-padding) * 2);
```

## 2.7 `<Environment>`

The `<Environment>` component allows you to modify the environment in which the other Mirai components are running. The environment is defined as the combination of language and currency. This component lets you adjust three properties:

- `data-currency:bool`: Controls the visibility of the currency selector (true/false).
- `data-locale:bool`: Controls the visibility of the language selector (true/false).
- `data-state:bool`: Controls the visibility of the current state data (true/false).

Here’s an example of its implementation:

```html
<div data-mirai-component="environment" data-currency="true" data-locale="true"></div>
```

## 2.8 `<Finder>`

The `<Finder>` component displays the general accommodation search interface. Here’s a basic example:

```html
<div data-mirai-component="finder"></div>
```

You can customize specific properties using HTML data attributes:

- `data-icon="true"`: Displays an icon on the button instead of the localized search text.
- `data-inline="false"`: Displays each input in the same format as an `<InputField>`.
- `data-layout="{type}}"`:
  - `"column"`: Displays the component in a column layout.
  - `"expand"`: Displays the component in an expand layout.

You can also adjust various visual properties using the CSS variables exposed by the component:

```css
--mirai-field-background: var(--mirai-ui-base);
--mirai-field-background-active: var(--mirai-ui-content-background);
--mirai-field-border: var(--mirai-ui-input-text-border);
--mirai-field-border-active: var(--mirai-ui-input-color-active);
--mirai-field-border-radius: var(--mirai-ui-border-radius);
--mirai-field-height: calc(var(--mirai-ui-input-min-height) + var(--mirai-ui-space-XXS));
--mirai-field-content-color: var(--mirai-ui-content);
--mirai-field-icon-color: var(--mirai-field-content-color);
--mirai-field-label-color: var(--mirai-ui-content-light);

--mirai-finder-background: var(--mirai-ui-base);
--mirai-finder-border: var(--mirai-ui-input-text-border);
--mirai-finder-border-radius: var(--mirai-ui-border-radius);
--mirai-finder-button-background: var(--mirai-ui-button-background);
--mirai-finder-button-background-active: var(--mirai-ui-button-background-active);
--mirai-finder-button-border-radius: var(--mirai-ui-border-radius);
--mirai-finder-button-color: var(--mirai-ui-button-color);
--mirai-finder-button-color-active: var(--mirai-ui-base);
--mirai-finder-button-font-family: var(--mirai-ui-font);
--mirai-finder-button-font-size: inherit;
--mirai-finder-button-font-weight: var(--mirai-ui-button-font-weight);
--mirai-finder-gap: 0;
--mirai-finder-padding: var(--mirai-ui-space-XS);
--mirai-finder-separator-color: var(--mirai-ui-content-border);
```

Additionally, you can visually customize three fields within this component:

- Hotel
- Date
- Occupation

The following CSS variables are available for customization:

```css
/* Calendar */
--mirai-finder-calendar-padding: var(--mirai-ui-space-M);

/* Occupation */
--mirai-occupation-scrollview-max-height: 340px;
--mirai-occupation-width: 320px;

/* Places */
--mirai-places-item-height: 32px;
--mirai-places-item-width: 300px;
--mirai-places-item-background-selected: var(--mirai-ui-accent);
--mirai-places-item-color-selected: var(--mirai-ui-base);
--mirai-places-padding: var(--mirai-ui-space-M);
--mirai-places-items-per-column: 9;
```

These variables allow you to control the padding, dimensions, and other styling aspects of the calendar, occupation selector, and places fields, offering greater flexibility to align the component with your website’s design.

### Events

The component features input and output events. To modify the state, you must publish the `setStore` event. To track changes in the state, subscribe to the `finderChange` event. To retrieve the values when the finder is initialized, subscribe to the `finderLoaded` event.

To ensure the `Mirai.Event` infrastructure is ready for publishing and subscribing to events, listen for the standard HTML event `MIRAI:EVENT:core:events:ready`:

```javascript
document.addEventListener('MIRAI:EVENT:core:events:ready', () => {
  // Now you can safely subscribe to finder events
});
```

### Using the `setStore` Event

The `setStore` event allows you to update the component's state by publishing data. You can include one or more values as needed:

```javascript
window.Mirai.Event.publish('setStore', {
  chainSelectorValue: 111222,
  calendar: [new Date(), new Date()], // An array representing a date range
  hsri: '02080',
  occupation: [
    { ages: [null, null], amount: 2, type: 2 }, // Type 2: adults
    { ages: [3], amount: 1, type: 3 }, // Type 3: children
  ],
  promocode: 'TEST',
});
```

**Notes:**

- `type` values: 1 = guest, 2 = adult, 3 = children.
- You can send partial data (e.g., only `promocode`) or the full object.

### Using the `finderChange` Event

The `finderChange` event notifies you when a field in the finder changes. It provides the affected field, its previous value, and the new value:

```javascript
window.Mirai.Event.subscribe('finderChange', ({ field, previousValue, value } = {}) => {
  // Possible field values: 'place', 'calendar', 'occupation', 'promocode'
  console.log(`Field ${field} changed from ${previousValue} to ${value}`);
});
```

### Using the `finderLoaded` Event

The `finderLoaded` event fires when the finder is fully loaded, providing the initial values of its fields:

```javascript
window.Mirai.Event.subscribe('finderLoaded', ({ calendar, occupation, place, promocode } = {}) => {
  console.log('Finder loaded with:', { calendar, occupation, place, promocode });
});
```

### Using the `logged` Event

The `logged` event is fired after a successful user login. This event provides user information and is primarily used for analytics tracking.

```javascript
window.Mirai.Event.subscribe('logged', ({ event, response } = {}) => {
  // event: 'logged'
  // response contains user information after login
  console.log('User logged in:', response);
  console.log('User details:', {
    email: response.email,
    firstName: response.firstName,
    lastName: response.lastName,
    country: response.country,
    level: response.level,
  });
});
```

**Event Data Structure:**

- `event`: The event type (`'logged'`)
- `response`: Object containing user information:
  - `email`: User's email address
  - `firstName`: User's first name
  - `lastName`: User's last name
  - `country`: User's country
  - `level`: User's membership level

**Notes:**

- This event is automatically published after successful authentication via the login modal
- Subscribe to this event to implement custom user authentication workflows or analytics

### Using the `loggedOut` Event

The `loggedOut` event is fired when a user logs out or when their session expires. This event provides the user information that was available before logout.

```javascript
window.Mirai.Event.subscribe('loggedOut', () => {
  // event: 'loggedOut'
});
```

**When is this event triggered:**

- Manual logout via the session menu
- Automatic logout due to external token expiration

**Notes:**

- This event is published before the session is cleared from the store
- Use this event to implement custom logout workflows or cleanup processes

### Using the `chatOpen` Event

The `chatOpen` event triggers the display of the `<Chat>` visual component. When this event is published, the chat interface will automatically appear, allowing the user to start a conversation or inquiry.

```javascript
window.Mirai.Event.publish('chatOpen');
```

### Using the `cookieBannerOpen` Event

The `cookieBannerOpen` event triggers the display of the `<CookieBanner>` visual component. When this event is published, the cookie banner will automatically appear, allowing the user to accept or decline the use of cookies.

```javascript
window.Mirai.Event.publish('cookieBannerOpen');
```

### Using the `cookieBannerSkippedByCountry` Event

The `cookieBannerSkippedByCountry` event is fired when the cookie banner is not shown because cookie consent is inactive for the current country.

```javascript
window.Mirai.Event.subscribe('cookieBannerSkippedByCountry', () => {
  console.log('Cookie banner skipped because country is inactive');
});
```

**When is this event triggered:**

- Cookie banner is disabled by country configuration (`countryInactive = true`)

**Notes:**

- This is an output event published by core
- The event does not include a payload

## 2.9 `<Header>`

The `<Header>` component is another new addition to the Mirai component suite. It allows you to create a header for your pages that can include:

- The hotel logo and/or name
- The status of the booking process (e.g., Choose, Personal Details, Confirmation)
- A language selector
- A currency selector
- Access to the user session

Some of these elements are automatically managed within the Mirai component. However, you can control certain elements using the following HTML attributes:

- `data-currency:bool`: Displays the currency selector.
- `data-locale:bool`: Displays the language selector.
- `data-login:bool`: Displays the session login button.
- `data-name:bool`: Displays the hotel name.

Here’s an example of how you might implement the component:

```html
<div data-mirai-component="header" data-currency="true" data-locale="true"></div>
```

## 2.10 `<Profile>`

The `<Profile>` component displays two tabs: Personal Information and My Bookings.

- **Personal Information**: Allows the logged-in user to manage their personal details, change their password, and delete their account.
- **My Bookings**: Allows the logged-in user to manage their bookings, including the option to cancel bookings.

Here’s how to implement the component:

```html
<div data-mirai-component="profile"></div>a-mirai-component="profile"></div>
```

## 2.11 `<Rates>`

The `<Rates>` component is used for selecting rooms and rates. It includes a feature/flag system that allows you to customize the visibility and layout of various elements through URL parameters. The possible values it can receive are:

- `columnMode`: Displays the results in two columns.
- `hideRadio`: Hides the radio input and replaces it with a button.
- `hideStandaloneBoard`: If only one accommodation type is available, it will not be displayed.
- `showAllBoards`: Displays all available boards (only the boards belonging to the active rate are selectable).
- `showAllOffers`: Displays all available offers (only the offers belonging to the active cancellation are selectable).
- `showMaxOccupation`: Displays the maximum room occupancy.
- `showOffersFirst`: Changes the selection process to offer + board. The default process is cancellation + offer + board.
- `showPreviewPrice`: Displays a total price summary in the footer.
- `showPricePerNight`: Displays prices per night.
- `showRateIncluded`: Displays the inclusions of each rate without using a tooltip.

Here’s an example of how to use it:

`http://....&features=showOffersFirst,showClubDiscount`

> Note: You can combine multiple features by separating them in the `features` URL parameter using a comma `,`.

## 2.12 `<Session>`

The `<Session>` component has two behaviors. If the user is not logged in, it shows an action button that opens a login modal. If the user is logged in, it displays a menu with two options: Personal Information and My Bookings.

```html
<div data-mirai-component="session"></div>
```

Use `data-headless="true"` to keep the component mounted without rendering the login button or account menu. The login modal can then be opened with `Mirai.Event.publish('login')`.

```html
<div data-mirai-component="session" data-headless="true"></div>
```

This component supports _ghosting_. If only one HTML structure is provided, it will be used for the login component. Alternatively, two different HTML structures can be used: one for the login view and another for the logged-in/account view.

Here’s an example:

```html
<div data-mirai-component="session">
  <div data-ghost>
    <div data-ghost>
      {/* Session.Login */}
      <span>[[common.action.login]]</span>
      {/* Session.Account */}
    </div>
  </div>
</div>
```

In this example, we replace the default HTML markup with a button containing the text `Login Here`:

```html
<div data-mirai-component="session">
  <div data-ghost>
    <p class="login">Login Here</p>
    <p class="account">Account</p>
  </div>
</div>
```

In this example, we replace the markup with two `<p>` elements, one for login and one for account:

```html
<div data-mirai-component="session">
  <div data-ghost>
    <p class="login">Login</p>
    <p class="account">[firstName] [lastName] - [email] - ExampleText</p>
  </div>
</div>
```

You can also bind session elements to dynamic data, like this:

```html
<div data-mirai-component="session">
  <div data-ghost>
    <p class="login">Login</p>
    <p class="account">[firstName] [lastName] - [email] - ExampleText</p>
  </div>
</div>
```

This allows you to display personalized information for the logged-in user, such as their name or email.

## 2.13 `<Signup>`

The `<Signup>` component displays the registration form for the Mirai platform.

```html
<div data-mirai-component="signup"></div>
```

# 3. Development

You have to follow the next steps:

1. Install [node.js](https://nodejs.org/en/download/package-manager) and [yarn](https://classic.yarnpkg.com/lang/en/docs/install/#mac-stable).
2. Clone the project with SSH git@gitlab.com:miraicorp/front/core.git or HTTPS https://gitlab.com/miraicorp/front/core.git.
3. In the project, execute `yarn` command. This command install the dependencies.
4. Change the file `env.development` to put the service url that you want.
5. Add to local.mirai.com to hosts file and keep free 8080 port. Or you can change the file `/scripts/start.js` to choose the port and host that you want.
6. Execute `yarn start` command.
7. You can manage the hotel that you want to test with the `miraiId` param. For example, for the Hotel Moderno, you need to type the next in the navigator url: http://local.mirai.com:8080/?miraiId=10030559. If you want to test a chain, you need add the param `type=chain`. For example, for Garden, the url is http://local.mirai.com:8080/?miraiId=501404&type=chain.
8. You can access to Checkout (Client form) and Booking (Manage reservation) directly with the next urls http://local.mirai.com:8080/step2-checkout and http://local.mirai.com:8080/step3-booking. Add `miraiId` param and the params of Client Form url or Manage reservation url to test.
