Components
Located in @kiwicom/nitro/lib/components/<component>
.
Features:
Utilities:
- BaggageOverview
- BaggagePaymentSummary
- BaggagePicker
- BaggagePickerBRBRedesign
- BookingSavingsBanner
- Button
- ClickOutside
- ClientOnly
- CloseByKey
- CookiesPopup
- CustomerBaggageTile
- DateInput
- Desktop
- InitAuth
- InitCurrency
- InitIntl
- InitLog
- InitRelayEnvironment
- InitStarred
- InputEmail
- InputPhone
- Itinerary
- LogMount
- Mobile
- Price
- Starred
- Text
- TextNode
- Toggle
- Translate
- TranslateNode
- TranslateRef
- Value
- ValueBind
Features
Actual components that do stuff. See storybook for a live example.
CookiesConsent
Import:
import CookiesConsent from "@kiwicom/nitro/lib/components/CookiesConsent";
Types:
type Props = {|
onAccept: () => void,
|};
declare export default React.ComponentType<Props>;
Context needs:
Selectors data-test
:
"CookiesConsent"
Closeable cookies thingie.
Currency
Import:
import Currency from "@kiwicom/nitro/lib/components/Currency";
Types:
type Props = {|
positionMenuTablet?: number,
positionMenuDesktop?: number,
inverted?: boolean,
onSetModal?: (modal: ModalType) => void,
// defaulted
native?: boolean,
loading?: React.Node,
|};
declare export default React.ComponentType<Props>;
See types:
Context needs:
Selectors data-test
:
"Currency"
"Currency-Open"
{`Currency-Item-${item.id}`}
A currency picker.
DatePicker
Import:
import DatePicker from "@kiwicom/nitro/lib/components/DatePicker";
Types:
type Props = {|
value: Date,
onChange: (date: Date) => void,
label: string,
icon?: React.Node,
min: Date,
max: Date,
|};
declare export default React.ComponentType<Props>;
Context needs:
TODOs
- DI
new Date()
into components for tests
Footer
Import:
import Footer from "@kiwicom/nitro/lib/components/Footer";
Types:
type Props = {||};
declare export default React.ComponentType<Props>;
Context needs:
HeaderLinks
Import:
import HeaderLinks from "@kiwicom/nitro/lib/components/HeaderLinks";
Types:
type Splitster = {
// FIXME add a firm structure
[key: string]: string,
};
type Response = {|
splitster: Splitster,
items: HeaderLink[],
|};
type Props = {|
languageId: string,
currencyId: string,
searchForm: SearchForm | null,
splitster: Splitster,
active?: string, // TODO maybe add specific if ids are also specified
inverted?: boolean,
newDesign?: boolean,
onFetch?: (services: Response) => void,
testResponse?: Response, // TODO DI actual API call
context?: HeaderLinksContext,
|};
declare export default React.ComponentType<Props>;
See types:
Context needs:
LocationPicker
Import:
import LocationPicker from "@kiwicom/nitro/lib/components/LocationPicker";
Types:
type Props = {|
value: Location | null,
onChange: (loc: Location) => void,
label: React.Node,
icon?: React.Node,
error?: React.Node,
// defaulted
environment?: Environment,
queryName?: "allLocations" | "holidaysLocations",
locationType?:
| "airport"
| "autonomous_territory"
| "city"
| "country"
| "station"
| "subdivision",
|};
declare export default React.ComponentType<Props>;
See types:
Context needs:
- Supports main and holidays gql location api.
- By default uses allLocations query voyager.
- To fetch specific location type allLocations has paramater called option, which is sent via locationType prop.
Example:
import LocationPicker from "@kiwicom/nitro/lib/components/LocationPicker";
import Translate from "@kiwicom/nitro/lib/components/Translate";
<LocationPicker
value={from}
onChange={setSomething()}
label={<Translate t="search.from" />}
/>;
with options
<LocationPicker
value={from}
onChange={setSomething()}
// option
locationType="airport"
label={<Translate t="search.from" />}
/>
holidays
<LocationPicker
value={from}
onChange={setSomething()}
// option
queryName="holidaysLocations"
label={<Translate t="search.from" />}
/>
MagicLogin
Import:
import MagicLogin from "@kiwicom/nitro/lib/components/MagicLogin";
Types:
type Props = {|
initialScreen: "intro" | "signUp",
type: "mmb" | "help" | "refer",
disableSocialLogin?: boolean,
onClose: () => void,
onSignIn: (user: AuthUser) => void,
onSocialLogin: (provider: SocialProvider) => Promise<void>,
onGetSimpleToken: AuthToken => void,
|};
declare export default React.ComponentType<Props>;
See types:
Context needs:
Selectors data-test
:
"MagicLogin"
"MagicLogin-AskForMagic"
"MagicLogin-BookingId"
"MagicLogin-CheckEmail"
"MagicLogin-CheckEmail"
"MagicLogin-CreateAccount"
"MagicLogin-Email"
"MagicLogin-Email"
"MagicLogin-Email"
"MagicLogin-GetSingleBooking"
"MagicLogin-GetSingleBookingBack"
"MagicLogin-GetSingleBookingSubmit"
"MagicLogin-IncorrectEmail"
"MagicLogin-Intro"
"MagicLogin-LoginViaSocials"
"MagicLogin-NoAccount"
"MagicLogin-NoAccountBack"
"MagicLogin-Password"
"MagicLogin-Password"
"MagicLogin-PasswordConfirm"
"MagicLogin-PasswordInput"
"MagicLogin-PasswordStrengthBar"
"MagicLogin-PasswordValidationStrengthLabel"
"MagicLogin-PasswordValidationTooltip"
"MagicLogin-SocialLogin"
Modal component handling the whole login flow with magic link.
Docs
WIKI - New login flow with magic link
Props
- disableSocialLogin - disable the possibility to login via social network on intro screen, which enables to bypass the whole login flow and user can log in even without previously existing account. Default: false
- initialScreen - by default it shows intro screen where user is asked for e-mail based on which following steps are decided. You can pass
signUp
to display registration form immediately. - type - Explains the reason why user is asked to login, current options are
mmb
to manage bookings,help
to get personalized help &refer
to refer a friend to get a bonus. Default:mmb
- onClose - callback to close the modal. TODO: should be handled probably by
ModalContext
in future.
data-test
attributes for acceptance tests
MagicLogin
can be used to test if modal is opened as it wraps the whole login modal.- Different stages of login process:
MagicLogin-Intro
- initial screen of the login (unless registration was triggered immediately)- additional section
MagicLogin-LoginViaSocials
is appended on same level in DOM asAccountLogin
unless login with social networks without e-mail check is disallowed.
- additional section
MagicLogin-CreateAccount
- registration formMagicLogin-Password
- login screen which asks for kiwi.com password.MagicLogin-SocialLogin
- screen which offers login via FB/Google after successful e-mail check.MagicLogin-NoAccount
- when user has no account or booking, this screen is displayed where he can either proceed with registration or go back to intro screen.MagicLogin-CheckEmail
- this is shown upon successful request to reset password or when e-mail with magic link is sent.
MagicLogin-CloseButton
- close button for the whole login modal.MagicLogin-AskForMagic
- button that sends e-mail with magic link when clickedMagicLogin-GetSingleBooking
- alternative one-time sign in form into single booking via bid & IATA code- Also, all inputs should have its own
data-test
attribute corresponding to their purpose -MagicLogin-Email
,MagicLogin-Password
Example
import * as React from "react"
import MagicLogin from "@kiwicom/nitro/lib/components/MagicLogin"
import type { AuthUser } from "@kiwicom/nitro/lib/records/Auth"
type Provider = "facebook" | "google"
type ConnectorHandlers = {|
onSocialLogin: (provider: Provider) => Promise<*>,
onSignIn: (userInfo: AuthUser) => void,
|}
type OwnProps = {|
disableSocialLogin: boolean,
initialScreen: "intro" | "signUp",
type: "mmb" | "help" | "refer",
onClose: () => void,
|}
type Props = {|
...ConnectorHandlers,
...OwnProps,
|}
// onSignIn fn should handle usual action which takes place after successful login via email & password
const onSignIn = (user) => ({ type: LOGIN_SUCCESS, res: user })
// onSocialLogin fn should trigger full OAuth login process thought specified provider
const onSocialLogin = (provider: Provider) => {}
// Redux connector HOC
const connector: Connector<OwnProps, Props> = connect(
null,
dispatch => ({
onSignIn: (user: AuthUser) => dispatch(onSignIn(user)),
onSocialLogin: (provider: Provider) => dispatch(onSocialLogin(provider)),
}),
)
export default connector(MagicLogin)
NavBar
Import:
import NavBar from "@kiwicom/nitro/lib/components/NavBar";
Types:
type NavElement = "currencies" | "help" | "starred" | "mmb" | "languages" | "logo" | "sideNav";
type Props = {|
starred: React.Node,
subscription: React.Node,
portal: string,
hide?: NavElement | NavElement[],
onOpenFaq: ?() => void,
onSetModal: (modal: Modal) => void,
onSaveLanguage: (lang: string) => void,
onSelectTrip: (bid: string) => void,
onLogoClick: (ev: SyntheticMouseEvent<HTMLAnchorElement>) => void,
// defaulted
headerLinks?: React.Node, // null
newDesign?: boolean,
debug?: React.Node, // null
inverted?: boolean, // false
animateLogo?: boolean,
logoAnimateShow?: boolean,
|};
declare export default React.ComponentType<Props>;
See types:
Context needs:
Selectors data-test
:
"NavBar"
"NavBar-Help"
"NavBar-SideNav"
"NavBar-SideNav-Close"
"NavBar-SideNav-Open"
SideBar
Import:
import SideBar from "@kiwicom/nitro/lib/components/SideBar";
Types:
type Props = {|
shown: boolean,
inverted?: boolean, // opens from the other side
unmasked?: boolean, // removes outer mask and disables onClick
onClick: () => void,
children: React.Node,
className?: string,
|};
declare export default React.ComponentType<Props>;
A container for a sidebar sliding from the right (left in RTL). It is appended to document.body
.
Utilities
Things that help in development.
BaggageOverview
Import:
import BaggageOverview from "@kiwicom/nitro/lib/components/BaggageOverview";
Types:
FAQLinksHandlerType,
DefinitionWithPassenger,
Definition,
OverviewContextType,
} from "../../records/Baggage";
type Props = {|
definitions?: Definition[],
definitionsWithPassengers?: DefinitionWithPassenger[],
FAQLinksHandler?: FAQLinksHandlerType,
context: OverviewContextType,
|};
declare export default React.ComponentType<Props>;
Context needs:
Selectors data-test
:
"BaggageOverview-BaggageItem-Passengers"
"BaggageOverview-NoPersonalItem"
{`BaggageOverview-${context}`}
-
{`BaggageOverview-BaggageItem-${category}`}
- renders baggage overview
- depending on props can be used as standalone component or wrapped in Container
Example:
standalone
<BaggageOverview
definitions={definitions}
FAQLinksHandler={category => {}}
context="MMB-PassengerCard"
/>
wrapped in Container
<Container
passengers={[
{
paxId: 3,
firstName: "George",
lastName: "Bush",
baggage: {
holdBag: 0,
handBag: 1
}
}
]}
baggage={baggageData}
context="booking"
>
{({ props }) => <BaggageOverview {...props} />}
</Container>
BaggagePaymentSummary
Import:
import BaggagePaymentSummary from "@kiwicom/nitro/lib/components/BaggagePaymentSummary";
Types:
type Passenger = {|
paxId: number,
firstName: string,
lastName: string,
baggage: {
holdBag: number,
handBag: number,
},
|};
type Props = {|
passengers: Passenger[],
baggage: BaggageType,
|};
declare export default React.ComponentType<Props>;
See types:
Context needs:
Selectors data-test
:
"BaggagePaymentSummary"
"BaggagePaymentSummary-TotalPayment"
{`BaggagePaymentSummary-PassengerBaggages-${paxId}-Price`}
-
{`BaggagePaymentSummary-PassengerBaggages-${paxId}`}
- renders baggage payment summary
- renders baggages per passenger with price per passenger
- renders summary price for all baggages in itinerary
Example:
<BaggagePaymentSummary
passengers={[
{
paxId: 1,
firstName: "Vaclav",
lastName: "Havel",
baggage: {
holdBag: 1,
handBag: 1
}
}
]}
baggage={baggageData}
/>
BaggagePicker
Import:
import BaggagePicker from "@kiwicom/nitro/lib/components/BaggagePicker";
Types:
type Props = {|
changeBagCombination: (picker: BaggageCategory, item: number) => void,
passengerCategory: PassengerGroup,
passengerBaggage: { handBag: number, holdBag: number },
baggage: BaggageType,
shouldShowRecheckNote?: boolean,
airlines: { [string]: Airline },
pickerType: BaggageCategory,
context: "booking" | "mmb",
currentCombination?: number,
prioBoardingLinkHandler?: (arg: Airline[]) => void,
description?: React.Node,
|};
declare export default React.ComponentType<Props>;
See types:
Context needs:
Selectors data-test
:
"BaggagePicker-EmptyLabel"
"BaggagePicker-EmptyOption"
"BaggagePicker-NoPersonalItemLabel"
"BaggagePicker-OptionItem-Current"
"BaggagePicker-OptionItem-Price"
"BaggagePicker-PriorityBoardingInfo"
"BaggagePicker-RecheckAlert"
"BaggagePicker-ShowButton"
{`BaggagePicker-${pickerType}`}
{`BaggagePicker-Option-${item.index}`}
-
{`BaggagePicker-OptionItem-${category}`}
- renders baggage picker
Example:
<BaggagePicker
airlines={airlines}
baggage={baggageData}
context="context"
changeBagCombination={(type, index) => {}}
passengerBaggage=
passengerCategory="adult"
prioBoardingLinkHandler={airlines => console.log("prioAirlines", airlines)}
pickerType="handBag"
shouldShowRecheckNote={false}
/>
BaggagePickerBRBRedesign
Import:
import BaggagePickerBRBRedesign from "@kiwicom/nitro/lib/components/BaggagePickerBRBRedesign";
Types:
type Props = {|
changeBagCombination: (picker: BaggageCategory, item: number) => void,
passengerCategory: PassengerGroup,
passengerBaggage: { handBag: number, holdBag: number },
baggage: BaggageType,
shouldShowRecheckNote?: boolean,
airlines: { [string]: Airline },
pickerType: BaggageCategory,
context: "booking" | "mmb",
currentCombination?: number,
prioBoardingLinkHandler?: (arg: Airline[]) => void,
description?: React.Node,
shouldShowAddBlueRibbonBag: boolean,
blueRibbonBagPrice: PriceType,
isBlueRibbonBagAdded: boolean,
addBlueRibbonBag: () => void,
removeBlueRibbonBag: () => void,
openBlueribbonBagsSmartFAQ: () => void,
|};
declare export default React.ComponentType<Props>;
See types:
Context needs:
Selectors data-test
:
"BaggagePickerBRBRedesign-AddBlueRibbonBagButton"
"BaggagePickerBRBRedesign-AddBlueRibbonBags"
"BaggagePickerBRBRedesign-EmptyLabel"
"BaggagePickerBRBRedesign-EmptyOption"
"BaggagePickerBRBRedesign-NoPersonalItemLabel"
"BaggagePickerBRBRedesign-OptionItem-Current"
"BaggagePickerBRBRedesign-OptionItem-Price"
"BaggagePickerBRBRedesign-PriorityBoardingInfo"
"BaggagePickerBRBRedesign-RecheckAlert"
"BaggagePickerBRBRedesign-RemoveBlueRibbonBagButton"
"BaggagePickerBRBRedesign-ShowButton"
{`BaggagePickerBRBRedesign-${pickerType}`}
{`BaggagePickerBRBRedesign-Option-${item.index}`}
-
{`BaggagePickerBRBRedesign-OptionItem-${category}`}
- renders baggage picker, forked from BaggagePicker to allow different offering of Blue Ribbon Bags protection.
Example:
<BaggagePickerBRBRedesign
airlines={airlines}
baggage={baggageData}
context="context"
changeBagCombination={(type, index) => {}}
passengerBaggage=
passengerCategory="adult"
prioBoardingLinkHandler={airlines => console.log("prioAirlines", airlines)}
pickerType="handBag"
shouldShowRecheckNote={false}
shouldShowAddBlueRibbonBag={true}
blueRibbonBagPrice=
isBlueRibbonBagAdded={isAdded}
addBlueRibbonBag={add}
removeBlueRibbonBag={remove}
openBlueribbonBagsSmartFAQ={() => {console.log("opening SmartFAQ article")}}
/>
BookingSavingsBanner
Import:
import BookingSavingsBanner from "@kiwicom/nitro/lib/components/BookingSavingsBanner";
Types:
type Props = {|
amount: number,
currency: string,
onLearnMoreClick: (e: SyntheticEvent<HTMLButtonElement>) => void, // Triggers redirection to learn more article
onMoreTripsClick: (e: SyntheticEvent<HTMLButtonElement>) => void, // Triggers modal with alternative trips
|};
declare export default React.ComponentType<Props>;
Context needs:
Selectors data-test
:
"BookingSavingsBanner"
"BookingSavingsBanner-LearnMore"
"BookingSavingsBanner-MoreTrips"
Throw-away ticket banner indicating savings in €.
Button
Import:
import Button from "@kiwicom/nitro/lib/components/Button";
Types:
type Props = {|
...$Diff<PropsOrbit, { children: ?React.Node }>,
t: string,
values?: { [key: string]: string | number },
html?: boolean,
transform?: (value: string) => string,
|};
declare export default React.ComponentType<Props>;
Context needs:
Our Translate
wrapped in Orbit Button
. Accepts both our and their props.
Button component shorter and nicer!
ClickOutside
Import:
import ClickOutside from "@kiwicom/nitro/lib/components/ClickOutside";
Types:
type Props = {|
className?: string,
onClickOutside: (ev: MouseEvent) => void,
children: React.Node | React.Node[],
// defaulted
active?: boolean, // true
|};
declare export default React.ComponentType<Props>;
Fires a callback whenever a user clicks outside of this component.
Example:
const MyComponent = ({ open, onCloseModal }: Props) => (
<ClickOutside active={open} onClickOutside={onCloseModal}>
<MyModal open={open} />
</ClickOutside>
);
ClientOnly
Import:
import ClientOnly from "@kiwicom/nitro/lib/components/ClientOnly";
Types:
type Props = {|
children: React.Node,
// defaulted
loader?: React.Node, // null
|};
declare export default React.ComponentType<Props>;
Renders only on the client, useful for wrapping components that break server-side rendering.
Example:
const MyComponent = () => (
<ClientOnly>
<>
<ComponentWithSideEffects />
<ComponentUsingTheWindowObject />
</>
</ClientOnly>
);
CloseByKey
Import:
import CloseByKey from "@kiwicom/nitro/lib/components/CloseByKey";
Types:
type Props = {|
onClose: (ev: KeyboardEvent) => void,
children: React.Node,
// defaulted
closeKey?: string, // Escape
|};
declare export default React.ComponentType<Props>;
Fires a callback whenever a user presses the close button (Escape by default).
CookiesPopup
Import:
import CookiesPopup from "@kiwicom/nitro/lib/components/CookiesPopup";
Types:
type Props = {|
onAccept: ({|
performance: boolean,
marketing: boolean,
advertisement: boolean,
|}) => void,
type?: "popup" | "banner",
|};
declare export default React.ComponentType<Props>;
Context needs:
Selectors data-test
:
"CookiesPopup"
Closeable cookies thingie #2.
CustomerBaggageTile
Import:
import CustomerBaggageTile from "@kiwicom/nitro/lib/components/CustomerBaggageTile";
Types:
type Props = {|
firstName: string,
middleName?: string,
lastName: string,
gender: Gender,
dayOfBirth?: string,
isProcessing: boolean,
current?: {
handBag: number,
holdBag: number,
},
selected?: {
handBag: number,
holdBag: number,
},
newDefinitions?: Definition[],
onClick?: () => void,
baggage: BaggageType,
|};
declare export default React.ComponentType<Props>;
See types:
Context needs:
Selectors data-test
:
"CustomerBaggageTile-BaggageItem"
"CustomerBaggageTile-ContactUsText"
"CustomerBaggageTile-Content"
"CustomerBaggageTile-Title"
{`CustomerBaggageTile-Badge-${status}`}
{`CustomerBaggageTile-Badge-${status}`}
-
{`CustomerBaggageTile-Badge-${status}`}
- renders baggage tile for customer
- component should be used in baggage ordering process
- component has features:
- order statuses
- differ newly selected baggages from current
Example:
<CustomerBaggageTile
firstName="Vaclav"
lastName="Havel"
gender="male"
isProcessing={false},
current=
selected=
onClick={ () => {}}
baggage={baggageData}
/>
DateInput
Import:
import DateInput from "@kiwicom/nitro/lib/components/DateInput";
Types:
type Props = {|
label: string,
value?: ?Date,
error?: string,
onChange: (?Date) => void,
|};
declare export default React.ComponentType<Props>;
Context needs:
Selectors data-test
:
"DateInput"
"DateInput-Date"
"DateInput-Month"
-
"DateInput-Year"
-
Date input field, with default date validation included
label: string
error?: string
- default date validation is done by component, but you can use this property to indicate that e.g. it’s not in your allowed rangevalue?: Date
- passDate
to set initial dateonChange: (?Date) => void
- when user filled all fields and Date is valid, you get backDate
, otherwisenull
Desktop
Import:
import Desktop from "@kiwicom/nitro/lib/components/Desktop";
Types:
type Props = {|
children: React.Node | React.Node[],
// defaulted
display?: "block" | "inline" | "inline-block" | "flex", // block
|};
declare export default React.ComponentType<Props>;
Renders only above tablet width.
Example:
const NavBar = () => (
<>
<Desktop>
<Button>A desktop-only button</Button>
</Desktop>
<Menu />
</>
);
InitAuth
Import:
import InitAuth from "@kiwicom/nitro/lib/components/InitAuth";
Types:
type MyBookingInput = {|
bid: string,
email: string,
iata: string,
departure: Date,
|};
type RegisterInput = {|
firstName: string,
lastName: string,
email: string,
password: string,
|};
type OnMyBookingArg = {|
token: string,
bid: number,
|};
type Arg = {|
auth: Auth | null,
loading: boolean,
onMyBooking: (input: MyBookingInput) => Promise<void>,
onRegister: (input: RegisterInput) => Promise<void>,
onSocialAuth: (provider: SocialProvider) => Promise<void>,
onSignIn: (email: string, password: string) => Promise<void>,
onSetAuth: (auth: Auth) => void,
onSignOut: () => void,
|};
type Props = {|
brand: Brand,
redirectURL: string,
onMyBooking: (arg: OnMyBookingArg) => void,
onRegister: () => void,
onSocialAuth: (authURL: string) => void,
onSignIn: (auth: Auth) => void,
onSignOut: () => void,
children: (arg: Arg) => React.Node,
|};
declare export default React.ComponentType<Props>;
See types:
Calls APIs for you, handles loading state and supplies context with Relay environment with the auth token. Supplied callbacks are only there for the side effects:
- saving token to cookies on login
- removing token from cookies on logout
- redirecting the user on social login
- popping a note to check email on register
- redirecting the user to MMB on my booking
It also logs the user in on mount if you supply the token
prop.
Saves or removes the AFFILIATE_ID
cookie on sign in.
InitCurrency
Import:
import InitCurrency from "@kiwicom/nitro/lib/components/InitCurrency";
Types:
type Arg = {|
currency: Currency,
available: Currencies,
recommended: Currency[],
onChange: (code: string) => void,
|};
type Props = {|
brand: Brand,
countries: Countries,
affiliate: string,
ip: string,
langCurrency: string,
children: (arg: Arg) => React.Node,
onChange: (currency: string) => void,
// defaulted
mostUsed?: string[],
// DI
getCurrencies?: () => Promise<FetchedCurrencies>,
getGeoCountry?: (ip: string) => Promise<string>,
url?: string,
|};
declare export default React.ComponentType<Props>;
See types:
TODO
InitIntl
Import:
import InitIntl from "@kiwicom/nitro/lib/components/InitIntl";
Types:
type Props = {|
raw: IntlRaw,
children: (arg: Context) => React.Node,
// defaulted
getLocale?: Promise<$FlowFixMe>, // resolves en-US by default
|};
declare export default React.ComponentType<Props>;
See types:
Context needs:
Useful for initiating the intl context from raw intl data.
import type { IntlRaw } from "@kiwicom/nitro/lib/records/Intl";
const raw: IntlRaw = window.__INTL__; // intl data from the server
const App = () => (
<InitIntl raw={raw}>
{intl => (
<IntlProvider value={intl}>
<Root />
</IntlProvider>
)}
</InitIntl>
)
const node = document.getElementById("root");
if (node) {
ReactDOM.hydrate(<App />, node);
}
On the server:
import type { IntlRaw } from "@kiwicom/nitro/lib/records/Intl";
import { locales } from "./data";
export default function render(locale: string) {
const raw: IntlRaw = locales[locale];
const markup = ReactDOM.renderToString(
<InitIntl raw={raw}>
{intl => (
<IntlProvider value={intl}>
<Root />
</IntlProvider>
)}
</InitIntl>
);
// <Html /> puts the raw intl data into window.__INTL__
return ReactDOM.renderToStaticNodeStream(<Html intl={raw} />);
}
InitLog
Import:
import InitLog from "@kiwicom/nitro/lib/components/InitLog";
Types:
type Props = {|
children: (ctx: Context) => React.Node,
|};
declare export default React.ComponentType<Props>;
Context needs:
Initializes the log context.
Logs are logged using the log/logger service.
Example:
import { Provider as LogProvider } from "@kiwicom/nitro/lib/services/log/context";
import InitLog from "@kiwicom/nitro/lib/components/InitLog";
import * as logger from "@kiwicom/nitro/lib/services/log/logger";
logger.globals.userId = window.__SESSION__.userId;
logger.globals.langId = window.__INTL__.id;
// ...
ReactDOM.render(
<InitLog>
{ctx => (
<LogProvider value={ctx}>
<App />
</LogProvider>
)}
</InitLog>,
node,
);
InitRelayEnvironment
Import:
import InitRelayEnvironment from "@kiwicom/nitro/lib/components/InitRelayEnvironment";
Types:
type Props = {|
clientID: string,
uri?: string,
children: React.Node,
|};
declare export default React.ComponentType<Props>;
Context needs:
Initializes RelayEnvironmentProvider
from @kiwicom/relay with environment containing correct HTTP headers.
Note you must always specify clientID
which should identify your application to helps us know who is sending the request.
InitStarred
Import:
import InitStarred from "@kiwicom/nitro/lib/components/InitStarred";
Types:
type Args = {|
list: StarredItem[],
onRemove: (arg: string, e: SyntheticEvent<HTMLDivElement>) => void,
onAdd: (arg: StarredItem) => void,
onClear: (e: SyntheticEvent<HTMLDivElement>) => void,
|};
type Props = {|
children: (args: Args) => React.Node,
|};
declare export default React.ComponentType<Props>;
See types:
Just mount it and it works!
InputEmail
Import:
import InputEmail from "@kiwicom/nitro/lib/components/InputEmail";
Types:
type Props = {|
...SpaceAfter,
size?: "small" | "normal",
name?: string,
label?: Translation,
inlineLabel?: boolean,
value?: (() => string | number) | string | number,
placeholder?: Translation,
help?: React.Node,
prefix?: React$Node,
suffix?: React$Node,
tabIndex?: string,
autoComplete?: string,
id?: string,
error: string,
onChange: ({ value: string, error: string }) => void,
onFocus?: (ev: SyntheticInputEvent<HTMLInputElement>) => void | Promise<any>,
onBlur?: (ev: SyntheticInputEvent<HTMLInputElement>) => void | Promise<any>,
onKeyDown?: (ev: SyntheticKeyboardEvent<HTMLInputElement>) => void | Promise<any>,
onKeyUp?: (ev: SyntheticKeyboardEvent<HTMLInputElement>) => void | Promise<any>,
|};
declare export default React.ComponentType<Props>;
Context needs:
Nitro Email
Wrapper for InputField
from Orbit-components
- Email validation by
validator.js
- Translation for required:
forms.this_field_must_be_filled
- Translation for validation:
forms.wrong_format_email
- Has
emailCorrector
function which suggests correct email spelling address, viahelp
prop fromInputField
InputPhone
Import:
import InputPhone from "@kiwicom/nitro/lib/components/InputPhone";
Types:
type Props = {|
...SpaceAfter,
size?: "small" | "normal",
name?: string,
label?: Translation,
inlineLabel?: boolean,
value?: (() => string | number) | string | number,
placeholder?: Translation,
help?: React.Node,
prefix?: React$Node,
suffix?: React$Node,
tabIndex?: string,
autoComplete?: string,
maxLength?: number,
minLength?: number,
id?: string,
error: string,
onChange: ({ error: string, value: string, code?: string }) => void,
onFocus?: (ev: SyntheticInputEvent<HTMLInputElement>) => void | Promise<any>,
onBlur?: (ev: SyntheticInputEvent<HTMLInputElement>) => void | Promise<any>,
onKeyDown?: (ev: SyntheticKeyboardEvent<HTMLInputElement>) => void | Promise<any>,
onKeyUp?: (ev: SyntheticKeyboardEvent<HTMLInputElement>) => void | Promise<any>,
|};
declare export default React.ComponentType<Props>;
Context needs:
Nitro Phone
Wrapper for InputField
from Orbit-components
- Phone validation by call to
https://check-phone.kiwi.com/
- Translation for required:
forms.this_field_must_be_filled
- Translation for validation:
forms.errors.invalid_phone
andforms.errors.not_supported
Itinerary
Import:
import Itinerary from "@kiwicom/nitro/lib/components/Itinerary";
Types:
type Props = {|
itinerary: ItineraryNormalized,
|};
declare export default React.ComponentType<Props>;
See types:
Context needs:
- Renders all trip types aka Itineraries (oneWay, return, multicity and nomad)
- It was made similiar to search graphql date structure
- Uses flat date structure
- You can check new structure in these records:
To implement Itinerary
you have to import flatten function.
Example:
import { flatten } from "@kiwicom/nitro/lib/records/Itinerary";
<Itinerary itinerary={flatten(ItineraryOneWay)} />;
LogMount
Import:
import LogMount from "@kiwicom/nitro/lib/components/LogMount";
Types:
type Props = {|
event: Event,
// defaulted
props?: EventProps,
|};
declare export default React.ComponentType<Props>;
See types:
Context needs:
Logs the given event and props on mount.
Useful for declarative tracking of opening modals or page sections.
Mobile
Import:
import Mobile from "@kiwicom/nitro/lib/components/Mobile";
Types:
type Props = {|
children: React.Node | React.Node[],
// defaulted
display?: "block" | "inline" | "inline-block" | "flex", // block
|};
declare export default React.ComponentType<Props>;
Renders only below tablet width.
Example:
const NavBar = () => (
<>
<Mobile>
<Button>A mobile-only button</Button>
</Mobile>
<Menu />
</>
);
Price
Import:
import Price from "@kiwicom/nitro/lib/components/Price";
Types:
type Props = {|
value: number,
|};
declare export default React.ComponentType<Props>;
Context needs:
Renders a formatted price.
Example:
const Pay = ({ value }: Props) => (
<Button>
<TextNode
t="Pay __x__"
values={
{ x: <Price value={value} /> }
}
/>
</Button>
);
Starred
Import:
import Starred from "@kiwicom/nitro/lib/components/Starred";
Types:
type Props = {|
positionMenuDesktop?: number,
positionMenuTablet?: number,
inverted?: boolean,
|};
declare export default React.ComponentType<Props>;
Context needs:
Text
Import:
import Text from "@kiwicom/nitro/lib/components/Text";
Types:
type Props = {|
...$Diff<PropsOrbit, { children: React.Node }>,
t: string,
values?: { [key: string]: string | number },
html?: boolean,
transform?: (value: string) => string,
|};
declare export default React.ComponentType<Props>;
Context needs:
Our Translate
wrapped in Orbit’s Text
. Accepts both our and their props.
Useful for both translating and making text nicer!
TextNode
Import:
import TextNode from "@kiwicom/nitro/lib/components/TextNode";
Types:
type Props = {|
...$Diff<PropsOrbit, { children: React.Node }>,
t: string,
values: { [key: string]: React.Node },
transform?: (value: string) => string,
|};
declare export default React.ComponentType<Props>;
Context needs:
Our TranslateNode
wrapped in Orbit’s Text
. Accepts both our and their props.
Useful for both translating and making text nicer!
Toggle
Import:
import Toggle from "@kiwicom/nitro/lib/components/Toggle";
Types:
type Data = {|
open: boolean,
onToggle: () => void,
|};
type Props = {|
children: (data: Data) => React.Node,
// defaulted
initial?: boolean, // false
|};
declare export default React.ComponentType<Props>;
A container that holds state of something being open.
Example:
const MyComponent = () => (
<Toggle>
{({ open, onToggle }) => (
<>
<h3>{open ? "Open" : "Closed"}</h3>
<Button onClick={onToggle}>Toggle</Button>
</>
)}
</Toggle>
);
Translate
Import:
import Translate from "@kiwicom/nitro/lib/components/Translate";
Types:
type Props = {|
t: string,
// defaulted
values?: { [key: string]: string | number }, // {}
html?: boolean, // false
transform?: (value: string) => string, // identity
|};
declare export default React.ComponentType<Props>;
Context needs:
Translates the supplied key.
The text output can be transformed using the
transform
function. You can use arrow functions - the component does not implement pure render.
Example:
const Submit = () => (
<Button>
<Translate t="Submit" />
</Button>
);
TranslateNode
Import:
import TranslateNode from "@kiwicom/nitro/lib/components/TranslateNode";
Types:
type Props = {|
t: string,
values: { [key: string]: React.Node },
// defaulted
transform?: (value: string) => string, // identity
|};
declare export default React.ComponentType<Props>;
Context needs:
The same as Translate
, except values are React.Node
. Useful when you need to inject elements with event handlers!
The text output can be transformed using the
transform
function. You can use arrow functions - the component does not implement pure render.
Example:
const MyComponent = () => (
<TranslateNode
t="Click this: __x__"
values={
{ x: <button onClick={() => alert("Clicked")}>Yo</button> }
}
/>
);
TranslateRef
Import:
import TranslateRef from "@kiwicom/nitro/lib/components/TranslateRef";
Types:
type Props = {|
t: string,
values?: Values,
render: (ref: string, index: number) => React.Node,
transform?: (value: string) => string,
|};
declare export default React.ComponentType<Props>;
Context needs:
The same as Translate
, except it expects the translation to contain a <ref></ref>
tag to be replaced with the result of the render
function call. Useful for injecting event handlers!
The text output can be transformed using the
transform
function. You can use arrow functions - the component does not implement pure render.
Example:
const MyComponent = () => (
<TranslateRef
t="Some stuff, <ref>read more</ref>."
render={text => <Link to="/about">{text}</Link>}
/>
);
Value
Import:
import Value from "@kiwicom/nitro/lib/components/Value";
Types:
type Data = {|
value: string,
onChange: (value?: string) => void, // 'value' defaults to ""
|};
type Props = {|
children: (data: Data) => React.Node,
// defaulted
initial?: string, // ""
|};
declare export default React.ComponentType<Props>;
A render props container component that holds a string value. Useful for modals, for example.
Super useful when combined with the ValueBind component!
Example:
const AuthModals = ({ query }: Props) => (
<Value initial={query.modal || ""}>
{({ value, onChange }) => (
<>
<ModalLogin open={value === "login"} onClose={onChange} />
<ModalRegister open={value === "register"} onClose={onChange} />
<ValueBind value="login" onChange={onChange}>
{({ onClick }) => <Button onClick={onClick}>Login</Button>}
</ValueBind>
<ValueBind value="register" onChange={onChange}>
{({ onClick }) => <Button onClick={onClick}>Register</Button>}
</ValueBind>
</>
)}
</Value>
)
ValueBind
Import:
import ValueBind from "@kiwicom/nitro/lib/components/ValueBind";
Types:
type Data = {|
onClick: () => void,
|};
type Props = {|
value: string,
onChange: (value: string) => void,
children: (data: Data) => React.Node,
|};
declare export default React.ComponentType<Props>;
Binds a value to a callback, that’s it. Useful for changing onChange
callbacks to onClick
ones.
const OpenLogin = ({ onChange }: Props) => (
<ValueBind value="login" onChange={onChange}>
{({ onClick }) => (
<Button onClick={onClick} />
)}
</ValueBind>
)