@trackunit/react-components 0.1.99 → 0.1.101

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.cjs CHANGED
@@ -10,6 +10,7 @@ var reactUse = require('react-use');
10
10
  var reactDayPicker = require('react-day-picker');
11
11
  var locale = require('date-fns/locale');
12
12
  var react = require('@floating-ui/react');
13
+ var lodash = require('lodash');
13
14
  var usePortal = require('react-useportal');
14
15
  var reactRouterDom = require('react-router-dom');
15
16
  var reactHelmetAsync = require('react-helmet-async');
@@ -1278,6 +1279,50 @@ function tryParse(value) {
1278
1279
  }
1279
1280
  }
1280
1281
 
1282
+ /**
1283
+ * Given any value this hook will return the previous value whenever the current value changes
1284
+ */
1285
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1286
+ function usePrevious(value) {
1287
+ const ref = React.useRef();
1288
+ React.useEffect(() => {
1289
+ ref.current = value;
1290
+ });
1291
+ return ref.current;
1292
+ }
1293
+ /**
1294
+ * Wraps a normal useReducer with local storage functionality
1295
+ *
1296
+ * @param {string} key - The key the state is saved with in local storage.
1297
+ */
1298
+ const useLocalStorageReducer = (key, reducer, initialState
1299
+ //return must be explicitly typed atm for some reason
1300
+ ) => {
1301
+ const init = () => {
1302
+ const stringState = localStorage.getItem(key);
1303
+ if (stringState) {
1304
+ try {
1305
+ return JSON.parse(stringState);
1306
+ }
1307
+ catch (error) {
1308
+ return initialState;
1309
+ }
1310
+ }
1311
+ else {
1312
+ return initialState;
1313
+ }
1314
+ };
1315
+ const [state, dispatch] = React.useReducer(reducer, initialState, init);
1316
+ const prevState = usePrevious(state);
1317
+ React.useEffect(() => {
1318
+ if (!lodash.isEqual(prevState, state)) {
1319
+ const stringifiedState = JSON.stringify(state);
1320
+ localStorage.setItem(key, stringifiedState);
1321
+ }
1322
+ }, [prevState, state, key]);
1323
+ return [state, dispatch];
1324
+ };
1325
+
1281
1326
  /**
1282
1327
  * Custom hook to handle window resize events and provide the current window size.
1283
1328
  *
@@ -1362,15 +1407,15 @@ const MoreMenu = ({ className, dataTestId, menuPlacement, iconProps = {
1362
1407
  circular: true,
1363
1408
  square: true,
1364
1409
  color: "tertiary",
1365
- }, children, }) => {
1410
+ }, customButton, children, }) => {
1366
1411
  const [actionMenuIsOpen, setActionMenuIsOpen] = React.useState(false);
1367
1412
  const actionMenuRef = React.useRef(null);
1368
1413
  useClickOutside(actionMenuRef, () => {
1369
1414
  setActionMenuIsOpen(false);
1370
1415
  });
1371
- return (jsxRuntime.jsx(Root$3, Object.assign({ ref: actionMenuRef, className: className, "data-testid": dataTestId }, { children: jsxRuntime.jsxs(Popover, Object.assign({ placement: menuPlacement }, { children: [jsxRuntime.jsx(PopoverTrigger, { children: jsxRuntime.jsx(IconButton, Object.assign({}, iconButtonProps, { icon: iconProps.name ? jsxRuntime.jsx(Icon, Object.assign({}, iconProps, { name: iconProps.name })) : null, onClick: () => {
1416
+ return (jsxRuntime.jsx(Root$3, Object.assign({ ref: actionMenuRef, className: className, "data-testid": dataTestId }, { children: jsxRuntime.jsxs(Popover, Object.assign({ placement: menuPlacement }, { children: [jsxRuntime.jsx(PopoverTrigger, { children: customButton !== null && customButton !== void 0 ? customButton : (jsxRuntime.jsx(IconButton, Object.assign({}, iconButtonProps, { icon: iconProps.name ? jsxRuntime.jsx(Icon, Object.assign({}, iconProps, { name: iconProps.name })) : null, onClick: () => {
1372
1417
  setActionMenuIsOpen(!actionMenuIsOpen);
1373
- } })) }), jsxRuntime.jsx(PopoverContent, { children: close => (typeof children === "function" ? children(close) : children) })] })) })));
1418
+ } }))) }), jsxRuntime.jsx(PopoverContent, { children: close => (typeof children === "function" ? children(close) : children) })] })) })));
1374
1419
  };
1375
1420
  const Root$3 = tailwindStyledComponents.tw.div `
1376
1421
  tu-more-menu
@@ -2245,6 +2290,7 @@ exports.useContainerProps = useContainerProps;
2245
2290
  exports.useDebounce = useDebounce;
2246
2291
  exports.useDevicePixelRatio = useDevicePixelRatio;
2247
2292
  exports.useLocalStorage = useLocalStorage;
2293
+ exports.useLocalStorageReducer = useLocalStorageReducer;
2248
2294
  exports.useModal = useModal;
2249
2295
  exports.usePopoverContext = usePopoverContext;
2250
2296
  exports.usePrompt = usePrompt;
package/index.js CHANGED
@@ -1,12 +1,13 @@
1
1
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
2
  import { tw, tws, twx } from '@trackunit/tailwind-styled-components';
3
3
  import * as React from 'react';
4
- import React__default, { useState, useMemo, createContext, useContext, forwardRef, isValidElement, cloneElement, useCallback, useEffect, Children, useRef, memo } from 'react';
4
+ import React__default, { useState, useMemo, createContext, useContext, forwardRef, isValidElement, cloneElement, useCallback, useEffect, Children, useReducer, useRef, memo } from 'react';
5
5
  import { HeroIconsArray, heroIconLookup, TrackunitSolidIconsArray, TrackunitOutlineIconsArray, trackunitIconLookup } from '@trackunit/ui-icons';
6
6
  import { useMeasure, useCopyToClipboard } from 'react-use';
7
7
  import { DayPicker as DayPicker$1 } from 'react-day-picker';
8
8
  import { enGB, enUS, da, de, cs, nl, fr, fi, hu, it, nb, pl, pt, ru, ro, es, sv, ja, th } from 'date-fns/locale';
9
9
  import { useFloating, autoUpdate, offset, flip, shift, size, useClick, useDismiss, useHover, useRole, useInteractions, useMergeRefs, FloatingPortal, FloatingFocusManager } from '@floating-ui/react';
10
+ import { isEqual } from 'lodash';
10
11
  import usePortal from 'react-useportal';
11
12
  import { UNSAFE_NavigationContext } from 'react-router-dom';
12
13
  import { HelmetProvider, Helmet } from 'react-helmet-async';
@@ -1251,6 +1252,50 @@ function tryParse(value) {
1251
1252
  }
1252
1253
  }
1253
1254
 
1255
+ /**
1256
+ * Given any value this hook will return the previous value whenever the current value changes
1257
+ */
1258
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1259
+ function usePrevious(value) {
1260
+ const ref = useRef();
1261
+ useEffect(() => {
1262
+ ref.current = value;
1263
+ });
1264
+ return ref.current;
1265
+ }
1266
+ /**
1267
+ * Wraps a normal useReducer with local storage functionality
1268
+ *
1269
+ * @param {string} key - The key the state is saved with in local storage.
1270
+ */
1271
+ const useLocalStorageReducer = (key, reducer, initialState
1272
+ //return must be explicitly typed atm for some reason
1273
+ ) => {
1274
+ const init = () => {
1275
+ const stringState = localStorage.getItem(key);
1276
+ if (stringState) {
1277
+ try {
1278
+ return JSON.parse(stringState);
1279
+ }
1280
+ catch (error) {
1281
+ return initialState;
1282
+ }
1283
+ }
1284
+ else {
1285
+ return initialState;
1286
+ }
1287
+ };
1288
+ const [state, dispatch] = useReducer(reducer, initialState, init);
1289
+ const prevState = usePrevious(state);
1290
+ useEffect(() => {
1291
+ if (!isEqual(prevState, state)) {
1292
+ const stringifiedState = JSON.stringify(state);
1293
+ localStorage.setItem(key, stringifiedState);
1294
+ }
1295
+ }, [prevState, state, key]);
1296
+ return [state, dispatch];
1297
+ };
1298
+
1254
1299
  /**
1255
1300
  * Custom hook to handle window resize events and provide the current window size.
1256
1301
  *
@@ -1335,15 +1380,15 @@ const MoreMenu = ({ className, dataTestId, menuPlacement, iconProps = {
1335
1380
  circular: true,
1336
1381
  square: true,
1337
1382
  color: "tertiary",
1338
- }, children, }) => {
1383
+ }, customButton, children, }) => {
1339
1384
  const [actionMenuIsOpen, setActionMenuIsOpen] = useState(false);
1340
1385
  const actionMenuRef = useRef(null);
1341
1386
  useClickOutside(actionMenuRef, () => {
1342
1387
  setActionMenuIsOpen(false);
1343
1388
  });
1344
- return (jsx(Root$3, Object.assign({ ref: actionMenuRef, className: className, "data-testid": dataTestId }, { children: jsxs(Popover, Object.assign({ placement: menuPlacement }, { children: [jsx(PopoverTrigger, { children: jsx(IconButton, Object.assign({}, iconButtonProps, { icon: iconProps.name ? jsx(Icon, Object.assign({}, iconProps, { name: iconProps.name })) : null, onClick: () => {
1389
+ return (jsx(Root$3, Object.assign({ ref: actionMenuRef, className: className, "data-testid": dataTestId }, { children: jsxs(Popover, Object.assign({ placement: menuPlacement }, { children: [jsx(PopoverTrigger, { children: customButton !== null && customButton !== void 0 ? customButton : (jsx(IconButton, Object.assign({}, iconButtonProps, { icon: iconProps.name ? jsx(Icon, Object.assign({}, iconProps, { name: iconProps.name })) : null, onClick: () => {
1345
1390
  setActionMenuIsOpen(!actionMenuIsOpen);
1346
- } })) }), jsx(PopoverContent, { children: close => (typeof children === "function" ? children(close) : children) })] })) })));
1391
+ } }))) }), jsx(PopoverContent, { children: close => (typeof children === "function" ? children(close) : children) })] })) })));
1347
1392
  };
1348
1393
  const Root$3 = tw.div `
1349
1394
  tu-more-menu
@@ -2155,4 +2200,4 @@ const Layout = tw.div `
2155
2200
  tu-layout-TwoColumnLayout
2156
2201
  `;
2157
2202
 
2158
- export { Alert, Badge, Button, Card, CardBody, CardFooter, CardHeader, Collapse, ContentGridArea, CopyableText, DayPicker, DayPickerPopover, DayRangePicker, DensityContainer, Drawer, ExternalLink, FilterListMapLayout, FullWidthRepeatingLayout, GridArea, Heading$1 as Heading, Icon, IconButton, Indicator, IntrinsicallyResponsiveGrid, MenuItem, MenuList, MinTopFullContentLayout, Modal, ModalBackdrop, MoreMenu, NavGridArea, PageHeader, Pagination, Popover, PopoverContent, PopoverTitle, PopoverTrigger, Prompt, ROLE_CARD, SectionHeader, Sidebar, SkeletonLines, Spacer, Spinner, StarButton, Tag, Text$1 as Text, Timeline, TimelineElement, Tip, TitleGridArea, TitleNavContentLayout, Tooltip, TwoColumnLayout, ValueBar, docs, getDevicePixelRatio, getValueBarColorByValue, useClickOutside, useContainerProps, useDebounce, useDevicePixelRatio, useLocalStorage, useModal, usePopoverContext, usePrompt, useResize, useTimeout };
2203
+ export { Alert, Badge, Button, Card, CardBody, CardFooter, CardHeader, Collapse, ContentGridArea, CopyableText, DayPicker, DayPickerPopover, DayRangePicker, DensityContainer, Drawer, ExternalLink, FilterListMapLayout, FullWidthRepeatingLayout, GridArea, Heading$1 as Heading, Icon, IconButton, Indicator, IntrinsicallyResponsiveGrid, MenuItem, MenuList, MinTopFullContentLayout, Modal, ModalBackdrop, MoreMenu, NavGridArea, PageHeader, Pagination, Popover, PopoverContent, PopoverTitle, PopoverTrigger, Prompt, ROLE_CARD, SectionHeader, Sidebar, SkeletonLines, Spacer, Spinner, StarButton, Tag, Text$1 as Text, Timeline, TimelineElement, Tip, TitleGridArea, TitleNavContentLayout, Tooltip, TwoColumnLayout, ValueBar, docs, getDevicePixelRatio, getValueBarColorByValue, useClickOutside, useContainerProps, useDebounce, useDevicePixelRatio, useLocalStorage, useLocalStorageReducer, useModal, usePopoverContext, usePrompt, useResize, useTimeout };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trackunit/react-components",
3
- "version": "0.1.99",
3
+ "version": "0.1.101",
4
4
  "repository": "https://github.com/Trackunit/manager",
5
5
  "license": "SEE LICENSE IN LICENSE.txt",
6
6
  "dependencies": {
@@ -10,6 +10,7 @@
10
10
  "@trackunit/ui-design-tokens": "0.0.66",
11
11
  "@trackunit/ui-icons": "0.0.64",
12
12
  "date-fns": "2.29.3",
13
+ "lodash": "4.17.21",
13
14
  "react": "18.2.0",
14
15
  "react-day-picker": "8.7.1",
15
16
  "react-dom": "18.2.0",
@@ -1,4 +1,4 @@
1
- /// <reference types="react" />
1
+ import { ReactNode } from "react";
2
2
  import { CommonProps } from "../../../common/CommonProps";
3
3
  import { IconButtonProps } from "../../buttons";
4
4
  import { IconProps } from "../../Icon/Icon";
@@ -11,6 +11,7 @@ export interface MoreMenuProps extends CommonProps {
11
11
  menuPlacement?: PopoverPlacement;
12
12
  iconProps?: FilteredIconProps;
13
13
  iconButtonProps?: FilteredIconButtonProps;
14
+ customButton?: ReactNode;
14
15
  }
15
16
  /**
16
17
  * A kebab menu component.
@@ -19,5 +20,5 @@ export interface MoreMenuProps extends CommonProps {
19
20
  * @param {MoreMenuProps} props - The props for the MoreMenu component
20
21
  * @returns {JSX.Element} MoreMenu component
21
22
  */
22
- export declare const MoreMenu: ({ className, dataTestId, menuPlacement, iconProps, iconButtonProps, children, }: MoreMenuProps) => JSX.Element;
23
+ export declare const MoreMenu: ({ className, dataTestId, menuPlacement, iconProps, iconButtonProps, customButton, children, }: MoreMenuProps) => JSX.Element;
23
24
  export {};
@@ -2,5 +2,6 @@ export * from "./useClickOutside";
2
2
  export * from "./useDebounce";
3
3
  export * from "./useDevicePixelRatio";
4
4
  export * from "./useLocalStorage";
5
+ export * from "./useLocalStorageReducer";
5
6
  export * from "./useResize";
6
7
  export * from "./useTimeout";
@@ -0,0 +1,7 @@
1
+ import { Dispatch } from "react";
2
+ /**
3
+ * Wraps a normal useReducer with local storage functionality
4
+ *
5
+ * @param {string} key - The key the state is saved with in local storage.
6
+ */
7
+ export declare const useLocalStorageReducer: <State, Action>(key: string, reducer: (state: State, action: Action) => State, initialState: State) => [State, Dispatch<Action>];