@dynamic-framework/ui-react 2.7.0 → 2.9.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 +276 -22
- package/dist/css/dynamic-ui.min.css +2 -2
- package/dist/index.esm.js +677 -298
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +683 -297
- package/dist/index.js.map +1 -1
- package/dist/types/components/DDropdown/DDropdown.d.ts +10 -2
- package/dist/types/components/DInputCheck/DInputCheck.d.ts +1 -0
- package/dist/types/components/DInputSwitch/DInputSwitch.d.ts +2 -1
- package/dist/types/components/DModal/components/DModalHeader.d.ts +5 -1
- package/dist/types/components/DOffcanvas/components/DOffcanvasHeader.d.ts +5 -1
- 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/DTooltip/DTooltip.d.ts +38 -3
- 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/dist/types/utils/buildUrl.d.ts +32 -0
- package/dist/types/utils/index.d.ts +2 -0
- package/dist/types/utils/sanitizeHref.d.ts +37 -0
- package/dist/types/utils/tests/buildUrl.spec.d.ts +1 -0
- package/dist/types/utils/tests/sanitizeHref.spec.d.ts +1 -0
- package/package.json +9 -6
- package/src/style/_shame.scss +1 -5
- package/src/style/abstracts/variables/_+import.scss +2 -0
- package/src/style/abstracts/variables/_box.scss +7 -0
- package/src/style/abstracts/variables/_forms.scss +1 -3
- package/src/style/abstracts/variables/_input-currency.scss +1 -0
- package/src/style/abstracts/variables/_shadow.scss +12 -1
- package/src/style/base/_+import.scss +0 -1
- package/src/style/base/_form-check.scss +4 -2
- package/src/style/components/_+import.scss +7 -0
- package/src/style/components/_d-box-file.scss +5 -0
- package/src/style/components/_d-box.scss +5 -5
- 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
- package/src/style/base/_form-text.scss +0 -12
package/dist/index.esm.js
CHANGED
|
@@ -563,12 +563,12 @@ function DIcon(_a) {
|
|
|
563
563
|
return (jsx(DIconBase, Object.assign({ icon: resolvedIcon, familyClass: propFamilyClass !== null && propFamilyClass !== void 0 ? propFamilyClass : familyClass, familyPrefix: propFamilyPrefix !== null && propFamilyPrefix !== void 0 ? propFamilyPrefix : familyPrefix, materialStyle: propMaterialStyle !== null && propMaterialStyle !== void 0 ? propMaterialStyle : materialStyle }, props)));
|
|
564
564
|
}
|
|
565
565
|
|
|
566
|
-
function DAlert({ color = 'success', icon: iconProp, iconFamilyClass, iconFamilyPrefix, iconMaterialStyle
|
|
567
|
-
const { iconMap: { alert, xLg, }, } = useDContext();
|
|
566
|
+
function DAlert({ color = 'success', icon: iconProp, iconFamilyClass, iconFamilyPrefix, iconMaterialStyle, iconClose: iconCloseProp, iconCloseFamilyClass, iconCloseFamilyPrefix, iconCloseMaterialStyle, showClose, onClose, children, id, className, style, dataAttributes, }) {
|
|
567
|
+
const { icon: { materialStyle, familyClass, familyPrefix, }, iconMap: { alert, xLg, }, } = useDContext();
|
|
568
568
|
const icon = useMemo(() => iconProp || alert[color], [alert, iconProp, color]);
|
|
569
569
|
const iconClose = useMemo(() => (iconCloseProp || xLg), [iconCloseProp, xLg]);
|
|
570
570
|
const generateClasses = useMemo(() => (Object.assign({ alert: true, [`alert-${color}`]: true, 'fade show': !!showClose }, className && { [className]: true })), [color, showClose, className]);
|
|
571
|
-
return (jsxs("div", Object.assign({ className: classNames(generateClasses), style: style, role: "alert", id: id }, dataAttributes, { children: [icon && (jsx(DIcon, { className: "alert-icon", icon: icon, familyClass: iconFamilyClass, familyPrefix: iconFamilyPrefix, materialStyle: iconMaterialStyle })), jsx("div", { className: "alert-text", children: children }), showClose && (jsx("button", { type: "button", className: "d-close", "aria-label": "Close", onClick: onClose, children: jsx(DIcon, { icon: iconClose, familyClass: iconCloseFamilyClass, familyPrefix: iconCloseFamilyPrefix, materialStyle: iconCloseMaterialStyle }) }))] })));
|
|
571
|
+
return (jsxs("div", Object.assign({ className: classNames(generateClasses), style: style, role: "alert", id: id }, dataAttributes, { children: [icon && (jsx(DIcon, { className: "alert-icon", icon: icon, familyClass: iconFamilyClass !== null && iconFamilyClass !== void 0 ? iconFamilyClass : familyClass, familyPrefix: iconFamilyPrefix !== null && iconFamilyPrefix !== void 0 ? iconFamilyPrefix : familyPrefix, materialStyle: iconMaterialStyle !== null && iconMaterialStyle !== void 0 ? iconMaterialStyle : materialStyle })), jsx("div", { className: "alert-text", children: children }), showClose && (jsx("button", { type: "button", className: "d-close", "aria-label": "Close", onClick: onClose, children: jsx(DIcon, { icon: iconClose, familyClass: iconCloseFamilyClass !== null && iconCloseFamilyClass !== void 0 ? iconCloseFamilyClass : familyClass, familyPrefix: iconCloseFamilyPrefix !== null && iconCloseFamilyPrefix !== void 0 ? iconCloseFamilyPrefix : familyPrefix, materialStyle: iconCloseMaterialStyle !== null && iconCloseMaterialStyle !== void 0 ? iconCloseMaterialStyle : materialStyle }) }))] })));
|
|
572
572
|
}
|
|
573
573
|
|
|
574
574
|
function DAvatar({ id, size, image, name: nameProp, useNameAsInitials = false, className, style, dataAttributes, }) {
|
|
@@ -590,6 +590,7 @@ function DAvatar({ id, size, image, name: nameProp, useNameAsInitials = false, c
|
|
|
590
590
|
|
|
591
591
|
function DBadge(props) {
|
|
592
592
|
const { text, soft = false, color = 'primary', id, rounded, className, size, style, iconStart, iconEnd, iconMaterialStyle, iconFamilyClass, iconFamilyPrefix, dataAttributes, } = props;
|
|
593
|
+
const { icon: { familyClass, familyPrefix, materialStyle, }, } = useDContext();
|
|
593
594
|
// Responsive size resolution using useResponsiveProp
|
|
594
595
|
const { responsivePropValue } = useResponsiveProp(true);
|
|
595
596
|
const resolvedSize = useMemo(() => {
|
|
@@ -606,7 +607,7 @@ function DBadge(props) {
|
|
|
606
607
|
'rounded-pill': !!rounded,
|
|
607
608
|
[`badge-${resolvedSize}`]: !!resolvedSize,
|
|
608
609
|
}), [rounded, soft, color, resolvedSize]);
|
|
609
|
-
return (jsxs("span", Object.assign({ className: classNames(generateClasses, className), style: style }, id && { id }, dataAttributes, { children: [iconStart && (jsx(DIcon, { icon: iconStart, familyClass: iconFamilyClass, familyPrefix: iconFamilyPrefix, materialStyle: iconMaterialStyle })), jsx("span", { children: text }), iconEnd && (jsx(DIcon, { icon: iconEnd, familyClass: iconFamilyClass, familyPrefix: iconFamilyPrefix, materialStyle: iconMaterialStyle }))] })));
|
|
610
|
+
return (jsxs("span", Object.assign({ className: classNames(generateClasses, className), style: style }, id && { id }, dataAttributes, { children: [iconStart && (jsx(DIcon, { icon: iconStart, familyClass: iconFamilyClass !== null && iconFamilyClass !== void 0 ? iconFamilyClass : familyClass, familyPrefix: iconFamilyPrefix !== null && iconFamilyPrefix !== void 0 ? iconFamilyPrefix : familyPrefix, materialStyle: iconMaterialStyle !== null && iconMaterialStyle !== void 0 ? iconMaterialStyle : materialStyle })), jsx("span", { children: text }), iconEnd && (jsx(DIcon, { icon: iconEnd, familyClass: iconFamilyClass !== null && iconFamilyClass !== void 0 ? iconFamilyClass : familyClass, familyPrefix: iconFamilyPrefix !== null && iconFamilyPrefix !== void 0 ? iconFamilyPrefix : familyPrefix, materialStyle: iconMaterialStyle !== null && iconMaterialStyle !== void 0 ? iconMaterialStyle : materialStyle }))] })));
|
|
610
611
|
}
|
|
611
612
|
|
|
612
613
|
function DBox({ className, style, children, dataAttributes, }) {
|
|
@@ -638,6 +639,7 @@ function DInput(_a, ref) {
|
|
|
638
639
|
const inputRef = useProvidedRefOrCreate(ref);
|
|
639
640
|
const innerId = useId();
|
|
640
641
|
const id = useMemo(() => idProp || innerId, [idProp, innerId]);
|
|
642
|
+
const { icon: { familyClass, familyPrefix, materialStyle, }, } = useDContext();
|
|
641
643
|
const handleOnChange = useCallback((event) => {
|
|
642
644
|
onChange === null || onChange === void 0 ? void 0 : onChange(event.currentTarget.value);
|
|
643
645
|
}, [onChange]);
|
|
@@ -700,7 +702,7 @@ function DInput(_a, ref) {
|
|
|
700
702
|
[`input-group-${size}`]: !!size,
|
|
701
703
|
'input-group': true,
|
|
702
704
|
'has-validation': invalid || valid,
|
|
703
|
-
}), children: [!!inputStart && (jsx("div", { className: "input-group-text", id: `${id}InputStart`, children: inputStart })), iconStart && (onIconStartClick ? (jsx("button", { type: "button", className: "input-group-text", id: `${id}Start`, onClick: handleOnIconStartClick, disabled: disabled || loading || iconStartDisabled, "aria-label": iconStartAriaLabel || (typeof iconStart === 'string' ? iconStart : 'start icon'), tabIndex: iconStartTabIndex, children: jsx(DIcon, { icon: iconStart, familyClass: iconStartFamilyClass, familyPrefix: iconStartFamilyPrefix, materialStyle: iconStartMaterialStyle }) })) : (jsx("div", { className: "input-group-text", id: `${id}Start`, "aria-hidden": "true", tabIndex: -1, children: jsx(DIcon, { icon: iconStart, familyClass: iconStartFamilyClass, familyPrefix: iconStartFamilyPrefix, materialStyle: iconStartMaterialStyle }) }))), dynamicComponent, (iconEnd && !loading) && (onIconEndClick ? (jsx("button", { type: "button", className: "input-group-text", id: `${id}End`, onClick: handleOnIconEndClick, disabled: disabled || loading || iconEndDisabled, "aria-label": iconEndAriaLabel || (typeof iconEnd === 'string' ? iconEnd : 'end icon'), tabIndex: iconEndTabIndex, children: jsx(DIcon, { icon: iconEnd, familyClass: iconEndFamilyClass, familyPrefix: iconEndFamilyPrefix, materialStyle: iconEndMaterialStyle }) })) : (jsx("div", { className: "input-group-text", id: `${id}End`, "aria-hidden": "true", tabIndex: -1, children: jsx(DIcon, { icon: iconEnd, familyClass: iconEndFamilyClass, familyPrefix: iconEndFamilyPrefix, materialStyle: iconEndMaterialStyle }) }))), loading && (jsx("div", { className: "input-group-text", id: `${id}Loading`, children: jsx("span", { className: "spinner-border spinner-border-sm", role: "status", "aria-hidden": "true", "data-testid": "loading-spinner", children: jsx("span", { className: "visually-hidden", children: "Loading..." }) }) })), !!inputEnd && (jsx("div", { className: "input-group-text", id: `${id}InputEnd`, children: inputEnd }))] }), hint && (jsx("div", { className: "form-text", id: `${id}Hint`, children: hint }))] })));
|
|
705
|
+
}), children: [!!inputStart && (jsx("div", { className: "input-group-text", id: `${id}InputStart`, children: inputStart })), iconStart && (onIconStartClick ? (jsx("button", { type: "button", className: "input-group-text", id: `${id}Start`, onClick: handleOnIconStartClick, disabled: disabled || loading || iconStartDisabled, "aria-label": iconStartAriaLabel || (typeof iconStart === 'string' ? iconStart : 'start icon'), tabIndex: iconStartTabIndex, children: jsx(DIcon, { icon: iconStart, familyClass: iconStartFamilyClass !== null && iconStartFamilyClass !== void 0 ? iconStartFamilyClass : familyClass, familyPrefix: iconStartFamilyPrefix !== null && iconStartFamilyPrefix !== void 0 ? iconStartFamilyPrefix : familyPrefix, materialStyle: iconStartMaterialStyle !== null && iconStartMaterialStyle !== void 0 ? iconStartMaterialStyle : materialStyle }) })) : (jsx("div", { className: "input-group-text", id: `${id}Start`, "aria-hidden": "true", tabIndex: -1, children: jsx(DIcon, { icon: iconStart, familyClass: iconStartFamilyClass !== null && iconStartFamilyClass !== void 0 ? iconStartFamilyClass : familyClass, familyPrefix: iconStartFamilyPrefix !== null && iconStartFamilyPrefix !== void 0 ? iconStartFamilyPrefix : familyPrefix, materialStyle: iconStartMaterialStyle !== null && iconStartMaterialStyle !== void 0 ? iconStartMaterialStyle : materialStyle }) }))), dynamicComponent, (iconEnd && !loading) && (onIconEndClick ? (jsx("button", { type: "button", className: "input-group-text", id: `${id}End`, onClick: handleOnIconEndClick, disabled: disabled || loading || iconEndDisabled, "aria-label": iconEndAriaLabel || (typeof iconEnd === 'string' ? iconEnd : 'end icon'), tabIndex: iconEndTabIndex, children: jsx(DIcon, { icon: iconEnd, familyClass: iconEndFamilyClass !== null && iconEndFamilyClass !== void 0 ? iconEndFamilyClass : familyClass, familyPrefix: iconEndFamilyPrefix !== null && iconEndFamilyPrefix !== void 0 ? iconEndFamilyPrefix : familyPrefix, materialStyle: iconEndMaterialStyle !== null && iconEndMaterialStyle !== void 0 ? iconEndMaterialStyle : materialStyle }) })) : (jsx("div", { className: "input-group-text", id: `${id}End`, "aria-hidden": "true", tabIndex: -1, children: jsx(DIcon, { icon: iconEnd, familyClass: iconEndFamilyClass !== null && iconEndFamilyClass !== void 0 ? iconEndFamilyClass : familyClass, familyPrefix: iconEndFamilyPrefix !== null && iconEndFamilyPrefix !== void 0 ? iconEndFamilyPrefix : familyPrefix, materialStyle: iconEndMaterialStyle !== null && iconEndMaterialStyle !== void 0 ? iconEndMaterialStyle : materialStyle }) }))), loading && (jsx("div", { className: "input-group-text", id: `${id}Loading`, children: jsx("span", { className: "spinner-border spinner-border-sm", role: "status", "aria-hidden": "true", "data-testid": "loading-spinner", children: jsx("span", { className: "visually-hidden", children: "Loading..." }) }) })), !!inputEnd && (jsx("div", { className: "input-group-text", id: `${id}InputEnd`, children: inputEnd }))] }), hint && (jsx("div", { className: "form-text", id: `${id}Hint`, children: hint }))] })));
|
|
704
706
|
}
|
|
705
707
|
const ForwardedDInput = forwardRef(DInput);
|
|
706
708
|
ForwardedDInput.displayName = 'DInput';
|
|
@@ -1096,7 +1098,7 @@ function useDBoxFile(props) {
|
|
|
1096
1098
|
|
|
1097
1099
|
function DBoxFile(_a) {
|
|
1098
1100
|
var { icon: iconProp, iconFamilyClass, iconFamilyPrefix, iconMaterialStyle, children, className, style, dataAttributes } = _a, props = __rest(_a, ["icon", "iconFamilyClass", "iconFamilyPrefix", "iconMaterialStyle", "children", "className", "style", "dataAttributes"]);
|
|
1099
|
-
const { iconMap: { upload } } = useDContext();
|
|
1101
|
+
const { icon: { familyClass, familyPrefix, materialStyle, }, iconMap: { upload }, } = useDContext();
|
|
1100
1102
|
const icon = useMemo(() => iconProp || upload, [iconProp, upload]);
|
|
1101
1103
|
const { inputRef, rootRef, isDragValid, isDragInvalid, acceptAttr, files, handleFileSelect, handleDrop, handleDragEnter, handleDragLeave, handleClick, handleKeyDown, handleRemoveFile, openFileDialog, } = useDBoxFile(props);
|
|
1102
1104
|
return (jsxs(Fragment, { children: [jsx("section", Object.assign({ className: classNames('d-box-file', {
|
|
@@ -1104,13 +1106,14 @@ function DBoxFile(_a) {
|
|
|
1104
1106
|
'd-box-file-disabled': props.disabled,
|
|
1105
1107
|
'd-box-file-valid': isDragValid,
|
|
1106
1108
|
'd-box-file-invalid': isDragInvalid,
|
|
1107
|
-
}, className), style: style }, dataAttributes, { children: jsxs("div", Object.assign({ className: "d-box-file-dropzone", ref: rootRef, onDragEnter: handleDragEnter, onDragOver: (e) => e.preventDefault(), onDragLeave: handleDragLeave, onDrop: handleDrop, onClick: handleClick, onKeyDown: handleKeyDown }, (!props.disabled && !props.noKeyboard ? { tabIndex: 0 } : {}), { role: "presentation", children: [jsx("input", { type: "file", multiple: props.multiple, style: { display: 'none' }, ref: inputRef, disabled: props.disabled, onChange: handleFileSelect, onClick: (e) => e.stopPropagation(), tabIndex: -1, accept: acceptAttr }), icon && iconProp !== false && (jsx(DIcon, { icon: icon, familyClass: iconFamilyClass, familyPrefix: iconFamilyPrefix, materialStyle: iconMaterialStyle })), jsx("div", { className: "d-box-content", children: typeof children === 'function'
|
|
1109
|
+
}, className), style: style }, dataAttributes, { children: jsxs("div", Object.assign({ className: "d-box-file-dropzone", ref: rootRef, onDragEnter: handleDragEnter, onDragOver: (e) => e.preventDefault(), onDragLeave: handleDragLeave, onDrop: handleDrop, onClick: handleClick, onKeyDown: handleKeyDown }, (!props.disabled && !props.noKeyboard ? { tabIndex: 0 } : {}), { role: "presentation", children: [jsx("input", { type: "file", multiple: props.multiple, style: { display: 'none' }, ref: inputRef, disabled: props.disabled, onChange: handleFileSelect, onClick: (e) => e.stopPropagation(), tabIndex: -1, accept: acceptAttr }), icon && iconProp !== false && (jsx(DIcon, { icon: icon, familyClass: iconFamilyClass !== null && iconFamilyClass !== void 0 ? iconFamilyClass : familyClass, familyPrefix: iconFamilyPrefix !== null && iconFamilyPrefix !== void 0 ? iconFamilyPrefix : familyPrefix, materialStyle: iconMaterialStyle !== null && iconMaterialStyle !== void 0 ? iconMaterialStyle : materialStyle })), jsx("div", { className: "d-box-content", children: typeof children === 'function'
|
|
1108
1110
|
? children(openFileDialog)
|
|
1109
|
-
: children || (jsx("p", { className: "
|
|
1111
|
+
: children || (jsx("p", { className: "d-box-file-empty-text", children: "Drag and drop some files here, or click to select files" })) })] })) })), !!files.length && (jsx("ul", { className: "d-box-files", children: files.map((file, index) => (jsx(ForwardedDInput, { value: file.name, iconStart: "Paperclip", iconEnd: "Trash", readOnly: true, onIconEndClick: () => handleRemoveFile(index) }, `${file.name} ${index}`))) }))] }));
|
|
1110
1112
|
}
|
|
1111
1113
|
|
|
1112
1114
|
const DButton = forwardRef((props, ref) => {
|
|
1113
1115
|
const { color = 'primary', size, variant = 'solid', text, children, iconStart, iconStartFamilyClass, iconStartFamilyPrefix, iconStartMaterialStyle, iconEnd, iconEndFamilyClass, iconEndFamilyPrefix, iconEndMaterialStyle, loading = false, loadingText, loadingAriaLabel, disabled = false, className, style, dataAttributes, onClick, type = 'button', target, rel, href, 'aria-label': ariaLabelProp } = props, rest = __rest(props, ["color", "size", "variant", "text", "children", "iconStart", "iconStartFamilyClass", "iconStartFamilyPrefix", "iconStartMaterialStyle", "iconEnd", "iconEndFamilyClass", "iconEndFamilyPrefix", "iconEndMaterialStyle", "loading", "loadingText", "loadingAriaLabel", "disabled", "className", "style", "dataAttributes", "onClick", "type", "target", "rel", "href", 'aria-label']);
|
|
1116
|
+
const { icon: { familyClass, familyPrefix, materialStyle, }, } = useDContext();
|
|
1114
1117
|
// Responsive size resolution using useResponsiveProp
|
|
1115
1118
|
const { responsivePropValue } = useResponsiveProp(true);
|
|
1116
1119
|
const resolvedSize = useMemo(() => {
|
|
@@ -1164,7 +1167,7 @@ const DButton = forwardRef((props, ref) => {
|
|
|
1164
1167
|
ref.current = node;
|
|
1165
1168
|
}, className: classNames(classes, className), style: Object.assign(Object.assign({}, style), (loading && buttonWidth
|
|
1166
1169
|
? { minWidth: `${buttonWidth}px` }
|
|
1167
|
-
: undefined)), "aria-label": ariaLabel, "aria-busy": loading, "aria-disabled": isDisabled, onClick: handleClick }, dataAttributes, { children: [loading && (jsxs("span", { className: "btn-loading", children: [jsx("span", { className: "spinner-border spinner-border-sm", "aria-hidden": "true" }), loadingText && jsx("span", { role: "status", children: loadingText })] })), !loading && (jsxs(Fragment, { children: [iconStart && (jsx(DIcon, { icon: iconStart, familyClass: iconStartFamilyClass, familyPrefix: iconStartFamilyPrefix, materialStyle: iconStartMaterialStyle })), content, iconEnd && (jsx(DIcon, { icon: iconEnd, familyClass: iconEndFamilyClass, familyPrefix: iconEndFamilyPrefix, materialStyle: iconEndMaterialStyle }))] }))] })));
|
|
1170
|
+
: undefined)), "aria-label": ariaLabel, "aria-busy": loading, "aria-disabled": isDisabled, onClick: handleClick }, dataAttributes, { children: [loading && (jsxs("span", { className: "btn-loading", children: [jsx("span", { className: "spinner-border spinner-border-sm", "aria-hidden": "true" }), loadingText && jsx("span", { role: "status", children: loadingText })] })), !loading && (jsxs(Fragment, { children: [iconStart && (jsx(DIcon, { icon: iconStart, familyClass: iconStartFamilyClass !== null && iconStartFamilyClass !== void 0 ? iconStartFamilyClass : familyClass, familyPrefix: iconStartFamilyPrefix !== null && iconStartFamilyPrefix !== void 0 ? iconStartFamilyPrefix : familyPrefix, materialStyle: iconStartMaterialStyle !== null && iconStartMaterialStyle !== void 0 ? iconStartMaterialStyle : materialStyle })), content, iconEnd && (jsx(DIcon, { icon: iconEnd, familyClass: iconEndFamilyClass !== null && iconEndFamilyClass !== void 0 ? iconEndFamilyClass : familyClass, familyPrefix: iconEndFamilyPrefix !== null && iconEndFamilyPrefix !== void 0 ? iconEndFamilyPrefix : familyPrefix, materialStyle: iconEndMaterialStyle !== null && iconEndMaterialStyle !== void 0 ? iconEndMaterialStyle : materialStyle }))] }))] })));
|
|
1168
1171
|
}
|
|
1169
1172
|
return (jsxs("button", Object.assign({ ref: (node) => {
|
|
1170
1173
|
buttonRef.current = node;
|
|
@@ -1178,12 +1181,13 @@ const DButton = forwardRef((props, ref) => {
|
|
|
1178
1181
|
// eslint-disable-next-line react/button-has-type
|
|
1179
1182
|
type: type, className: classNames(classes, className), style: Object.assign(Object.assign({}, style), (loading && buttonWidth
|
|
1180
1183
|
? { minWidth: `${buttonWidth}px` }
|
|
1181
|
-
: undefined)), disabled: isDisabled, "aria-label": ariaLabel, "aria-busy": loading, "aria-disabled": isDisabled, onClick: handleClick }, dataAttributes, rest, { children: [loading && (jsxs("span", { className: "btn-loading", children: [jsx("span", { className: "spinner-border spinner-border-sm", "aria-hidden": "true" }), loadingText && jsx("span", { role: "status", children: loadingText })] })), !loading && (jsxs(Fragment, { children: [iconStart && (jsx(DIcon, { icon: iconStart, familyClass: iconStartFamilyClass, familyPrefix: iconStartFamilyPrefix, materialStyle: iconStartMaterialStyle })), content, iconEnd && (jsx(DIcon, { icon: iconEnd, familyClass: iconEndFamilyClass, familyPrefix: iconEndFamilyPrefix, materialStyle: iconEndMaterialStyle }))] }))] })));
|
|
1184
|
+
: undefined)), disabled: isDisabled, "aria-label": ariaLabel, "aria-busy": loading, "aria-disabled": isDisabled, onClick: handleClick }, dataAttributes, rest, { children: [loading && (jsxs("span", { className: "btn-loading", children: [jsx("span", { className: "spinner-border spinner-border-sm", "aria-hidden": "true" }), loadingText && jsx("span", { role: "status", children: loadingText })] })), !loading && (jsxs(Fragment, { children: [iconStart && (jsx(DIcon, { icon: iconStart, familyClass: iconStartFamilyClass !== null && iconStartFamilyClass !== void 0 ? iconStartFamilyClass : familyClass, familyPrefix: iconStartFamilyPrefix !== null && iconStartFamilyPrefix !== void 0 ? iconStartFamilyPrefix : familyPrefix, materialStyle: iconStartMaterialStyle !== null && iconStartMaterialStyle !== void 0 ? iconStartMaterialStyle : materialStyle })), content, iconEnd && (jsx(DIcon, { icon: iconEnd, familyClass: iconEndFamilyClass !== null && iconEndFamilyClass !== void 0 ? iconEndFamilyClass : familyClass, familyPrefix: iconEndFamilyPrefix !== null && iconEndFamilyPrefix !== void 0 ? iconEndFamilyPrefix : familyPrefix, materialStyle: iconEndMaterialStyle !== null && iconEndMaterialStyle !== void 0 ? iconEndMaterialStyle : materialStyle }))] }))] })));
|
|
1182
1185
|
});
|
|
1183
1186
|
DButton.displayName = 'DButton';
|
|
1184
1187
|
|
|
1185
1188
|
function DButtonIcon(_a) {
|
|
1186
1189
|
var { id, icon, size, className, variant, state, loadingAriaLabel, iconMaterialStyle, disabled = false, color = 'primary', loading = false, href, target, rel, stopPropagationEnabled = true, style, iconFamilyClass, iconFamilyPrefix, dataAttributes, onClick, 'aria-label': ariaLabelProp } = _a, rest = __rest(_a, ["id", "icon", "size", "className", "variant", "state", "loadingAriaLabel", "iconMaterialStyle", "disabled", "color", "loading", "href", "target", "rel", "stopPropagationEnabled", "style", "iconFamilyClass", "iconFamilyPrefix", "dataAttributes", "onClick", 'aria-label']);
|
|
1190
|
+
const { icon: { familyClass, familyPrefix, materialStyle, }, } = useDContext();
|
|
1187
1191
|
const generateClasses = useMemo(() => {
|
|
1188
1192
|
const variantClass = !variant || variant === 'solid'
|
|
1189
1193
|
? `btn-${color}`
|
|
@@ -1207,11 +1211,11 @@ function DButtonIcon(_a) {
|
|
|
1207
1211
|
if (href) {
|
|
1208
1212
|
return (jsx("a", Object.assign({ id: id, href: href, target: target, rel: rel, className: classNames(generateClasses, className), style: style, onClick: clickHandler, "aria-label": ariaLabel, "aria-disabled": isDisabled }, dataAttributes, { children: loading
|
|
1209
1213
|
? (jsx("span", { className: "spinner-border spinner-border-sm", role: "status", "aria-hidden": "true", children: jsx("span", { className: "visually-hidden", children: "Loading..." }) }))
|
|
1210
|
-
: (jsx(DIcon, { icon: icon, familyClass: iconFamilyClass, familyPrefix: iconFamilyPrefix, materialStyle: iconMaterialStyle })) })));
|
|
1214
|
+
: (jsx(DIcon, { icon: icon, familyClass: iconFamilyClass !== null && iconFamilyClass !== void 0 ? iconFamilyClass : familyClass, familyPrefix: iconFamilyPrefix !== null && iconFamilyPrefix !== void 0 ? iconFamilyPrefix : familyPrefix, materialStyle: iconMaterialStyle !== null && iconMaterialStyle !== void 0 ? iconMaterialStyle : materialStyle })) })));
|
|
1211
1215
|
}
|
|
1212
1216
|
return (jsx("button", Object.assign({ className: classNames(generateClasses, className), style: style, disabled: state === 'disabled' || loading, onClick: clickHandler, "aria-label": ariaLabel }, dataAttributes, rest, { children: loading
|
|
1213
1217
|
? (jsx("span", { className: "spinner-border spinner-border-sm", role: "status", "aria-hidden": "true", children: jsx("span", { className: "visually-hidden", children: "Loading..." }) }))
|
|
1214
|
-
: (jsx(DIcon, { icon: icon, familyClass: iconFamilyClass, familyPrefix: iconFamilyPrefix, materialStyle: iconMaterialStyle })) })));
|
|
1218
|
+
: (jsx(DIcon, { icon: icon, familyClass: iconFamilyClass !== null && iconFamilyClass !== void 0 ? iconFamilyClass : familyClass, familyPrefix: iconFamilyPrefix !== null && iconFamilyPrefix !== void 0 ? iconFamilyPrefix : familyPrefix, materialStyle: iconMaterialStyle !== null && iconMaterialStyle !== void 0 ? iconMaterialStyle : materialStyle })) })));
|
|
1215
1219
|
}
|
|
1216
1220
|
|
|
1217
1221
|
function DCardHeader({ className, style, children, }) {
|
|
@@ -1274,12 +1278,12 @@ function DChip({ color = 'primary', text, icon, iconFamilyClass, iconFamilyPrefi
|
|
|
1274
1278
|
'd-chip': true,
|
|
1275
1279
|
[`d-chip-${color}`]: !!color,
|
|
1276
1280
|
}), [color]);
|
|
1277
|
-
const { iconMap: { xLg, }, } = useDContext();
|
|
1281
|
+
const { icon: { familyClass, familyPrefix, materialStyle, }, iconMap: { xLg, }, } = useDContext();
|
|
1278
1282
|
const iconClose = useMemo(() => iconCloseProp || xLg, [iconCloseProp, xLg]);
|
|
1279
|
-
return (jsxs("span", Object.assign({ className: classNames(generateClasses, className), style: style }, dataAttributes, { children: [icon && (jsx("div", { className: "d-chip-icon-container", children: jsx(DIcon, { icon: icon, familyClass: iconFamilyClass, familyPrefix: iconFamilyPrefix, materialStyle: iconMaterialStyle }) })), jsx("span", { children: text }), showClose && (jsx("button", { type: "button", className: "d-chip-icon-container", onClick: onClose, "aria-label": closeAriaLabel, children: jsx(DIcon, { icon: iconClose, familyClass: iconCloseFamilyClass, familyPrefix: iconCloseFamilyPrefix, materialStyle: iconCloseMaterialStyle }) }))] })));
|
|
1283
|
+
return (jsxs("span", Object.assign({ className: classNames(generateClasses, className), style: style }, dataAttributes, { children: [icon && (jsx("div", { className: "d-chip-icon-container", children: jsx(DIcon, { icon: icon, familyClass: iconFamilyClass !== null && iconFamilyClass !== void 0 ? iconFamilyClass : familyClass, familyPrefix: iconFamilyPrefix !== null && iconFamilyPrefix !== void 0 ? iconFamilyPrefix : familyPrefix, materialStyle: iconMaterialStyle !== null && iconMaterialStyle !== void 0 ? iconMaterialStyle : materialStyle }) })), jsx("span", { children: text }), showClose && (jsx("button", { type: "button", className: "d-chip-icon-container", onClick: onClose, "aria-label": closeAriaLabel, children: jsx(DIcon, { icon: iconClose, familyClass: iconCloseFamilyClass !== null && iconCloseFamilyClass !== void 0 ? iconCloseFamilyClass : familyClass, familyPrefix: iconCloseFamilyPrefix !== null && iconCloseFamilyPrefix !== void 0 ? iconCloseFamilyPrefix : familyPrefix, materialStyle: iconCloseMaterialStyle !== null && iconCloseMaterialStyle !== void 0 ? iconCloseMaterialStyle : materialStyle }) }))] })));
|
|
1280
1284
|
}
|
|
1281
1285
|
|
|
1282
|
-
function DCollapse({ id, className, style, Component, defaultCollapsed = true, onChange, children, iconOpen: iconOpenProp, iconClose: iconCloseProp, iconFamilyClass, iconFamilyPrefix, iconMaterialStyle
|
|
1286
|
+
function DCollapse({ id, className, style, Component, defaultCollapsed = true, onChange, children, iconOpen: iconOpenProp, iconClose: iconCloseProp, iconFamilyClass, iconFamilyPrefix, iconMaterialStyle, dataAttributes, }) {
|
|
1283
1287
|
const [collapsed, setCollapsed] = useState(defaultCollapsed);
|
|
1284
1288
|
const onChangeCollapse = () => {
|
|
1285
1289
|
setCollapsed((prev) => {
|
|
@@ -1293,10 +1297,10 @@ function DCollapse({ id, className, style, Component, defaultCollapsed = true, o
|
|
|
1293
1297
|
useEffect(() => {
|
|
1294
1298
|
setCollapsed(defaultCollapsed);
|
|
1295
1299
|
}, [defaultCollapsed]);
|
|
1296
|
-
const { iconMap: { chevronDown, chevronUp, }, } = useDContext();
|
|
1300
|
+
const { icon: { familyClass, familyPrefix, materialStyle, }, iconMap: { chevronDown, chevronUp, }, } = useDContext();
|
|
1297
1301
|
const iconOpen = useMemo(() => iconOpenProp || chevronDown, [chevronDown, iconOpenProp]);
|
|
1298
1302
|
const iconClose = useMemo(() => iconCloseProp || chevronUp, [chevronUp, iconCloseProp]);
|
|
1299
|
-
return (jsxs("div", Object.assign({ id: id, className: classNames('collapse-container', className), style: style }, dataAttributes, { children: [jsxs("button", { className: "collapse-button", type: "button", onClick: onChangeCollapse, children: [jsx("div", { className: "flex-grow-1", children: Component }), jsx(DIcon, { color: "primary", size: "1.25rem", icon: collapsed ? iconOpen : iconClose, familyClass: iconFamilyClass, familyPrefix: iconFamilyPrefix, materialStyle: iconMaterialStyle })] }), jsx("div", { className: classNames('collapse-body-wrapper', {
|
|
1303
|
+
return (jsxs("div", Object.assign({ id: id, className: classNames('collapse-container', className), style: style }, dataAttributes, { children: [jsxs("button", { className: "collapse-button", type: "button", onClick: onChangeCollapse, children: [jsx("div", { className: "flex-grow-1", children: Component }), jsx(DIcon, { className: "collapse-icon", color: "primary", size: "1.25rem", icon: collapsed ? iconOpen : iconClose, familyClass: iconFamilyClass !== null && iconFamilyClass !== void 0 ? iconFamilyClass : familyClass, familyPrefix: iconFamilyPrefix !== null && iconFamilyPrefix !== void 0 ? iconFamilyPrefix : familyPrefix, materialStyle: iconMaterialStyle !== null && iconMaterialStyle !== void 0 ? iconMaterialStyle : materialStyle })] }), jsx("div", { className: classNames('collapse-body-wrapper', {
|
|
1300
1304
|
show: !collapsed,
|
|
1301
1305
|
}), children: jsx("div", { className: "collapse-body", children: children }) })] })));
|
|
1302
1306
|
}
|
|
@@ -1482,9 +1486,9 @@ function DDatePickerHeaderSelector({ date, changeYear, changeMonth, decreaseMont
|
|
|
1482
1486
|
return (jsxs("div", { className: classNames('react-datepicker__header-selector react-datepicker__header-year-selector', className), style: style, children: [jsx(DButtonIcon, { icon: iconPrev || chevronLeft, size: iconSize, variant: "link", onClick: decreaseYear, disabled: prevYearButtonDisabled, "aria-label": prevYearAriaLabel, className: "header-button" }), jsx("p", { children: `${startYear} - ${endYear}` }), jsx(DButtonIcon, { icon: iconNext || chevronRight, size: iconSize, variant: "link", onClick: increaseYear, disabled: nextYearButtonDisabled, "aria-label": nextYearAriaLabel, className: "header-button" })] }));
|
|
1483
1487
|
}
|
|
1484
1488
|
if (pickerType === PickerType.Quarter || pickerType === PickerType.Month) {
|
|
1485
|
-
return (jsxs("div", { className: classNames(`react-datepicker__header-selector react-datepicker__header-${pickerType}-selector`, className), style: style, children: [jsx(DButtonIcon, { icon: iconPrev || chevronLeft, size: iconSize, variant: "link", onClick: decreaseYear, disabled: prevMonthButtonDisabled, "aria-label": prevMonthAriaLabel, className: "header-button", style: { visibility: customHeaderCount === 0 ? 'visible' : 'hidden' } }), jsx("div", { className: "
|
|
1489
|
+
return (jsxs("div", { className: classNames(`react-datepicker__header-selector react-datepicker__header-${pickerType}-selector`, className), style: style, children: [jsx(DButtonIcon, { icon: iconPrev || chevronLeft, size: iconSize, variant: "link", onClick: decreaseYear, disabled: prevMonthButtonDisabled, "aria-label": prevMonthAriaLabel, className: "header-button", style: { visibility: customHeaderCount === 0 ? 'visible' : 'hidden' } }), jsx("div", { className: "react-datepicker__header-year-selector", children: showHeaderSelectors ? (jsx(DSelect$1, { options: years, value: defaultYear, defaultValue: defaultYear, onChange: (year) => changeYear(Number(year === null || year === void 0 ? void 0 : year.value)), searchable: false })) : (jsx("p", { children: defaultYear === null || defaultYear === void 0 ? void 0 : defaultYear.label })) }), jsx(DButtonIcon, { icon: iconNext || chevronRight, size: iconSize, variant: "link", onClick: increaseYear, disabled: nextMonthButtonDisabled, "aria-label": nextMonthAriaLabel, className: "header-button", style: { visibility: customHeaderCount === monthsShown - 1 ? 'visible' : 'hidden' } })] }));
|
|
1486
1490
|
}
|
|
1487
|
-
return (jsxs(Fragment, { children: [jsxs("div", { className: "datepicker-top-header", children: [showHeaderSelectors && (jsx(DSelect$1, { options: years, value: defaultYear, defaultValue: defaultYear, onChange: (year) => changeYear(Number(year === null || year === void 0 ? void 0 : year.value)), searchable: false, className: "custom-year-selector" })), jsx("h4", { className: "
|
|
1491
|
+
return (jsxs(Fragment, { children: [jsxs("div", { className: "datepicker-top-header", children: [showHeaderSelectors && (jsx(DSelect$1, { options: years, value: defaultYear, defaultValue: defaultYear, onChange: (year) => changeYear(Number(year === null || year === void 0 ? void 0 : year.value)), searchable: false, className: "custom-year-selector" })), jsx("h4", { className: "datepicker-top-header-title", children: format(monthDate, formatHeaderDate, { locale }) })] }), jsxs("div", { className: classNames('react-datepicker__header-selector react-datepicker__header-day-selector', className), style: style, children: [jsx(DButtonIcon, { icon: iconPrev || chevronLeft, size: iconSize, variant: "link", onClick: decreaseMonth, disabled: prevMonthButtonDisabled, "aria-label": prevMonthAriaLabel, className: "header-button", style: { visibility: customHeaderCount === 0 ? 'visible' : 'hidden' } }), showHeaderSelectors ? (jsx(DSelect$1, { options: months, value: defaultMonth, defaultValue: defaultMonth, onChange: (month) => changeMonth((month === null || month === void 0 ? void 0 : month.value) || 0), searchable: false, className: "custom-month-selector" })) : (jsx("p", { children: `${defaultMonth.label} ${defaultYear === null || defaultYear === void 0 ? void 0 : defaultYear.label}` })), jsx(DButtonIcon, { icon: iconNext || chevronRight, size: iconSize, variant: "link", onClick: increaseMonth, disabled: nextMonthButtonDisabled, "aria-label": nextMonthAriaLabel, className: "header-button", style: { visibility: customHeaderCount === monthsShown - 1 ? 'visible' : 'hidden' } })] })] }));
|
|
1488
1492
|
}
|
|
1489
1493
|
|
|
1490
1494
|
function DDatePicker(_a) {
|
|
@@ -1619,11 +1623,24 @@ function formatValue(value, currencyOptions) {
|
|
|
1619
1623
|
}
|
|
1620
1624
|
return currency(value, Object.assign(Object.assign({}, currencyOptions), { symbol: '' })).format();
|
|
1621
1625
|
}
|
|
1622
|
-
function useInputCurrency(currencyOptions, value, onFocus, onChange, onBlur, ref) {
|
|
1626
|
+
function useInputCurrency(currencyOptions, value, onFocus, onChange, onBlur, ref, minValue, maxValue) {
|
|
1623
1627
|
const inputRef = useProvidedRefOrCreate(ref);
|
|
1628
|
+
const clampValue = useCallback((newValue) => {
|
|
1629
|
+
if (newValue === undefined) {
|
|
1630
|
+
return newValue;
|
|
1631
|
+
}
|
|
1632
|
+
let clampedValue = newValue;
|
|
1633
|
+
if (minValue !== undefined) {
|
|
1634
|
+
clampedValue = Math.max(clampedValue, minValue);
|
|
1635
|
+
}
|
|
1636
|
+
if (maxValue !== undefined) {
|
|
1637
|
+
clampedValue = Math.min(clampedValue, maxValue);
|
|
1638
|
+
}
|
|
1639
|
+
return clampedValue;
|
|
1640
|
+
}, [minValue, maxValue]);
|
|
1624
1641
|
const [innerType, setInnerType] = useState('text');
|
|
1625
|
-
const [innerNumber, setInnerNumber] = useState(value);
|
|
1626
|
-
const [innerString, setInnerString] = useState(formatValue(value, currencyOptions));
|
|
1642
|
+
const [innerNumber, setInnerNumber] = useState(clampValue(value));
|
|
1643
|
+
const [innerString, setInnerString] = useState(formatValue(clampValue(value), currencyOptions));
|
|
1627
1644
|
const handleOnFocus = useCallback((event) => {
|
|
1628
1645
|
event.stopPropagation();
|
|
1629
1646
|
setInnerType('number');
|
|
@@ -1632,15 +1649,14 @@ function useInputCurrency(currencyOptions, value, onFocus, onChange, onBlur, ref
|
|
|
1632
1649
|
const handleOnBlur = useCallback((event) => {
|
|
1633
1650
|
event.stopPropagation();
|
|
1634
1651
|
setInnerType('text');
|
|
1652
|
+
const clampedNumber = clampValue(innerNumber);
|
|
1653
|
+
if (clampedNumber !== innerNumber) {
|
|
1654
|
+
setInnerNumber(clampedNumber);
|
|
1655
|
+
setInnerString(formatValue(clampedNumber, currencyOptions));
|
|
1656
|
+
onChange === null || onChange === void 0 ? void 0 : onChange(clampedNumber);
|
|
1657
|
+
}
|
|
1635
1658
|
onBlur === null || onBlur === void 0 ? void 0 : onBlur(event);
|
|
1636
|
-
}, [onBlur]);
|
|
1637
|
-
const generateStyleVariables = useMemo(() => ({
|
|
1638
|
-
[`--${PREFIX_BS}input-currency-component-symbol-color`]: `var(--${PREFIX_BS}secondary)`,
|
|
1639
|
-
[`--${PREFIX_BS}input-currency-symbol-color`]: `var(--${PREFIX_BS}input-currency-component-symbol-color)`,
|
|
1640
|
-
}), []);
|
|
1641
|
-
const generateSymbolStyleVariables = useMemo(() => ({
|
|
1642
|
-
color: `var(--${PREFIX_BS}input-currency-symbol-color)`,
|
|
1643
|
-
}), []);
|
|
1659
|
+
}, [onBlur, innerNumber, clampValue, currencyOptions, onChange]);
|
|
1644
1660
|
const handleOnChange = useCallback((newValue) => {
|
|
1645
1661
|
const newNumber = (newValue === undefined || newValue === '') ? undefined : Number(newValue);
|
|
1646
1662
|
if (newNumber !== innerNumber) {
|
|
@@ -1649,7 +1665,12 @@ function useInputCurrency(currencyOptions, value, onFocus, onChange, onBlur, ref
|
|
|
1649
1665
|
onChange === null || onChange === void 0 ? void 0 : onChange(newNumber);
|
|
1650
1666
|
}
|
|
1651
1667
|
}, [currencyOptions, onChange, innerNumber]);
|
|
1668
|
+
const isMountedRef = useRef(false);
|
|
1652
1669
|
useEffect(() => {
|
|
1670
|
+
if (!isMountedRef.current) {
|
|
1671
|
+
isMountedRef.current = true;
|
|
1672
|
+
return;
|
|
1673
|
+
}
|
|
1653
1674
|
if (value !== innerNumber) {
|
|
1654
1675
|
setInnerNumber(value);
|
|
1655
1676
|
setInnerString(formatValue(value, currencyOptions));
|
|
@@ -1663,8 +1684,6 @@ function useInputCurrency(currencyOptions, value, onFocus, onChange, onBlur, ref
|
|
|
1663
1684
|
handleOnFocus,
|
|
1664
1685
|
handleOnChange,
|
|
1665
1686
|
handleOnBlur,
|
|
1666
|
-
generateStyleVariables,
|
|
1667
|
-
generateSymbolStyleVariables,
|
|
1668
1687
|
};
|
|
1669
1688
|
}
|
|
1670
1689
|
|
|
@@ -1769,6 +1788,149 @@ function useConfirmModal(config) {
|
|
|
1769
1788
|
return { open };
|
|
1770
1789
|
}
|
|
1771
1790
|
|
|
1791
|
+
/**
|
|
1792
|
+
* Generic seconds-based countdown hook.
|
|
1793
|
+
*
|
|
1794
|
+
* Starts counting down from `seconds` to `0` and exposes `restartCountdown`
|
|
1795
|
+
* to reset and restart the timer (e.g. for "resend code in Xs" patterns,
|
|
1796
|
+
* session-expiry banners, or any other cooldown/throttle UI).
|
|
1797
|
+
*
|
|
1798
|
+
* @example
|
|
1799
|
+
* const { secondsLeft, restartCountdown } = useCountdown(30);
|
|
1800
|
+
*/
|
|
1801
|
+
function useCountdown(seconds) {
|
|
1802
|
+
const [secondsLeft, setSecondsLeft] = useState(seconds);
|
|
1803
|
+
const [isActive, setIsActive] = useState(true);
|
|
1804
|
+
const resetCountdown = useCallback((newSeconds = seconds) => {
|
|
1805
|
+
setIsActive(false);
|
|
1806
|
+
setSecondsLeft(newSeconds);
|
|
1807
|
+
}, [seconds]);
|
|
1808
|
+
const restartCountdown = useCallback(() => {
|
|
1809
|
+
resetCountdown(seconds);
|
|
1810
|
+
setIsActive(true);
|
|
1811
|
+
}, [resetCountdown, seconds]);
|
|
1812
|
+
useEffect(() => {
|
|
1813
|
+
if (!isActive) {
|
|
1814
|
+
return () => { };
|
|
1815
|
+
}
|
|
1816
|
+
const interval = setInterval(() => {
|
|
1817
|
+
setSecondsLeft((prevSeconds) => {
|
|
1818
|
+
const newSeconds = prevSeconds - 1;
|
|
1819
|
+
if (newSeconds <= 0) {
|
|
1820
|
+
clearInterval(interval);
|
|
1821
|
+
setIsActive(false);
|
|
1822
|
+
return 0;
|
|
1823
|
+
}
|
|
1824
|
+
return newSeconds;
|
|
1825
|
+
});
|
|
1826
|
+
}, 1000);
|
|
1827
|
+
return () => clearInterval(interval);
|
|
1828
|
+
}, [isActive]);
|
|
1829
|
+
return { secondsLeft, restartCountdown };
|
|
1830
|
+
}
|
|
1831
|
+
|
|
1832
|
+
/**
|
|
1833
|
+
* Headless hook exposing the same OTP logic used internally by `DOtp`
|
|
1834
|
+
* (code state, length + correctness validation, submit action and resend
|
|
1835
|
+
* countdown), without any bundled markup/styles.
|
|
1836
|
+
*
|
|
1837
|
+
* Use this when the default `DOtp` component doesn't match your design and
|
|
1838
|
+
* you need to build a fully custom UI while reusing the same behavior.
|
|
1839
|
+
*
|
|
1840
|
+
* Internally composes `useCountdown` for the resend timer and re-exposes
|
|
1841
|
+
* `secondsLeft`/`restartCountdown`, so there is no need to call
|
|
1842
|
+
* `useCountdown` separately.
|
|
1843
|
+
*
|
|
1844
|
+
* `invalid` becomes `true` both when the OTP is shorter than `otpSize` and
|
|
1845
|
+
* when `action` throws/rejects (e.g. the backend rejected the entered code
|
|
1846
|
+
* as incorrect). In the latter case, the thrown value is exposed as `error`
|
|
1847
|
+
* so custom UIs can render an appropriate message (e.g. "Invalid code" vs.
|
|
1848
|
+
* "Enter all digits"). `invalid`/`error` are cleared automatically as soon
|
|
1849
|
+
* as the user edits the code via `setOtp`.
|
|
1850
|
+
*
|
|
1851
|
+
* @example
|
|
1852
|
+
* function CustomOtp() {
|
|
1853
|
+
* const {
|
|
1854
|
+
* otp,
|
|
1855
|
+
* setOtp,
|
|
1856
|
+
* invalid,
|
|
1857
|
+
* error,
|
|
1858
|
+
* submit,
|
|
1859
|
+
* isLoading,
|
|
1860
|
+
* secondsLeft,
|
|
1861
|
+
* restartCountdown,
|
|
1862
|
+
* } = useOtp({ action: async () => verifyOtp(otp), otpSize: 6, seconds: 15 });
|
|
1863
|
+
*
|
|
1864
|
+
* return (
|
|
1865
|
+
* <>
|
|
1866
|
+
* <MyCustomPinInput value={otp} onChange={setOtp} invalid={invalid} />
|
|
1867
|
+
* {invalid && <span>{error ? 'Invalid code' : 'Enter all digits'}</span>}
|
|
1868
|
+
* <button disabled={isLoading} onClick={() => { submit().catch(() => {}); }}>
|
|
1869
|
+
* {isLoading ? 'Submitting...' : 'Submit'}
|
|
1870
|
+
* </button>
|
|
1871
|
+
* <button disabled={secondsLeft > 0} onClick={restartCountdown}>
|
|
1872
|
+
* Resend {secondsLeft > 0 ? `(${secondsLeft}s)` : ''}
|
|
1873
|
+
* </button>
|
|
1874
|
+
* </>
|
|
1875
|
+
* );
|
|
1876
|
+
* }
|
|
1877
|
+
*/
|
|
1878
|
+
function useOtp({ action, otpSize = 6, seconds = 15, }) {
|
|
1879
|
+
const [otp, setOtpValue] = useState('');
|
|
1880
|
+
const [invalid, setInvalid] = useState(false);
|
|
1881
|
+
const [error, setError] = useState(null);
|
|
1882
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
1883
|
+
const { secondsLeft, restartCountdown } = useCountdown(seconds);
|
|
1884
|
+
const setOtp = useCallback((value) => {
|
|
1885
|
+
setOtpValue((prevOtp) => {
|
|
1886
|
+
// Guard against no-op calls (e.g. DInputPin re-notifying the same
|
|
1887
|
+
// value when its onChange reference changes) so we don't wipe out
|
|
1888
|
+
// an `invalid`/`error` state that was just set by submit().
|
|
1889
|
+
if (prevOtp === value) {
|
|
1890
|
+
return prevOtp;
|
|
1891
|
+
}
|
|
1892
|
+
setInvalid(false);
|
|
1893
|
+
setError(null);
|
|
1894
|
+
return value;
|
|
1895
|
+
});
|
|
1896
|
+
}, []);
|
|
1897
|
+
const submit = useCallback(async () => {
|
|
1898
|
+
if (otp.length < otpSize) {
|
|
1899
|
+
setInvalid(true);
|
|
1900
|
+
setError(null);
|
|
1901
|
+
return;
|
|
1902
|
+
}
|
|
1903
|
+
setIsLoading(true);
|
|
1904
|
+
try {
|
|
1905
|
+
await action();
|
|
1906
|
+
setInvalid(false);
|
|
1907
|
+
setError(null);
|
|
1908
|
+
}
|
|
1909
|
+
catch (err) {
|
|
1910
|
+
setInvalid(true);
|
|
1911
|
+
setError(err);
|
|
1912
|
+
throw err;
|
|
1913
|
+
}
|
|
1914
|
+
finally {
|
|
1915
|
+
setIsLoading(false);
|
|
1916
|
+
}
|
|
1917
|
+
}, [
|
|
1918
|
+
otp.length,
|
|
1919
|
+
action,
|
|
1920
|
+
otpSize,
|
|
1921
|
+
]);
|
|
1922
|
+
return {
|
|
1923
|
+
otp,
|
|
1924
|
+
setOtp,
|
|
1925
|
+
invalid,
|
|
1926
|
+
error,
|
|
1927
|
+
submit,
|
|
1928
|
+
isLoading,
|
|
1929
|
+
secondsLeft,
|
|
1930
|
+
restartCountdown,
|
|
1931
|
+
};
|
|
1932
|
+
}
|
|
1933
|
+
|
|
1772
1934
|
function DInputCounter(_a, ref) {
|
|
1773
1935
|
var { minValue, maxValue, value = minValue, invalid, iconStart: iconStartProp, iconEnd: iconEndProp, iconStartAriaLabel = 'decrease action', iconEndAriaLabel = 'increase action', style, onChange } = _a, props = __rest(_a, ["minValue", "maxValue", "value", "invalid", "iconStart", "iconEnd", "iconStartAriaLabel", "iconEndAriaLabel", "style", "onChange"]);
|
|
1774
1936
|
const { handleOnWheel, } = useDisableInputWheel(ref);
|
|
@@ -1811,8 +1973,8 @@ function DInputCurrency(_a, ref) {
|
|
|
1811
1973
|
var { value, minValue, maxValue, currencyCode, onFocus, onBlur, onChange } = _a, props = __rest(_a, ["value", "minValue", "maxValue", "currencyCode", "onFocus", "onBlur", "onChange"]);
|
|
1812
1974
|
const { currency: currencyOptions } = useDContext();
|
|
1813
1975
|
const { handleOnWheel, } = useDisableInputWheel(ref);
|
|
1814
|
-
const { inputRef, innerValue, innerType, handleOnFocus, handleOnChange, handleOnBlur,
|
|
1815
|
-
return (jsx(ForwardedDInput, Object.assign({ ref: inputRef, value: innerValue, onChange: handleOnChange,
|
|
1976
|
+
const { inputRef, innerValue, innerType, handleOnFocus, handleOnChange, handleOnBlur, } = useInputCurrency(currencyOptions, value, onFocus, onChange, onBlur, ref, minValue, maxValue);
|
|
1977
|
+
return (jsx(ForwardedDInput, Object.assign({ ref: inputRef, value: innerValue, onChange: handleOnChange, inputMode: "decimal", type: innerType, onFocus: handleOnFocus, onBlur: handleOnBlur, onWheel: handleOnWheel, inputStart: (jsx("span", { slot: "input-start", className: "d-input-currency-symbol", children: currencyCode || currencyOptions.symbol })) }, props)));
|
|
1816
1978
|
}
|
|
1817
1979
|
const ForwardedDInputCurrency = forwardRef(DInputCurrency);
|
|
1818
1980
|
ForwardedDInputCurrency.displayName = 'DInputCurrency';
|
|
@@ -1834,26 +1996,25 @@ ForwardedDInputPassword.displayName = 'DInputPassword';
|
|
|
1834
1996
|
|
|
1835
1997
|
function PasswordCheckItem({ password, regex, text, }) {
|
|
1836
1998
|
const isValid = regex.test(password);
|
|
1837
|
-
return (jsxs("li", { className:
|
|
1999
|
+
return (jsxs("li", { className: `d-password-check-item${isValid ? ' is-valid' : ''}`, children: [jsx(DIcon, { className: "d-password-check-item-icon", icon: isValid ? 'CircleCheck' : 'Circle', size: "16px" }), jsx("span", { children: text })] }));
|
|
1838
2000
|
}
|
|
1839
2001
|
|
|
1840
|
-
const
|
|
2002
|
+
const getStrengthModifier = (strength, total) => {
|
|
1841
2003
|
const percentage = total > 0 ? strength / total : 0;
|
|
1842
2004
|
if (percentage === 0)
|
|
1843
|
-
return '
|
|
2005
|
+
return 'is-empty';
|
|
1844
2006
|
if (percentage <= 0.25)
|
|
1845
|
-
return '
|
|
2007
|
+
return 'is-weak';
|
|
1846
2008
|
if (percentage <= 0.5)
|
|
1847
|
-
return '
|
|
2009
|
+
return 'is-fair';
|
|
1848
2010
|
if (percentage <= 0.75)
|
|
1849
|
-
return '
|
|
1850
|
-
return '
|
|
2011
|
+
return 'is-good';
|
|
2012
|
+
return 'is-strong';
|
|
1851
2013
|
};
|
|
1852
2014
|
function PasswordStrengthBar({ strength, total }) {
|
|
1853
2015
|
const percentage = total > 0 ? (strength / total) * 100 : 0;
|
|
1854
|
-
return (jsx("div", { className: "
|
|
2016
|
+
return (jsx("div", { className: "d-password-strength-bar", children: jsx("div", { className: `d-password-strength-bar-fill ${getStrengthModifier(strength, total)}`, style: {
|
|
1855
2017
|
width: `${percentage}%`,
|
|
1856
|
-
transition: 'width 0.3s ease-in-out',
|
|
1857
2018
|
} }) }));
|
|
1858
2019
|
}
|
|
1859
2020
|
|
|
@@ -1889,7 +2050,7 @@ function PasswordChecksList({ password, validationMessages, enabledChecks, }) {
|
|
|
1889
2050
|
const passwordChecks = allChecks.filter((check) => enabledChecks.includes(check.key));
|
|
1890
2051
|
const passed = passwordChecks.filter((r) => r.regex.test(password)).length;
|
|
1891
2052
|
const total = passwordChecks.length;
|
|
1892
|
-
return (jsxs("div", { className: "
|
|
2053
|
+
return (jsxs("div", { className: "d-password-strength-meter", children: [jsx(PasswordStrengthBar, { strength: passed, total: total }), jsx("ul", { className: "d-password-check-list", children: passwordChecks.map(({ key, regex, text }) => (jsx(PasswordCheckItem, { password: password, regex: regex, text: text }, key))) })] }));
|
|
1893
2054
|
}
|
|
1894
2055
|
|
|
1895
2056
|
const DEFAULT_VALIDATION_MESSAGES = {
|
|
@@ -1930,9 +2091,9 @@ function DInputCheck(_a) {
|
|
|
1930
2091
|
]);
|
|
1931
2092
|
useEffect(() => {
|
|
1932
2093
|
if (innerRef.current) {
|
|
1933
|
-
innerRef.current.indeterminate = Boolean(indeterminate);
|
|
2094
|
+
innerRef.current.indeterminate = type === 'checkbox' && Boolean(indeterminate);
|
|
1934
2095
|
}
|
|
1935
|
-
}, [indeterminate]);
|
|
2096
|
+
}, [indeterminate, type]);
|
|
1936
2097
|
useEffect(() => {
|
|
1937
2098
|
if (innerRef.current) {
|
|
1938
2099
|
innerRef.current.checked = checked;
|
|
@@ -2125,10 +2286,18 @@ function DInputSelect({ id: idProp, name, label = '', className, style, options
|
|
|
2125
2286
|
}), children: [iconStart && (jsx("button", { type: "button", className: "input-group-text", id: `${id}Start`, onClick: iconStartClickHandler, disabled: disabled || loading, "aria-label": iconStartAriaLabel, children: iconStart && (jsx(DIcon, { icon: iconStart, familyClass: iconStartFamilyClass, familyPrefix: iconStartFamilyPrefix })) })), dynamicComponent, iconEnd && !loading && (jsx("button", { type: "button", className: "input-group-text", id: `${id}End`, onClick: iconEndClickHandler, disabled: disabled || loading, "aria-label": iconEndAriaLabel, children: iconEnd && (jsx(DIcon, { icon: iconEnd, familyClass: iconEndFamilyClass, familyPrefix: iconEndFamilyPrefix })) })), loading && (jsx("div", { className: "input-group-text form-control-icon loading", children: jsx("span", { className: "spinner-border spinner-border-sm", role: "status", "aria-hidden": "true", children: jsx("span", { className: "visually-hidden", children: "Loading..." }) }) }))] }), hint && (jsx("div", { className: "form-text", id: `${id}Hint`, children: hint }))] })));
|
|
2126
2287
|
}
|
|
2127
2288
|
|
|
2128
|
-
function DInputSwitch({ id: idProp, label, ariaLabel, name, checked, disabled, invalid = false, valid = false, readonly, className, style, dataAttributes, inputClassName, onChange, }) {
|
|
2289
|
+
function DInputSwitch({ id: idProp, label, ariaLabel, name, checked, disabled, invalid = false, valid = false, hint, readonly, className, style, dataAttributes, inputClassName, onChange, }) {
|
|
2129
2290
|
const innerId = useId();
|
|
2130
2291
|
const id = useMemo(() => idProp || innerId, [idProp, innerId]);
|
|
2131
2292
|
const [internalIsChecked, setInternalIsChecked] = useState(checked);
|
|
2293
|
+
const ariaDescribedby = useMemo(() => ([
|
|
2294
|
+
!!hint && `${id}Hint`,
|
|
2295
|
+
]
|
|
2296
|
+
.filter(Boolean)
|
|
2297
|
+
.join(' ')), [
|
|
2298
|
+
id,
|
|
2299
|
+
hint,
|
|
2300
|
+
]);
|
|
2132
2301
|
useEffect(() => {
|
|
2133
2302
|
setInternalIsChecked(checked);
|
|
2134
2303
|
}, [checked]);
|
|
@@ -2137,10 +2306,10 @@ function DInputSwitch({ id: idProp, label, ariaLabel, name, checked, disabled, i
|
|
|
2137
2306
|
setInternalIsChecked(value);
|
|
2138
2307
|
onChange === null || onChange === void 0 ? void 0 : onChange(value);
|
|
2139
2308
|
}, [onChange]);
|
|
2140
|
-
return (jsxs("div", Object.assign({ className: classNames('form-check form-switch', className) }, dataAttributes, { children: [jsx("input", { id: id, name: name, onChange: readonly ? () => false : changeHandler, className: classNames('form-check-input', {
|
|
2309
|
+
return (jsxs("div", Object.assign({ className: classNames('form-check form-switch', className) }, dataAttributes, { children: [jsx("input", Object.assign({ id: id, name: name, onChange: readonly ? () => false : changeHandler, className: classNames('form-check-input', {
|
|
2141
2310
|
'is-invalid': invalid,
|
|
2142
2311
|
'is-valid': valid,
|
|
2143
|
-
}, inputClassName), style: style, type: "checkbox", role: "switch", checked: internalIsChecked, disabled: disabled, "aria-label": ariaLabel }), label && (jsx("label", { className: "form-check-label", htmlFor: id, children: label }))] })));
|
|
2312
|
+
}, inputClassName), style: style, type: "checkbox", role: "switch", checked: internalIsChecked, disabled: disabled, "aria-label": ariaLabel }, ariaDescribedby && { 'aria-describedby': ariaDescribedby })), label && (jsx("label", { className: "form-check-label", htmlFor: id, children: label })), hint && (jsx("div", { className: "form-text", id: `${id}Hint`, children: hint }))] })));
|
|
2144
2313
|
}
|
|
2145
2314
|
|
|
2146
2315
|
function DInputRange(_a, ref) {
|
|
@@ -2181,6 +2350,7 @@ const ForwardedDInputRange = forwardRef(DInputRange);
|
|
|
2181
2350
|
ForwardedDInputRange.displayName = 'DInputRange';
|
|
2182
2351
|
|
|
2183
2352
|
function DListGroupItem({ as = 'li', action: actionProp, active, disabled, href, onClick, color, iconStart, iconStartFamilyClass, iconStartFamilyPrefix, iconStartMaterialStyle, iconEnd, iconEndFamilyClass, iconEndFamilyPrefix, iconEndMaterialStyle, children, className, style, dataAttributes, }) {
|
|
2353
|
+
const { icon: { familyClass, familyPrefix, materialStyle, }, } = useDContext();
|
|
2184
2354
|
const Tag = useMemo(() => {
|
|
2185
2355
|
if (href) {
|
|
2186
2356
|
return 'a';
|
|
@@ -2209,7 +2379,7 @@ function DListGroupItem({ as = 'li', action: actionProp, active, disabled, href,
|
|
|
2209
2379
|
}
|
|
2210
2380
|
return Object.assign(Object.assign({}, active && { 'aria-current': true }), disabled && { 'aria-disabled': true });
|
|
2211
2381
|
}, [Tag, active, disabled]);
|
|
2212
|
-
return (jsxs(Tag, Object.assign({ className: classNames(generateClasses, className), style: style }, Tag === 'a' && href && { href }, onClick && { onClick }, ariaAttributes, dataAttributes, Tag === 'button' && { type: 'button' }, { children: [iconStart && (jsx(DIcon, { icon: iconStart, familyClass: iconStartFamilyClass, familyPrefix: iconStartFamilyPrefix, materialStyle: iconStartMaterialStyle })), children, iconEnd && (jsx(DIcon, { icon: iconEnd, familyClass: iconEndFamilyClass, familyPrefix: iconEndFamilyPrefix, materialStyle: iconEndMaterialStyle, className: "ms-auto" }))] })));
|
|
2382
|
+
return (jsxs(Tag, Object.assign({ className: classNames(generateClasses, className), style: style }, Tag === 'a' && href && { href }, onClick && { onClick }, ariaAttributes, dataAttributes, Tag === 'button' && { type: 'button' }, { children: [iconStart && (jsx(DIcon, { icon: iconStart, familyClass: iconStartFamilyClass !== null && iconStartFamilyClass !== void 0 ? iconStartFamilyClass : familyClass, familyPrefix: iconStartFamilyPrefix !== null && iconStartFamilyPrefix !== void 0 ? iconStartFamilyPrefix : familyPrefix, materialStyle: iconStartMaterialStyle !== null && iconStartMaterialStyle !== void 0 ? iconStartMaterialStyle : materialStyle })), children, iconEnd && (jsx(DIcon, { icon: iconEnd, familyClass: iconEndFamilyClass !== null && iconEndFamilyClass !== void 0 ? iconEndFamilyClass : familyClass, familyPrefix: iconEndFamilyPrefix !== null && iconEndFamilyPrefix !== void 0 ? iconEndFamilyPrefix : familyPrefix, materialStyle: iconEndMaterialStyle !== null && iconEndMaterialStyle !== void 0 ? iconEndMaterialStyle : materialStyle, className: "ms-auto" }))] })));
|
|
2213
2383
|
}
|
|
2214
2384
|
|
|
2215
2385
|
function DListGroup({ as = 'ul', numbered, flush, horizontal, children, className, style, dataAttributes, }) {
|
|
@@ -2236,10 +2406,11 @@ var DListGroup$1 = Object.assign(DListGroup, {
|
|
|
2236
2406
|
Item: DListGroupItem,
|
|
2237
2407
|
});
|
|
2238
2408
|
|
|
2239
|
-
function DModalHeader({ showCloseButton, onClose, children, className, style, iconFamilyClass, iconFamilyPrefix, icon: iconProp, materialStyle
|
|
2240
|
-
|
|
2409
|
+
function DModalHeader({ showCloseButton, onClose, children, className, style, iconFamilyClass, iconFamilyPrefix, icon: iconProp, iconMaterialStyle, materialStyle: materialStyleProp, }) {
|
|
2410
|
+
var _a;
|
|
2411
|
+
const { icon: { familyClass, familyPrefix, materialStyle, }, iconMap: { xLg, }, } = useDContext();
|
|
2241
2412
|
const icon = useMemo(() => iconProp || xLg, [iconProp, xLg]);
|
|
2242
|
-
return (jsxs(Fragment, { children: [jsxs("div", { className: classNames('modal-header', className), style: style, children: [jsx("div", { children: children }), showCloseButton && (jsx("button", { type: "button", className: "d-close
|
|
2413
|
+
return (jsxs(Fragment, { children: [jsxs("div", { className: classNames('modal-header', className), style: style, children: [jsx("div", { children: children }), showCloseButton && (jsx("button", { type: "button", className: "d-close", "aria-label": "Close", onClick: onClose, children: jsx(DIcon, { icon: icon, familyClass: iconFamilyClass !== null && iconFamilyClass !== void 0 ? iconFamilyClass : familyClass, familyPrefix: iconFamilyPrefix !== null && iconFamilyPrefix !== void 0 ? iconFamilyPrefix : familyPrefix, materialStyle: (_a = iconMaterialStyle !== null && iconMaterialStyle !== void 0 ? iconMaterialStyle : materialStyleProp) !== null && _a !== void 0 ? _a : materialStyle }) }))] }), jsx("div", { className: "d-modal-separator" })] }));
|
|
2243
2414
|
}
|
|
2244
2415
|
|
|
2245
2416
|
function DModalBody({ children, className, style, }) {
|
|
@@ -2280,10 +2451,11 @@ var DModal$1 = Object.assign(DModal, {
|
|
|
2280
2451
|
Footer: DModalFooter,
|
|
2281
2452
|
});
|
|
2282
2453
|
|
|
2283
|
-
function DOffcanvasHeader({ showCloseButton, onClose, children, className, style, iconFamilyClass, iconFamilyPrefix, icon: iconProp, materialStyle
|
|
2284
|
-
|
|
2454
|
+
function DOffcanvasHeader({ showCloseButton, onClose, children, className, style, iconFamilyClass, iconFamilyPrefix, icon: iconProp, iconMaterialStyle, materialStyle: materialStyleProp, }) {
|
|
2455
|
+
var _a;
|
|
2456
|
+
const { icon: { familyClass, familyPrefix, materialStyle, }, iconMap: { xLg, }, } = useDContext();
|
|
2285
2457
|
const icon = useMemo(() => iconProp || xLg, [iconProp, xLg]);
|
|
2286
|
-
return (jsxs(Fragment, { children: [jsxs("div", { className: classNames('offcanvas-header', className), style: style, children: [jsx("div", { children: children }), showCloseButton && (jsx("button", { type: "button", className: "d-close
|
|
2458
|
+
return (jsxs(Fragment, { children: [jsxs("div", { className: classNames('offcanvas-header', className), style: style, children: [jsx("div", { children: children }), showCloseButton && (jsx("button", { type: "button", className: "d-close", "aria-label": "Close", onClick: onClose, children: jsx(DIcon, { icon: icon, familyClass: iconFamilyClass !== null && iconFamilyClass !== void 0 ? iconFamilyClass : familyClass, familyPrefix: iconFamilyPrefix !== null && iconFamilyPrefix !== void 0 ? iconFamilyPrefix : familyPrefix, materialStyle: (_a = iconMaterialStyle !== null && iconMaterialStyle !== void 0 ? iconMaterialStyle : materialStyleProp) !== null && _a !== void 0 ? _a : materialStyle }) }))] }), jsx("div", { className: "d-offcanvas-separator" })] }));
|
|
2287
2459
|
}
|
|
2288
2460
|
|
|
2289
2461
|
function DOffcanvasBody({ children, className, style, }) {
|
|
@@ -2410,7 +2582,7 @@ function DPopover({ children, renderComponent, open, setOpen, adjustContentToRen
|
|
|
2410
2582
|
}
|
|
2411
2583
|
const reference = cloneElement(triggerElement, Object.assign({ ref: refs.setReference }, getReferenceProps(triggerElement.props)));
|
|
2412
2584
|
return (jsxs("div", Object.assign({ className: classNames('d-popover', className), style: generateStyleVariables }, dataAttributes, { children: [reference, isOpen && (jsx(FloatingFocusManager, { context: context, modal: false, children: jsx("div", Object.assign({ className: classNames('d-popover-content', {
|
|
2413
|
-
'
|
|
2585
|
+
'd-popover-content-fill': adjustContentToRender,
|
|
2414
2586
|
}), ref: refs.setFloating, style: floatingStyles, "aria-labelledby": headingId }, getFloatingProps(), { children: children })) }))] })));
|
|
2415
2587
|
}
|
|
2416
2588
|
|
|
@@ -2424,8 +2596,8 @@ function DProgress({ className, style, currentValue, minValue = 0, maxValue = 10
|
|
|
2424
2596
|
return (jsx("div", Object.assign({ className: classNames('progress', className), style: Object.assign({ height }, style) }, dataAttributes, { children: jsx("div", { className: classNames(generateClasses), role: "progressbar", "aria-label": "Progress bar", style: { width: formatProgress }, "aria-valuenow": currentValue, "aria-valuemin": minValue, "aria-valuemax": maxValue, children: !hideCurrentValue && formatProgress }) })));
|
|
2425
2597
|
}
|
|
2426
2598
|
|
|
2427
|
-
function DStepper$2({ options, currentStep, iconSuccess: iconSuccessProp, iconSuccessFamilyClass, iconSuccessFamilyPrefix, iconSuccessMaterialStyle
|
|
2428
|
-
const { iconMap: { check, }, } = useDContext();
|
|
2599
|
+
function DStepper$2({ options, currentStep, iconSuccess: iconSuccessProp, iconSuccessFamilyClass, iconSuccessFamilyPrefix, iconSuccessMaterialStyle, vertical = false, completed, alignStart = false, className, style, }) {
|
|
2600
|
+
const { icon: { familyClass, familyPrefix, materialStyle, }, iconMap: { check, }, } = useDContext();
|
|
2429
2601
|
const icon = useMemo(() => iconSuccessProp || check, [check, iconSuccessProp]);
|
|
2430
2602
|
if (currentStep < 1 || currentStep > options.length) {
|
|
2431
2603
|
throw new Error('Current step should be in the range from 1 to options length');
|
|
@@ -2440,7 +2612,7 @@ function DStepper$2({ options, currentStep, iconSuccess: iconSuccessProp, iconSu
|
|
|
2440
2612
|
}), children: [jsx("div", { className: "d-step-value", children: jsxs("div", { className: classNames({
|
|
2441
2613
|
'd-step-icon-container': true,
|
|
2442
2614
|
'd-step-check': value < currentStep || completed,
|
|
2443
|
-
}), children: [((value < currentStep) || completed) && (jsx(DIcon, { icon: icon, familyClass: iconSuccessFamilyClass, familyPrefix: iconSuccessFamilyPrefix, materialStyle: iconSuccessMaterialStyle, className: "d-step-icon" })), value] }) }), jsxs("div", { className: "d-step-text-container", children: [jsx("div", { className: "d-step-label", children: label }), description && (jsx("div", { className: "d-step-description", children: description }))] })] }, value))) }));
|
|
2615
|
+
}), children: [((value < currentStep) || completed) && (jsx(DIcon, { icon: icon, familyClass: iconSuccessFamilyClass !== null && iconSuccessFamilyClass !== void 0 ? iconSuccessFamilyClass : familyClass, familyPrefix: iconSuccessFamilyPrefix !== null && iconSuccessFamilyPrefix !== void 0 ? iconSuccessFamilyPrefix : familyPrefix, materialStyle: iconSuccessMaterialStyle !== null && iconSuccessMaterialStyle !== void 0 ? iconSuccessMaterialStyle : materialStyle, className: "d-step-icon" })), value] }) }), jsxs("div", { className: "d-step-text-container", children: [jsx("div", { className: "d-step-label", children: label }), description && (jsx("div", { className: "d-step-description", children: description }))] })] }, value))) }));
|
|
2444
2616
|
}
|
|
2445
2617
|
|
|
2446
2618
|
function DStepper$1({ options, currentStep, className, style, }) {
|
|
@@ -2473,14 +2645,21 @@ function DStepper$1({ options, currentStep, className, style, }) {
|
|
|
2473
2645
|
return (jsxs("div", { className: classNames('d-stepper', className), style: style, children: [jsx("div", { className: "d-step-bar", style: { background: progressStyle }, children: jsx("p", { className: "d-step-number", children: `${currentStep}/${options.length}` }) }), jsx("div", { className: "d-step-info", children: Object.keys(currentOption).length > 0 && (jsxs(Fragment, { children: [jsx("div", { className: "d-step-label", children: currentOption.label }), jsx("div", { className: "d-step-description", children: currentOption.description || '' })] })) })] }));
|
|
2474
2646
|
}
|
|
2475
2647
|
|
|
2476
|
-
function DStepper({ options, currentStep, iconSuccess, iconSuccessFamilyClass, iconSuccessFamilyPrefix, iconSuccessMaterialStyle
|
|
2477
|
-
|
|
2648
|
+
function DStepper({ options, currentStep, iconSuccess, iconSuccessFamilyClass, iconSuccessFamilyPrefix, iconSuccessMaterialStyle, vertical = false, breakpoint = 'lg', className, completed = false, style, dataAttributes, }) {
|
|
2649
|
+
const { icon: { familyClass, familyPrefix, materialStyle, }, } = useDContext();
|
|
2650
|
+
return (jsxs("div", Object.assign({ className: className, style: style }, dataAttributes, { children: [jsx("div", { className: classNames('d-stepper-mobile', `d-block d-${breakpoint}-none`), children: jsx(DStepper$1, { options: options, currentStep: currentStep }) }), jsx("div", { className: classNames('d-stepper-desktop', `d-none d-${breakpoint}-block`), children: jsx(DStepper$2, { options: options, currentStep: currentStep, vertical: vertical, iconSuccess: iconSuccess, iconSuccessFamilyClass: iconSuccessFamilyClass !== null && iconSuccessFamilyClass !== void 0 ? iconSuccessFamilyClass : familyClass, iconSuccessFamilyPrefix: iconSuccessFamilyPrefix !== null && iconSuccessFamilyPrefix !== void 0 ? iconSuccessFamilyPrefix : familyPrefix, iconSuccessMaterialStyle: iconSuccessMaterialStyle !== null && iconSuccessMaterialStyle !== void 0 ? iconSuccessMaterialStyle : materialStyle, completed: completed }) })] })));
|
|
2478
2651
|
}
|
|
2479
2652
|
|
|
2480
2653
|
const ARROW_WIDTH = 8;
|
|
2481
2654
|
const ARROW_HEIGHT = 4;
|
|
2482
|
-
const GAP = 2;
|
|
2483
|
-
|
|
2655
|
+
const GAP$1 = 2;
|
|
2656
|
+
/**
|
|
2657
|
+
* Tooltip is an abstraction component that wraps any element (`Component`) and displays
|
|
2658
|
+
* floating contextual content (`children`) positioned relative to it using Floating UI.
|
|
2659
|
+
* Use it to add short, non-critical hints or descriptions triggered by hover, focus, or
|
|
2660
|
+
* click, without altering the surrounding layout.
|
|
2661
|
+
*/
|
|
2662
|
+
function DTooltip({ className, childrenClassName, style, offSet = ARROW_HEIGHT + GAP$1, padding, withFocus = false, withClick = false, withHover = true, open = false, placement = 'top', size, Component, children, }) {
|
|
2484
2663
|
const [isOpen, setIsOpen] = useState(open);
|
|
2485
2664
|
const arrowRef = useRef(null);
|
|
2486
2665
|
const { refs, context, floatingStyles, } = useFloating({
|
|
@@ -2549,8 +2728,16 @@ function DTabs({ children, defaultSelected, onChange, options, className, classN
|
|
|
2549
2728
|
useEffect(() => {
|
|
2550
2729
|
setSelected(defaultSelected);
|
|
2551
2730
|
}, [defaultSelected]);
|
|
2552
|
-
const generateClasses = useMemo(() => (Object.assign({ nav: true, '
|
|
2731
|
+
const generateClasses = useMemo(() => (Object.assign({ nav: true, 'd-tabs-nav-vertical': vertical && variant !== 'tabs', [`nav-${variant}`]: true }, className && { [className]: true })), [vertical, variant, className]);
|
|
2553
2732
|
const tabRefs = useRef([]);
|
|
2733
|
+
// Always holds the latest `options` without needing to be a dependency:
|
|
2734
|
+
// `options` is commonly passed as an inline array literal (e.g.
|
|
2735
|
+
// `options={[{ label: 'SMS', tab: 'sms' }, ...]}`), so it's a new array
|
|
2736
|
+
// reference on every parent render even when its content hasn't changed.
|
|
2737
|
+
// Reading it from this ref (updated synchronously on every render) lets
|
|
2738
|
+
// the focus effect below react only to `selected` changing.
|
|
2739
|
+
const optionsRef = useRef(options);
|
|
2740
|
+
optionsRef.current = options;
|
|
2554
2741
|
useEffect(() => {
|
|
2555
2742
|
tabRefs.current = options.map((_, i) => tabRefs.current[i] || createRef());
|
|
2556
2743
|
}, [options]);
|
|
@@ -2565,20 +2752,28 @@ function DTabs({ children, defaultSelected, onChange, options, className, classN
|
|
|
2565
2752
|
setSelected(firstEnabled.tab);
|
|
2566
2753
|
}
|
|
2567
2754
|
}, [options, selected]);
|
|
2568
|
-
// Declarative focus management
|
|
2569
|
-
|
|
2755
|
+
// Declarative focus management. Wrapped in `useCallback` with an empty
|
|
2756
|
+
// dependency array since it only reads from the `tabRefs` ref, so its
|
|
2757
|
+
// identity stays stable across renders and it can safely be used as an
|
|
2758
|
+
// effect dependency below.
|
|
2759
|
+
const focusTab = useCallback((idx) => {
|
|
2570
2760
|
var _a;
|
|
2571
2761
|
if ((_a = tabRefs.current[idx]) === null || _a === void 0 ? void 0 : _a.current) {
|
|
2572
2762
|
tabRefs.current[idx].current.focus();
|
|
2573
2763
|
}
|
|
2574
|
-
};
|
|
2575
|
-
// Focus selected tab when selected changes
|
|
2764
|
+
}, []);
|
|
2765
|
+
// Focus selected tab when selected changes.
|
|
2766
|
+
// Reads `options` from `optionsRef` (see comment above) instead of
|
|
2767
|
+
// depending on `options` directly, so a parent re-render that merely
|
|
2768
|
+
// creates a new `options` reference with identical content doesn't call
|
|
2769
|
+
// `focusTab` again and steal focus away from unrelated elements on the
|
|
2770
|
+
// page (e.g. an OTP input).
|
|
2576
2771
|
useEffect(() => {
|
|
2577
|
-
const idx =
|
|
2772
|
+
const idx = optionsRef.current.findIndex((opt) => opt.tab === selected && !opt.disabled);
|
|
2578
2773
|
if (idx !== -1) {
|
|
2579
2774
|
focusTab(idx);
|
|
2580
2775
|
}
|
|
2581
|
-
}, [selected,
|
|
2776
|
+
}, [selected, focusTab]);
|
|
2582
2777
|
const handleKeyDown = useCallback((idx, e) => {
|
|
2583
2778
|
const count = options.length;
|
|
2584
2779
|
if (count === 0)
|
|
@@ -2607,7 +2802,7 @@ function DTabs({ children, defaultSelected, onChange, options, className, classN
|
|
|
2607
2802
|
}
|
|
2608
2803
|
}
|
|
2609
2804
|
}
|
|
2610
|
-
}, [options, vertical]);
|
|
2805
|
+
}, [options, vertical, focusTab]);
|
|
2611
2806
|
let tablistProps = {};
|
|
2612
2807
|
if (ariaLabelledBy) {
|
|
2613
2808
|
tablistProps = { 'aria-labelledby': ariaLabelledBy };
|
|
@@ -2620,12 +2815,12 @@ function DTabs({ children, defaultSelected, onChange, options, className, classN
|
|
|
2620
2815
|
isSelected,
|
|
2621
2816
|
}), [isSelected]);
|
|
2622
2817
|
return (jsx(TabContext.Provider, { value: value, children: jsxs("div", Object.assign({ className: classNames({
|
|
2623
|
-
'd-
|
|
2624
|
-
'
|
|
2818
|
+
'd-tabs': true,
|
|
2819
|
+
'd-tabs-column': !vertical || variant === 'tabs',
|
|
2625
2820
|
}), style: style }, dataAttributes, { children: [jsx("ul", Object.assign({ className: classNames(generateClasses), role: "tablist", "aria-orientation": vertical ? 'vertical' : undefined }, tablistProps, { children: options.map((option, idx) => {
|
|
2626
2821
|
const isTabSelected = !!option.tab && option.tab === selected;
|
|
2627
2822
|
return (jsx("li", { role: "presentation", className: "nav-item", children: jsx("button", { ref: tabRefs.current[idx], id: `${option.tab}Tab`, className: classNames('nav-link', { active: isTabSelected }, classNameTab), type: "button", role: "tab", "aria-controls": `${option.tab}Pane`, "aria-selected": isTabSelected, tabIndex: isTabSelected ? 0 : -1, disabled: option.disabled, onClick: () => onSelect(option), onKeyDown: (e) => handleKeyDown(idx, e), children: option.label }) }, option.tab));
|
|
2628
|
-
}) })), jsx("div", { className: "
|
|
2823
|
+
}) })), jsx("div", { className: "d-tabs-content tab-content", children: children })] })) }));
|
|
2629
2824
|
}
|
|
2630
2825
|
var DTabs$1 = Object.assign(DTabs, {
|
|
2631
2826
|
Tab: DTabContent,
|
|
@@ -2687,11 +2882,11 @@ function useDToast() {
|
|
|
2687
2882
|
if (!description) {
|
|
2688
2883
|
return (jsx(DToast$1, { className: classNames({
|
|
2689
2884
|
[`toast-${color}`]: !!color,
|
|
2690
|
-
}, 'show'), children: jsxs(DToast$1.Body, { children: [icon && (jsx(DIcon, { className: "toast-icon", icon: icon })), jsx("p", { className: "toast-title", children: title }), jsx("button", { type: "button", className: "d-close
|
|
2885
|
+
}, 'show'), children: jsxs(DToast$1.Body, { children: [icon && (jsx(DIcon, { className: "toast-icon", icon: icon })), jsx("p", { className: "toast-title", children: title }), jsx("button", { type: "button", className: "d-close", "aria-label": "Close", onClick: () => toast.dismiss(id), children: jsx(DIcon, { icon: closeIcon || xLg }) })] }) }));
|
|
2691
2886
|
}
|
|
2692
2887
|
return (jsxs(DToast$1, { className: classNames({
|
|
2693
2888
|
[`toast-${color}`]: !!color,
|
|
2694
|
-
}, 'show'), children: [jsxs(DToast$1.Header, { children: [icon && (jsx(DIcon, { className: "toast-icon", icon: icon })), jsx("p", { className: "toast-title", children: title }), timestamp && (jsx("small", { className: "toast-timestamp", children: timestamp })), jsx("button", { type: "button", className: "d-close
|
|
2889
|
+
}, 'show'), children: [jsxs(DToast$1.Header, { children: [icon && (jsx(DIcon, { className: "toast-icon", icon: icon })), jsx("p", { className: "toast-title", children: title }), timestamp && (jsx("small", { className: "toast-timestamp", children: timestamp })), jsx("button", { type: "button", className: "d-close", "aria-label": "Close", onClick: () => toast.dismiss(id), children: jsx(DIcon, { icon: closeIcon || xLg }) })] }), jsx(DToast$1.Body, { children: jsx("span", { children: description }) })] }));
|
|
2695
2890
|
}, toastProps);
|
|
2696
2891
|
}, [xLg]);
|
|
2697
2892
|
return {
|
|
@@ -2713,11 +2908,10 @@ async function configureI8n(resources, _a = {}) {
|
|
|
2713
2908
|
.then((t) => t);
|
|
2714
2909
|
}
|
|
2715
2910
|
|
|
2716
|
-
function getQueryString(value, config = {
|
|
2717
|
-
useSearch
|
|
2718
|
-
|
|
2719
|
-
|
|
2720
|
-
return urlParams.get(value) || config.default;
|
|
2911
|
+
function getQueryString(value, config = {}) {
|
|
2912
|
+
const { useSearch = true, default: defaultValue } = config;
|
|
2913
|
+
const urlParams = new URLSearchParams(useSearch ? window.location.search : '');
|
|
2914
|
+
return urlParams.get(value) || defaultValue;
|
|
2721
2915
|
}
|
|
2722
2916
|
|
|
2723
2917
|
function changeQueryString(values, { useSearch = true, pushState = false, } = {}) {
|
|
@@ -2747,11 +2941,132 @@ function validatePhoneNumber(phone) {
|
|
|
2747
2941
|
}
|
|
2748
2942
|
}
|
|
2749
2943
|
|
|
2944
|
+
const SAFE_SCHEMES = new Set(['http:', 'https:', 'mailto:', 'tel:']);
|
|
2945
|
+
/**
|
|
2946
|
+
* Characters the URL parser drops before resolving a URL, so they cannot be used to hide a
|
|
2947
|
+
* scheme-relative prefix or a dangerous scheme (e.g. `/<TAB>/evil.com`, `java<TAB>script:`).
|
|
2948
|
+
*/
|
|
2949
|
+
const IGNORED_CHARS$1 = /[\t\n\r]/g;
|
|
2950
|
+
/**
|
|
2951
|
+
* Two leading separators in any combination. Browsers treat a leading `\` exactly like a
|
|
2952
|
+
* leading `/`, so `//`, `/\`, `\/` and `\\` all resolve to a scheme-relative URL.
|
|
2953
|
+
*/
|
|
2954
|
+
const SCHEME_RELATIVE = /^[/\\]{2}/;
|
|
2955
|
+
const LEADING_SEPARATOR = /^[/\\]/;
|
|
2956
|
+
/**
|
|
2957
|
+
* Validates a `href` value and returns it only if it is safe to render as a link,
|
|
2958
|
+
* preventing XSS through unsafe URL schemes and scheme-relative URLs.
|
|
2959
|
+
*
|
|
2960
|
+
* Before validating, the value is trimmed and every tab, line feed and carriage return is
|
|
2961
|
+
* removed, because the URL parser ignores those characters too and they would otherwise
|
|
2962
|
+
* hide an unsafe value from the checks below.
|
|
2963
|
+
*
|
|
2964
|
+
* A `href` is considered safe when it is either:
|
|
2965
|
+
* - An absolute path starting with a single separator (e.g. `/accounts/42`). A leading `\`
|
|
2966
|
+
* is normalized to `/` in the returned value, since that is how the browser resolves it.
|
|
2967
|
+
* - A URL using one of the allowed schemes: `http:`, `https:`, `mailto:`, `tel:`.
|
|
2968
|
+
*
|
|
2969
|
+
* A `href` is rejected (returns `undefined`) when it is:
|
|
2970
|
+
* - Empty or made only of whitespace/ignored characters (`''`, `' '`).
|
|
2971
|
+
* - Scheme-relative (starts with two separators, e.g. `//evil.com`, `/\evil.com`,
|
|
2972
|
+
* `/<TAB>/evil.com`), since the browser would resolve it using the current protocol and it
|
|
2973
|
+
* can be used to redirect to an attacker-controlled host.
|
|
2974
|
+
* - Using a disallowed/dangerous scheme, such as `javascript:` or `data:`
|
|
2975
|
+
* (e.g. `javascript:alert(1)`, `data:text/html,<script>...</script>`).
|
|
2976
|
+
* - Not parseable as an absolute URL and not an absolute path, such as bare fragments
|
|
2977
|
+
* (`#anchor`) or scheme-less relative paths (`relative/path`). These cannot be validated
|
|
2978
|
+
* against `SAFE_SCHEMES`, so they are rejected rather than assumed safe.
|
|
2979
|
+
*
|
|
2980
|
+
* @param href - The raw URL or path to validate, typically coming from user input,
|
|
2981
|
+
* a CMS, or an external API.
|
|
2982
|
+
* @returns The sanitized `href` when safe, `undefined` otherwise.
|
|
2983
|
+
*
|
|
2984
|
+
* @example
|
|
2985
|
+
* sanitizeHref('/accounts/42'); // '/accounts/42'
|
|
2986
|
+
* sanitizeHref('https://example.com'); // 'https://example.com'
|
|
2987
|
+
* sanitizeHref('mailto:test@example.com'); // 'mailto:test@example.com'
|
|
2988
|
+
* sanitizeHref('//evil.com'); // undefined
|
|
2989
|
+
* sanitizeHref('/\\evil.com'); // undefined
|
|
2990
|
+
* sanitizeHref('javascript:alert(1)'); // undefined
|
|
2991
|
+
*/
|
|
2992
|
+
function sanitizeHref(href) {
|
|
2993
|
+
const normalized = href.trim().replace(IGNORED_CHARS$1, '');
|
|
2994
|
+
if (!normalized)
|
|
2995
|
+
return undefined;
|
|
2996
|
+
if (SCHEME_RELATIVE.test(normalized))
|
|
2997
|
+
return undefined;
|
|
2998
|
+
if (LEADING_SEPARATOR.test(normalized))
|
|
2999
|
+
return `/${normalized.slice(1)}`;
|
|
3000
|
+
try {
|
|
3001
|
+
const { protocol } = new URL(normalized);
|
|
3002
|
+
return SAFE_SCHEMES.has(protocol) ? normalized : undefined;
|
|
3003
|
+
}
|
|
3004
|
+
catch (_a) {
|
|
3005
|
+
return undefined;
|
|
3006
|
+
}
|
|
3007
|
+
}
|
|
3008
|
+
|
|
3009
|
+
/**
|
|
3010
|
+
* Characters the URL parser drops before resolving a URL, so they cannot be used to hide a
|
|
3011
|
+
* scheme-relative prefix (e.g. `/<TAB>/evil.com`).
|
|
3012
|
+
*/
|
|
3013
|
+
const IGNORED_CHARS = /[\t\n\r]/g;
|
|
3014
|
+
/**
|
|
3015
|
+
* Leading separators. Browsers treat a leading `\` exactly like a leading `/`, so both have
|
|
3016
|
+
* to be stripped to prevent scheme-relative URLs (`//evil.com`, `/\evil.com`, `\\evil.com`).
|
|
3017
|
+
*/
|
|
3018
|
+
const LEADING_SEPARATORS = /^[/\\]+/;
|
|
3019
|
+
/**
|
|
3020
|
+
* Builds an internal URL from a `path` and a set of query `params`, normalizing leading
|
|
3021
|
+
* separators to prevent scheme-relative URLs (e.g. `//accounts` and `/\accounts` both become
|
|
3022
|
+
* `/accounts`).
|
|
3023
|
+
*
|
|
3024
|
+
* The `path` is trimmed and every tab, line feed and carriage return is removed before
|
|
3025
|
+
* building the result, because the URL parser ignores those characters too and they would
|
|
3026
|
+
* otherwise hide a scheme-relative prefix (`/<TAB>/evil.com` resolves to `//evil.com`).
|
|
3027
|
+
*
|
|
3028
|
+
* Handles the special case where `path` is the literal string `'#'`, which happens when
|
|
3029
|
+
* a Liquid template variable used as a link target is left unconfigured; in that case the
|
|
3030
|
+
* params are ignored and `'#'` is returned as-is instead of building a broken URL.
|
|
3031
|
+
*
|
|
3032
|
+
* @param path - The path to build the URL from. Leading separators are stripped before
|
|
3033
|
+
* building the result (`/accounts`, `//accounts` and `\accounts` are all treated as `accounts`).
|
|
3034
|
+
* @param params - Key/value pairs serialized as the query string.
|
|
3035
|
+
* @returns The resulting URL:
|
|
3036
|
+
* - `'#'` when `path` normalizes to `'#'` (`'#'`, `'/#'`), ignoring the params.
|
|
3037
|
+
* - `'/'` when `path` is empty and there are no params.
|
|
3038
|
+
* - `'/?<query>'` when `path` is empty and there are params.
|
|
3039
|
+
* - `'<path>'` or `'<path>?<query>'` when `path` starts with `#`, since a fragment must not be
|
|
3040
|
+
* prefixed with `/` (it would navigate away from the current document).
|
|
3041
|
+
* - `'/<path>'` or `'/<path>?<query>'` otherwise.
|
|
3042
|
+
*
|
|
3043
|
+
* @example
|
|
3044
|
+
* buildUrl('accounts', { account_id: '42' }); // '/accounts?account_id=42'
|
|
3045
|
+
* buildUrl('//accounts', {}); // '/accounts'
|
|
3046
|
+
* buildUrl('#', { account_id: '42' }); // '#'
|
|
3047
|
+
* buildUrl('#accounts', { account_id: '42' }); // '#accounts?account_id=42'
|
|
3048
|
+
* buildUrl('', { tab: 'movimientos' }); // '/?tab=movimientos'
|
|
3049
|
+
*/
|
|
3050
|
+
function buildUrl(path, params) {
|
|
3051
|
+
const normalizedPath = path
|
|
3052
|
+
.trim()
|
|
3053
|
+
.replace(IGNORED_CHARS, '')
|
|
3054
|
+
.replace(LEADING_SEPARATORS, '');
|
|
3055
|
+
if (normalizedPath === '#')
|
|
3056
|
+
return '#';
|
|
3057
|
+
const query = new URLSearchParams(Object.entries(params).map(([key, value]) => [key, String(value)])).toString();
|
|
3058
|
+
if (normalizedPath === '')
|
|
3059
|
+
return query ? `/?${query}` : '/';
|
|
3060
|
+
const prefix = normalizedPath.startsWith('#') ? '' : '/';
|
|
3061
|
+
return `${prefix}${normalizedPath}${query ? `?${query}` : ''}`;
|
|
3062
|
+
}
|
|
3063
|
+
|
|
2750
3064
|
function DInputPhone(_a, ref) {
|
|
2751
3065
|
var { id: idProp, style, className, label = '', disabled = false, loading = false, iconFamilyClass, iconFamilyPrefix, iconMaterialStyle, iconEnd, iconEndDisabled, iconEndFamilyClass, iconEndFamilyPrefix, iconEndAriaLabel, iconEndTabIndex, iconEndMaterialStyle, hint, size, invalid = false, valid = false, floatingLabel = false, inputEnd, value, placeholder = '', dataAttributes, onChange, onIconEndClick, countrySelectorProps, filteredCountries, defaultCountry = 'cl' } = _a, inputProps = __rest(_a, ["id", "style", "className", "label", "disabled", "loading", "iconFamilyClass", "iconFamilyPrefix", "iconMaterialStyle", "iconEnd", "iconEndDisabled", "iconEndFamilyClass", "iconEndFamilyPrefix", "iconEndAriaLabel", "iconEndTabIndex", "iconEndMaterialStyle", "hint", "size", "invalid", "valid", "floatingLabel", "inputEnd", "value", "placeholder", "dataAttributes", "onChange", "onIconEndClick", "countrySelectorProps", "filteredCountries", "defaultCountry"]);
|
|
2752
3066
|
const innerRef = useProvidedRefOrCreate(ref);
|
|
2753
3067
|
const innerId = useId();
|
|
2754
3068
|
const id = useMemo(() => idProp || innerId, [idProp, innerId]);
|
|
3069
|
+
const { icon: { familyClass, familyPrefix, materialStyle, }, } = useDContext();
|
|
2755
3070
|
const handleOnIconEndClick = useCallback(() => {
|
|
2756
3071
|
onIconEndClick === null || onIconEndClick === void 0 ? void 0 : onIconEndClick(value);
|
|
2757
3072
|
}, [onIconEndClick, value]);
|
|
@@ -2825,7 +3140,7 @@ function DInputPhone(_a, ref) {
|
|
|
2825
3140
|
[`input-group-${size}`]: !!size,
|
|
2826
3141
|
'input-group': true,
|
|
2827
3142
|
'has-validation': invalid || valid,
|
|
2828
|
-
}), children: [jsx(CountrySelector, Object.assign({}, countrySelectorProps, { selectedCountry: country.iso2, onSelect: ({ iso2 }) => setCountry(iso2), countries: countries, disabled: disabled || loading, className: classNames('input-group-text', countrySelectorProps === null || countrySelectorProps === void 0 ? void 0 : countrySelectorProps.className) })), dynamicComponent, (iconEnd && !loading) && (jsx("button", { type: "button", className: "input-group-text", id: `${id}End`, onClick: handleOnIconEndClick, disabled: disabled || loading || iconEndDisabled, "aria-label": iconEndAriaLabel, tabIndex: onIconEndClick ? iconEndTabIndex : -1, children: jsx(DIcon, { icon: iconEnd, familyClass: iconEndFamilyClass, familyPrefix: iconEndFamilyPrefix, materialStyle: iconEndMaterialStyle }) })), loading && (jsx("div", { className: "input-group-text", id: `${id}Loading`, children: jsx("span", { className: "spinner-border spinner-border-sm", role: "status", "aria-hidden": "true", children: jsx("span", { className: "visually-hidden", children: "Loading..." }) }) })), !!inputEnd && (jsx("div", { className: "input-group-text", id: `${id}InputEnd`, children: inputEnd }))] }), hint && (jsx("div", { className: "form-text", id: `${id}Hint`, children: hint }))] })));
|
|
3143
|
+
}), children: [jsx(CountrySelector, Object.assign({}, countrySelectorProps, { selectedCountry: country.iso2, onSelect: ({ iso2 }) => setCountry(iso2), countries: countries, disabled: disabled || loading, className: classNames('input-group-text', countrySelectorProps === null || countrySelectorProps === void 0 ? void 0 : countrySelectorProps.className) })), dynamicComponent, (iconEnd && !loading) && (jsx("button", { type: "button", className: "input-group-text", id: `${id}End`, onClick: handleOnIconEndClick, disabled: disabled || loading || iconEndDisabled, "aria-label": iconEndAriaLabel, tabIndex: onIconEndClick ? iconEndTabIndex : -1, children: jsx(DIcon, { icon: iconEnd, familyClass: iconEndFamilyClass !== null && iconEndFamilyClass !== void 0 ? iconEndFamilyClass : familyClass, familyPrefix: iconEndFamilyPrefix !== null && iconEndFamilyPrefix !== void 0 ? iconEndFamilyPrefix : familyPrefix, materialStyle: iconEndMaterialStyle !== null && iconEndMaterialStyle !== void 0 ? iconEndMaterialStyle : materialStyle }) })), loading && (jsx("div", { className: "input-group-text", id: `${id}Loading`, children: jsx("span", { className: "spinner-border spinner-border-sm", role: "status", "aria-hidden": "true", children: jsx("span", { className: "visually-hidden", children: "Loading..." }) }) })), !!inputEnd && (jsx("div", { className: "input-group-text", id: `${id}InputEnd`, children: inputEnd }))] }), hint && (jsx("div", { className: "form-text", id: `${id}Hint`, children: hint }))] })));
|
|
2829
3144
|
}
|
|
2830
3145
|
const ForwardedDInputPhone = forwardRef(DInputPhone);
|
|
2831
3146
|
ForwardedDInputPhone.displayName = 'DInputPhone';
|
|
@@ -2840,89 +3155,228 @@ function DCreditCard({ brand = 'visa', name, number, holderText = 'Card Holder',
|
|
|
2840
3155
|
return (jsxs("div", { className: classNames('d-credit-card', isVertical && 'is-vertical', className), children: [jsxs("div", { className: "d-credit-card-header", children: [jsx("img", { src: logoImage || BRAND_LOGOS[brand] || DEFAULT_IMAGE, alt: brand, className: "d-credit-card-logo", width: 100 }), isChipVisible && (jsx("div", { className: "d-credit-card-chip", children: jsx("img", { src: CHIP_IMAGE, alt: "chip", width: 30, className: "d-credit-card-chip-image" }) }))] }), jsxs("div", { className: "d-credit-card-details", children: [jsx("div", { className: "d-credit-card-number", children: number }), jsx("small", { className: "d-credit-card-holder-text", children: holderText }), jsx("span", { className: "d-credit-card-name", children: name })] })] }));
|
|
2841
3156
|
}
|
|
2842
3157
|
|
|
3158
|
+
// Gap between the toggle and the menu.
|
|
3159
|
+
const GAP = 4;
|
|
3160
|
+
// Minimum distance the menu should keep from the viewport edges.
|
|
3161
|
+
const VIEWPORT_PADDING = 8;
|
|
3162
|
+
// Minimum usable height left for the menu before we consider a side unusable.
|
|
3163
|
+
const MIN_USABLE_SPACE = 120;
|
|
2843
3164
|
const getItemClass = (action) => classNames({
|
|
2844
3165
|
'dropdown-item d-flex align-items-center': true,
|
|
2845
3166
|
[`dropdown-item-${action.color}`]: !!action.color,
|
|
2846
3167
|
disabled: action.disabled,
|
|
2847
3168
|
});
|
|
2848
|
-
|
|
3169
|
+
const clamp = (value, min, max) => {
|
|
3170
|
+
if (max < min)
|
|
3171
|
+
return min;
|
|
3172
|
+
return Math.min(Math.max(value, min), max);
|
|
3173
|
+
};
|
|
3174
|
+
/**
|
|
3175
|
+
* `position: fixed` is normally relative to the viewport, but any ancestor
|
|
3176
|
+
* with a `transform`, `perspective`, `filter`, `will-change` (of those) or a
|
|
3177
|
+
* non-trivial `contain` establishes a new containing block, making `fixed`
|
|
3178
|
+
* behave like `absolute` relative to that ancestor instead (e.g. Storybook's
|
|
3179
|
+
* docs canvas wrapper, animated cards, sticky containers, etc.). We detect
|
|
3180
|
+
* that ancestor so the computed coordinates can be adjusted accordingly,
|
|
3181
|
+
* keeping the menu correctly anchored to the toggle in every context.
|
|
3182
|
+
*/
|
|
3183
|
+
const getFixedPositioningOffset = (fromEl) => {
|
|
3184
|
+
var _a;
|
|
3185
|
+
let node = (_a = fromEl === null || fromEl === void 0 ? void 0 : fromEl.parentElement) !== null && _a !== void 0 ? _a : null;
|
|
3186
|
+
while (node && node !== document.body) {
|
|
3187
|
+
const cs = window.getComputedStyle(node);
|
|
3188
|
+
// Treat empty/undefined values as "unset" (jsdom returns "" rather than
|
|
3189
|
+
// the CSS initial value like "none" for some of these properties).
|
|
3190
|
+
const isSet = (value) => !!value && value !== 'none';
|
|
3191
|
+
const establishesContainingBlock = isSet(cs.transform)
|
|
3192
|
+
|| isSet(cs.perspective)
|
|
3193
|
+
|| isSet(cs.filter)
|
|
3194
|
+
|| isSet(cs.backdropFilter)
|
|
3195
|
+
|| ['transform', 'perspective', 'filter'].some((prop) => { var _a; return (_a = cs.willChange) === null || _a === void 0 ? void 0 : _a.includes(prop); })
|
|
3196
|
+
|| cs.contain.split(' ').some((value) => ['layout', 'paint', 'strict', 'content'].includes(value));
|
|
3197
|
+
if (establishesContainingBlock) {
|
|
3198
|
+
const rect = node.getBoundingClientRect();
|
|
3199
|
+
return { top: rect.top, left: rect.left };
|
|
3200
|
+
}
|
|
3201
|
+
node = node.parentElement;
|
|
3202
|
+
}
|
|
3203
|
+
return { top: 0, left: 0 };
|
|
3204
|
+
};
|
|
3205
|
+
/**
|
|
3206
|
+
* Resolves where the menu should render (flip) and where it should sit along
|
|
3207
|
+
* the cross axis (shift), so it always stays fully inside the viewport
|
|
3208
|
+
* regardless of where the toggle is placed or how the viewport is resized.
|
|
3209
|
+
* This mimics floating-ui's `flip` + `shift` middlewares without adding the
|
|
3210
|
+
* dependency, keeping the existing Bootstrap markup/classes.
|
|
3211
|
+
*/
|
|
3212
|
+
const computeCoords = (toggleRect, menuSize, placement, alignment) => {
|
|
3213
|
+
const viewportWidth = window.innerWidth;
|
|
3214
|
+
const viewportHeight = window.innerHeight;
|
|
3215
|
+
const spaceBelow = viewportHeight - toggleRect.bottom;
|
|
3216
|
+
const spaceAbove = toggleRect.top;
|
|
3217
|
+
const spaceLeft = toggleRect.left;
|
|
3218
|
+
const spaceRight = viewportWidth - toggleRect.right;
|
|
3219
|
+
let side = placement === 'auto'
|
|
3220
|
+
? 'down'
|
|
3221
|
+
: placement;
|
|
3222
|
+
if (placement === 'auto') {
|
|
3223
|
+
side = spaceBelow >= menuSize.height + GAP || spaceBelow >= spaceAbove ? 'down' : 'up';
|
|
3224
|
+
}
|
|
3225
|
+
// Flip within the current axis if the chosen side can't fit the menu but
|
|
3226
|
+
// the opposite side (same axis) can.
|
|
3227
|
+
if (side === 'down' && spaceBelow < menuSize.height + GAP && spaceAbove > spaceBelow) {
|
|
3228
|
+
side = 'up';
|
|
3229
|
+
}
|
|
3230
|
+
else if (side === 'up' && spaceAbove < menuSize.height + GAP && spaceBelow > spaceAbove) {
|
|
3231
|
+
side = 'down';
|
|
3232
|
+
}
|
|
3233
|
+
else if (side === 'start' && spaceLeft < menuSize.width + GAP && spaceRight > spaceLeft) {
|
|
3234
|
+
side = 'end';
|
|
3235
|
+
}
|
|
3236
|
+
else if (side === 'end' && spaceRight < menuSize.width + GAP && spaceLeft > spaceRight) {
|
|
3237
|
+
side = 'start';
|
|
3238
|
+
}
|
|
3239
|
+
// Cross-axis fallback: e.g. a horizontally-centered toggle on a narrow
|
|
3240
|
+
// viewport can't open sideways (neither `start` nor `end` fit), but there
|
|
3241
|
+
// is plenty of room above/below — switch the whole axis in that case
|
|
3242
|
+
// (and vice versa for `down`/`up` squeezed against a short viewport).
|
|
3243
|
+
const bestVerticalSpace = Math.max(spaceBelow, spaceAbove);
|
|
3244
|
+
const bestHorizontalSpace = Math.max(spaceLeft, spaceRight);
|
|
3245
|
+
if (side === 'down' || side === 'up') {
|
|
3246
|
+
if (bestVerticalSpace < MIN_USABLE_SPACE && bestHorizontalSpace > bestVerticalSpace) {
|
|
3247
|
+
side = spaceRight >= spaceLeft ? 'end' : 'start';
|
|
3248
|
+
}
|
|
3249
|
+
}
|
|
3250
|
+
else if (bestHorizontalSpace < menuSize.width + GAP
|
|
3251
|
+
&& bestVerticalSpace > bestHorizontalSpace) {
|
|
3252
|
+
side = spaceBelow >= spaceAbove ? 'down' : 'up';
|
|
3253
|
+
}
|
|
3254
|
+
if (side === 'down' || side === 'up') {
|
|
3255
|
+
const top = side === 'down'
|
|
3256
|
+
? toggleRect.bottom + GAP
|
|
3257
|
+
: toggleRect.top - menuSize.height - GAP;
|
|
3258
|
+
// Align horizontally per the requested `alignment` (start/end/center), then
|
|
3259
|
+
// fall back to the opposite edge if the preferred alignment would overflow
|
|
3260
|
+
// the viewport, and clamp as a final safety net so it never overflows.
|
|
3261
|
+
let left;
|
|
3262
|
+
if (alignment === 'end') {
|
|
3263
|
+
left = toggleRect.right - menuSize.width;
|
|
3264
|
+
}
|
|
3265
|
+
else if (alignment === 'center') {
|
|
3266
|
+
left = toggleRect.left + (toggleRect.width / 2) - (menuSize.width / 2);
|
|
3267
|
+
}
|
|
3268
|
+
else {
|
|
3269
|
+
left = toggleRect.left;
|
|
3270
|
+
}
|
|
3271
|
+
if (left + menuSize.width > viewportWidth - VIEWPORT_PADDING && alignment !== 'end') {
|
|
3272
|
+
const altLeft = toggleRect.right - menuSize.width;
|
|
3273
|
+
if (altLeft >= VIEWPORT_PADDING)
|
|
3274
|
+
left = altLeft;
|
|
3275
|
+
}
|
|
3276
|
+
else if (left < VIEWPORT_PADDING && alignment !== 'start') {
|
|
3277
|
+
const altLeft = toggleRect.left;
|
|
3278
|
+
if (altLeft + menuSize.width <= viewportWidth - VIEWPORT_PADDING)
|
|
3279
|
+
left = altLeft;
|
|
3280
|
+
}
|
|
3281
|
+
left = clamp(left, VIEWPORT_PADDING, Math.max(viewportWidth - menuSize.width - VIEWPORT_PADDING, VIEWPORT_PADDING));
|
|
3282
|
+
const availableHeight = side === 'down' ? spaceBelow : spaceAbove;
|
|
3283
|
+
// Cap strictly to the space actually available on the resolved side —
|
|
3284
|
+
// MIN_USABLE_SPACE is only meant to influence the flip/shift decision
|
|
3285
|
+
// above, not to force a taller box than what physically fits and
|
|
3286
|
+
// overflow the viewport.
|
|
3287
|
+
const maxUsableHeight = Math.max(availableHeight - GAP - VIEWPORT_PADDING, 0);
|
|
3288
|
+
return {
|
|
3289
|
+
top,
|
|
3290
|
+
left,
|
|
3291
|
+
minWidth: Math.max(toggleRect.width, 160),
|
|
3292
|
+
maxHeight: `${maxUsableHeight}px`,
|
|
3293
|
+
resolvedSide: side,
|
|
3294
|
+
};
|
|
3295
|
+
}
|
|
3296
|
+
// side is 'start' or 'end'
|
|
3297
|
+
let left = side === 'start'
|
|
3298
|
+
? toggleRect.left - menuSize.width - GAP
|
|
3299
|
+
: toggleRect.right + GAP;
|
|
3300
|
+
// Safety-net clamp: in rare cases where the toggle is squeezed so tightly
|
|
3301
|
+
// that no side of any axis has enough room, keep the menu inside the
|
|
3302
|
+
// viewport rather than letting it render off-screen.
|
|
3303
|
+
left = clamp(left, VIEWPORT_PADDING, Math.max(viewportWidth - menuSize.width - VIEWPORT_PADDING, VIEWPORT_PADDING));
|
|
3304
|
+
// Shift vertically: align with the toggle's top edge by default, but switch
|
|
3305
|
+
// to the bottom edge (or clamp) if that would overflow the viewport.
|
|
3306
|
+
let { top } = toggleRect;
|
|
3307
|
+
if (top + menuSize.height > viewportHeight - VIEWPORT_PADDING) {
|
|
3308
|
+
top = toggleRect.bottom - menuSize.height;
|
|
3309
|
+
}
|
|
3310
|
+
top = clamp(top, VIEWPORT_PADDING, Math.max(viewportHeight - menuSize.height - VIEWPORT_PADDING, VIEWPORT_PADDING));
|
|
3311
|
+
return {
|
|
3312
|
+
top,
|
|
3313
|
+
left,
|
|
3314
|
+
minWidth: Math.max(toggleRect.width, 160),
|
|
3315
|
+
maxHeight: `${Math.max(viewportHeight - top - VIEWPORT_PADDING, 0)}px`,
|
|
3316
|
+
resolvedSide: side,
|
|
3317
|
+
};
|
|
3318
|
+
};
|
|
3319
|
+
function DDropdown({ actions, dropdownToggle, className, classNameMenu, asPortal = false, placement = 'auto', alignment = 'start', }) {
|
|
2849
3320
|
const [open, setOpen] = useState(false);
|
|
2850
|
-
const [
|
|
2851
|
-
|
|
2852
|
-
//
|
|
2853
|
-
|
|
2854
|
-
//
|
|
3321
|
+
const [coords, setCoords] = useState(null);
|
|
3322
|
+
// Initialize from `placement` (falling back to 'down' for 'auto') so the
|
|
3323
|
+
// wrapper's `drop-*` class reflects the requested side even before the
|
|
3324
|
+
// first open/measurement, matching the previous `drop-${placement}` class
|
|
3325
|
+
// behavior (relevant for Bootstrap caret/orientation styling).
|
|
3326
|
+
const [resolvedSide, setResolvedSide] = useState(placement === 'auto' ? 'down' : placement);
|
|
3327
|
+
// Wraps the toggle in both modes — used to read its viewport-relative rect.
|
|
2855
3328
|
const toggleRef = useRef(null);
|
|
2856
|
-
// Ref on the rendered <ul> — used for outside-click detection
|
|
3329
|
+
// Ref on the rendered <ul> — used to measure its size and for outside-click detection.
|
|
2857
3330
|
const menuRef = useRef(null);
|
|
2858
3331
|
const toggle = () => {
|
|
2859
|
-
|
|
3332
|
+
setCoords(null);
|
|
2860
3333
|
setOpen((prev) => !prev);
|
|
2861
3334
|
};
|
|
2862
|
-
|
|
2863
|
-
//
|
|
2864
|
-
const
|
|
2865
|
-
if (!toggleRef.current)
|
|
3335
|
+
// Measures the toggle + menu and (re)computes fixed, pixel-perfect coords
|
|
3336
|
+
// with collision detection, so the menu never overflows the viewport.
|
|
3337
|
+
const updatePosition = useCallback(() => {
|
|
3338
|
+
if (!toggleRef.current || !menuRef.current)
|
|
3339
|
+
return;
|
|
3340
|
+
const toggleRect = toggleRef.current.getBoundingClientRect();
|
|
3341
|
+
// If the toggle itself has scrolled completely out of the viewport
|
|
3342
|
+
// (regardless of `placement`), close the menu instead of leaving it
|
|
3343
|
+
// rendered detached from the toggle that opened it.
|
|
3344
|
+
const toggleIsMeasured = toggleRect.width > 0 || toggleRect.height > 0;
|
|
3345
|
+
const toggleIsOutOfView = toggleRect.bottom <= 0
|
|
3346
|
+
|| toggleRect.top >= window.innerHeight
|
|
3347
|
+
|| toggleRect.right <= 0
|
|
3348
|
+
|| toggleRect.left >= window.innerWidth;
|
|
3349
|
+
if (toggleIsMeasured && toggleIsOutOfView) {
|
|
3350
|
+
setOpen(false);
|
|
2866
3351
|
return;
|
|
2867
|
-
const rect = toggleRef.current.getBoundingClientRect();
|
|
2868
|
-
const spaceRight = window.innerWidth - rect.right;
|
|
2869
|
-
const spaceBottom = window.innerHeight - rect.bottom;
|
|
2870
|
-
const spaceTop = rect.top;
|
|
2871
|
-
let resolvedPlacement;
|
|
2872
|
-
if (placement === 'auto') {
|
|
2873
|
-
if (spaceBottom < 150) {
|
|
2874
|
-
resolvedPlacement = 'up';
|
|
2875
|
-
}
|
|
2876
|
-
else if (spaceRight < 150) {
|
|
2877
|
-
resolvedPlacement = 'start';
|
|
2878
|
-
}
|
|
2879
|
-
else {
|
|
2880
|
-
resolvedPlacement = 'down';
|
|
2881
|
-
}
|
|
2882
|
-
}
|
|
2883
|
-
else {
|
|
2884
|
-
resolvedPlacement = placement;
|
|
2885
|
-
}
|
|
2886
|
-
const openStart = resolvedPlacement === 'start';
|
|
2887
|
-
const openEnd = resolvedPlacement === 'end';
|
|
2888
|
-
const openUp = resolvedPlacement === 'up';
|
|
2889
|
-
let availableHeight = spaceBottom;
|
|
2890
|
-
if (openUp) {
|
|
2891
|
-
availableHeight = spaceTop;
|
|
2892
|
-
}
|
|
2893
|
-
else if (openStart || openEnd) {
|
|
2894
|
-
availableHeight = window.innerHeight - rect.top;
|
|
2895
|
-
}
|
|
2896
|
-
const verticalCoords = openUp
|
|
2897
|
-
? { bottom: window.innerHeight - rect.top + 4 }
|
|
2898
|
-
: { top: openStart || openEnd ? rect.top : rect.bottom + 4 };
|
|
2899
|
-
let horizontalCoords;
|
|
2900
|
-
if (openStart) {
|
|
2901
|
-
horizontalCoords = { right: window.innerWidth - rect.left + 4 };
|
|
2902
|
-
}
|
|
2903
|
-
else if (openEnd) {
|
|
2904
|
-
horizontalCoords = { left: rect.right + 4 };
|
|
2905
|
-
}
|
|
2906
|
-
else {
|
|
2907
|
-
horizontalCoords = { left: rect.left };
|
|
2908
3352
|
}
|
|
2909
|
-
|
|
2910
|
-
|
|
2911
|
-
|
|
2912
|
-
|
|
2913
|
-
|
|
2914
|
-
|
|
2915
|
-
const
|
|
2916
|
-
|
|
2917
|
-
|
|
2918
|
-
|
|
2919
|
-
};
|
|
2920
|
-
|
|
2921
|
-
|
|
2922
|
-
|
|
2923
|
-
|
|
2924
|
-
|
|
2925
|
-
if (
|
|
3353
|
+
const menuRect = menuRef.current.getBoundingClientRect();
|
|
3354
|
+
const _a = computeCoords(toggleRect, { width: menuRect.width, height: menuRect.height }, placement, alignment), { resolvedSide: side } = _a, menuCoords = __rest(_a, ["resolvedSide"]);
|
|
3355
|
+
// In portal mode the menu is appended to document.body, whose containing
|
|
3356
|
+
// block for `fixed` is always the viewport (no adjustment needed). In
|
|
3357
|
+
// inline mode the menu stays next to the toggle, so we must look for a
|
|
3358
|
+
// containing-block-establishing ancestor starting from the toggle.
|
|
3359
|
+
const offset = asPortal
|
|
3360
|
+
? { top: 0, left: 0 }
|
|
3361
|
+
: getFixedPositioningOffset(toggleRef.current);
|
|
3362
|
+
setResolvedSide(side);
|
|
3363
|
+
setCoords(Object.assign(Object.assign({}, menuCoords), { top: menuCoords.top - offset.top, left: menuCoords.left - offset.left }));
|
|
3364
|
+
}, [placement, alignment, asPortal]);
|
|
3365
|
+
// Throttles scroll/resize-triggered updates to at most once per frame,
|
|
3366
|
+
// avoiding repeated forced reflows on busy/high-frequency scroll events.
|
|
3367
|
+
const rafIdRef = useRef(null);
|
|
3368
|
+
const scheduleUpdatePosition = useCallback(() => {
|
|
3369
|
+
if (rafIdRef.current !== null)
|
|
3370
|
+
return;
|
|
3371
|
+
rafIdRef.current = window.requestAnimationFrame(() => {
|
|
3372
|
+
rafIdRef.current = null;
|
|
3373
|
+
updatePosition();
|
|
3374
|
+
});
|
|
3375
|
+
}, [updatePosition]);
|
|
3376
|
+
// Outside-click detection (checks both the toggle and the floating menu,
|
|
3377
|
+
// since in portal mode the menu isn't a DOM descendant of the toggle).
|
|
3378
|
+
useLayoutEffect(() => {
|
|
3379
|
+
if (!open)
|
|
2926
3380
|
return () => { };
|
|
2927
3381
|
const handler = (event) => {
|
|
2928
3382
|
var _a, _b;
|
|
@@ -2933,35 +3387,25 @@ function DDropdown({ actions, dropdownToggle, className, classNameMenu, asPortal
|
|
|
2933
3387
|
};
|
|
2934
3388
|
document.addEventListener('mousedown', handler);
|
|
2935
3389
|
return () => document.removeEventListener('mousedown', handler);
|
|
2936
|
-
}, [
|
|
2937
|
-
//
|
|
2938
|
-
|
|
2939
|
-
|
|
2940
|
-
|
|
2941
|
-
|
|
2942
|
-
const spaceBottom = window.innerHeight - rect.bottom;
|
|
2943
|
-
const spaceRight = window.innerWidth - rect.right;
|
|
2944
|
-
if (spaceBottom < 150)
|
|
2945
|
-
setPosition('up');
|
|
2946
|
-
else if (spaceRight < 150)
|
|
2947
|
-
setPosition('start');
|
|
2948
|
-
else
|
|
2949
|
-
setPosition('down');
|
|
2950
|
-
}, [asPortal, open, placement]);
|
|
2951
|
-
// Compute + track coords: portal mode
|
|
2952
|
-
// Re-runs whenever the menu opens and keeps coords fresh on scroll/resize
|
|
2953
|
-
useEffect(() => {
|
|
2954
|
-
if (!asPortal || !open)
|
|
3390
|
+
}, [open]);
|
|
3391
|
+
// Computes the initial position synchronously (before paint, to avoid a
|
|
3392
|
+
// flicker) and keeps it fresh while the menu is open and the viewport
|
|
3393
|
+
// scrolls or resizes (throttled to one update per frame, see above).
|
|
3394
|
+
useLayoutEffect(() => {
|
|
3395
|
+
if (!open)
|
|
2955
3396
|
return () => { };
|
|
2956
|
-
|
|
2957
|
-
|
|
2958
|
-
window.addEventListener('
|
|
2959
|
-
window.addEventListener('resize', update, { passive: true });
|
|
3397
|
+
updatePosition();
|
|
3398
|
+
window.addEventListener('scroll', scheduleUpdatePosition, { passive: true, capture: true });
|
|
3399
|
+
window.addEventListener('resize', scheduleUpdatePosition, { passive: true });
|
|
2960
3400
|
return () => {
|
|
2961
|
-
window.removeEventListener('scroll',
|
|
2962
|
-
window.removeEventListener('resize',
|
|
3401
|
+
window.removeEventListener('scroll', scheduleUpdatePosition, { capture: true });
|
|
3402
|
+
window.removeEventListener('resize', scheduleUpdatePosition);
|
|
3403
|
+
if (rafIdRef.current !== null) {
|
|
3404
|
+
window.cancelAnimationFrame(rafIdRef.current);
|
|
3405
|
+
rafIdRef.current = null;
|
|
3406
|
+
}
|
|
2963
3407
|
};
|
|
2964
|
-
}, [
|
|
3408
|
+
}, [open, updatePosition, scheduleUpdatePosition]);
|
|
2965
3409
|
let ToggleElement;
|
|
2966
3410
|
if (dropdownToggle) {
|
|
2967
3411
|
ToggleElement = typeof dropdownToggle === 'function'
|
|
@@ -2971,57 +3415,30 @@ function DDropdown({ actions, dropdownToggle, className, classNameMenu, asPortal
|
|
|
2971
3415
|
else {
|
|
2972
3416
|
ToggleElement = (jsx(DButtonIcon, { variant: "link", stopPropagationEnabled: false, "aria-label": "Toggle Dropdown", "aria-haspopup": "menu", "aria-expanded": open, onClick: toggle, icon: "MoreVertical" }));
|
|
2973
3417
|
}
|
|
2974
|
-
|
|
3418
|
+
// Until the first measurement is available, keep the menu off-screen but
|
|
3419
|
+
// measurable (visibility: hidden preserves layout, unlike display: none).
|
|
3420
|
+
const menuStyle = coords
|
|
2975
3421
|
? {
|
|
2976
3422
|
position: 'fixed',
|
|
2977
|
-
top:
|
|
2978
|
-
|
|
2979
|
-
|
|
2980
|
-
|
|
2981
|
-
minWidth: menuCoords.minWidth,
|
|
2982
|
-
maxHeight: menuCoords.maxHeight,
|
|
3423
|
+
top: coords.top,
|
|
3424
|
+
left: coords.left,
|
|
3425
|
+
minWidth: coords.minWidth,
|
|
3426
|
+
maxHeight: coords.maxHeight,
|
|
2983
3427
|
overflowY: 'auto',
|
|
2984
3428
|
zIndex: 1050,
|
|
2985
3429
|
transform: 'none',
|
|
3430
|
+
visibility: 'visible',
|
|
2986
3431
|
}
|
|
2987
|
-
:
|
|
2988
|
-
|
|
2989
|
-
|
|
2990
|
-
|
|
2991
|
-
|
|
2992
|
-
|
|
2993
|
-
|
|
2994
|
-
|
|
2995
|
-
|
|
2996
|
-
|
|
2997
|
-
inlineLeft = 'auto';
|
|
2998
|
-
}
|
|
2999
|
-
else if (resolvedInlinePosition === 'end') {
|
|
3000
|
-
inlineLeft = '100%';
|
|
3001
|
-
}
|
|
3002
|
-
let inlineRight = 'auto';
|
|
3003
|
-
if (resolvedInlinePosition === 'start') {
|
|
3004
|
-
inlineRight = '100%';
|
|
3005
|
-
}
|
|
3006
|
-
let inlineTransform = 'translateY(4px)';
|
|
3007
|
-
if (resolvedInlinePosition === 'up') {
|
|
3008
|
-
inlineTransform = 'translateY(-4px)';
|
|
3009
|
-
}
|
|
3010
|
-
else if (resolvedInlinePosition === 'start') {
|
|
3011
|
-
inlineTransform = 'translateX(-4px)';
|
|
3012
|
-
}
|
|
3013
|
-
else if (resolvedInlinePosition === 'end') {
|
|
3014
|
-
inlineTransform = 'translateX(4px)';
|
|
3015
|
-
}
|
|
3016
|
-
const inlineMenuStyle = {
|
|
3017
|
-
position: 'absolute',
|
|
3018
|
-
top: inlineTop,
|
|
3019
|
-
bottom: resolvedInlinePosition === 'up' ? '100%' : 'auto',
|
|
3020
|
-
left: inlineLeft,
|
|
3021
|
-
right: inlineRight,
|
|
3022
|
-
transform: inlineTransform,
|
|
3023
|
-
};
|
|
3024
|
-
const menuItems = (jsx("ul", { ref: menuRef, role: "menu", className: classNames('dropdown-menu p-2', { show: open }, classNameMenu), style: portalMenuStyle !== null && portalMenuStyle !== void 0 ? portalMenuStyle : inlineMenuStyle, children: actions.map((action, index) => {
|
|
3432
|
+
: {
|
|
3433
|
+
position: 'fixed',
|
|
3434
|
+
top: 0,
|
|
3435
|
+
left: 0,
|
|
3436
|
+
visibility: 'hidden',
|
|
3437
|
+
pointerEvents: 'none',
|
|
3438
|
+
zIndex: 1050,
|
|
3439
|
+
transform: 'none',
|
|
3440
|
+
};
|
|
3441
|
+
const menuItems = (jsx("ul", { ref: menuRef, role: "menu", className: classNames('dropdown-menu p-2', { show: open }, classNameMenu), style: menuStyle, children: actions.map((action, index) => {
|
|
3025
3442
|
if (action.isDivider) {
|
|
3026
3443
|
return jsx("hr", { className: "dropdown-divider" }, index);
|
|
3027
3444
|
}
|
|
@@ -3040,10 +3457,7 @@ function DDropdown({ actions, dropdownToggle, className, classNameMenu, asPortal
|
|
|
3040
3457
|
}
|
|
3041
3458
|
}, disabled: action.disabled, children: [action.icon && jsx(DIcon, { icon: action.icon, className: "me-2", size: "1rem" }), action.label] })) }, index));
|
|
3042
3459
|
}) }));
|
|
3043
|
-
|
|
3044
|
-
return (jsxs("div", { ref: toggleRef, className: classNames('dropdown', className), children: [ToggleElement, open && menuCoords && createPortal(menuItems, document.body)] }));
|
|
3045
|
-
}
|
|
3046
|
-
return (jsxs("div", { className: classNames(`dropdown drop-${resolvedInlinePosition}`, className), ref: dropdownRef, children: [ToggleElement, menuItems] }));
|
|
3460
|
+
return (jsxs("div", { ref: toggleRef, className: classNames(`dropdown drop-${resolvedSide} d-inline-block`, className), children: [ToggleElement, open && (asPortal ? createPortal(menuItems, document.body) : menuItems)] }));
|
|
3047
3461
|
}
|
|
3048
3462
|
|
|
3049
3463
|
function useScreenshot() {
|
|
@@ -3073,13 +3487,18 @@ function useScreenshot() {
|
|
|
3073
3487
|
|
|
3074
3488
|
function useScreenshotDownload() {
|
|
3075
3489
|
const { clipRef, takeBlob } = useScreenshot();
|
|
3076
|
-
const download = useCallback(async () => {
|
|
3077
|
-
const blob = await takeBlob();
|
|
3490
|
+
const download = useCallback(async (fileName = 'voucher') => {
|
|
3491
|
+
const blob = await takeBlob('image/jpeg');
|
|
3078
3492
|
const url = window.URL.createObjectURL(blob);
|
|
3079
3493
|
const link = window.document.createElement('a');
|
|
3080
3494
|
link.style.display = 'none';
|
|
3081
3495
|
link.href = url;
|
|
3082
|
-
|
|
3496
|
+
// Fall back to the default base name when the caller passes a blank/whitespace value,
|
|
3497
|
+
// so the file is never named just ".jpg".
|
|
3498
|
+
const safeFileName = fileName.trim() || 'voucher';
|
|
3499
|
+
// The extension is always appended by the hook to guarantee a valid image file,
|
|
3500
|
+
// regardless of what fileName the caller passes (e.g. "receipt.png" -> "receipt.png.jpg").
|
|
3501
|
+
link.download = `${safeFileName}.jpg`;
|
|
3083
3502
|
document.body.appendChild(link);
|
|
3084
3503
|
link.click();
|
|
3085
3504
|
document.body.removeChild(link);
|
|
@@ -3093,11 +3512,15 @@ function useScreenshotDownload() {
|
|
|
3093
3512
|
|
|
3094
3513
|
function useScreenshotWebShare() {
|
|
3095
3514
|
const { takeBlob, clipRef } = useScreenshot();
|
|
3096
|
-
const share = useCallback(async () => {
|
|
3097
|
-
const blob = await takeBlob();
|
|
3098
|
-
|
|
3099
|
-
|
|
3100
|
-
|
|
3515
|
+
const share = useCallback(async (fileName = 'voucher') => {
|
|
3516
|
+
const blob = await takeBlob('image/jpeg');
|
|
3517
|
+
// Fall back to the default base name when the caller passes a blank/whitespace value,
|
|
3518
|
+
// so the file is never named just ".jpeg".
|
|
3519
|
+
const safeFileName = fileName.trim() || 'voucher';
|
|
3520
|
+
// The extension is always appended by the hook to guarantee a valid image file,
|
|
3521
|
+
// regardless of what fileName the caller passes (e.g. "receipt.png" -> "receipt.png.jpeg").
|
|
3522
|
+
const image = new File([blob], `${safeFileName}.jpeg`, { type: 'image/jpeg' });
|
|
3523
|
+
if (!navigator.canShare || !navigator.canShare({ files: [image] })) {
|
|
3101
3524
|
window.print();
|
|
3102
3525
|
return;
|
|
3103
3526
|
}
|
|
@@ -3109,11 +3532,11 @@ function useScreenshotWebShare() {
|
|
|
3109
3532
|
};
|
|
3110
3533
|
}
|
|
3111
3534
|
|
|
3112
|
-
function DVoucher({ amount, amountDetails, icon, title, onError, message, downloadText = 'Download', shareText = 'Share', className, children, }) {
|
|
3535
|
+
function DVoucher({ amount, amountDetails, icon, title, onError, message, downloadText = 'Download', shareText = 'Share', fileName = 'voucher', hideActions = false, className, children, }) {
|
|
3113
3536
|
const { shareRef, share } = useScreenshotWebShare();
|
|
3114
3537
|
const { downloadRef, download } = useScreenshotDownload();
|
|
3115
3538
|
const handleShare = () => {
|
|
3116
|
-
share()
|
|
3539
|
+
share(fileName)
|
|
3117
3540
|
.catch(async (err) => {
|
|
3118
3541
|
if (onError) {
|
|
3119
3542
|
await onError(err);
|
|
@@ -3124,7 +3547,7 @@ function DVoucher({ amount, amountDetails, icon, title, onError, message, downlo
|
|
|
3124
3547
|
});
|
|
3125
3548
|
};
|
|
3126
3549
|
const handleDownload = () => {
|
|
3127
|
-
download()
|
|
3550
|
+
download(fileName)
|
|
3128
3551
|
.catch(async (err) => {
|
|
3129
3552
|
if (onError) {
|
|
3130
3553
|
await onError(err);
|
|
@@ -3152,80 +3575,36 @@ function DVoucher({ amount, amountDetails, icon, title, onError, message, downlo
|
|
|
3152
3575
|
return (jsx("div", { className: classNames('d-voucher', className), ref: (el) => {
|
|
3153
3576
|
shareRef.current = el;
|
|
3154
3577
|
downloadRef.current = el;
|
|
3155
|
-
}, children: jsxs("div", { children: [jsxs("div", { className: "d-voucher-header", children: [resolvedIconProps && (jsx(DIcon, Object.assign({}, resolvedIconProps))), jsxs("div", { className: "
|
|
3156
|
-
}
|
|
3157
|
-
|
|
3158
|
-
function useCountdown(seconds) {
|
|
3159
|
-
const [secondsLeft, setSecondsLeft] = useState(seconds);
|
|
3160
|
-
const [isActive, setIsActive] = useState(true);
|
|
3161
|
-
const resetCountdown = useCallback((newSeconds = seconds) => {
|
|
3162
|
-
setIsActive(false);
|
|
3163
|
-
setSecondsLeft(newSeconds);
|
|
3164
|
-
}, [seconds]);
|
|
3165
|
-
const restartCountdown = useCallback(() => {
|
|
3166
|
-
resetCountdown(seconds);
|
|
3167
|
-
setIsActive(true);
|
|
3168
|
-
}, [resetCountdown, seconds]);
|
|
3169
|
-
useEffect(() => {
|
|
3170
|
-
if (!isActive) {
|
|
3171
|
-
return () => { };
|
|
3172
|
-
}
|
|
3173
|
-
const interval = setInterval(() => {
|
|
3174
|
-
setSecondsLeft((prevSeconds) => {
|
|
3175
|
-
const newSeconds = prevSeconds - 1;
|
|
3176
|
-
if (newSeconds <= 0) {
|
|
3177
|
-
clearInterval(interval);
|
|
3178
|
-
setIsActive(false);
|
|
3179
|
-
return 0;
|
|
3180
|
-
}
|
|
3181
|
-
return newSeconds;
|
|
3182
|
-
});
|
|
3183
|
-
}, 1000);
|
|
3184
|
-
return () => clearInterval(interval);
|
|
3185
|
-
}, [isActive]);
|
|
3186
|
-
return { secondsLeft, restartCountdown };
|
|
3578
|
+
}, children: jsxs("div", { children: [jsxs("div", { className: "d-voucher-header", children: [resolvedIconProps && (jsx(DIcon, Object.assign({}, resolvedIconProps))), jsxs("div", { className: "d-voucher-title-group", children: [jsx("h3", { className: "d-voucher-title", children: title }), jsx("p", { className: "d-voucher-message", children: message })] })] }), amount && (jsxs("div", { className: "d-voucher-amount", children: [jsx("div", { className: classNames('d-voucher-amount-value', { 'd-voucher-amount-value-with-details': !!amountDetails }), children: amount }), amountDetails] })), jsx("hr", { className: "d-voucher-divider" }), children, !hideActions && (jsxs(Fragment, { children: [jsx("hr", { className: "my-4" }), jsxs("div", { className: "d-voucher-footer", children: [jsx(DButton, { onClick: handleShare, iconStart: "Share2", text: shareText, variant: "outline", size: "sm" }), jsx(DButton, { onClick: handleDownload, iconStart: "Download", text: downloadText, variant: "outline", size: "sm" })] })] }))] }) }));
|
|
3187
3579
|
}
|
|
3188
3580
|
|
|
3189
3581
|
const defaultMessage = (secs) => (secs > 0
|
|
3190
3582
|
? `Didn't get any code? Resend in: ${secs}s`
|
|
3191
3583
|
: "Didn't get any code?");
|
|
3192
|
-
function OtpCountdown({
|
|
3193
|
-
|
|
3194
|
-
return (jsxs("div", { className: "d-flex gap-2 align-items-center", children: [jsx("p", { className: "mb-0 flex-1", children: message ? message(secondsLeft) : defaultMessage(secondsLeft) }), jsx(DButton, { text: resendText, variant: "link", className: "text-nowrap", disabled: secondsLeft > 0, onClick: restartCountdown })] }));
|
|
3584
|
+
function OtpCountdown({ secondsLeft, restartCountdown, resendText, message, }) {
|
|
3585
|
+
return (jsxs("div", { className: "d-otp-countdown", children: [jsx("p", { className: "d-otp-countdown-text", children: message ? message(secondsLeft) : defaultMessage(secondsLeft) }), jsx(DButton, { text: resendText, variant: "link", className: "text-nowrap", disabled: secondsLeft > 0, onClick: restartCountdown })] }));
|
|
3195
3586
|
}
|
|
3196
3587
|
|
|
3197
3588
|
const TEXT_PROPS = {
|
|
3198
3589
|
resend: 'Resend',
|
|
3199
|
-
resendText: 'Resend
|
|
3590
|
+
resendText: 'Resend',
|
|
3200
3591
|
submit: 'Authorize and continue',
|
|
3201
3592
|
title: 'We will send you a 6-digit code to your associated phone number so you can continue with your request.',
|
|
3593
|
+
invalidCode: 'Invalid code, please try again.',
|
|
3202
3594
|
contact: (jsxs(Fragment, { children: [jsx("span", { children: "Problems with your digital token? Contact us" }), ' ', jsx("a", { href: "https://www.modyo.com", className: "link-primary text-nowrap", target: "_blank", rel: "noreferrer", children: "Contact us" })] })),
|
|
3203
3595
|
};
|
|
3204
3596
|
function DOtp({ className, action, isLoading, otpSize = 6, texts = TEXT_PROPS, seconds = 15, }) {
|
|
3205
|
-
const
|
|
3206
|
-
|
|
3207
|
-
|
|
3208
|
-
if (otp.length < otpSize) {
|
|
3209
|
-
setInvalid(true);
|
|
3210
|
-
return;
|
|
3211
|
-
}
|
|
3212
|
-
setInvalid(false);
|
|
3213
|
-
await action();
|
|
3214
|
-
}, [
|
|
3215
|
-
otp.length,
|
|
3216
|
-
action,
|
|
3217
|
-
otpSize,
|
|
3218
|
-
]);
|
|
3219
|
-
return (jsxs("div", { className: className, children: [jsx("p", { children: texts.title }), jsxs("div", { className: "d-flex flex-column gap-6 pb-4 px-3", children: [jsxs("div", { className: "d-flex flex-column gap-6", children: [jsx(DInputPin, { className: "modal-otp-pin", characters: otpSize, onChange: (e) => setOtp(e), invalid: invalid && otp.length < otpSize, placeholder: "0" }), jsx(OtpCountdown, { seconds: seconds, resendText: texts.resend })] }), jsx("hr", { className: "m-0" }), jsxs("div", { className: "d-flex flex-column flex-lg-row gap-4 align-items-center", children: [jsx(DButton, { text: texts.submit, onClick: () => {
|
|
3220
|
-
handler().catch((err) => {
|
|
3597
|
+
const { setOtp, invalid, submit, isLoading: isSubmitting, secondsLeft, restartCountdown, } = useOtp({ action, otpSize, seconds });
|
|
3598
|
+
return (jsxs("div", { className: className, children: [jsx("p", { children: texts.title }), jsxs("div", { className: "d-otp d-otp-content", children: [jsxs("div", { className: "d-otp-fields", children: [jsx(DInputPin, { className: "modal-otp-pin", characters: otpSize, onChange: (e) => setOtp(e), invalid: invalid, hint: invalid ? texts.invalidCode : undefined, placeholder: "0" }), jsx(OtpCountdown, { secondsLeft: secondsLeft, restartCountdown: restartCountdown, resendText: texts.resendText })] }), jsx("hr", { className: "d-otp-divider" }), jsxs("div", { className: "d-otp-footer", children: [jsx(DButton, { text: texts.submit, onClick: () => {
|
|
3599
|
+
submit().catch((err) => {
|
|
3221
3600
|
// eslint-disable-next-line no-console
|
|
3222
3601
|
console.error('Error in DOtp action:', err);
|
|
3223
3602
|
});
|
|
3224
|
-
}, loading: isLoading }), jsx("p", { className: "
|
|
3603
|
+
}, loading: isLoading || isSubmitting }), jsx("p", { className: "d-otp-contact", children: texts.contact })] })] })] }));
|
|
3225
3604
|
}
|
|
3226
3605
|
|
|
3227
3606
|
function DefaultErrorBoundary({ resetErrorBoundary }) {
|
|
3228
|
-
return (jsx(DAlert, { color: "danger", showClose: false, children: jsxs("div", { className: "d-
|
|
3607
|
+
return (jsx(DAlert, { color: "danger", showClose: false, children: jsxs("div", { className: "d-error-boundary-content", children: [jsx("span", { children: "An unexpected error occurred." }), jsx(DButton, { color: "secondary", variant: "outline", size: "sm", onClick: resetErrorBoundary, children: "Retry" })] }) }));
|
|
3229
3608
|
}
|
|
3230
3609
|
|
|
3231
3610
|
function DErrorBoundary({ name, fallback, resetKeys, onReset, onError, children, }) {
|
|
@@ -3243,15 +3622,15 @@ function DErrorBoundary({ name, fallback, resetKeys, onReset, onError, children,
|
|
|
3243
3622
|
}
|
|
3244
3623
|
|
|
3245
3624
|
function ErrorState({ message, onRetry, retryMessage = 'Retry', color = 'danger', }) {
|
|
3246
|
-
return (jsxs(DAlert, { color: color, className: "d-
|
|
3625
|
+
return (jsxs(DAlert, { color: color, className: "d-error-state", children: [jsx("div", { className: "d-error-state-content", children: jsx("p", { className: "d-error-state-message", children: message !== null && message !== void 0 ? message : 'An unexpected error occurred.' }) }), onRetry && (jsx(DButton, { onClick: onRetry, text: retryMessage, variant: "outline", iconStart: "RefreshCw" }))] }));
|
|
3247
3626
|
}
|
|
3248
3627
|
|
|
3249
3628
|
function EmptyState({ message, icon = 'FileText', actionText, onAction, }) {
|
|
3250
|
-
return (jsxs("div", { className: "d-
|
|
3629
|
+
return (jsxs("div", { className: "d-empty-state", children: [jsx(DIcon, { icon: icon, size: "3rem", className: "d-empty-state-icon" }), jsx("p", { className: "d-empty-state-message", children: message !== null && message !== void 0 ? message : 'No data available.' }), actionText && onAction && (jsx(DButton, { onClick: onAction, text: actionText, variant: "outline" }))] }));
|
|
3251
3630
|
}
|
|
3252
3631
|
|
|
3253
3632
|
function LoadingState({ ariaLabel = 'Loading...', className }) {
|
|
3254
|
-
return (jsx("div", { className: `d-
|
|
3633
|
+
return (jsx("div", { className: `d-loading-state ${className || ''}`.trim(), "aria-busy": "true", "aria-live": "polite", children: jsx("span", { className: "spinner-border", role: "status", "aria-label": ariaLabel }) }));
|
|
3255
3634
|
}
|
|
3256
3635
|
|
|
3257
3636
|
function render(renderable) {
|
|
@@ -3310,7 +3689,7 @@ function DConfirmModalUI({ entry }) {
|
|
|
3310
3689
|
}
|
|
3311
3690
|
});
|
|
3312
3691
|
}, [onConfirmAction]);
|
|
3313
|
-
return (jsxs(DModal$1, { name: entry.id, size: "lg", className: `confirm-modal ${critical ? 'critical-modal' : ''}`, children: [jsx(DModal$1.Header, { onClose: handleClose, showCloseButton: true, children: jsx("h5", { className: "fw-bold", children: title }) }), jsxs(DModal$1.Body, { className: "
|
|
3692
|
+
return (jsxs(DModal$1, { name: entry.id, size: "lg", className: `confirm-modal ${critical ? 'critical-modal' : ''}`, children: [jsx(DModal$1.Header, { onClose: handleClose, showCloseButton: true, children: jsx("h5", { className: "fw-bold", children: title }) }), jsxs(DModal$1.Body, { className: "d-confirm-modal-body", children: [jsx("p", { className: "d-confirm-modal-message", children: message }), critical && (jsx(ForwardedDInput, { type: "text", label: critical.codeLabel || 'Confirmation code', placeholder: critical.inputPlaceholder, value: confirmationCode, onChange: (value) => setConfirmationCode(value), className: "d-confirm-modal-field", autoFocus: true }))] }), jsxs(DModal$1.Footer, { children: [jsx(DButton, { text: cancelLabel, variant: "outline", color: "secondary", onClick: handleClose, disabled: internalLoading }), jsx(DButton, { text: confirmLabel, color: confirmColor, onClick: handleConfirmClick, disabled: isConfirmDisabled, loading: internalLoading })] })] }));
|
|
3314
3693
|
}
|
|
3315
3694
|
|
|
3316
3695
|
/**
|
|
@@ -3363,5 +3742,5 @@ function DConfirmModalContainer({ nodeId }) {
|
|
|
3363
3742
|
return createPortal(jsx(AnimatePresence, { children: entries.map((entry) => (jsxs(motion.div, { initial: { opacity: 0 }, animate: { opacity: 1 }, exit: { opacity: 0, transition: { delay: 0.3 } }, transition: { duration: 0.15, ease: 'linear' }, children: [jsx("div", { className: "backdrop backdrop-confirm-modal", onClick: entry.onCloseAction, role: "presentation" }), jsx(DConfirmModalUI, { entry: entry })] }, entry.id))) }), portalNode);
|
|
3364
3743
|
}
|
|
3365
3744
|
|
|
3366
|
-
export { DAlert, DAvatar, DBadge, DBox, DBoxFile, DButton, DButtonIcon, DCard$1 as DCard, DCardBody, DCardFooter, DCardHeader, DCarousel$1 as DCarousel, DCarouselSlide, DChip, DCollapse, DConfirmModalContainer, DContext, DContextProvider, DCreditCard, DCurrencyText, DDataStateWrapper, DDatePicker, DDropdown, DErrorBoundary, DIcon, DIconBase, ForwardedDInput as DInput, DInputCheck, ForwardedDInputCounter as DInputCounter, ForwardedDInputCurrency as DInputCurrency, ForwardedDInputMask as DInputMask, ForwardedDInputPassword as DInputPassword, ForwardedDInputPhone as DInputPhone, DInputPin, ForwardedDInputRange as DInputRange, ForwardedDInputSearch as DInputSearch, DInputSelect, DInputSwitch, DLayout$1 as DLayout, DLayoutPane, DListGroup$1 as DListGroup, DListGroupItem, DModal$1 as DModal, DModalBody, DModalFooter, DModalHeader, DOffcanvas$1 as DOffcanvas, DOffcanvasBody, DOffcanvasFooter, DOffcanvasHeader, DOtp, DPaginator, DPasswordStrengthMeter, DPopover, DProgress, DSelect$1 as DSelect, DStepper, DStepper$2 as DStepperDesktop, DStepper$1 as DStepperMobile, DTabContent, DTabs$1 as DTabs, DTimeline, DToast$1 as DToast, DToastContainer, DTooltip, DVoucher, EmptyState, ErrorState, LoadingState, changeQueryString, checkMediaQuery, configureI8n as configureI18n, formatCurrency, getCssVariable, getQueryString, subscribeToMediaQuery, useConfirmModal, useDContext, useDPortalContext, useDToast, useDisableBodyScrollEffect, useDisableInputWheel, useFormatCurrency, useInputCurrency, useItemSelection, useMediaBreakpointUpLg, useMediaBreakpointUpMd, useMediaBreakpointUpSm, useMediaBreakpointUpXl, useMediaBreakpointUpXs, useMediaBreakpointUpXxl, useMediaQuery, useProvidedRefOrCreate, useStackState, useTabContext, validatePhoneNumber };
|
|
3745
|
+
export { DAlert, DAvatar, DBadge, DBox, DBoxFile, DButton, DButtonIcon, DCard$1 as DCard, DCardBody, DCardFooter, DCardHeader, DCarousel$1 as DCarousel, DCarouselSlide, DChip, DCollapse, DConfirmModalContainer, DContext, DContextProvider, DCreditCard, DCurrencyText, DDataStateWrapper, DDatePicker, DDropdown, DErrorBoundary, DIcon, DIconBase, ForwardedDInput as DInput, DInputCheck, ForwardedDInputCounter as DInputCounter, ForwardedDInputCurrency as DInputCurrency, ForwardedDInputMask as DInputMask, ForwardedDInputPassword as DInputPassword, ForwardedDInputPhone as DInputPhone, DInputPin, ForwardedDInputRange as DInputRange, ForwardedDInputSearch as DInputSearch, DInputSelect, DInputSwitch, DLayout$1 as DLayout, DLayoutPane, DListGroup$1 as DListGroup, DListGroupItem, DModal$1 as DModal, DModalBody, DModalFooter, DModalHeader, DOffcanvas$1 as DOffcanvas, DOffcanvasBody, DOffcanvasFooter, DOffcanvasHeader, DOtp, DPaginator, DPasswordStrengthMeter, DPopover, DProgress, DSelect$1 as DSelect, DStepper, DStepper$2 as DStepperDesktop, DStepper$1 as DStepperMobile, DTabContent, DTabs$1 as DTabs, DTimeline, DToast$1 as DToast, DToastContainer, DTooltip, DVoucher, EmptyState, ErrorState, LoadingState, buildUrl, changeQueryString, checkMediaQuery, configureI8n as configureI18n, formatCurrency, getCssVariable, getQueryString, sanitizeHref, subscribeToMediaQuery, useConfirmModal, useCountdown, useDContext, useDPortalContext, useDToast, useDisableBodyScrollEffect, useDisableInputWheel, useFormatCurrency, useInputCurrency, useItemSelection, useMediaBreakpointUpLg, useMediaBreakpointUpMd, useMediaBreakpointUpSm, useMediaBreakpointUpXl, useMediaBreakpointUpXs, useMediaBreakpointUpXxl, useMediaQuery, useOtp, useProvidedRefOrCreate, useScreenshot, useScreenshotDownload, useScreenshotWebShare, useStackState, useTabContext, validatePhoneNumber };
|
|
3367
3746
|
//# sourceMappingURL=index.esm.js.map
|