@boxcustodia/library 2.0.0-alpha.12 → 2.0.0-alpha.13
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 +38 -38
- package/dist/index.d.ts +28 -29
- package/dist/index.es.js +6804 -6792
- package/package.json +1 -1
- package/src/__doc__/Migration.mdx +2 -26
- package/src/components/combobox/combobox.tsx +29 -23
- package/src/components/divider/divider.stories.tsx +120 -51
- package/src/components/divider/divider.tsx +16 -16
- package/src/components/field/field.stories.tsx +1 -1
- package/src/components/multi-select/multi-select.stories.tsx +1 -1
- package/src/components/number-input/number-input.tsx +7 -5
- package/src/components/password/password.tsx +9 -5
package/package.json
CHANGED
|
@@ -232,12 +232,12 @@ La prop `containerClassName` fue eliminada. Usá `className` para estilizar el i
|
|
|
232
232
|
|
|
233
233
|
---
|
|
234
234
|
|
|
235
|
-
##
|
|
235
|
+
## 4. Version 2.0.0-alpha.11
|
|
236
236
|
|
|
237
237
|
### Instalación
|
|
238
238
|
|
|
239
239
|
```bash
|
|
240
|
-
npm install @boxcustodia/library@2.0.0-alpha.
|
|
240
|
+
npm install @boxcustodia/library@2.0.0-alpha.11
|
|
241
241
|
```
|
|
242
242
|
|
|
243
243
|
### Cambios necesarios
|
|
@@ -260,18 +260,6 @@ import { useForm, Form, FormField } from "@/components/form/form";
|
|
|
260
260
|
|
|
261
261
|
El resto de tu código no necesita ningún cambio.
|
|
262
262
|
|
|
263
|
-
---
|
|
264
|
-
|
|
265
|
-
## 4. Version 2.0.0-alpha.10
|
|
266
|
-
|
|
267
|
-
### Instalación
|
|
268
|
-
|
|
269
|
-
```bash
|
|
270
|
-
npm install @boxcustodia/library@2.0.0-alpha.10
|
|
271
|
-
```
|
|
272
|
-
|
|
273
|
-
### Cambios necesarios
|
|
274
|
-
|
|
275
263
|
#### Calendar
|
|
276
264
|
|
|
277
265
|
El componente `Calendar` fue completamente reescrito usando `react-day-picker` en lugar de una implementación custom. La API cambió significativamente:
|
|
@@ -391,18 +379,6 @@ El componente ahora soporta múltiples modos y cambió de API internamente.
|
|
|
391
379
|
|
|
392
380
|
**Si necesitás un date picker editable:** Usá el nuevo componente `DateInput` que permite escribir la fecha directamente en el input además de seleccionar desde el calendar.
|
|
393
381
|
|
|
394
|
-
---
|
|
395
|
-
|
|
396
|
-
## 5. Version 2.0.0-alpha.11
|
|
397
|
-
|
|
398
|
-
### Instalación
|
|
399
|
-
|
|
400
|
-
```bash
|
|
401
|
-
npm install @boxcustodia/library@2.0.0-alpha.11
|
|
402
|
-
```
|
|
403
|
-
|
|
404
|
-
### Cambios necesarios
|
|
405
|
-
|
|
406
382
|
#### Combobox
|
|
407
383
|
|
|
408
384
|
El Combobox fue completamente reescrito usando Base UI en lugar de la arquitectura anterior. La API es significativamente diferente. Ahora soporta selección múltiple con chips dinámicos y una arquitectura de primitivas para casos de uso avanzados.
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Combobox as ComboboxPrimitive } from "@base-ui/react/combobox";
|
|
2
|
+
import { Field as FieldPrimitive } from "@base-ui/react/field";
|
|
2
3
|
import { ChevronsUpDownIcon, XIcon } from "lucide-react";
|
|
3
4
|
import * as React from "react";
|
|
4
5
|
import { cn } from "../../lib";
|
|
@@ -487,31 +488,36 @@ export function ComboboxChips({
|
|
|
487
488
|
const { chipsRef } = React.useContext(ComboboxContext);
|
|
488
489
|
|
|
489
490
|
return (
|
|
490
|
-
<
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
aria-hidden="true"
|
|
507
|
-
className="flex shrink-0 items-center ps-2 opacity-80 has-[+[data-slot=combobox-chip]]:pe-2 [&_svg:not([class*='size-'])]:size-4.5 sm:[&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:-ms-0.5 [&_svg]:-me-1.5"
|
|
508
|
-
data-slot="combobox-start-addon"
|
|
491
|
+
<FieldPrimitive.Validity>
|
|
492
|
+
{({ validity }) => (
|
|
493
|
+
<ComboboxPrimitive.Chips
|
|
494
|
+
aria-invalid={validity.valid === false ? true : undefined}
|
|
495
|
+
className={cn(
|
|
496
|
+
inputBaseClasses,
|
|
497
|
+
"relative inline-flex pr-6 w-full flex-wrap gap-1",
|
|
498
|
+
"placeholder:text-muted-foreground",
|
|
499
|
+
"focus-within:border-ring",
|
|
500
|
+
"aria-invalid:border-error focus-within:aria-invalid:ring-error/20",
|
|
501
|
+
"has-disabled:cursor-not-allowed has-disabled:opacity-50",
|
|
502
|
+
className,
|
|
503
|
+
)}
|
|
504
|
+
data-slot="combobox-chips"
|
|
505
|
+
ref={chipsRef as React.Ref<HTMLDivElement> | null}
|
|
506
|
+
{...props}
|
|
509
507
|
>
|
|
510
|
-
{startAddon
|
|
511
|
-
|
|
508
|
+
{startAddon && (
|
|
509
|
+
<div
|
|
510
|
+
aria-hidden="true"
|
|
511
|
+
className="flex shrink-0 items-center ps-2 opacity-80 has-[+[data-slot=combobox-chip]]:pe-2 [&_svg:not([class*='size-'])]:size-4.5 sm:[&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:-ms-0.5 [&_svg]:-me-1.5"
|
|
512
|
+
data-slot="combobox-start-addon"
|
|
513
|
+
>
|
|
514
|
+
{startAddon}
|
|
515
|
+
</div>
|
|
516
|
+
)}
|
|
517
|
+
{children}
|
|
518
|
+
</ComboboxPrimitive.Chips>
|
|
512
519
|
)}
|
|
513
|
-
|
|
514
|
-
</ComboboxPrimitive.Chips>
|
|
520
|
+
</FieldPrimitive.Validity>
|
|
515
521
|
);
|
|
516
522
|
}
|
|
517
523
|
|
|
@@ -1,70 +1,139 @@
|
|
|
1
|
-
import { Meta, StoryObj } from "@storybook/react-vite";
|
|
2
|
-
import {
|
|
3
|
-
import { Button, Divider } from "../../components";
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react-vite";
|
|
2
|
+
import { Divider } from "../../components";
|
|
4
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Visual separator between sections or inline elements.
|
|
6
|
+
*
|
|
7
|
+
* Built on the Base UI `Separator` primitive. Supports `orientation` (`horizontal` | `vertical`)
|
|
8
|
+
* and a `render` prop for polymorphic composition. The DOM element receives `data-orientation`
|
|
9
|
+
* which can be used as a CSS selector for conditional styles.
|
|
10
|
+
*/
|
|
5
11
|
const meta: Meta<typeof Divider> = {
|
|
6
|
-
title: "
|
|
12
|
+
title: "Components/Divider",
|
|
7
13
|
component: Divider,
|
|
14
|
+
args: {
|
|
15
|
+
orientation: "horizontal",
|
|
16
|
+
},
|
|
17
|
+
parameters: {
|
|
18
|
+
layout: "centered",
|
|
19
|
+
},
|
|
8
20
|
};
|
|
9
21
|
|
|
10
22
|
export default meta;
|
|
11
|
-
type Story = StoryObj<typeof
|
|
23
|
+
type Story = StoryObj<typeof Divider>;
|
|
12
24
|
|
|
25
|
+
export const Default: Story = {
|
|
26
|
+
render: () => (
|
|
27
|
+
<div className="w-72 rounded-lg border p-4 text-sm">
|
|
28
|
+
<div className="flex items-center justify-between">
|
|
29
|
+
<span className="font-medium">Deployment #847</span>
|
|
30
|
+
<span className="text-xs text-green-500">● Live</span>
|
|
31
|
+
</div>
|
|
32
|
+
<Divider className="my-3" />
|
|
33
|
+
<div className="space-y-1.5 text-muted-foreground">
|
|
34
|
+
<div className="flex justify-between">
|
|
35
|
+
<span>Triggered by</span>
|
|
36
|
+
<span className="text-foreground">fbaigorria</span>
|
|
37
|
+
</div>
|
|
38
|
+
<div className="flex justify-between">
|
|
39
|
+
<span>Branch</span>
|
|
40
|
+
<span className="text-foreground">develop</span>
|
|
41
|
+
</div>
|
|
42
|
+
<div className="flex justify-between">
|
|
43
|
+
<span>Duration</span>
|
|
44
|
+
<span className="text-foreground">1m 43s</span>
|
|
45
|
+
</div>
|
|
46
|
+
</div>
|
|
47
|
+
<Divider className="my-3" />
|
|
48
|
+
<div className="flex items-center justify-center gap-4 text-muted-foreground">
|
|
49
|
+
<span>2 warnings</span>
|
|
50
|
+
<Divider orientation="vertical" className="h-4" />
|
|
51
|
+
<span>0 errors</span>
|
|
52
|
+
<Divider orientation="vertical" className="h-4" />
|
|
53
|
+
<span>127 tests</span>
|
|
54
|
+
</div>
|
|
55
|
+
</div>
|
|
56
|
+
),
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Default orientation. Renders a full-width 1px horizontal line via `data-[orientation=horizontal]`.
|
|
61
|
+
* Commonly used to separate named sections inside a panel or card.
|
|
62
|
+
*/
|
|
13
63
|
export const Horizontal: Story = {
|
|
64
|
+
render: () => (
|
|
65
|
+
<div className="w-72 rounded-lg border p-4 space-y-4">
|
|
66
|
+
<div>
|
|
67
|
+
<p className="text-sm font-medium">Profile</p>
|
|
68
|
+
<p className="text-xs text-muted-foreground">Franco Baigorria</p>
|
|
69
|
+
</div>
|
|
70
|
+
<Divider />
|
|
71
|
+
<div>
|
|
72
|
+
<p className="text-sm font-medium">Team</p>
|
|
73
|
+
<p className="text-xs text-muted-foreground">Engineering</p>
|
|
74
|
+
</div>
|
|
75
|
+
<Divider />
|
|
76
|
+
<div>
|
|
77
|
+
<p className="text-sm font-medium">Role</p>
|
|
78
|
+
<p className="text-xs text-muted-foreground">Frontend Architect</p>
|
|
79
|
+
</div>
|
|
80
|
+
</div>
|
|
81
|
+
),
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* In vertical orientation the component uses `self-stretch` to fill the full height of
|
|
86
|
+
* the flex container. Wrapping in a `div` with `flex` and a defined height is the expected pattern.
|
|
87
|
+
*/
|
|
88
|
+
export const Vertical: Story = {
|
|
14
89
|
args: {
|
|
15
|
-
orientation: "
|
|
90
|
+
orientation: "vertical",
|
|
16
91
|
},
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
<
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
</Button>
|
|
27
|
-
<Story />
|
|
28
|
-
<Button size="icon">
|
|
29
|
-
<Github />
|
|
30
|
-
</Button>
|
|
31
|
-
</div>
|
|
32
|
-
),
|
|
33
|
-
],
|
|
92
|
+
render: (args) => (
|
|
93
|
+
<div className="flex h-10 items-center gap-4">
|
|
94
|
+
<span className="text-sm">Section A</span>
|
|
95
|
+
<Divider {...args} />
|
|
96
|
+
<span className="text-sm">Section B</span>
|
|
97
|
+
<Divider {...args} />
|
|
98
|
+
<span className="text-sm">Section C</span>
|
|
99
|
+
</div>
|
|
100
|
+
),
|
|
34
101
|
};
|
|
35
102
|
|
|
36
103
|
/**
|
|
37
|
-
*
|
|
38
|
-
*
|
|
104
|
+
* The `render` prop replaces the rendered DOM element. Useful for swapping semantics
|
|
105
|
+
* to `<hr>` or any other element without losing component styles.
|
|
39
106
|
*
|
|
40
107
|
* ```tsx
|
|
41
|
-
* <
|
|
42
|
-
* <PencilIcon />
|
|
43
|
-
* <Divider orientation="vertical" /> // <- vertical
|
|
44
|
-
* <CatIcon />
|
|
45
|
-
* </div>
|
|
108
|
+
* <Divider render={<hr />} />
|
|
46
109
|
* ```
|
|
47
110
|
*/
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
111
|
+
export const Render: Story = {
|
|
112
|
+
render: (args) => (
|
|
113
|
+
<div className="w-64">
|
|
114
|
+
<Divider {...args} render={<hr />} />
|
|
115
|
+
</div>
|
|
116
|
+
),
|
|
117
|
+
parameters: {
|
|
118
|
+
docs: {
|
|
119
|
+
source: {
|
|
120
|
+
code: `<Divider render={<hr />} />`,
|
|
121
|
+
},
|
|
122
|
+
},
|
|
52
123
|
},
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
),
|
|
69
|
-
],
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* `className` accepts Tailwind classes to override color, thickness, or spacing.
|
|
128
|
+
* `data-[orientation=horizontal]` and `data-[orientation=vertical]` are available
|
|
129
|
+
* as CSS selectors for advanced conditional styles.
|
|
130
|
+
*/
|
|
131
|
+
export const Custom: Story = {
|
|
132
|
+
render: () => (
|
|
133
|
+
<div className="space-y-4 w-64">
|
|
134
|
+
<Divider className="bg-primary" />
|
|
135
|
+
<Divider className="bg-error" />
|
|
136
|
+
<Divider className="border-t border-dashed border-input bg-transparent" />
|
|
137
|
+
</div>
|
|
138
|
+
),
|
|
70
139
|
};
|
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
type Props = {
|
|
5
|
-
orientation?: "horizontal" | "vertical";
|
|
6
|
-
} & HTMLProps<HTMLHRElement>;
|
|
7
|
-
|
|
8
|
-
export const Divider = (props: Props) => {
|
|
9
|
-
const { className, orientation = "horizontal" } = props;
|
|
1
|
+
import { Separator as SeparatorPrimitive } from "@base-ui/react/separator";
|
|
2
|
+
import type React from "react";
|
|
3
|
+
import { cn } from "tailwind-variants";
|
|
10
4
|
|
|
5
|
+
export function Divider({
|
|
6
|
+
className,
|
|
7
|
+
orientation = "horizontal",
|
|
8
|
+
...props
|
|
9
|
+
}: SeparatorPrimitive.Props): React.ReactElement {
|
|
11
10
|
return (
|
|
12
|
-
<
|
|
13
|
-
{...props}
|
|
14
|
-
aria-orientation={orientation}
|
|
11
|
+
<SeparatorPrimitive
|
|
15
12
|
className={cn(
|
|
16
|
-
"shrink-0 bg-input",
|
|
17
|
-
orientation === "horizontal" ? "h-[1px] w-full" : "h-full w-[1px]",
|
|
13
|
+
"shrink-0 bg-input data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:w-px data-[orientation=vertical]:not-[[class^='h-']]:not-[[class*='_h-']]:self-stretch",
|
|
18
14
|
className,
|
|
19
15
|
)}
|
|
20
|
-
data-slot="
|
|
16
|
+
data-slot="separator"
|
|
17
|
+
orientation={orientation}
|
|
18
|
+
{...props}
|
|
21
19
|
/>
|
|
22
20
|
);
|
|
23
|
-
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export { SeparatorPrimitive };
|
|
@@ -127,7 +127,7 @@ export const WithValidity: Story = {
|
|
|
127
127
|
<FieldValidity>
|
|
128
128
|
{({ validity }) =>
|
|
129
129
|
!validity.valid && (
|
|
130
|
-
<p className="text-
|
|
130
|
+
<p className="text-error-foreground text-xs">
|
|
131
131
|
{validity.valueMissing
|
|
132
132
|
? "Email is required."
|
|
133
133
|
: "Enter a valid email address."}
|
|
@@ -11,7 +11,7 @@ const generateRandomOption = () => ({
|
|
|
11
11
|
const items = faker.helpers.multiple(generateRandomOption, { count: 10 });
|
|
12
12
|
|
|
13
13
|
const meta: Meta<typeof MultiSelect> = {
|
|
14
|
-
title: "
|
|
14
|
+
title: "Deprecated/MultiSelect",
|
|
15
15
|
component: MultiSelect,
|
|
16
16
|
args: {
|
|
17
17
|
items,
|
|
@@ -32,11 +32,12 @@ export function NumberInputGroup({
|
|
|
32
32
|
return (
|
|
33
33
|
<NumberFieldPrimitive.Group
|
|
34
34
|
className={cn(
|
|
35
|
-
"flex w-full items-center overflow-hidden rounded-md
|
|
36
|
-
"
|
|
37
|
-
"
|
|
38
|
-
"
|
|
39
|
-
"
|
|
35
|
+
"flex h-10 w-full items-center overflow-hidden rounded-md bg-background text-sm transition-shadow",
|
|
36
|
+
"outline outline-1 outline-input [outline-offset:-1px]",
|
|
37
|
+
"focus-within:outline-ring",
|
|
38
|
+
"aria-invalid:outline-error focus-within:aria-invalid:ring-error/20",
|
|
39
|
+
"has-aria-invalid:outline-error focus-within:has-aria-invalid:ring-error/20",
|
|
40
|
+
"data-[invalid]:outline-error focus-within:data-[invalid]:ring-error/20",
|
|
40
41
|
"data-disabled:cursor-not-allowed data-disabled:opacity-50 data-disabled:pointer-events-none",
|
|
41
42
|
"[&_svg]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0",
|
|
42
43
|
className,
|
|
@@ -195,6 +196,7 @@ export function NumberInput({
|
|
|
195
196
|
{...(invalid ? { "aria-invalid": true } : {})}
|
|
196
197
|
placeholder={placeholder}
|
|
197
198
|
{...inputProps}
|
|
199
|
+
className={cn("self-stretch", inputProps?.className)}
|
|
198
200
|
/>
|
|
199
201
|
{!hideControls && (
|
|
200
202
|
<div className="flex flex-col self-stretch divide-y divide-input border-l border-input">
|
|
@@ -37,10 +37,7 @@ export function Password({
|
|
|
37
37
|
return (
|
|
38
38
|
<div
|
|
39
39
|
className={cn(
|
|
40
|
-
"relative inline-flex w-full
|
|
41
|
-
"text-sm transition-shadow",
|
|
42
|
-
"has-focus-visible:border-ring",
|
|
43
|
-
"has-aria-invalid:border-error has-focus-visible:has-aria-invalid:ring-error/20",
|
|
40
|
+
"relative inline-flex w-full",
|
|
44
41
|
"has-disabled:cursor-not-allowed has-disabled:opacity-50",
|
|
45
42
|
className,
|
|
46
43
|
)}
|
|
@@ -50,7 +47,14 @@ export function Password({
|
|
|
50
47
|
{...rest}
|
|
51
48
|
onChange={handleChange}
|
|
52
49
|
type={showPassword ? "text" : "password"}
|
|
53
|
-
className=
|
|
50
|
+
className={cn(
|
|
51
|
+
"h-10 w-full min-w-0 rounded-md border border-input bg-background",
|
|
52
|
+
"pl-3 pr-10 text-sm outline-none transition-shadow placeholder:text-muted-foreground",
|
|
53
|
+
"focus-visible:border-ring",
|
|
54
|
+
"aria-invalid:border-error focus-visible:aria-invalid:ring-error/20",
|
|
55
|
+
"disabled:cursor-not-allowed",
|
|
56
|
+
"[&::-ms-clear]:hidden [&::-ms-reveal]:hidden",
|
|
57
|
+
)}
|
|
54
58
|
/>
|
|
55
59
|
<button
|
|
56
60
|
data-slot="password-toggle"
|