@eml-payments/ui-kit 1.5.2 → 1.5.4
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/dist/index.css +2 -2
- package/dist/src/components/Button/ButtonVariants.d.ts +1 -1
- package/dist/src/components/Button/ButtonVariants.js +1 -0
- package/dist/src/components/Combobox/Combobox.d.ts +28 -0
- package/dist/src/components/Combobox/Combobox.js +58 -0
- package/dist/src/components/Combobox/Combobox.stories.d.ts +12 -0
- package/dist/src/components/Combobox/Combobox.stories.js +86 -0
- package/dist/src/components/Combobox/index.d.ts +1 -0
- package/dist/src/components/Combobox/index.js +1 -0
- package/dist/src/components/Input/Input.js +12 -8
- package/dist/src/components/Input/Input.stories.d.ts +3 -2
- package/dist/src/components/Input/Input.stories.js +9 -2
- package/dist/src/components/InputGroup/InputGroup.d.ts +16 -0
- package/dist/src/components/InputGroup/InputGroup.js +58 -0
- package/dist/src/components/InputGroup/InputGroup.stories.d.ts +19 -0
- package/dist/src/components/InputGroup/InputGroup.stories.js +62 -0
- package/dist/src/components/InputGroup/index.d.ts +1 -0
- package/dist/src/components/InputGroup/index.js +1 -0
- package/dist/src/components/Select/Select.js +1 -1
- package/dist/src/components/Stepper/Stepper.js +1 -1
- package/dist/src/components/Table/StandardTable/StandardTable.stories.js +5 -1
- package/dist/src/components/Table/hooks/useInfiniteScrolling.js +1 -0
- package/dist/src/components/Table/hooks/useTableController.js +4 -14
- package/dist/src/components/Textarea/Textarea.js +12 -7
- package/dist/src/components/Textarea/Textarea.stories.d.ts +2 -1
- package/dist/src/components/Textarea/Textarea.stories.js +6 -2
- package/dist/src/components/index.d.ts +2 -0
- package/dist/src/components/index.js +2 -0
- package/package.json +11 -5
- package/dist/index.d.cts +0 -488
- package/dist/index.d.ts +0 -488
- package/dist/src/components/Table/BaseTable/index.d.ts +0 -1
- package/dist/src/components/Table/BaseTable/index.js +0 -1
|
@@ -21,7 +21,7 @@ const ControlledLengthIndicator = (args) => {
|
|
|
21
21
|
export const Text = {
|
|
22
22
|
args: { type: 'text', placeholder: 'Enter text...' },
|
|
23
23
|
};
|
|
24
|
-
export const
|
|
24
|
+
export const NumberInput = {
|
|
25
25
|
args: { type: 'number', placeholder: 'Enter number...' },
|
|
26
26
|
};
|
|
27
27
|
export const WithValue = {
|
|
@@ -36,9 +36,16 @@ export const PasswordInput = {
|
|
|
36
36
|
export const WithHelperText = {
|
|
37
37
|
args: { helperText: 'This is a helper text', placeholder: 'Enter text...' },
|
|
38
38
|
};
|
|
39
|
-
export const
|
|
39
|
+
export const WithControlledLengthIndicator = {
|
|
40
40
|
render: (args) => _jsx(ControlledLengthIndicator, { ...args }),
|
|
41
41
|
};
|
|
42
|
+
export const WithMaxLengthIndicator = {
|
|
43
|
+
args: {
|
|
44
|
+
maxLength: 50,
|
|
45
|
+
helperText: 'This is a helper text',
|
|
46
|
+
placeholder: 'Type here to see counter...',
|
|
47
|
+
},
|
|
48
|
+
};
|
|
42
49
|
export const Disabled = {
|
|
43
50
|
args: { disabled: true, placeholder: 'Disabled input' },
|
|
44
51
|
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { type VariantProps } from 'class-variance-authority';
|
|
3
|
+
import { Button } from '../../components/Button';
|
|
4
|
+
declare function InputGroup({ className, ...props }: React.ComponentProps<'div'>): import("react/jsx-runtime").JSX.Element;
|
|
5
|
+
declare const inputGroupAddonVariants: (props?: ({
|
|
6
|
+
align?: "block-end" | "block-start" | "inline-end" | "inline-start" | null | undefined;
|
|
7
|
+
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
8
|
+
declare function InputGroupAddon({ className, align, ...props }: React.ComponentProps<'div'> & VariantProps<typeof inputGroupAddonVariants>): import("react/jsx-runtime").JSX.Element;
|
|
9
|
+
declare const inputGroupButtonVariants: (props?: ({
|
|
10
|
+
size?: "sm" | "xs" | "icon-xs" | "icon-sm" | null | undefined;
|
|
11
|
+
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
12
|
+
declare function InputGroupButton({ className, type, variant, size, ...props }: Omit<React.ComponentProps<typeof Button>, 'size'> & VariantProps<typeof inputGroupButtonVariants>): import("react/jsx-runtime").JSX.Element;
|
|
13
|
+
declare function InputGroupText({ className, ...props }: React.ComponentProps<'span'>): import("react/jsx-runtime").JSX.Element;
|
|
14
|
+
declare function InputGroupInput({ className, ...props }: React.ComponentProps<'input'>): import("react/jsx-runtime").JSX.Element;
|
|
15
|
+
declare function InputGroupTextarea({ className, ...props }: React.ComponentProps<'textarea'>): import("react/jsx-runtime").JSX.Element;
|
|
16
|
+
export { InputGroup, InputGroupAddon, InputGroupButton, InputGroupText, InputGroupInput, InputGroupTextarea };
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { cva } from 'class-variance-authority';
|
|
4
|
+
import { cn } from '../../lib/utils';
|
|
5
|
+
import { Button } from '../../components/Button';
|
|
6
|
+
import { Input } from '../../components/Input';
|
|
7
|
+
import { Textarea } from '../../components/Textarea';
|
|
8
|
+
function InputGroup({ className, ...props }) {
|
|
9
|
+
return (_jsx("div", { "data-slot": "input-group", role: "group", className: cn('border-input dark:bg-input/30 has-[[data-slot=input-group-control]:focus-visible]:border-ring has-[[data-slot=input-group-control]:focus-visible]:ring-ring/50 has-[[data-slot][aria-invalid=true]]:ring-destructive/20 has-[[data-slot][aria-invalid=true]]:border-destructive dark:has-[[data-slot][aria-invalid=true]]:ring-destructive/40 has-disabled:bg-input/50 dark:has-disabled:bg-input/80 h-8 rounded-lg border transition-colors in-data-[slot=combobox-content]:focus-within:border-inherit in-data-[slot=combobox-content]:focus-within:ring-0 has-disabled:opacity-50 has-[[data-slot=input-group-control]:focus-visible]:ring-3 has-[[data-slot][aria-invalid=true]]:ring-3 has-[>[data-align=block-end]]:h-auto has-[>[data-align=block-end]]:flex-col has-[>[data-align=block-start]]:h-auto has-[>[data-align=block-start]]:flex-col has-[>[data-align=block-end]]:[&>input]:pt-3 has-[>[data-align=block-start]]:[&>input]:pb-3 has-[>[data-align=inline-end]]:[&>input]:pr-1.5 has-[>[data-align=inline-start]]:[&>input]:pl-1.5 group/input-group relative flex w-full min-w-0 items-center outline-none has-[>textarea]:h-auto', className), ...props }));
|
|
10
|
+
}
|
|
11
|
+
const inputGroupAddonVariants = cva("text-muted-foreground h-auto gap-2 py-1.5 text-sm font-medium group-data-[disabled=true]/input-group:opacity-50 [&>kbd]:rounded-[calc(var(--radius)-5px)] [&>svg:not([class*='size-'])]:size-4 flex cursor-text items-center justify-center select-none", {
|
|
12
|
+
variants: {
|
|
13
|
+
align: {
|
|
14
|
+
'inline-start': 'pl-2 has-[>button]:ml-[-0.3rem] has-[>kbd]:ml-[-0.15rem] order-first',
|
|
15
|
+
'inline-end': 'pr-2 has-[>button]:mr-[-0.3rem] has-[>kbd]:mr-[-0.15rem] order-last',
|
|
16
|
+
'block-start': 'px-2.5 pt-2 group-has-[>input]/input-group:pt-2 [.border-b]:pb-2 order-first w-full justify-start',
|
|
17
|
+
'block-end': 'px-2.5 pb-2 group-has-[>input]/input-group:pb-2 [.border-t]:pt-2 order-last w-full justify-start',
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
defaultVariants: {
|
|
21
|
+
align: 'inline-start',
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
function InputGroupAddon({ className, align = 'inline-start', ...props }) {
|
|
25
|
+
return (_jsx("div", { role: "group", "data-slot": "input-group-addon", "data-align": align, className: cn(inputGroupAddonVariants({ align }), className), onClick: (e) => {
|
|
26
|
+
var _a, _b;
|
|
27
|
+
if (e.target.closest('button')) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
(_b = (_a = e.currentTarget.parentElement) === null || _a === void 0 ? void 0 : _a.querySelector('input')) === null || _b === void 0 ? void 0 : _b.focus();
|
|
31
|
+
}, ...props }));
|
|
32
|
+
}
|
|
33
|
+
const inputGroupButtonVariants = cva('gap-2 text-sm flex items-center shadow-none', {
|
|
34
|
+
variants: {
|
|
35
|
+
size: {
|
|
36
|
+
xs: "h-6 gap-1 rounded-[calc(var(--radius)-3px)] px-1.5 [&>svg:not([class*='size-'])]:size-3.5",
|
|
37
|
+
sm: '',
|
|
38
|
+
'icon-xs': 'size-6 rounded-[calc(var(--radius)-3px)] p-0 has-[>svg]:p-0',
|
|
39
|
+
'icon-sm': 'size-8 p-0 has-[>svg]:p-0',
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
defaultVariants: {
|
|
43
|
+
size: 'xs',
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
function InputGroupButton({ className, type = 'button', variant = 'ghost', size = 'xs', ...props }) {
|
|
47
|
+
return (_jsx(Button, { type: type, "data-size": size, variant: variant, className: cn(inputGroupButtonVariants({ size }), className), ...props }));
|
|
48
|
+
}
|
|
49
|
+
function InputGroupText({ className, ...props }) {
|
|
50
|
+
return (_jsx("span", { className: cn("text-muted-foreground gap-2 text-sm [&_svg:not([class*='size-'])]:size-4 flex items-center [&_svg]:pointer-events-none", className), ...props }));
|
|
51
|
+
}
|
|
52
|
+
function InputGroupInput({ className, ...props }) {
|
|
53
|
+
return (_jsx(Input, { "data-slot": "input-group-control", className: cn('rounded-none border-0 bg-transparent shadow-none ring-0 focus-visible:ring-0 disabled:bg-transparent aria-invalid:ring-0 dark:bg-transparent dark:disabled:bg-transparent flex-1', className), ...props }));
|
|
54
|
+
}
|
|
55
|
+
function InputGroupTextarea({ className, ...props }) {
|
|
56
|
+
return (_jsx(Textarea, { "data-slot": "input-group-control", className: cn('rounded-none border-0 bg-transparent py-2 shadow-none ring-0 focus-visible:ring-0 disabled:bg-transparent aria-invalid:ring-0 dark:bg-transparent dark:disabled:bg-transparent flex-1 resize-none', className), ...props }));
|
|
57
|
+
}
|
|
58
|
+
export { InputGroup, InputGroupAddon, InputGroupButton, InputGroupText, InputGroupInput, InputGroupTextarea };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import { InputGroup } from './InputGroup';
|
|
3
|
+
declare const meta: Meta<typeof InputGroup>;
|
|
4
|
+
export default meta;
|
|
5
|
+
type Story = StoryObj<typeof InputGroup>;
|
|
6
|
+
export declare const Basic: Story;
|
|
7
|
+
export declare const WithInlineStartAddon: Story;
|
|
8
|
+
export declare const WithInlineEndAddon: Story;
|
|
9
|
+
export declare const WithBothInlineAddons: Story;
|
|
10
|
+
export declare const WithBlockStartAddon: Story;
|
|
11
|
+
export declare const WithBlockEndAddon: Story;
|
|
12
|
+
export declare const WithInlineStartButton: Story;
|
|
13
|
+
export declare const WithInlineEndButton: Story;
|
|
14
|
+
export declare const WithPassword: Story;
|
|
15
|
+
export declare const WithMultipleButtons: Story;
|
|
16
|
+
export declare const WithTextAndIcon: Story;
|
|
17
|
+
export declare const WithTextarea: Story;
|
|
18
|
+
export declare const Disabled: Story;
|
|
19
|
+
export declare const Invalid: Story;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { SearchIcon, CalendarIcon, UserIcon, MailIcon, XIcon, EyeIcon, EyeOffIcon } from 'lucide-react';
|
|
3
|
+
import { useState } from 'react';
|
|
4
|
+
import { InputGroup, InputGroupAddon, InputGroupButton, InputGroupText, InputGroupInput, InputGroupTextarea, } from './InputGroup';
|
|
5
|
+
const meta = {
|
|
6
|
+
title: 'UIKit/InputGroup',
|
|
7
|
+
component: InputGroup,
|
|
8
|
+
tags: ['autodocs'],
|
|
9
|
+
parameters: {
|
|
10
|
+
docs: {
|
|
11
|
+
description: {
|
|
12
|
+
component: 'A versatile input group component that allows combining inputs with addons, buttons, and text.',
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
};
|
|
17
|
+
export default meta;
|
|
18
|
+
export const Basic = {
|
|
19
|
+
render: () => (_jsx(InputGroup, { children: _jsx(InputGroupInput, { placeholder: "Enter text..." }) })),
|
|
20
|
+
};
|
|
21
|
+
export const WithInlineStartAddon = {
|
|
22
|
+
render: () => (_jsxs(InputGroup, { children: [_jsx(InputGroupAddon, { align: "inline-start", children: _jsx(SearchIcon, {}) }), _jsx(InputGroupInput, { placeholder: "Search..." })] })),
|
|
23
|
+
};
|
|
24
|
+
export const WithInlineEndAddon = {
|
|
25
|
+
render: () => (_jsxs(InputGroup, { children: [_jsx(InputGroupInput, { placeholder: "Enter email..." }), _jsx(InputGroupAddon, { align: "inline-end", children: _jsx(MailIcon, {}) })] })),
|
|
26
|
+
};
|
|
27
|
+
export const WithBothInlineAddons = {
|
|
28
|
+
render: () => (_jsxs(InputGroup, { children: [_jsx(InputGroupAddon, { align: "inline-start", children: _jsx(UserIcon, {}) }), _jsx(InputGroupInput, { placeholder: "Username" }), _jsx(InputGroupAddon, { align: "inline-end", children: _jsx("span", { className: "text-xs", children: "@domain.com" }) })] })),
|
|
29
|
+
};
|
|
30
|
+
export const WithBlockStartAddon = {
|
|
31
|
+
render: () => (_jsxs(InputGroup, { children: [_jsx(InputGroupAddon, { align: "block-start", children: _jsx(InputGroupText, { children: "Email Address" }) }), _jsx(InputGroupInput, { placeholder: "john@example.com" })] })),
|
|
32
|
+
};
|
|
33
|
+
export const WithBlockEndAddon = {
|
|
34
|
+
render: () => (_jsxs(InputGroup, { children: [_jsx(InputGroupInput, { placeholder: "Enter your message..." }), _jsx(InputGroupAddon, { align: "block-end", children: _jsx(InputGroupText, { children: "Additional information" }) })] })),
|
|
35
|
+
};
|
|
36
|
+
export const WithInlineStartButton = {
|
|
37
|
+
render: () => (_jsxs(InputGroup, { children: [_jsx(InputGroupAddon, { align: "inline-start", children: _jsx(InputGroupButton, { size: "icon-xs", children: _jsx(SearchIcon, {}) }) }), _jsx(InputGroupInput, { placeholder: "Search..." })] })),
|
|
38
|
+
};
|
|
39
|
+
export const WithInlineEndButton = {
|
|
40
|
+
render: () => (_jsxs(InputGroup, { children: [_jsx(InputGroupInput, { placeholder: "Enter text..." }), _jsx(InputGroupAddon, { align: "inline-end", children: _jsx(InputGroupButton, { size: "icon-xs", variant: "ghost", children: _jsx(XIcon, {}) }) })] })),
|
|
41
|
+
};
|
|
42
|
+
export const WithPassword = {
|
|
43
|
+
render: () => {
|
|
44
|
+
const [showPassword, setShowPassword] = useState(false);
|
|
45
|
+
return (_jsxs(InputGroup, { children: [_jsx(InputGroupInput, { type: showPassword ? 'text' : 'password', placeholder: "Enter password..." }), _jsx(InputGroupAddon, { align: "inline-end", children: _jsx(InputGroupButton, { size: "icon-xs", variant: "ghost", onClick: () => setShowPassword(!showPassword), children: showPassword ? _jsx(EyeOffIcon, {}) : _jsx(EyeIcon, {}) }) })] }));
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
export const WithMultipleButtons = {
|
|
49
|
+
render: () => (_jsxs(InputGroup, { children: [_jsx(InputGroupAddon, { align: "inline-start", children: _jsx(InputGroupButton, { size: "xs", children: "Copy" }) }), _jsx(InputGroupInput, { placeholder: "Enter value..." }), _jsxs(InputGroupAddon, { align: "inline-end", children: [_jsx(InputGroupButton, { size: "xs", variant: "primary", children: "Save" }), _jsx(InputGroupButton, { size: "icon-xs", variant: "ghost", children: _jsx(XIcon, {}) })] })] })),
|
|
50
|
+
};
|
|
51
|
+
export const WithTextAndIcon = {
|
|
52
|
+
render: () => (_jsxs(InputGroup, { children: [_jsxs(InputGroupAddon, { align: "inline-start", children: [_jsx(CalendarIcon, {}), _jsx(InputGroupText, { children: "Date" })] }), _jsx(InputGroupInput, { placeholder: "Select date..." })] })),
|
|
53
|
+
};
|
|
54
|
+
export const WithTextarea = {
|
|
55
|
+
render: () => (_jsxs(InputGroup, { children: [_jsx(InputGroupAddon, { align: "block-start", children: _jsx(InputGroupText, { children: "Description" }) }), _jsx(InputGroupTextarea, { placeholder: "Enter your description...", rows: 4 }), _jsx(InputGroupAddon, { align: "block-end", children: _jsx(InputGroupText, { children: "Max 500 characters" }) })] })),
|
|
56
|
+
};
|
|
57
|
+
export const Disabled = {
|
|
58
|
+
render: () => (_jsxs(InputGroup, { children: [_jsx(InputGroupAddon, { align: "inline-start", children: _jsx(UserIcon, {}) }), _jsx(InputGroupInput, { placeholder: "Disabled input...", disabled: true }), _jsx(InputGroupAddon, { align: "inline-end", children: _jsx(InputGroupButton, { size: "icon-xs", disabled: true, children: _jsx(XIcon, {}) }) })] })),
|
|
59
|
+
};
|
|
60
|
+
export const Invalid = {
|
|
61
|
+
render: () => (_jsxs(InputGroup, { children: [_jsx(InputGroupAddon, { align: "inline-start", children: _jsx(MailIcon, {}) }), _jsx(InputGroupInput, { placeholder: "Enter email...", "aria-invalid": "true", defaultValue: "Invalid email" })] })),
|
|
62
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './InputGroup';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './InputGroup';
|
|
@@ -116,7 +116,7 @@ const SelectContent = React.forwardRef(({ className, children, position = 'poppe
|
|
|
116
116
|
const filteredItemsCount = React.useMemo(() => {
|
|
117
117
|
return countSelectItems(filteredChildren);
|
|
118
118
|
}, [filteredChildren]);
|
|
119
|
-
const noResultsContent = (_jsxs("div", { className: "px-2 py-1.5 flex flex-col items-start gap-1", children: [_jsx("span", { className: "text-xs text-muted-foreground", children: noResultsText }), noResultsButtonText && onNoResultsButtonClick && (_jsx(Button, { variant: "
|
|
119
|
+
const noResultsContent = (_jsxs("div", { className: "px-2 py-1.5 flex flex-col items-start gap-1", children: [_jsx("span", { className: "text-xs text-muted-foreground", children: noResultsText }), noResultsButtonText && onNoResultsButtonClick && (_jsx(Button, { variant: "secondaryText", onMouseDown: (event) => event.preventDefault(), onClick: onNoResultsButtonClick, className: "h-auto p-0 text-sm", children: noResultsButtonText }))] }));
|
|
120
120
|
return (_jsx(SelectPrimitive.Portal, { children: _jsxs(SelectPrimitive.Content, { ref: ref, className: cn('relative z-50 max-h-(--radix-select-content-available-height) min-w-32 overflow-y-auto overflow-x-hidden rounded-(--uikit-radius) border bg-popover text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-(--radix-select-content-transform-origin)', position === 'popper' &&
|
|
121
121
|
'data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1', className), position: position, onCloseAutoFocus: () => {
|
|
122
122
|
if (shouldShowSearch) {
|
|
@@ -19,7 +19,7 @@ export function Stepper({ steps, currentStep, onStepChange, contentProps, classN
|
|
|
19
19
|
onStepChange === null || onStepChange === void 0 ? void 0 : onStepChange(step.id);
|
|
20
20
|
}, children: [_jsx("div", { className: cn('w-9 h-9 rounded-full flex items-center justify-center', isPastStep && 'bg-(--uikit-success)/10 text-(--uikit-success)', isActive &&
|
|
21
21
|
!isPastStep &&
|
|
22
|
-
'bg-(--uikit-
|
|
22
|
+
'bg-(--uikit-secondary)/10 text-[var(--uikit-secondary)]', !isPastStep && !isActive && 'bg-muted/50 text-muted-foreground'), children: isPastStep ? _jsx(Check, { size: 16, strokeWidth: 3 }) : ((_a = step.icon) !== null && _a !== void 0 ? _a : index + 1) }), _jsx("span", { className: cn('text-sm font-normal not-italic', isPastStep && 'text-(--uikit-success)', isActive && 'text-[var(--uikit-secondary)]', !isPastStep && !isActive && 'text-muted-foreground'), children: step.label })] }), index < steps.length - 1 && (_jsx("div", { className: cn(isVertical ? 'w-[3px] h-14 my-2' : 'h-[3px] flex-1 mx-3 mt-4', isPastStep ? 'bg-(--uikit-success)' : 'bg-muted') }))] }, step.id));
|
|
23
23
|
}) })), _jsx("div", { className: "flex-1", children: (() => {
|
|
24
24
|
if (React.isValidElement(currentContent)) {
|
|
25
25
|
return currentContent;
|
|
@@ -56,7 +56,11 @@ export const EmptyState = {
|
|
|
56
56
|
render: () => (_jsx(StandardTable, { id: "empty-table", data: [], columns: columns, customNoRows: { message: 'No users found' }, paginationMode: "client" })),
|
|
57
57
|
};
|
|
58
58
|
export const EmptyStateWithIcon = {
|
|
59
|
-
render: () => (_jsx(StandardTable, { id: "empty-table-with-icon", data: [], columns: columns, paginationMode: "none", customNoRows: {
|
|
59
|
+
render: () => (_jsx(StandardTable, { id: "empty-table-with-icon", data: [], columns: columns, paginationMode: "none", customNoRows: {
|
|
60
|
+
message: 'No transactions',
|
|
61
|
+
icon: _jsx(MdReceiptLong, { size: 56 }),
|
|
62
|
+
messageClassName: 'text-xl font-bold',
|
|
63
|
+
} })),
|
|
60
64
|
};
|
|
61
65
|
export const Loading = {
|
|
62
66
|
render: () => _jsx(StandardTable, { id: "loading-table", data: [], columns: columns, isLoading: true, paginationMode: "client" }),
|
|
@@ -24,6 +24,7 @@ export function useInfiniteScrolling(params) {
|
|
|
24
24
|
count: allRows.length + (isInfinite && hasNextPage ? 1 : 0),
|
|
25
25
|
getScrollElement: () => parentScrollRef.current,
|
|
26
26
|
estimateSize: () => { var _a; return (_a = virtualization === null || virtualization === void 0 ? void 0 : virtualization.rowEstimate) !== null && _a !== void 0 ? _a : 48; },
|
|
27
|
+
measureElement: (el) => { var _a; return (_a = el === null || el === void 0 ? void 0 : el.getBoundingClientRect().height) !== null && _a !== void 0 ? _a : 48; },
|
|
27
28
|
overscan: (_a = virtualization === null || virtualization === void 0 ? void 0 : virtualization.overscan) !== null && _a !== void 0 ? _a : 6,
|
|
28
29
|
});
|
|
29
30
|
const loadLockRef = useRef(false);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useEffect,
|
|
1
|
+
import { useEffect, useMemo, useRef, useState } from 'react';
|
|
2
2
|
import { useReactTable, getCoreRowModel, getSortedRowModel, getPaginationRowModel, getGroupedRowModel, getExpandedRowModel, } from '@tanstack/react-table';
|
|
3
3
|
import { applyFlexSizes, getCheckboxSelectionColumn } from '../table.helpers';
|
|
4
4
|
import { usePaginationController } from './usePaginationController';
|
|
@@ -12,17 +12,7 @@ export function useTableController({ id, height, data, columns, checkboxSelectio
|
|
|
12
12
|
const columnVisibility = useMemo(() => {
|
|
13
13
|
return Object.fromEntries(stableGrouping.map((columnId) => [columnId, false]));
|
|
14
14
|
}, [stableGrouping]);
|
|
15
|
-
const [
|
|
16
|
-
useLayoutEffect(() => {
|
|
17
|
-
if (!parentScrollRef.current)
|
|
18
|
-
return;
|
|
19
|
-
const ro = new ResizeObserver(([entry]) => {
|
|
20
|
-
setContainerWidth(entry.contentRect.width);
|
|
21
|
-
});
|
|
22
|
-
ro.observe(parentScrollRef.current);
|
|
23
|
-
return () => ro.disconnect();
|
|
24
|
-
}, []);
|
|
25
|
-
const [tableColumns, setTableColumns] = useState(() => applyFlexSizes(columns !== null && columns !== void 0 ? columns : [], containerWidth, !!(virtualization === null || virtualization === void 0 ? void 0 : virtualization.enabled)));
|
|
15
|
+
const [tableColumns, setTableColumns] = useState(() => applyFlexSizes(columns !== null && columns !== void 0 ? columns : []));
|
|
26
16
|
const [internalSorting, setInternalSorting] = useState(sorting !== null && sorting !== void 0 ? sorting : []);
|
|
27
17
|
const [internalRowSelection, setInternalRowSelection] = useState(() => {
|
|
28
18
|
if (selectedRowIds) {
|
|
@@ -108,7 +98,7 @@ export function useTableController({ id, height, data, columns, checkboxSelectio
|
|
|
108
98
|
return checkboxSelection ? getCheckboxSelectionColumn(table) : null;
|
|
109
99
|
}, [checkboxSelection, table]);
|
|
110
100
|
useEffect(() => {
|
|
111
|
-
const normalized = applyFlexSizes(columns !== null && columns !== void 0 ? columns : []
|
|
101
|
+
const normalized = applyFlexSizes(columns !== null && columns !== void 0 ? columns : []);
|
|
112
102
|
let finalColumns;
|
|
113
103
|
if (checkboxSelection && selectionColumn) {
|
|
114
104
|
if (checkboxPosition === 'start') {
|
|
@@ -125,7 +115,7 @@ export function useTableController({ id, height, data, columns, checkboxSelectio
|
|
|
125
115
|
finalColumns = normalized;
|
|
126
116
|
}
|
|
127
117
|
setTableColumns(finalColumns);
|
|
128
|
-
}, [columns, checkboxSelection, checkboxPosition
|
|
118
|
+
}, [columns, checkboxSelection, checkboxPosition]);
|
|
129
119
|
return {
|
|
130
120
|
table,
|
|
131
121
|
height,
|
|
@@ -2,20 +2,25 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import React from 'react';
|
|
3
3
|
import { cn } from '../../lib/utils';
|
|
4
4
|
import { useUIKitTheme } from '../../context/useUIKitTheme';
|
|
5
|
-
export const Textarea = React.forwardRef(({ label, error, helperText, className, maxLength, 'aria-describedby': ariaDescribedBy, 'aria-invalid': ariaInvalid, ...props }, ref) => {
|
|
6
|
-
var _a
|
|
5
|
+
export const Textarea = React.forwardRef(({ label, error, helperText, className, value, defaultValue, onChange, maxLength, 'aria-describedby': ariaDescribedBy, 'aria-invalid': ariaInvalid, ...props }, ref) => {
|
|
6
|
+
var _a;
|
|
7
7
|
const theme = useUIKitTheme();
|
|
8
8
|
const generatedId = React.useId();
|
|
9
9
|
const textareaId = (_a = props.id) !== null && _a !== void 0 ? _a : generatedId;
|
|
10
10
|
const isInvalid = Boolean(error) || (ariaInvalid !== undefined && ariaInvalid !== false && ariaInvalid !== 'false');
|
|
11
|
-
const isControlled =
|
|
12
|
-
const
|
|
13
|
-
const currentLength =
|
|
14
|
-
const showLengthIndicator =
|
|
11
|
+
const isControlled = value !== undefined;
|
|
12
|
+
const [uncontrolledLength, setUncontrolledLength] = React.useState(() => String(defaultValue !== null && defaultValue !== void 0 ? defaultValue : '').length);
|
|
13
|
+
const currentLength = isControlled ? String(value !== null && value !== void 0 ? value : '').length : uncontrolledLength;
|
|
14
|
+
const showLengthIndicator = typeof maxLength === 'number' && !error;
|
|
15
15
|
const showHelperRow = !error && (helperText || showLengthIndicator);
|
|
16
16
|
const errorId = error ? `${textareaId}-error` : undefined;
|
|
17
17
|
const helperId = showHelperRow ? `${textareaId}-helper` : undefined;
|
|
18
18
|
const describedBy = [ariaDescribedBy, errorId, helperId].filter(Boolean).join(' ') || undefined;
|
|
19
|
-
return (_jsxs("div", { className: cn(className), children: [label && (_jsx("label", { htmlFor: textareaId, className: "text-
|
|
19
|
+
return (_jsxs("div", { className: cn(className), children: [label && (_jsx("label", { htmlFor: textareaId, className: "text-xs font-normal text-muted-foreground", children: label })), _jsx("textarea", { id: textareaId, "aria-invalid": isInvalid, "aria-describedby": describedBy, value: value, defaultValue: defaultValue, onChange: (event) => {
|
|
20
|
+
if (!isControlled) {
|
|
21
|
+
setUncontrolledLength(event.target.value.length);
|
|
22
|
+
}
|
|
23
|
+
onChange === null || onChange === void 0 ? void 0 : onChange(event);
|
|
24
|
+
}, maxLength: maxLength, style: { fontFamily: theme.fontFamily }, className: cn('flex min-h-[80px] w-full text-(--uikit-textSecondary) rounded-(--uikit-radius) border border-(--uikit-inputEnabledBorder) bg-background hover:border-(--uikit-inputHoverBorder) px-3 py-2 text-base ring-offset-background placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50 md:text-sm transition focus-visible:outline-none focus-visible:border-(--uikit-primary) focus-visible:ring-2 focus-visible:ring-(--uikit-primary) aria-invalid:border-(--uikit-error) aria-invalid:focus-visible:ring-(--uikit-error)'), ref: ref, ...props }), error && (_jsx("p", { id: errorId, className: "text-sm font-medium text-error", children: error })), showHelperRow && (_jsxs("div", { id: helperId, className: "mt-1 flex items-center justify-between gap-2", children: [helperText ? (_jsx("p", { className: "text-xs font-normal text-muted-foreground", children: helperText })) : (_jsx("span", {})), showLengthIndicator && (_jsxs("span", { className: "text-xs font-normal text-muted-foreground", children: [currentLength, "/", maxLength] }))] }))] }));
|
|
20
25
|
});
|
|
21
26
|
Textarea.displayName = 'Textarea';
|
|
@@ -5,6 +5,7 @@ export default meta;
|
|
|
5
5
|
type Story = StoryObj<TextareaProps>;
|
|
6
6
|
export declare const Default: Story;
|
|
7
7
|
export declare const WithHelperText: Story;
|
|
8
|
-
export declare const
|
|
8
|
+
export declare const WithMaxLengthIndicator: Story;
|
|
9
|
+
export declare const WithMaxLengthIndicatorControlled: Story;
|
|
9
10
|
export declare const WithError: Story;
|
|
10
11
|
export declare const Disabled: Story;
|
|
@@ -21,12 +21,16 @@ export const WithHelperText = {
|
|
|
21
21
|
helperText: 'This is a helper text',
|
|
22
22
|
},
|
|
23
23
|
};
|
|
24
|
-
export const
|
|
25
|
-
render: (args) => _jsx(ControlledLengthIndicator, { ...args }),
|
|
24
|
+
export const WithMaxLengthIndicator = {
|
|
26
25
|
args: {
|
|
26
|
+
maxLength: 50,
|
|
27
27
|
helperText: 'This is a helper text',
|
|
28
|
+
placeholder: 'Type here to see counter...',
|
|
28
29
|
},
|
|
29
30
|
};
|
|
31
|
+
export const WithMaxLengthIndicatorControlled = {
|
|
32
|
+
render: (args) => _jsx(ControlledLengthIndicator, { ...args }),
|
|
33
|
+
};
|
|
30
34
|
export const WithError = {
|
|
31
35
|
args: {
|
|
32
36
|
error: 'Something went wrong',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eml-payments/ui-kit",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.4",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "ARLO UIKit",
|
|
6
6
|
"homepage": "https://github.com/EML-Payments/arlo.npm.uikit#readme",
|
|
@@ -43,12 +43,13 @@
|
|
|
43
43
|
"format:fix": "prettier --write \"**/*.{js,jsx,ts,tsx,json,htm,html,yml,yaml}\"",
|
|
44
44
|
"task:prettier": "prettier \"./src/**/*.{ts,tsx}\" --check --log-level error",
|
|
45
45
|
"task:prettier:fix": "prettier --write \"./src/**/*.{ts,tsx}\" --check --log-level error",
|
|
46
|
-
"task:eslint": "eslint \"
|
|
47
|
-
"task:eslint:fix": "eslint \"
|
|
46
|
+
"task:eslint": "eslint \"src/**/*.{ts,tsx}\" --cache",
|
|
47
|
+
"task:eslint:fix": "eslint \"src/**/*.{ts,tsx}\" --fix --cache",
|
|
48
48
|
"task:typecheck": "tsc",
|
|
49
49
|
"formatx": "npm run task:prettier:fix && npm run task:eslint:fix && npm run task:typecheck"
|
|
50
50
|
},
|
|
51
51
|
"dependencies": {
|
|
52
|
+
"@base-ui/react": "^1.3.0",
|
|
52
53
|
"@radix-ui/react-avatar": "^1.1.10",
|
|
53
54
|
"@radix-ui/react-checkbox": "^1.3.2",
|
|
54
55
|
"@radix-ui/react-dialog": "^1.1.14",
|
|
@@ -67,7 +68,7 @@
|
|
|
67
68
|
"class-variance-authority": "^0.7.1",
|
|
68
69
|
"clsx": "^2.1.1",
|
|
69
70
|
"dayjs": "^1.11.19",
|
|
70
|
-
"lucide-react": "^0.
|
|
71
|
+
"lucide-react": "^0.577.0",
|
|
71
72
|
"prettier": "^3.6.2",
|
|
72
73
|
"react": ">=18.0.0",
|
|
73
74
|
"react-day-picker": "^9.13.0",
|
|
@@ -87,6 +88,7 @@
|
|
|
87
88
|
"@storybook/react-vite": "^10.0.6",
|
|
88
89
|
"@tailwindcss/cli": "^4.1.12",
|
|
89
90
|
"@typescript-eslint/eslint-plugin": "^8.35.1",
|
|
91
|
+
"baseline-browser-mapping": "^2.10.0",
|
|
90
92
|
"eslint": "^9.31.0",
|
|
91
93
|
"eslint-config-prettier": "^10.1.5",
|
|
92
94
|
"eslint-plugin-import": "^2.32.0",
|
|
@@ -113,6 +115,10 @@
|
|
|
113
115
|
]
|
|
114
116
|
},
|
|
115
117
|
"lint-staged": {
|
|
116
|
-
"*.{js,ts,tsx}":
|
|
118
|
+
"*.{js,ts,tsx}": [
|
|
119
|
+
"prettier --write",
|
|
120
|
+
"eslint --fix"
|
|
121
|
+
],
|
|
122
|
+
"*.{json,md,css}": "prettier --write"
|
|
117
123
|
}
|
|
118
124
|
}
|