Compare commits
2 Commits
b0f75f390f
...
4a5d3d0621
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4a5d3d0621 | ||
|
|
07bac39d31 |
14
dist/Card/Card.d.ts
vendored
14
dist/Card/Card.d.ts
vendored
@@ -2,7 +2,19 @@ import React from 'react';
|
||||
export interface CardProps {
|
||||
children: React.ReactNode;
|
||||
className?: string;
|
||||
padding?: 'none' | 'sm' | 'md' | 'lg';
|
||||
hover?: boolean;
|
||||
}
|
||||
export declare const Card: React.FC<CardProps>;
|
||||
export declare const CardHeader: React.FC<{
|
||||
children: React.ReactNode;
|
||||
className?: string;
|
||||
}>;
|
||||
export declare const CardContent: React.FC<{
|
||||
children: React.ReactNode;
|
||||
className?: string;
|
||||
}>;
|
||||
export declare const CardFooter: React.FC<{
|
||||
children: React.ReactNode;
|
||||
className?: string;
|
||||
}>;
|
||||
export default Card;
|
||||
|
||||
17
dist/Card/Card.js
vendored
17
dist/Card/Card.js
vendored
@@ -1,11 +1,12 @@
|
||||
import { jsx as _jsx } from "react/jsx-runtime";
|
||||
export const Card = ({ children, className = '', padding = 'md' }) => {
|
||||
const paddingClasses = {
|
||||
none: '',
|
||||
sm: 'p-3',
|
||||
md: 'p-6',
|
||||
lg: 'p-8'
|
||||
};
|
||||
return (_jsx("div", { className: `bg-white rounded-xl shadow-lg border border-gray-200 ${paddingClasses[padding]} ${className}`, children: children }));
|
||||
export const Card = ({ children, className = '', hover = false }) => {
|
||||
return (_jsx("div", { className: `
|
||||
bg-white rounded-xl border border-gray-200 shadow-sm
|
||||
${hover ? 'hover:shadow-md transition-shadow duration-200' : ''}
|
||||
${className}
|
||||
`, children: children }));
|
||||
};
|
||||
export const CardHeader = ({ children, className = '' }) => (_jsx("div", { className: `p-6 pb-4 ${className}`, children: children }));
|
||||
export const CardContent = ({ children, className = '' }) => (_jsx("div", { className: `p-6 pt-0 ${className}`, children: children }));
|
||||
export const CardFooter = ({ children, className = '' }) => (_jsx("div", { className: `p-6 pt-4 border-t border-gray-100 ${className}`, children: children }));
|
||||
export default Card;
|
||||
|
||||
3
dist/ChatInterface/ChatInterface.d.ts
vendored
Normal file
3
dist/ChatInterface/ChatInterface.d.ts
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
import React from 'react';
|
||||
export declare const ChatInterface: React.FC;
|
||||
export default ChatInterface;
|
||||
28
dist/ChatInterface/ChatInterface.js
vendored
Normal file
28
dist/ChatInterface/ChatInterface.js
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
||||
import { useState } from 'react';
|
||||
import Message from '../Message';
|
||||
import Input from '../Input';
|
||||
import Button from '../Button';
|
||||
export const ChatInterface = () => {
|
||||
const [message, setMessage] = useState('');
|
||||
const [messages, setMessages] = useState([
|
||||
{ id: 1, text: '¡Hola! ¿En qué puedo ayudarte?', isOwn: false, timestamp: '10:00' },
|
||||
{ id: 2, text: 'Me gustaría información sobre mis inversiones', isOwn: true, timestamp: '10:01' },
|
||||
]);
|
||||
const sendMessage = () => {
|
||||
if (message.trim()) {
|
||||
setMessages([
|
||||
...messages,
|
||||
{
|
||||
id: messages.length + 1,
|
||||
text: message,
|
||||
isOwn: true,
|
||||
timestamp: new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })
|
||||
}
|
||||
]);
|
||||
setMessage('');
|
||||
}
|
||||
};
|
||||
return (_jsxs("div", { className: "flex flex-col h-full bg-maya-background rounded-lg border border-gray-200", children: [_jsx("div", { className: "bg-white px-4 py-3 border-b border-gray-200 rounded-t-lg", children: _jsxs("div", { className: "flex items-center space-x-3", children: [_jsx("div", { className: "w-3 h-3 bg-maya-primary rounded-full" }), _jsx("h3", { className: "font-semibold text-gray-800", children: "Soporte Banorte" }), _jsx("div", { className: "w-2 h-2 bg-maya-success rounded-full" })] }) }), _jsx("div", { className: "flex-1 p-4 overflow-y-auto", children: messages.map((msg) => (_jsx(Message, { text: msg.text, isOwn: msg.isOwn, timestamp: msg.timestamp }, msg.id))) }), _jsx("div", { className: "bg-white p-4 border-t border-gray-200 rounded-b-lg", children: _jsxs("div", { className: "flex space-x-2", children: [_jsx(Input, { value: message, onChange: (e) => setMessage(e.target.value), placeholder: "Escribe tu mensaje...", className: "flex-1", onKeyPress: (e) => e.key === 'Enter' && sendMessage() }), _jsx(Button, { onClick: sendMessage, variant: "primary", children: "Enviar" })] }) })] }));
|
||||
};
|
||||
export default ChatInterface;
|
||||
2
dist/ChatInterface/index.d.ts
vendored
Normal file
2
dist/ChatInterface/index.d.ts
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
export { default } from './ChatInterface';
|
||||
export type { ChatInterface } from './ChatInterface';
|
||||
1
dist/ChatInterface/index.js
vendored
Normal file
1
dist/ChatInterface/index.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
export { default } from './ChatInterface';
|
||||
8
dist/Input/Input.d.ts
vendored
Normal file
8
dist/Input/Input.d.ts
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
import React from 'react';
|
||||
export interface InputProps extends React.InputHTMLAttributes<HTMLInputElement> {
|
||||
label?: string;
|
||||
error?: string;
|
||||
helperText?: string;
|
||||
}
|
||||
export declare const Input: React.ForwardRefExoticComponent<InputProps & React.RefAttributes<HTMLInputElement>>;
|
||||
export default Input;
|
||||
8
dist/Input/Input.js
vendored
Normal file
8
dist/Input/Input.js
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
||||
import React from 'react';
|
||||
export const Input = React.forwardRef(({ label, error, helperText, className = '', ...props }, ref) => {
|
||||
return (_jsxs("div", { className: "space-y-1", children: [label && (_jsx("label", { className: "block text-sm font-medium text-gray-700 mb-1", children: label })), _jsx("input", { ref: ref, className: `w-full px-3 py-2 border rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:ring-maya-primary focus:border-transparent transition-all ${error
|
||||
? 'border-red-300 bg-red-50'
|
||||
: 'border-gray-300 hover:border-gray-400'} ${className}`, ...props }), error && (_jsx("p", { className: "text-sm text-maya-danger", children: error })), helperText && !error && (_jsx("p", { className: "text-sm text-gray-500", children: helperText }))] }));
|
||||
});
|
||||
export default Input;
|
||||
2
dist/Input/index.d.ts
vendored
Normal file
2
dist/Input/index.d.ts
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
export { default } from './Input';
|
||||
export type { InputProps } from './Input';
|
||||
1
dist/Input/index.js
vendored
Normal file
1
dist/Input/index.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
export { default } from './Input';
|
||||
9
dist/Message/Message.d.ts
vendored
Normal file
9
dist/Message/Message.d.ts
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
import React from 'react';
|
||||
export interface MessageProps {
|
||||
text: string;
|
||||
isOwn?: boolean;
|
||||
timestamp?: string;
|
||||
status?: 'sent' | 'delivered' | 'read';
|
||||
}
|
||||
export declare const Message: React.FC<MessageProps>;
|
||||
export default Message;
|
||||
7
dist/Message/Message.js
vendored
Normal file
7
dist/Message/Message.js
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
||||
export const Message = ({ text, isOwn = false, timestamp, status = 'sent' }) => {
|
||||
return (_jsx("div", { className: `flex ${isOwn ? 'justify-end' : 'justify-start'} mb-4`, children: _jsxs("div", { className: `max-w-xs lg:max-w-md px-4 py-2 rounded-2xl ${isOwn
|
||||
? 'bg-maya-primary text-white rounded-br-none'
|
||||
: 'bg-maya-accent text-gray-800 rounded-bl-none'}`, children: [_jsx("p", { className: "text-sm", children: text }), _jsxs("div", { className: `flex items-center justify-end space-x-1 mt-1 ${isOwn ? 'text-red-100' : 'text-gray-500'}`, children: [_jsx("span", { className: "text-xs", children: timestamp }), isOwn && (_jsx("span", { className: "text-xs", children: status === 'read' ? '✓✓' : status === 'delivered' ? '✓✓' : '✓' }))] })] }) }));
|
||||
};
|
||||
export default Message;
|
||||
2
dist/Message/index.d.ts
vendored
Normal file
2
dist/Message/index.d.ts
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
export { default } from './Message';
|
||||
export type { MessageProps } from './Message';
|
||||
1
dist/Message/index.js
vendored
Normal file
1
dist/Message/index.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
export { default } from './Message';
|
||||
5
dist/index.d.ts
vendored
5
dist/index.d.ts
vendored
@@ -1,4 +1,9 @@
|
||||
export { default as Button } from './Button';
|
||||
export { default as Card } from './Card';
|
||||
export { default as Input } from './Input';
|
||||
export { default as Message } from './Message';
|
||||
export { default as ChatInterface } from './ChatInterface';
|
||||
export type { ButtonProps } from './Button';
|
||||
export type { CardProps } from './Card';
|
||||
export type { InputProps } from './Input';
|
||||
export type { MessageProps } from './Message';
|
||||
|
||||
3
dist/index.js
vendored
3
dist/index.js
vendored
@@ -1,3 +1,6 @@
|
||||
// src/index.ts
|
||||
export { default as Button } from './Button';
|
||||
export { default as Card } from './Card';
|
||||
export { default as Input } from './Input';
|
||||
export { default as Message } from './Message';
|
||||
export { default as ChatInterface } from './ChatInterface';
|
||||
|
||||
2
dist/styles.css
vendored
2
dist/styles.css
vendored
File diff suppressed because one or more lines are too long
@@ -3,26 +3,50 @@ import React from 'react';
|
||||
export interface CardProps {
|
||||
children: React.ReactNode;
|
||||
className?: string;
|
||||
padding?: 'none' | 'sm' | 'md' | 'lg';
|
||||
hover?: boolean;
|
||||
}
|
||||
|
||||
export const Card: React.FC<CardProps> = ({
|
||||
children,
|
||||
className = '',
|
||||
padding = 'md'
|
||||
hover = false
|
||||
}) => {
|
||||
const paddingClasses = {
|
||||
none: '',
|
||||
sm: 'p-3',
|
||||
md: 'p-6',
|
||||
lg: 'p-8'
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={`bg-white rounded-xl shadow-lg border border-gray-200 ${paddingClasses[padding]} ${className}`}>
|
||||
<div className={`
|
||||
bg-white rounded-xl border border-gray-200 shadow-sm
|
||||
${hover ? 'hover:shadow-md transition-shadow duration-200' : ''}
|
||||
${className}
|
||||
`}>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Card;
|
||||
export const CardHeader: React.FC<{ children: React.ReactNode; className?: string }> = ({
|
||||
children,
|
||||
className = ''
|
||||
}) => (
|
||||
<div className={`p-6 pb-4 ${className}`}>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
|
||||
export const CardContent: React.FC<{ children: React.ReactNode; className?: string }> = ({
|
||||
children,
|
||||
className = ''
|
||||
}) => (
|
||||
<div className={`p-6 pt-0 ${className}`}>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
|
||||
export const CardFooter: React.FC<{ children: React.ReactNode; className?: string }> = ({
|
||||
children,
|
||||
className = ''
|
||||
}) => (
|
||||
<div className={`p-6 pt-4 border-t border-gray-100 ${className}`}>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
|
||||
export default Card
|
||||
70
src/components/ChatInterface/ChatInterface.tsx
Normal file
70
src/components/ChatInterface/ChatInterface.tsx
Normal file
@@ -0,0 +1,70 @@
|
||||
import React, { useState } from 'react';
|
||||
import Message from '../Message';
|
||||
import Input from '../Input';
|
||||
import Button from '../Button';
|
||||
|
||||
export const ChatInterface: React.FC = () => {
|
||||
const [message, setMessage] = useState('');
|
||||
const [messages, setMessages] = useState([
|
||||
{ id: 1, text: '¡Hola! ¿En qué puedo ayudarte?', isOwn: false, timestamp: '10:00' },
|
||||
{ id: 2, text: 'Me gustaría información sobre mis inversiones', isOwn: true, timestamp: '10:01' },
|
||||
]);
|
||||
|
||||
const sendMessage = () => {
|
||||
if (message.trim()) {
|
||||
setMessages([
|
||||
...messages,
|
||||
{
|
||||
id: messages.length + 1,
|
||||
text: message,
|
||||
isOwn: true,
|
||||
timestamp: new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })
|
||||
}
|
||||
]);
|
||||
setMessage('');
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex flex-col h-full bg-maya-background rounded-lg border border-gray-200">
|
||||
{/* Chat Header */}
|
||||
<div className="bg-white px-4 py-3 border-b border-gray-200 rounded-t-lg">
|
||||
<div className="flex items-center space-x-3">
|
||||
<div className="w-3 h-3 bg-maya-primary rounded-full"></div>
|
||||
<h3 className="font-semibold text-gray-800">Soporte Banorte</h3>
|
||||
<div className="w-2 h-2 bg-maya-success rounded-full"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Messages Area */}
|
||||
<div className="flex-1 p-4 overflow-y-auto">
|
||||
{messages.map((msg) => (
|
||||
<Message
|
||||
key={msg.id}
|
||||
text={msg.text}
|
||||
isOwn={msg.isOwn}
|
||||
timestamp={msg.timestamp}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Input Area */}
|
||||
<div className="bg-white p-4 border-t border-gray-200 rounded-b-lg">
|
||||
<div className="flex space-x-2">
|
||||
<Input
|
||||
value={message}
|
||||
onChange={(e) => setMessage(e.target.value)}
|
||||
placeholder="Escribe tu mensaje..."
|
||||
className="flex-1"
|
||||
onKeyPress={(e) => e.key === 'Enter' && sendMessage()}
|
||||
/>
|
||||
<Button onClick={sendMessage} variant="primary">
|
||||
Enviar
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ChatInterface
|
||||
2
src/components/ChatInterface/index.ts
Normal file
2
src/components/ChatInterface/index.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export { default } from './ChatInterface';
|
||||
export type { ChatInterface } from './ChatInterface';
|
||||
39
src/components/Input/Input.tsx
Normal file
39
src/components/Input/Input.tsx
Normal file
@@ -0,0 +1,39 @@
|
||||
import React from 'react';
|
||||
|
||||
|
||||
export interface InputProps extends React.InputHTMLAttributes<HTMLInputElement> {
|
||||
label?: string;
|
||||
error?: string;
|
||||
helperText?: string;
|
||||
}
|
||||
|
||||
export const Input = React.forwardRef<HTMLInputElement, InputProps>(
|
||||
({ label, error, helperText, className = '', ...props }, ref) => {
|
||||
return (
|
||||
<div className="space-y-1">
|
||||
{label && (
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
{label}
|
||||
</label>
|
||||
)}
|
||||
<input
|
||||
ref={ref}
|
||||
className={`w-full px-3 py-2 border rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:ring-maya-primary focus:border-transparent transition-all ${
|
||||
error
|
||||
? 'border-red-300 bg-red-50'
|
||||
: 'border-gray-300 hover:border-gray-400'
|
||||
} ${className}`}
|
||||
{...props}
|
||||
/>
|
||||
{error && (
|
||||
<p className="text-sm text-maya-danger">{error}</p>
|
||||
)}
|
||||
{helperText && !error && (
|
||||
<p className="text-sm text-gray-500">{helperText}</p>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
export default Input
|
||||
2
src/components/Input/index.ts
Normal file
2
src/components/Input/index.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export { default } from './Input';
|
||||
export type { InputProps } from './Input';
|
||||
39
src/components/Message/Message.tsx
Normal file
39
src/components/Message/Message.tsx
Normal file
@@ -0,0 +1,39 @@
|
||||
import React from 'react';
|
||||
|
||||
export interface MessageProps {
|
||||
text: string;
|
||||
isOwn?: boolean;
|
||||
timestamp?: string;
|
||||
status?: 'sent' | 'delivered' | 'read';
|
||||
}
|
||||
|
||||
export const Message: React.FC<MessageProps> = ({
|
||||
text,
|
||||
isOwn = false,
|
||||
timestamp,
|
||||
status = 'sent'
|
||||
}) => {
|
||||
return (
|
||||
<div className={`flex ${isOwn ? 'justify-end' : 'justify-start'} mb-4`}>
|
||||
<div className={`max-w-xs lg:max-w-md px-4 py-2 rounded-2xl ${
|
||||
isOwn
|
||||
? 'bg-maya-primary text-white rounded-br-none'
|
||||
: 'bg-maya-accent text-gray-800 rounded-bl-none'
|
||||
}`}>
|
||||
<p className="text-sm">{text}</p>
|
||||
<div className={`flex items-center justify-end space-x-1 mt-1 ${
|
||||
isOwn ? 'text-red-100' : 'text-gray-500'
|
||||
}`}>
|
||||
<span className="text-xs">{timestamp}</span>
|
||||
{isOwn && (
|
||||
<span className="text-xs">
|
||||
{status === 'read' ? '✓✓' : status === 'delivered' ? '✓✓' : '✓'}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Message
|
||||
2
src/components/Message/index.ts
Normal file
2
src/components/Message/index.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export { default } from './Message';
|
||||
export type { MessageProps } from './Message';
|
||||
@@ -1,5 +1,11 @@
|
||||
// src/index.ts
|
||||
export { default as Button } from './Button';
|
||||
export { default as Card } from './Card';
|
||||
export { default as Input } from './Input';
|
||||
export { default as Message } from './Message';
|
||||
export { default as ChatInterface } from './ChatInterface';
|
||||
|
||||
export type { ButtonProps } from './Button';
|
||||
export type { CardProps } from './Card';
|
||||
export type { InputProps } from './Input';
|
||||
export type { MessageProps } from './Message';
|
||||
@@ -6,15 +6,13 @@ module.exports = {
|
||||
extend: {
|
||||
colors: {
|
||||
'maya': {
|
||||
primary: '#EF2945', // Rojo primario del logo Banorte
|
||||
secondary: '#684D3D', // Café secundario del logo
|
||||
neutral: {
|
||||
light: '#F5F5F5', // Fondo claro
|
||||
medium: '#C7C9C9', // Gris medio
|
||||
dark: '#6A6867', // Gris oscuro
|
||||
},
|
||||
success: '#10B981',
|
||||
danger: '#EF4444',
|
||||
primary: '#EA002A',
|
||||
secondary: '#684D3D',
|
||||
accent: '#C7C9C9',
|
||||
background: '#F5F5F5',
|
||||
dark: '#6A6867',
|
||||
success: '#10B981',
|
||||
danger: '#EF4444',
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user