@lumx/react 3.6.6 → 3.6.7-alpha.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/index.d.ts +15 -0
- package/index.js +100 -18
- package/index.js.map +1 -1
- package/package.json +3 -3
- package/src/components/date-picker/DatePicker.test.tsx +3 -0
- package/src/components/date-picker/DatePicker.tsx +4 -7
- package/src/components/date-picker/DatePickerControlled.test.tsx +46 -2
- package/src/components/date-picker/DatePickerControlled.tsx +80 -5
- package/src/components/date-picker/DatePickerField.test.tsx +3 -0
- package/src/components/message/Message.stories.tsx +16 -0
- package/src/components/message/Message.test.tsx +25 -3
- package/src/components/message/Message.tsx +26 -3
- package/src/components/popover/Popover.tsx +6 -2
- package/src/stories/generated/Message/Demos.stories.tsx +1 -0
- package/src/utils/date/getYearDisplayName.test.ts +20 -0
- package/src/utils/date/getYearDisplayName.ts +12 -0
package/index.d.ts
CHANGED
|
@@ -586,6 +586,8 @@ interface DatePickerControlledProps extends DatePickerProps {
|
|
|
586
586
|
onPrevMonthChange(): void;
|
|
587
587
|
/** On next month change callback. */
|
|
588
588
|
onNextMonthChange(): void;
|
|
589
|
+
/** On month/year change callback. */
|
|
590
|
+
onMonthChange?: (newMonth: Date) => void;
|
|
589
591
|
}
|
|
590
592
|
/**
|
|
591
593
|
* DatePickerControlled component.
|
|
@@ -792,6 +794,8 @@ interface PopoverProps extends GenericProps, HasTheme {
|
|
|
792
794
|
placement?: Placement;
|
|
793
795
|
/** Whether the popover should be rendered into a DOM node that exists outside the DOM hierarchy of the parent component. */
|
|
794
796
|
usePortal?: boolean;
|
|
797
|
+
/** The element in which the focus trap should be set. Default to popover. */
|
|
798
|
+
focusTrapZone?: RefObject<HTMLElement>;
|
|
795
799
|
/** Z-axis position. */
|
|
796
800
|
zIndex?: number;
|
|
797
801
|
/** On close callback (on click away or Escape pressed). */
|
|
@@ -1646,6 +1650,17 @@ interface MessageProps extends GenericProps {
|
|
|
1646
1650
|
kind?: Kind;
|
|
1647
1651
|
/** Message custom icon SVG path. */
|
|
1648
1652
|
icon?: string;
|
|
1653
|
+
/**
|
|
1654
|
+
* Displays a close button.
|
|
1655
|
+
*
|
|
1656
|
+
* NB: only available if `kind === 'info' && hasBackground === true`
|
|
1657
|
+
*/
|
|
1658
|
+
closeButtonProps?: {
|
|
1659
|
+
/** The callback called when the button is clicked */
|
|
1660
|
+
onClick: () => void;
|
|
1661
|
+
/** The label of the close button. */
|
|
1662
|
+
label: string;
|
|
1663
|
+
};
|
|
1649
1664
|
}
|
|
1650
1665
|
/**
|
|
1651
1666
|
* Message component.
|
package/index.js
CHANGED
|
@@ -2262,6 +2262,21 @@ function usePreviousValue(value) {
|
|
|
2262
2262
|
return prevValue;
|
|
2263
2263
|
}
|
|
2264
2264
|
|
|
2265
|
+
const getYearDisplayName = locale => {
|
|
2266
|
+
let label;
|
|
2267
|
+
try {
|
|
2268
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
2269
|
+
// @ts-ignore
|
|
2270
|
+
const displayNames = new Intl.DisplayNames(locale, {
|
|
2271
|
+
type: 'dateTimeField'
|
|
2272
|
+
});
|
|
2273
|
+
label = displayNames.of('year');
|
|
2274
|
+
} catch (error) {
|
|
2275
|
+
label = '';
|
|
2276
|
+
}
|
|
2277
|
+
return label;
|
|
2278
|
+
};
|
|
2279
|
+
|
|
2265
2280
|
/**
|
|
2266
2281
|
* Defines the props of the component.
|
|
2267
2282
|
*/
|
|
@@ -2279,6 +2294,7 @@ const COMPONENT_NAME$e = 'DatePickerControlled';
|
|
|
2279
2294
|
* @return React element.
|
|
2280
2295
|
*/
|
|
2281
2296
|
const DatePickerControlled = /*#__PURE__*/forwardRef((props, ref) => {
|
|
2297
|
+
var _RegExp$exec;
|
|
2282
2298
|
const {
|
|
2283
2299
|
locale = getCurrentLocale(),
|
|
2284
2300
|
maxDate,
|
|
@@ -2290,7 +2306,8 @@ const DatePickerControlled = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
2290
2306
|
previousButtonProps,
|
|
2291
2307
|
selectedMonth,
|
|
2292
2308
|
todayOrSelectedDateRef,
|
|
2293
|
-
value
|
|
2309
|
+
value,
|
|
2310
|
+
onMonthChange
|
|
2294
2311
|
} = props;
|
|
2295
2312
|
const {
|
|
2296
2313
|
weeks,
|
|
@@ -2299,6 +2316,37 @@ const DatePickerControlled = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
2299
2316
|
const localeObj = parseLocale(locale);
|
|
2300
2317
|
return getMonthCalendar(localeObj, selectedMonth, minDate, maxDate);
|
|
2301
2318
|
}, [locale, minDate, maxDate, selectedMonth]);
|
|
2319
|
+
const selectedYear = selectedMonth.toLocaleDateString(locale, {
|
|
2320
|
+
year: 'numeric'
|
|
2321
|
+
}).slice(0, 4);
|
|
2322
|
+
const [textFieldYearValue, setTextFieldYearValue] = React.useState(selectedYear);
|
|
2323
|
+
const isYearValid = Number(textFieldYearValue) > 0 && Number(textFieldYearValue) <= 9999;
|
|
2324
|
+
|
|
2325
|
+
// Updates month offset when validating year. Adds or removes 12 months per year when updating year value.
|
|
2326
|
+
const updateMonthOffset = React.useCallback(() => {
|
|
2327
|
+
if (isYearValid) {
|
|
2328
|
+
const yearNumber = selectedMonth.getFullYear();
|
|
2329
|
+
const offset = (Number(textFieldYearValue) - yearNumber) * 12;
|
|
2330
|
+
if (onMonthChange) {
|
|
2331
|
+
onMonthChange(addMonthResetDay(selectedMonth, offset));
|
|
2332
|
+
}
|
|
2333
|
+
}
|
|
2334
|
+
}, [isYearValid, selectedMonth, textFieldYearValue, onMonthChange]);
|
|
2335
|
+
const monthYear = selectedMonth.toLocaleDateString(locale, {
|
|
2336
|
+
year: 'numeric',
|
|
2337
|
+
month: 'long'
|
|
2338
|
+
});
|
|
2339
|
+
|
|
2340
|
+
// Year can only be validatd by pressing Enter key or on Blur. The below handles the press Enter key case
|
|
2341
|
+
const handleKeyPress = React.useMemo(() => onEnterPressed(updateMonthOffset), [updateMonthOffset]);
|
|
2342
|
+
|
|
2343
|
+
// Required to update year in the TextField when the user changes year by using prev next month arrows
|
|
2344
|
+
React.useEffect(() => {
|
|
2345
|
+
if (Number(textFieldYearValue) !== selectedMonth.getFullYear()) {
|
|
2346
|
+
setTextFieldYearValue(selectedMonth.getFullYear().toString());
|
|
2347
|
+
}
|
|
2348
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
2349
|
+
}, [selectedMonth]);
|
|
2302
2350
|
const prevSelectedMonth = usePreviousValue(selectedMonth);
|
|
2303
2351
|
const monthHasChanged = prevSelectedMonth && !isSameDay(selectedMonth, prevSelectedMonth);
|
|
2304
2352
|
|
|
@@ -2307,6 +2355,7 @@ const DatePickerControlled = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
2307
2355
|
React.useEffect(() => {
|
|
2308
2356
|
if (monthHasChanged) setLabelAriaLive('polite');
|
|
2309
2357
|
}, [monthHasChanged]);
|
|
2358
|
+
const label = getYearDisplayName(locale);
|
|
2310
2359
|
return /*#__PURE__*/React.createElement("div", {
|
|
2311
2360
|
ref: ref,
|
|
2312
2361
|
className: `${CLASSNAME$c}`
|
|
@@ -2322,13 +2371,32 @@ const DatePickerControlled = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
2322
2371
|
icon: mdiChevronLeft,
|
|
2323
2372
|
onClick: onPrevMonthChange
|
|
2324
2373
|
})),
|
|
2325
|
-
label: /*#__PURE__*/React.createElement("span", {
|
|
2374
|
+
label: /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("span", {
|
|
2375
|
+
"aria-live": labelAriaLive,
|
|
2376
|
+
className: onMonthChange ? 'visually-hidden' : '',
|
|
2377
|
+
dir: "auto"
|
|
2378
|
+
}, monthYear), onMonthChange && /*#__PURE__*/React.createElement(FlexBox, {
|
|
2326
2379
|
className: `${CLASSNAME$c}__month`,
|
|
2327
|
-
"
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2380
|
+
orientation: "horizontal",
|
|
2381
|
+
hAlign: "center",
|
|
2382
|
+
gap: "regular",
|
|
2383
|
+
vAlign: "center",
|
|
2384
|
+
dir: "auto"
|
|
2385
|
+
}, (_RegExp$exec = RegExp(`(.*)(${selectedYear})(.*)`).exec(monthYear)) === null || _RegExp$exec === void 0 ? void 0 : _RegExp$exec.slice(1).filter(part => part !== '').map(part => part === selectedYear ? /*#__PURE__*/React.createElement(TextField, {
|
|
2386
|
+
value: textFieldYearValue,
|
|
2387
|
+
"aria-label": label,
|
|
2388
|
+
onChange: setTextFieldYearValue,
|
|
2389
|
+
type: "number",
|
|
2390
|
+
max: 9999,
|
|
2391
|
+
min: 0,
|
|
2392
|
+
onBlur: updateMonthOffset,
|
|
2393
|
+
onKeyPress: handleKeyPress,
|
|
2394
|
+
key: "year",
|
|
2395
|
+
className: `${CLASSNAME$c}__year`
|
|
2396
|
+
}) : /*#__PURE__*/React.createElement(Text, {
|
|
2397
|
+
as: "p",
|
|
2398
|
+
key: part
|
|
2399
|
+
}, part))))
|
|
2332
2400
|
}), /*#__PURE__*/React.createElement("div", {
|
|
2333
2401
|
className: `${CLASSNAME$c}__calendar`
|
|
2334
2402
|
}, /*#__PURE__*/React.createElement("div", {
|
|
@@ -2410,14 +2478,12 @@ const DatePicker = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
2410
2478
|
console.warn(`[@lumx/react/DatePicker] Invalid date provided ${referenceDate}`);
|
|
2411
2479
|
referenceDate = new Date();
|
|
2412
2480
|
}
|
|
2413
|
-
const [
|
|
2414
|
-
const setPrevMonth = () =>
|
|
2415
|
-
const setNextMonth = () =>
|
|
2481
|
+
const [selectedMonth, setSelectedMonth] = useState(referenceDate);
|
|
2482
|
+
const setPrevMonth = () => setSelectedMonth(current => addMonthResetDay(current, -1));
|
|
2483
|
+
const setNextMonth = () => setSelectedMonth(current => addMonthResetDay(current, +1));
|
|
2416
2484
|
const onDatePickerChange = newDate => {
|
|
2417
2485
|
onChange(newDate);
|
|
2418
|
-
setMonthOffset(0);
|
|
2419
2486
|
};
|
|
2420
|
-
const selectedMonth = addMonthResetDay(referenceDate, monthOffset);
|
|
2421
2487
|
return /*#__PURE__*/React.createElement(DatePickerControlled, _extends({
|
|
2422
2488
|
ref: ref
|
|
2423
2489
|
}, forwardedProps, {
|
|
@@ -2427,7 +2493,8 @@ const DatePicker = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
2427
2493
|
onPrevMonthChange: setPrevMonth,
|
|
2428
2494
|
onNextMonthChange: setNextMonth,
|
|
2429
2495
|
selectedMonth: selectedMonth,
|
|
2430
|
-
onChange: onDatePickerChange
|
|
2496
|
+
onChange: onDatePickerChange,
|
|
2497
|
+
onMonthChange: setSelectedMonth
|
|
2431
2498
|
}));
|
|
2432
2499
|
});
|
|
2433
2500
|
DatePicker.displayName = COMPONENT_NAME$d;
|
|
@@ -6471,7 +6538,7 @@ function usePopoverStyle(_ref5) {
|
|
|
6471
6538
|
};
|
|
6472
6539
|
}
|
|
6473
6540
|
|
|
6474
|
-
const _excluded$m = ["anchorRef", "as", "children", "className", "closeOnClickAway", "closeOnEscape", "elevation", "focusElement", "hasArrow", "isOpen", "onClose", "parentElement", "usePortal", "focusAnchorOnClose", "withFocusTrap", "boundaryRef", "fitToAnchorWidth", "fitWithinViewportHeight", "offset", "placement", "style", "theme", "zIndex"];
|
|
6541
|
+
const _excluded$m = ["anchorRef", "as", "children", "className", "closeOnClickAway", "closeOnEscape", "elevation", "focusElement", "hasArrow", "isOpen", "onClose", "parentElement", "usePortal", "focusAnchorOnClose", "withFocusTrap", "boundaryRef", "fitToAnchorWidth", "fitWithinViewportHeight", "focusTrapZone", "offset", "placement", "style", "theme", "zIndex"];
|
|
6475
6542
|
|
|
6476
6543
|
/**
|
|
6477
6544
|
* Defines the props of the component.
|
|
@@ -6524,6 +6591,7 @@ const _InnerPopover = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
6524
6591
|
boundaryRef,
|
|
6525
6592
|
fitToAnchorWidth,
|
|
6526
6593
|
fitWithinViewportHeight,
|
|
6594
|
+
focusTrapZone,
|
|
6527
6595
|
offset,
|
|
6528
6596
|
placement,
|
|
6529
6597
|
style,
|
|
@@ -6557,11 +6625,13 @@ const _InnerPopover = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
6557
6625
|
anchorRef,
|
|
6558
6626
|
parentElement
|
|
6559
6627
|
}, popperElement);
|
|
6628
|
+
const focusZoneElement = (focusTrapZone === null || focusTrapZone === void 0 ? void 0 : focusTrapZone.current) || (popoverRef === null || popoverRef === void 0 ? void 0 : popoverRef.current);
|
|
6629
|
+
console.log('focusZone', focusZoneElement);
|
|
6560
6630
|
useCallbackOnEscape(onClose, isOpen && closeOnEscape);
|
|
6561
6631
|
|
|
6562
6632
|
/** Only set focus within if the focus trap is disabled as they interfere with one another. */
|
|
6563
6633
|
useFocus(focusElement === null || focusElement === void 0 ? void 0 : focusElement.current, !withFocusTrap && isOpen && isPositioned);
|
|
6564
|
-
useFocusTrap(withFocusTrap && isOpen &&
|
|
6634
|
+
useFocusTrap(withFocusTrap && isOpen && focusZoneElement, focusElement === null || focusElement === void 0 ? void 0 : focusElement.current);
|
|
6565
6635
|
const clickAwayRefs = useRef([popoverRef, anchorRef]);
|
|
6566
6636
|
const mergedRefs = useMergeRefs(setPopperElement, ref, popoverRef);
|
|
6567
6637
|
return isOpen ? renderPopover( /*#__PURE__*/React.createElement(Component, _extends({}, forwardedProps, {
|
|
@@ -8233,7 +8303,7 @@ const ListSubheader = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
8233
8303
|
ListSubheader.displayName = COMPONENT_NAME$F;
|
|
8234
8304
|
ListSubheader.className = CLASSNAME$C;
|
|
8235
8305
|
|
|
8236
|
-
const _excluded$H = ["children", "className", "hasBackground", "kind", "icon"];
|
|
8306
|
+
const _excluded$H = ["children", "className", "hasBackground", "kind", "icon", "closeButtonProps"];
|
|
8237
8307
|
|
|
8238
8308
|
/**
|
|
8239
8309
|
* Defines the props of the component.
|
|
@@ -8284,13 +8354,19 @@ const Message = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
8284
8354
|
className,
|
|
8285
8355
|
hasBackground,
|
|
8286
8356
|
kind,
|
|
8287
|
-
icon: customIcon
|
|
8357
|
+
icon: customIcon,
|
|
8358
|
+
closeButtonProps
|
|
8288
8359
|
} = props,
|
|
8289
8360
|
forwardedProps = _objectWithoutProperties(props, _excluded$H);
|
|
8290
8361
|
const {
|
|
8291
8362
|
color,
|
|
8292
8363
|
icon
|
|
8293
8364
|
} = CONFIG$1[kind] || {};
|
|
8365
|
+
const {
|
|
8366
|
+
onClick,
|
|
8367
|
+
label: closeButtonLabel
|
|
8368
|
+
} = closeButtonProps || {};
|
|
8369
|
+
const isCloseButtonDisplayed = hasBackground && kind === 'info' && onClick && closeButtonLabel;
|
|
8294
8370
|
return /*#__PURE__*/React.createElement("div", _extends({
|
|
8295
8371
|
ref: ref,
|
|
8296
8372
|
className: classnames(className, handleBasicClasses({
|
|
@@ -8305,7 +8381,13 @@ const Message = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
8305
8381
|
color: color
|
|
8306
8382
|
}), /*#__PURE__*/React.createElement("div", {
|
|
8307
8383
|
className: `${CLASSNAME$D}__text`
|
|
8308
|
-
}, children)
|
|
8384
|
+
}, children), isCloseButtonDisplayed && /*#__PURE__*/React.createElement(IconButton, {
|
|
8385
|
+
className: `${CLASSNAME$D}__close-button`,
|
|
8386
|
+
icon: mdiClose,
|
|
8387
|
+
onClick: onClick,
|
|
8388
|
+
label: closeButtonLabel,
|
|
8389
|
+
emphasis: Emphasis.low
|
|
8390
|
+
}));
|
|
8309
8391
|
});
|
|
8310
8392
|
Message.displayName = COMPONENT_NAME$G;
|
|
8311
8393
|
Message.className = CLASSNAME$D;
|