@dynamic-framework/ui-react 2.0.0-dev.4 → 2.0.0-dev.6

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.
Files changed (37) hide show
  1. package/dist/css/dynamic-ui-non-root.css +66 -46
  2. package/dist/css/dynamic-ui-non-root.min.css +2 -2
  3. package/dist/css/dynamic-ui-root.css +1 -1
  4. package/dist/css/dynamic-ui-root.min.css +1 -1
  5. package/dist/css/dynamic-ui.css +66 -46
  6. package/dist/css/dynamic-ui.min.css +2 -2
  7. package/dist/index.esm.js +290 -64
  8. package/dist/index.esm.js.map +1 -1
  9. package/dist/index.js +280 -53
  10. package/dist/index.js.map +1 -1
  11. package/dist/types/components/DBoxFile/DBoxFile.d.ts +1 -1
  12. package/dist/types/components/DButton/DButton.d.ts +7 -17
  13. package/dist/types/components/DIconBase/DIconBase.d.ts +1 -1
  14. package/dist/types/components/DInputCheck/DInputCheck.d.ts +2 -1
  15. package/dist/types/components/DInputSwitch/DInputSwitch.d.ts +2 -1
  16. package/dist/types/components/DModal/DModal.d.ts +3 -1
  17. package/dist/types/components/DOffcanvas/DOffcanvas.d.ts +3 -1
  18. package/dist/types/components/DPasswordStrengthMeter/DPasswordStrengthMeter.d.ts +23 -0
  19. package/dist/types/components/DPasswordStrengthMeter/PasswordCheckItem.d.ts +7 -0
  20. package/dist/types/components/DPasswordStrengthMeter/PasswordCheckList.d.ts +14 -0
  21. package/dist/types/components/DPasswordStrengthMeter/PasswordStrength.d.ts +6 -0
  22. package/dist/types/components/DPasswordStrengthMeter/index.d.ts +3 -0
  23. package/dist/types/components/DVoucher/DVoucher.d.ts +14 -0
  24. package/dist/types/components/DVoucher/hooks/useScreenshot.d.ts +5 -0
  25. package/dist/types/components/DVoucher/hooks/useScreenshotDownload.d.ts +5 -0
  26. package/dist/types/components/DVoucher/hooks/useScreenshotWebShare.d.ts +5 -0
  27. package/dist/types/components/DVoucher/index.d.ts +2 -0
  28. package/dist/types/components/index.d.ts +3 -1
  29. package/jest/setup.js +0 -2
  30. package/package.json +7 -4
  31. package/src/style/abstracts/variables/_buttons.scss +2 -0
  32. package/src/style/base/_buttons.scss +56 -65
  33. package/src/style/components/_+import.scss +1 -0
  34. package/src/style/components/_d-box-file.scss +1 -1
  35. package/src/style/components/_d-voucher.scss +30 -0
  36. package/dist/types/components/DTableHead/DTableHead.d.ts +0 -9
  37. package/dist/types/components/DTableHead/index.d.ts +0 -2
package/dist/index.js CHANGED
@@ -6,6 +6,7 @@ var React = require('react');
6
6
  var tslib = require('tslib');
7
7
  var LucideIcons = require('lucide-react');
8
8
  var reactDom = require('react-dom');
9
+ var framerMotion = require('framer-motion');
9
10
  var fileSelector = require('file-selector');
10
11
  var reactSplide = require('@splidejs/react-splide');
11
12
  var currency = require('currency.js');
@@ -18,6 +19,7 @@ var react = require('@floating-ui/react');
18
19
  var reactHotToast = require('react-hot-toast');
19
20
  var reactInternationalPhone = require('react-international-phone');
20
21
  var googleLibphonenumber = require('google-libphonenumber');
22
+ var html2canvas = require('html2canvas');
21
23
  var i18n = require('i18next');
22
24
  var reactI18next = require('react-i18next');
23
25
 
@@ -42,7 +44,7 @@ var LucideIcons__namespace = /*#__PURE__*/_interopNamespaceDefault(LucideIcons);
42
44
 
43
45
  const PREFIX_BS = 'bs-';
44
46
 
45
- function DIconBase({ icon, color, style, className, size, hasCircle = false, materialStyle = false, familyClass = 'material-symbols-outlined', strokeWidth = 2, dataAttributes, }) {
47
+ function DIconBase({ icon, color, style, className, size, hasCircle = false, materialStyle = false, familyClass, familyPrefix, strokeWidth = 2, dataAttributes, }) {
46
48
  // If materialStyle is true, use Material Design icons (legacy)
47
49
  const useMaterialIcons = materialStyle;
48
50
  // Get Lucide icon component
@@ -69,13 +71,7 @@ function DIconBase({ icon, color, style, className, size, hasCircle = false, mat
69
71
  return {};
70
72
  }, [hasCircle, color]);
71
73
  const generateStyleVariables = React.useMemo(() => (Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, size && { [`--${PREFIX_BS}icon-component-size`]: size }), colorStyle), backgroundStyle), hasCircle && { [`--${PREFIX_BS}icon-component-padding`]: `calc(var(--${PREFIX_BS}icon-component-size, 24px) * 0.4)` }), style)), [size, colorStyle, backgroundStyle, hasCircle, style]);
72
- const generateClasses = React.useMemo(() => (Object.assign(Object.assign({ 'd-icon': true }, useMaterialIcons && {
73
- [familyClass]: true,
74
- }), className && { [className]: true })), [
75
- className,
76
- useMaterialIcons,
77
- familyClass,
78
- ]);
74
+ const generateClasses = React.useMemo(() => (Object.assign({ 'd-icon': true }, className && { [className]: true })), [className]);
79
75
  const iconSize = React.useMemo(() => {
80
76
  if (size) {
81
77
  const numSize = parseInt(size, 10);
@@ -85,10 +81,13 @@ function DIconBase({ icon, color, style, className, size, hasCircle = false, mat
85
81
  }, [size]);
86
82
  // Render Material Design icon (legacy support)
87
83
  if (useMaterialIcons) {
88
- return (jsxRuntime.jsx("i", Object.assign({ className: classNames(generateClasses), style: generateStyleVariables }, dataAttributes, { children: icon })));
84
+ return (jsxRuntime.jsx("i", Object.assign({ className: classNames(generateClasses, familyClass), style: generateStyleVariables }, dataAttributes, { children: icon })));
89
85
  }
90
86
  // Render Lucide icon
91
87
  if (!LucideIcon) {
88
+ if (familyClass && familyPrefix) {
89
+ return (jsxRuntime.jsx("i", Object.assign({ className: classNames(generateClasses, familyClass, `${familyPrefix}${icon}`), style: generateStyleVariables }, dataAttributes)));
90
+ }
92
91
  // eslint-disable-next-line no-console
93
92
  console.warn(`Icon "${icon}" not found in Lucide. Make sure to use PascalCase names (e.g., "Home", "User", "Settings")`);
94
93
  return (jsxRuntime.jsx("span", Object.assign({ className: classNames(generateClasses), style: generateStyleVariables }, dataAttributes, { children: "?" })));
@@ -252,7 +251,10 @@ function DPortalContextProvider({ portalName, children, availablePortals, }) {
252
251
  return (jsxRuntime.jsxs(DPortalContext.Provider, { value: value, children: [children, created && reactDom.createPortal(
253
252
  // eslint-disable-next-line max-len
254
253
  // eslint-disable-next-line jsx-a11y/no-static-element-interactions
255
- jsxRuntime.jsx("div", { onClick: ({ target }) => handleClose(target), onKeyDown: () => { }, children: stack.map(({ Component, name, payload, }) => (jsxRuntime.jsxs(React.Fragment, { children: [jsxRuntime.jsx("div", { className: "backdrop fade show" }), jsxRuntime.jsx(Component, { name: name, payload: payload })] }, name))) }), document.getElementById(portalName))] }));
254
+ jsxRuntime.jsx("div", { onClick: ({ target }) => handleClose(target), onKeyDown: () => { }, children: jsxRuntime.jsx(framerMotion.AnimatePresence, { children: stack.flatMap(({ Component, name, payload, }) => [
255
+ jsxRuntime.jsx(framerMotion.motion.div, { className: "backdrop", initial: { opacity: 0 }, animate: { opacity: 0.5 }, exit: { opacity: 0, transition: { delay: 0.3 } }, transition: { duration: 0.15, ease: 'linear' } }, `${name}-backdrop`),
256
+ jsxRuntime.jsx(Component, { name: name, payload: payload }, name),
257
+ ]) }) }), document.getElementById(portalName))] }));
256
258
  }
257
259
  function useDPortalContext() {
258
260
  const context = React.useContext(DPortalContext);
@@ -884,31 +886,64 @@ function DBoxFile(_a) {
884
886
  'd-box-file-disabled': props.disabled,
885
887
  'd-box-file-valid': isDragValid,
886
888
  'd-box-file-invalid': isDragInvalid,
887
- }, className), style: style }, dataAttributes, { children: jsxRuntime.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: [jsxRuntime.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 }), jsxRuntime.jsx(DIcon, { icon: icon, familyClass: iconFamilyClass, familyPrefix: iconFamilyPrefix, materialStyle: iconMaterialStyle }), jsxRuntime.jsx("div", { className: "d-box-content", children: typeof children === 'function'
889
+ }, className), style: style }, dataAttributes, { children: jsxRuntime.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: [jsxRuntime.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 && (jsxRuntime.jsx(DIcon, { icon: icon, familyClass: iconFamilyClass, familyPrefix: iconFamilyPrefix, materialStyle: iconMaterialStyle })), jsxRuntime.jsx("div", { className: "d-box-content", children: typeof children === 'function'
888
890
  ? children(openFileDialog)
889
- : 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}`))) }))] }));
891
+ : children || (jsxRuntime.jsx("p", { className: "text-center m-0", children: "Drag and drop some files here, or click to select files" })) })] })) })), !!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
892
  }
891
893
 
892
- function DButton({ color = 'primary', size, variant, state, text = '', children, ariaLabel, iconStart, iconStartFamilyClass, iconStartFamilyPrefix, iconStartMaterialStyle, iconEnd, iconEndFamilyClass, iconEndFamilyPrefix, iconEndMaterialStyle, loadingText, value, type = 'button', loading = false, loadingAriaLabel, disabled = false, stopPropagationEnabled = true, className, style, form, dataAttributes, onClick, }) {
893
- const generateClasses = React.useMemo(() => {
894
+ const DButton = React.forwardRef((props, ref) => {
895
+ 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"]);
896
+ const [buttonWidth, setButtonWidth] = React.useState();
897
+ const buttonRef = React.useRef(null);
898
+ const isDisabled = React.useMemo(() => disabled || loading, [disabled, loading]);
899
+ const content = React.useMemo(() => children || text, [children, text]);
900
+ const classes = React.useMemo(() => {
894
901
  const variantClass = variant
895
902
  ? `btn-${variant}-${color}`
896
903
  : `btn-${color}`;
897
- return Object.assign(Object.assign(Object.assign({ btn: true, [variantClass]: true }, size && { [`btn-${size}`]: true }), (state && state !== 'disabled') && { [state]: true }), { loading });
898
- }, [variant, color, size, state, loading]);
899
- const clickHandler = React.useCallback((event) => {
900
- if (stopPropagationEnabled) {
901
- event.stopPropagation();
904
+ return {
905
+ btn: true,
906
+ [variantClass]: true,
907
+ [`btn-${size}`]: !!size,
908
+ loading,
909
+ };
910
+ }, [variant, color, size, loading]);
911
+ const ariaLabel = React.useMemo(() => {
912
+ const ariaLabelProp = rest['aria-label'];
913
+ return loading
914
+ ? loadingAriaLabel || ariaLabelProp || text
915
+ : ariaLabelProp || text;
916
+ }, [loading, loadingAriaLabel, rest, text]);
917
+ const handleClick = React.useCallback((event) => {
918
+ if (disabled || loading) {
919
+ event.preventDefault();
920
+ return;
902
921
  }
903
922
  onClick === null || onClick === void 0 ? void 0 : onClick(event);
904
- }, [stopPropagationEnabled, onClick]);
905
- const isDisabled = React.useMemo(() => (state === 'disabled' || loading || disabled), [state, loading, disabled]);
906
- const content = children || text;
907
- const newAriaLabel = React.useMemo(() => (loading
908
- ? (loadingAriaLabel || ariaLabel || text)
909
- : (ariaLabel || text)), [loading, loadingAriaLabel, ariaLabel, text]);
910
- return (jsxRuntime.jsxs("button", Object.assign({ className: classNames(generateClasses, className), style: style, type: type, disabled: isDisabled, onClick: clickHandler, "aria-label": newAriaLabel, form: form }, dataAttributes, value && { value }, { children: [iconStart && (jsxRuntime.jsx(DIcon, { icon: iconStart, familyClass: iconStartFamilyClass, familyPrefix: iconStartFamilyPrefix, materialStyle: iconStartMaterialStyle })), loading && (jsxRuntime.jsx("span", { className: "spinner-border spinner-border-sm", role: "status", "aria-hidden": "true", children: jsxRuntime.jsx("span", { className: "visually-hidden", children: "Loading..." }) })), jsxRuntime.jsx("span", { children: loading && loadingText ? loadingText : content }), iconEnd && (jsxRuntime.jsx(DIcon, { icon: iconEnd, familyClass: iconEndFamilyClass, familyPrefix: iconEndFamilyPrefix, materialStyle: iconEndMaterialStyle }))] })));
911
- }
923
+ }, [disabled, loading, onClick]);
924
+ React.useEffect(() => {
925
+ if (!loading && buttonRef.current) {
926
+ const width = buttonRef.current.offsetWidth;
927
+ if (width > 0)
928
+ setButtonWidth(width);
929
+ }
930
+ // eslint-disable-next-line react-hooks/exhaustive-deps
931
+ }, [content, iconEnd, iconStart]);
932
+ return (jsxRuntime.jsxs("button", Object.assign({ ref: (node) => {
933
+ buttonRef.current = node;
934
+ if (typeof ref === 'function')
935
+ ref(node);
936
+ // eslint-disable-next-line max-len
937
+ // eslint-disable-next-line no-param-reassign, @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access
938
+ else if (ref)
939
+ ref.current = node;
940
+ },
941
+ // eslint-disable-next-line react/button-has-type
942
+ type: type, className: classNames(classes, className), style: Object.assign(Object.assign({}, style), (loading && buttonWidth
943
+ ? { minWidth: `${buttonWidth}px` }
944
+ : 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 }))] }))] })));
945
+ });
946
+ DButton.displayName = 'DButton';
912
947
 
913
948
  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
949
  const generateClasses = React.useMemo(() => {
@@ -1043,7 +1078,7 @@ const ForwardedDDatePickerInput = React.forwardRef(DDatePickerInput);
1043
1078
  ForwardedDDatePickerInput.displayName = 'DDatePickerInput';
1044
1079
 
1045
1080
  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"]);
1081
+ 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
1082
  const innerRef = React.useRef(null);
1048
1083
  const innerId = React.useId();
1049
1084
  const id = React.useMemo(() => idProp || innerId, [idProp, innerId]);
@@ -1071,11 +1106,11 @@ function DInputCheck(_a) {
1071
1106
  const inputComponent = React.useMemo(() => (jsxRuntime.jsx("input", Object.assign({ ref: innerRef, onChange: handleChange, className: classNames('form-check-input', {
1072
1107
  'is-invalid': invalid,
1073
1108
  'is-valid': valid,
1074
- }, className), style: style, id: id, disabled: disabled, type: type, name: name, value: value, "aria-label": ariaLabel }, ariaDescribedby && { 'aria-describedby': ariaDescribedby }, props))), [
1109
+ }, inputClassName), style: style, id: id, disabled: disabled, type: type, name: name, value: value, "aria-label": ariaLabel }, ariaDescribedby && { 'aria-describedby': ariaDescribedby }, props))), [
1075
1110
  handleChange,
1076
1111
  invalid,
1077
1112
  valid,
1078
- className,
1113
+ inputClassName,
1079
1114
  style,
1080
1115
  id,
1081
1116
  disabled,
@@ -1089,7 +1124,7 @@ function DInputCheck(_a) {
1089
1124
  if (!label) {
1090
1125
  return inputComponent;
1091
1126
  }
1092
- return (jsxRuntime.jsxs("div", Object.assign({ className: "form-check" }, 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 }))] })));
1127
+ 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
1128
  }
1094
1129
 
1095
1130
  function DSelectOptionCheck(_a) {
@@ -1513,6 +1548,86 @@ function DInputPassword(_a, ref) {
1513
1548
  const ForwardedDInputPassword = React.forwardRef(DInputPassword);
1514
1549
  ForwardedDInputPassword.displayName = 'DInputPassword';
1515
1550
 
1551
+ function PasswordCheckItem({ password, regex, text, }) {
1552
+ const isValid = regex.test(password);
1553
+ 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 })] }));
1554
+ }
1555
+
1556
+ const getColorClass = (strength, total) => {
1557
+ const percentage = total > 0 ? strength / total : 0;
1558
+ if (percentage === 0)
1559
+ return 'bg-gray-200';
1560
+ if (percentage <= 0.25)
1561
+ return 'bg-danger';
1562
+ if (percentage <= 0.5)
1563
+ return 'bg-warning';
1564
+ if (percentage <= 0.75)
1565
+ return 'bg-info';
1566
+ return 'bg-success';
1567
+ };
1568
+ function PasswordStrengthBar({ strength, total }) {
1569
+ const percentage = total > 0 ? (strength / total) * 100 : 0;
1570
+ 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: {
1571
+ width: `${percentage}%`,
1572
+ transition: 'width 0.3s ease-in-out',
1573
+ } }) }));
1574
+ }
1575
+
1576
+ const CHECK_REGEX = {
1577
+ uppercase: /[A-Z]/,
1578
+ lowercase: /[a-z]/,
1579
+ number: /\d/,
1580
+ specialChar: /[~!@#$^*\-_=[\]{}|;,.?]/,
1581
+ };
1582
+ function PasswordChecksList({ password, validationMessages, enabledChecks, }) {
1583
+ const allChecks = [
1584
+ {
1585
+ key: 'uppercase',
1586
+ regex: CHECK_REGEX.uppercase,
1587
+ text: validationMessages.uppercaseLetter,
1588
+ },
1589
+ {
1590
+ key: 'lowercase',
1591
+ regex: CHECK_REGEX.lowercase,
1592
+ text: validationMessages.lowercaseLetter,
1593
+ },
1594
+ {
1595
+ key: 'number',
1596
+ regex: CHECK_REGEX.number,
1597
+ text: validationMessages.number,
1598
+ },
1599
+ {
1600
+ key: 'specialChar',
1601
+ regex: CHECK_REGEX.specialChar,
1602
+ text: validationMessages.especialChar,
1603
+ },
1604
+ ];
1605
+ const passwordChecks = allChecks.filter((check) => enabledChecks.includes(check.key));
1606
+ const passed = passwordChecks.filter((r) => r.regex.test(password)).length;
1607
+ const total = passwordChecks.length;
1608
+ 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))) })] }));
1609
+ }
1610
+
1611
+ const DEFAULT_VALIDATION_MESSAGES = {
1612
+ number: 'At least one number',
1613
+ lowercaseLetter: 'At least one lowercase letter',
1614
+ uppercaseLetter: 'At least one uppercase letter',
1615
+ especialChar: 'At least one of these special characters: ~!@#$^*-_=[]{}|;,.?',
1616
+ notMatch: 'The password confirmation and the new password do not match.',
1617
+ };
1618
+ const DEFAULT_ENABLED_CHECKS = ['uppercase', 'lowercase', 'number', 'specialChar'];
1619
+ function DPasswordStrengthMeter({ id, label = 'Password', placeholder, value = '', name, disabled = false, invalid = false, validationMessages = DEFAULT_VALIDATION_MESSAGES, enabledChecks = DEFAULT_ENABLED_CHECKS, className, style, dataAttributes, onChange, }) {
1620
+ const [password, setPassword] = React.useState(value);
1621
+ React.useEffect(() => {
1622
+ setPassword(value);
1623
+ }, [value]);
1624
+ const handleChange = (newValue) => {
1625
+ setPassword(newValue);
1626
+ onChange === null || onChange === void 0 ? void 0 : onChange(newValue);
1627
+ };
1628
+ 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 })] })));
1629
+ }
1630
+
1516
1631
  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
1632
  const innerId = React.useId();
1518
1633
  const id = React.useMemo(() => idProp || innerId, [idProp, innerId]);
@@ -1676,7 +1791,7 @@ function DInputSelect({ id: idProp, name, label = '', className, style, options
1676
1791
  }), 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
1792
  }
1678
1793
 
1679
- function DInputSwitch({ id: idProp, label, ariaLabel, name, checked, disabled, invalid = false, valid = false, readonly, className, style, dataAttributes, onChange, }) {
1794
+ function DInputSwitch({ id: idProp, label, ariaLabel, name, checked, disabled, invalid = false, valid = false, readonly, className, style, dataAttributes, inputClassName, onChange, }) {
1680
1795
  const innerId = React.useId();
1681
1796
  const id = React.useMemo(() => idProp || innerId, [idProp, innerId]);
1682
1797
  const [internalIsChecked, setInternalIsChecked] = React.useState(checked);
@@ -1688,10 +1803,10 @@ function DInputSwitch({ id: idProp, label, ariaLabel, name, checked, disabled, i
1688
1803
  setInternalIsChecked(value);
1689
1804
  onChange === null || onChange === void 0 ? void 0 : onChange(value);
1690
1805
  }, [onChange]);
1691
- return (jsxRuntime.jsxs("div", Object.assign({ className: "form-check form-switch" }, dataAttributes, { children: [jsxRuntime.jsx("input", { id: id, name: name, onChange: readonly ? () => false : changeHandler, className: classNames('form-check-input', {
1806
+ 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
1807
  'is-invalid': invalid,
1693
1808
  'is-valid': valid,
1694
- }, className), 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 }))] })));
1809
+ }, 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
1810
  }
1696
1811
 
1697
1812
  function DInputRange(_a, ref) {
@@ -1805,7 +1920,11 @@ function DModalFooter({ className, style, actionPlacement, children, }) {
1805
1920
  return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("div", { className: "d-modal-separator" }), jsxRuntime.jsx("div", { className: classNames(generateClasses, className), style: style, children: children })] }));
1806
1921
  }
1807
1922
 
1808
- function DModal$1({ name, className, style, staticBackdrop, scrollable, centered, fullScreen, fullScreenFrom, size, children, dataAttributes, }) {
1923
+ const defaultTransition$1 = {
1924
+ ease: 'easeInOut',
1925
+ duration: 0.3,
1926
+ };
1927
+ function DModal$1({ name, className, style, staticBackdrop, scrollable, centered, fullScreen, fullScreenFrom, size, transition, children, dataAttributes, }) {
1809
1928
  const fullScreenClass = React.useMemo(() => {
1810
1929
  if (fullScreen) {
1811
1930
  if (fullScreenFrom) {
@@ -1816,7 +1935,7 @@ function DModal$1({ name, className, style, staticBackdrop, scrollable, centered
1816
1935
  return '';
1817
1936
  }, [fullScreenFrom, fullScreen]);
1818
1937
  const generateModalDialogClasses = React.useMemo(() => (Object.assign({ 'modal-dialog': true, 'modal-dialog-centered': !!centered, 'modal-dialog-scrollable': !!scrollable, [fullScreenClass]: !!fullScreen }, size && { [`modal-${size}`]: true })), [fullScreenClass, centered, fullScreen, scrollable, size]);
1819
- return (jsxRuntime.jsx("div", Object.assign({ className: classNames('modal portal fade show', className), id: name, tabIndex: -1, "aria-labelledby": `${name}Label`, "aria-hidden": "false", style: style }, staticBackdrop && ({
1938
+ return (jsxRuntime.jsx(framerMotion.motion.div, Object.assign({ className: classNames('modal portal show', className), id: name, tabIndex: -1, "aria-labelledby": `${name}Label`, "aria-hidden": "false", style: style, initial: { opacity: 0, scale: 0.95 }, animate: { opacity: 1, scale: 1 }, exit: { opacity: 0, scale: 0.95 }, transition: Object.assign(Object.assign({}, (transition !== null && transition !== void 0 ? transition : defaultTransition$1)), { delay: 0.15 }) }, staticBackdrop && ({
1820
1939
  [`data-${PREFIX_BS}backdrop`]: 'static',
1821
1940
  [`data-${PREFIX_BS}keyboard`]: 'false',
1822
1941
  }), dataAttributes, { children: jsxRuntime.jsx("div", { className: classNames(generateModalDialogClasses), children: jsxRuntime.jsx("div", { className: "modal-content", children: children }) }) })));
@@ -1845,10 +1964,36 @@ function DOffcanvasFooter({ actionPlacement, children, className, style, }) {
1845
1964
  return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("div", { className: "d-offcanvas-separator" }), jsxRuntime.jsx("div", { className: classNames(generateClasses, className), style: style, children: children })] }));
1846
1965
  }
1847
1966
 
1848
- function DOffcanvas$1({ name, className, style, staticBackdrop, scrollable, openFrom = 'end', children, dataAttributes, }) {
1849
- return (jsxRuntime.jsx("div", Object.assign({ className: classNames('offcanvas portal show', {
1967
+ const variants = {
1968
+ hidden: (openFrom) => {
1969
+ const properties = {};
1970
+ if (openFrom === 'start') {
1971
+ properties.x = '-100%';
1972
+ }
1973
+ if (openFrom === 'end') {
1974
+ properties.x = '100%';
1975
+ }
1976
+ if (openFrom === 'top') {
1977
+ properties.y = '-100%';
1978
+ }
1979
+ if (openFrom === 'bottom') {
1980
+ properties.y = '100%';
1981
+ }
1982
+ return properties;
1983
+ },
1984
+ visible: {
1985
+ x: 0,
1986
+ y: 0,
1987
+ },
1988
+ };
1989
+ const defaultTransition = {
1990
+ ease: 'easeInOut',
1991
+ duration: 0.3,
1992
+ };
1993
+ function DOffcanvas$1({ name, className, style, staticBackdrop, scrollable, openFrom = 'end', transition, children, dataAttributes, }) {
1994
+ return (jsxRuntime.jsx(framerMotion.motion.div, Object.assign({ className: classNames('offcanvas portal show', {
1850
1995
  [`offcanvas-${openFrom}`]: openFrom,
1851
- }, className), style: style, id: name, tabIndex: -1, "aria-labelledby": `${name}Label`, "aria-hidden": "false" }, staticBackdrop && ({
1996
+ }, className), style: Object.assign(Object.assign({}, style), { transition: 'none' }), id: name, tabIndex: -1, "aria-labelledby": `${name}Label`, "aria-hidden": "false", custom: openFrom, variants: variants, initial: "hidden", animate: "visible", exit: "hidden", transition: Object.assign(Object.assign({}, (transition !== null && transition !== void 0 ? transition : defaultTransition)), { delay: 0.15 }) }, staticBackdrop && ({
1852
1997
  [`data-${PREFIX_BS}backdrop`]: 'static',
1853
1998
  [`data-${PREFIX_BS}keyboard`]: 'false',
1854
1999
  }), scrollable && ({
@@ -2102,19 +2247,6 @@ function useDToast() {
2102
2247
  };
2103
2248
  }
2104
2249
 
2105
- function DTableHead({ className, style, field, label, value = '', onChange, }) {
2106
- const handleOnChange = React.useCallback(() => {
2107
- if (value === field) {
2108
- return onChange(`-${field}`);
2109
- }
2110
- if (value === `-${field}`) {
2111
- return onChange('');
2112
- }
2113
- return onChange(field);
2114
- }, [field, value, onChange]);
2115
- return (jsxRuntime.jsx("th", { style: style, className: classNames('d-table-head', className), children: jsxRuntime.jsxs("button", { type: "button", onClick: handleOnChange, children: [label, value && value.includes(field) && (jsxRuntime.jsx(DIcon, { icon: value === field ? 'arrow-up' : 'arrow-down' }))] }) }));
2116
- }
2117
-
2118
2250
  async function configureI8n(resources, _a = {}) {
2119
2251
  var { lng = 'en', fallbackLng = 'en' } = _a, config = tslib.__rest(_a, ["lng", "fallbackLng"]);
2120
2252
  return i18n
@@ -2328,6 +2460,100 @@ function DDropdown({ actions, dropdownToggle, className, }) {
2328
2460
  }) })] }));
2329
2461
  }
2330
2462
 
2463
+ function useScreenshot() {
2464
+ const clipRef = React.useRef(null);
2465
+ const takeBlob = React.useCallback(async (type) => {
2466
+ if (!clipRef.current) {
2467
+ throw new Error('set the clipRef');
2468
+ }
2469
+ const canvas = await html2canvas(clipRef === null || clipRef === void 0 ? void 0 : clipRef.current, {
2470
+ allowTaint: true,
2471
+ useCORS: true,
2472
+ });
2473
+ return (new Promise((resolve, reject) => {
2474
+ canvas.toBlob((innerBlob) => {
2475
+ if (!innerBlob) {
2476
+ return reject();
2477
+ }
2478
+ return resolve(innerBlob);
2479
+ }, type);
2480
+ }));
2481
+ }, []);
2482
+ return {
2483
+ clipRef,
2484
+ takeBlob,
2485
+ };
2486
+ }
2487
+
2488
+ function useScreenshotDownload() {
2489
+ const { clipRef, takeBlob } = useScreenshot();
2490
+ const download = React.useCallback(async () => {
2491
+ const blob = await takeBlob();
2492
+ const url = window.URL.createObjectURL(blob);
2493
+ const link = window.document.createElement('a');
2494
+ link.style.display = 'none';
2495
+ link.href = url;
2496
+ link.download = 'voucher.jpg';
2497
+ document.body.appendChild(link);
2498
+ link.click();
2499
+ document.body.removeChild(link);
2500
+ window.URL.revokeObjectURL(url);
2501
+ }, [takeBlob]);
2502
+ return {
2503
+ download,
2504
+ downloadRef: clipRef,
2505
+ };
2506
+ }
2507
+
2508
+ function useScreenshotWebShare() {
2509
+ const { takeBlob, clipRef } = useScreenshot();
2510
+ const share = React.useCallback(async () => {
2511
+ const blob = await takeBlob();
2512
+ const image = new File([blob], 'voucher.jpeg', { type: 'image/jpeg' });
2513
+ if (!navigator.canShare
2514
+ && (navigator.canShare && !navigator.canShare({ files: [image] }))) {
2515
+ window.print();
2516
+ return;
2517
+ }
2518
+ await navigator.share({ files: [image] });
2519
+ }, [takeBlob]);
2520
+ return {
2521
+ share,
2522
+ shareRef: clipRef,
2523
+ };
2524
+ }
2525
+
2526
+ function DVoucher({ amount, amountDetails, icon = 'CircleCheckBig', color = 'success', title, onError, message, downloadText = 'Download', shareText = 'Share', children, }) {
2527
+ const { shareRef, share } = useScreenshotWebShare();
2528
+ const { downloadRef, download } = useScreenshotDownload();
2529
+ const handleShare = () => {
2530
+ share()
2531
+ .catch(async (err) => {
2532
+ if (onError) {
2533
+ await onError(err);
2534
+ }
2535
+ })
2536
+ .catch(() => {
2537
+ // Error already handled by onError
2538
+ });
2539
+ };
2540
+ const handleDownload = () => {
2541
+ download()
2542
+ .catch(async (err) => {
2543
+ if (onError) {
2544
+ await onError(err);
2545
+ }
2546
+ })
2547
+ .catch(() => {
2548
+ // Error already handled by onError
2549
+ });
2550
+ };
2551
+ return (jsxRuntime.jsx("div", { className: "d-voucher", ref: (el) => {
2552
+ shareRef.current = el;
2553
+ downloadRef.current = el;
2554
+ }, 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" })] })] }) }));
2555
+ }
2556
+
2331
2557
  exports.DAlert = DAlert;
2332
2558
  exports.DAvatar = DAvatar;
2333
2559
  exports.DBadge = DBadge;
@@ -2375,6 +2601,7 @@ exports.DOffcanvasBody = DOffcanvasBody;
2375
2601
  exports.DOffcanvasFooter = DOffcanvasFooter;
2376
2602
  exports.DOffcanvasHeader = DOffcanvasHeader;
2377
2603
  exports.DPaginator = DPaginator;
2604
+ exports.DPasswordStrengthMeter = DPasswordStrengthMeter;
2378
2605
  exports.DPopover = DPopover;
2379
2606
  exports.DProgress = DProgress;
2380
2607
  exports.DSelect = DSelect;
@@ -2382,12 +2609,12 @@ exports.DStepper = DStepper;
2382
2609
  exports.DStepperDesktop = DStepper$2;
2383
2610
  exports.DStepperMobile = DStepper$1;
2384
2611
  exports.DTabContent = DTabContent;
2385
- exports.DTableHead = DTableHead;
2386
2612
  exports.DTabs = DTabs;
2387
2613
  exports.DTimeline = DTimeline;
2388
2614
  exports.DToast = DToast;
2389
2615
  exports.DToastContainer = DToastContainer;
2390
2616
  exports.DTooltip = DTooltip;
2617
+ exports.DVoucher = DVoucher;
2391
2618
  exports.changeQueryString = changeQueryString;
2392
2619
  exports.checkMediaQuery = checkMediaQuery;
2393
2620
  exports.configureI18n = configureI8n;