@adamjanicki/ui-extended 1.0.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Adam Janicki
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,38 @@
1
+ # @adamjanicki/ui-extended
2
+
3
+ **Warning: use at own risk, these are mainly for personal use across my other sites, so while I strive to write good code, there may be bugs!**
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @adamjanicki/ui-extended
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```ts
14
+ // Add here
15
+ ```
16
+
17
+ ## Importing CSS
18
+
19
+ Unfortunately, there was no great way to handle CSS. I often hate how large libraries make it extremely difficult to override CSS without using `!important`, or using inline styles. So, I've decided to just import the CSS directly into your project. Here's an example of how to do it:
20
+
21
+ ```ts
22
+ import React from "react";
23
+ import ReactDOM from "react-dom/client";
24
+ // Make sure to import this first so your styles take priority!
25
+ import "@adamjanicki/ui-extended/style.css";
26
+ // All your other global styles can go here!
27
+ import "src/css/style.css";
28
+ import App from "src/App";
29
+
30
+ const root = ReactDOM.createRoot(
31
+ document.getElementById("root") as HTMLElement
32
+ );
33
+ root.render(
34
+ <React.StrictMode>
35
+ <App />
36
+ </React.StrictMode>
37
+ );
38
+ ```
@@ -0,0 +1,89 @@
1
+ import React from "react";
2
+ import Popover from "../Popover/Popover";
3
+ import { IconInput } from "@adamjanicki/ui";
4
+ interface Props<T> {
5
+ /**
6
+ * The value of the input field
7
+ */
8
+ value: string;
9
+ /**
10
+ * Callback for when the input field changes
11
+ * @param event standard React ChangeEvent
12
+ */
13
+ onInputChange: (event: React.ChangeEvent<HTMLInputElement>) => void;
14
+ /**
15
+ * Callback for when an option is selected
16
+ * @param value selected value
17
+ */
18
+ onSelect: (value: T) => void;
19
+ /**
20
+ * The list of available options
21
+ */
22
+ options: T[] | readonly T[];
23
+ /**
24
+ * Predicate to filter options
25
+ * @param option current option
26
+ * @returns true if the option should be displayed
27
+ */
28
+ filterOption?: (option: T) => boolean;
29
+ /**
30
+ * Render function for the option
31
+ * @param option current option
32
+ * @returns node to render for the option
33
+ */
34
+ renderOption?: (option: T) => React.ReactNode;
35
+ /**
36
+ * Node to render when no options are available
37
+ */
38
+ noOptionsNode?: React.ReactNode;
39
+ /**
40
+ * Classname to apply to the root element
41
+ */
42
+ className?: string;
43
+ /**
44
+ * Style to apply to the root element
45
+ */
46
+ style?: React.CSSProperties;
47
+ /**
48
+ * Group options by a string
49
+ * @param option current option
50
+ * @returns String to group by
51
+ */
52
+ groupBy?: (option: T) => string;
53
+ /**
54
+ * Render function for the group
55
+ * @param group name
56
+ * @returns node to render for the group
57
+ */
58
+ renderGroup?: (group: string) => React.ReactNode;
59
+ /**
60
+ * Allow free text input
61
+ */
62
+ freeSolo?: boolean;
63
+ /**
64
+ * Focus on the input field after selecting an option
65
+ */
66
+ focusOnSelect?: boolean;
67
+ /**
68
+ * Props for the input field
69
+ */
70
+ InputProps?: React.ComponentProps<typeof IconInput>;
71
+ /**
72
+ * Props for the popover
73
+ */
74
+ popoverProps?: Partial<React.ComponentProps<typeof Popover>>;
75
+ /**
76
+ * Props for the list element
77
+ */
78
+ listProps?: React.ComponentProps<"ul">;
79
+ /**
80
+ * Props for the list item elements
81
+ */
82
+ listItemProps?: React.ComponentProps<"li">;
83
+ /**
84
+ * Footer node to render at the bottom of the popover
85
+ */
86
+ footer?: React.ReactNode;
87
+ }
88
+ declare const Autocomplete: <T>(props: Props<T>) => JSX.Element;
89
+ export default Autocomplete;
@@ -0,0 +1,133 @@
1
+ var __assign = (this && this.__assign) || function () {
2
+ __assign = Object.assign || function(t) {
3
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
4
+ s = arguments[i];
5
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
6
+ t[p] = s[p];
7
+ }
8
+ return t;
9
+ };
10
+ return __assign.apply(this, arguments);
11
+ };
12
+ var __rest = (this && this.__rest) || function (s, e) {
13
+ var t = {};
14
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
15
+ t[p] = s[p];
16
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
17
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
18
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
19
+ t[p[i]] = s[p[i]];
20
+ }
21
+ return t;
22
+ };
23
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
24
+ import React from "react";
25
+ import Popover from "../Popover/Popover";
26
+ import ClickOutside from "@adamjanicki/ui/components/ClickOutside";
27
+ import { IconInput } from "@adamjanicki/ui";
28
+ import { classNames } from "@adamjanicki/ui/utils/util";
29
+ var defaultRenderOption = function (option) { return (_jsx("div", { className: "ajui-autocomplete-default-rendering", children: "".concat(option) })); };
30
+ var Autocomplete = function (props) {
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"]);
33
+ var onRef = React.useRef(null);
34
+ var nextRef = React.useRef(null);
35
+ var prevRef = React.useRef(null);
36
+ var _k = React.useState(), on = _k[0], setOn = _k[1];
37
+ var filteredOptions = options.filter(filterOption);
38
+ var groupMap = new Map();
39
+ if (groupBy) {
40
+ var uniqueGroups_1 = [];
41
+ filteredOptions.forEach(function (option) {
42
+ var group = groupBy(option);
43
+ if (!uniqueGroups_1.includes(group)) {
44
+ uniqueGroups_1.push(group);
45
+ }
46
+ });
47
+ var offset_1 = 0;
48
+ filteredOptions = uniqueGroups_1
49
+ .map(function (group) {
50
+ var filtered = filteredOptions.filter(function (option) { return groupBy(option) === group; });
51
+ groupMap.set(offset_1, group);
52
+ offset_1 += filtered.length;
53
+ return filtered;
54
+ })
55
+ .flat();
56
+ }
57
+ if (freeSolo && value.length > 0 && filteredOptions.length === 0) {
58
+ filteredOptions.push(value);
59
+ }
60
+ var handleChange = function (v) {
61
+ onSelect(v);
62
+ var current = inputRef.current;
63
+ closeMenu();
64
+ if (focusOnSelect)
65
+ return current === null || current === void 0 ? void 0 : current.focus();
66
+ };
67
+ var closeMenu = function () {
68
+ setOn(undefined);
69
+ setOpen(false);
70
+ };
71
+ var openMenu = function () {
72
+ setOpen(true);
73
+ };
74
+ var handleKeys = function (_a) {
75
+ var code = _a.code;
76
+ if (code === "Escape") {
77
+ closeMenu();
78
+ }
79
+ var modulo = filteredOptions.length;
80
+ if (code === "Enter") {
81
+ var current = onRef.current;
82
+ if (modulo > 0 && current) {
83
+ return current.click();
84
+ }
85
+ }
86
+ if (modulo > 0 && code === "ArrowDown") {
87
+ var newOn = ((on !== undefined ? on : -1) + 1) % modulo;
88
+ setOn(newOn);
89
+ if (nextRef.current) {
90
+ nextRef.current.scrollIntoView({
91
+ block: "nearest",
92
+ behavior: "smooth",
93
+ });
94
+ }
95
+ }
96
+ else if (modulo > 0 && code === "ArrowUp") {
97
+ var newOn = ((on !== undefined ? on : 0) - 1 + modulo) % modulo;
98
+ setOn(newOn);
99
+ if (prevRef.current) {
100
+ prevRef.current.scrollIntoView({
101
+ block: "nearest",
102
+ behavior: "smooth",
103
+ });
104
+ }
105
+ }
106
+ };
107
+ var _l = React.useState(false), open = _l[0], setOpen = _l[1];
108
+ var inputContainerRef = React.useRef(null);
109
+ var inputRef = React.useRef(null);
110
+ var popoverOpen = open && (filteredOptions.length > 0 || value.length > 0);
111
+ 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
+ setOn(undefined);
113
+ onInputChange(e);
114
+ if (e.target.value) {
115
+ !open && openMenu();
116
+ }
117
+ else {
118
+ var current = inputRef.current;
119
+ current && current.focus();
120
+ }
121
+ }, onClick: function () {
122
+ !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
124
+ ? filteredOptions.map(function (option, index) {
125
+ 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
127
+ ? "ajui-autocomplete-on-option"
128
+ : undefined, listItemProps.className), onClick: function () { return handleChange(option); }, children: renderOption(option) }))] }, index));
129
+ })
130
+ : !freeSolo &&
131
+ (noOptionsNode || defaultRenderOption("No results found")) })), footer] }))] })) }));
132
+ };
133
+ export default Autocomplete;
@@ -0,0 +1,2 @@
1
+ import Autocomplete from "./Autocomplete";
2
+ export default Autocomplete;
@@ -0,0 +1,2 @@
1
+ import Autocomplete from "./Autocomplete";
2
+ export default Autocomplete;
@@ -0,0 +1,45 @@
1
+ import React from "react";
2
+ import { type Placement } from "@floating-ui/react";
3
+ type Props = {
4
+ /**
5
+ * Children to render inside the popover.
6
+ */
7
+ children: React.ReactNode | React.ReactNode[];
8
+ /**
9
+ * The trigger ref for the element to position the popover over.
10
+ */
11
+ triggerRef: React.RefObject<HTMLElement>;
12
+ /**
13
+ * Whether the popover is open.
14
+ */
15
+ open: boolean;
16
+ /**
17
+ * The placement of the popover relative to the trigger element.
18
+ * @default "bottom"
19
+ */
20
+ placement?: Placement;
21
+ /**
22
+ * Additional styles to apply to the popover container.
23
+ */
24
+ style?: React.CSSProperties;
25
+ /**
26
+ * Additional classes to apply to the popover container.
27
+ */
28
+ className?: string;
29
+ /**
30
+ * The offset of the popover relative to the trigger element.
31
+ * @default 0
32
+ */
33
+ offset?: number;
34
+ /**
35
+ * Callback function to execute when the popover is closed.
36
+ */
37
+ onClose?: () => void;
38
+ /**
39
+ * Whether to return focus to the trigger element when the popover is closed
40
+ * by pressing the escape key.
41
+ */
42
+ returnFocusOnEscape?: boolean;
43
+ };
44
+ declare const Popover: (props: Props) => JSX.Element | null;
45
+ export default Popover;
@@ -0,0 +1,39 @@
1
+ var __assign = (this && this.__assign) || function () {
2
+ __assign = Object.assign || function(t) {
3
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
4
+ s = arguments[i];
5
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
6
+ t[p] = s[p];
7
+ }
8
+ return t;
9
+ };
10
+ return __assign.apply(this, arguments);
11
+ };
12
+ import { jsx as _jsx } from "react/jsx-runtime";
13
+ import { useFloating, autoUpdate, offset, useDismiss, } from "@floating-ui/react";
14
+ var Popover = function (props) {
15
+ var triggerRef = props.triggerRef, open = props.open, _a = props.placement, placement = _a === void 0 ? "bottom" : _a, style = props.style, _b = props.offset, placementOffset = _b === void 0 ? 0 : _b, className = props.className, children = props.children, onClose = props.onClose, _c = props.returnFocusOnEscape, returnFocusOnEscape = _c === void 0 ? true : _c;
16
+ var handleOnClose = function () {
17
+ var _a, _b;
18
+ if (!returnFocusOnEscape)
19
+ (_b = (_a = triggerRef.current) === null || _a === void 0 ? void 0 : _a.blur) === null || _b === void 0 ? void 0 : _b.call(_a);
20
+ onClose === null || onClose === void 0 ? void 0 : onClose();
21
+ };
22
+ var middleware = [offset(placementOffset)];
23
+ var _d = useFloating({
24
+ elements: { reference: triggerRef.current },
25
+ open: open,
26
+ onOpenChange: function (open) {
27
+ if (!open)
28
+ handleOnClose();
29
+ },
30
+ placement: placement,
31
+ whileElementsMounted: autoUpdate,
32
+ middleware: middleware,
33
+ }), floatingStyles = _d.floatingStyles, context = _d.context, refs = _d.refs;
34
+ useDismiss(context);
35
+ if (!open)
36
+ return null;
37
+ return (_jsx("div", { ref: refs.setFloating, style: __assign(__assign(__assign({}, (style || {})), floatingStyles), { outline: "none" }), className: className, children: children }));
38
+ };
39
+ export default Popover;
@@ -0,0 +1,2 @@
1
+ import Popover from "./Popover";
2
+ export default Popover;
@@ -0,0 +1,2 @@
1
+ import Popover from "./Popover";
2
+ export default Popover;
@@ -0,0 +1,36 @@
1
+ import { type Placement } from "@floating-ui/react";
2
+ type Props = {
3
+ /**
4
+ * Children to render inside the tooltip container.
5
+ */
6
+ tooltipContent: React.ReactNode | React.ReactNode[];
7
+ /**
8
+ * The element to attach the tooltip to.
9
+ * **IMPORTANT**: This must be able to hold a ref.
10
+ */
11
+ children: React.ReactElement;
12
+ /**
13
+ * The placement of the popover relative to the trigger element.
14
+ * @default "bottom"
15
+ */
16
+ placement?: Placement;
17
+ /**
18
+ * Additional styles to apply to the tooltip container.
19
+ */
20
+ style?: React.CSSProperties;
21
+ /**
22
+ * Additional classes to apply to the tooltip container.
23
+ */
24
+ className?: string;
25
+ /**
26
+ * The offset of the popover relative to the trigger element.
27
+ * @default 0
28
+ */
29
+ offset?: number;
30
+ /**
31
+ * Whether to disable the flip behavior of the tooltip.
32
+ */
33
+ disableFlip?: boolean;
34
+ };
35
+ declare const Tooltip: (props: Props) => JSX.Element;
36
+ export default Tooltip;
@@ -0,0 +1,37 @@
1
+ var __assign = (this && this.__assign) || function () {
2
+ __assign = Object.assign || function(t) {
3
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
4
+ s = arguments[i];
5
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
6
+ t[p] = s[p];
7
+ }
8
+ return t;
9
+ };
10
+ return __assign.apply(this, arguments);
11
+ };
12
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
13
+ import { cloneElement, useState } from "react";
14
+ import { useFloating, useHover, useInteractions, flip, safePolygon, autoUpdate, offset, } from "@floating-ui/react";
15
+ var Tooltip = function (props) {
16
+ var children = props.children, content = props.tooltipContent, _a = props.placement, placement = _a === void 0 ? "bottom" : _a, style = props.style, _b = props.offset, placementOffset = _b === void 0 ? 0 : _b, className = props.className, _c = props.disableFlip, disableFlip = _c === void 0 ? false : _c;
17
+ var _d = useState(false), open = _d[0], setOpen = _d[1];
18
+ var middleware = [offset(placementOffset)];
19
+ if (!disableFlip) {
20
+ middleware.push(flip());
21
+ }
22
+ var _e = useFloating({
23
+ open: open,
24
+ onOpenChange: setOpen,
25
+ middleware: middleware,
26
+ whileElementsMounted: autoUpdate,
27
+ placement: placement,
28
+ }), refs = _e.refs, floatingStyles = _e.floatingStyles, context = _e.context;
29
+ var hover = useHover(context, {
30
+ delay: { open: 200, close: 100 },
31
+ handleClose: safePolygon(),
32
+ mouseOnly: true,
33
+ });
34
+ var _f = useInteractions([hover]), getReferenceProps = _f.getReferenceProps, getFloatingProps = _f.getFloatingProps;
35
+ return (_jsxs(_Fragment, { children: [cloneElement(children, __assign({ ref: refs.setReference }, getReferenceProps())), open && (_jsx("div", __assign({ ref: refs.setFloating, style: __assign(__assign({}, (style || {})), floatingStyles) }, getFloatingProps(), { className: className, children: content })))] }));
36
+ };
37
+ export default Tooltip;
@@ -0,0 +1,2 @@
1
+ import Tooltip from "./Tooltip";
2
+ export default Tooltip;
@@ -0,0 +1,2 @@
1
+ import Tooltip from "./Tooltip";
2
+ export default Tooltip;
@@ -0,0 +1 @@
1
+ export * from "./useTheme";
package/hooks/index.js ADDED
@@ -0,0 +1 @@
1
+ export * from "./useTheme";
@@ -0,0 +1,24 @@
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;
@@ -0,0 +1,27 @@
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
+ };
package/index.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ export { default as Popover } from "./components/Popover";
2
+ export { default as Tooltip } from "./components/Tooltip";
3
+ export { default as Autocomplete } from "./components/Autocomplete";
package/index.js ADDED
@@ -0,0 +1,4 @@
1
+ // Components
2
+ export { default as Popover } from "./components/Popover";
3
+ export { default as Tooltip } from "./components/Tooltip";
4
+ export { default as Autocomplete } from "./components/Autocomplete";
package/package.json ADDED
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "@adamjanicki/ui-extended",
3
+ "version": "1.0.0",
4
+ "description": "More advanced UI components and hooks for React in TypeScript",
5
+ "main": "./index.js",
6
+ "types": "./index.d.ts",
7
+ "author": "Adam Janicki",
8
+ "license": "MIT",
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "git+https://github.com/adamjanicki2/ui-extended.git"
12
+ },
13
+ "scripts": {
14
+ "build": "tsc; cp src/style.css ./style.css",
15
+ "clean": "./clean.sh",
16
+ "dev": "nodemon --watch src --ext ts,tsx,css --exec \"npm run build\"",
17
+ "lint": "eslint --ext .ts,.tsx src",
18
+ "prepare": "npm run lint; npm run build"
19
+ },
20
+ "peerDependencies": {
21
+ "react": ">=18",
22
+ "react-dom": ">=18"
23
+ },
24
+ "dependencies": {
25
+ "@adamjanicki/ui": ">=1.0.3",
26
+ "@floating-ui/react": ">=0.26.17"
27
+ },
28
+ "devDependencies": {
29
+ "@typescript-eslint/eslint-plugin": "^6.11.0",
30
+ "@typescript-eslint/parser": "^6.11.0",
31
+ "eslint": "^8.53.0",
32
+ "eslint-config-prettier": "^9.0.0",
33
+ "eslint-plugin-react": "^7.33.2",
34
+ "eslint-plugin-react-hooks": "^4.6.0",
35
+ "nodemon": "^3.1.4",
36
+ "typescript": "^5.2.2"
37
+ },
38
+ "eslintConfig": {
39
+ "extends": [
40
+ "react-app",
41
+ "react-app/jest"
42
+ ]
43
+ }
44
+ }
package/style.css ADDED
@@ -0,0 +1,42 @@
1
+ @media (hover: hover) {
2
+ .ajui-autocomplete-on-option,
3
+ .ajui-autocomplete-option:hover {
4
+ background-color: var(--ajui-light-gray);
5
+ }
6
+ [data-theme="dark"] .ajui-autocomplete-on-option,
7
+ [data-theme="dark"] .ajui-autocomplete-option:hover {
8
+ background-color: var(--ajui-darkest-gray);
9
+ }
10
+ }
11
+
12
+ .ajui-autocomplete-popover {
13
+ background-color: var(--ajui-default-background);
14
+ font-size: 1rem;
15
+ font-weight: 400;
16
+ border: 1px solid var(--ajui-default-border);
17
+ overflow: hidden;
18
+ border-radius: var(--ajui-rounded-radius);
19
+ }
20
+
21
+ .ajui-autocomplete-ul {
22
+ overflow: scroll;
23
+ max-height: 300px;
24
+ display: flex;
25
+ flex-direction: column;
26
+ padding: 0.25rem;
27
+ margin: 0;
28
+ }
29
+
30
+ .ajui-autocomplete-default-rendering {
31
+ padding: 0.5rem 1rem;
32
+ }
33
+
34
+ .ajui-autocomplete-li {
35
+ display: flex;
36
+ cursor: pointer;
37
+ border-radius: var(--ajui-rounded-radius);
38
+ }
39
+
40
+ .ajui-autocomplete-li > :first-child {
41
+ border-radius: var(--ajui-rounded-radius);
42
+ }
@@ -0,0 +1,8 @@
1
+ /**
2
+ * The type of corner to display, controlling the border radius property.
3
+ */
4
+ export type CornerType = "pill" | "rounded" | "sharp";
5
+ /**
6
+ * The type of message associated with a piece of content.
7
+ */
8
+ export type ContentType = "success" | "warning" | "error" | "info" | "static";
package/utils/types.js ADDED
@@ -0,0 +1 @@
1
+ export {};