@boxcustodia/library 2.0.0-alpha.12 → 2.0.0-alpha.14
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.cjs.js +1 -138
- package/dist/index.d.ts +1087 -720
- package/dist/index.es.js +7011 -56097
- package/dist/theme.css +1 -1
- package/package.json +34 -26
- package/src/__doc__/Examples.tsx +1 -1
- package/src/__doc__/Intro.mdx +3 -3
- package/src/__doc__/Tabs.mdx +112 -0
- package/src/__doc__/V2.mdx +1246 -0
- package/src/components/accordion/accordion.stories.tsx +143 -0
- package/src/components/accordion/accordion.tsx +135 -0
- package/src/components/accordion/index.ts +1 -0
- package/src/components/alert/alert.stories.tsx +24 -4
- package/src/components/alert/alert.tsx +17 -9
- package/src/components/alert-dialog/alert-dialog.stories.tsx +24 -0
- package/src/components/alert-dialog/alert-dialog.test.tsx +1 -1
- package/src/components/alert-dialog/alert-dialog.tsx +58 -10
- package/src/components/auto-complete/auto-complete.stories.tsx +616 -200
- package/src/components/auto-complete/auto-complete.tsx +420 -68
- package/src/components/auto-complete/index.ts +0 -1
- package/src/components/avatar/avatar.stories.tsx +162 -21
- package/src/components/avatar/avatar.tsx +79 -20
- package/src/components/button/button.stories.tsx +219 -294
- package/src/components/button/button.test.tsx +10 -17
- package/src/components/button/button.tsx +78 -19
- package/src/components/button/components/base-button.tsx +30 -53
- package/src/components/button/index.ts +0 -1
- package/src/components/calendar/calendar.stories.tsx +1 -1
- package/src/components/calendar/calendar.tsx +4 -4
- package/src/components/card/card.stories.tsx +141 -69
- package/src/components/card/card.tsx +155 -54
- package/src/components/center/center.stories.tsx +22 -39
- package/src/components/checkbox/checkbox.stories.tsx +25 -5
- package/src/components/checkbox/checkbox.tsx +76 -15
- package/src/components/checkbox-group/checkbox-group.stories.tsx +116 -28
- package/src/components/checkbox-group/checkbox-group.tsx +84 -3
- package/src/components/combobox/combobox.stories.tsx +33 -23
- package/src/components/combobox/combobox.tsx +99 -77
- package/src/components/date-picker/date-input.stories.tsx +14 -6
- package/src/components/date-picker/date-input.tsx +2 -2
- package/src/components/date-picker/date-picker.model.ts +13 -4
- package/src/components/date-picker/date-picker.stories.tsx +38 -12
- package/src/components/date-picker/date-picker.tsx +28 -14
- package/src/components/dialog/dialog.stories.tsx +18 -0
- package/src/components/dialog/dialog.test.tsx +1 -1
- package/src/components/dialog/dialog.tsx +51 -20
- package/src/components/divider/divider.stories.tsx +126 -51
- package/src/components/divider/divider.tsx +16 -16
- package/src/components/dropzone/dropzone.stories.tsx +71 -90
- package/src/components/dropzone/dropzone.tsx +383 -105
- package/src/components/dropzone/index.ts +0 -1
- package/src/components/empty/empty.stories.tsx +165 -0
- package/src/components/empty/empty.tsx +156 -0
- package/src/components/empty/index.ts +1 -0
- package/src/components/field/field.stories.tsx +227 -4
- package/src/components/field/field.tsx +77 -42
- package/src/components/form/form.stories.tsx +320 -197
- package/src/components/form/form.tsx +3 -23
- package/src/components/index.ts +2 -6
- package/src/components/input/input.stories.tsx +5 -5
- package/src/components/input/input.tsx +4 -4
- package/src/components/kbd/kbd.stories.tsx +1 -0
- package/src/components/label/label.stories.tsx +16 -0
- package/src/components/label/label.tsx +13 -2
- package/src/components/loader/loader.stories.tsx +7 -5
- package/src/components/loader/loader.tsx +8 -3
- package/src/components/menu/menu-primitives.tsx +207 -196
- package/src/components/menu/menu.stories.tsx +276 -146
- package/src/components/menu/menu.tsx +146 -54
- package/src/components/number-input/number-input.stories.tsx +27 -4
- package/src/components/number-input/number-input.test.tsx +2 -2
- package/src/components/number-input/number-input.tsx +31 -33
- package/src/components/otp/index.ts +1 -0
- package/src/components/otp/otp.stories.tsx +209 -0
- package/src/components/otp/otp.tsx +100 -0
- package/src/components/pagination/index.ts +1 -0
- package/src/components/pagination/pagination.model.ts +2 -0
- package/src/components/pagination/pagination.stories.tsx +154 -59
- package/src/components/pagination/pagination.test.tsx +122 -57
- package/src/components/pagination/pagination.tsx +575 -77
- package/src/components/password/password.stories.tsx +18 -3
- package/src/components/password/password.tsx +29 -9
- package/src/components/popover/popover.stories.tsx +26 -5
- package/src/components/popover/popover.tsx +15 -23
- package/src/components/progress/progress.stories.tsx +1 -0
- package/src/components/radio-group/index.ts +1 -0
- package/src/components/radio-group/radio-group.stories.tsx +251 -0
- package/src/components/radio-group/radio-group.tsx +212 -0
- package/src/components/scroll-area/scroll-area.stories.tsx +1 -0
- package/src/components/select/select.stories.tsx +118 -19
- package/src/components/select/select.tsx +67 -62
- package/src/components/skeleton/skeleton.stories.tsx +1 -0
- package/src/components/stack/stack.stories.tsx +179 -89
- package/src/components/stack/stack.tsx +2 -2
- package/src/components/stepper/index.ts +1 -1
- package/src/components/stepper/stepper.stories.tsx +767 -83
- package/src/components/stepper/stepper.test.tsx +18 -18
- package/src/components/stepper/stepper.tsx +554 -0
- package/src/components/switch/switch.stories.tsx +15 -1
- package/src/components/switch/switch.tsx +17 -4
- package/src/components/table/index.ts +0 -2
- package/src/components/table/table.stories.tsx +131 -18
- package/src/components/table/table.test.tsx +1 -1
- package/src/components/table/table.tsx +183 -77
- package/src/components/tabs/tabs.stories.tsx +373 -155
- package/src/components/tabs/tabs.test.tsx +12 -12
- package/src/components/tabs/tabs.tsx +72 -149
- package/src/components/tag/index.ts +0 -1
- package/src/components/tag/tag.stories.tsx +155 -120
- package/src/components/tag/tag.tsx +47 -95
- package/src/components/textarea/textarea.stories.tsx +8 -22
- package/src/components/textarea/textarea.tsx +17 -79
- package/src/components/timeline/timeline.stories.tsx +323 -42
- package/src/components/timeline/timeline.tsx +359 -132
- package/src/components/toast/toast.stories.tsx +1 -0
- package/src/components/tooltip/tooltip.tsx +11 -9
- package/src/components/tree/index.ts +0 -1
- package/src/components/tree/tree.stories.tsx +365 -408
- package/src/components/tree/tree.test.tsx +163 -0
- package/src/components/tree/tree.tsx +212 -36
- package/src/hooks/useAsync/__doc__/useAsync.stories.tsx +5 -5
- package/src/hooks/useClipboard/__doc__/useClipboard.stories.tsx +1 -3
- package/src/hooks/useDebounceCallback/__doc__/useDebouncedCallback.stories.tsx +6 -6
- package/src/hooks/useDocumentTitle/__doc__/useDocumentTitle.stories.tsx +1 -1
- package/src/hooks/useEventListener/__test__/useEventListener.test.tsx +1 -1
- package/src/hooks/useLocalStorage/__doc__/useLocalStorage.stories.tsx +1 -1
- package/src/hooks/usePagination/usePagination.tsx +36 -24
- package/src/styles/theme.css +1 -1
- package/src/utils/form.tsx +67 -37
- package/src/utils/index.ts +1 -1
- package/src/__doc__/Migration.mdx +0 -475
- package/src/components/auto-complete/auto-complete-primitives.tsx +0 -155
- package/src/components/background-image/background-image.stories.tsx +0 -21
- package/src/components/background-image/background-image.test.tsx +0 -29
- package/src/components/background-image/background-image.tsx +0 -23
- package/src/components/background-image/index.ts +0 -1
- package/src/components/button/button.variants.ts +0 -44
- package/src/components/button/components/loader-overlay.tsx +0 -21
- package/src/components/button/components/loading-icon.tsx +0 -47
- package/src/components/dropzone/upload-primitives.tsx +0 -310
- package/src/components/dropzone/use-dropzone.ts +0 -122
- package/src/components/empty-state/empty-state.stories.tsx +0 -56
- package/src/components/empty-state/empty-state.tsx +0 -39
- package/src/components/empty-state/index.ts +0 -1
- package/src/components/heading/heading.stories.tsx +0 -74
- package/src/components/heading/heading.tsx +0 -28
- package/src/components/heading/heading.variants.ts +0 -27
- package/src/components/heading/index.ts +0 -1
- package/src/components/kbd/kbd.variants.ts +0 -26
- package/src/components/menu/util/render-menu-item.tsx +0 -54
- package/src/components/multi-select/hooks/use-multi-select.ts +0 -66
- package/src/components/multi-select/index.ts +0 -1
- package/src/components/multi-select/multi-select.stories.tsx +0 -294
- package/src/components/multi-select/multi-select.tsx +0 -300
- package/src/components/multi-select/multi-select.variants.ts +0 -22
- package/src/components/pagination/components/pagination-option.tsx +0 -27
- package/src/components/show/index.ts +0 -1
- package/src/components/show/show.stories.tsx +0 -197
- package/src/components/show/show.test.tsx +0 -41
- package/src/components/show/show.tsx +0 -16
- package/src/components/stepper/Stepper.tsx +0 -190
- package/src/components/stepper/context/stepper-context.tsx +0 -11
- package/src/components/table/table-primitives.tsx +0 -122
- package/src/components/table/table.model.ts +0 -20
- package/src/components/table-pagination/index.ts +0 -2
- package/src/components/table-pagination/table-pagination.model.ts +0 -2
- package/src/components/table-pagination/table-pagination.stories.tsx +0 -23
- package/src/components/table-pagination/table-pagination.test.tsx +0 -32
- package/src/components/table-pagination/table-pagination.tsx +0 -108
- package/src/components/tabs/context/tabs-context.tsx +0 -14
- package/src/components/tag/tag.variants.ts +0 -31
- package/src/components/timeline/timeline-status.ts +0 -5
- package/src/components/tree/hooks/use-controllable-tree-state.ts +0 -80
- package/src/components/tree/tree-primitives.tsx +0 -126
|
@@ -1,197 +0,0 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from "@storybook/react-vite";
|
|
2
|
-
import { Flame, Phone, Rat, SprayCan } from "lucide-react";
|
|
3
|
-
import { Button, Show } from "../../components";
|
|
4
|
-
import { useHover, useToggle } from "../../hooks";
|
|
5
|
-
import { cn } from "../../lib";
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Componente que permite animar la entrada y salida de un componente.
|
|
9
|
-
*
|
|
10
|
-
* Expone dos estados `open` y `closed` para animar la entrada y salida respectivamente.
|
|
11
|
-
*
|
|
12
|
-
* ### Uso:
|
|
13
|
-
*
|
|
14
|
-
* ```tsx
|
|
15
|
-
* import { Show } from './Show';
|
|
16
|
-
*
|
|
17
|
-
* const Example = () => {
|
|
18
|
-
* const [open, toggle] = useToggle(false);
|
|
19
|
-
* return (
|
|
20
|
-
* <div>
|
|
21
|
-
* <button onClick={() => toggle()}>Toggle</button>
|
|
22
|
-
* <Show when={open}>
|
|
23
|
-
* <div className="animated-box">
|
|
24
|
-
* 🐙
|
|
25
|
-
* </div>
|
|
26
|
-
* </Show>
|
|
27
|
-
* </div>
|
|
28
|
-
* );
|
|
29
|
-
* };
|
|
30
|
-
* ```
|
|
31
|
-
*
|
|
32
|
-
* ### CSS para animaciones:
|
|
33
|
-
*
|
|
34
|
-
* Define las animaciones en un archivo CSS. En este ejemplo, se crean animaciones para la entrada (`fadeInZoomIn`) y la salida (`fadeOutZoomOut`).
|
|
35
|
-
*
|
|
36
|
-
* ```css
|
|
37
|
-
* @keyframes fadeInZoomIn {
|
|
38
|
-
* 0% {
|
|
39
|
-
* opacity: 0;
|
|
40
|
-
* transform: scale(0.95);
|
|
41
|
-
* }
|
|
42
|
-
* 100% {
|
|
43
|
-
* opacity: 1;
|
|
44
|
-
* transform: scale(1);
|
|
45
|
-
* }
|
|
46
|
-
* }
|
|
47
|
-
*
|
|
48
|
-
* @keyframes fadeOutZoomOut {
|
|
49
|
-
* 0% {
|
|
50
|
-
* opacity: 1;
|
|
51
|
-
* transform: scale(1);
|
|
52
|
-
* }
|
|
53
|
-
* 100% {
|
|
54
|
-
* opacity: 0;
|
|
55
|
-
* transform: scale(0.95);
|
|
56
|
-
* }
|
|
57
|
-
* }
|
|
58
|
-
*
|
|
59
|
-
* .animated-box[data-state="open"] {
|
|
60
|
-
* animation: fadeInZoomIn 0.5s forwards;
|
|
61
|
-
* }
|
|
62
|
-
*
|
|
63
|
-
* .animated-box[data-state="closed"] {
|
|
64
|
-
* animation: fadeOutZoomOut 0.5s forwards;
|
|
65
|
-
* }
|
|
66
|
-
* ```
|
|
67
|
-
*
|
|
68
|
-
* ### Alternativa con TailwindCSS:
|
|
69
|
-
*
|
|
70
|
-
* Alternativamente, se puede usar el plugin [tailwindcss-animate](https://www.npmjs.com/package/tailwindcss-animate)
|
|
71
|
-
* que ya trae animaciones predefinidas. Acá un ejemplo:
|
|
72
|
-
*
|
|
73
|
-
* ```tsx
|
|
74
|
-
* import { Show } from './Show';
|
|
75
|
-
*
|
|
76
|
-
* const Example = () => {
|
|
77
|
-
* const [open, toggle] = useToggle(false);
|
|
78
|
-
* return (
|
|
79
|
-
* <div>
|
|
80
|
-
* <button onClick={() => toggle()}>Toggle</button>
|
|
81
|
-
* <Show when={open}>
|
|
82
|
-
* <div
|
|
83
|
-
* className={cn(
|
|
84
|
-
* // Animaciones de entrada
|
|
85
|
-
* "data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",
|
|
86
|
-
* // Animaciones de salida
|
|
87
|
-
* "data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95"
|
|
88
|
-
* )}
|
|
89
|
-
* >
|
|
90
|
-
* 🐙
|
|
91
|
-
* </div>
|
|
92
|
-
* </Show>
|
|
93
|
-
* </div>
|
|
94
|
-
* );
|
|
95
|
-
* };
|
|
96
|
-
* ```
|
|
97
|
-
* ## Crea alias para acortar `data-[state-X]`
|
|
98
|
-
* En caso de que se quiera acortar el prefijo `data-[state-X]` se puede crear una variante en el archivo `tailwind.config.js`:
|
|
99
|
-
*
|
|
100
|
-
* ```tsx
|
|
101
|
-
* // tailwind.config.js
|
|
102
|
-
*
|
|
103
|
-
* // Importar plugin
|
|
104
|
-
* const plugin = require("tailwindcss/plugin");
|
|
105
|
-
*
|
|
106
|
-
* module.exports = {
|
|
107
|
-
* // ...
|
|
108
|
-
* plugins: [
|
|
109
|
-
* plugin(function ({ addVariant }) {
|
|
110
|
-
* addVariant("open", '&[data-state="open"]');
|
|
111
|
-
* addVariant("closed", '&[data-state="closed"]');
|
|
112
|
-
* }),
|
|
113
|
-
* ],
|
|
114
|
-
* };
|
|
115
|
-
*
|
|
116
|
-
* // Uso
|
|
117
|
-
* import { Show } from './Show';
|
|
118
|
-
*
|
|
119
|
-
* const Example = () => {
|
|
120
|
-
* const [open, toggle] = useToggle(false);
|
|
121
|
-
* return (
|
|
122
|
-
* <div>
|
|
123
|
-
* <button onClick={() => toggle()}>Toggle</button>
|
|
124
|
-
* <Show when={open}>
|
|
125
|
-
* <div
|
|
126
|
-
* className={cn(
|
|
127
|
-
* // Animaciones de entrada
|
|
128
|
-
* "open:animate-in open:fade-in-0 open:zoom-in-95",
|
|
129
|
-
* // Animaciones de salida
|
|
130
|
-
* "closed:animate-out closed:fade-out-0 closed:zoom-out-95"
|
|
131
|
-
* )}
|
|
132
|
-
* >
|
|
133
|
-
* 🐙
|
|
134
|
-
* </div>
|
|
135
|
-
* </Show>
|
|
136
|
-
* </div>
|
|
137
|
-
* );
|
|
138
|
-
* };
|
|
139
|
-
* ```
|
|
140
|
-
*/
|
|
141
|
-
const meta: Meta<typeof Show> = {
|
|
142
|
-
title: "others/Show",
|
|
143
|
-
component: Show,
|
|
144
|
-
};
|
|
145
|
-
|
|
146
|
-
export default meta;
|
|
147
|
-
type Story = StoryObj<typeof Show>;
|
|
148
|
-
|
|
149
|
-
export const Default: Story = {
|
|
150
|
-
render: () => {
|
|
151
|
-
const [open, toggle] = useToggle(false);
|
|
152
|
-
return (
|
|
153
|
-
<div>
|
|
154
|
-
<Button onClick={() => toggle()}>Toggle</Button>
|
|
155
|
-
<Show when={open}>
|
|
156
|
-
<div
|
|
157
|
-
className={cn(
|
|
158
|
-
"border rounded-md p-2 mt-2 w-[200px]",
|
|
159
|
-
"open:animate-in open:zoom-in-95",
|
|
160
|
-
"closed:animate-out closed:fade-out-0 closed:zoom-out-95",
|
|
161
|
-
)}
|
|
162
|
-
>
|
|
163
|
-
🐙
|
|
164
|
-
</div>
|
|
165
|
-
</Show>
|
|
166
|
-
</div>
|
|
167
|
-
);
|
|
168
|
-
},
|
|
169
|
-
};
|
|
170
|
-
|
|
171
|
-
export const Hover: Story = {
|
|
172
|
-
render: () => {
|
|
173
|
-
const { ref, isHovering } = useHover<HTMLDivElement>();
|
|
174
|
-
return (
|
|
175
|
-
<div
|
|
176
|
-
className="bg-gray-100 h-[300px] w-[300px] border border-dashed flex items-end overflow-hidden"
|
|
177
|
-
ref={ref}
|
|
178
|
-
>
|
|
179
|
-
<Show when={isHovering}>
|
|
180
|
-
<div
|
|
181
|
-
className={cn(
|
|
182
|
-
"rounded-md text-xl p-2 w-full flex justify-center gap-x-4",
|
|
183
|
-
"duration-300",
|
|
184
|
-
"open:animate-in open:slide-in-from-bottom",
|
|
185
|
-
"closed:animate-out closed:slide-out-to-bottom",
|
|
186
|
-
)}
|
|
187
|
-
>
|
|
188
|
-
<Phone />
|
|
189
|
-
<Rat />
|
|
190
|
-
<SprayCan />
|
|
191
|
-
<Flame />
|
|
192
|
-
</div>
|
|
193
|
-
</Show>
|
|
194
|
-
</div>
|
|
195
|
-
);
|
|
196
|
-
},
|
|
197
|
-
};
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import { render, screen } from "@testing-library/react";
|
|
2
|
-
import "@testing-library/jest-dom";
|
|
3
|
-
import { ComponentProps } from "react";
|
|
4
|
-
import { describe, expect, test } from "vitest";
|
|
5
|
-
import { Show } from "../../components";
|
|
6
|
-
|
|
7
|
-
type PresenceProps = ComponentProps<typeof Show>;
|
|
8
|
-
|
|
9
|
-
describe("Show Component", () => {
|
|
10
|
-
const renderPresence = (props: PresenceProps) => {
|
|
11
|
-
return render(<Show {...props} />);
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
test('renders the component with "open" state when "when" prop is true', () => {
|
|
15
|
-
renderPresence({ when: true, children: <div>hello</div> });
|
|
16
|
-
|
|
17
|
-
const slotElement = screen.getByText("hello");
|
|
18
|
-
expect(slotElement).toBeInTheDocument();
|
|
19
|
-
expect(slotElement).toHaveAttribute("data-state", "open");
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
test('unmount the component when "when" prop is false', () => {
|
|
23
|
-
renderPresence({ when: false, children: <div>hello</div> });
|
|
24
|
-
|
|
25
|
-
const slotElement = screen.queryByText("hello");
|
|
26
|
-
expect(slotElement).not.toBeInTheDocument();
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
test("passes additional props to the Slot component", () => {
|
|
30
|
-
renderPresence({
|
|
31
|
-
when: true,
|
|
32
|
-
className: "test-class",
|
|
33
|
-
children: <div>hello</div>,
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
const slotElement = screen.getByText("hello");
|
|
37
|
-
expect(slotElement).toBeInTheDocument();
|
|
38
|
-
|
|
39
|
-
expect(slotElement).toHaveClass("test-class");
|
|
40
|
-
});
|
|
41
|
-
});
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { Presence as AnimatePresence } from "@radix-ui/react-presence";
|
|
2
|
-
import { Slot } from "@radix-ui/react-slot";
|
|
3
|
-
import { ComponentProps, ComponentPropsWithoutRef } from "react";
|
|
4
|
-
|
|
5
|
-
interface Props extends ComponentPropsWithoutRef<typeof Slot> {
|
|
6
|
-
/** Si el componente está presente o no */
|
|
7
|
-
when: ComponentProps<typeof AnimatePresence>["present"];
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export const Show = ({ when, ...props }: Props) => {
|
|
11
|
-
return (
|
|
12
|
-
<AnimatePresence present={when}>
|
|
13
|
-
<Slot {...props} data-state={when ? "open" : "closed"} data-slot="show" />
|
|
14
|
-
</AnimatePresence>
|
|
15
|
-
);
|
|
16
|
-
};
|
|
@@ -1,190 +0,0 @@
|
|
|
1
|
-
import { useControllableState } from "@radix-ui/react-use-controllable-state";
|
|
2
|
-
import { HTMLProps, ReactNode } from "react";
|
|
3
|
-
import { ClassNameValue } from "tailwind-merge";
|
|
4
|
-
import { ClassName } from "@/models";
|
|
5
|
-
import { cn } from "../../lib";
|
|
6
|
-
import {
|
|
7
|
-
StepperContextProvider,
|
|
8
|
-
useStepperContext,
|
|
9
|
-
} from "./context/stepper-context";
|
|
10
|
-
|
|
11
|
-
interface StepperItemProps {
|
|
12
|
-
indicator?: ReactNode;
|
|
13
|
-
title: ReactNode;
|
|
14
|
-
content?: ReactNode;
|
|
15
|
-
disabled?: boolean;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
interface StepperProps extends Omit<HTMLProps<HTMLDivElement>, "onChange"> {
|
|
19
|
-
items?: StepperItemProps[];
|
|
20
|
-
current?: number;
|
|
21
|
-
onChange?: (index: number) => void;
|
|
22
|
-
className?: ClassName;
|
|
23
|
-
classNameList?: ClassName;
|
|
24
|
-
classNameItem?: ClassName;
|
|
25
|
-
classNameButton?: ClassName;
|
|
26
|
-
classNameIndicator?: ClassName;
|
|
27
|
-
classNameContent?: ClassName;
|
|
28
|
-
}
|
|
29
|
-
export function Stepper({
|
|
30
|
-
items = [],
|
|
31
|
-
current,
|
|
32
|
-
onChange,
|
|
33
|
-
className,
|
|
34
|
-
classNameList,
|
|
35
|
-
classNameItem,
|
|
36
|
-
classNameButton,
|
|
37
|
-
classNameIndicator,
|
|
38
|
-
classNameContent,
|
|
39
|
-
}: StepperProps) {
|
|
40
|
-
return (
|
|
41
|
-
<StepperContainer
|
|
42
|
-
className={className}
|
|
43
|
-
current={current}
|
|
44
|
-
onChange={onChange}
|
|
45
|
-
>
|
|
46
|
-
<StepperList className={classNameList}>
|
|
47
|
-
{items?.map((item, i) => (
|
|
48
|
-
<StepperTrigger
|
|
49
|
-
key={i}
|
|
50
|
-
value={i}
|
|
51
|
-
title={item?.title}
|
|
52
|
-
indicator={item?.indicator}
|
|
53
|
-
classNameItem={classNameItem}
|
|
54
|
-
classNameButton={classNameButton}
|
|
55
|
-
classNameIndicator={classNameIndicator}
|
|
56
|
-
/>
|
|
57
|
-
))}
|
|
58
|
-
</StepperList>
|
|
59
|
-
|
|
60
|
-
{items?.map((item, i) => (
|
|
61
|
-
<StepperContent className={classNameContent} key={i} value={i}>
|
|
62
|
-
{item?.content}
|
|
63
|
-
</StepperContent>
|
|
64
|
-
))}
|
|
65
|
-
</StepperContainer>
|
|
66
|
-
);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
interface StepperContainerProps
|
|
70
|
-
extends Omit<HTMLProps<HTMLDivElement>, "onChange"> {
|
|
71
|
-
current?: number;
|
|
72
|
-
onChange?: (index: number) => void;
|
|
73
|
-
className?: ClassName;
|
|
74
|
-
}
|
|
75
|
-
export function StepperContainer({
|
|
76
|
-
current: prop,
|
|
77
|
-
onChange,
|
|
78
|
-
className,
|
|
79
|
-
...props
|
|
80
|
-
}: StepperContainerProps) {
|
|
81
|
-
const [activeStep = 0, setActiveStep] = useControllableState<number>({
|
|
82
|
-
prop,
|
|
83
|
-
onChange,
|
|
84
|
-
defaultProp: 0,
|
|
85
|
-
});
|
|
86
|
-
return (
|
|
87
|
-
<StepperContextProvider value={{ activeStep, setActiveStep }}>
|
|
88
|
-
<div
|
|
89
|
-
data-slot="stepper"
|
|
90
|
-
className={cn(
|
|
91
|
-
"flex flex-col items-center w-full transition-all ease-in delay-150",
|
|
92
|
-
className,
|
|
93
|
-
)}
|
|
94
|
-
{...props}
|
|
95
|
-
/>
|
|
96
|
-
</StepperContextProvider>
|
|
97
|
-
);
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
interface StepperListProps extends HTMLProps<HTMLUListElement> {}
|
|
101
|
-
export function StepperList({
|
|
102
|
-
children,
|
|
103
|
-
className,
|
|
104
|
-
...props
|
|
105
|
-
}: StepperListProps) {
|
|
106
|
-
return (
|
|
107
|
-
<ul
|
|
108
|
-
data-slot="stepper-list"
|
|
109
|
-
className={cn(
|
|
110
|
-
"flex flex-col sm:flex-row sm:gap-0 gap-4 items-center w-full text-xs font-medium text-gray-900 sm:text-base mb-8",
|
|
111
|
-
className,
|
|
112
|
-
)}
|
|
113
|
-
{...props}
|
|
114
|
-
>
|
|
115
|
-
{children}
|
|
116
|
-
</ul>
|
|
117
|
-
);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
interface StepperTriggerProps {
|
|
121
|
-
indicator?: ReactNode;
|
|
122
|
-
title: ReactNode;
|
|
123
|
-
value: number;
|
|
124
|
-
disabled?: boolean;
|
|
125
|
-
classNameItem?: ClassNameValue;
|
|
126
|
-
classNameButton?: ClassNameValue;
|
|
127
|
-
classNameIndicator?: ClassNameValue;
|
|
128
|
-
}
|
|
129
|
-
export function StepperTrigger({
|
|
130
|
-
disabled,
|
|
131
|
-
value,
|
|
132
|
-
title,
|
|
133
|
-
indicator,
|
|
134
|
-
classNameItem,
|
|
135
|
-
classNameButton,
|
|
136
|
-
classNameIndicator,
|
|
137
|
-
}: StepperTriggerProps) {
|
|
138
|
-
const { activeStep, setActiveStep } = useStepperContext();
|
|
139
|
-
return (
|
|
140
|
-
<li
|
|
141
|
-
data-slot="stepper-trigger"
|
|
142
|
-
className={cn(
|
|
143
|
-
"flex relative text-primary transition-all ease-in delay-150",
|
|
144
|
-
"last:w-full last:sm:w-auto last:after:hidden",
|
|
145
|
-
`w-full after:content-[''] sm:after:w-full after:h-full after:w-0.5 sm:after:h-0.5 ${activeStep > value ? "after:bg-primary" : "after:bg-gray-300"} after:inline-block after:absolute after:top-5 sm:after:top-5 after:left-4 sm:after:left-10`,
|
|
146
|
-
classNameItem,
|
|
147
|
-
)}
|
|
148
|
-
>
|
|
149
|
-
<button
|
|
150
|
-
onClick={() => !disabled && setActiveStep(value)}
|
|
151
|
-
className={cn(
|
|
152
|
-
"z-10 flex items-center justify-center sm:flex-col gap-3 flex-row whitespace-nowrap cursor-pointer group transition-color ease-in delay-150",
|
|
153
|
-
activeStep >= value ? "text-primary" : "text-gray-500",
|
|
154
|
-
disabled && "cursor-not-allowed",
|
|
155
|
-
classNameButton,
|
|
156
|
-
)}
|
|
157
|
-
>
|
|
158
|
-
<span
|
|
159
|
-
data-slot="stepper-trigger-indicator"
|
|
160
|
-
className={cn(
|
|
161
|
-
"flex items-center transition-all overflow-hidden ease-in justify-center group-hover:scale-105 sm:w-10 sm:h-10 mx-auto text-sm border-2 rounded-full w-8 h-8",
|
|
162
|
-
activeStep > value &&
|
|
163
|
-
"bg-primary border-primary text-primary-foreground",
|
|
164
|
-
activeStep === value && "bg-gray-100 text-primary border-primary",
|
|
165
|
-
activeStep < value && "bg-white text-gray-500 border-input",
|
|
166
|
-
disabled && "text-gray-300",
|
|
167
|
-
classNameIndicator,
|
|
168
|
-
)}
|
|
169
|
-
>
|
|
170
|
-
{activeStep > value ? "✓" : indicator || value + 1}
|
|
171
|
-
</span>
|
|
172
|
-
{title}
|
|
173
|
-
</button>
|
|
174
|
-
</li>
|
|
175
|
-
);
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
interface StepperContentProps extends HTMLProps<HTMLDivElement> {
|
|
179
|
-
value: number;
|
|
180
|
-
}
|
|
181
|
-
export function StepperContent({
|
|
182
|
-
value,
|
|
183
|
-
className = "w-full",
|
|
184
|
-
...props
|
|
185
|
-
}: StepperContentProps) {
|
|
186
|
-
const { activeStep } = useStepperContext();
|
|
187
|
-
const isActiveStep = activeStep === value;
|
|
188
|
-
if (!isActiveStep) return null;
|
|
189
|
-
return <div data-slot="stepper-content" className={className} {...props} />;
|
|
190
|
-
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { createSafeContext } from "../../../utils";
|
|
2
|
-
|
|
3
|
-
interface StepperContextProps {
|
|
4
|
-
activeStep: number;
|
|
5
|
-
setActiveStep: (index: number) => void;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
export const [useStepperContext, StepperContextProvider] =
|
|
9
|
-
createSafeContext<StepperContextProps>();
|
|
10
|
-
|
|
11
|
-
export type { StepperContextProps };
|
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
import * as React from "react";
|
|
2
|
-
import { cn } from "../../lib";
|
|
3
|
-
|
|
4
|
-
type ContainerProps = React.ComponentProps<"div">;
|
|
5
|
-
type TableProps = React.ComponentProps<"table">;
|
|
6
|
-
|
|
7
|
-
type TableRootProps = TableProps & {
|
|
8
|
-
containerClassName?: ContainerProps["className"];
|
|
9
|
-
containerProps?: ContainerProps;
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
const TableRoot = ({
|
|
13
|
-
className,
|
|
14
|
-
containerClassName,
|
|
15
|
-
containerProps,
|
|
16
|
-
...props
|
|
17
|
-
}: TableRootProps) => (
|
|
18
|
-
<div
|
|
19
|
-
data-slot="table-container"
|
|
20
|
-
className={cn(
|
|
21
|
-
"relative w-full overflow-auto rounded-md border",
|
|
22
|
-
containerClassName,
|
|
23
|
-
)}
|
|
24
|
-
{...containerProps}
|
|
25
|
-
>
|
|
26
|
-
<table
|
|
27
|
-
data-slot="table"
|
|
28
|
-
className={cn("w-full caption-bottom text-sm", className)}
|
|
29
|
-
{...props}
|
|
30
|
-
/>
|
|
31
|
-
</div>
|
|
32
|
-
);
|
|
33
|
-
|
|
34
|
-
type TableHeaderProps = React.ComponentProps<"thead">;
|
|
35
|
-
|
|
36
|
-
const TableHeader = ({ className, ...props }: TableHeaderProps) => (
|
|
37
|
-
<thead
|
|
38
|
-
data-slot="table-header"
|
|
39
|
-
className={cn("[&_tr]:border-b", className)}
|
|
40
|
-
{...props}
|
|
41
|
-
/>
|
|
42
|
-
);
|
|
43
|
-
|
|
44
|
-
type TableBodyProps = React.ComponentProps<"tbody">;
|
|
45
|
-
|
|
46
|
-
const TableBody = ({ className, ...props }: TableBodyProps) => (
|
|
47
|
-
<tbody
|
|
48
|
-
data-slot="table-body"
|
|
49
|
-
className={cn("[&_tr:last-child]:border-0", className)}
|
|
50
|
-
{...props}
|
|
51
|
-
/>
|
|
52
|
-
);
|
|
53
|
-
|
|
54
|
-
type TableFooterProps = React.ComponentProps<"tfoot">;
|
|
55
|
-
|
|
56
|
-
const TableFooter = ({ className, ...props }: TableFooterProps) => (
|
|
57
|
-
<tfoot
|
|
58
|
-
data-slot="table-footer"
|
|
59
|
-
className={cn(
|
|
60
|
-
"border-t bg-muted/50 font-medium [&>tr]:last:border-b-0",
|
|
61
|
-
className,
|
|
62
|
-
)}
|
|
63
|
-
{...props}
|
|
64
|
-
/>
|
|
65
|
-
);
|
|
66
|
-
|
|
67
|
-
type TableRowProps = React.ComponentProps<"tr">;
|
|
68
|
-
|
|
69
|
-
const TableRow = ({ className, ...props }: TableRowProps) => (
|
|
70
|
-
<tr
|
|
71
|
-
data-slot="table-row"
|
|
72
|
-
className={cn(
|
|
73
|
-
"border-b transition-colors hover:bg-muted data-[selected=true]:bg-muted",
|
|
74
|
-
className,
|
|
75
|
-
)}
|
|
76
|
-
{...props}
|
|
77
|
-
/>
|
|
78
|
-
);
|
|
79
|
-
|
|
80
|
-
type TableHeadProps = React.ComponentProps<"th">;
|
|
81
|
-
|
|
82
|
-
const TableHead = ({ className, ...props }: TableHeadProps) => (
|
|
83
|
-
<th
|
|
84
|
-
data-slot="table-head"
|
|
85
|
-
className={cn(
|
|
86
|
-
"h-12 px-4 text-left align-middle font-medium text-muted-foreground sticky top-0 bg-background [&:has([role=checkbox])]:pr-0",
|
|
87
|
-
className,
|
|
88
|
-
)}
|
|
89
|
-
{...props}
|
|
90
|
-
/>
|
|
91
|
-
);
|
|
92
|
-
|
|
93
|
-
type TableCellProps = React.ComponentProps<"td">;
|
|
94
|
-
|
|
95
|
-
const TableCell = ({ className, ...props }: TableCellProps) => (
|
|
96
|
-
<td
|
|
97
|
-
data-slot="table-cell"
|
|
98
|
-
className={cn("p-4 align-middle [&:has([role=checkbox])]:pr-0", className)}
|
|
99
|
-
{...props}
|
|
100
|
-
/>
|
|
101
|
-
);
|
|
102
|
-
|
|
103
|
-
type TableCaptionProps = React.ComponentProps<"caption">;
|
|
104
|
-
|
|
105
|
-
const TableCaption = ({ className, ...props }: TableCaptionProps) => (
|
|
106
|
-
<caption
|
|
107
|
-
data-slot="table-caption"
|
|
108
|
-
className={cn("mt-4 text-sm text-muted-foreground", className)}
|
|
109
|
-
{...props}
|
|
110
|
-
/>
|
|
111
|
-
);
|
|
112
|
-
|
|
113
|
-
export {
|
|
114
|
-
TableBody,
|
|
115
|
-
TableCaption,
|
|
116
|
-
TableCell,
|
|
117
|
-
TableFooter,
|
|
118
|
-
TableHead,
|
|
119
|
-
TableHeader,
|
|
120
|
-
TableRoot,
|
|
121
|
-
TableRow,
|
|
122
|
-
};
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { ReactNode } from "react";
|
|
2
|
-
|
|
3
|
-
export type ColumnDef<T> = {
|
|
4
|
-
/**
|
|
5
|
-
* Header de la columna
|
|
6
|
-
*/
|
|
7
|
-
header: string | (() => ReactNode);
|
|
8
|
-
/**
|
|
9
|
-
* Clave que identifica la columna
|
|
10
|
-
*/
|
|
11
|
-
key: keyof T;
|
|
12
|
-
/**
|
|
13
|
-
* Elemento que se renderiza en la celda
|
|
14
|
-
*/
|
|
15
|
-
cell?: (row: T, index: number) => ReactNode;
|
|
16
|
-
/**
|
|
17
|
-
* Ancho de la columna
|
|
18
|
-
*/
|
|
19
|
-
width?: string | number;
|
|
20
|
-
};
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from "@storybook/react-vite";
|
|
2
|
-
import { TablePagination } from "../../components";
|
|
3
|
-
|
|
4
|
-
const meta: Meta<typeof TablePagination> = {
|
|
5
|
-
title: "Data display/TablePagination",
|
|
6
|
-
component: TablePagination,
|
|
7
|
-
args: {
|
|
8
|
-
totalItems: 100,
|
|
9
|
-
},
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
export default meta;
|
|
13
|
-
type Story = StoryObj<typeof TablePagination>;
|
|
14
|
-
|
|
15
|
-
export const Default: Story = {};
|
|
16
|
-
|
|
17
|
-
export const NoSizes: Story = {
|
|
18
|
-
args: { sizes: false },
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
export const OtherSizes: Story = {
|
|
22
|
-
args: { sizes: [1, 100, 1000] },
|
|
23
|
-
};
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { render, screen } from "@testing-library/react";
|
|
2
|
-
import { describe, expect, it } from "vitest";
|
|
3
|
-
import { TablePagination } from "../../components";
|
|
4
|
-
import { click } from "../../utils";
|
|
5
|
-
|
|
6
|
-
describe("TablePagination component", () => {
|
|
7
|
-
it("should render correctly", () => {
|
|
8
|
-
render(<TablePagination pageSize={10} totalItems={30} />);
|
|
9
|
-
const pagination = screen.getByText(/1 - 10 de 30/g);
|
|
10
|
-
expect(pagination).toBeInTheDocument();
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
it("should go next page", () => {
|
|
14
|
-
render(<TablePagination pageSize={10} totalItems={30} />);
|
|
15
|
-
const goNext = screen.getAllByRole("button")[1];
|
|
16
|
-
click(goNext);
|
|
17
|
-
|
|
18
|
-
const pagination = screen.getByText(/11 - 20 de 30/g);
|
|
19
|
-
expect(pagination).toBeInTheDocument();
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
it("should go prev page", () => {
|
|
23
|
-
render(
|
|
24
|
-
<TablePagination initialCurrentPage={2} pageSize={10} totalItems={30} />,
|
|
25
|
-
);
|
|
26
|
-
const goNext = screen.getAllByRole("button")[0];
|
|
27
|
-
click(goNext);
|
|
28
|
-
|
|
29
|
-
const pagination = screen.getByText(/1 - 10 de 30/g);
|
|
30
|
-
expect(pagination).toBeInTheDocument();
|
|
31
|
-
});
|
|
32
|
-
});
|