@linzjs/lui 21.51.1 → 21.53.0

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/CHANGELOG.md CHANGED
@@ -1,3 +1,17 @@
1
+ # [21.53.0](https://github.com/linz/lui/compare/v21.52.0...v21.53.0) (2024-11-04)
2
+
3
+
4
+ ### Features
5
+
6
+ * Adding an imperative API to LuiListBox to allow selecting or focusing the first item ([#1169](https://github.com/linz/lui/issues/1169)) ([fd56d9c](https://github.com/linz/lui/commit/fd56d9c520e4523820bd22567a0bf8e420b3a455))
7
+
8
+ # [21.52.0](https://github.com/linz/lui/compare/v21.51.1...v21.52.0) (2024-11-03)
9
+
10
+
11
+ ### Features
12
+
13
+ * Adding onNavigateOutOfBounds callback to LuiListBox ([#1168](https://github.com/linz/lui/issues/1168)) ([1146b6f](https://github.com/linz/lui/commit/1146b6f719be86b206687862ca8043958e44c211))
14
+
1
15
  ## [21.51.1](https://github.com/linz/lui/compare/v21.51.0...v21.51.1) (2024-10-31)
2
16
 
3
17
 
@@ -1,6 +1,6 @@
1
1
  import './LuiListBox.scss';
2
2
  import 'react-loading-skeleton/dist/skeleton.css';
3
- import { HTMLAttributes, Key, ReactNode } from 'react';
3
+ import { HTMLAttributes, Key, ReactNode, MutableRefObject } from 'react';
4
4
  import { SelectionBehavior, SelectionMode } from '@react-types/shared';
5
5
  import { AriaListBoxOptions } from '@react-aria/listbox';
6
6
  export declare type KeyGetter<T> = (item: T) => Key;
@@ -44,5 +44,15 @@ export interface ILuiListBoxProps<T = ILuiListBoxItem> extends Omit<HTMLAttribut
44
44
  getLabel?: LabelGetter<T>;
45
45
  loadingIndicator?: () => ReactNode;
46
46
  emptyIndicator?: () => ReactNode;
47
+ onNavigateOutOfBounds?: (bound: 'start' | 'end') => void;
47
48
  }
48
- export declare function LuiListBox<T extends object = ILuiListBoxItem>({ ariaLabel, ariaLabelledBy, itemRenderer, groupHeadingRenderer, loadingIndicator, emptyIndicator, selectionMode, selectionBehavior, disabled, disabledKeys, items, value, onChange, getKey, getGroup, getLabel, ariaProps, className, ...ulProps }: ILuiListBoxProps<T>): JSX.Element;
49
+ export interface ILuiListBoxHandle {
50
+ focusFirstItem: () => void;
51
+ selectFirstItem: () => void;
52
+ }
53
+ declare type ForwardedRef<T> = ((instance: T | null) => void) | MutableRefObject<T | null> | null;
54
+ export declare const LuiListBox: <T extends object = ILuiListBoxItem>(props: ILuiListBoxProps<T> & {
55
+ ref?: ForwardedRef<ILuiListBoxHandle> | undefined;
56
+ }) => ReturnType<typeof LuiListBoxWithRef>;
57
+ declare function LuiListBoxWithRef<T extends object = ILuiListBoxItem>(props: ILuiListBoxProps<T>, ref: ForwardedRef<ILuiListBoxHandle>): JSX.Element;
58
+ export {};
package/dist/index.d.ts CHANGED
@@ -59,7 +59,7 @@ export { LuiAccordicard } from './components/LuiAccordicard/LuiAccordicard';
59
59
  export { LuiAccordicardStatic } from './components/LuiAccordicardStatic/LuiAccordicardStatic';
60
60
  export { LuiAccordion } from './components/LuiAccordion/LuiAccordion';
61
61
  export * from './components/LuiMultiSwitch/LuiMultiSwitch';
62
- export { LuiListBox, type ILuiListBoxItem, type ILuiListBoxProps, type IItemRendererProps, } from './components/LuiListBox/LuiListBox';
62
+ export { LuiListBox, type ILuiListBoxItem, type ILuiListBoxProps, type IItemRendererProps, type ILuiListBoxHandle, } from './components/LuiListBox/LuiListBox';
63
63
  export { RadioItemRenderer } from './components/LuiListBox/Renderers/RadioItemRenderer';
64
64
  export { CheckboxItemRenderer } from './components/LuiListBox/Renderers/CheckboxItemRenderer';
65
65
  export { LuiSideMenu, type ILuiSideMenuProps, } from './components/LuiSideMenu/LuiSideMenu';
package/dist/index.js CHANGED
@@ -55177,7 +55177,7 @@ function useLuiListBox(_a) {
55177
55177
  if (!onChange) {
55178
55178
  return;
55179
55179
  }
55180
- onChange(keys === 'all' ? items.map(function (item) { return getKey(item); }) : Array.from(keys), keys === 'all' ? items : items.filter(function (item) { return keys.has(getKey(item)); }));
55180
+ onChange(keys === 'all' ? items.map(getKey) : Array.from(keys), keys === 'all' ? items : items.filter(function (item) { return keys.has(getKey(item)); }));
55181
55181
  }, [items, onChange, getKey]);
55182
55182
  var nodes = React.useMemo(function () { return mapItemsToNodes(items, getKey, getGroup, getLabel); }, [items, getKey, getGroup, getLabel]);
55183
55183
  return __assign(__assign({}, ariaProps), { items: nodes, selectionMode: selectionMode, selectionBehavior: selectionBehavior, selectedKeys: (Array.isArray(value) ? value : [value]).filter(Boolean), children: children, onSelectionChange: onSelectionChange, disabledKeys: disabled ? items.map(getKey) : disabledKeys });
@@ -58330,8 +58330,9 @@ function LuiListBoxGroup(_a) {
58330
58330
  React__default["default"].createElement("ul", __assign({ className: "LuiListBoxGroup-items" }, groupProps), (group.childNodes || []).map(function (node) { return (React__default["default"].createElement(LuiListBoxItem, { key: node.key, node: node, state: state, renderer: itemRenderer })); }))));
58331
58331
  }
58332
58332
 
58333
- function LuiListBox(_a) {
58334
- var ariaLabel = _a.ariaLabel, ariaLabelledBy = _a.ariaLabelledBy, _b = _a.itemRenderer, itemRenderer = _b === void 0 ? DefaultItemRenderer : _b, _c = _a.groupHeadingRenderer, groupHeadingRenderer = _c === void 0 ? DefaultGroupHeadingRenderer : _c, _d = _a.loadingIndicator, loadingIndicator = _d === void 0 ? DefaultLoadingIndicator : _d, _e = _a.emptyIndicator, emptyIndicator = _e === void 0 ? DefaultEmptyIndicator : _e, _f = _a.selectionMode, selectionMode = _f === void 0 ? 'single' : _f, _g = _a.selectionBehavior, selectionBehavior = _g === void 0 ? 'toggle' : _g, _h = _a.disabled, disabled = _h === void 0 ? false : _h, _j = _a.disabledKeys, disabledKeys = _j === void 0 ? [] : _j, items = _a.items, value = _a.value, onChange = _a.onChange, getKey = _a.getKey, getGroup = _a.getGroup, getLabel = _a.getLabel, ariaProps = _a.ariaProps, className = _a.className, ulProps = __rest(_a, ["ariaLabel", "ariaLabelledBy", "itemRenderer", "groupHeadingRenderer", "loadingIndicator", "emptyIndicator", "selectionMode", "selectionBehavior", "disabled", "disabledKeys", "items", "value", "onChange", "getKey", "getGroup", "getLabel", "ariaProps", "className"]);
58333
+ var LuiListBox = React.forwardRef(LuiListBoxWithRef);
58334
+ function LuiListBoxWithRef(props, ref) {
58335
+ var ariaLabel = props.ariaLabel, ariaLabelledBy = props.ariaLabelledBy, _a = props.itemRenderer, itemRenderer = _a === void 0 ? DefaultItemRenderer : _a, _b = props.groupHeadingRenderer, groupHeadingRenderer = _b === void 0 ? DefaultGroupHeadingRenderer : _b, _c = props.loadingIndicator, loadingIndicator = _c === void 0 ? DefaultLoadingIndicator : _c, _d = props.emptyIndicator, emptyIndicator = _d === void 0 ? DefaultEmptyIndicator : _d, _e = props.selectionMode, selectionMode = _e === void 0 ? 'single' : _e, _f = props.selectionBehavior, selectionBehavior = _f === void 0 ? 'toggle' : _f, _g = props.disabled, disabled = _g === void 0 ? false : _g, _h = props.disabledKeys, disabledKeys = _h === void 0 ? [] : _h, items = props.items, value = props.value, onChange = props.onChange, getKey = props.getKey, getGroup = props.getGroup, getLabel = props.getLabel, ariaProps = props.ariaProps, className = props.className, onNavigateOutOfBounds = props.onNavigateOutOfBounds, ulProps = __rest(props, ["ariaLabel", "ariaLabelledBy", "itemRenderer", "groupHeadingRenderer", "loadingIndicator", "emptyIndicator", "selectionMode", "selectionBehavior", "disabled", "disabledKeys", "items", "value", "onChange", "getKey", "getGroup", "getLabel", "ariaProps", "className", "onNavigateOutOfBounds"]);
58335
58336
  var listProps = useLuiListBox({
58336
58337
  selectionMode: selectionMode,
58337
58338
  selectionBehavior: selectionBehavior,
@@ -58346,10 +58347,38 @@ function LuiListBox(_a) {
58346
58347
  disabledKeys: disabledKeys
58347
58348
  });
58348
58349
  var ariaListBoxProps = React.useMemo(function () { return (__assign({ 'aria-label': ariaLabel, 'aria-labelledby': ariaLabelledBy }, listProps)); }, [listProps, ariaLabel, ariaLabelledBy]);
58349
- var ref = React.useRef(null);
58350
+ var listRef = React.useRef(null);
58350
58351
  var state = $e72dd72e1c76a225$export$2f645645f7bca764(listProps);
58351
- var listBoxProps = $c132121280ec012d$export$50eacbbf140a3141(ariaListBoxProps, state, ref).listBoxProps;
58352
- return (React__default["default"].createElement("ul", __assign({}, ulProps, listBoxProps, { ref: ref, className: clsx('LuiListBox', className) }),
58352
+ var listBoxProps = $c132121280ec012d$export$50eacbbf140a3141(ariaListBoxProps, state, listRef).listBoxProps;
58353
+ var getFirstItem = function () { var _a; return (_a = listRef.current) === null || _a === void 0 ? void 0 : _a.querySelector('li[data-key]:first-of-type'); };
58354
+ React.useImperativeHandle(ref, function () { return ({
58355
+ focusFirstItem: function () {
58356
+ var _a;
58357
+ (_a = getFirstItem()) === null || _a === void 0 ? void 0 : _a.focus();
58358
+ },
58359
+ selectFirstItem: function () {
58360
+ var _a;
58361
+ (_a = getFirstItem()) === null || _a === void 0 ? void 0 : _a.click();
58362
+ }
58363
+ }); });
58364
+ var onKeyDown = function (e) {
58365
+ var _a, _b;
58366
+ var lastFocusedKey = state.selectionManager.focusedKey;
58367
+ (_a = listBoxProps.onKeyDown) === null || _a === void 0 ? void 0 : _a.call(listBoxProps, e);
58368
+ (_b = ulProps.onKeyDown) === null || _b === void 0 ? void 0 : _b.call(ulProps, e);
58369
+ var currentFocusedKey = state.selectionManager.focusedKey;
58370
+ // Events can bubble through portals, ensure we are dealing with an element in this list (not a modal or menu rendered by an item in the list)
58371
+ if (!e.currentTarget.contains(e.target)) {
58372
+ return;
58373
+ }
58374
+ if (e.key === 'ArrowUp' && lastFocusedKey === currentFocusedKey) {
58375
+ onNavigateOutOfBounds === null || onNavigateOutOfBounds === void 0 ? void 0 : onNavigateOutOfBounds('start');
58376
+ }
58377
+ if (e.key === 'ArrowDown' && lastFocusedKey === currentFocusedKey) {
58378
+ onNavigateOutOfBounds === null || onNavigateOutOfBounds === void 0 ? void 0 : onNavigateOutOfBounds('end');
58379
+ }
58380
+ };
58381
+ return (React__default["default"].createElement("ul", __assign({}, ulProps, listBoxProps, { onKeyDown: onKeyDown, ref: listRef, className: clsx('LuiListBox', className) }),
58353
58382
  !items && loadingIndicator(),
58354
58383
  (items === null || items === void 0 ? void 0 : items.length) === 0 && emptyIndicator(),
58355
58384
  Array.from(state.collection).map(function (node) {