xertica-ui 2.1.1 → 2.1.2
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/CHANGELOG.md +13 -0
- package/bin/cli.ts +1 -1
- package/components/assistant/markdown-message/MarkdownMessage.tsx +27 -1
- package/components/ui/index.ts +1 -1
- package/components/ui/route-map/route-map.stories.tsx +54 -48
- package/components/ui/sheet/sheet.stories.tsx +95 -94
- package/components/ui/sheet/sheet.tsx +11 -0
- package/components/ui/simple-map/simple-map.stories.tsx +48 -43
- package/dist/AssistantChart-BAx9VQvb.cjs +3374 -0
- package/dist/AssistantChart-CVko2A1W.js +3348 -0
- package/dist/VerifyEmailPage-BE-L9mB7.js +2828 -0
- package/dist/VerifyEmailPage-CR7kb5df.cjs +2827 -0
- package/dist/assistant.cjs.js +1 -1
- package/dist/assistant.es.js +1 -1
- package/dist/cli.js +1 -1
- package/dist/components/ui/index.d.ts +1 -1
- package/dist/components/ui/sheet/sheet.d.ts +2 -1
- package/dist/index.cjs.js +4 -3
- package/dist/index.es.js +31 -30
- package/dist/pages.cjs.js +1 -1
- package/dist/pages.es.js +1 -1
- package/dist/ui.cjs.js +2 -1
- package/dist/ui.es.js +29 -28
- package/dist/xertica-assistant-B1IaHXnB.cjs +1894 -0
- package/dist/xertica-assistant-DPsESB6t.js +1878 -0
- package/dist/xertica-ui.css +1 -1
- package/docs/components/markdown-message.md +1 -0
- package/llms-full.txt +1 -0
- package/package.json +1 -1
- package/templates/package.json +2 -2
- package/templates/src/app/components/AppLayout.tsx +5 -1
- package/templates/src/app/components/AuthGuard.tsx +1 -1
- package/templates/src/pages/AssistantPage.tsx +304 -19
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,19 @@ Versioning follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
7
7
|
|
|
8
8
|
---
|
|
9
9
|
|
|
10
|
+
## [2.1.2] — 2026-05-14
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- **`MarkdownMessage` — suporte a tabelas GFM** — o parser regex do componente não convertia blocos de tabela Markdown (`| col | col |`) em HTML. Adicionada transformação de tabelas GFM completa (header, separador, linhas de dados) com estilos do design system (`border-border`, `hover:bg-muted/50`, `rounded-[var(--radius)]`, `overflow-x-auto`). A transformação roda antes das substituições de quebra de linha para evitar `<br/>` dentro das células.
|
|
15
|
+
|
|
16
|
+
### Added
|
|
17
|
+
|
|
18
|
+
- **Template — `AssistantPage`** — nova página de assistente completa: sidebar em modo `assistant` aberta por padrão (largura 320px), botão "Nova Conversa" (`variant="secondary"`), busca de conversas com filtro em tempo real, histórico de 8 conversas de exemplo em 3 grupos (Hoje / Ontem / Esta semana), modal de exclusão com `AlertDialog`, modal de renomeação com `Dialog` + `Input`, simulação de conteúdo ao selecionar conversa via `initialMessages`, botão "Voltar" em `variant` primário no `Header`.
|
|
19
|
+
- **Template — `AppLayout`** — novas props `sidebarVariant?: 'default' | 'assistant'` e `sidebarProps?: Record<string, any>` para permitir que páginas customizem a sidebar sem quebrar o contrato do layout.
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
10
23
|
## [2.1.1] — 2026-05-14
|
|
11
24
|
|
|
12
25
|
### Fixed
|
package/bin/cli.ts
CHANGED
|
@@ -64,8 +64,34 @@ export function MarkdownMessage({ content, className = '' }: MarkdownMessageProp
|
|
|
64
64
|
return `<ol class="list-decimal my-2">${items}</ol>`;
|
|
65
65
|
});
|
|
66
66
|
|
|
67
|
+
// GFM Tables — must run before line-break transforms
|
|
68
|
+
html = html.replace(/((?:^\|.+\|[ \t]*(?:\r?\n|$))+)/gm, (match) => {
|
|
69
|
+
const rows = match.trim().split(/\r?\n/).filter(line => line.trim());
|
|
70
|
+
if (rows.length < 2) return match;
|
|
71
|
+
|
|
72
|
+
const isSeparatorRow = /^\|[\s\-:|]+\|$/.test(rows[1].trim());
|
|
73
|
+
if (!isSeparatorRow) return match;
|
|
74
|
+
|
|
75
|
+
const parseCells = (row: string) =>
|
|
76
|
+
row.split('|').slice(1, -1).map(cell => cell.trim());
|
|
77
|
+
|
|
78
|
+
const headerCells = parseCells(rows[0])
|
|
79
|
+
.map(cell => `<th class="px-3 py-2 text-left font-medium text-xs uppercase tracking-wide border-b border-border">${cell}</th>`)
|
|
80
|
+
.join('');
|
|
81
|
+
|
|
82
|
+
const bodyRows = rows.slice(2)
|
|
83
|
+
.map(row =>
|
|
84
|
+
`<tr class="border-b border-border last:border-0 hover:bg-muted/50">${
|
|
85
|
+
parseCells(row).map(cell => `<td class="px-3 py-2 text-sm">${cell}</td>`).join('')
|
|
86
|
+
}</tr>`
|
|
87
|
+
)
|
|
88
|
+
.join('');
|
|
89
|
+
|
|
90
|
+
return `<div class="overflow-x-auto my-3 rounded-[var(--radius)] border border-border"><table class="w-full text-sm"><thead class="bg-muted/50"><tr>${headerCells}</tr></thead><tbody>${bodyRows}</tbody></table></div>`;
|
|
91
|
+
});
|
|
92
|
+
|
|
67
93
|
// Emojis and icons (keep as is)
|
|
68
|
-
|
|
94
|
+
|
|
69
95
|
// Line breaks (preserve double line breaks as paragraphs)
|
|
70
96
|
html = html.replace(/\n\n/g, '</p><p class="mb-2 break-words">');
|
|
71
97
|
html = html.replace(/\n/g, '<br/>');
|
package/components/ui/index.ts
CHANGED
|
@@ -85,7 +85,7 @@ export {
|
|
|
85
85
|
AlertDialogTitle,
|
|
86
86
|
AlertDialogTrigger
|
|
87
87
|
} from "./alert-dialog";
|
|
88
|
-
export { Sheet, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetPortal, SheetTitle, SheetTrigger } from "./sheet";
|
|
88
|
+
export { Sheet, SheetBody, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetPortal, SheetTitle, SheetTrigger } from "./sheet";
|
|
89
89
|
export { Drawer, DrawerContent, DrawerDescription, DrawerFooter, DrawerHandle, DrawerHeader, DrawerOverlay, DrawerPortal, DrawerTitle, DrawerTrigger } from "./drawer";
|
|
90
90
|
export { Popover, PopoverContent, PopoverTrigger } from "./popover";
|
|
91
91
|
export { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "./tooltip";
|
|
@@ -1,48 +1,54 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
-
import { RouteMap } from './route-map';
|
|
3
|
-
import React from 'react';
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
},
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
}
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import { RouteMap } from './route-map';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
|
|
5
|
+
function MapStoryFrame({ children }: { children: React.ReactNode }) {
|
|
6
|
+
return (
|
|
7
|
+
<div style={{ width: 'min(100vw - 48px, 960px)', minWidth: 320 }}>
|
|
8
|
+
{children}
|
|
9
|
+
</div>
|
|
10
|
+
);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const meta: Meta<typeof RouteMap> = {
|
|
14
|
+
title: 'UI/RouteMap',
|
|
15
|
+
component: RouteMap,
|
|
16
|
+
render: (args) => (
|
|
17
|
+
<MapStoryFrame>
|
|
18
|
+
<RouteMap {...args} />
|
|
19
|
+
</MapStoryFrame>
|
|
20
|
+
),
|
|
21
|
+
parameters: {
|
|
22
|
+
layout: 'centered',
|
|
23
|
+
},
|
|
24
|
+
argTypes: {
|
|
25
|
+
travelMode: {
|
|
26
|
+
control: 'select',
|
|
27
|
+
options: ['DRIVING', 'WALKING', 'BICYCLING', 'TRANSIT'],
|
|
28
|
+
},
|
|
29
|
+
height: { control: 'text' },
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export default meta;
|
|
34
|
+
type Story = StoryObj<typeof RouteMap>;
|
|
35
|
+
|
|
36
|
+
export const Default: Story = {
|
|
37
|
+
args: {
|
|
38
|
+
origin: { lat: -23.5505, lng: -46.6333 },
|
|
39
|
+
destination: { lat: -23.5617, lng: -46.6560 },
|
|
40
|
+
height: "400px",
|
|
41
|
+
onRouteCalculated: (dist, dur) => console.log(`Distance: ${dist}, Duration: ${dur}`),
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export const WithWaypoints: Story = {
|
|
46
|
+
args: {
|
|
47
|
+
origin: { lat: -23.5505, lng: -46.6333 },
|
|
48
|
+
destination: { lat: -23.5617, lng: -46.6560 },
|
|
49
|
+
waypoints: [
|
|
50
|
+
{ lat: -23.5550, lng: -46.6450 },
|
|
51
|
+
],
|
|
52
|
+
height: "500px",
|
|
53
|
+
},
|
|
54
|
+
};
|
|
@@ -1,94 +1,95 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
-
import {
|
|
3
|
-
Sheet,
|
|
4
|
-
SheetContent,
|
|
5
|
-
SheetDescription,
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
<
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
<
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import {
|
|
3
|
+
Sheet,
|
|
4
|
+
SheetContent,
|
|
5
|
+
SheetDescription,
|
|
6
|
+
SheetBody,
|
|
7
|
+
SheetFooter,
|
|
8
|
+
SheetHeader,
|
|
9
|
+
SheetTitle,
|
|
10
|
+
SheetTrigger,
|
|
11
|
+
SheetClose,
|
|
12
|
+
} from './sheet';
|
|
13
|
+
import { Button } from '../button';
|
|
14
|
+
import { Input } from '../input';
|
|
15
|
+
import { Label } from '../label';
|
|
16
|
+
import React from 'react';
|
|
17
|
+
|
|
18
|
+
const meta: Meta<typeof Sheet> = {
|
|
19
|
+
title: 'UI/Sheet',
|
|
20
|
+
component: Sheet,
|
|
21
|
+
render: (args) => <Sheet {...args} />,
|
|
22
|
+
argTypes: {
|
|
23
|
+
open: {
|
|
24
|
+
control: 'boolean',
|
|
25
|
+
description: 'Whether the sheet is open.',
|
|
26
|
+
},
|
|
27
|
+
modal: {
|
|
28
|
+
control: 'boolean',
|
|
29
|
+
description: 'Whether the sheet should be modal.',
|
|
30
|
+
defaultValue: true,
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export default meta;
|
|
36
|
+
type Story = StoryObj<typeof Sheet>;
|
|
37
|
+
|
|
38
|
+
export const Default: Story = {
|
|
39
|
+
render: (args) => (
|
|
40
|
+
<Sheet {...args}>
|
|
41
|
+
<SheetTrigger asChild>
|
|
42
|
+
<Button variant="outline">Open Right Sheet</Button>
|
|
43
|
+
</SheetTrigger>
|
|
44
|
+
<SheetContent>
|
|
45
|
+
<SheetHeader>
|
|
46
|
+
<SheetTitle>Edit profile</SheetTitle>
|
|
47
|
+
<SheetDescription>
|
|
48
|
+
Make changes to your profile here. Click save when you're done.
|
|
49
|
+
</SheetDescription>
|
|
50
|
+
</SheetHeader>
|
|
51
|
+
<SheetBody className="grid gap-4">
|
|
52
|
+
<div className="grid grid-cols-4 items-center gap-4">
|
|
53
|
+
<Label htmlFor="name" className="text-right">
|
|
54
|
+
Name
|
|
55
|
+
</Label>
|
|
56
|
+
<Input id="name" value="Pedro Duarte" className="col-span-3" />
|
|
57
|
+
</div>
|
|
58
|
+
<div className="grid grid-cols-4 items-center gap-4">
|
|
59
|
+
<Label htmlFor="username" className="text-right">
|
|
60
|
+
Username
|
|
61
|
+
</Label>
|
|
62
|
+
<Input id="username" value="@peduarte" className="col-span-3" />
|
|
63
|
+
</div>
|
|
64
|
+
</SheetBody>
|
|
65
|
+
<SheetFooter>
|
|
66
|
+
<SheetClose asChild>
|
|
67
|
+
<Button type="submit">Save changes</Button>
|
|
68
|
+
</SheetClose>
|
|
69
|
+
</SheetFooter>
|
|
70
|
+
</SheetContent>
|
|
71
|
+
</Sheet>
|
|
72
|
+
),
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
export const SideBySide: Story = {
|
|
76
|
+
render: () => (
|
|
77
|
+
<div className="grid grid-cols-2 gap-2 w-fit">
|
|
78
|
+
{(["top", "bottom", "left", "right"] as const).map((side) => (
|
|
79
|
+
<Sheet key={side}>
|
|
80
|
+
<SheetTrigger asChild>
|
|
81
|
+
<Button variant="outline">{side}</Button>
|
|
82
|
+
</SheetTrigger>
|
|
83
|
+
<SheetContent side={side}>
|
|
84
|
+
<SheetHeader>
|
|
85
|
+
<SheetTitle>Edit profile</SheetTitle>
|
|
86
|
+
<SheetDescription>
|
|
87
|
+
This sheet pops out from the {side}.
|
|
88
|
+
</SheetDescription>
|
|
89
|
+
</SheetHeader>
|
|
90
|
+
</SheetContent>
|
|
91
|
+
</Sheet>
|
|
92
|
+
))}
|
|
93
|
+
</div>
|
|
94
|
+
),
|
|
95
|
+
};
|
|
@@ -102,6 +102,16 @@ function SheetHeader({ className, ...props }: React.ComponentProps<"div">) {
|
|
|
102
102
|
);
|
|
103
103
|
}
|
|
104
104
|
|
|
105
|
+
function SheetBody({ className, ...props }: React.ComponentProps<"div">) {
|
|
106
|
+
return (
|
|
107
|
+
<div
|
|
108
|
+
data-slot="sheet-body"
|
|
109
|
+
className={cn("flex-1 overflow-auto px-6", className)}
|
|
110
|
+
{...props}
|
|
111
|
+
/>
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
|
|
105
115
|
function SheetFooter({ className, ...props }: React.ComponentProps<"div">) {
|
|
106
116
|
return (
|
|
107
117
|
<div
|
|
@@ -144,6 +154,7 @@ export {
|
|
|
144
154
|
SheetClose,
|
|
145
155
|
SheetContent,
|
|
146
156
|
SheetHeader,
|
|
157
|
+
SheetBody,
|
|
147
158
|
SheetFooter,
|
|
148
159
|
SheetTitle,
|
|
149
160
|
SheetDescription,
|
|
@@ -1,43 +1,48 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
-
import { SimpleMap } from './simple-map';
|
|
3
|
-
import React from 'react';
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import { SimpleMap } from './simple-map';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
|
|
5
|
+
function MapStoryFrame({ children }: { children: React.ReactNode }) {
|
|
6
|
+
return (
|
|
7
|
+
<div style={{ width: 'min(100vw - 48px, 960px)', minWidth: 320 }}>
|
|
8
|
+
{children}
|
|
9
|
+
</div>
|
|
10
|
+
);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const meta: Meta<typeof SimpleMap> = {
|
|
14
|
+
title: 'UI/SimpleMap',
|
|
15
|
+
component: SimpleMap,
|
|
16
|
+
render: (args) => (
|
|
17
|
+
<MapStoryFrame>
|
|
18
|
+
<SimpleMap {...args} />
|
|
19
|
+
</MapStoryFrame>
|
|
20
|
+
),
|
|
21
|
+
parameters: {
|
|
22
|
+
layout: 'centered',
|
|
23
|
+
},
|
|
24
|
+
argTypes: {
|
|
25
|
+
zoom: { control: { type: 'range', min: 1, max: 20 } },
|
|
26
|
+
height: { control: 'text' },
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export default meta;
|
|
31
|
+
type Story = StoryObj<typeof SimpleMap>;
|
|
32
|
+
|
|
33
|
+
export const Default: Story = {
|
|
34
|
+
args: {
|
|
35
|
+
center: { lat: -23.5505, lng: -46.6333 },
|
|
36
|
+
markerTitle: "Central Office",
|
|
37
|
+
markerInfo: "Paulista Ave, 1000",
|
|
38
|
+
zoom: 15,
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export const WithoutMarker: Story = {
|
|
43
|
+
args: {
|
|
44
|
+
center: { lat: -23.5505, lng: -46.6333 },
|
|
45
|
+
showMarker: false,
|
|
46
|
+
zoom: 12,
|
|
47
|
+
},
|
|
48
|
+
};
|