@dynamic-framework/ui-react 2.0.0-dev.4 → 2.0.0-dev.5
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-non-root.css +65 -45
- package/dist/css/dynamic-ui-non-root.min.css +2 -2
- package/dist/css/dynamic-ui-root.css +1 -1
- package/dist/css/dynamic-ui-root.min.css +1 -1
- package/dist/css/dynamic-ui.css +65 -45
- package/dist/css/dynamic-ui.min.css +2 -2
- package/dist/index.esm.js +231 -23
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +232 -22
- package/dist/index.js.map +1 -1
- package/dist/types/components/DButton/DButton.d.ts +7 -17
- package/dist/types/components/DInputCheck/DInputCheck.d.ts +2 -1
- package/dist/types/components/DInputSwitch/DInputSwitch.d.ts +2 -1
- package/dist/types/components/DPasswordStrengthMeter/DPasswordStrengthMeter.d.ts +23 -0
- package/dist/types/components/DPasswordStrengthMeter/PasswordCheckItem.d.ts +7 -0
- package/dist/types/components/DPasswordStrengthMeter/PasswordCheckList.d.ts +14 -0
- package/dist/types/components/DPasswordStrengthMeter/PasswordStrength.d.ts +6 -0
- package/dist/types/components/DPasswordStrengthMeter/index.d.ts +3 -0
- package/dist/types/components/DVoucher/DVoucher.d.ts +14 -0
- package/dist/types/components/DVoucher/hooks/useScreenshot.d.ts +5 -0
- package/dist/types/components/DVoucher/hooks/useScreenshotDownload.d.ts +5 -0
- package/dist/types/components/DVoucher/hooks/useScreenshotWebShare.d.ts +5 -0
- package/dist/types/components/DVoucher/index.d.ts +2 -0
- package/dist/types/components/index.d.ts +3 -0
- package/jest/setup.js +0 -2
- package/package.json +6 -4
- package/src/style/abstracts/variables/_buttons.scss +2 -0
- package/src/style/base/_buttons.scss +56 -65
- package/src/style/components/_+import.scss +1 -0
- package/src/style/components/_d-voucher.scss +30 -0
package/dist/index.js
CHANGED
|
@@ -18,6 +18,7 @@ var react = require('@floating-ui/react');
|
|
|
18
18
|
var reactHotToast = require('react-hot-toast');
|
|
19
19
|
var reactInternationalPhone = require('react-international-phone');
|
|
20
20
|
var googleLibphonenumber = require('google-libphonenumber');
|
|
21
|
+
var html2canvas = require('html2canvas');
|
|
21
22
|
var i18n = require('i18next');
|
|
22
23
|
var reactI18next = require('react-i18next');
|
|
23
24
|
|
|
@@ -889,26 +890,59 @@ function DBoxFile(_a) {
|
|
|
889
890
|
: children })] })) })), !!files.length && (jsxRuntime.jsx("ul", { className: "d-box-files", children: files.map((file, index) => (jsxRuntime.jsx(ForwardedDInput, { value: file.name, iconStart: "paperclip", iconEnd: "trash", readOnly: true, onIconEndClick: () => handleRemoveFile(index) }, `${file.name} ${index}`))) }))] }));
|
|
890
891
|
}
|
|
891
892
|
|
|
892
|
-
|
|
893
|
-
const
|
|
893
|
+
const DButton = React.forwardRef((props, ref) => {
|
|
894
|
+
const { color = 'primary', size, variant, text, children, iconStart, iconStartFamilyClass, iconStartFamilyPrefix, iconStartMaterialStyle, iconEnd, iconEndFamilyClass, iconEndFamilyPrefix, iconEndMaterialStyle, loading = false, loadingText, loadingAriaLabel, disabled = false, className, style, dataAttributes, onClick, type = 'button' } = props, rest = tslib.__rest(props, ["color", "size", "variant", "text", "children", "iconStart", "iconStartFamilyClass", "iconStartFamilyPrefix", "iconStartMaterialStyle", "iconEnd", "iconEndFamilyClass", "iconEndFamilyPrefix", "iconEndMaterialStyle", "loading", "loadingText", "loadingAriaLabel", "disabled", "className", "style", "dataAttributes", "onClick", "type"]);
|
|
895
|
+
const [buttonWidth, setButtonWidth] = React.useState();
|
|
896
|
+
const buttonRef = React.useRef(null);
|
|
897
|
+
const isDisabled = React.useMemo(() => disabled || loading, [disabled, loading]);
|
|
898
|
+
const content = React.useMemo(() => children || text, [children, text]);
|
|
899
|
+
const classes = React.useMemo(() => {
|
|
894
900
|
const variantClass = variant
|
|
895
901
|
? `btn-${variant}-${color}`
|
|
896
902
|
: `btn-${color}`;
|
|
897
|
-
return
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
903
|
+
return {
|
|
904
|
+
btn: true,
|
|
905
|
+
[variantClass]: true,
|
|
906
|
+
[`btn-${size}`]: !!size,
|
|
907
|
+
loading,
|
|
908
|
+
};
|
|
909
|
+
}, [variant, color, size, loading]);
|
|
910
|
+
const ariaLabel = React.useMemo(() => {
|
|
911
|
+
const ariaLabelProp = rest['aria-label'];
|
|
912
|
+
return loading
|
|
913
|
+
? loadingAriaLabel || ariaLabelProp || text
|
|
914
|
+
: ariaLabelProp || text;
|
|
915
|
+
}, [loading, loadingAriaLabel, rest, text]);
|
|
916
|
+
const handleClick = React.useCallback((event) => {
|
|
917
|
+
if (disabled || loading) {
|
|
918
|
+
event.preventDefault();
|
|
919
|
+
return;
|
|
902
920
|
}
|
|
903
921
|
onClick === null || onClick === void 0 ? void 0 : onClick(event);
|
|
904
|
-
}, [
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
922
|
+
}, [disabled, loading, onClick]);
|
|
923
|
+
React.useEffect(() => {
|
|
924
|
+
if (!loading && buttonRef.current) {
|
|
925
|
+
const width = buttonRef.current.offsetWidth;
|
|
926
|
+
if (width > 0)
|
|
927
|
+
setButtonWidth(width);
|
|
928
|
+
}
|
|
929
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
930
|
+
}, [content, iconEnd, iconStart]);
|
|
931
|
+
return (jsxRuntime.jsxs("button", Object.assign({ ref: (node) => {
|
|
932
|
+
buttonRef.current = node;
|
|
933
|
+
if (typeof ref === 'function')
|
|
934
|
+
ref(node);
|
|
935
|
+
// eslint-disable-next-line max-len
|
|
936
|
+
// eslint-disable-next-line no-param-reassign, @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access
|
|
937
|
+
else if (ref)
|
|
938
|
+
ref.current = node;
|
|
939
|
+
},
|
|
940
|
+
// eslint-disable-next-line react/button-has-type
|
|
941
|
+
type: type, className: classNames(classes, className), style: Object.assign(Object.assign({}, style), (loading && buttonWidth
|
|
942
|
+
? { minWidth: `${buttonWidth}px` }
|
|
943
|
+
: undefined)), disabled: isDisabled, "aria-label": ariaLabel, "aria-busy": loading, "aria-disabled": isDisabled, onClick: handleClick }, dataAttributes, rest, { children: [loading && (jsxRuntime.jsxs("span", { className: "btn-loading", children: [jsxRuntime.jsx("span", { className: "spinner-border spinner-border-sm", "aria-hidden": "true" }), loadingText && jsxRuntime.jsx("span", { role: "status", children: loadingText })] })), !loading && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [iconStart && (jsxRuntime.jsx(DIcon, { icon: iconStart, familyClass: iconStartFamilyClass, familyPrefix: iconStartFamilyPrefix, materialStyle: iconStartMaterialStyle })), content, iconEnd && (jsxRuntime.jsx(DIcon, { icon: iconEnd, familyClass: iconEndFamilyClass, familyPrefix: iconEndFamilyPrefix, materialStyle: iconEndMaterialStyle }))] }))] })));
|
|
944
|
+
});
|
|
945
|
+
DButton.displayName = 'DButton';
|
|
912
946
|
|
|
913
947
|
function DButtonIcon({ id, icon, size, className, variant, state, loadingAriaLabel, iconMaterialStyle, ariaLabel, color = 'primary', type = 'button', loading = false, disabled = false, stopPropagationEnabled = true, style, iconFamilyClass, iconFamilyPrefix, dataAttributes, onClick, }) {
|
|
914
948
|
const generateClasses = React.useMemo(() => {
|
|
@@ -1043,7 +1077,7 @@ const ForwardedDDatePickerInput = React.forwardRef(DDatePickerInput);
|
|
|
1043
1077
|
ForwardedDDatePickerInput.displayName = 'DDatePickerInput';
|
|
1044
1078
|
|
|
1045
1079
|
function DInputCheck(_a) {
|
|
1046
|
-
var { id: idProp, type, name, label, ariaLabel, checked = false, disabled = false, invalid = false, valid = false, indeterminate, value, hint, onChange, className, style, dataAttributes } = _a, props = tslib.__rest(_a, ["id", "type", "name", "label", "ariaLabel", "checked", "disabled", "invalid", "valid", "indeterminate", "value", "hint", "onChange", "className", "style", "dataAttributes"]);
|
|
1080
|
+
var { id: idProp, type, name, label, ariaLabel, checked = false, disabled = false, invalid = false, valid = false, indeterminate, inputClassName, value, hint, onChange, className, style, dataAttributes } = _a, props = tslib.__rest(_a, ["id", "type", "name", "label", "ariaLabel", "checked", "disabled", "invalid", "valid", "indeterminate", "inputClassName", "value", "hint", "onChange", "className", "style", "dataAttributes"]);
|
|
1047
1081
|
const innerRef = React.useRef(null);
|
|
1048
1082
|
const innerId = React.useId();
|
|
1049
1083
|
const id = React.useMemo(() => idProp || innerId, [idProp, innerId]);
|
|
@@ -1071,11 +1105,11 @@ function DInputCheck(_a) {
|
|
|
1071
1105
|
const inputComponent = React.useMemo(() => (jsxRuntime.jsx("input", Object.assign({ ref: innerRef, onChange: handleChange, className: classNames('form-check-input', {
|
|
1072
1106
|
'is-invalid': invalid,
|
|
1073
1107
|
'is-valid': valid,
|
|
1074
|
-
},
|
|
1108
|
+
}, inputClassName), style: style, id: id, disabled: disabled, type: type, name: name, value: value, "aria-label": ariaLabel }, ariaDescribedby && { 'aria-describedby': ariaDescribedby }, props))), [
|
|
1075
1109
|
handleChange,
|
|
1076
1110
|
invalid,
|
|
1077
1111
|
valid,
|
|
1078
|
-
|
|
1112
|
+
inputClassName,
|
|
1079
1113
|
style,
|
|
1080
1114
|
id,
|
|
1081
1115
|
disabled,
|
|
@@ -1089,7 +1123,7 @@ function DInputCheck(_a) {
|
|
|
1089
1123
|
if (!label) {
|
|
1090
1124
|
return inputComponent;
|
|
1091
1125
|
}
|
|
1092
|
-
return (jsxRuntime.jsxs("div", Object.assign({ className:
|
|
1126
|
+
return (jsxRuntime.jsxs("div", Object.assign({ className: classNames('form-check', className) }, dataAttributes, { children: [inputComponent, jsxRuntime.jsx("label", { className: "form-check-label", htmlFor: id, children: label }), hint && (jsxRuntime.jsx("div", { className: "form-text", id: `${id}Hint`, children: hint }))] })));
|
|
1093
1127
|
}
|
|
1094
1128
|
|
|
1095
1129
|
function DSelectOptionCheck(_a) {
|
|
@@ -1513,6 +1547,86 @@ function DInputPassword(_a, ref) {
|
|
|
1513
1547
|
const ForwardedDInputPassword = React.forwardRef(DInputPassword);
|
|
1514
1548
|
ForwardedDInputPassword.displayName = 'DInputPassword';
|
|
1515
1549
|
|
|
1550
|
+
function PasswordCheckItem({ password, regex, text, }) {
|
|
1551
|
+
const isValid = regex.test(password);
|
|
1552
|
+
return (jsxRuntime.jsxs("li", { className: "d-flex gap-2 align-items-start small text-gray-600", children: [jsxRuntime.jsx(DIcon, { className: classNames('flex-shrink-0', isValid ? 'text-success' : 'text-gray-300'), icon: isValid ? 'CircleCheck' : 'Circle', size: "16px" }), jsxRuntime.jsx("span", { className: classNames({ 'text-success': isValid }), children: text })] }));
|
|
1553
|
+
}
|
|
1554
|
+
|
|
1555
|
+
const getColorClass = (strength, total) => {
|
|
1556
|
+
const percentage = total > 0 ? strength / total : 0;
|
|
1557
|
+
if (percentage === 0)
|
|
1558
|
+
return 'bg-gray-200';
|
|
1559
|
+
if (percentage <= 0.25)
|
|
1560
|
+
return 'bg-danger';
|
|
1561
|
+
if (percentage <= 0.5)
|
|
1562
|
+
return 'bg-warning';
|
|
1563
|
+
if (percentage <= 0.75)
|
|
1564
|
+
return 'bg-info';
|
|
1565
|
+
return 'bg-success';
|
|
1566
|
+
};
|
|
1567
|
+
function PasswordStrengthBar({ strength, total }) {
|
|
1568
|
+
const percentage = total > 0 ? (strength / total) * 100 : 0;
|
|
1569
|
+
return (jsxRuntime.jsx("div", { className: "w-100 rounded-3 overflow-hidden bg-gray-100 mb-2", style: { height: '8px' }, children: jsxRuntime.jsx("div", { className: `h-100 ${getColorClass(strength, total)}`, style: {
|
|
1570
|
+
width: `${percentage}%`,
|
|
1571
|
+
transition: 'width 0.3s ease-in-out',
|
|
1572
|
+
} }) }));
|
|
1573
|
+
}
|
|
1574
|
+
|
|
1575
|
+
const CHECK_REGEX = {
|
|
1576
|
+
uppercase: /[A-Z]/,
|
|
1577
|
+
lowercase: /[a-z]/,
|
|
1578
|
+
number: /\d/,
|
|
1579
|
+
specialChar: /[~!@#$^*\-_=[\]{}|;,.?]/,
|
|
1580
|
+
};
|
|
1581
|
+
function PasswordChecksList({ password, validationMessages, enabledChecks, }) {
|
|
1582
|
+
const allChecks = [
|
|
1583
|
+
{
|
|
1584
|
+
key: 'uppercase',
|
|
1585
|
+
regex: CHECK_REGEX.uppercase,
|
|
1586
|
+
text: validationMessages.uppercaseLetter,
|
|
1587
|
+
},
|
|
1588
|
+
{
|
|
1589
|
+
key: 'lowercase',
|
|
1590
|
+
regex: CHECK_REGEX.lowercase,
|
|
1591
|
+
text: validationMessages.lowercaseLetter,
|
|
1592
|
+
},
|
|
1593
|
+
{
|
|
1594
|
+
key: 'number',
|
|
1595
|
+
regex: CHECK_REGEX.number,
|
|
1596
|
+
text: validationMessages.number,
|
|
1597
|
+
},
|
|
1598
|
+
{
|
|
1599
|
+
key: 'specialChar',
|
|
1600
|
+
regex: CHECK_REGEX.specialChar,
|
|
1601
|
+
text: validationMessages.especialChar,
|
|
1602
|
+
},
|
|
1603
|
+
];
|
|
1604
|
+
const passwordChecks = allChecks.filter((check) => enabledChecks.includes(check.key));
|
|
1605
|
+
const passed = passwordChecks.filter((r) => r.regex.test(password)).length;
|
|
1606
|
+
const total = passwordChecks.length;
|
|
1607
|
+
return (jsxRuntime.jsxs("div", { className: "mt-2", children: [jsxRuntime.jsx(PasswordStrengthBar, { strength: passed, total: total }), jsxRuntime.jsx("ul", { className: "list-unstyled m-0 d-flex flex-column gap-2", children: passwordChecks.map(({ key, regex, text }) => (jsxRuntime.jsx(PasswordCheckItem, { password: password, regex: regex, text: text }, key))) })] }));
|
|
1608
|
+
}
|
|
1609
|
+
|
|
1610
|
+
const DEFAULT_VALIDATION_MESSAGES = {
|
|
1611
|
+
number: 'At least one number',
|
|
1612
|
+
lowercaseLetter: 'At least one lowercase letter',
|
|
1613
|
+
uppercaseLetter: 'At least one uppercase letter',
|
|
1614
|
+
especialChar: 'At least one of these special characters: ~!@#$^*-_=[]{}|;,.?',
|
|
1615
|
+
notMatch: 'The password confirmation and the new password do not match.',
|
|
1616
|
+
};
|
|
1617
|
+
const DEFAULT_ENABLED_CHECKS = ['uppercase', 'lowercase', 'number', 'specialChar'];
|
|
1618
|
+
function DPasswordStrengthMeter({ id, label = 'Password', placeholder, value = '', name, disabled = false, invalid = false, validationMessages = DEFAULT_VALIDATION_MESSAGES, enabledChecks = DEFAULT_ENABLED_CHECKS, className, style, dataAttributes, onChange, }) {
|
|
1619
|
+
const [password, setPassword] = React.useState(value);
|
|
1620
|
+
React.useEffect(() => {
|
|
1621
|
+
setPassword(value);
|
|
1622
|
+
}, [value]);
|
|
1623
|
+
const handleChange = (newValue) => {
|
|
1624
|
+
setPassword(newValue);
|
|
1625
|
+
onChange === null || onChange === void 0 ? void 0 : onChange(newValue);
|
|
1626
|
+
};
|
|
1627
|
+
return (jsxRuntime.jsxs("div", Object.assign({ className: className, style: style }, dataAttributes, { children: [jsxRuntime.jsx(ForwardedDInputPassword, { id: id, label: label, placeholder: placeholder, value: password, name: name, disabled: disabled, invalid: invalid, onChange: handleChange }), jsxRuntime.jsx(PasswordChecksList, { password: password, validationMessages: validationMessages, enabledChecks: enabledChecks })] })));
|
|
1628
|
+
}
|
|
1629
|
+
|
|
1516
1630
|
function DInputPin({ id: idProp, label = '', placeholder, type = 'text', disabled = false, loading = false, secret = false, characters = 4, innerInputMode = 'text', hint, invalid = false, valid = false, className, style, dataAttributes, onChange, }) {
|
|
1517
1631
|
const innerId = React.useId();
|
|
1518
1632
|
const id = React.useMemo(() => idProp || innerId, [idProp, innerId]);
|
|
@@ -1676,7 +1790,7 @@ function DInputSelect({ id: idProp, name, label = '', className, style, options
|
|
|
1676
1790
|
}), children: [iconStart && (jsxRuntime.jsx("button", { type: "button", className: "input-group-text", id: `${id}Start`, onClick: iconStartClickHandler, disabled: disabled || loading, "aria-label": iconStartAriaLabel, children: iconStart && (jsxRuntime.jsx(DIcon, { icon: iconStart, familyClass: iconStartFamilyClass, familyPrefix: iconStartFamilyPrefix })) })), dynamicComponent, iconEnd && !loading && (jsxRuntime.jsx("button", { type: "button", className: "input-group-text", id: `${id}End`, onClick: iconEndClickHandler, disabled: disabled || loading, "aria-label": iconEndAriaLabel, children: iconEnd && (jsxRuntime.jsx(DIcon, { icon: iconEnd, familyClass: iconEndFamilyClass, familyPrefix: iconEndFamilyPrefix })) })), loading && (jsxRuntime.jsx("div", { className: "input-group-text form-control-icon loading", children: jsxRuntime.jsx("span", { className: "spinner-border spinner-border-sm", role: "status", "aria-hidden": "true", children: jsxRuntime.jsx("span", { className: "visually-hidden", children: "Loading..." }) }) }))] }), hint && (jsxRuntime.jsx("div", { className: "form-text", id: `${id}Hint`, children: hint }))] })));
|
|
1677
1791
|
}
|
|
1678
1792
|
|
|
1679
|
-
function DInputSwitch({ id: idProp, label, ariaLabel, name, checked, disabled, invalid = false, valid = false, readonly, className, style, dataAttributes, onChange, }) {
|
|
1793
|
+
function DInputSwitch({ id: idProp, label, ariaLabel, name, checked, disabled, invalid = false, valid = false, readonly, className, style, dataAttributes, inputClassName, onChange, }) {
|
|
1680
1794
|
const innerId = React.useId();
|
|
1681
1795
|
const id = React.useMemo(() => idProp || innerId, [idProp, innerId]);
|
|
1682
1796
|
const [internalIsChecked, setInternalIsChecked] = React.useState(checked);
|
|
@@ -1688,10 +1802,10 @@ function DInputSwitch({ id: idProp, label, ariaLabel, name, checked, disabled, i
|
|
|
1688
1802
|
setInternalIsChecked(value);
|
|
1689
1803
|
onChange === null || onChange === void 0 ? void 0 : onChange(value);
|
|
1690
1804
|
}, [onChange]);
|
|
1691
|
-
return (jsxRuntime.jsxs("div", Object.assign({ className:
|
|
1805
|
+
return (jsxRuntime.jsxs("div", Object.assign({ className: classNames('form-check', className) }, dataAttributes, { children: [jsxRuntime.jsx("input", { id: id, name: name, onChange: readonly ? () => false : changeHandler, className: classNames('form-check-input', {
|
|
1692
1806
|
'is-invalid': invalid,
|
|
1693
1807
|
'is-valid': valid,
|
|
1694
|
-
},
|
|
1808
|
+
}, inputClassName), style: style, type: "checkbox", role: "switch", checked: internalIsChecked, disabled: disabled, "aria-label": ariaLabel }), label && (jsxRuntime.jsx("label", { className: "form-check-label", htmlFor: id, children: label }))] })));
|
|
1695
1809
|
}
|
|
1696
1810
|
|
|
1697
1811
|
function DInputRange(_a, ref) {
|
|
@@ -2328,6 +2442,100 @@ function DDropdown({ actions, dropdownToggle, className, }) {
|
|
|
2328
2442
|
}) })] }));
|
|
2329
2443
|
}
|
|
2330
2444
|
|
|
2445
|
+
function useScreenshot() {
|
|
2446
|
+
const clipRef = React.useRef(null);
|
|
2447
|
+
const takeBlob = React.useCallback(async (type) => {
|
|
2448
|
+
if (!clipRef.current) {
|
|
2449
|
+
throw new Error('set the clipRef');
|
|
2450
|
+
}
|
|
2451
|
+
const canvas = await html2canvas(clipRef === null || clipRef === void 0 ? void 0 : clipRef.current, {
|
|
2452
|
+
allowTaint: true,
|
|
2453
|
+
useCORS: true,
|
|
2454
|
+
});
|
|
2455
|
+
return (new Promise((resolve, reject) => {
|
|
2456
|
+
canvas.toBlob((innerBlob) => {
|
|
2457
|
+
if (!innerBlob) {
|
|
2458
|
+
return reject();
|
|
2459
|
+
}
|
|
2460
|
+
return resolve(innerBlob);
|
|
2461
|
+
}, type);
|
|
2462
|
+
}));
|
|
2463
|
+
}, []);
|
|
2464
|
+
return {
|
|
2465
|
+
clipRef,
|
|
2466
|
+
takeBlob,
|
|
2467
|
+
};
|
|
2468
|
+
}
|
|
2469
|
+
|
|
2470
|
+
function useScreenshotDownload() {
|
|
2471
|
+
const { clipRef, takeBlob } = useScreenshot();
|
|
2472
|
+
const download = React.useCallback(async () => {
|
|
2473
|
+
const blob = await takeBlob();
|
|
2474
|
+
const url = window.URL.createObjectURL(blob);
|
|
2475
|
+
const link = window.document.createElement('a');
|
|
2476
|
+
link.style.display = 'none';
|
|
2477
|
+
link.href = url;
|
|
2478
|
+
link.download = 'voucher.jpg';
|
|
2479
|
+
document.body.appendChild(link);
|
|
2480
|
+
link.click();
|
|
2481
|
+
document.body.removeChild(link);
|
|
2482
|
+
window.URL.revokeObjectURL(url);
|
|
2483
|
+
}, [takeBlob]);
|
|
2484
|
+
return {
|
|
2485
|
+
download,
|
|
2486
|
+
downloadRef: clipRef,
|
|
2487
|
+
};
|
|
2488
|
+
}
|
|
2489
|
+
|
|
2490
|
+
function useScreenshotWebShare() {
|
|
2491
|
+
const { takeBlob, clipRef } = useScreenshot();
|
|
2492
|
+
const share = React.useCallback(async () => {
|
|
2493
|
+
const blob = await takeBlob();
|
|
2494
|
+
const image = new File([blob], 'voucher.jpeg', { type: 'image/jpeg' });
|
|
2495
|
+
if (!navigator.canShare
|
|
2496
|
+
&& (navigator.canShare && !navigator.canShare({ files: [image] }))) {
|
|
2497
|
+
window.print();
|
|
2498
|
+
return;
|
|
2499
|
+
}
|
|
2500
|
+
await navigator.share({ files: [image] });
|
|
2501
|
+
}, [takeBlob]);
|
|
2502
|
+
return {
|
|
2503
|
+
share,
|
|
2504
|
+
shareRef: clipRef,
|
|
2505
|
+
};
|
|
2506
|
+
}
|
|
2507
|
+
|
|
2508
|
+
function DVoucher({ amount, amountDetails, icon = 'CircleCheckBig', color = 'success', title, onError, message, downloadText = 'Download', shareText = 'Share', children, }) {
|
|
2509
|
+
const { shareRef, share } = useScreenshotWebShare();
|
|
2510
|
+
const { downloadRef, download } = useScreenshotDownload();
|
|
2511
|
+
const handleShare = () => {
|
|
2512
|
+
share()
|
|
2513
|
+
.catch(async (err) => {
|
|
2514
|
+
if (onError) {
|
|
2515
|
+
await onError(err);
|
|
2516
|
+
}
|
|
2517
|
+
})
|
|
2518
|
+
.catch(() => {
|
|
2519
|
+
// Error already handled by onError
|
|
2520
|
+
});
|
|
2521
|
+
};
|
|
2522
|
+
const handleDownload = () => {
|
|
2523
|
+
download()
|
|
2524
|
+
.catch(async (err) => {
|
|
2525
|
+
if (onError) {
|
|
2526
|
+
await onError(err);
|
|
2527
|
+
}
|
|
2528
|
+
})
|
|
2529
|
+
.catch(() => {
|
|
2530
|
+
// Error already handled by onError
|
|
2531
|
+
});
|
|
2532
|
+
};
|
|
2533
|
+
return (jsxRuntime.jsx("div", { className: "d-voucher", ref: (el) => {
|
|
2534
|
+
shareRef.current = el;
|
|
2535
|
+
downloadRef.current = el;
|
|
2536
|
+
}, children: jsxRuntime.jsxs("div", { children: [jsxRuntime.jsxs("div", { className: "d-voucher-header", children: [jsxRuntime.jsx(DIcon, { icon: icon, color: color }), jsxRuntime.jsxs("div", { className: "text-center", children: [jsxRuntime.jsx("h3", { className: "mb-2", children: title }), jsxRuntime.jsx("p", { className: "m-0", children: message })] })] }), amount && (jsxRuntime.jsxs("div", { className: "d-voucher-amount", children: [jsxRuntime.jsx("div", { className: classNames('text-center fw-bold fs-3', amountDetails ? 'mb-1' : 'm-0'), children: amount }), amountDetails] })), jsxRuntime.jsx("hr", { className: "my-4" }), children, jsxRuntime.jsx("hr", { className: "my-4" }), jsxRuntime.jsxs("div", { className: "d-voucher-footer", children: [jsxRuntime.jsx(DButton, { onClick: handleShare, iconStart: "Share2", text: shareText, variant: "outline", size: "sm" }), jsxRuntime.jsx(DButton, { onClick: handleDownload, iconStart: "Download", text: downloadText, variant: "outline", size: "sm" })] })] }) }));
|
|
2537
|
+
}
|
|
2538
|
+
|
|
2331
2539
|
exports.DAlert = DAlert;
|
|
2332
2540
|
exports.DAvatar = DAvatar;
|
|
2333
2541
|
exports.DBadge = DBadge;
|
|
@@ -2375,6 +2583,7 @@ exports.DOffcanvasBody = DOffcanvasBody;
|
|
|
2375
2583
|
exports.DOffcanvasFooter = DOffcanvasFooter;
|
|
2376
2584
|
exports.DOffcanvasHeader = DOffcanvasHeader;
|
|
2377
2585
|
exports.DPaginator = DPaginator;
|
|
2586
|
+
exports.DPasswordStrengthMeter = DPasswordStrengthMeter;
|
|
2378
2587
|
exports.DPopover = DPopover;
|
|
2379
2588
|
exports.DProgress = DProgress;
|
|
2380
2589
|
exports.DSelect = DSelect;
|
|
@@ -2388,6 +2597,7 @@ exports.DTimeline = DTimeline;
|
|
|
2388
2597
|
exports.DToast = DToast;
|
|
2389
2598
|
exports.DToastContainer = DToastContainer;
|
|
2390
2599
|
exports.DTooltip = DTooltip;
|
|
2600
|
+
exports.DVoucher = DVoucher;
|
|
2391
2601
|
exports.changeQueryString = changeQueryString;
|
|
2392
2602
|
exports.checkMediaQuery = checkMediaQuery;
|
|
2393
2603
|
exports.configureI18n = configureI8n;
|