@lumx/react 4.3.2-alpha.22 → 4.3.2-alpha.24
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/Tooltip-2RZbmkfM.d.ts +915 -0
- package/_internal/{CzTdCnO5.js → BQFZG9jO.js} +398 -5
- package/_internal/BQFZG9jO.js.map +1 -0
- package/index.d.ts +80 -955
- package/index.js +2 -272
- package/index.js.map +1 -1
- package/package.json +3 -3
- package/utils/index.d.ts +189 -2
- package/utils/index.js +364 -4
- package/utils/index.js.map +1 -1
- package/_internal/CzTdCnO5.js.map +0 -1
|
@@ -4,6 +4,7 @@ import isEmpty from 'lodash/isEmpty.js';
|
|
|
4
4
|
import { join, visuallyHidden } from '@lumx/core/js/utils/classNames';
|
|
5
5
|
import { createPortal } from 'react-dom';
|
|
6
6
|
import noop from 'lodash/noop.js';
|
|
7
|
+
import uniqueId from 'lodash/uniqueId.js';
|
|
7
8
|
import findLast from 'lodash/findLast.js';
|
|
8
9
|
import find from 'lodash/find.js';
|
|
9
10
|
import findLastIndex from 'lodash/findLastIndex.js';
|
|
@@ -1234,7 +1235,7 @@ const OPTIONS_UPDATED = (state, action) => {
|
|
|
1234
1235
|
};
|
|
1235
1236
|
|
|
1236
1237
|
/** Reducers for each action type: */
|
|
1237
|
-
const REDUCERS = {
|
|
1238
|
+
const REDUCERS$1 = {
|
|
1238
1239
|
REGISTER_TAB_STOP,
|
|
1239
1240
|
UNREGISTER_TAB_STOP,
|
|
1240
1241
|
UPDATE_TAB_STOP,
|
|
@@ -1246,8 +1247,8 @@ const REDUCERS = {
|
|
|
1246
1247
|
};
|
|
1247
1248
|
|
|
1248
1249
|
/** Main reducer */
|
|
1249
|
-
const reducer = (state, action) => {
|
|
1250
|
-
return REDUCERS[action.type]?.(state, action) || state;
|
|
1250
|
+
const reducer$1 = (state, action) => {
|
|
1251
|
+
return REDUCERS$1[action.type]?.(state, action) || state;
|
|
1251
1252
|
};
|
|
1252
1253
|
|
|
1253
1254
|
const MovingFocusContext = /*#__PURE__*/React__default.createContext({
|
|
@@ -1371,5 +1372,397 @@ const useVirtualFocus = (id, domElementRef, disabled = false, rowKey = null, aut
|
|
|
1371
1372
|
return focused;
|
|
1372
1373
|
};
|
|
1373
1374
|
|
|
1374
|
-
|
|
1375
|
-
|
|
1375
|
+
/** Generate the combobox option id from the combobox id and the given id */
|
|
1376
|
+
const generateOptionId = (comboboxId, optionId) => `${comboboxId}-option-${optionId}`;
|
|
1377
|
+
|
|
1378
|
+
/** Verifies that the combobox registered option is an action */
|
|
1379
|
+
const isComboboxAction = option => Boolean(option?.isAction);
|
|
1380
|
+
|
|
1381
|
+
/** Verifies that the combobox registered option is the option's value */
|
|
1382
|
+
const isComboboxValue = option => {
|
|
1383
|
+
return !isComboboxAction(option);
|
|
1384
|
+
};
|
|
1385
|
+
|
|
1386
|
+
const comboboxId = `combobox-${uniqueId()}`;
|
|
1387
|
+
const initialState = {
|
|
1388
|
+
comboboxId,
|
|
1389
|
+
listboxId: `${comboboxId}-popover`,
|
|
1390
|
+
status: 'idle',
|
|
1391
|
+
isOpen: false,
|
|
1392
|
+
inputValue: '',
|
|
1393
|
+
showAll: true,
|
|
1394
|
+
options: {},
|
|
1395
|
+
type: 'listbox',
|
|
1396
|
+
optionsLength: 0
|
|
1397
|
+
};
|
|
1398
|
+
|
|
1399
|
+
/** Actions when the combobox opens. */
|
|
1400
|
+
const OPEN_COMBOBOX = (state, action) => {
|
|
1401
|
+
const {
|
|
1402
|
+
manual
|
|
1403
|
+
} = action.payload || {};
|
|
1404
|
+
// If the combobox was manually opened, show all suggestions
|
|
1405
|
+
return {
|
|
1406
|
+
...state,
|
|
1407
|
+
showAll: Boolean(manual),
|
|
1408
|
+
isOpen: true
|
|
1409
|
+
};
|
|
1410
|
+
};
|
|
1411
|
+
|
|
1412
|
+
/** Actions when the combobox closes */
|
|
1413
|
+
const CLOSE_COMBOBOX = state => {
|
|
1414
|
+
return {
|
|
1415
|
+
...state,
|
|
1416
|
+
showAll: true,
|
|
1417
|
+
isOpen: false
|
|
1418
|
+
};
|
|
1419
|
+
};
|
|
1420
|
+
|
|
1421
|
+
/** Actions on input update. */
|
|
1422
|
+
const SET_INPUT_VALUE = (state, action) => {
|
|
1423
|
+
return {
|
|
1424
|
+
...state,
|
|
1425
|
+
inputValue: action.payload,
|
|
1426
|
+
// When the user is changing the value, show only values that are related to the input value.
|
|
1427
|
+
showAll: false,
|
|
1428
|
+
isOpen: true
|
|
1429
|
+
};
|
|
1430
|
+
};
|
|
1431
|
+
|
|
1432
|
+
/** Register an option to the state */
|
|
1433
|
+
const ADD_OPTION = (state, action) => {
|
|
1434
|
+
const {
|
|
1435
|
+
id,
|
|
1436
|
+
option
|
|
1437
|
+
} = action.payload;
|
|
1438
|
+
const {
|
|
1439
|
+
options
|
|
1440
|
+
} = state;
|
|
1441
|
+
if (options[id]) {
|
|
1442
|
+
// Option already exists, return state unchanged
|
|
1443
|
+
return state;
|
|
1444
|
+
}
|
|
1445
|
+
const newOptions = {
|
|
1446
|
+
...options,
|
|
1447
|
+
[id]: option
|
|
1448
|
+
};
|
|
1449
|
+
let newType = state.type;
|
|
1450
|
+
if (isComboboxAction(option)) {
|
|
1451
|
+
newType = 'grid';
|
|
1452
|
+
}
|
|
1453
|
+
let newOptionsLength = state.optionsLength;
|
|
1454
|
+
if (isComboboxValue(option)) {
|
|
1455
|
+
newOptionsLength += 1;
|
|
1456
|
+
}
|
|
1457
|
+
return {
|
|
1458
|
+
...state,
|
|
1459
|
+
options: newOptions,
|
|
1460
|
+
type: newType,
|
|
1461
|
+
optionsLength: newOptionsLength
|
|
1462
|
+
};
|
|
1463
|
+
};
|
|
1464
|
+
|
|
1465
|
+
/** Remove an option from the state */
|
|
1466
|
+
const REMOVE_OPTION = (state, action) => {
|
|
1467
|
+
const {
|
|
1468
|
+
id
|
|
1469
|
+
} = action.payload;
|
|
1470
|
+
const {
|
|
1471
|
+
options
|
|
1472
|
+
} = state;
|
|
1473
|
+
const option = options[id];
|
|
1474
|
+
if (!options[id]) {
|
|
1475
|
+
// Option doesn't exist, return state unchanged
|
|
1476
|
+
return state;
|
|
1477
|
+
}
|
|
1478
|
+
const newOptions = {
|
|
1479
|
+
...options
|
|
1480
|
+
};
|
|
1481
|
+
delete newOptions[id];
|
|
1482
|
+
let newOptionsLength = state.optionsLength;
|
|
1483
|
+
if (isComboboxValue(option)) {
|
|
1484
|
+
newOptionsLength -= 1;
|
|
1485
|
+
}
|
|
1486
|
+
return {
|
|
1487
|
+
...state,
|
|
1488
|
+
options: newOptions,
|
|
1489
|
+
optionsLength: newOptionsLength
|
|
1490
|
+
};
|
|
1491
|
+
};
|
|
1492
|
+
|
|
1493
|
+
/** Reducers for each action type: */
|
|
1494
|
+
const REDUCERS = {
|
|
1495
|
+
OPEN_COMBOBOX,
|
|
1496
|
+
CLOSE_COMBOBOX,
|
|
1497
|
+
SET_INPUT_VALUE,
|
|
1498
|
+
ADD_OPTION,
|
|
1499
|
+
REMOVE_OPTION
|
|
1500
|
+
};
|
|
1501
|
+
|
|
1502
|
+
/** Main reducer */
|
|
1503
|
+
const reducer = (state, action) => {
|
|
1504
|
+
return REDUCERS[action.type]?.(state, action) || state;
|
|
1505
|
+
};
|
|
1506
|
+
|
|
1507
|
+
/** Dispatch for the combobox component */
|
|
1508
|
+
|
|
1509
|
+
/** Context for the Combobox component */
|
|
1510
|
+
const ComboboxContext = /*#__PURE__*/React__default.createContext({
|
|
1511
|
+
...initialState,
|
|
1512
|
+
openOnFocus: false,
|
|
1513
|
+
openOnClick: false,
|
|
1514
|
+
selectionType: 'single',
|
|
1515
|
+
optionsLength: 0,
|
|
1516
|
+
onSelect: noop,
|
|
1517
|
+
onInputChange: noop,
|
|
1518
|
+
onOpen: noop,
|
|
1519
|
+
dispatch: noop,
|
|
1520
|
+
translations: {
|
|
1521
|
+
clearLabel: '',
|
|
1522
|
+
tryReloadLabel: '',
|
|
1523
|
+
showSuggestionsLabel: '',
|
|
1524
|
+
noResultsForInputLabel: input => input || '',
|
|
1525
|
+
loadingLabel: '',
|
|
1526
|
+
serviceUnavailableLabel: '',
|
|
1527
|
+
nbOptionsLabel: options => `${options}`
|
|
1528
|
+
}
|
|
1529
|
+
});
|
|
1530
|
+
|
|
1531
|
+
/** Context for a combobox section to store its unique id */
|
|
1532
|
+
const SectionContext = /*#__PURE__*/React__default.createContext({
|
|
1533
|
+
sectionId: ''
|
|
1534
|
+
});
|
|
1535
|
+
|
|
1536
|
+
const ComboboxOptionContext = /*#__PURE__*/createContext({});
|
|
1537
|
+
/** Context Provider to store the current combobox option id. */
|
|
1538
|
+
const ComboboxOptionContextProvider = ({
|
|
1539
|
+
optionId,
|
|
1540
|
+
isKeyboardHighlighted,
|
|
1541
|
+
children
|
|
1542
|
+
}) => {
|
|
1543
|
+
const value = React__default.useMemo(() => ({
|
|
1544
|
+
optionId,
|
|
1545
|
+
isKeyboardHighlighted
|
|
1546
|
+
}), [optionId, isKeyboardHighlighted]);
|
|
1547
|
+
return /*#__PURE__*/jsx(ComboboxOptionContext.Provider, {
|
|
1548
|
+
value: value,
|
|
1549
|
+
children: children
|
|
1550
|
+
});
|
|
1551
|
+
};
|
|
1552
|
+
|
|
1553
|
+
/**
|
|
1554
|
+
* Retrieve the current combobox option id.
|
|
1555
|
+
* Must be used within a ComboboxOptionIdProvider
|
|
1556
|
+
*/
|
|
1557
|
+
const useComboboxOptionContext = () => {
|
|
1558
|
+
const comboboxOption = useContext(ComboboxOptionContext);
|
|
1559
|
+
if (!comboboxOption?.optionId) {
|
|
1560
|
+
throw new Error('This hook must be used within a ComboboxOptionIdProvider');
|
|
1561
|
+
}
|
|
1562
|
+
return comboboxOption;
|
|
1563
|
+
};
|
|
1564
|
+
|
|
1565
|
+
/** Context to store the refs of the combobox elements */
|
|
1566
|
+
const ComboboxRefsContext = /*#__PURE__*/createContext({
|
|
1567
|
+
triggerRef: {
|
|
1568
|
+
current: null
|
|
1569
|
+
},
|
|
1570
|
+
anchorRef: {
|
|
1571
|
+
current: null
|
|
1572
|
+
}
|
|
1573
|
+
});
|
|
1574
|
+
/** Provider to store the required refs for the Combobox */
|
|
1575
|
+
const ComboboxRefsProvider = ({
|
|
1576
|
+
triggerRef,
|
|
1577
|
+
anchorRef,
|
|
1578
|
+
children
|
|
1579
|
+
}) => {
|
|
1580
|
+
const value = useMemo(() => ({
|
|
1581
|
+
triggerRef,
|
|
1582
|
+
anchorRef
|
|
1583
|
+
}), [triggerRef, anchorRef]);
|
|
1584
|
+
return /*#__PURE__*/jsx(ComboboxRefsContext.Provider, {
|
|
1585
|
+
value: value,
|
|
1586
|
+
children: children
|
|
1587
|
+
});
|
|
1588
|
+
};
|
|
1589
|
+
|
|
1590
|
+
/** Retrieves the combobox elements references from context */
|
|
1591
|
+
const useComboboxRefs = () => {
|
|
1592
|
+
const refs = useContext(ComboboxRefsContext);
|
|
1593
|
+
if (!refs) {
|
|
1594
|
+
throw new Error('The useComboboxRefs hook must be called within a ComboboxRefsProvider');
|
|
1595
|
+
}
|
|
1596
|
+
return refs;
|
|
1597
|
+
};
|
|
1598
|
+
|
|
1599
|
+
/** Retrieve the current combobox state and actions */
|
|
1600
|
+
const useCombobox = () => {
|
|
1601
|
+
const comboboxContext = React__default.useContext(ComboboxContext);
|
|
1602
|
+
const {
|
|
1603
|
+
dispatch: movingFocusDispatch
|
|
1604
|
+
} = React__default.useContext(MovingFocusContext);
|
|
1605
|
+
const {
|
|
1606
|
+
onSelect,
|
|
1607
|
+
onInputChange,
|
|
1608
|
+
onOpen,
|
|
1609
|
+
dispatch,
|
|
1610
|
+
inputValue,
|
|
1611
|
+
...contextValues
|
|
1612
|
+
} = comboboxContext;
|
|
1613
|
+
const {
|
|
1614
|
+
triggerRef
|
|
1615
|
+
} = useComboboxRefs();
|
|
1616
|
+
|
|
1617
|
+
/** Action triggered when the listBox is closed without selecting any option */
|
|
1618
|
+
const handleClose = React__default.useCallback(() => {
|
|
1619
|
+
dispatch({
|
|
1620
|
+
type: 'CLOSE_COMBOBOX'
|
|
1621
|
+
});
|
|
1622
|
+
// Reset visual focus
|
|
1623
|
+
movingFocusDispatch({
|
|
1624
|
+
type: 'RESET_SELECTED_TAB_STOP'
|
|
1625
|
+
});
|
|
1626
|
+
}, [dispatch, movingFocusDispatch]);
|
|
1627
|
+
|
|
1628
|
+
// Handle callbacks on options mounted
|
|
1629
|
+
const [optionsMountedCallbacks, setOptionsMountedCallback] = React__default.useState();
|
|
1630
|
+
React__default.useEffect(() => {
|
|
1631
|
+
if (comboboxContext.optionsLength > 0 && optionsMountedCallbacks?.length) {
|
|
1632
|
+
const optionsArray = Object.values(comboboxContext.options);
|
|
1633
|
+
// Execute callbacks
|
|
1634
|
+
for (const callback of optionsMountedCallbacks) {
|
|
1635
|
+
callback(optionsArray);
|
|
1636
|
+
}
|
|
1637
|
+
setOptionsMountedCallback(undefined);
|
|
1638
|
+
}
|
|
1639
|
+
}, [comboboxContext.options, comboboxContext.optionsLength, optionsMountedCallbacks]);
|
|
1640
|
+
|
|
1641
|
+
/** Callback for when an option is selected */
|
|
1642
|
+
const handleSelected = React__default.useCallback((option, source) => {
|
|
1643
|
+
if (option?.isDisabled) {
|
|
1644
|
+
return;
|
|
1645
|
+
}
|
|
1646
|
+
if (isComboboxValue(option)) {
|
|
1647
|
+
/**
|
|
1648
|
+
* We only close the list if the selection type is single.
|
|
1649
|
+
* If it is multiple, we want to allow the user to continue
|
|
1650
|
+
* selecting multiple options.
|
|
1651
|
+
*/
|
|
1652
|
+
if (comboboxContext.selectionType !== 'multiple') {
|
|
1653
|
+
handleClose();
|
|
1654
|
+
}
|
|
1655
|
+
/** Call parent onSelect callback */
|
|
1656
|
+
if (onSelect) {
|
|
1657
|
+
onSelect(option);
|
|
1658
|
+
}
|
|
1659
|
+
}
|
|
1660
|
+
|
|
1661
|
+
/** If the option itself has a custom action, also call it */
|
|
1662
|
+
if (option?.onSelect) {
|
|
1663
|
+
option.onSelect(option, source);
|
|
1664
|
+
}
|
|
1665
|
+
|
|
1666
|
+
/** Reset focus on input */
|
|
1667
|
+
if (triggerRef?.current) {
|
|
1668
|
+
triggerRef.current?.focus();
|
|
1669
|
+
}
|
|
1670
|
+
}, [comboboxContext.selectionType, handleClose, onSelect, triggerRef]);
|
|
1671
|
+
|
|
1672
|
+
/** Callback for when the input must be updated */
|
|
1673
|
+
const handleInputChange = React__default.useCallback((value, ...args) => {
|
|
1674
|
+
// Update the local state
|
|
1675
|
+
dispatch({
|
|
1676
|
+
type: 'SET_INPUT_VALUE',
|
|
1677
|
+
payload: value
|
|
1678
|
+
});
|
|
1679
|
+
// If a callback if given, call it with the value
|
|
1680
|
+
if (onInputChange) {
|
|
1681
|
+
onInputChange(value, ...args);
|
|
1682
|
+
}
|
|
1683
|
+
// Reset visual focus
|
|
1684
|
+
movingFocusDispatch({
|
|
1685
|
+
type: 'RESET_SELECTED_TAB_STOP'
|
|
1686
|
+
});
|
|
1687
|
+
}, [dispatch, movingFocusDispatch, onInputChange]);
|
|
1688
|
+
|
|
1689
|
+
/**
|
|
1690
|
+
* Open the popover
|
|
1691
|
+
*
|
|
1692
|
+
* @returns a promise with the updated context once all options are mounted
|
|
1693
|
+
*/
|
|
1694
|
+
const handleOpen = React__default.useCallback(params => {
|
|
1695
|
+
/** update the local state */
|
|
1696
|
+
dispatch({
|
|
1697
|
+
type: 'OPEN_COMBOBOX',
|
|
1698
|
+
payload: params
|
|
1699
|
+
});
|
|
1700
|
+
/** If a parent callback was given, trigger it with state information */
|
|
1701
|
+
if (onOpen) {
|
|
1702
|
+
onOpen({
|
|
1703
|
+
currentValue: inputValue,
|
|
1704
|
+
manual: Boolean(params?.manual)
|
|
1705
|
+
});
|
|
1706
|
+
}
|
|
1707
|
+
|
|
1708
|
+
// Promise resolving options on mount
|
|
1709
|
+
return new Promise(resolve => {
|
|
1710
|
+
// Append to the list of callback on options mounted
|
|
1711
|
+
setOptionsMountedCallback((callbacks = []) => {
|
|
1712
|
+
callbacks.push(resolve);
|
|
1713
|
+
return callbacks;
|
|
1714
|
+
});
|
|
1715
|
+
});
|
|
1716
|
+
}, [dispatch, inputValue, onOpen]);
|
|
1717
|
+
return React__default.useMemo(() => ({
|
|
1718
|
+
handleClose,
|
|
1719
|
+
handleOpen,
|
|
1720
|
+
handleInputChange,
|
|
1721
|
+
handleSelected,
|
|
1722
|
+
dispatch,
|
|
1723
|
+
inputValue,
|
|
1724
|
+
...contextValues
|
|
1725
|
+
}), [contextValues, dispatch, handleClose, handleInputChange, handleOpen, handleSelected, inputValue]);
|
|
1726
|
+
};
|
|
1727
|
+
|
|
1728
|
+
/** Retrieve the current combobox section id */
|
|
1729
|
+
const useComboboxSectionId = () => {
|
|
1730
|
+
return useContext(SectionContext);
|
|
1731
|
+
};
|
|
1732
|
+
|
|
1733
|
+
/**
|
|
1734
|
+
* Register the given option to the context
|
|
1735
|
+
*/
|
|
1736
|
+
const useRegisterOption = (registerId, option, shouldRegister) => {
|
|
1737
|
+
const {
|
|
1738
|
+
dispatch
|
|
1739
|
+
} = useCombobox();
|
|
1740
|
+
|
|
1741
|
+
/** Register the given options */
|
|
1742
|
+
React__default.useEffect(() => {
|
|
1743
|
+
if (option && shouldRegister) {
|
|
1744
|
+
dispatch({
|
|
1745
|
+
type: 'ADD_OPTION',
|
|
1746
|
+
payload: {
|
|
1747
|
+
id: registerId,
|
|
1748
|
+
option
|
|
1749
|
+
}
|
|
1750
|
+
});
|
|
1751
|
+
}
|
|
1752
|
+
|
|
1753
|
+
// Unregister ids if/when the component unmounts or if option changes
|
|
1754
|
+
return () => {
|
|
1755
|
+
if (option) {
|
|
1756
|
+
dispatch({
|
|
1757
|
+
type: 'REMOVE_OPTION',
|
|
1758
|
+
payload: {
|
|
1759
|
+
id: registerId
|
|
1760
|
+
}
|
|
1761
|
+
});
|
|
1762
|
+
}
|
|
1763
|
+
};
|
|
1764
|
+
}, [dispatch, option, registerId, shouldRegister]);
|
|
1765
|
+
};
|
|
1766
|
+
|
|
1767
|
+
export { A11YLiveMessage as A, ComboboxOptionContextProvider as C, DisabledStateProvider as D, INITIAL_STATE as I, MovingFocusContext as M, NAV_KEYS as N, Portal as P, SectionContext as S, useComboboxSectionId as a, useCombobox as b, useRegisterOption as c, useVirtualFocus as d, useComboboxOptionContext as e, useComboboxRefs as f, generateOptionId as g, ClickAwayProvider as h, buildLoopAroundObject as i, getPointerTypeFromEvent as j, ComboboxContext as k, isComboboxValue as l, initialState as m, ComboboxOptionContext as n, reducer as o, ComboboxRefsProvider as p, PortalProvider as q, reducer$1 as r, useDisabledStateContext as u };
|
|
1768
|
+
//# sourceMappingURL=BQFZG9jO.js.map
|