@dynamic-framework/ui-react 1.34.0 → 1.35.1
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/README.md +1 -1
- package/dist/css/bootstrap-icons.css +3 -3
- package/dist/css/bootstrap-icons.min.css +2 -2
- package/dist/css/bootstrap-icons.scss +1 -1
- package/dist/css/dynamic-ui-non-root.css +722 -962
- 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 +722 -962
- package/dist/css/dynamic-ui.min.css +2 -2
- package/dist/css/fonts/bootstrap-icons.woff +0 -0
- package/dist/css/fonts/bootstrap-icons.woff2 +0 -0
- package/dist/index.esm.js +576 -146
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +573 -143
- package/dist/index.js.map +1 -1
- package/dist/js/bootstrap.bundle.js +19 -18
- package/dist/js/bootstrap.bundle.min.js +3 -3
- package/dist/js/bootstrap.esm.js +19 -16
- package/dist/js/bootstrap.esm.min.js +3 -3
- package/dist/js/bootstrap.js +19 -16
- package/dist/js/bootstrap.min.js +3 -3
- package/dist/types/components/DBoxFile/DBoxFile.d.ts +6 -5
- package/dist/types/components/DBoxFile/useDBoxFile.d.ts +37 -0
- package/dist/types/components/DBoxFile/utils.d.ts +39 -0
- package/dist/types/components/DDatePicker/DDatePicker.d.ts +6 -12
- package/dist/types/components/DDatePicker/components/DDatePickerHeaderSelector.d.ts +38 -0
- package/dist/types/components/{DDatePickerInput → DDatePicker/components}/DDatePickerInput.d.ts +2 -2
- package/dist/types/components/{DDatePickerTime → DDatePicker/components}/DDatePickerTime.d.ts +2 -2
- package/dist/types/components/DInput/DInput.d.ts +1 -1
- package/dist/types/components/DInputCounter/DInputCounter.d.ts +2 -2
- package/dist/types/components/DInputCurrency/DInputCurrency.d.ts +2 -2
- package/dist/types/components/DInputCurrencyBase/DInputCurrencyBase.d.ts +2 -2
- package/dist/types/components/DInputMask/DInputMask.d.ts +1 -1
- package/dist/types/components/DInputRange/DInputRange.d.ts +1 -1
- package/dist/types/components/DInputSearch/DInputSearch.d.ts +1 -1
- package/dist/types/components/DPopover/DPopover.d.ts +0 -3
- package/dist/types/utils/attr-accept.d.ts +11 -0
- package/dist/types/utils/getKeyboardFocusableElements.d.ts +1 -0
- package/jest/setup.js +14 -0
- package/package.json +13 -14
- package/src/style/abstracts/variables/_+import.scss +1 -0
- package/src/style/abstracts/variables/_box-file.scss +14 -7
- package/src/style/abstracts/variables/_cards.scss +1 -1
- package/src/style/abstracts/variables/_datepicker.scss +50 -0
- package/src/style/abstracts/variables/_forms.scss +6 -3
- package/src/style/base/_form-switch.scss +23 -2
- package/src/style/base/_input-group.scss +18 -1
- package/src/style/base/_nav.scss +0 -1
- package/src/style/base/_toast.scss +2 -0
- package/src/style/components/_d-box-file.scss +31 -15
- package/src/style/components/_d-button-icon.scss +17 -16
- package/src/style/components/_d-datepicker.scss +582 -243
- package/src/style/components/_d-input-pin.scss +8 -5
- package/src/style/components/_d-quick-action-button.scss +1 -1
- package/src/style/components/_d-quick-action-check.scss +1 -1
- package/src/style/components/_d-select.scss +35 -6
- package/src/style/components/_d-stepper-desktop.scss +1 -1
- package/src/style/helpers/_text-truncate.scss +2 -2
- package/dist/types/components/DDatePickerHeader/DDatePickerHeader.d.ts +0 -24
- package/dist/types/components/DDatePickerHeader/index.d.ts +0 -2
- package/dist/types/components/DDatePickerInput/index.d.ts +0 -2
- package/dist/types/components/DDatePickerTime/index.d.ts +0 -2
package/dist/index.esm.js
CHANGED
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
import { jsx, jsxs, Fragment as Fragment$1 } from 'react/jsx-runtime';
|
|
2
|
-
import React, { useMemo, useEffect, useState, useCallback,
|
|
2
|
+
import React, { useMemo, useEffect, useState, useCallback, useContext, createContext, Fragment, useLayoutEffect, forwardRef, useId, useRef, useSyncExternalStore } from 'react';
|
|
3
3
|
import classNames from 'classnames';
|
|
4
4
|
import { __rest } from 'tslib';
|
|
5
5
|
import { createPortal } from 'react-dom';
|
|
6
|
-
import {
|
|
6
|
+
import { fromEvent } from 'file-selector';
|
|
7
7
|
import { SplideSlide, Splide } from '@splidejs/react-splide';
|
|
8
8
|
import currency from 'currency.js';
|
|
9
9
|
import DatePicker from 'react-datepicker';
|
|
10
|
-
import { getYear, format, getMonth
|
|
10
|
+
import { getYear, format, getMonth } from 'date-fns';
|
|
11
|
+
import { enUS } from 'date-fns/locale';
|
|
11
12
|
import Select, { components } from 'react-select';
|
|
12
13
|
import { InputMask } from '@react-input/mask';
|
|
13
14
|
import ResponsivePagination from 'react-responsive-pagination';
|
|
14
|
-
import { useFloating, offset, flip, shift,
|
|
15
|
+
import { useFloating, autoUpdate, offset, flip, shift, useClick, useDismiss, useRole, useInteractions, useId as useId$1, FloatingFocusManager, arrow, useHover, useFocus, FloatingPortal, FloatingArrow } from '@floating-ui/react';
|
|
15
16
|
import ContentLoader from 'react-content-loader';
|
|
16
17
|
import { Toaster, toast } from 'react-hot-toast';
|
|
17
18
|
import i18n from 'i18next';
|
|
@@ -19,7 +20,7 @@ import { initReactI18next } from 'react-i18next';
|
|
|
19
20
|
|
|
20
21
|
const PREFIX_BS = 'bs-';
|
|
21
22
|
|
|
22
|
-
function DIconBase({ icon, theme, style, className, size
|
|
23
|
+
function DIconBase({ icon, theme, style, className, size, loading = false, loadingDuration = 1.8, hasCircle = false, circleSize = `calc(var(--${PREFIX_BS}icon-size) * 1)`, color, backgroundColor, materialStyle = false, familyClass = 'bi', familyPrefix = 'bi-', dataAttributes, }) {
|
|
23
24
|
const colorStyle = useMemo(() => {
|
|
24
25
|
if (color) {
|
|
25
26
|
return { [`--${PREFIX_BS}icon-component-color`]: color };
|
|
@@ -47,7 +48,7 @@ function DIconBase({ icon, theme, style, className, size = '1.5rem', loading = f
|
|
|
47
48
|
}
|
|
48
49
|
return { [`--${PREFIX_BS}icon-component-padding`]: '0' };
|
|
49
50
|
}, [circleSize, hasCircle]);
|
|
50
|
-
const generateStyleVariables = useMemo(() => (Object.assign(Object.assign(Object.assign(Object.assign({ [`--${PREFIX_BS}icon-component-
|
|
51
|
+
const generateStyleVariables = useMemo(() => (Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ [`--${PREFIX_BS}icon-component-loading-duration`]: `${loadingDuration}s` }, size && { [`--${PREFIX_BS}icon-component-size`]: size }), colorStyle), backgroundStyle), circleSizeStyle), style)), [size, loadingDuration, colorStyle, backgroundStyle, circleSizeStyle, style]);
|
|
51
52
|
const generateClasses = useMemo(() => (Object.assign(Object.assign({ 'd-icon': true, [familyClass]: true, 'd-icon-loading': loading }, !materialStyle && {
|
|
52
53
|
[`${familyPrefix}${icon}`]: true,
|
|
53
54
|
}), className && { [className]: true })), [
|
|
@@ -126,12 +127,22 @@ function useStackState(initialList = []) {
|
|
|
126
127
|
return [list, controls];
|
|
127
128
|
}
|
|
128
129
|
|
|
130
|
+
function getKeyboardFocusableElements(container) {
|
|
131
|
+
if (!container) {
|
|
132
|
+
return [];
|
|
133
|
+
}
|
|
134
|
+
return [
|
|
135
|
+
...container.querySelectorAll('a, button, input, textarea, select, details, [tabindex]:not([tabindex="-1"])'),
|
|
136
|
+
].filter((element) => !element.hasAttribute('disabled'));
|
|
137
|
+
}
|
|
138
|
+
|
|
129
139
|
const DPortalContext = createContext(undefined);
|
|
130
140
|
function DPortalContextProvider({ portalName, children, availablePortals, }) {
|
|
131
141
|
const { created } = usePortal(portalName);
|
|
132
142
|
const [stack, { push, pop, isEmpty }] = useStackState([]);
|
|
133
143
|
useDisableBodyScrollEffect(Boolean(stack.length));
|
|
134
144
|
const openPortal = useCallback((name, payload) => {
|
|
145
|
+
var _a;
|
|
135
146
|
if (!availablePortals) {
|
|
136
147
|
throw new Error(`there is no component for portal ${name.toString()}`);
|
|
137
148
|
}
|
|
@@ -144,6 +155,7 @@ function DPortalContextProvider({ portalName, children, availablePortals, }) {
|
|
|
144
155
|
Component,
|
|
145
156
|
payload,
|
|
146
157
|
});
|
|
158
|
+
(_a = document.activeElement) === null || _a === void 0 ? void 0 : _a.blur();
|
|
147
159
|
}, [availablePortals, push]);
|
|
148
160
|
const closePortal = useCallback(() => {
|
|
149
161
|
if (isEmpty()) {
|
|
@@ -173,10 +185,26 @@ function DPortalContextProvider({ portalName, children, availablePortals, }) {
|
|
|
173
185
|
}, [closePortal]);
|
|
174
186
|
useEffect(() => {
|
|
175
187
|
const keyEvent = (event) => {
|
|
188
|
+
const lastPortal = document.querySelector(`#${portalName} > div > div:last-child`);
|
|
176
189
|
if (event.key === 'Escape') {
|
|
177
|
-
const lastPortal = document.querySelector(`#${portalName} > div > div:last-child`);
|
|
178
190
|
if (lastPortal) {
|
|
179
191
|
handleClose(lastPortal);
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
if (event.key === 'Tab') {
|
|
196
|
+
const focusableElements = getKeyboardFocusableElements(lastPortal);
|
|
197
|
+
if (focusableElements.length === 0)
|
|
198
|
+
return;
|
|
199
|
+
const firstElement = focusableElements[0];
|
|
200
|
+
const lastElement = focusableElements[focusableElements.length - 1];
|
|
201
|
+
if (event.shiftKey && document.activeElement === firstElement) {
|
|
202
|
+
event.preventDefault();
|
|
203
|
+
lastElement.focus();
|
|
204
|
+
}
|
|
205
|
+
else if (!event.shiftKey && document.activeElement === lastElement) {
|
|
206
|
+
event.preventDefault();
|
|
207
|
+
firstElement.focus();
|
|
180
208
|
}
|
|
181
209
|
}
|
|
182
210
|
};
|
|
@@ -270,7 +298,6 @@ function DContextProvider({ language = DEFAULT_STATE.language, currency = DEFAUL
|
|
|
270
298
|
});
|
|
271
299
|
const setContext = useCallback((newValue) => (setInternalContext((prevInternalContext) => (Object.assign(Object.assign({}, prevInternalContext), newValue)))), []);
|
|
272
300
|
useLayoutEffect(() => {
|
|
273
|
-
console.log('context');
|
|
274
301
|
setContext({
|
|
275
302
|
breakpoints: {
|
|
276
303
|
xs: getCssVariable(`--${PREFIX_BS}breakpoint-xs`),
|
|
@@ -340,18 +367,494 @@ function DBadge({ text, soft = false, theme = 'primary', id, rounded, className,
|
|
|
340
367
|
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 }))] })));
|
|
341
368
|
}
|
|
342
369
|
|
|
370
|
+
/* eslint-disable */
|
|
371
|
+
/**
|
|
372
|
+
* This file is originally from `@primer/react`
|
|
373
|
+
* The original source for this lived in the URL below.
|
|
374
|
+
*
|
|
375
|
+
* @see https://github.com/primer/react/blob/216d2a9f57b8acb0701ab4e04a23e057fc325c90/src/hooks/useProvidedRefOrCreate.ts
|
|
376
|
+
*/
|
|
377
|
+
/**
|
|
378
|
+
* There are some situations where we only want to create a new ref if one is not provided to a component
|
|
379
|
+
* or hook as a prop. However, due to the `rules-of-hooks`, we cannot conditionally make a call to `React.useRef`
|
|
380
|
+
* only in the situations where the ref is not provided as a prop.
|
|
381
|
+
* This hook aims to encapsulate that logic, so the consumer doesn't need to be concerned with violating `rules-of-hooks`.
|
|
382
|
+
* @param providedRef The ref to use - if undefined, will use the ref from a call to React.useRef
|
|
383
|
+
* @type TRef The type of the RefObject which should be created.
|
|
384
|
+
*/
|
|
385
|
+
function useProvidedRefOrCreate(providedRef) {
|
|
386
|
+
const createdRef = React.useRef(null);
|
|
387
|
+
return providedRef !== null && providedRef !== void 0 ? providedRef : createdRef;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
function DInput(_a, ref) {
|
|
391
|
+
var { id: idProp, style, className, label = '', labelIcon, labelIconFamilyClass, labelIconFamilyPrefix, labelIconMaterialStyle, disabled = false, loading = false, iconFamilyClass, iconFamilyPrefix, iconMaterialStyle, iconStart, iconStartDisabled, iconStartFamilyClass, iconStartFamilyPrefix, iconStartAriaLabel, iconStartTabIndex, iconStartMaterialStyle, iconEnd, iconEndDisabled, iconEndFamilyClass, iconEndFamilyPrefix, iconEndAriaLabel, iconEndTabIndex, iconEndMaterialStyle, hint, size, invalid = false, valid = false, floatingLabel = false, inputStart, inputEnd, value, placeholder = '', dataAttributes, onChange, onIconStartClick, onIconEndClick } = _a, inputProps = __rest(_a, ["id", "style", "className", "label", "labelIcon", "labelIconFamilyClass", "labelIconFamilyPrefix", "labelIconMaterialStyle", "disabled", "loading", "iconFamilyClass", "iconFamilyPrefix", "iconMaterialStyle", "iconStart", "iconStartDisabled", "iconStartFamilyClass", "iconStartFamilyPrefix", "iconStartAriaLabel", "iconStartTabIndex", "iconStartMaterialStyle", "iconEnd", "iconEndDisabled", "iconEndFamilyClass", "iconEndFamilyPrefix", "iconEndAriaLabel", "iconEndTabIndex", "iconEndMaterialStyle", "hint", "size", "invalid", "valid", "floatingLabel", "inputStart", "inputEnd", "value", "placeholder", "dataAttributes", "onChange", "onIconStartClick", "onIconEndClick"]);
|
|
392
|
+
const inputRef = useProvidedRefOrCreate(ref);
|
|
393
|
+
const innerId = useId();
|
|
394
|
+
const id = useMemo(() => idProp || innerId, [idProp, innerId]);
|
|
395
|
+
const handleOnChange = useCallback((event) => {
|
|
396
|
+
onChange === null || onChange === void 0 ? void 0 : onChange(event.currentTarget.value);
|
|
397
|
+
}, [onChange]);
|
|
398
|
+
const handleOnIconStartClick = useCallback(() => {
|
|
399
|
+
onIconStartClick === null || onIconStartClick === void 0 ? void 0 : onIconStartClick(value);
|
|
400
|
+
}, [onIconStartClick, value]);
|
|
401
|
+
const handleOnIconEndClick = useCallback(() => {
|
|
402
|
+
onIconEndClick === null || onIconEndClick === void 0 ? void 0 : onIconEndClick(value);
|
|
403
|
+
}, [onIconEndClick, value]);
|
|
404
|
+
const ariaDescribedby = useMemo(() => ([
|
|
405
|
+
!!inputStart && `${id}InputStart`,
|
|
406
|
+
!!iconStart && `${id}Start`,
|
|
407
|
+
(invalid || valid) && !iconEnd && !loading && `${id}State`,
|
|
408
|
+
(iconEnd && !loading) && `${id}End`,
|
|
409
|
+
loading && `${id}Loading`,
|
|
410
|
+
!!inputEnd && `${id}InputEnd`,
|
|
411
|
+
!!hint && `${id}Hint`,
|
|
412
|
+
]
|
|
413
|
+
.filter(Boolean)
|
|
414
|
+
.join(' ')), [
|
|
415
|
+
id,
|
|
416
|
+
inputStart,
|
|
417
|
+
iconStart,
|
|
418
|
+
invalid,
|
|
419
|
+
valid,
|
|
420
|
+
iconEnd,
|
|
421
|
+
loading,
|
|
422
|
+
inputEnd,
|
|
423
|
+
hint,
|
|
424
|
+
]);
|
|
425
|
+
const inputComponent = useMemo(() => (jsx("input", Object.assign({ ref: inputRef, id: id, className: classNames('form-control', {
|
|
426
|
+
'is-invalid': invalid,
|
|
427
|
+
'is-valid': valid,
|
|
428
|
+
}), disabled: disabled || loading, value: value, onChange: handleOnChange }, (floatingLabel || placeholder) && { placeholder: floatingLabel ? '' : placeholder }, ariaDescribedby && { 'aria-describedby': ariaDescribedby }, inputProps))), [
|
|
429
|
+
ariaDescribedby,
|
|
430
|
+
disabled,
|
|
431
|
+
handleOnChange,
|
|
432
|
+
id,
|
|
433
|
+
inputProps,
|
|
434
|
+
inputRef,
|
|
435
|
+
invalid,
|
|
436
|
+
loading,
|
|
437
|
+
placeholder,
|
|
438
|
+
floatingLabel,
|
|
439
|
+
valid,
|
|
440
|
+
value,
|
|
441
|
+
]);
|
|
442
|
+
const labelComponent = useMemo(() => (jsxs("label", { htmlFor: id, children: [label, labelIcon && (jsx(DIcon, { icon: labelIcon, size: `var(--${PREFIX_BS}label-font-size)`, familyClass: labelIconFamilyClass, familyPrefix: labelIconFamilyPrefix, materialStyle: labelIconMaterialStyle }))] })), [
|
|
443
|
+
id,
|
|
444
|
+
label,
|
|
445
|
+
labelIcon,
|
|
446
|
+
labelIconFamilyClass,
|
|
447
|
+
labelIconFamilyPrefix,
|
|
448
|
+
labelIconMaterialStyle,
|
|
449
|
+
]);
|
|
450
|
+
const dynamicComponent = useMemo(() => {
|
|
451
|
+
if (floatingLabel) {
|
|
452
|
+
return (jsxs("div", { className: "form-floating", children: [inputComponent, labelComponent] }));
|
|
453
|
+
}
|
|
454
|
+
return inputComponent;
|
|
455
|
+
}, [floatingLabel, inputComponent, labelComponent]);
|
|
456
|
+
return (jsxs("div", Object.assign({ className: className, style: style }, dataAttributes, { children: [label && !floatingLabel && labelComponent, jsxs("div", { className: classNames({
|
|
457
|
+
[`input-group-${size}`]: !!size,
|
|
458
|
+
'input-group': true,
|
|
459
|
+
'has-validation': invalid || valid,
|
|
460
|
+
}), children: [!!inputStart && (jsx("div", { className: "input-group-text", id: `${id}InputStart`, children: inputStart })), iconStart && (jsx("button", { type: "button", className: "input-group-text", id: `${id}Start`, onClick: handleOnIconStartClick, disabled: disabled || loading || iconStartDisabled, "aria-label": iconStartAriaLabel, tabIndex: onIconStartClick ? iconStartTabIndex : -1, children: jsx(DIcon, { icon: iconStart, familyClass: iconStartFamilyClass, familyPrefix: iconStartFamilyPrefix, materialStyle: iconStartMaterialStyle }) })), 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 }))] })));
|
|
461
|
+
}
|
|
462
|
+
const ForwardedDInput = forwardRef(DInput);
|
|
463
|
+
ForwardedDInput.displayName = 'DInput';
|
|
464
|
+
|
|
465
|
+
/**
|
|
466
|
+
* Check if the provided file type should be accepted by the input with accept attribute.
|
|
467
|
+
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/Input#attr-accept
|
|
468
|
+
*
|
|
469
|
+
* Inspired by https://github.com/enyo/dropzone
|
|
470
|
+
*
|
|
471
|
+
* @param file {File} https://developer.mozilla.org/en-US/docs/Web/API/File
|
|
472
|
+
* @param acceptedFiles {string|string[]}
|
|
473
|
+
* @returns {boolean}
|
|
474
|
+
*/
|
|
475
|
+
function attrAccept(file, acceptedFiles) {
|
|
476
|
+
if (file && acceptedFiles) {
|
|
477
|
+
const acceptedFilesArray = Array.isArray(acceptedFiles)
|
|
478
|
+
? acceptedFiles
|
|
479
|
+
: acceptedFiles.split(',');
|
|
480
|
+
if (acceptedFilesArray.length === 0) {
|
|
481
|
+
return true;
|
|
482
|
+
}
|
|
483
|
+
const fileName = file.name || '';
|
|
484
|
+
const mimeType = (file.type || '').toLowerCase();
|
|
485
|
+
const baseMimeType = mimeType.replace(/\/.*$/, '');
|
|
486
|
+
return acceptedFilesArray.some((type) => {
|
|
487
|
+
const validType = type.trim().toLowerCase();
|
|
488
|
+
if (validType.charAt(0) === '.') {
|
|
489
|
+
return fileName.toLowerCase().endsWith(validType);
|
|
490
|
+
}
|
|
491
|
+
if (validType.endsWith('/*')) {
|
|
492
|
+
// This is something like a image/* mime type
|
|
493
|
+
return baseMimeType === validType.replace(/\/.*$/, '');
|
|
494
|
+
}
|
|
495
|
+
return mimeType === validType;
|
|
496
|
+
});
|
|
497
|
+
}
|
|
498
|
+
return true;
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
const isIeOrEdge = (userAgent = window.navigator.userAgent) => ((userAgent.indexOf('MSIE') !== -1 || userAgent.indexOf('Trident/') !== -1)
|
|
502
|
+
|| userAgent.indexOf('Edge/') !== -1);
|
|
503
|
+
const ErrorCodes = {
|
|
504
|
+
FileInvalidType: 'file-invalid-type',
|
|
505
|
+
FileTooLarge: 'file-too-large',
|
|
506
|
+
FileTooSmall: 'file-too-small',
|
|
507
|
+
TooManyFiles: 'too-many-files',
|
|
508
|
+
FailedFetch: 'failed-fetch-file',
|
|
509
|
+
};
|
|
510
|
+
// Check if v is a MIME type string.
|
|
511
|
+
function isMIMEType(v) {
|
|
512
|
+
return (v === 'audio/*'
|
|
513
|
+
|| v === 'video/*'
|
|
514
|
+
|| v === 'image/*'
|
|
515
|
+
|| v === 'text/*'
|
|
516
|
+
|| v === 'application/*'
|
|
517
|
+
|| /\w+\/[-+.\w]+/g.test(v));
|
|
518
|
+
}
|
|
519
|
+
// Check if v is a file extension.
|
|
520
|
+
function isExt(v) {
|
|
521
|
+
return /^.*\.[\w]+$/.test(v);
|
|
522
|
+
}
|
|
523
|
+
function isDefined(value) {
|
|
524
|
+
return value !== undefined && value !== null;
|
|
525
|
+
}
|
|
526
|
+
// Convert the `{accept}` dropzone prop to an array of MIME types/extensions.
|
|
527
|
+
function acceptPropAsAcceptAttr(accept) {
|
|
528
|
+
return (Object.entries(accept)
|
|
529
|
+
.reduce((a, [mimeType, ext]) => [...a, mimeType, ...ext], [])
|
|
530
|
+
.filter((v) => isMIMEType(v) || isExt(v))
|
|
531
|
+
.join(','));
|
|
532
|
+
}
|
|
533
|
+
function fileAccepted(file, accept) {
|
|
534
|
+
const isAcceptable = file.type === 'application/x-moz-file' || attrAccept(file, accept);
|
|
535
|
+
if (!isAcceptable) {
|
|
536
|
+
return [
|
|
537
|
+
false,
|
|
538
|
+
{
|
|
539
|
+
code: ErrorCodes.FileInvalidType,
|
|
540
|
+
message: 'File has an unsupported file type',
|
|
541
|
+
},
|
|
542
|
+
];
|
|
543
|
+
}
|
|
544
|
+
return [true, null];
|
|
545
|
+
}
|
|
546
|
+
function fileMatchSize(file, minSize, maxSize) {
|
|
547
|
+
if (isDefined(file.size)) {
|
|
548
|
+
if (isDefined(minSize) && file.size < minSize) {
|
|
549
|
+
return [
|
|
550
|
+
false,
|
|
551
|
+
{
|
|
552
|
+
code: ErrorCodes.FileTooSmall,
|
|
553
|
+
message: `File "${file.name}" is too small. Minimum size is ${minSize} bytes.`,
|
|
554
|
+
},
|
|
555
|
+
];
|
|
556
|
+
}
|
|
557
|
+
if (isDefined(maxSize) && file.size > maxSize) {
|
|
558
|
+
return [
|
|
559
|
+
false, {
|
|
560
|
+
code: ErrorCodes.FileTooLarge,
|
|
561
|
+
message: `File "${file.name}" is too large. Maximum size is ${maxSize} bytes.`,
|
|
562
|
+
},
|
|
563
|
+
];
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
return [true, null];
|
|
567
|
+
}
|
|
568
|
+
async function urlToFile(url) {
|
|
569
|
+
var _a;
|
|
570
|
+
try {
|
|
571
|
+
const res = await fetch(url);
|
|
572
|
+
if (!res.ok) {
|
|
573
|
+
return [
|
|
574
|
+
null,
|
|
575
|
+
{
|
|
576
|
+
code: ErrorCodes.FailedFetch,
|
|
577
|
+
message: `Failed to fetch file from ${url}`,
|
|
578
|
+
},
|
|
579
|
+
];
|
|
580
|
+
}
|
|
581
|
+
const blob = await res.blob();
|
|
582
|
+
const filename = ((_a = url.split('/').pop()) === null || _a === void 0 ? void 0 : _a.split('?')[0]) || 'file';
|
|
583
|
+
const file = new File([blob], filename, { type: blob.type });
|
|
584
|
+
return [file, null];
|
|
585
|
+
}
|
|
586
|
+
catch (error) {
|
|
587
|
+
return [
|
|
588
|
+
null,
|
|
589
|
+
{
|
|
590
|
+
code: ErrorCodes.FailedFetch,
|
|
591
|
+
message: `Failed to fetch file from ${url}}`,
|
|
592
|
+
},
|
|
593
|
+
];
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
async function urlsToFiles(urls) {
|
|
597
|
+
const results = await Promise.all(urls.map(urlToFile));
|
|
598
|
+
let acceptedFiles = [];
|
|
599
|
+
let errors = [];
|
|
600
|
+
results.forEach(([file, error]) => {
|
|
601
|
+
if (file) {
|
|
602
|
+
acceptedFiles = [...acceptedFiles, file];
|
|
603
|
+
}
|
|
604
|
+
if (error) {
|
|
605
|
+
errors = [...errors, error];
|
|
606
|
+
}
|
|
607
|
+
});
|
|
608
|
+
return [acceptedFiles, errors];
|
|
609
|
+
}
|
|
610
|
+
const DEFAULT_PROPS = {
|
|
611
|
+
disabled: false,
|
|
612
|
+
maxSize: Infinity,
|
|
613
|
+
minSize: 0,
|
|
614
|
+
multiple: false,
|
|
615
|
+
maxFiles: Infinity,
|
|
616
|
+
noClick: false,
|
|
617
|
+
noKeyboard: false,
|
|
618
|
+
noDrag: false,
|
|
619
|
+
autoFocus: false,
|
|
620
|
+
};
|
|
621
|
+
|
|
622
|
+
/* eslint-disable no-param-reassign */
|
|
623
|
+
function useDBoxFile(props) {
|
|
624
|
+
const { accept, autoFocus, disabled, maxSize, minSize, multiple, maxFiles, value: preloadUrls, onDragEnter, onDragLeave, onDrop, onError, noClick, noKeyboard, noDrag, } = Object.assign(Object.assign({}, DEFAULT_PROPS), props);
|
|
625
|
+
const inputRef = useRef(null);
|
|
626
|
+
const rootRef = useRef(null);
|
|
627
|
+
const dragTargetsRef = useRef([]);
|
|
628
|
+
const acceptAttr = useMemo(() => acceptPropAsAcceptAttr(accept), [accept]);
|
|
629
|
+
const [files, setFiles] = useState([]);
|
|
630
|
+
const [isDragValid, setIsDragValid] = useState(false);
|
|
631
|
+
const [isDragInvalid, setIsDragInvalid] = useState(false);
|
|
632
|
+
const preventDropOnDocument = useCallback((event) => {
|
|
633
|
+
if (rootRef.current && rootRef.current.contains(event.target)) {
|
|
634
|
+
// If we intercepted an event for our instance
|
|
635
|
+
// let it propagate down to the instance's onDrop handler
|
|
636
|
+
return;
|
|
637
|
+
}
|
|
638
|
+
event.preventDefault();
|
|
639
|
+
dragTargetsRef.current = [];
|
|
640
|
+
}, []);
|
|
641
|
+
useEffect(() => {
|
|
642
|
+
// Prevent drop over anywhere in the document
|
|
643
|
+
document.addEventListener('dragover', preventDropOnDocument, false);
|
|
644
|
+
document.addEventListener('drop', preventDropOnDocument, false);
|
|
645
|
+
return () => {
|
|
646
|
+
document.removeEventListener('dragover', preventDropOnDocument);
|
|
647
|
+
document.removeEventListener('drop', preventDropOnDocument);
|
|
648
|
+
};
|
|
649
|
+
}, [preventDropOnDocument]);
|
|
650
|
+
// Auto focus the root when autoFocus is true
|
|
651
|
+
useEffect(() => {
|
|
652
|
+
if (!disabled && autoFocus && rootRef.current) {
|
|
653
|
+
rootRef.current.focus();
|
|
654
|
+
}
|
|
655
|
+
}, [rootRef, autoFocus, disabled]);
|
|
656
|
+
useEffect(() => {
|
|
657
|
+
if (!preloadUrls || !preloadUrls.length)
|
|
658
|
+
return;
|
|
659
|
+
// eslint-disable-next-line no-void
|
|
660
|
+
void (async () => {
|
|
661
|
+
const [accepted, errors] = await urlsToFiles(preloadUrls);
|
|
662
|
+
if (accepted.length) {
|
|
663
|
+
setFiles(accepted);
|
|
664
|
+
}
|
|
665
|
+
if (errors.length) {
|
|
666
|
+
onError === null || onError === void 0 ? void 0 : onError(new Error(errors.map((e) => e.message).join(', ')));
|
|
667
|
+
}
|
|
668
|
+
})();
|
|
669
|
+
}, [preloadUrls, onError]);
|
|
670
|
+
const processFiles = useCallback((inputFiles, event) => {
|
|
671
|
+
let acceptedFiles = [];
|
|
672
|
+
let rejectedFiles = [];
|
|
673
|
+
// Handle size and type validation
|
|
674
|
+
inputFiles.forEach((file) => {
|
|
675
|
+
const [isTypeValid, acceptError] = fileAccepted(file, acceptAttr);
|
|
676
|
+
const [isSizeValid, sizeError] = fileMatchSize(file, minSize, maxSize);
|
|
677
|
+
const errors = [acceptError, sizeError].filter((e) => Boolean(e));
|
|
678
|
+
if (isTypeValid && isSizeValid) {
|
|
679
|
+
acceptedFiles = [...acceptedFiles, file];
|
|
680
|
+
}
|
|
681
|
+
else {
|
|
682
|
+
rejectedFiles = [...rejectedFiles, { file, errors }];
|
|
683
|
+
}
|
|
684
|
+
});
|
|
685
|
+
// Handle maxFiles overflow by trimming
|
|
686
|
+
const total = files.length + acceptedFiles.length;
|
|
687
|
+
if (total > maxFiles) {
|
|
688
|
+
const allowed = Math.max(0, maxFiles - files.length);
|
|
689
|
+
const accepted = acceptedFiles.slice(0, allowed);
|
|
690
|
+
const rejected = acceptedFiles.slice(allowed).map((file) => ({
|
|
691
|
+
file,
|
|
692
|
+
errors: [
|
|
693
|
+
{
|
|
694
|
+
code: ErrorCodes.TooManyFiles,
|
|
695
|
+
message: `Exceeds maximum number of files (${maxFiles})`,
|
|
696
|
+
},
|
|
697
|
+
],
|
|
698
|
+
}));
|
|
699
|
+
acceptedFiles = [...accepted];
|
|
700
|
+
rejectedFiles = [...rejectedFiles, ...rejected];
|
|
701
|
+
}
|
|
702
|
+
if (multiple) {
|
|
703
|
+
setFiles((prev) => [...prev, ...acceptedFiles]);
|
|
704
|
+
}
|
|
705
|
+
else {
|
|
706
|
+
setFiles(acceptedFiles.slice(0, 1));
|
|
707
|
+
}
|
|
708
|
+
if (onDrop) {
|
|
709
|
+
onDrop(acceptedFiles, rejectedFiles, event);
|
|
710
|
+
}
|
|
711
|
+
}, [
|
|
712
|
+
acceptAttr,
|
|
713
|
+
files.length,
|
|
714
|
+
maxFiles,
|
|
715
|
+
maxSize,
|
|
716
|
+
minSize,
|
|
717
|
+
multiple,
|
|
718
|
+
onDrop,
|
|
719
|
+
]);
|
|
720
|
+
const handleDragEnter = useCallback((event) => {
|
|
721
|
+
event.preventDefault();
|
|
722
|
+
event.stopPropagation();
|
|
723
|
+
if (disabled || noDrag)
|
|
724
|
+
return;
|
|
725
|
+
if (event.target instanceof HTMLElement) {
|
|
726
|
+
dragTargetsRef.current = [...dragTargetsRef.current, event.target];
|
|
727
|
+
}
|
|
728
|
+
fromEvent(event).then((eventFiles) => {
|
|
729
|
+
const fileCount = eventFiles.length;
|
|
730
|
+
if (fileCount === 0) {
|
|
731
|
+
setIsDragValid(false);
|
|
732
|
+
setIsDragInvalid(true);
|
|
733
|
+
return;
|
|
734
|
+
}
|
|
735
|
+
const isDragAccepted = eventFiles.every((file) => {
|
|
736
|
+
const [typeValid] = fileAccepted(file, acceptAttr);
|
|
737
|
+
const [sizeValid] = fileMatchSize(file, minSize, maxSize);
|
|
738
|
+
return typeValid && sizeValid;
|
|
739
|
+
});
|
|
740
|
+
setIsDragValid(isDragAccepted);
|
|
741
|
+
setIsDragInvalid(!isDragAccepted);
|
|
742
|
+
onDragEnter === null || onDragEnter === void 0 ? void 0 : onDragEnter(event);
|
|
743
|
+
}).catch((error) => {
|
|
744
|
+
onError === null || onError === void 0 ? void 0 : onError(error);
|
|
745
|
+
});
|
|
746
|
+
}, [
|
|
747
|
+
acceptAttr,
|
|
748
|
+
disabled,
|
|
749
|
+
maxSize,
|
|
750
|
+
minSize,
|
|
751
|
+
noDrag,
|
|
752
|
+
onDragEnter,
|
|
753
|
+
onError,
|
|
754
|
+
]);
|
|
755
|
+
const handleDrop = useCallback((event) => {
|
|
756
|
+
event.preventDefault();
|
|
757
|
+
event.persist();
|
|
758
|
+
event.stopPropagation();
|
|
759
|
+
dragTargetsRef.current = [];
|
|
760
|
+
setIsDragValid(false);
|
|
761
|
+
setIsDragInvalid(false);
|
|
762
|
+
if (disabled || noDrag)
|
|
763
|
+
return;
|
|
764
|
+
const droppedArray = Array.from(event.dataTransfer.files);
|
|
765
|
+
processFiles(droppedArray, event.nativeEvent);
|
|
766
|
+
}, [
|
|
767
|
+
disabled,
|
|
768
|
+
noDrag,
|
|
769
|
+
processFiles,
|
|
770
|
+
]);
|
|
771
|
+
const handleDragLeave = useCallback((event) => {
|
|
772
|
+
event.preventDefault();
|
|
773
|
+
event.stopPropagation();
|
|
774
|
+
if (disabled || noDrag)
|
|
775
|
+
return;
|
|
776
|
+
// Only deactivate once the dropzone and all children have been left
|
|
777
|
+
const targets = dragTargetsRef.current.filter((target) => rootRef.current && rootRef.current.contains(target));
|
|
778
|
+
// Make sure to remove a target present multiple times only once
|
|
779
|
+
// (Firefox may fire dragenter/dragleave multiple times on the same element)
|
|
780
|
+
if (event.target instanceof HTMLElement) {
|
|
781
|
+
const targetIdx = targets.indexOf(event.target);
|
|
782
|
+
if (targetIdx !== -1) {
|
|
783
|
+
targets.splice(targetIdx, 1);
|
|
784
|
+
}
|
|
785
|
+
dragTargetsRef.current = targets;
|
|
786
|
+
}
|
|
787
|
+
if (targets.length === 0) {
|
|
788
|
+
setIsDragValid(false);
|
|
789
|
+
setIsDragInvalid(false);
|
|
790
|
+
onDragLeave === null || onDragLeave === void 0 ? void 0 : onDragLeave(event);
|
|
791
|
+
}
|
|
792
|
+
}, [disabled, noDrag, onDragLeave]);
|
|
793
|
+
const handleFileSelect = useCallback((event) => {
|
|
794
|
+
const targetFiles = event.target.files;
|
|
795
|
+
if (!targetFiles)
|
|
796
|
+
return;
|
|
797
|
+
const selectedFiles = Array.from(targetFiles);
|
|
798
|
+
processFiles(selectedFiles, event.nativeEvent);
|
|
799
|
+
event.target.value = '';
|
|
800
|
+
}, [processFiles]);
|
|
801
|
+
const handleRemoveFile = useCallback((index) => {
|
|
802
|
+
setFiles((prevFiles) => prevFiles.filter((_, i) => i !== index));
|
|
803
|
+
}, []);
|
|
804
|
+
const openFileDialog = useCallback(() => {
|
|
805
|
+
var _a;
|
|
806
|
+
if (disabled)
|
|
807
|
+
return;
|
|
808
|
+
(_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.click();
|
|
809
|
+
}, [disabled]);
|
|
810
|
+
const handleClick = useCallback(() => {
|
|
811
|
+
if (noClick) {
|
|
812
|
+
return;
|
|
813
|
+
}
|
|
814
|
+
if (isIeOrEdge()) {
|
|
815
|
+
setTimeout(openFileDialog, 0);
|
|
816
|
+
}
|
|
817
|
+
else {
|
|
818
|
+
openFileDialog();
|
|
819
|
+
}
|
|
820
|
+
}, [noClick, openFileDialog]);
|
|
821
|
+
const handleKeyDown = useCallback((event) => {
|
|
822
|
+
if (!noKeyboard && (event.key === ' ' || event.key === 'Enter')) {
|
|
823
|
+
event.preventDefault();
|
|
824
|
+
openFileDialog();
|
|
825
|
+
}
|
|
826
|
+
}, [noKeyboard, openFileDialog]);
|
|
827
|
+
return {
|
|
828
|
+
inputRef,
|
|
829
|
+
rootRef,
|
|
830
|
+
files,
|
|
831
|
+
isDragValid,
|
|
832
|
+
isDragInvalid,
|
|
833
|
+
acceptAttr,
|
|
834
|
+
openFileDialog,
|
|
835
|
+
handleFileSelect,
|
|
836
|
+
handleDrop,
|
|
837
|
+
handleDragEnter,
|
|
838
|
+
handleDragLeave,
|
|
839
|
+
handleRemoveFile,
|
|
840
|
+
handleClick,
|
|
841
|
+
handleKeyDown,
|
|
842
|
+
};
|
|
843
|
+
}
|
|
844
|
+
|
|
343
845
|
function DBoxFile(_a) {
|
|
344
|
-
var { icon: iconProp, iconFamilyClass, iconFamilyPrefix, iconMaterialStyle,
|
|
345
|
-
const {
|
|
346
|
-
const { iconMap: { upload, }, } = useDContext();
|
|
846
|
+
var { icon: iconProp, iconFamilyClass, iconFamilyPrefix, iconMaterialStyle, children, className, style, dataAttributes } = _a, props = __rest(_a, ["icon", "iconFamilyClass", "iconFamilyPrefix", "iconMaterialStyle", "children", "className", "style", "dataAttributes"]);
|
|
847
|
+
const { iconMap: { upload } } = useDContext();
|
|
347
848
|
const icon = useMemo(() => iconProp || upload, [iconProp, upload]);
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
849
|
+
const { inputRef, rootRef, isDragValid, isDragInvalid, acceptAttr, files, handleFileSelect, handleDrop, handleDragEnter, handleDragLeave, handleClick, handleKeyDown, handleRemoveFile, openFileDialog, } = useDBoxFile(props);
|
|
850
|
+
return (jsxs(Fragment$1, { children: [jsx("section", Object.assign({ className: classNames('d-box-file', {
|
|
851
|
+
'd-box-file-selected': files.length > 0,
|
|
852
|
+
'd-box-file-disabled': props.disabled,
|
|
853
|
+
'd-box-file-valid': isDragValid,
|
|
854
|
+
'd-box-file-invalid': isDragInvalid,
|
|
855
|
+
}, 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 }), jsx(DIcon, { icon: icon, familyClass: iconFamilyClass, familyPrefix: iconFamilyPrefix, materialStyle: iconMaterialStyle }), jsx("div", { className: "d-box-content", children: typeof children === 'function'
|
|
856
|
+
? children(openFileDialog)
|
|
857
|
+
: children })] })) })), !!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))) }))] }));
|
|
355
858
|
}
|
|
356
859
|
|
|
357
860
|
function DButton({ theme = 'primary', size, variant, state, text = '', ariaLabel, iconStart, iconStartFamilyClass, iconStartFamilyPrefix, iconStartMaterialStyle, iconEnd, iconEndFamilyClass, iconEndFamilyPrefix, iconEndMaterialStyle, value, type = 'button', loading = false, loadingAriaLabel, disabled = false, stopPropagationEnabled = true, className, style, form, dataAttributes, onClick, }) {
|
|
@@ -492,102 +995,6 @@ function DCurrencyText({ value, className, style, dataAttributes, }) {
|
|
|
492
995
|
return (jsx("span", Object.assign({ className: className, style: style }, dataAttributes, { children: valueFormatted })));
|
|
493
996
|
}
|
|
494
997
|
|
|
495
|
-
/* eslint-disable */
|
|
496
|
-
/**
|
|
497
|
-
* This file is originally from `@primer/react`
|
|
498
|
-
* The original source for this lived in the URL below.
|
|
499
|
-
*
|
|
500
|
-
* @see https://github.com/primer/react/blob/216d2a9f57b8acb0701ab4e04a23e057fc325c90/src/hooks/useProvidedRefOrCreate.ts
|
|
501
|
-
*/
|
|
502
|
-
/**
|
|
503
|
-
* There are some situations where we only want to create a new ref if one is not provided to a component
|
|
504
|
-
* or hook as a prop. However, due to the `rules-of-hooks`, we cannot conditionally make a call to `React.useRef`
|
|
505
|
-
* only in the situations where the ref is not provided as a prop.
|
|
506
|
-
* This hook aims to encapsulate that logic, so the consumer doesn't need to be concerned with violating `rules-of-hooks`.
|
|
507
|
-
* @param providedRef The ref to use - if undefined, will use the ref from a call to React.useRef
|
|
508
|
-
* @type TRef The type of the RefObject which should be created.
|
|
509
|
-
*/
|
|
510
|
-
function useProvidedRefOrCreate(providedRef) {
|
|
511
|
-
const createdRef = React.useRef(null);
|
|
512
|
-
return providedRef !== null && providedRef !== void 0 ? providedRef : createdRef;
|
|
513
|
-
}
|
|
514
|
-
|
|
515
|
-
function DInput(_a, ref) {
|
|
516
|
-
var { id: idProp, style, className, label = '', labelIcon, labelIconFamilyClass, labelIconFamilyPrefix, labelIconMaterialStyle, disabled = false, loading = false, iconFamilyClass, iconFamilyPrefix, iconMaterialStyle, iconStart, iconStartDisabled, iconStartFamilyClass, iconStartFamilyPrefix, iconStartAriaLabel, iconStartTabIndex, iconStartMaterialStyle, iconEnd, iconEndDisabled, iconEndFamilyClass, iconEndFamilyPrefix, iconEndAriaLabel, iconEndTabIndex, iconEndMaterialStyle, hint, size, invalid = false, valid = false, floatingLabel = false, inputStart, inputEnd, value, placeholder = '', dataAttributes, onChange, onIconStartClick, onIconEndClick } = _a, inputProps = __rest(_a, ["id", "style", "className", "label", "labelIcon", "labelIconFamilyClass", "labelIconFamilyPrefix", "labelIconMaterialStyle", "disabled", "loading", "iconFamilyClass", "iconFamilyPrefix", "iconMaterialStyle", "iconStart", "iconStartDisabled", "iconStartFamilyClass", "iconStartFamilyPrefix", "iconStartAriaLabel", "iconStartTabIndex", "iconStartMaterialStyle", "iconEnd", "iconEndDisabled", "iconEndFamilyClass", "iconEndFamilyPrefix", "iconEndAriaLabel", "iconEndTabIndex", "iconEndMaterialStyle", "hint", "size", "invalid", "valid", "floatingLabel", "inputStart", "inputEnd", "value", "placeholder", "dataAttributes", "onChange", "onIconStartClick", "onIconEndClick"]);
|
|
517
|
-
const inputRef = useProvidedRefOrCreate(ref);
|
|
518
|
-
const innerId = useId();
|
|
519
|
-
const id = useMemo(() => idProp || innerId, [idProp, innerId]);
|
|
520
|
-
const handleOnChange = useCallback((event) => {
|
|
521
|
-
onChange === null || onChange === void 0 ? void 0 : onChange(event.currentTarget.value);
|
|
522
|
-
}, [onChange]);
|
|
523
|
-
const handleOnIconStartClick = useCallback(() => {
|
|
524
|
-
onIconStartClick === null || onIconStartClick === void 0 ? void 0 : onIconStartClick(value);
|
|
525
|
-
}, [onIconStartClick, value]);
|
|
526
|
-
const handleOnIconEndClick = useCallback(() => {
|
|
527
|
-
onIconEndClick === null || onIconEndClick === void 0 ? void 0 : onIconEndClick(value);
|
|
528
|
-
}, [onIconEndClick, value]);
|
|
529
|
-
const ariaDescribedby = useMemo(() => ([
|
|
530
|
-
!!inputStart && `${id}InputStart`,
|
|
531
|
-
!!iconStart && `${id}Start`,
|
|
532
|
-
(invalid || valid) && !iconEnd && !loading && `${id}State`,
|
|
533
|
-
(iconEnd && !loading) && `${id}End`,
|
|
534
|
-
loading && `${id}Loading`,
|
|
535
|
-
!!inputEnd && `${id}InputEnd`,
|
|
536
|
-
!!hint && `${id}Hint`,
|
|
537
|
-
]
|
|
538
|
-
.filter(Boolean)
|
|
539
|
-
.join(' ')), [
|
|
540
|
-
id,
|
|
541
|
-
inputStart,
|
|
542
|
-
iconStart,
|
|
543
|
-
invalid,
|
|
544
|
-
valid,
|
|
545
|
-
iconEnd,
|
|
546
|
-
loading,
|
|
547
|
-
inputEnd,
|
|
548
|
-
hint,
|
|
549
|
-
]);
|
|
550
|
-
const inputComponent = useMemo(() => (jsx("input", Object.assign({ ref: inputRef, id: id, className: classNames('form-control', {
|
|
551
|
-
[`form-control-${size}`]: !!size,
|
|
552
|
-
'is-invalid': invalid,
|
|
553
|
-
'is-valid': valid,
|
|
554
|
-
}), disabled: disabled || loading, value: value, onChange: handleOnChange }, (floatingLabel || placeholder) && { placeholder: floatingLabel ? '' : placeholder }, ariaDescribedby && { 'aria-describedby': ariaDescribedby }, inputProps))), [
|
|
555
|
-
ariaDescribedby,
|
|
556
|
-
disabled,
|
|
557
|
-
handleOnChange,
|
|
558
|
-
id,
|
|
559
|
-
inputProps,
|
|
560
|
-
inputRef,
|
|
561
|
-
invalid,
|
|
562
|
-
loading,
|
|
563
|
-
placeholder,
|
|
564
|
-
floatingLabel,
|
|
565
|
-
valid,
|
|
566
|
-
value,
|
|
567
|
-
size,
|
|
568
|
-
]);
|
|
569
|
-
const labelComponent = useMemo(() => (jsxs("label", { htmlFor: id, children: [label, labelIcon && (jsx(DIcon, { icon: labelIcon, size: `var(--${PREFIX_BS}label-font-size)`, familyClass: labelIconFamilyClass, familyPrefix: labelIconFamilyPrefix, materialStyle: labelIconMaterialStyle }))] })), [
|
|
570
|
-
id,
|
|
571
|
-
label,
|
|
572
|
-
labelIcon,
|
|
573
|
-
labelIconFamilyClass,
|
|
574
|
-
labelIconFamilyPrefix,
|
|
575
|
-
labelIconMaterialStyle,
|
|
576
|
-
]);
|
|
577
|
-
const dynamicComponent = useMemo(() => {
|
|
578
|
-
if (floatingLabel) {
|
|
579
|
-
return (jsxs("div", { className: "form-floating", children: [inputComponent, labelComponent] }));
|
|
580
|
-
}
|
|
581
|
-
return inputComponent;
|
|
582
|
-
}, [floatingLabel, inputComponent, labelComponent]);
|
|
583
|
-
return (jsxs("div", Object.assign({ className: className, style: style }, dataAttributes, { children: [label && !floatingLabel && labelComponent, jsxs("div", { className: classNames({
|
|
584
|
-
'input-group': true,
|
|
585
|
-
'has-validation': invalid || valid,
|
|
586
|
-
}), children: [!!inputStart && (jsx("div", { className: "input-group-text", id: `${id}InputStart`, children: inputStart })), iconStart && (jsx("button", { type: "button", className: "input-group-text", id: `${id}Start`, onClick: handleOnIconStartClick, disabled: disabled || loading || iconStartDisabled, "aria-label": iconStartAriaLabel, tabIndex: onIconStartClick ? iconStartTabIndex : -1, children: jsx(DIcon, { icon: iconStart, familyClass: iconStartFamilyClass, familyPrefix: iconStartFamilyPrefix, materialStyle: iconStartMaterialStyle }) })), 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 }))] })));
|
|
587
|
-
}
|
|
588
|
-
const ForwardedDInput = forwardRef(DInput);
|
|
589
|
-
ForwardedDInput.displayName = 'DInput';
|
|
590
|
-
|
|
591
998
|
function DDatePickerTime(_a) {
|
|
592
999
|
var { value, onChange, id, label, className, style } = _a, props = __rest(_a, ["value", "onChange", "id", "label", "className", "style"]);
|
|
593
1000
|
return (jsxs("div", { className: classNames('d-flex align-items-center gap-2 flex-column d-datepicker-time', className), style: style, children: [label && (jsx("label", { htmlFor: id, className: "d-datepicker-time-label", children: label })), jsx(ForwardedDInput, Object.assign({ className: "w-100" }, onChange && {
|
|
@@ -597,7 +1004,8 @@ function DDatePickerTime(_a) {
|
|
|
597
1004
|
|
|
598
1005
|
function DDatePickerInput(_a, ref) {
|
|
599
1006
|
var { value, onClick, id, iconEnd, className, style, inputLabel, readOnly: ignored } = _a, props = __rest(_a, ["value", "onClick", "id", "iconEnd", "className", "style", "inputLabel", "readOnly"]);
|
|
600
|
-
|
|
1007
|
+
const { iconMap: { calendar } } = useDContext();
|
|
1008
|
+
return (jsx(ForwardedDInput, Object.assign({ ref: ref, onClick: onClick, readOnly: true, type: "text", id: id, value: value, onIconEndClick: onClick, iconEnd: iconEnd || calendar, className: className, style: style, label: inputLabel }, props)));
|
|
601
1009
|
}
|
|
602
1010
|
const ForwardedDDatePickerInput = forwardRef(DDatePickerInput);
|
|
603
1011
|
ForwardedDDatePickerInput.displayName = 'DDatePickerInput';
|
|
@@ -681,8 +1089,8 @@ function DSelectDropdownIndicator(props) {
|
|
|
681
1089
|
}
|
|
682
1090
|
|
|
683
1091
|
function DSelectClearIndicator(props) {
|
|
684
|
-
const { iconMap: {
|
|
685
|
-
return (jsx(components.ClearIndicator, Object.assign({}, props, { children: jsx(DIcon, { icon:
|
|
1092
|
+
const { iconMap: { x, }, } = useDContext();
|
|
1093
|
+
return (jsx(components.ClearIndicator, Object.assign({}, props, { children: jsx(DIcon, { icon: x }) })));
|
|
686
1094
|
}
|
|
687
1095
|
|
|
688
1096
|
function DSelectMultiValueRemove(props) {
|
|
@@ -766,43 +1174,65 @@ var DSelect$1 = Object.assign(DSelect, {
|
|
|
766
1174
|
Placeholder: DSelectPlaceholder,
|
|
767
1175
|
});
|
|
768
1176
|
|
|
769
|
-
|
|
1177
|
+
var PickerType;
|
|
1178
|
+
(function (PickerType) {
|
|
1179
|
+
PickerType["Default"] = "default";
|
|
1180
|
+
PickerType["Quarter"] = "quarter";
|
|
1181
|
+
PickerType["Month"] = "month";
|
|
1182
|
+
PickerType["Year"] = "year";
|
|
1183
|
+
})(PickerType || (PickerType = {}));
|
|
1184
|
+
function DDatePickerHeaderSelector({ date, changeYear, changeMonth, decreaseMonth, increaseMonth, decreaseYear, increaseYear, monthDate, pickerType, prevMonthButtonDisabled, nextMonthButtonDisabled, monthsShown = 1, iconPrev, iconNext, prevYearButtonDisabled, nextYearButtonDisabled, iconFamilyClass, iconFamilyPrefix, iconMaterialStyle = false, prevMonthAriaLabel = 'decrease month', nextMonthAriaLabel = 'increase month', prevYearAriaLabel = 'decrease year', nextYearAriaLabel = 'increase year', iconSize = 'sm', buttonVariant = 'link', buttonTheme = 'dark', style, className, minYearSelect = 1900, maxYearSelect = 2100, showHeaderSelectors = false, customHeaderCount, }) {
|
|
1185
|
+
const { iconMap: { chevronLeft, chevronRight, }, } = useDContext();
|
|
770
1186
|
const arrayYears = useMemo(() => Array.from({ length: maxYearSelect - minYearSelect + 1 }, (_, index) => minYearSelect + index), [maxYearSelect, minYearSelect]);
|
|
771
1187
|
const years = useMemo(() => arrayYears.map((year) => ({
|
|
772
1188
|
label: year.toString(),
|
|
773
1189
|
value: year,
|
|
774
1190
|
})), [arrayYears]);
|
|
775
|
-
const defaultYear = useMemo(() => years.find((year) => year.value === getYear(
|
|
776
|
-
const arrayMonths = useMemo(() => Array.from({ length: 12 }, (_, i) => format(new Date(2000, i), 'LLLL', { locale })), [
|
|
1191
|
+
const defaultYear = useMemo(() => years.find((year) => year.value === getYear(monthDate)), [monthDate, years]);
|
|
1192
|
+
const arrayMonths = useMemo(() => Array.from({ length: 12 }, (_, i) => format(new Date(2000, i), 'LLLL', { locale: enUS })), []);
|
|
777
1193
|
const months = useMemo(() => arrayMonths.map((month, i) => ({
|
|
778
1194
|
label: month,
|
|
779
1195
|
value: i,
|
|
780
1196
|
})), [arrayMonths]);
|
|
781
1197
|
const defaultMonth = useMemo(() => ({
|
|
782
|
-
label: arrayMonths[getMonth(
|
|
783
|
-
value: getMonth(
|
|
784
|
-
}), [arrayMonths,
|
|
785
|
-
|
|
1198
|
+
label: arrayMonths[getMonth(monthDate)],
|
|
1199
|
+
value: getMonth(monthDate),
|
|
1200
|
+
}), [arrayMonths, monthDate]);
|
|
1201
|
+
const getYearRange = useCallback(() => {
|
|
1202
|
+
const blockIndex = Math.floor((date.getFullYear() - 1) / 12);
|
|
1203
|
+
const startYear = blockIndex * 12 + 1;
|
|
1204
|
+
const endYear = startYear + 11;
|
|
1205
|
+
return [startYear, endYear];
|
|
1206
|
+
}, [date]);
|
|
1207
|
+
const [startYear, endYear] = getYearRange();
|
|
1208
|
+
if (pickerType === PickerType.Year) {
|
|
1209
|
+
return (jsxs("div", { className: classNames('react-datepicker__header-selector react-datepicker__header-year-selector', className), style: style, children: [jsx(DButton, { iconStart: iconPrev || chevronLeft, iconStartFamilyClass: iconFamilyClass, iconStartFamilyPrefix: iconFamilyPrefix, iconStartMaterialStyle: iconMaterialStyle, size: iconSize, variant: buttonVariant, theme: buttonTheme, onClick: decreaseYear, disabled: prevYearButtonDisabled, ariaLabel: prevYearAriaLabel, className: "header-button" }), jsx("p", { children: `${startYear} - ${endYear}` }), jsx(DButton, { iconStart: iconNext || chevronRight, iconStartFamilyClass: iconFamilyClass, iconStartFamilyPrefix: iconFamilyPrefix, iconStartMaterialStyle: iconMaterialStyle, size: iconSize, variant: buttonVariant, theme: buttonTheme, onClick: increaseYear, disabled: nextYearButtonDisabled, ariaLabel: nextYearAriaLabel, className: "header-button" })] }));
|
|
1210
|
+
}
|
|
1211
|
+
if (pickerType === PickerType.Quarter || pickerType === PickerType.Month) {
|
|
1212
|
+
return (jsxs("div", { className: classNames(`react-datepicker__header-selector react-datepicker__header-${pickerType}-selector`, className), style: style, children: [jsx(DButton, { iconStart: iconPrev || chevronLeft, iconStartFamilyClass: iconFamilyClass, iconStartFamilyPrefix: iconFamilyPrefix, iconStartMaterialStyle: iconMaterialStyle, size: iconSize, variant: buttonVariant, theme: buttonTheme, onClick: decreaseYear, disabled: prevMonthButtonDisabled, ariaLabel: prevMonthAriaLabel, className: "header-button", style: { visibility: customHeaderCount === 0 ? 'visible' : 'hidden' } }), jsx("div", { className: "d-flex justify-content-center flex-grow-1", 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(DButton, { iconStart: iconNext || chevronRight, iconStartFamilyClass: iconFamilyClass, iconStartFamilyPrefix: iconFamilyPrefix, iconStartMaterialStyle: iconMaterialStyle, size: iconSize, variant: buttonVariant, theme: buttonTheme, onClick: increaseYear, disabled: nextMonthButtonDisabled, ariaLabel: nextMonthAriaLabel, className: "header-button", style: { visibility: customHeaderCount === monthsShown - 1 ? 'visible' : 'hidden' } })] }));
|
|
1213
|
+
}
|
|
1214
|
+
return (jsxs("div", { className: classNames('react-datepicker__header-selector react-datepicker__header-day-selector', className), style: style, children: [jsx(DButton, { iconStart: iconPrev || chevronLeft, iconStartFamilyClass: iconFamilyClass, iconStartFamilyPrefix: iconFamilyPrefix, iconStartMaterialStyle: iconMaterialStyle, size: iconSize, variant: buttonVariant, theme: buttonTheme, onClick: decreaseMonth, disabled: prevMonthButtonDisabled, ariaLabel: prevMonthAriaLabel, className: "header-button", style: { visibility: customHeaderCount === 0 ? 'visible' : 'hidden' } }), showHeaderSelectors ? (jsxs(Fragment$1, { children: [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(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("p", { children: `${defaultMonth.label} ${defaultYear === null || defaultYear === void 0 ? void 0 : defaultYear.label}` })), jsx(DButton, { iconStart: iconNext || chevronRight, iconStartFamilyClass: iconFamilyClass, iconStartFamilyPrefix: iconFamilyPrefix, iconStartMaterialStyle: iconMaterialStyle, size: iconSize, variant: buttonVariant, theme: buttonTheme, onClick: increaseMonth, disabled: nextMonthButtonDisabled, ariaLabel: nextMonthAriaLabel, className: "header-button", style: { visibility: customHeaderCount === monthsShown - 1 ? 'visible' : 'hidden' } })] }));
|
|
786
1215
|
}
|
|
787
1216
|
|
|
788
|
-
/**
|
|
789
|
-
* @deprecated
|
|
790
|
-
*/
|
|
791
1217
|
function DDatePicker(_a) {
|
|
792
|
-
var {
|
|
793
|
-
const
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
1218
|
+
var { inputLabel, inputHint, inputAriaLabel, inputActionAriaLabel = 'open calendar', inputId = 'input-calendar', timeId = 'input-time', timeLabel, iconInput, iconHeaderPrev, iconHeaderNext, iconMaterialStyle, iconFamilyClass, iconFamilyPrefix, minYearSelect, maxYearSelect, iconHeaderSize, headerPrevMonthAriaLabel, headerNextMonthAriaLabel, headerButtonVariant, headerButtonTheme, invalid = false, valid = false, renderCustomHeader: renderCustomHeaderProp, className, dateFormatCalendar: dateFormatCalendarProp, style, dataAttributes, placeholder, showHeaderSelectors } = _a, props = __rest(_a, ["inputLabel", "inputHint", "inputAriaLabel", "inputActionAriaLabel", "inputId", "timeId", "timeLabel", "iconInput", "iconHeaderPrev", "iconHeaderNext", "iconMaterialStyle", "iconFamilyClass", "iconFamilyPrefix", "minYearSelect", "maxYearSelect", "iconHeaderSize", "headerPrevMonthAriaLabel", "headerNextMonthAriaLabel", "headerButtonVariant", "headerButtonTheme", "invalid", "valid", "renderCustomHeader", "className", "dateFormatCalendar", "style", "dataAttributes", "placeholder", "showHeaderSelectors"]);
|
|
1219
|
+
const pickerType = useMemo(() => {
|
|
1220
|
+
if (props.showQuarterYearPicker)
|
|
1221
|
+
return PickerType.Quarter;
|
|
1222
|
+
if (props.showMonthYearPicker)
|
|
1223
|
+
return PickerType.Month;
|
|
1224
|
+
if (props.showYearPicker)
|
|
1225
|
+
return PickerType.Year;
|
|
1226
|
+
return PickerType.Default;
|
|
1227
|
+
}, [
|
|
1228
|
+
props.showQuarterYearPicker,
|
|
1229
|
+
props.showMonthYearPicker,
|
|
1230
|
+
props.showYearPicker,
|
|
1231
|
+
]);
|
|
1232
|
+
const DatePickerHeader = useCallback((headerProps) => (jsx(DDatePickerHeaderSelector, Object.assign({}, headerProps, { monthsShown: props.monthsShown, iconPrev: iconHeaderPrev, iconNext: iconHeaderNext, iconMaterialStyle: iconMaterialStyle, prevMonthAriaLabel: headerPrevMonthAriaLabel, nextMonthAriaLabel: headerNextMonthAriaLabel, iconSize: iconHeaderSize, buttonVariant: headerButtonVariant, buttonTheme: headerButtonTheme, minYearSelect: minYearSelect, maxYearSelect: maxYearSelect, pickerType: pickerType, showHeaderSelectors: showHeaderSelectors }))), [
|
|
1233
|
+
iconHeaderNext,
|
|
1234
|
+
iconHeaderPrev,
|
|
1235
|
+
iconMaterialStyle,
|
|
806
1236
|
headerPrevMonthAriaLabel,
|
|
807
1237
|
headerNextMonthAriaLabel,
|
|
808
1238
|
iconHeaderSize,
|
|
@@ -810,10 +1240,13 @@ function DDatePicker(_a) {
|
|
|
810
1240
|
headerButtonTheme,
|
|
811
1241
|
minYearSelect,
|
|
812
1242
|
maxYearSelect,
|
|
1243
|
+
pickerType,
|
|
1244
|
+
showHeaderSelectors,
|
|
1245
|
+
props.monthsShown,
|
|
813
1246
|
]);
|
|
814
1247
|
const defaultRenderCustomHeader = useCallback((headerProps) => (jsx(DatePickerHeader, Object.assign({}, headerProps))), [DatePickerHeader]);
|
|
815
1248
|
const renderCustomHeader = useMemo(() => (renderCustomHeaderProp || defaultRenderCustomHeader), [defaultRenderCustomHeader, renderCustomHeaderProp]);
|
|
816
|
-
return (jsx(DatePicker, Object.assign({
|
|
1249
|
+
return (jsx(DatePicker, Object.assign({ calendarClassName: "d-date-picker", renderCustomHeader: renderCustomHeader, customInput: (jsx(ForwardedDDatePickerInput, { id: inputId, "aria-label": inputAriaLabel, iconEndAriaLabel: inputActionAriaLabel, iconMaterialStyle: iconMaterialStyle, iconEnd: iconInput, inputLabel: inputLabel, className: className, style: style, invalid: invalid, valid: valid, hint: inputHint })), customTimeInput: (jsx(DDatePickerTime, { id: timeId, label: timeLabel })), placeholderText: placeholder }, dataAttributes, props)));
|
|
817
1250
|
}
|
|
818
1251
|
|
|
819
1252
|
function DInputMask(props, ref) {
|
|
@@ -1322,7 +1755,7 @@ function DListGroupItem({ as = 'li', action: actionProp, active, disabled, href,
|
|
|
1322
1755
|
}
|
|
1323
1756
|
return Object.assign(Object.assign({}, active && { 'aria-current': true }), disabled && { 'aria-disabled': true });
|
|
1324
1757
|
}, [Tag, active, disabled]);
|
|
1325
|
-
return (jsx(Tag, Object.assign({ className: classNames(generateClasses, className), style: style }, Tag === 'a' && href && { href }, onClick && { onClick }, ariaAttributes, dataAttributes, { children: children })));
|
|
1758
|
+
return (jsx(Tag, Object.assign({ className: classNames(generateClasses, className), style: style }, Tag === 'a' && href && { href }, onClick && { onClick }, ariaAttributes, dataAttributes, Tag === 'button' && { type: 'button' }, { children: children })));
|
|
1326
1759
|
}
|
|
1327
1760
|
|
|
1328
1761
|
function DListGroup({ as = 'ul', numbered, flush, horizontal, children, className, style, dataAttributes, }) {
|
|
@@ -1432,9 +1865,6 @@ function DPaginator(_a) {
|
|
|
1432
1865
|
return (jsx(ResponsivePagination, Object.assign({ navClassName: classNames('page-item-arrow', navClassName) }, backwardCompatibilityProps)));
|
|
1433
1866
|
}
|
|
1434
1867
|
|
|
1435
|
-
/**
|
|
1436
|
-
* @deprecated
|
|
1437
|
-
*/
|
|
1438
1868
|
function DPopover({ children, renderComponent, open, setOpen, adjustContentToRender = false, className, style, dataAttributes, }) {
|
|
1439
1869
|
const [isOpen, setIsOpen] = useState(false);
|
|
1440
1870
|
useEffect(() => {
|