@trackunit/react-components 0.0.173 → 0.0.175

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.
@@ -0,0 +1,71 @@
1
+ /// <reference types="react" />
2
+ export interface IPaginationProps {
3
+ /**
4
+ * A go to page handler
5
+ */
6
+ gotoPage: (index: number) => void;
7
+ /**
8
+ * A go to previous page handler
9
+ */
10
+ previousPage: () => void;
11
+ /**
12
+ * A a go to next page handler
13
+ */
14
+ nextPage: () => void;
15
+ /**
16
+ * A current page index
17
+ */
18
+ pageIndex?: number;
19
+ /**
20
+ * Amount of pages
21
+ */
22
+ pageCount?: number | null;
23
+ /**
24
+ * A flag to enable previous page button
25
+ */
26
+ canPreviousPage?: boolean;
27
+ /**
28
+ * A flag to enable next page button
29
+ */
30
+ canNextPage?: boolean;
31
+ /**
32
+ * A parent name
33
+ */
34
+ parentName: string;
35
+ /**
36
+ * A event name used for logging
37
+ */
38
+ eventName?: string;
39
+ /**
40
+ * A flag indicating loading state
41
+ */
42
+ loading?: boolean;
43
+ /**
44
+ * A custom class to override styles
45
+ */
46
+ className?: string;
47
+ /**
48
+ * A data test id
49
+ */
50
+ dataTestId?: string;
51
+ /**
52
+ * You can attach logging handler for page change
53
+ */
54
+ logPageChange?: (eventName: string, event: EventProperties) => void;
55
+ /**
56
+ * An helper to get translation for count.
57
+ */
58
+ getTranslatedCount: (count: number) => string;
59
+ /**
60
+ * An helper to get translation for page.
61
+ */
62
+ getTranslatedPage: () => string;
63
+ }
64
+ export declare type EventProperties = Record<string, string | number | boolean | null | undefined | (string | number)[]>;
65
+ /**
66
+ * Pagination Description. It could be used when you need navigation for your paging feature.
67
+ *
68
+ * @param {IPaginationProps} props - The props for the Pagination component
69
+ * @returns {JSX.Element} Pagination component
70
+ */
71
+ export declare const Pagination: ({ gotoPage, previousPage, nextPage, pageCount, pageIndex, canPreviousPage, canNextPage, loading, eventName, parentName, className, dataTestId, logPageChange, getTranslatedCount, getTranslatedPage, }: IPaginationProps) => JSX.Element;
@@ -22,6 +22,7 @@ export * from "./Modal";
22
22
  export * from "./NumberField/NumberField";
23
23
  export * from "./NumberInput/NumberInput";
24
24
  export * from "./PageHeader";
25
+ export * from "./Pagination/Pagination";
25
26
  export * from "./Popover";
26
27
  export * from "./Prompt";
27
28
  export * from "./RadioGroup";
package/index.js CHANGED
@@ -1,7 +1,7 @@
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, forwardRef, useRef, Fragment as Fragment$1, useCallback, createElement, useEffect, useContext, memo } from 'react';
4
+ import React__default, { useState, forwardRef, useRef, Fragment as Fragment$1, useCallback, createElement, memo, useEffect, useContext } from 'react';
5
5
  import { HeroIconsArray, heroIconLookup, TrackunitSolidIconsArray, TrackunitOutlineIconsArray, trackunitIconLookup } from '@trackunit/ui-icons';
6
6
  import EChart from 'echarts-for-react';
7
7
  import { v4 } from 'uuid';
@@ -351,7 +351,7 @@ const Icon$1 = ({
351
351
  className: iconSizeClassName
352
352
  })
353
353
  }, {
354
- children: jsx(Root$4, Object.assign({
354
+ children: jsx(Root$5, Object.assign({
355
355
  "$color": color,
356
356
  onClick: onClick,
357
357
  "data-testid": dataTestId,
@@ -370,7 +370,7 @@ const Icon$1 = ({
370
370
  const LoadingDot = tw.span`
371
371
  tu-loading-dot
372
372
  `;
373
- const Root$4 = tw.span`
373
+ const Root$5 = tw.span`
374
374
  tu-icon
375
375
  ${({
376
376
  $color
@@ -1465,7 +1465,7 @@ const Label$2 = ({
1465
1465
  disabled,
1466
1466
  isInvalid
1467
1467
  }) => {
1468
- return jsx(Root$3, Object.assign({
1468
+ return jsx(Root$4, Object.assign({
1469
1469
  id: id || "",
1470
1470
  htmlFor: htmlFor || "",
1471
1471
  className: className,
@@ -1476,7 +1476,7 @@ const Label$2 = ({
1476
1476
  children: children
1477
1477
  }));
1478
1478
  };
1479
- const Root$3 = tw.label`
1479
+ const Root$4 = tw.label`
1480
1480
  tu-label
1481
1481
  ${({
1482
1482
  $disabled
@@ -2686,7 +2686,7 @@ const LegendItem = ({
2686
2686
  dataTestId
2687
2687
  }) => {
2688
2688
  const handleOnClick = onClick && !disabled ? () => onClick() : undefined;
2689
- return jsxs(Root$2, Object.assign({
2689
+ return jsxs(Root$3, Object.assign({
2690
2690
  "data-testid": dataTestId,
2691
2691
  "$disabled": disabled,
2692
2692
  className: className,
@@ -2703,7 +2703,7 @@ const LegendItem = ({
2703
2703
  })]
2704
2704
  }));
2705
2705
  };
2706
- const Root$2 = tw.div`
2706
+ const Root$3 = tw.div`
2707
2707
  inline-flex
2708
2708
  items-center
2709
2709
  transition-all
@@ -3248,6 +3248,239 @@ const StyledTip = twx(Tip)`
3248
3248
  ${p => p.link ? tws`tu-page-header__tip` : null}
3249
3249
  `;
3250
3250
 
3251
+ /**
3252
+ * Display placeholder lines before the data gets loaded to reduce load-time frustration.
3253
+ */
3254
+
3255
+ const SkeletonLines = memo(({
3256
+ margin = "10px 0",
3257
+ lines = 1,
3258
+ height,
3259
+ width = "100%",
3260
+ className,
3261
+ dataTestId
3262
+ }) => {
3263
+ const skeletonLines = [];
3264
+
3265
+ const getWidth = index => {
3266
+ if (width instanceof Array) {
3267
+ return width[index] || "100%";
3268
+ }
3269
+
3270
+ return width;
3271
+ };
3272
+
3273
+ const getHeight = index => {
3274
+ if (height instanceof Array) {
3275
+ return height[index] || "auto";
3276
+ }
3277
+
3278
+ return height;
3279
+ };
3280
+
3281
+ for (let i = 0; i < lines; i++) {
3282
+ skeletonLines.push(jsx(SkeletonLine, Object.assign({
3283
+ "data-testid": dataTestId,
3284
+ "data-type": "loading-skeleton-line",
3285
+ className: className,
3286
+ style: {
3287
+ height: getHeight(i),
3288
+ width: getWidth(i),
3289
+ margin: margin
3290
+ }
3291
+ }, {
3292
+ children: "\u00A0"
3293
+ }), i));
3294
+ } // eslint-disable-next-line react/jsx-no-useless-fragment
3295
+
3296
+
3297
+ return jsx(Fragment, {
3298
+ children: skeletonLines
3299
+ });
3300
+ });
3301
+ const SkeletonLine = tw.div`
3302
+ tu-skeleton-line
3303
+ `;
3304
+
3305
+ /**
3306
+ * Pagination Description. It could be used when you need navigation for your paging feature.
3307
+ *
3308
+ * @param {IPaginationProps} props - The props for the Pagination component
3309
+ * @returns {JSX.Element} Pagination component
3310
+ */
3311
+
3312
+ const Pagination = ({
3313
+ gotoPage,
3314
+ previousPage,
3315
+ nextPage,
3316
+ pageCount,
3317
+ pageIndex,
3318
+ canPreviousPage,
3319
+ canNextPage,
3320
+ loading,
3321
+ eventName,
3322
+ parentName,
3323
+ className,
3324
+ dataTestId,
3325
+ logPageChange,
3326
+ getTranslatedCount,
3327
+ getTranslatedPage
3328
+ }) => {
3329
+ const [page, setPage] = React.useState(pageIndex);
3330
+ const [pageInputValue, setPageInputValue] = React.useState(String(pageIndex !== undefined ? pageIndex + 1 : 1));
3331
+
3332
+ if (!loading && pageCount === undefined) {
3333
+ throw Error("Pagination should be provided with a pageCount");
3334
+ }
3335
+
3336
+ React.useEffect(() => {
3337
+ if (pageIndex !== undefined && (isNaN(pageIndex) || pageIndex < 0)) {
3338
+ gotoPage(0);
3339
+ } else if (pageIndex !== undefined && pageCount !== null && pageCount !== undefined && pageIndex > pageCount - 1) {
3340
+ gotoPage(pageCount - 1);
3341
+ } else {
3342
+ setPage(pageIndex);
3343
+ pageIndex !== undefined && setPageInputValue(String(pageIndex + 1));
3344
+ }
3345
+ }, [pageIndex, gotoPage, setPage, setPageInputValue, pageCount]);
3346
+ const parsePageString = React.useCallback(pageString => {
3347
+ let val = parseInt(pageString);
3348
+ val = isNaN(val) ? 0 : val;
3349
+ val = val < 1 ? 0 : val - 1;
3350
+
3351
+ if (pageCount !== undefined && pageCount !== null) {
3352
+ val = val > pageCount ? pageCount - 1 : val;
3353
+ }
3354
+
3355
+ return val;
3356
+ }, [pageCount]);
3357
+ const handlePageChange = React.useCallback(action => {
3358
+ const from = page;
3359
+ let to = from;
3360
+ let description = "";
3361
+
3362
+ switch (action) {
3363
+ case "prev":
3364
+ to = from !== undefined ? from - 1 : 0;
3365
+ previousPage();
3366
+ description = "Previous Page";
3367
+ break;
3368
+
3369
+ case "next":
3370
+ to = from !== undefined ? from + 1 : 0;
3371
+ nextPage();
3372
+ description = "Next Page";
3373
+ break;
3374
+
3375
+ case "manual":
3376
+ to = parsePageString(pageInputValue);
3377
+ gotoPage(to);
3378
+ description = "Manual Page Change";
3379
+ break;
3380
+ }
3381
+
3382
+ if (to) {
3383
+ setPage(to);
3384
+ setPageInputValue(String(to + 1));
3385
+ }
3386
+
3387
+ eventName && logPageChange && logPageChange(eventName, {
3388
+ parentName,
3389
+ type: "Pagination",
3390
+ from: from !== undefined ? from : "",
3391
+ to: to !== undefined ? to : "",
3392
+ action: description
3393
+ });
3394
+ }, [page, logPageChange, eventName, parentName, previousPage, nextPage, parsePageString, pageInputValue, gotoPage]);
3395
+
3396
+ const handleOnBlur = () => {
3397
+ handlePageChange("manual");
3398
+ };
3399
+
3400
+ const handleOnFocus = e => e.target.select();
3401
+
3402
+ const handleOnChange = React.useCallback(e => {
3403
+ setPageInputValue(e.target.value);
3404
+ }, []);
3405
+ const handleOnKeyPress = React.useCallback(e => {
3406
+ if (e.key !== "Enter") {
3407
+ return;
3408
+ }
3409
+
3410
+ handlePageChange("manual");
3411
+ }, [handlePageChange]);
3412
+
3413
+ if (loading) {
3414
+ return jsx(Root$2, Object.assign({
3415
+ className: className
3416
+ }, {
3417
+ children: jsx(SkeletonLines, {
3418
+ height: 16,
3419
+ width: 150
3420
+ })
3421
+ }));
3422
+ }
3423
+
3424
+ return jsxs(Root$2, Object.assign({
3425
+ "data-testid": dataTestId,
3426
+ className: className
3427
+ }, {
3428
+ children: [jsx(IconButton, {
3429
+ onClick: () => handlePageChange("prev"),
3430
+ disabled: page !== undefined && page <= 0,
3431
+ "data-testid": "prev-page",
3432
+ icon: jsx(Icon$1, {
3433
+ name: "ChevronLeftIcon",
3434
+ size: "small"
3435
+ }),
3436
+ size: "small",
3437
+ color: "secondary",
3438
+ variant: "transparent"
3439
+ }), jsx(Text$1, {
3440
+ children: getTranslatedPage()
3441
+ }), jsx(PageInput, {
3442
+ type: "number",
3443
+ min: 1,
3444
+ // max={amountOfPages}
3445
+ value: pageInputValue,
3446
+ onFocus: handleOnFocus,
3447
+ onBlur: handleOnBlur,
3448
+ onChange: handleOnChange,
3449
+ onKeyPress: handleOnKeyPress,
3450
+ "data-testid": "page-input"
3451
+ }), jsx(TextStyled, Object.assign({
3452
+ dataTestId: "page-count"
3453
+ }, {
3454
+ children: pageCount !== null && pageCount !== undefined && getTranslatedCount(pageCount)
3455
+ })), jsx(IconButton, {
3456
+ onClick: () => handlePageChange("next"),
3457
+ disabled: page !== undefined && pageCount !== undefined && pageCount !== null && page >= pageCount - 1,
3458
+ "data-testid": "next-page",
3459
+ icon: jsx(Icon$1, {
3460
+ name: "ChevronRightIcon",
3461
+ size: "small"
3462
+ }),
3463
+ size: "small",
3464
+ color: "secondary",
3465
+ variant: "transparent"
3466
+ })]
3467
+ }));
3468
+ };
3469
+ const Root$2 = tw.div`
3470
+ tu-pagination
3471
+ `;
3472
+ const TextStyled = twx(Text$1)`
3473
+ tu-pagination__text
3474
+ `;
3475
+ const PageInput = tw.input`
3476
+ tu-pagination__page-input
3477
+ [&::-webkit-inner-spin-button]:[-webkit-appearance:none]
3478
+ [&::-webkit-outer-spin-button]:[-webkit-appearance:none]
3479
+ [&::-webkit-inner-spin-button]:m-0
3480
+ [&::-webkit-outer-spin-button]:m-0
3481
+ [-moz-appearance:textfield]
3482
+ `;
3483
+
3251
3484
  function useConfirmExit(confirmExit, when = true) {
3252
3485
  const {
3253
3486
  navigator
@@ -4417,60 +4650,6 @@ const SelectContainer = tw.div`
4417
4650
  `;
4418
4651
  Select.displayName = "Select";
4419
4652
 
4420
- /**
4421
- * Display placeholder lines before the data gets loaded to reduce load-time frustration.
4422
- */
4423
-
4424
- const SkeletonLines = memo(({
4425
- margin = "10px 0",
4426
- lines = 1,
4427
- height,
4428
- width = "100%",
4429
- className,
4430
- dataTestId
4431
- }) => {
4432
- const skeletonLines = [];
4433
-
4434
- const getWidth = index => {
4435
- if (width instanceof Array) {
4436
- return width[index] || "100%";
4437
- }
4438
-
4439
- return width;
4440
- };
4441
-
4442
- const getHeight = index => {
4443
- if (height instanceof Array) {
4444
- return height[index] || "auto";
4445
- }
4446
-
4447
- return height;
4448
- };
4449
-
4450
- for (let i = 0; i < lines; i++) {
4451
- skeletonLines.push(jsx(SkeletonLine, Object.assign({
4452
- "data-testid": dataTestId,
4453
- "data-type": "loading-skeleton-line",
4454
- className: className,
4455
- style: {
4456
- height: getHeight(i),
4457
- width: getWidth(i),
4458
- margin: margin
4459
- }
4460
- }, {
4461
- children: "\u00A0"
4462
- }), i));
4463
- } // eslint-disable-next-line react/jsx-no-useless-fragment
4464
-
4465
-
4466
- return jsx(Fragment, {
4467
- children: skeletonLines
4468
- });
4469
- });
4470
- const SkeletonLine = tw.div`
4471
- tu-skeleton-line
4472
- `;
4473
-
4474
4653
  /**
4475
4654
  * The TextArea is a base component, and should not be used very often.
4476
4655
  * For most cases the TextAreaField is the correct component.
@@ -5371,4 +5550,4 @@ const Layout = tw.div`
5371
5550
  tu-layout-TwoColumnLayout
5372
5551
  `;
5373
5552
 
5374
- export { ActionButton, Alert, AnimatedPopover, Badge, BaseInput, Button, Card, CardBody, CardFooter, CardHeader, Chart, Checkbox, Collapse, CopyableText, CreatableSelect, DateField, DateInput, DayPicker, DayPickerPopover, DayRangePicker, DensityContainer, FilterListMapLayout, FormGroup, FullWidthRepeatingLayout, GridArea, Heading$1 as Heading, Icon$1 as Icon, IconButton, Indicator$1 as Indicator, IntrinsicallyResponsiveGrid, Label$2 as Label, LegendItem, MenuItem, MenuList, MinTopFullContentLayout, Modal, ModalBackdrop, MultiSelectMenuItem, NumberField, NumberInput, PageHeader, PopoverLifecycle, PopoverList, PopoverListItem, PopoverTitle, Prompt, ROLE_CARD, RadioGroup, RadioItem, SectionHeader, Select, SelectPrefix, SingleSelectMenuItem, SkeletonLines, Spacer, Spinner, StarButton, Tag, Text$1 as Text, TextArea, TextAreaField, TextField, TextInput, Timeline, TimelineElement, Tip, TitleNavContentLayout, Toggle, Tooltip, TwoColumnLayout, ValueBar, docs, getOrderedOptions, getValueBarColorByValue, isMultiValue, useContainerProps, useCustomComponents, useDebounce, useLocalStorage, useModal, usePopover, usePrompt, useTimeout };
5553
+ export { ActionButton, Alert, AnimatedPopover, Badge, BaseInput, Button, Card, CardBody, CardFooter, CardHeader, Chart, Checkbox, Collapse, CopyableText, CreatableSelect, DateField, DateInput, DayPicker, DayPickerPopover, DayRangePicker, DensityContainer, FilterListMapLayout, FormGroup, FullWidthRepeatingLayout, GridArea, Heading$1 as Heading, Icon$1 as Icon, IconButton, Indicator$1 as Indicator, IntrinsicallyResponsiveGrid, Label$2 as Label, LegendItem, MenuItem, MenuList, MinTopFullContentLayout, Modal, ModalBackdrop, MultiSelectMenuItem, NumberField, NumberInput, PageHeader, Pagination, PopoverLifecycle, PopoverList, PopoverListItem, PopoverTitle, Prompt, ROLE_CARD, RadioGroup, RadioItem, SectionHeader, Select, SelectPrefix, SingleSelectMenuItem, SkeletonLines, Spacer, Spinner, StarButton, Tag, Text$1 as Text, TextArea, TextAreaField, TextField, TextInput, Timeline, TimelineElement, Tip, TitleNavContentLayout, Toggle, Tooltip, TwoColumnLayout, ValueBar, docs, getOrderedOptions, getValueBarColorByValue, isMultiValue, useContainerProps, useCustomComponents, useDebounce, useLocalStorage, useModal, usePopover, usePrompt, useTimeout };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trackunit/react-components",
3
- "version": "0.0.173",
3
+ "version": "0.0.175",
4
4
  "repository": "https://github.com/Trackunit/manager",
5
5
  "license": "SEE LICENSE IN LICENSE.txt",
6
6
  "dependencies": {