@dynamic-framework/ui-react 2.7.0 → 2.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/css/dynamic-ui.css +272 -1
- package/dist/css/dynamic-ui.min.css +2 -2
- package/dist/index.esm.js +503 -267
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +507 -266
- package/dist/index.js.map +1 -1
- package/dist/types/components/DDropdown/DDropdown.d.ts +10 -2
- package/dist/types/components/DOtp/DOtp.d.ts +1 -0
- package/dist/types/components/DOtp/components/OtpCountdown.d.ts +3 -2
- package/dist/types/components/DVoucher/DVoucher.d.ts +3 -1
- package/dist/types/components/DVoucher/hooks/useScreenshotDownload.d.ts +1 -1
- package/dist/types/components/DVoucher/hooks/useScreenshotDownload.spec.d.ts +1 -0
- package/dist/types/components/DVoucher/hooks/useScreenshotWebShare.d.ts +1 -1
- package/dist/types/components/DVoucher/hooks/useScreenshotWebShare.spec.d.ts +1 -0
- package/dist/types/components/DVoucher/index.d.ts +3 -0
- package/dist/types/components/index.d.ts +1 -1
- package/dist/types/hooks/index.d.ts +3 -0
- package/dist/types/hooks/tests/useCountdown.spec.d.ts +1 -0
- package/dist/types/hooks/useCountdown.d.ts +14 -0
- package/dist/types/hooks/useInputCurrency.d.ts +1 -6
- package/dist/types/hooks/useOtp.d.ts +98 -0
- package/package.json +1 -1
- package/src/style/abstracts/variables/_+import.scss +1 -0
- package/src/style/abstracts/variables/_input-currency.scss +1 -0
- package/src/style/components/_+import.scss +7 -0
- package/src/style/components/_d-box-file.scss +5 -0
- package/src/style/components/_d-close.scss +1 -0
- package/src/style/components/_d-confirm-modal.scss +17 -0
- package/src/style/components/_d-data-state-wrapper.scss +47 -0
- package/src/style/components/_d-datepicker.scss +11 -0
- package/src/style/components/_d-error-boundary.scss +7 -0
- package/src/style/components/_d-input-currency.scss +5 -0
- package/src/style/components/_d-otp.scss +54 -0
- package/src/style/components/_d-password-strength-meter.scss +76 -0
- package/src/style/components/_d-popover.scss +4 -0
- package/src/style/components/_d-stepper.scss +8 -0
- package/src/style/components/_d-tabs.scss +18 -0
- package/src/style/components/_d-voucher.scss +30 -0
- package/dist/types/components/DOtp/DOtpspec.d.ts +0 -0
- package/dist/types/components/DOtp/hooks/useCountdown.d.ts +0 -4
|
@@ -8,7 +8,14 @@ export type DropdownAction = {
|
|
|
8
8
|
isDivider?: boolean;
|
|
9
9
|
label: string;
|
|
10
10
|
};
|
|
11
|
-
type
|
|
11
|
+
type ResolvedSide = 'down' | 'up' | 'start' | 'end';
|
|
12
|
+
type DropdownPlacement = 'auto' | ResolvedSide;
|
|
13
|
+
/**
|
|
14
|
+
* Horizontal alignment of the menu relative to the toggle, applied only when
|
|
15
|
+
* the resolved placement is vertical (`down`/`up`) — mirrors Bootstrap's
|
|
16
|
+
* `dropdown-menu-end`/`dropdown-center` menu alignment options.
|
|
17
|
+
*/
|
|
18
|
+
export type DropdownAlignment = 'start' | 'end' | 'center';
|
|
12
19
|
type Props = {
|
|
13
20
|
actions: DropdownAction[];
|
|
14
21
|
dropdownToggle?: ((props: {
|
|
@@ -19,6 +26,7 @@ type Props = {
|
|
|
19
26
|
classNameMenu?: string;
|
|
20
27
|
asPortal?: boolean;
|
|
21
28
|
placement?: DropdownPlacement;
|
|
29
|
+
alignment?: DropdownAlignment;
|
|
22
30
|
};
|
|
23
|
-
export default function DDropdown({ actions, dropdownToggle, className, classNameMenu, asPortal, placement, }: Props): import("react").JSX.Element;
|
|
31
|
+
export default function DDropdown({ actions, dropdownToggle, className, classNameMenu, asPortal, placement, alignment, }: Props): import("react").JSX.Element;
|
|
24
32
|
export {};
|
|
@@ -11,6 +11,7 @@ export type PropsOtp = PropsWithChildren<{
|
|
|
11
11
|
title?: string;
|
|
12
12
|
contact?: string | React.ReactNode;
|
|
13
13
|
resendText?: string;
|
|
14
|
+
invalidCode?: string;
|
|
14
15
|
};
|
|
15
16
|
}>;
|
|
16
17
|
export default function DOtp({ className, action, isLoading, otpSize, texts, seconds, }: PropsOtp): import("react").JSX.Element;
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
2
|
type Props = {
|
|
3
|
-
|
|
3
|
+
secondsLeft: number;
|
|
4
|
+
restartCountdown: () => void;
|
|
4
5
|
resendText?: string;
|
|
5
6
|
message?: (secondsLeft: number) => string;
|
|
6
7
|
};
|
|
7
|
-
export default function OtpCountdown({
|
|
8
|
+
export default function OtpCountdown({ secondsLeft, restartCountdown, resendText, message, }: Props): import("react").JSX.Element;
|
|
8
9
|
export {};
|
|
@@ -9,7 +9,9 @@ type Props = PropsWithChildren<{
|
|
|
9
9
|
title: string;
|
|
10
10
|
downloadText?: string;
|
|
11
11
|
shareText?: string;
|
|
12
|
+
fileName?: string;
|
|
13
|
+
hideActions?: boolean;
|
|
12
14
|
onError?: (err: Error) => Promise<void> | void;
|
|
13
15
|
}>;
|
|
14
|
-
export default function DVoucher({ amount, amountDetails, icon, title, onError, message, downloadText, shareText, className, children, }: Props): import("react").JSX.Element;
|
|
16
|
+
export default function DVoucher({ amount, amountDetails, icon, title, onError, message, downloadText, shareText, fileName, hideActions, className, children, }: Props): import("react").JSX.Element;
|
|
15
17
|
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,2 +1,5 @@
|
|
|
1
1
|
import DVoucher from './DVoucher';
|
|
2
|
+
export { default as useScreenshot } from './hooks/useScreenshot';
|
|
3
|
+
export { default as useScreenshotDownload } from './hooks/useScreenshotDownload';
|
|
4
|
+
export { default as useScreenshotWebShare } from './hooks/useScreenshotWebShare';
|
|
2
5
|
export default DVoucher;
|
|
@@ -50,7 +50,7 @@ export type { DToastContainerProps, DToastOptions, ToastData } from './DToastCon
|
|
|
50
50
|
export { default as DInputPhone } from './DInputPhone';
|
|
51
51
|
export { default as DCreditCard } from './DCreditCard';
|
|
52
52
|
export { default as DDropdown } from './DDropdown';
|
|
53
|
-
export { default as DVoucher } from './DVoucher';
|
|
53
|
+
export { default as DVoucher, useScreenshot, useScreenshotDownload, useScreenshotWebShare, } from './DVoucher';
|
|
54
54
|
export { default as DOtp } from './DOtp';
|
|
55
55
|
export { default as DErrorBoundary, useErrorBoundary, type FallbackProps, getErrorMessage, } from './DErrorBoundary';
|
|
56
56
|
export { default as DDataStateWrapper, EmptyState, ErrorState, LoadingState, } from './DDataStateWrapper';
|
|
@@ -9,3 +9,6 @@ export { default as useMediaQuery } from './useMediaQuery';
|
|
|
9
9
|
export { default as useConfirmModal } from './useConfirmModal';
|
|
10
10
|
export type { UseConfirmModalConfig, UseConfirmModalReturn, ConfirmModalColor, CriticalConfirmConfig, } from './useConfirmModal';
|
|
11
11
|
export { useMediaBreakpointUpXs, useMediaBreakpointUpSm, useMediaBreakpointUpMd, useMediaBreakpointUpLg, useMediaBreakpointUpXl, useMediaBreakpointUpXxl, } from './useMediaBreakpointUp';
|
|
12
|
+
export { default as useCountdown } from './useCountdown';
|
|
13
|
+
export { default as useOtp } from './useOtp';
|
|
14
|
+
export type { UseOtpConfig, UseOtpReturn } from './useOtp';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generic seconds-based countdown hook.
|
|
3
|
+
*
|
|
4
|
+
* Starts counting down from `seconds` to `0` and exposes `restartCountdown`
|
|
5
|
+
* to reset and restart the timer (e.g. for "resend code in Xs" patterns,
|
|
6
|
+
* session-expiry banners, or any other cooldown/throttle UI).
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* const { secondsLeft, restartCountdown } = useCountdown(30);
|
|
10
|
+
*/
|
|
11
|
+
export default function useCountdown(seconds: number): {
|
|
12
|
+
secondsLeft: number;
|
|
13
|
+
restartCountdown: () => void;
|
|
14
|
+
};
|
|
@@ -1,15 +1,10 @@
|
|
|
1
1
|
import type { RefObject, ForwardedRef, FocusEvent } from 'react';
|
|
2
2
|
import type { Options } from 'currency.js';
|
|
3
|
-
|
|
4
|
-
export default function useInputCurrency(currencyOptions: Options, value?: number, onFocus?: (event: FocusEvent<HTMLInputElement>) => void, onChange?: (value?: number) => void, onBlur?: (event: FocusEvent<HTMLInputElement>) => void, ref?: ForwardedRef<HTMLInputElement>): {
|
|
3
|
+
export default function useInputCurrency(currencyOptions: Options, value?: number, onFocus?: (event: FocusEvent<HTMLInputElement>) => void, onChange?: (value?: number) => void, onBlur?: (event: FocusEvent<HTMLInputElement>) => void, ref?: ForwardedRef<HTMLInputElement>, minValue?: number, maxValue?: number): {
|
|
5
4
|
inputRef: RefObject<HTMLInputElement | null>;
|
|
6
5
|
innerValue: string;
|
|
7
6
|
innerType: string;
|
|
8
7
|
handleOnFocus: (event: FocusEvent<HTMLInputElement>) => void;
|
|
9
8
|
handleOnChange: (newValue?: string) => void;
|
|
10
9
|
handleOnBlur: (event: FocusEvent<HTMLInputElement>) => void;
|
|
11
|
-
generateStyleVariables: CustomStyles;
|
|
12
|
-
generateSymbolStyleVariables: {
|
|
13
|
-
color: string;
|
|
14
|
-
};
|
|
15
10
|
};
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
export type UseOtpConfig = {
|
|
2
|
+
/** Called when the OTP reaches the expected length and `submit()` is invoked. */
|
|
3
|
+
action: () => Promise<void> | void;
|
|
4
|
+
/** Expected number of digits/characters for a valid OTP. Defaults to `6`. */
|
|
5
|
+
otpSize?: number;
|
|
6
|
+
/** Initial countdown (in seconds) before resend becomes available. Defaults to `15`. */
|
|
7
|
+
seconds?: number;
|
|
8
|
+
};
|
|
9
|
+
export type UseOtpReturn = {
|
|
10
|
+
/** Current OTP value. */
|
|
11
|
+
otp: string;
|
|
12
|
+
/**
|
|
13
|
+
* Updates the OTP value (wire this to your custom pin input's `onChange`).
|
|
14
|
+
* Also clears `invalid`/`error` as soon as the value actually changes, so
|
|
15
|
+
* the error state disappears once the user edits the code (a no-op call
|
|
16
|
+
* with the same value, e.g. from an uncontrolled input re-notifying its
|
|
17
|
+
* current value, does not reset `invalid`/`error`).
|
|
18
|
+
*/
|
|
19
|
+
setOtp: (value: string) => void;
|
|
20
|
+
/**
|
|
21
|
+
* `true` when `submit()` is called with an OTP shorter than `otpSize`, or
|
|
22
|
+
* when `action` throws/rejects (e.g. the backend rejected the entered
|
|
23
|
+
* code as incorrect).
|
|
24
|
+
*/
|
|
25
|
+
invalid: boolean;
|
|
26
|
+
/**
|
|
27
|
+
* The value thrown/rejected by `action`, or `null` otherwise. Use it to
|
|
28
|
+
* render a specific message for a wrong code, as opposed to a too-short
|
|
29
|
+
* one.
|
|
30
|
+
*/
|
|
31
|
+
error: unknown;
|
|
32
|
+
/**
|
|
33
|
+
* Validates the OTP length; if valid, calls `action`. If `action`
|
|
34
|
+
* rejects, the returned promise rejects too (so callers can still
|
|
35
|
+
* `.catch()` it for logging), and `invalid`/`error` are set beforehand.
|
|
36
|
+
*/
|
|
37
|
+
submit: () => Promise<void>;
|
|
38
|
+
/**
|
|
39
|
+
* `true` while `action` is being awaited inside `submit()` (i.e. the OTP
|
|
40
|
+
* passed the length check and the async action hasn't settled yet). Wire
|
|
41
|
+
* it to your submit button's loading/disabled state. It's `false` while
|
|
42
|
+
* idle and immediately after `action` settles (whether it resolves or
|
|
43
|
+
* rejects), and it's never set to `true` for the too-short/length
|
|
44
|
+
* validation failure since `action` isn't called in that case.
|
|
45
|
+
*/
|
|
46
|
+
isLoading: boolean;
|
|
47
|
+
/** Seconds remaining until resend is available. */
|
|
48
|
+
secondsLeft: number;
|
|
49
|
+
/** Restarts the resend countdown (call it from your "Resend" action). */
|
|
50
|
+
restartCountdown: () => void;
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* Headless hook exposing the same OTP logic used internally by `DOtp`
|
|
54
|
+
* (code state, length + correctness validation, submit action and resend
|
|
55
|
+
* countdown), without any bundled markup/styles.
|
|
56
|
+
*
|
|
57
|
+
* Use this when the default `DOtp` component doesn't match your design and
|
|
58
|
+
* you need to build a fully custom UI while reusing the same behavior.
|
|
59
|
+
*
|
|
60
|
+
* Internally composes `useCountdown` for the resend timer and re-exposes
|
|
61
|
+
* `secondsLeft`/`restartCountdown`, so there is no need to call
|
|
62
|
+
* `useCountdown` separately.
|
|
63
|
+
*
|
|
64
|
+
* `invalid` becomes `true` both when the OTP is shorter than `otpSize` and
|
|
65
|
+
* when `action` throws/rejects (e.g. the backend rejected the entered code
|
|
66
|
+
* as incorrect). In the latter case, the thrown value is exposed as `error`
|
|
67
|
+
* so custom UIs can render an appropriate message (e.g. "Invalid code" vs.
|
|
68
|
+
* "Enter all digits"). `invalid`/`error` are cleared automatically as soon
|
|
69
|
+
* as the user edits the code via `setOtp`.
|
|
70
|
+
*
|
|
71
|
+
* @example
|
|
72
|
+
* function CustomOtp() {
|
|
73
|
+
* const {
|
|
74
|
+
* otp,
|
|
75
|
+
* setOtp,
|
|
76
|
+
* invalid,
|
|
77
|
+
* error,
|
|
78
|
+
* submit,
|
|
79
|
+
* isLoading,
|
|
80
|
+
* secondsLeft,
|
|
81
|
+
* restartCountdown,
|
|
82
|
+
* } = useOtp({ action: async () => verifyOtp(otp), otpSize: 6, seconds: 15 });
|
|
83
|
+
*
|
|
84
|
+
* return (
|
|
85
|
+
* <>
|
|
86
|
+
* <MyCustomPinInput value={otp} onChange={setOtp} invalid={invalid} />
|
|
87
|
+
* {invalid && <span>{error ? 'Invalid code' : 'Enter all digits'}</span>}
|
|
88
|
+
* <button disabled={isLoading} onClick={() => { submit().catch(() => {}); }}>
|
|
89
|
+
* {isLoading ? 'Submitting...' : 'Submit'}
|
|
90
|
+
* </button>
|
|
91
|
+
* <button disabled={secondsLeft > 0} onClick={restartCountdown}>
|
|
92
|
+
* Resend {secondsLeft > 0 ? `(${secondsLeft}s)` : ''}
|
|
93
|
+
* </button>
|
|
94
|
+
* </>
|
|
95
|
+
* );
|
|
96
|
+
* }
|
|
97
|
+
*/
|
|
98
|
+
export default function useOtp({ action, otpSize, seconds, }: UseOtpConfig): UseOtpReturn;
|
package/package.json
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
$input-currency-symbol-color: var(--#{$prefix}secondary) !default;
|
|
@@ -22,3 +22,10 @@
|
|
|
22
22
|
@import "d-table-head";
|
|
23
23
|
@import "d-input-phone";
|
|
24
24
|
@import "d-credit-card";
|
|
25
|
+
@import "d-input-currency";
|
|
26
|
+
@import "d-confirm-modal";
|
|
27
|
+
@import "d-data-state-wrapper";
|
|
28
|
+
@import "d-error-boundary";
|
|
29
|
+
@import "d-otp";
|
|
30
|
+
@import "d-password-strength-meter";
|
|
31
|
+
@import "d-stepper";
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
.confirm-modal {
|
|
2
|
+
--#{$prefix}confirm-modal-body-padding-y: var(--#{$prefix}ref-spacer-3);
|
|
3
|
+
--#{$prefix}confirm-modal-body-padding-x: var(--#{$prefix}ref-spacer-5);
|
|
4
|
+
--#{$prefix}confirm-modal-field-gap: var(--#{$prefix}ref-spacer-4);
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
.d-confirm-modal-body {
|
|
8
|
+
padding: var(--#{$prefix}confirm-modal-body-padding-y) var(--#{$prefix}confirm-modal-body-padding-x);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.d-confirm-modal-message {
|
|
12
|
+
margin-bottom: var(--#{$prefix}confirm-modal-field-gap);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.d-confirm-modal-field {
|
|
16
|
+
margin-bottom: var(--#{$prefix}confirm-modal-field-gap);
|
|
17
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
.d-empty-state {
|
|
2
|
+
--#{$prefix}empty-state-padding: var(--#{$prefix}ref-spacer-5);
|
|
3
|
+
--#{$prefix}empty-state-spacing: var(--#{$prefix}ref-spacer-3);
|
|
4
|
+
--#{$prefix}empty-state-color: var(--#{$prefix}secondary);
|
|
5
|
+
|
|
6
|
+
display: flex;
|
|
7
|
+
flex-direction: column;
|
|
8
|
+
align-items: center;
|
|
9
|
+
justify-content: center;
|
|
10
|
+
padding: var(--#{$prefix}empty-state-padding);
|
|
11
|
+
text-align: center;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.d-empty-state-icon {
|
|
15
|
+
margin-bottom: var(--#{$prefix}empty-state-spacing);
|
|
16
|
+
color: var(--#{$prefix}empty-state-color);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.d-empty-state-message {
|
|
20
|
+
margin-bottom: var(--#{$prefix}empty-state-spacing);
|
|
21
|
+
color: var(--#{$prefix}empty-state-color);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.d-error-state {
|
|
25
|
+
--#{$prefix}error-state-gap: var(--#{$prefix}ref-spacer-3);
|
|
26
|
+
|
|
27
|
+
display: flex;
|
|
28
|
+
gap: var(--#{$prefix}error-state-gap);
|
|
29
|
+
align-items: center;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.d-error-state-content {
|
|
33
|
+
flex: 1 1 auto;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.d-error-state-message {
|
|
37
|
+
margin-bottom: 0;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.d-loading-state {
|
|
41
|
+
--#{$prefix}loading-state-padding: var(--#{$prefix}ref-spacer-4);
|
|
42
|
+
|
|
43
|
+
display: flex;
|
|
44
|
+
align-items: center;
|
|
45
|
+
justify-content: center;
|
|
46
|
+
padding: var(--#{$prefix}loading-state-padding);
|
|
47
|
+
}
|
|
@@ -215,6 +215,12 @@
|
|
|
215
215
|
}
|
|
216
216
|
}
|
|
217
217
|
|
|
218
|
+
&-year-selector {
|
|
219
|
+
display: flex;
|
|
220
|
+
flex-grow: 1;
|
|
221
|
+
justify-content: center;
|
|
222
|
+
}
|
|
223
|
+
|
|
218
224
|
&-day-selector {
|
|
219
225
|
margin-bottom: var(--#{$prefix}ref-spacer-4);
|
|
220
226
|
|
|
@@ -287,6 +293,11 @@
|
|
|
287
293
|
margin-top: -.5rem;
|
|
288
294
|
}
|
|
289
295
|
|
|
296
|
+
.datepicker-top-header-title {
|
|
297
|
+
margin-bottom: 0;
|
|
298
|
+
font-weight: var(--#{$prefix}fw-normal);
|
|
299
|
+
}
|
|
300
|
+
|
|
290
301
|
.react-datepicker__year,
|
|
291
302
|
.react-datepicker__quarterPicker {
|
|
292
303
|
--#{$prefix}datepicker-body-gap: 1rem;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
.d-otp {
|
|
2
|
+
--#{$prefix}otp-content-gap: var(--#{$prefix}ref-spacer-6);
|
|
3
|
+
--#{$prefix}otp-content-padding-x: var(--#{$prefix}ref-spacer-3);
|
|
4
|
+
--#{$prefix}otp-content-padding-bottom: var(--#{$prefix}ref-spacer-4);
|
|
5
|
+
--#{$prefix}otp-footer-gap: var(--#{$prefix}ref-spacer-4);
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
.d-otp-content {
|
|
9
|
+
display: flex;
|
|
10
|
+
flex-direction: column;
|
|
11
|
+
gap: var(--#{$prefix}otp-content-gap);
|
|
12
|
+
padding: 0 var(--#{$prefix}otp-content-padding-x) var(--#{$prefix}otp-content-padding-bottom);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.d-otp-fields {
|
|
16
|
+
display: flex;
|
|
17
|
+
flex-direction: column;
|
|
18
|
+
gap: var(--#{$prefix}otp-content-gap);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.d-otp-divider {
|
|
22
|
+
margin: 0;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.d-otp-footer {
|
|
26
|
+
display: flex;
|
|
27
|
+
flex-direction: column;
|
|
28
|
+
gap: var(--#{$prefix}otp-footer-gap);
|
|
29
|
+
align-items: center;
|
|
30
|
+
|
|
31
|
+
@include media-breakpoint-up(lg) {
|
|
32
|
+
flex-direction: row;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.d-otp-contact {
|
|
37
|
+
margin-bottom: 0;
|
|
38
|
+
font-size: .875em;
|
|
39
|
+
|
|
40
|
+
@include media-breakpoint-up(lg) {
|
|
41
|
+
margin-left: auto;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.d-otp-countdown {
|
|
46
|
+
display: flex;
|
|
47
|
+
gap: var(--#{$prefix}ref-spacer-2);
|
|
48
|
+
align-items: center;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.d-otp-countdown-text {
|
|
52
|
+
flex: 1 1 auto;
|
|
53
|
+
margin-bottom: 0;
|
|
54
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
.d-password-strength-meter {
|
|
2
|
+
--#{$prefix}password-strength-meter-margin-top: var(--#{$prefix}ref-spacer-2);
|
|
3
|
+
|
|
4
|
+
margin-top: var(--#{$prefix}password-strength-meter-margin-top);
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
.d-password-strength-bar {
|
|
8
|
+
--#{$prefix}password-strength-bar-height: 8px;
|
|
9
|
+
--#{$prefix}password-strength-bar-radius: var(--#{$prefix}border-radius-lg);
|
|
10
|
+
--#{$prefix}password-strength-bar-bg: var(--#{$prefix}gray-100);
|
|
11
|
+
--#{$prefix}password-strength-bar-margin-bottom: var(--#{$prefix}ref-spacer-2);
|
|
12
|
+
|
|
13
|
+
width: 100%;
|
|
14
|
+
height: var(--#{$prefix}password-strength-bar-height);
|
|
15
|
+
margin-bottom: var(--#{$prefix}password-strength-bar-margin-bottom);
|
|
16
|
+
overflow: hidden;
|
|
17
|
+
background: var(--#{$prefix}password-strength-bar-bg);
|
|
18
|
+
border-radius: var(--#{$prefix}password-strength-bar-radius);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.d-password-strength-bar-fill {
|
|
22
|
+
height: 100%;
|
|
23
|
+
transition: width .3s ease-in-out;
|
|
24
|
+
|
|
25
|
+
&.is-empty {
|
|
26
|
+
background: var(--#{$prefix}gray-200);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
&.is-weak {
|
|
30
|
+
background: var(--#{$prefix}danger);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
&.is-fair {
|
|
34
|
+
background: var(--#{$prefix}warning);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
&.is-good {
|
|
38
|
+
background: var(--#{$prefix}info);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
&.is-strong {
|
|
42
|
+
background: var(--#{$prefix}success);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.d-password-check-list {
|
|
47
|
+
display: flex;
|
|
48
|
+
flex-direction: column;
|
|
49
|
+
gap: var(--#{$prefix}ref-spacer-2);
|
|
50
|
+
padding-left: 0;
|
|
51
|
+
margin: 0;
|
|
52
|
+
list-style: none;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.d-password-check-item {
|
|
56
|
+
--#{$prefix}password-check-item-color: var(--#{$prefix}gray-600);
|
|
57
|
+
|
|
58
|
+
display: flex;
|
|
59
|
+
gap: var(--#{$prefix}ref-spacer-2);
|
|
60
|
+
align-items: flex-start;
|
|
61
|
+
font-size: .875em;
|
|
62
|
+
color: var(--#{$prefix}password-check-item-color);
|
|
63
|
+
|
|
64
|
+
&.is-valid {
|
|
65
|
+
color: var(--#{$prefix}success);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.d-password-check-item-icon {
|
|
70
|
+
flex-shrink: 0;
|
|
71
|
+
color: var(--#{$prefix}gray-300);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.d-password-check-item.is-valid .d-password-check-item-icon {
|
|
75
|
+
color: var(--#{$prefix}success);
|
|
76
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// Semantic hook classes for theming. The mobile/desktop toggle itself relies on
|
|
2
|
+
// Bootstrap's responsive display utilities (d-{breakpoint}-none / d-{breakpoint}-block)
|
|
3
|
+
// because the breakpoint is dynamic (component prop) and CSS custom properties
|
|
4
|
+
// cannot be read inside media queries.
|
|
5
|
+
.d-stepper-mobile,
|
|
6
|
+
.d-stepper-desktop {
|
|
7
|
+
width: 100%;
|
|
8
|
+
}
|
|
@@ -1,3 +1,21 @@
|
|
|
1
|
+
.d-tabs {
|
|
2
|
+
display: flex;
|
|
3
|
+
width: 100%;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
.d-tabs-column {
|
|
7
|
+
flex-direction: column;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
.d-tabs-nav-vertical {
|
|
11
|
+
flex-direction: column;
|
|
12
|
+
align-items: center;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.d-tabs-content {
|
|
16
|
+
width: 100%;
|
|
17
|
+
}
|
|
18
|
+
|
|
1
19
|
.nav-toggle-button-group {
|
|
2
20
|
--#{$prefix}toggle-button-group-border-color: var(--#{$prefix}gray-50);
|
|
3
21
|
--#{$prefix}toggle-button-group-border-radius: 4rem;
|
|
@@ -5,6 +5,9 @@
|
|
|
5
5
|
--#{$prefix}voucher-amount-rounded: var(--#{$prefix}ref-spacer-4);
|
|
6
6
|
--#{$prefix}voucher-footer-gap: var(--#{$prefix}ref-spacer-4);
|
|
7
7
|
--#{$prefix}voucher-margin: 0 0 var(--#{$prefix}ref-spacer-4) 0;
|
|
8
|
+
--#{$prefix}voucher-title-margin-bottom: var(--#{$prefix}ref-spacer-2);
|
|
9
|
+
--#{$prefix}voucher-amount-value-margin: var(--#{$prefix}ref-spacer-1);
|
|
10
|
+
--#{$prefix}voucher-divider-margin: var(--#{$prefix}ref-spacer-4);
|
|
8
11
|
}
|
|
9
12
|
|
|
10
13
|
.d-voucher-header {
|
|
@@ -28,3 +31,30 @@
|
|
|
28
31
|
gap: var(--#{$prefix}voucher-footer-gap);
|
|
29
32
|
justify-content: flex-start;
|
|
30
33
|
}
|
|
34
|
+
|
|
35
|
+
.d-voucher-title-group {
|
|
36
|
+
text-align: center;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.d-voucher-title {
|
|
40
|
+
margin-bottom: var(--#{$prefix}voucher-title-margin-bottom);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.d-voucher-message {
|
|
44
|
+
margin: 0;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.d-voucher-amount-value {
|
|
48
|
+
margin: 0;
|
|
49
|
+
font-size: var(--#{$prefix}fs-3);
|
|
50
|
+
font-weight: var(--#{$prefix}fw-bold);
|
|
51
|
+
text-align: center;
|
|
52
|
+
|
|
53
|
+
&.d-voucher-amount-value-with-details {
|
|
54
|
+
margin-bottom: var(--#{$prefix}voucher-amount-value-margin);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.d-voucher-divider {
|
|
59
|
+
margin: var(--#{$prefix}voucher-divider-margin) 0;
|
|
60
|
+
}
|
|
File without changes
|