From 433e65983f9d93496c05144ff78b514ea8513613 Mon Sep 17 00:00:00 2001 From: sachaMemmir5 <93584845+sachaMemmir5@users.noreply.github.com> Date: Tue, 28 Jan 2025 14:41:35 +0100 Subject: [PATCH] v1.31.3 (#258) --- CHANGELOG.md | 9 +- package-lock.json | 4 +- package.json | 2 +- types/identity-ui.d.ts | 361 ++++++++++++++++++++++++++++++++++++----- 4 files changed, 328 insertions(+), 48 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ca02543..bc942c6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,11 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +## [1.31.3] - 2025-01-28 + +### Fixed +- Fix form phone number field when optional and not valued + ## [1.31.2] - 2025-01-14 ### Fixed @@ -536,7 +541,9 @@ The eye icon is now correctly displayed in the Auth widget. First version of the SDK Web UI. -[Unreleased]: https://github.com/ReachFive/identity-web-ui-sdk/compare/v1.31.2...HEAD +[Unreleased]: https://github.com/ReachFive/identity-web-ui-sdk/compare/v1.31.3...HEAD + +[1.31.3]: https://github.com/ReachFive/identity-web-ui-sdk/compare/v1.31.2...v1.31.3 [1.31.2]: https://github.com/ReachFive/identity-web-ui-sdk/compare/v1.31.1...v1.31.2 diff --git a/package-lock.json b/package-lock.json index 5e6f696..bc4bec2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@reachfive/identity-ui", - "version": "1.31.2", + "version": "1.31.3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@reachfive/identity-ui", - "version": "1.31.2", + "version": "1.31.3", "license": "MIT", "dependencies": { "@reachfive/identity-core": "^1.34.0", diff --git a/package.json b/package.json index 2799bee..089dfbb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@reachfive/identity-ui", - "version": "1.31.2", + "version": "1.31.3", "description": "ReachFive Identity Web UI SDK", "author": "ReachFive", "repository": { diff --git a/types/identity-ui.d.ts b/types/identity-ui.d.ts index a97f356..1030995 100644 --- a/types/identity-ui.d.ts +++ b/types/identity-ui.d.ts @@ -1,15 +1,19 @@ /** - * @reachfive/identity-ui - v1.31.2 - * Compiled Tue, 14 Jan 2025 13:12:56 UTC + * @reachfive/identity-ui - v1.31.222 + * Compiled Tue, 28 Jan 2025 13:28:17 UTC * * Copyright (c) ReachFive. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. **/ -import React$1, { CSSProperties } from 'react'; -import { Config as Config$1, RemoteSettings, ConsentVersions, CustomField, Client as Client$1, SessionInfo, AuthOptions, MFA, PasswordlessResponse, SingleFactorPasswordlessParams, Profile, UserConsent, DeviceCredential } from '@reachfive/identity-core'; +import * as React from 'react'; +import React__default, { CSSProperties, ComponentType } from 'react'; +import { Config as Config$1, RemoteSettings, ConsentVersions, CustomField, Client as Client$1, SessionInfo, ConsentType, PasswordPolicy, CustomFieldType, AuthOptions, MFA, PasswordlessResponse, SingleFactorPasswordlessParams, Profile, UserConsent, DeviceCredential } from '@reachfive/identity-core'; export { Config } from '@reachfive/identity-core'; +import { Country, Value as Value$2 } from 'react-phone-number-input'; +import { DateTime } from 'luxon'; +import * as libphonenumber_js from 'libphonenumber-js'; import { PasswordlessParams } from '@reachfive/identity-core/es/main/oAuthClient'; type Prettify = { @@ -20,6 +24,12 @@ type RecursivePartial = { [P in keyof T]?: RecursivePartial } & {} +/** + * From T, make optional a set of properties whose keys are in the union K + * @example Optional<{ firstname: string, lastname: string }, 'lastname'> // => { firstname: string, lastname?: string } + */ +type Optional = Pick, K> & Omit; + type RequiredProperty = T & { [P in K]-?: T[P]; } @@ -233,65 +243,217 @@ interface I18nProps { } type WithI18n

= P & I18nProps; +declare class PathMapping { + protected readonly modelPath: string; + constructor(modelPath: string); + bind>(model: T): unknown; + unbind, V>(model: T, value: V): T | V; +} + +declare class CompoundValidator { + current: Validator | CompoundValidator; + next: Validator | CompoundValidator; + constructor(current: Validator | CompoundValidator, next: Validator | CompoundValidator); + create(i18n: I18nResolver): ValidatorInstance; + and(validator: Validator | CompoundValidator): CompoundValidator; +} type VaildatorError = { error: string; }; type ValidatorSuccess = { success?: true; }; -type VaildatorResult = boolean | VaildatorError | ValidatorSuccess; +type ValidatorResult = boolean | VaildatorError | ValidatorSuccess; +type ValidatorInstance = (value: T, ctx: C) => ValidatorResult; +type Rule = (value: T, ctx: C) => boolean; +type Hint = (value: T) => (string | undefined); +interface ValidatorOptions { + rule: Rule; + hint?: Hint | string; + parameters?: Record; +} +declare class Validator { + rule: Rule; + hint: Hint; + parameters: Record; + constructor({ rule, hint, parameters }: ValidatorOptions); + create(i18n: I18nResolver): ValidatorInstance; + and(validator: Validator | CompoundValidator): CompoundValidator; +} -type FormValue = T | RichFormValue; +type FormValue = T | RichFormValue; type RichFormValue = Record; +/** @todo to refine */ +type FormContext = { + errorMessage?: string; + fields: FieldValues; + hasErrors?: boolean; + isLoading?: boolean; + isSubmitted: boolean; +}; +type FieldValues = { + [K in keyof T]: FieldValue; +}; + interface FieldCreateProps { - showLabel: boolean + showLabel: boolean; +} +interface FieldCreator = {}, K extends string = 'raw'> { + path: string; + create: (options: WithI18n) => Field$1; +} +interface Field$1 = {}, K extends string = 'raw'> { + key: string; + render: (props: Partial

& Partial> & { + state: FieldValue; + }) => React__default.ReactNode; + initialize: >(model: M) => FieldValue; + unbind: >(model: M, state: FieldValue) => M; + validate: (data: FieldValue, ctx: FormContext) => ValidatorResult; +} +type FieldValue = {}> = E & { + value?: FormValue; + isDirty?: boolean; + validation?: ValidatorResult; +}; +type FieldComponentProps = {}, K extends string = 'raw'> = P & { + inputId: string; + key: string; + path: string; + label: string; + onChange: (value: FieldValue) => void; + placeholder?: string; + autoComplete?: AutoFill; + rawProperty?: K; + required?: boolean; + readOnly?: boolean; + i18n: I18nResolver; + showLabel?: boolean; + value?: FormValue; + validation?: ValidatorResult; +}; +interface Formatter { + bind: (value?: T) => FormValue | undefined; + unbind: (value?: FormValue) => T | null; +} +type FieldDefinition = { + key: string; + path?: string; + label: string; + required?: boolean; + readOnly?: boolean; + autoComplete?: AutoFill; + defaultValue?: T; + format?: Formatter; + validator?: Validator | CompoundValidator; +}; +interface FieldProps, ExtraParams extends Record = {}, K extends string = 'raw', E extends Record = {}> extends FieldDefinition { + label: string; + mapping?: PathMapping; + format?: Formatter; + rawProperty?: K; + component: ComponentType

; + extendedParams?: ExtraParams | ((i18n: I18nResolver) => ExtraParams); +} + +type ConsentFieldOptions$1 = { + type: ConsentType; + consentCannotBeGranted?: boolean; + description: string; + version: { + language: string; + versionId: number; + }; +}; +interface ConsentFieldProps extends FieldComponentProps { +} +type Value$1 = { + consentType?: ConsentType; + consentVersion?: { + language: string; + versionId: number; + }; + granted: boolean; +}; +declare function consentField({ type, required, consentCannotBeGranted, description, version, ...props }: Omit, 'defaultValue'> & { + defaultValue?: boolean; +} & ConsentFieldOptions$1): FieldCreator; + +type ExtraParams$2 = { + locale: string; + yearDebounce?: number; +}; +interface DateFieldProps extends FieldComponentProps { +} +declare function dateField({ key, label, yearDebounce, locale, ...props }: Optional, 'key' | 'label'> & Optional, config: Config): FieldCreator; + +interface Option { + label: string; + value: string; +} +interface SelectProps extends React__default.SelectHTMLAttributes { + hasError?: boolean; + options: Option[]; + placeholder?: string; } -interface FieldCreator { - path: string, - create: (options: WithI18n) => Field$1 +type Value = SelectProps['value']; +type SelectOptions = { + values: SelectProps['options']; +}; +interface SelectFieldProps extends FieldComponentProps { } +declare function selectField({ values, ...config }: FieldDefinition & SelectOptions): FieldCreator; -interface Field$1 { - key: string - render: (props: P & Partial> & { state: FieldValue }) => React.ReactNode - initialize: (model: M) => FieldValue - unbind: (model: M, state: FieldValue) => M - validate: (data: FieldValue, ctx: S) => VaildatorResult +interface CheckboxFieldProps extends FieldComponentProps { } +declare function checkboxField(props: Omit, 'format' | 'component'>): FieldCreator; -type FieldValue = E & { - value?: T - isDirty?: boolean - validation?: VaildatorResult +type SimplePasswordFieldOptions = { + canShowPassword?: boolean; + placeholder?: React__default.InputHTMLAttributes['placeholder']; +}; +interface SimplePasswordFieldProps extends FieldComponentProps { } +declare const simplePasswordField: ({ canShowPassword, placeholder, ...props }: FieldDefinition & SimplePasswordFieldOptions) => FieldCreator; -type FieldComponentProps = P & { - inputId: string - key: string - path: string - label: string - onChange: (value: FieldValue) => void - placeholder?: string - autoComplete?: AutoFill - required?: boolean - readOnly?: boolean - i18n: I18nResolver - showLabel?: boolean - value?: FormValue - validation?: VaildatorResult +type PasswordStrengthScore = 0 | 1 | 2 | 3 | 4; +interface PasswordRule { + label: string; + verify: (value: string) => boolean; } -/** The field's representation. */ -type Field = { - key: string - label?: string - required?: boolean - type?: 'hidden' | 'text' | 'number' | 'email' | 'tel' +type ExtraValues = { + strength?: PasswordStrengthScore; +}; +type ExtraParams$1 = { + blacklist?: string[]; + canShowPassword?: boolean; + enabledRules: Record; + minStrength: PasswordStrengthScore; +}; +interface PasswordFieldProps extends FieldComponentProps { } +type RuleKeys = Exclude; +declare const passwordField: ({ key, label, blacklist, canShowPassword, enabledRules, minStrength, required, validator, ...props }: Optional, 'key' | 'label'> & Partial, { passwordPolicy }: Config) => FieldCreator; type PhoneNumberOptions = { + /** + * If defaultCountry is specified then the phone number can be input both in "international" format and "national" format. + * A phone number that's being input in "national" format will be parsed as a phone number belonging to the defaultCountry. + */ + defaultCountry?: Country; + /** + * If country is specified then the phone number can only be input in "national" (not "international") format, + * and will be parsed as a phonenumber belonging to the country. + */ + country?: Country; + /** + * If locale is specified then translate component using the given language. + * @see https://gitlab.com/catamphetamine/react-phone-number-input/tree/master/locale + */ + locale?: string; /** * If `withCountryCallingCode` property is explicitly set to true then the "country calling code" part (e.g. "+1" when country is "US") is included in the input field (but still isn't editable). * @default true @@ -303,6 +465,117 @@ type PhoneNumberOptions = { */ withCountrySelect?: boolean; }; +/** + * If neither country nor defaultCountry are specified then the phone number can only be input in "international" format. + */ +interface PhoneNumberFieldProps extends FieldComponentProps, PhoneNumberOptions { +} +declare const phoneNumberField: ({ key, label, defaultCountry, country, locale, withCountryCallingCode, withCountrySelect, ...props }: Optional, 'key' | 'label'> & PhoneNumberOptions, config: Config) => FieldCreator; + +type SimpleFieldOptions = { + placeholder?: React__default.InputHTMLAttributes['placeholder']; + type?: React__default.HTMLInputTypeAttribute; +}; +interface SimpleFieldProps extends FieldComponentProps { +} +declare const simpleField: ({ placeholder, type, ...props }: FieldDefinition & SimpleFieldOptions) => FieldCreator; + +declare function birthdateField({ min, max, label, ...props }: Parameters[0] & { + min?: number; + max?: number; +}, config: Config): FieldCreator, DateFieldProps, { + locale: string; + yearDebounce?: number | undefined; +}, "raw">; + +type FieldBuilder = typeof simpleField | typeof checkboxField | typeof selectField | typeof dateField | typeof birthdateField | typeof phoneNumberField | typeof passwordField | typeof simplePasswordField | typeof consentField; +type FieldConfig = Parameters[0]; +type PredefinedFieldConfig = Prettify, 'label'>>; +type PredefinedFieldOptions = { + [K in keyof typeof predefinedFields]: Prettify<{ + key: K; + } & Parameters<(typeof predefinedFields)[K]>[0]>; +}[keyof typeof predefinedFields]; +type CustomFieldOptions = Prettify<{ + key: string; +} & FieldOptions>; +type ConsentFieldOptions = { + key: string; + errorArchivedConsents?: boolean; +}; +type DataType = { + dataType: T; +}; +type FieldOptions = Prettify & FieldConfig> | Prettify & FieldConfig> | Prettify & FieldConfig> | Prettify & FieldConfig> | Prettify & FieldConfig> | Prettify & FieldConfig> | Prettify & FieldConfig> | Prettify & FieldConfig> | Prettify & FieldConfig>; +type PredefinedFieldBuilder = (props: PredefinedFieldConfig, config: Config) => ReturnType; +declare const predefinedFields: { + customIdentifier: PredefinedFieldBuilder<({ placeholder, type, ...props }: FieldDefinition & { + placeholder?: string | undefined; + type?: React.HTMLInputTypeAttribute | undefined; + }) => FieldCreator>; + givenName: PredefinedFieldBuilder<({ placeholder, type, ...props }: FieldDefinition & { + placeholder?: string | undefined; + type?: React.HTMLInputTypeAttribute | undefined; + }) => FieldCreator>; + familyName: PredefinedFieldBuilder<({ placeholder, type, ...props }: FieldDefinition & { + placeholder?: string | undefined; + type?: React.HTMLInputTypeAttribute | undefined; + }) => FieldCreator>; + email: PredefinedFieldBuilder<({ placeholder, type, ...props }: FieldDefinition & { + placeholder?: string | undefined; + type?: React.HTMLInputTypeAttribute | undefined; + }) => FieldCreator>; + phoneNumber: PredefinedFieldBuilder<({ key, label, defaultCountry, country, locale, withCountryCallingCode, withCountrySelect, ...props }: Pick>, "label" | "key"> & Omit, "label" | "key"> & PhoneNumberOptions, config: Config) => FieldCreator>; + password: PredefinedFieldBuilder<({ key, label, blacklist, canShowPassword, enabledRules, minStrength, required, validator, ...props }: Pick>, "label" | "key"> & Omit, "label" | "key"> & Partial<{ + blacklist?: string[] | undefined; + canShowPassword?: boolean | undefined; + enabledRules: Record<"minLength" | "uppercaseCharacters" | "specialCharacters" | "lowercaseCharacters" | "digitCharacters", PasswordRule>; + minStrength: PasswordStrengthScore; + }>, { passwordPolicy }: Config) => FieldCreator; + minStrength: PasswordStrengthScore; + }, "raw">>; + passwordConfirmation: PredefinedFieldBuilder<({ canShowPassword, placeholder, ...props }: FieldDefinition & { + canShowPassword?: boolean | undefined; + placeholder?: string | undefined; + }) => FieldCreator>; + gender: PredefinedFieldBuilder; + birthdate: PredefinedFieldBuilder; + 'address.streetAddress': PredefinedFieldBuilder<({ placeholder, type, ...props }: FieldDefinition & { + placeholder?: string | undefined; + type?: React.HTMLInputTypeAttribute | undefined; + }) => FieldCreator>; + 'address.locality': PredefinedFieldBuilder<({ placeholder, type, ...props }: FieldDefinition & { + placeholder?: string | undefined; + type?: React.HTMLInputTypeAttribute | undefined; + }) => FieldCreator>; + 'address.region': PredefinedFieldBuilder<({ placeholder, type, ...props }: FieldDefinition & { + placeholder?: string | undefined; + type?: React.HTMLInputTypeAttribute | undefined; + }) => FieldCreator>; + 'address.postalCode': PredefinedFieldBuilder<({ placeholder, type, ...props }: FieldDefinition & { + placeholder?: string | undefined; + type?: React.HTMLInputTypeAttribute | undefined; + }) => FieldCreator>; + 'address.country': PredefinedFieldBuilder<({ placeholder, type, ...props }: FieldDefinition & { + placeholder?: string | undefined; + type?: React.HTMLInputTypeAttribute | undefined; + }) => FieldCreator>; + friendlyName: PredefinedFieldBuilder<({ placeholder, type, ...props }: FieldDefinition & { + placeholder?: string | undefined; + type?: React.HTMLInputTypeAttribute | undefined; + }) => FieldCreator>; +}; +/** + * @example { key: "email" } + * @example { key: "family_name", defaultValue: "Moreau", required": true } + * @example { key: "given_name", defaultValue: "Kylian", type: "hidden" } + * @example { key: "customFields.date", path: "date", dataType: "date" } + * @example { key: "consents.foo" } + */ +type Field = PredefinedFieldOptions | CustomFieldOptions | ConsentFieldOptions; type LoginViewProps = { /** @@ -630,9 +903,9 @@ interface ReauthViewProps { socialProviders?: string[]; } -interface StartPasswordlessFormData { +type StartPasswordlessFormData = { authType: PasswordlessParams['authType']; -} +}; interface MainViewProps$6 { /** * **Not recommended** @@ -921,7 +1194,7 @@ interface ProfileEditorProps { /** * */ - resolvedFields: FieldCreator[]; + resolvedFields: FieldCreator[]; /** * Whether the form fields' labels are displayed on the form view. * @default false @@ -1095,7 +1368,7 @@ interface WidgetProps { onReady?: (instance: WidgetInstance) => void; } type WidgetOptions

= Prettify

; -type Widget

= (props: P, ctx: Context) => Promise; +type Widget

= (props: P, ctx: Context) => Promise; declare class UiClient { config: Config; core: Client$1;