@adamjanicki/ui-extended 1.0.0 → 1.0.2

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.
@@ -1,5 +1,5 @@
1
1
  import React from "react";
2
- import Popover from "../Popover/Popover";
2
+ import Popover from "./Popover";
3
3
  import { IconInput } from "@adamjanicki/ui";
4
4
  interface Props<T> {
5
5
  /**
@@ -84,6 +84,10 @@ interface Props<T> {
84
84
  * Footer node to render at the bottom of the popover
85
85
  */
86
86
  footer?: React.ReactNode;
87
+ /**
88
+ * A callback to be called when the user hits the enter key while no option is selected
89
+ */
90
+ onUnselectedEnter?: () => void;
87
91
  }
88
92
  declare const Autocomplete: <T>(props: Props<T>) => JSX.Element;
89
93
  export default Autocomplete;
@@ -22,18 +22,21 @@ var __rest = (this && this.__rest) || function (s, e) {
22
22
  };
23
23
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
24
24
  import React from "react";
25
- import Popover from "../Popover/Popover";
25
+ import Popover from "./Popover";
26
26
  import ClickOutside from "@adamjanicki/ui/components/ClickOutside";
27
27
  import { IconInput } from "@adamjanicki/ui";
28
28
  import { classNames } from "@adamjanicki/ui/utils/util";
29
29
  var defaultRenderOption = function (option) { return (_jsx("div", { className: "ajui-autocomplete-default-rendering", children: "".concat(option) })); };
30
30
  var Autocomplete = function (props) {
31
31
  var _a, _b;
32
- var options = props.options, _c = props.renderOption, renderOption = _c === void 0 ? defaultRenderOption : _c, _d = props.filterOption, filterOption = _d === void 0 ? function () { return true; } : _d, groupBy = props.groupBy, renderGroup = props.renderGroup, noOptionsNode = props.noOptionsNode, _e = props.InputProps, InputProps = _e === void 0 ? {} : _e, _f = props.freeSolo, freeSolo = _f === void 0 ? false : _f, _g = props.focusOnSelect, focusOnSelect = _g === void 0 ? true : _g, value = props.value, onInputChange = props.onInputChange, onSelect = props.onSelect, popoverProps = props.popoverProps, footer = props.footer, _h = props.listItemProps, listItemProps = _h === void 0 ? {} : _h, _j = props.listProps, listProps = _j === void 0 ? {} : _j, rest = __rest(props, ["options", "renderOption", "filterOption", "groupBy", "renderGroup", "noOptionsNode", "InputProps", "freeSolo", "focusOnSelect", "value", "onInputChange", "onSelect", "popoverProps", "footer", "listItemProps", "listProps"]);
32
+ var options = props.options, _c = props.renderOption, renderOption = _c === void 0 ? defaultRenderOption : _c, _d = props.filterOption, filterOption = _d === void 0 ? function () { return true; } : _d, groupBy = props.groupBy, renderGroup = props.renderGroup, noOptionsNode = props.noOptionsNode, _e = props.InputProps, InputProps = _e === void 0 ? {} : _e, _f = props.freeSolo, freeSolo = _f === void 0 ? false : _f, _g = props.focusOnSelect, focusOnSelect = _g === void 0 ? true : _g, value = props.value, onInputChange = props.onInputChange, onSelect = props.onSelect, popoverProps = props.popoverProps, footer = props.footer, _h = props.listItemProps, listItemProps = _h === void 0 ? {} : _h, _j = props.listProps, listProps = _j === void 0 ? {} : _j, onUnselectedEnter = props.onUnselectedEnter, rest = __rest(props, ["options", "renderOption", "filterOption", "groupBy", "renderGroup", "noOptionsNode", "InputProps", "freeSolo", "focusOnSelect", "value", "onInputChange", "onSelect", "popoverProps", "footer", "listItemProps", "listProps", "onUnselectedEnter"]);
33
+ var inputContainerRef = React.useRef(null);
34
+ var inputRef = React.useRef(null);
33
35
  var onRef = React.useRef(null);
34
36
  var nextRef = React.useRef(null);
35
37
  var prevRef = React.useRef(null);
36
38
  var _k = React.useState(), on = _k[0], setOn = _k[1];
39
+ var _l = React.useState(false), open = _l[0], setOpen = _l[1];
37
40
  var filteredOptions = options.filter(filterOption);
38
41
  var groupMap = new Map();
39
42
  if (groupBy) {
@@ -82,6 +85,9 @@ var Autocomplete = function (props) {
82
85
  if (modulo > 0 && current) {
83
86
  return current.click();
84
87
  }
88
+ else {
89
+ onUnselectedEnter === null || onUnselectedEnter === void 0 ? void 0 : onUnselectedEnter();
90
+ }
85
91
  }
86
92
  if (modulo > 0 && code === "ArrowDown") {
87
93
  var newOn = ((on !== undefined ? on : -1) + 1) % modulo;
@@ -104,9 +110,9 @@ var Autocomplete = function (props) {
104
110
  }
105
111
  }
106
112
  };
107
- var _l = React.useState(false), open = _l[0], setOpen = _l[1];
108
- var inputContainerRef = React.useRef(null);
109
- var inputRef = React.useRef(null);
113
+ var prev = ((on !== null && on !== void 0 ? on : filteredOptions.length) + filteredOptions.length - 1) %
114
+ filteredOptions.length;
115
+ var next = ((on !== null && on !== void 0 ? on : -1) + filteredOptions.length + 1) % filteredOptions.length;
110
116
  var popoverOpen = open && (filteredOptions.length > 0 || value.length > 0);
111
117
  return (_jsx(ClickOutside, { onClickOutside: closeMenu, children: _jsxs("div", __assign({}, rest, { onKeyUp: function (e) { return handleKeys(e); }, children: [_jsx(IconInput, __assign({}, InputProps, { ref: inputContainerRef, inputProps: __assign(__assign({}, (InputProps.inputProps || {})), { value: value, onChange: function (e) {
112
118
  setOn(undefined);
@@ -120,10 +126,17 @@ var Autocomplete = function (props) {
120
126
  }
121
127
  }, onClick: function () {
122
128
  !open && openMenu();
123
- }, ref: inputRef, autoComplete: "off" }) })), _jsxs(Popover, __assign({}, popoverProps, { open: popoverOpen, triggerRef: inputContainerRef, style: __assign(__assign({ zIndex: 100 }, ((popoverProps === null || popoverProps === void 0 ? void 0 : popoverProps.style) || {})), { padding: 0, margin: 0, width: (_b = (_a = inputContainerRef.current) === null || _a === void 0 ? void 0 : _a.offsetWidth) !== null && _b !== void 0 ? _b : 0 }), className: "ajui-autocomplete-popover", children: [_jsx("ul", __assign({}, listProps, { className: classNames("ajui-autocomplete-ul", listProps.className), children: filteredOptions.length
129
+ }, ref: inputRef, autoComplete: "off" }) })), _jsxs(Popover, __assign({}, popoverProps, { open: popoverOpen, triggerRef: inputContainerRef, style: __assign(__assign({ zIndex: 100 }, ((popoverProps === null || popoverProps === void 0 ? void 0 : popoverProps.style) || {})), { padding: 0, margin: 0, width: (_b = (_a = inputContainerRef.current) === null || _a === void 0 ? void 0 : _a.offsetWidth) !== null && _b !== void 0 ? _b : 0 }), className: classNames("ajui-autocomplete-popover", popoverProps === null || popoverProps === void 0 ? void 0 : popoverProps.className), children: [_jsx("ul", __assign({}, listProps, { className: classNames("ajui-autocomplete-ul", listProps.className), children: filteredOptions.length
124
130
  ? filteredOptions.map(function (option, index) {
125
131
  var group = groupMap.get(index);
126
- return (_jsxs(React.Fragment, { children: [group && ((renderGroup === null || renderGroup === void 0 ? void 0 : renderGroup(group)) || group), _jsx("li", __assign({}, listItemProps, { ref: on === index ? onRef : null, onMouseEnter: function () { return setOn(index); }, className: classNames("ajui-autocomplete-li", on === index
132
+ var ref = index === on
133
+ ? onRef
134
+ : index === prev
135
+ ? prevRef
136
+ : index === next
137
+ ? nextRef
138
+ : undefined;
139
+ return (_jsxs(React.Fragment, { children: [group && ((renderGroup === null || renderGroup === void 0 ? void 0 : renderGroup(group)) || group), _jsx("li", __assign({}, listItemProps, { ref: ref, onMouseEnter: function () { return setOn(index); }, className: classNames("ajui-autocomplete-li", on === index
127
140
  ? "ajui-autocomplete-on-option"
128
141
  : undefined, listItemProps.className), onClick: function () { return handleChange(option); }, children: renderOption(option) }))] }, index));
129
142
  })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adamjanicki/ui-extended",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "More advanced UI components and hooks for React in TypeScript",
5
5
  "main": "./index.js",
6
6
  "types": "./index.d.ts",
@@ -1,2 +0,0 @@
1
- import Autocomplete from "./Autocomplete";
2
- export default Autocomplete;
@@ -1,2 +0,0 @@
1
- import Autocomplete from "./Autocomplete";
2
- export default Autocomplete;
@@ -1,2 +0,0 @@
1
- import Popover from "./Popover";
2
- export default Popover;
@@ -1,2 +0,0 @@
1
- import Popover from "./Popover";
2
- export default Popover;
@@ -1,2 +0,0 @@
1
- import Tooltip from "./Tooltip";
2
- export default Tooltip;
@@ -1,2 +0,0 @@
1
- import Tooltip from "./Tooltip";
2
- export default Tooltip;
package/hooks/index.d.ts DELETED
@@ -1 +0,0 @@
1
- export * from "./useTheme";
package/hooks/index.js DELETED
@@ -1 +0,0 @@
1
- export * from "./useTheme";
@@ -1,24 +0,0 @@
1
- export type Theme = "light" | "dark";
2
- export type ThemePreference = Theme | "system";
3
- export type ThemePreferenceStore = {
4
- /**
5
- * The current theme preference.
6
- */
7
- preference: ThemePreference;
8
- /**
9
- * Set the theme preference.
10
- *
11
- * @param preference the new theme preference
12
- */
13
- setPreference: (preference: ThemePreference) => void;
14
- };
15
- /**
16
- * A hook for getting and setting the current theme preference.
17
- */
18
- export declare const useThemePreference: any;
19
- /**
20
- * A hook for getting the current theme
21
- *
22
- * @returns The current theme, either "light" or "dark"
23
- */
24
- export declare const useTheme: () => Theme;
package/hooks/useTheme.js DELETED
@@ -1,27 +0,0 @@
1
- import { create } from "zustand";
2
- import { createJSONStorage, persist } from "zustand/middleware";
3
- import { useMediaQuery } from "@adamjanicki/ui";
4
- /**
5
- * A hook for getting and setting the current theme preference.
6
- */
7
- export var useThemePreference = create(persist(function (set) { return ({
8
- preference: "system",
9
- setPreference: function (preference) { return set({ preference: preference }); },
10
- }); }, {
11
- name: "theme-preference-store",
12
- storage: createJSONStorage(function () { return localStorage; }),
13
- }));
14
- /**
15
- * A hook for getting the current theme
16
- *
17
- * @returns The current theme, either "light" or "dark"
18
- */
19
- export var useTheme = function () {
20
- var prefersDark = useMediaQuery({ query: "(prefers-color-scheme: dark)" });
21
- var preference = useThemePreference().preference;
22
- return preference === "system"
23
- ? prefersDark
24
- ? "dark"
25
- : "light"
26
- : preference;
27
- };
File without changes
File without changes