indas-ui 0.1.0 → 0.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/dist/cjs/components/chat/index.js +20 -0
- package/dist/cjs/components/chat/multimodal-input.js +11 -4
- package/dist/cjs/components/forms/date-picker/DatePicker.js +2 -2
- package/dist/cjs/components/forms/file-attachment/FileAttachment.js +1 -1
- package/dist/cjs/components/layout/index.js +3 -1
- package/dist/cjs/components/layout/sidebar.js +1 -1
- package/dist/components/chat/index.d.ts +5 -0
- package/dist/components/chat/index.js +13 -0
- package/dist/components/chat/multimodal-input.d.ts +12 -1
- package/dist/components/chat/multimodal-input.js +12 -6
- package/dist/components/forms/date-picker/DatePicker.d.ts +5 -1
- package/dist/components/forms/date-picker/DatePicker.js +2 -2
- package/dist/components/layout/index.d.ts +2 -0
- package/dist/components/layout/index.js +1 -0
- package/package.json +187 -182
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
"use strict";
|
|
3
|
+
// Chat Components - Centralized exports
|
|
4
|
+
//
|
|
5
|
+
// Only the backend-agnostic pieces are exported. `Chat` itself is deliberately left out: it is
|
|
6
|
+
// bound to Estimo's stack (next-auth's useSession, the /api/synthia endpoints in lib/api/ai/chat,
|
|
7
|
+
// and Estimo's alert and language contexts), so a host app on a different backend cannot use it.
|
|
8
|
+
// `Messages` and `MultimodalInput` take everything they render as props and so travel anywhere.
|
|
9
|
+
//
|
|
10
|
+
// Hosts that want the full assembly compose it themselves: SidePanel (from 'indas-ui/layout') for
|
|
11
|
+
// the conversation rail, Messages for the transcript, MultimodalInput for the composer.
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.ChatPromptNavigator = exports.DEFAULT_CHAT_ACCEPT = exports.MultimodalInput = exports.Messages = void 0;
|
|
14
|
+
var ai_messages_1 = require("./ai-messages.js");
|
|
15
|
+
Object.defineProperty(exports, "Messages", { enumerable: true, get: function () { return ai_messages_1.Messages; } });
|
|
16
|
+
var multimodal_input_1 = require("./multimodal-input.js");
|
|
17
|
+
Object.defineProperty(exports, "MultimodalInput", { enumerable: true, get: function () { return multimodal_input_1.MultimodalInput; } });
|
|
18
|
+
Object.defineProperty(exports, "DEFAULT_CHAT_ACCEPT", { enumerable: true, get: function () { return multimodal_input_1.DEFAULT_CHAT_ACCEPT; } });
|
|
19
|
+
var chat_prompt_navigator_1 = require("./chat-prompt-navigator.js");
|
|
20
|
+
Object.defineProperty(exports, "ChatPromptNavigator", { enumerable: true, get: function () { return chat_prompt_navigator_1.ChatPromptNavigator; } });
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
"use strict";
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.DEFAULT_CHAT_ACCEPT = void 0;
|
|
4
5
|
exports.MultimodalInput = MultimodalInput;
|
|
5
6
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
6
7
|
/**
|
|
@@ -11,8 +12,12 @@ const react_1 = require("react");
|
|
|
11
12
|
const lucide_react_1 = require("lucide-react");
|
|
12
13
|
const utils_1 = require("../../lib/utils.js");
|
|
13
14
|
const LanguageContext_1 = require("../../contexts/LanguageContext.js");
|
|
14
|
-
|
|
15
|
-
|
|
15
|
+
/** What the paperclip offers when the host does not say: images, PDFs and documents. */
|
|
16
|
+
exports.DEFAULT_CHAT_ACCEPT = 'image/*,application/pdf,.doc,.docx,.txt';
|
|
17
|
+
function MultimodalInput({ onSubmit, onStop, isLoading = false, placeholder = 'Send a message...', allowFileUpload = true, accept = exports.DEFAULT_CHAT_ACCEPT, multiple = true, attachLabel = 'Attach file', compact = false, disabled = false, disabledReason }) {
|
|
18
|
+
// Optional: the composer is exported for host apps that have no LanguageProvider, and falls
|
|
19
|
+
// back to the English source text rather than throwing.
|
|
20
|
+
const { t } = (0, LanguageContext_1.useOptionalLanguage)();
|
|
16
21
|
const [input, setInput] = (0, react_1.useState)('');
|
|
17
22
|
const [files, setFiles] = (0, react_1.useState)([]);
|
|
18
23
|
const [isListening, setIsListening] = (0, react_1.useState)(false);
|
|
@@ -102,12 +107,14 @@ function MultimodalInput({ onSubmit, onStop, isLoading = false, placeholder = 'S
|
|
|
102
107
|
};
|
|
103
108
|
const handleFileSelect = (e) => {
|
|
104
109
|
const selectedFiles = Array.from(e.target.files || []);
|
|
105
|
-
setFiles(prev => [...prev, ...selectedFiles]);
|
|
110
|
+
setFiles(prev => (multiple ? [...prev, ...selectedFiles] : selectedFiles.slice(0, 1)));
|
|
111
|
+
// Cleared so picking the same file again (after removing it) still fires a change.
|
|
112
|
+
e.target.value = '';
|
|
106
113
|
};
|
|
107
114
|
const removeFile = (index) => {
|
|
108
115
|
setFiles(prev => prev.filter((_, i) => i !== index));
|
|
109
116
|
};
|
|
110
|
-
return ((0, jsx_runtime_1.jsx)("div", { className: (0, utils_1.cn)("bg-[rgb(var(--bg-surface))] shrink-0", compact ? "px-1 py-1" : "border-t border-[rgb(var(--bd-default))] px-4 py-2.5"), children: (0, jsx_runtime_1.jsxs)("div", { className: "max-w-3xl mx-auto", children: [disabled && disabledReason && ((0, jsx_runtime_1.jsxs)("div", { className: "mb-2 px-3 py-2 rounded-lg bg-amber-500/10 border border-amber-500/30 text-xs text-amber-700 dark:text-amber-400 flex items-center gap-2", children: [(0, jsx_runtime_1.jsxs)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className: "shrink-0", children: [(0, jsx_runtime_1.jsx)("circle", { cx: "12", cy: "12", r: "10" }), (0, jsx_runtime_1.jsx)("line", { x1: "12", y1: "8", x2: "12", y2: "12" }), (0, jsx_runtime_1.jsx)("line", { x1: "12", y1: "16", x2: "12.01", y2: "16" })] }), (0, jsx_runtime_1.jsx)("span", { children: disabledReason })] })), files.length > 0 && ((0, jsx_runtime_1.jsx)("div", { className: "flex flex-wrap gap-2 mb-3", children: files.map((file, index) => ((0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2 px-3 py-2 bg-[rgb(var(--bg-app))] border border-[rgb(var(--bd-default))] rounded-lg text-sm", children: [file.type.startsWith('image/') ? ((0, jsx_runtime_1.jsx)(lucide_react_1.Image, { className: "w-4 h-4 text-[rgb(var(--fg-muted))]" })) : ((0, jsx_runtime_1.jsx)(lucide_react_1.FileIcon, { className: "w-4 h-4 text-[rgb(var(--fg-muted))]" })), (0, jsx_runtime_1.jsx)("span", { className: "text-[rgb(var(--fg-default))] truncate max-w-[150px]", children: file.name }), (0, jsx_runtime_1.jsx)("button", { onClick: () => removeFile(index), className: "text-[rgb(var(--fg-muted))] hover:text-[rgb(var(--fg-default))] transition-colors", children: (0, jsx_runtime_1.jsx)(lucide_react_1.X, { className: "w-3 h-3" }) })] }, index))) })), (0, jsx_runtime_1.jsxs)("div", { className: (0, utils_1.cn)("relative flex items-center gap-1 bg-[rgb(var(--bg-app))]/60 backdrop-blur-xl border border-[rgb(var(--bd-default))] shadow-lg transition-all duration-250 focus-within:border-[rgb(var(--color-primary))] focus-within:shadow-[0_0_0_4px_rgb(var(--color-primary)/0.12),0_20px_25px_-5px_rgba(0,0,0,0.15)] focus-within:-translate-y-px", compact ? "rounded-xl p-1.5" : "rounded-2xl p-2.5"), children: [allowFileUpload && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("input", { ref: fileInputRef, type: "file", multiple:
|
|
117
|
+
return ((0, jsx_runtime_1.jsx)("div", { className: (0, utils_1.cn)("bg-[rgb(var(--bg-surface))] shrink-0", compact ? "px-1 py-1" : "border-t border-[rgb(var(--bd-default))] px-4 py-2.5"), children: (0, jsx_runtime_1.jsxs)("div", { className: "max-w-3xl mx-auto", children: [disabled && disabledReason && ((0, jsx_runtime_1.jsxs)("div", { className: "mb-2 px-3 py-2 rounded-lg bg-amber-500/10 border border-amber-500/30 text-xs text-amber-700 dark:text-amber-400 flex items-center gap-2", children: [(0, jsx_runtime_1.jsxs)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className: "shrink-0", children: [(0, jsx_runtime_1.jsx)("circle", { cx: "12", cy: "12", r: "10" }), (0, jsx_runtime_1.jsx)("line", { x1: "12", y1: "8", x2: "12", y2: "12" }), (0, jsx_runtime_1.jsx)("line", { x1: "12", y1: "16", x2: "12.01", y2: "16" })] }), (0, jsx_runtime_1.jsx)("span", { children: disabledReason })] })), files.length > 0 && ((0, jsx_runtime_1.jsx)("div", { className: "flex flex-wrap gap-2 mb-3", children: files.map((file, index) => ((0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2 px-3 py-2 bg-[rgb(var(--bg-app))] border border-[rgb(var(--bd-default))] rounded-lg text-sm", children: [file.type.startsWith('image/') ? ((0, jsx_runtime_1.jsx)(lucide_react_1.Image, { className: "w-4 h-4 text-[rgb(var(--fg-muted))]" })) : /\.(xlsx|xls|csv)$/i.test(file.name) ? ((0, jsx_runtime_1.jsx)(lucide_react_1.FileSpreadsheet, { className: "w-4 h-4 text-[rgb(var(--fg-muted))]" })) : ((0, jsx_runtime_1.jsx)(lucide_react_1.FileIcon, { className: "w-4 h-4 text-[rgb(var(--fg-muted))]" })), (0, jsx_runtime_1.jsx)("span", { className: "text-[rgb(var(--fg-default))] truncate max-w-[150px]", children: file.name }), (0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => removeFile(index), "aria-label": `Remove ${file.name}`, className: "text-[rgb(var(--fg-muted))] hover:text-[rgb(var(--fg-default))] transition-colors", children: (0, jsx_runtime_1.jsx)(lucide_react_1.X, { className: "w-3 h-3" }) })] }, index))) })), (0, jsx_runtime_1.jsxs)("div", { className: (0, utils_1.cn)("relative flex items-center gap-1 bg-[rgb(var(--bg-app))]/60 backdrop-blur-xl border border-[rgb(var(--bd-default))] shadow-lg transition-all duration-250 focus-within:border-[rgb(var(--color-primary))] focus-within:shadow-[0_0_0_4px_rgb(var(--color-primary)/0.12),0_20px_25px_-5px_rgba(0,0,0,0.15)] focus-within:-translate-y-px", compact ? "rounded-xl p-1.5" : "rounded-2xl p-2.5"), children: [allowFileUpload && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("input", { ref: fileInputRef, type: "file", multiple: multiple, accept: accept, onChange: handleFileSelect, className: "hidden" }), (0, jsx_runtime_1.jsx)("button", { onClick: () => fileInputRef.current?.click(), className: "shrink-0 !min-h-0 w-9 h-9 rounded-lg flex items-center justify-center transition-colors text-[rgb(var(--fg-muted))] hover:text-[rgb(var(--fg-default))] hover:bg-[rgb(var(--bg-subtle))]", "aria-label": attachLabel, title: attachLabel, children: (0, jsx_runtime_1.jsx)(lucide_react_1.Paperclip, { className: "w-4 h-4" }) })] })), (0, jsx_runtime_1.jsx)("textarea", { ref: textareaRef, "data-chat-input": true, value: input, onChange: (e) => setInput(e.target.value), onKeyDown: handleKeyDown, placeholder: disabled ? t('Conversation closed — start a new chat')
|
|
111
118
|
: isListening ? t('Listening...')
|
|
112
119
|
: placeholder, disabled: isListening || disabled, autoFocus: !disabled, rows: 1, className: (0, utils_1.cn)('flex-1 bg-transparent text-[rgb(var(--fg-default))] placeholder:text-[rgb(var(--fg-muted))]', 'resize-none outline-none text-sm', compact ? 'px-2 py-1.5 max-h-[120px]' : 'px-3 py-2.5 max-h-[200px]', 'overflow-y-auto', disabled && 'cursor-not-allowed') }), speechSupported && ((0, jsx_runtime_1.jsx)("button", { onClick: handleVoiceInput, className: (0, utils_1.cn)('shrink-0 !min-h-0 w-9 h-9 rounded-lg flex items-center justify-center transition-colors', isListening
|
|
113
120
|
? 'text-red-500 bg-red-500/10 animate-pulse'
|
|
@@ -48,7 +48,7 @@ const shared_utils_1 = require("./shared-utils.js");
|
|
|
48
48
|
// ============================================
|
|
49
49
|
// DatePicker Component (Single/Range dates without time)
|
|
50
50
|
// ============================================
|
|
51
|
-
function DatePicker({ value, onChange, mode = 'single', placeholder = 'Select date...', label, error, disabled = false, minDate, maxDate, className, showTime = false, showFromTo = false, returnFormat = 'date', inline = false, iconOnly = false, popoverAlign, presets }) {
|
|
51
|
+
function DatePicker({ id, 'aria-label': ariaLabel, value, onChange, mode = 'single', placeholder = 'Select date...', label, error, disabled = false, minDate, maxDate, className, showTime = false, showFromTo = false, returnFormat = 'date', inline = false, iconOnly = false, popoverAlign, presets }) {
|
|
52
52
|
const [isOpen, setIsOpen] = React.useState(false);
|
|
53
53
|
const [currentMonth, setCurrentMonth] = React.useState(new Date());
|
|
54
54
|
const [secondMonth, setSecondMonth] = React.useState(() => {
|
|
@@ -703,7 +703,7 @@ function DatePicker({ value, onChange, mode = 'single', placeholder = 'Select da
|
|
|
703
703
|
? `Date filter: ${selectedRange.from ? new Date(selectedRange.from).toLocaleDateString('en-GB', { day: '2-digit', month: 'short', year: 'numeric' }) : ''}${selectedRange.to ? ` – ${new Date(selectedRange.to).toLocaleDateString('en-GB', { day: '2-digit', month: 'short', year: 'numeric' })}` : ''}`
|
|
704
704
|
: 'Select date range', children: [(0, jsx_runtime_1.jsx)(lucide_react_1.CalendarDays, { className: "h-3.5 w-3.5 flex-shrink-0" }), (0, jsx_runtime_1.jsx)("span", { className: "hidden sm:inline text-xs", children: selectedRange.from || selectedRange.to
|
|
705
705
|
? `${selectedRange.from ? new Date(selectedRange.from).toLocaleDateString('en-GB', { day: '2-digit', month: 'short' }) : ''}${selectedRange.to ? ` – ${new Date(selectedRange.to).toLocaleDateString('en-GB', { day: '2-digit', month: 'short' })}` : ''}`
|
|
706
|
-
: 'Date' }), (selectedRange.from || selectedRange.to) && ((0, jsx_runtime_1.jsx)("span", { className: "absolute -top-0.5 -right-0.5 h-1.5 w-1.5 rounded-full bg-[rgb(var(--color-primary))] ring-1 ring-[rgb(var(--bg-surface))]" }))] })) : ((0, jsx_runtime_1.jsx)("div", { className: "relative", ref: inputWrapperRef, children: (0, jsx_runtime_1.jsx)(ui_2.Input, { value: inputValue, onChange: handleInputChange, onBlur: handleInputBlur, onKeyDown: handleInputKeyDown, placeholder: getPlaceholder(), disabled: disabled, error: error, className: (0, utils_1.cn)('pl-2 pr-9 text-xs w-full', error && 'border-red-300'), onFocus: () => !disabled && setIsOpen(true), rightIcon: lucide_react_1.Calendar, onRightIconClick: () => !disabled && setIsOpen(!isOpen) }) })) }), (0, jsx_runtime_1.jsx)(Popover.Portal, { container: typeof document !== 'undefined' ? document.body : undefined, children: (0, jsx_runtime_1.jsxs)(Popover.Content, { ref: calendarRef, className: (0, utils_1.cn)("z-[300] bg-[rgb(var(--bg-surface))] rounded-xl shadow-2xl border border-[rgb(var(--bd-default))] backdrop-blur-sm", "data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95", "data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95", "data-[side=bottom]:slide-in-from-top-2 data-[side=top]:slide-in-from-bottom-2", mode === 'range' ? 'w-[95vw] sm:w-auto sm:min-w-[580px] p-2' : 'w-[95vw] sm:w-auto sm:min-w-[280px] p-3', 'max-w-[calc(100vw-2rem)]'), side: "bottom", align: popoverAlign ?? (mode === 'range' ? 'end' : 'start'), sideOffset: 8, avoidCollisions: true, collisionPadding: 16, sticky: "always", onOpenAutoFocus: (e) => e.preventDefault(), onKeyDown: handleCalendarKeyDown, tabIndex: -1, onInteractOutside: (e) => {
|
|
706
|
+
: 'Date' }), (selectedRange.from || selectedRange.to) && ((0, jsx_runtime_1.jsx)("span", { className: "absolute -top-0.5 -right-0.5 h-1.5 w-1.5 rounded-full bg-[rgb(var(--color-primary))] ring-1 ring-[rgb(var(--bg-surface))]" }))] })) : ((0, jsx_runtime_1.jsx)("div", { className: "relative", ref: inputWrapperRef, onClick: (e) => e.preventDefault(), children: (0, jsx_runtime_1.jsx)(ui_2.Input, { id: id, "aria-label": ariaLabel, value: inputValue, onChange: handleInputChange, onBlur: handleInputBlur, onKeyDown: handleInputKeyDown, placeholder: getPlaceholder(), disabled: disabled, error: error, className: (0, utils_1.cn)('pl-2 pr-9 text-xs w-full', error && 'border-red-300'), onFocus: () => !disabled && setIsOpen(true), rightIcon: lucide_react_1.Calendar, onRightIconClick: () => !disabled && setIsOpen(!isOpen) }) })) }), (0, jsx_runtime_1.jsx)(Popover.Portal, { container: typeof document !== 'undefined' ? document.body : undefined, children: (0, jsx_runtime_1.jsxs)(Popover.Content, { ref: calendarRef, className: (0, utils_1.cn)("z-[300] bg-[rgb(var(--bg-surface))] rounded-xl shadow-2xl border border-[rgb(var(--bd-default))] backdrop-blur-sm", "data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95", "data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95", "data-[side=bottom]:slide-in-from-top-2 data-[side=top]:slide-in-from-bottom-2", mode === 'range' ? 'w-[95vw] sm:w-auto sm:min-w-[580px] p-2' : 'w-[95vw] sm:w-auto sm:min-w-[280px] p-3', 'max-w-[calc(100vw-2rem)]'), side: "bottom", align: popoverAlign ?? (mode === 'range' ? 'end' : 'start'), sideOffset: 8, avoidCollisions: true, collisionPadding: 16, sticky: "always", onOpenAutoFocus: (e) => e.preventDefault(), onKeyDown: handleCalendarKeyDown, tabIndex: -1, onInteractOutside: (e) => {
|
|
707
707
|
// Prevent closing when interacting with nested Radix portals (like Dropdowns)
|
|
708
708
|
const target = e.target;
|
|
709
709
|
if (target?.closest('[data-radix-popper-content-wrapper]')) {
|
|
@@ -40,7 +40,7 @@ const React = __importStar(require("react"));
|
|
|
40
40
|
const react_dom_1 = require("react-dom");
|
|
41
41
|
const framer_motion_1 = require("framer-motion");
|
|
42
42
|
const react_image_crop_1 = __importStar(require("react-image-crop"));
|
|
43
|
-
|
|
43
|
+
|
|
44
44
|
const lucide_react_1 = require("lucide-react");
|
|
45
45
|
const utils_1 = require("../../../lib/utils.js");
|
|
46
46
|
const ui_1 = require("../../ui/index.js");
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
"use strict";
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
-
exports.FloatingActionButton = exports.Grid = exports.Page = exports.AppShell = exports.CompactFooter = exports.Footer = exports.DynamicSidebar = void 0;
|
|
4
|
+
exports.SidePanel = exports.FloatingActionButton = exports.Grid = exports.Page = exports.AppShell = exports.CompactFooter = exports.Footer = exports.DynamicSidebar = void 0;
|
|
5
5
|
// Layout Components - Centralized exports
|
|
6
6
|
var sidebar_1 = require("./sidebar.js");
|
|
7
7
|
Object.defineProperty(exports, "DynamicSidebar", { enumerable: true, get: function () { return sidebar_1.DynamicSidebar; } });
|
|
@@ -14,3 +14,5 @@ Object.defineProperty(exports, "Page", { enumerable: true, get: function () { re
|
|
|
14
14
|
Object.defineProperty(exports, "Grid", { enumerable: true, get: function () { return app_shell_1.Grid; } });
|
|
15
15
|
var floating_action_button_1 = require("./floating-action-button.js");
|
|
16
16
|
Object.defineProperty(exports, "FloatingActionButton", { enumerable: true, get: function () { return floating_action_button_1.FloatingActionButton; } });
|
|
17
|
+
var side_panel_1 = require("./side-panel.js");
|
|
18
|
+
Object.defineProperty(exports, "SidePanel", { enumerable: true, get: function () { return side_panel_1.SidePanel; } });
|
|
@@ -48,7 +48,7 @@ const useTranslation_1 = require("../../hooks/useTranslation.js");
|
|
|
48
48
|
const ui_1 = require("../ui/index.js");
|
|
49
49
|
const api_1 = require("../../lib/api/index.js");
|
|
50
50
|
const utils_2 = require("../../lib/utils.js");
|
|
51
|
-
|
|
51
|
+
|
|
52
52
|
const react_dom_1 = require("react-dom");
|
|
53
53
|
const SidebarContextMenu_1 = require("./SidebarContextMenu.js");
|
|
54
54
|
const SidebarPreferencesContext_1 = require("../../contexts/SidebarPreferencesContext.js");
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { Messages } from './ai-messages.js';
|
|
2
|
+
export type { SelectableItem } from './ai-messages.js';
|
|
3
|
+
export { MultimodalInput, DEFAULT_CHAT_ACCEPT } from './multimodal-input.js';
|
|
4
|
+
export { ChatPromptNavigator } from './chat-prompt-navigator.js';
|
|
5
|
+
export type { Message, Conversation, UIDataEntry, UIDataItem, TokenUsage } from '../../lib/api/ai/types.js';
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
// Chat Components - Centralized exports
|
|
3
|
+
//
|
|
4
|
+
// Only the backend-agnostic pieces are exported. `Chat` itself is deliberately left out: it is
|
|
5
|
+
// bound to Estimo's stack (next-auth's useSession, the /api/synthia endpoints in lib/api/ai/chat,
|
|
6
|
+
// and Estimo's alert and language contexts), so a host app on a different backend cannot use it.
|
|
7
|
+
// `Messages` and `MultimodalInput` take everything they render as props and so travel anywhere.
|
|
8
|
+
//
|
|
9
|
+
// Hosts that want the full assembly compose it themselves: SidePanel (from 'indas-ui/layout') for
|
|
10
|
+
// the conversation rail, Messages for the transcript, MultimodalInput for the composer.
|
|
11
|
+
export { Messages } from './ai-messages.js';
|
|
12
|
+
export { MultimodalInput, DEFAULT_CHAT_ACCEPT } from './multimodal-input.js';
|
|
13
|
+
export { ChatPromptNavigator } from './chat-prompt-navigator.js';
|
|
@@ -1,12 +1,23 @@
|
|
|
1
|
+
/** What the paperclip offers when the host does not say: images, PDFs and documents. */
|
|
2
|
+
export declare const DEFAULT_CHAT_ACCEPT = "image/*,application/pdf,.doc,.docx,.txt";
|
|
1
3
|
interface MultimodalInputProps {
|
|
2
4
|
onSubmit: (text: string, files?: File[]) => void;
|
|
3
5
|
onStop?: () => void;
|
|
4
6
|
isLoading?: boolean;
|
|
5
7
|
placeholder?: string;
|
|
6
8
|
allowFileUpload?: boolean;
|
|
9
|
+
/**
|
|
10
|
+
* File types the paperclip offers, as an `<input accept>` list. Defaults to
|
|
11
|
+
* DEFAULT_CHAT_ACCEPT; a host that reads spreadsheets adds `.xlsx,.xls,.csv`.
|
|
12
|
+
*/
|
|
13
|
+
accept?: string;
|
|
14
|
+
/** Allow several files at once. Default true; false keeps one attachment, replacing the last. */
|
|
15
|
+
multiple?: boolean;
|
|
16
|
+
/** Screen-reader name of the paperclip. Default "Attach file". */
|
|
17
|
+
attachLabel?: string;
|
|
7
18
|
compact?: boolean;
|
|
8
19
|
disabled?: boolean;
|
|
9
20
|
disabledReason?: string;
|
|
10
21
|
}
|
|
11
|
-
export declare function MultimodalInput({ onSubmit, onStop, isLoading, placeholder, allowFileUpload, compact, disabled, disabledReason }: MultimodalInputProps): import("react").JSX.Element;
|
|
22
|
+
export declare function MultimodalInput({ onSubmit, onStop, isLoading, placeholder, allowFileUpload, accept, multiple, attachLabel, compact, disabled, disabledReason }: MultimodalInputProps): import("react").JSX.Element;
|
|
12
23
|
export {};
|
|
@@ -5,11 +5,15 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
|
|
|
5
5
|
* Chat input with auto-expanding textarea, file upload, and voice input
|
|
6
6
|
*/
|
|
7
7
|
import { useState, useRef, useEffect, useCallback } from 'react';
|
|
8
|
-
import { Send, Paperclip, Mic, MicOff, X, FileIcon, Image as ImageIcon } from 'lucide-react';
|
|
8
|
+
import { Send, Paperclip, Mic, MicOff, X, FileIcon, FileSpreadsheet, Image as ImageIcon } from 'lucide-react';
|
|
9
9
|
import { cn } from '../../lib/utils.js';
|
|
10
|
-
import {
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
import { useOptionalLanguage } from '../../contexts/LanguageContext.js';
|
|
11
|
+
/** What the paperclip offers when the host does not say: images, PDFs and documents. */
|
|
12
|
+
export const DEFAULT_CHAT_ACCEPT = 'image/*,application/pdf,.doc,.docx,.txt';
|
|
13
|
+
export function MultimodalInput({ onSubmit, onStop, isLoading = false, placeholder = 'Send a message...', allowFileUpload = true, accept = DEFAULT_CHAT_ACCEPT, multiple = true, attachLabel = 'Attach file', compact = false, disabled = false, disabledReason }) {
|
|
14
|
+
// Optional: the composer is exported for host apps that have no LanguageProvider, and falls
|
|
15
|
+
// back to the English source text rather than throwing.
|
|
16
|
+
const { t } = useOptionalLanguage();
|
|
13
17
|
const [input, setInput] = useState('');
|
|
14
18
|
const [files, setFiles] = useState([]);
|
|
15
19
|
const [isListening, setIsListening] = useState(false);
|
|
@@ -99,12 +103,14 @@ export function MultimodalInput({ onSubmit, onStop, isLoading = false, placehold
|
|
|
99
103
|
};
|
|
100
104
|
const handleFileSelect = (e) => {
|
|
101
105
|
const selectedFiles = Array.from(e.target.files || []);
|
|
102
|
-
setFiles(prev => [...prev, ...selectedFiles]);
|
|
106
|
+
setFiles(prev => (multiple ? [...prev, ...selectedFiles] : selectedFiles.slice(0, 1)));
|
|
107
|
+
// Cleared so picking the same file again (after removing it) still fires a change.
|
|
108
|
+
e.target.value = '';
|
|
103
109
|
};
|
|
104
110
|
const removeFile = (index) => {
|
|
105
111
|
setFiles(prev => prev.filter((_, i) => i !== index));
|
|
106
112
|
};
|
|
107
|
-
return (_jsx("div", { className: cn("bg-[rgb(var(--bg-surface))] shrink-0", compact ? "px-1 py-1" : "border-t border-[rgb(var(--bd-default))] px-4 py-2.5"), children: _jsxs("div", { className: "max-w-3xl mx-auto", children: [disabled && disabledReason && (_jsxs("div", { className: "mb-2 px-3 py-2 rounded-lg bg-amber-500/10 border border-amber-500/30 text-xs text-amber-700 dark:text-amber-400 flex items-center gap-2", children: [_jsxs("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className: "shrink-0", children: [_jsx("circle", { cx: "12", cy: "12", r: "10" }), _jsx("line", { x1: "12", y1: "8", x2: "12", y2: "12" }), _jsx("line", { x1: "12", y1: "16", x2: "12.01", y2: "16" })] }), _jsx("span", { children: disabledReason })] })), files.length > 0 && (_jsx("div", { className: "flex flex-wrap gap-2 mb-3", children: files.map((file, index) => (_jsxs("div", { className: "flex items-center gap-2 px-3 py-2 bg-[rgb(var(--bg-app))] border border-[rgb(var(--bd-default))] rounded-lg text-sm", children: [file.type.startsWith('image/') ? (_jsx(ImageIcon, { className: "w-4 h-4 text-[rgb(var(--fg-muted))]" })) : (_jsx(FileIcon, { className: "w-4 h-4 text-[rgb(var(--fg-muted))]" })), _jsx("span", { className: "text-[rgb(var(--fg-default))] truncate max-w-[150px]", children: file.name }), _jsx("button", { onClick: () => removeFile(index), className: "text-[rgb(var(--fg-muted))] hover:text-[rgb(var(--fg-default))] transition-colors", children: _jsx(X, { className: "w-3 h-3" }) })] }, index))) })), _jsxs("div", { className: cn("relative flex items-center gap-1 bg-[rgb(var(--bg-app))]/60 backdrop-blur-xl border border-[rgb(var(--bd-default))] shadow-lg transition-all duration-250 focus-within:border-[rgb(var(--color-primary))] focus-within:shadow-[0_0_0_4px_rgb(var(--color-primary)/0.12),0_20px_25px_-5px_rgba(0,0,0,0.15)] focus-within:-translate-y-px", compact ? "rounded-xl p-1.5" : "rounded-2xl p-2.5"), children: [allowFileUpload && (_jsxs(_Fragment, { children: [_jsx("input", { ref: fileInputRef, type: "file", multiple:
|
|
113
|
+
return (_jsx("div", { className: cn("bg-[rgb(var(--bg-surface))] shrink-0", compact ? "px-1 py-1" : "border-t border-[rgb(var(--bd-default))] px-4 py-2.5"), children: _jsxs("div", { className: "max-w-3xl mx-auto", children: [disabled && disabledReason && (_jsxs("div", { className: "mb-2 px-3 py-2 rounded-lg bg-amber-500/10 border border-amber-500/30 text-xs text-amber-700 dark:text-amber-400 flex items-center gap-2", children: [_jsxs("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className: "shrink-0", children: [_jsx("circle", { cx: "12", cy: "12", r: "10" }), _jsx("line", { x1: "12", y1: "8", x2: "12", y2: "12" }), _jsx("line", { x1: "12", y1: "16", x2: "12.01", y2: "16" })] }), _jsx("span", { children: disabledReason })] })), files.length > 0 && (_jsx("div", { className: "flex flex-wrap gap-2 mb-3", children: files.map((file, index) => (_jsxs("div", { className: "flex items-center gap-2 px-3 py-2 bg-[rgb(var(--bg-app))] border border-[rgb(var(--bd-default))] rounded-lg text-sm", children: [file.type.startsWith('image/') ? (_jsx(ImageIcon, { className: "w-4 h-4 text-[rgb(var(--fg-muted))]" })) : /\.(xlsx|xls|csv)$/i.test(file.name) ? (_jsx(FileSpreadsheet, { className: "w-4 h-4 text-[rgb(var(--fg-muted))]" })) : (_jsx(FileIcon, { className: "w-4 h-4 text-[rgb(var(--fg-muted))]" })), _jsx("span", { className: "text-[rgb(var(--fg-default))] truncate max-w-[150px]", children: file.name }), _jsx("button", { type: "button", onClick: () => removeFile(index), "aria-label": `Remove ${file.name}`, className: "text-[rgb(var(--fg-muted))] hover:text-[rgb(var(--fg-default))] transition-colors", children: _jsx(X, { className: "w-3 h-3" }) })] }, index))) })), _jsxs("div", { className: cn("relative flex items-center gap-1 bg-[rgb(var(--bg-app))]/60 backdrop-blur-xl border border-[rgb(var(--bd-default))] shadow-lg transition-all duration-250 focus-within:border-[rgb(var(--color-primary))] focus-within:shadow-[0_0_0_4px_rgb(var(--color-primary)/0.12),0_20px_25px_-5px_rgba(0,0,0,0.15)] focus-within:-translate-y-px", compact ? "rounded-xl p-1.5" : "rounded-2xl p-2.5"), children: [allowFileUpload && (_jsxs(_Fragment, { children: [_jsx("input", { ref: fileInputRef, type: "file", multiple: multiple, accept: accept, onChange: handleFileSelect, className: "hidden" }), _jsx("button", { onClick: () => fileInputRef.current?.click(), className: "shrink-0 !min-h-0 w-9 h-9 rounded-lg flex items-center justify-center transition-colors text-[rgb(var(--fg-muted))] hover:text-[rgb(var(--fg-default))] hover:bg-[rgb(var(--bg-subtle))]", "aria-label": attachLabel, title: attachLabel, children: _jsx(Paperclip, { className: "w-4 h-4" }) })] })), _jsx("textarea", { ref: textareaRef, "data-chat-input": true, value: input, onChange: (e) => setInput(e.target.value), onKeyDown: handleKeyDown, placeholder: disabled ? t('Conversation closed — start a new chat')
|
|
108
114
|
: isListening ? t('Listening...')
|
|
109
115
|
: placeholder, disabled: isListening || disabled, autoFocus: !disabled, rows: 1, className: cn('flex-1 bg-transparent text-[rgb(var(--fg-default))] placeholder:text-[rgb(var(--fg-muted))]', 'resize-none outline-none text-sm', compact ? 'px-2 py-1.5 max-h-[120px]' : 'px-3 py-2.5 max-h-[200px]', 'overflow-y-auto', disabled && 'cursor-not-allowed') }), speechSupported && (_jsx("button", { onClick: handleVoiceInput, className: cn('shrink-0 !min-h-0 w-9 h-9 rounded-lg flex items-center justify-center transition-colors', isListening
|
|
110
116
|
? 'text-red-500 bg-red-500/10 animate-pulse'
|
|
@@ -4,6 +4,10 @@ export interface DateRange {
|
|
|
4
4
|
to?: Date;
|
|
5
5
|
}
|
|
6
6
|
export interface DatePickerProps {
|
|
7
|
+
/** Forwarded to the text input so a <label htmlFor> can target it. */
|
|
8
|
+
id?: string;
|
|
9
|
+
/** Accessible name for the input when no visible label is rendered. */
|
|
10
|
+
'aria-label'?: string;
|
|
7
11
|
value?: Date | DateRange | string;
|
|
8
12
|
onChange?: (date: Date | DateRange | string | undefined) => void;
|
|
9
13
|
mode?: 'single' | 'range';
|
|
@@ -28,4 +32,4 @@ export interface DatePickerProps {
|
|
|
28
32
|
value: Date | DateRange;
|
|
29
33
|
}>;
|
|
30
34
|
}
|
|
31
|
-
export declare function DatePicker({ value, onChange, mode, placeholder, label, error, disabled, minDate, maxDate, className, showTime, showFromTo, returnFormat, inline, iconOnly, popoverAlign, presets }: DatePickerProps): React.JSX.Element;
|
|
35
|
+
export declare function DatePicker({ id, 'aria-label': ariaLabel, value, onChange, mode, placeholder, label, error, disabled, minDate, maxDate, className, showTime, showFromTo, returnFormat, inline, iconOnly, popoverAlign, presets }: DatePickerProps): React.JSX.Element;
|
|
@@ -12,7 +12,7 @@ import { MONTHS, WEEKDAYS, PERIOD_OPTIONS, TIME_OPTIONS, getDaysInMonth, getFirs
|
|
|
12
12
|
// ============================================
|
|
13
13
|
// DatePicker Component (Single/Range dates without time)
|
|
14
14
|
// ============================================
|
|
15
|
-
export function DatePicker({ value, onChange, mode = 'single', placeholder = 'Select date...', label, error, disabled = false, minDate, maxDate, className, showTime = false, showFromTo = false, returnFormat = 'date', inline = false, iconOnly = false, popoverAlign, presets }) {
|
|
15
|
+
export function DatePicker({ id, 'aria-label': ariaLabel, value, onChange, mode = 'single', placeholder = 'Select date...', label, error, disabled = false, minDate, maxDate, className, showTime = false, showFromTo = false, returnFormat = 'date', inline = false, iconOnly = false, popoverAlign, presets }) {
|
|
16
16
|
const [isOpen, setIsOpen] = React.useState(false);
|
|
17
17
|
const [currentMonth, setCurrentMonth] = React.useState(new Date());
|
|
18
18
|
const [secondMonth, setSecondMonth] = React.useState(() => {
|
|
@@ -667,7 +667,7 @@ export function DatePicker({ value, onChange, mode = 'single', placeholder = 'Se
|
|
|
667
667
|
? `Date filter: ${selectedRange.from ? new Date(selectedRange.from).toLocaleDateString('en-GB', { day: '2-digit', month: 'short', year: 'numeric' }) : ''}${selectedRange.to ? ` – ${new Date(selectedRange.to).toLocaleDateString('en-GB', { day: '2-digit', month: 'short', year: 'numeric' })}` : ''}`
|
|
668
668
|
: 'Select date range', children: [_jsx(CalendarDays, { className: "h-3.5 w-3.5 flex-shrink-0" }), _jsx("span", { className: "hidden sm:inline text-xs", children: selectedRange.from || selectedRange.to
|
|
669
669
|
? `${selectedRange.from ? new Date(selectedRange.from).toLocaleDateString('en-GB', { day: '2-digit', month: 'short' }) : ''}${selectedRange.to ? ` – ${new Date(selectedRange.to).toLocaleDateString('en-GB', { day: '2-digit', month: 'short' })}` : ''}`
|
|
670
|
-
: 'Date' }), (selectedRange.from || selectedRange.to) && (_jsx("span", { className: "absolute -top-0.5 -right-0.5 h-1.5 w-1.5 rounded-full bg-[rgb(var(--color-primary))] ring-1 ring-[rgb(var(--bg-surface))]" }))] })) : (_jsx("div", { className: "relative", ref: inputWrapperRef, children: _jsx(Input, { value: inputValue, onChange: handleInputChange, onBlur: handleInputBlur, onKeyDown: handleInputKeyDown, placeholder: getPlaceholder(), disabled: disabled, error: error, className: cn('pl-2 pr-9 text-xs w-full', error && 'border-red-300'), onFocus: () => !disabled && setIsOpen(true), rightIcon: Calendar, onRightIconClick: () => !disabled && setIsOpen(!isOpen) }) })) }), _jsx(Popover.Portal, { container: typeof document !== 'undefined' ? document.body : undefined, children: _jsxs(Popover.Content, { ref: calendarRef, className: cn("z-[300] bg-[rgb(var(--bg-surface))] rounded-xl shadow-2xl border border-[rgb(var(--bd-default))] backdrop-blur-sm", "data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95", "data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95", "data-[side=bottom]:slide-in-from-top-2 data-[side=top]:slide-in-from-bottom-2", mode === 'range' ? 'w-[95vw] sm:w-auto sm:min-w-[580px] p-2' : 'w-[95vw] sm:w-auto sm:min-w-[280px] p-3', 'max-w-[calc(100vw-2rem)]'), side: "bottom", align: popoverAlign ?? (mode === 'range' ? 'end' : 'start'), sideOffset: 8, avoidCollisions: true, collisionPadding: 16, sticky: "always", onOpenAutoFocus: (e) => e.preventDefault(), onKeyDown: handleCalendarKeyDown, tabIndex: -1, onInteractOutside: (e) => {
|
|
670
|
+
: 'Date' }), (selectedRange.from || selectedRange.to) && (_jsx("span", { className: "absolute -top-0.5 -right-0.5 h-1.5 w-1.5 rounded-full bg-[rgb(var(--color-primary))] ring-1 ring-[rgb(var(--bg-surface))]" }))] })) : (_jsx("div", { className: "relative", ref: inputWrapperRef, onClick: (e) => e.preventDefault(), children: _jsx(Input, { id: id, "aria-label": ariaLabel, value: inputValue, onChange: handleInputChange, onBlur: handleInputBlur, onKeyDown: handleInputKeyDown, placeholder: getPlaceholder(), disabled: disabled, error: error, className: cn('pl-2 pr-9 text-xs w-full', error && 'border-red-300'), onFocus: () => !disabled && setIsOpen(true), rightIcon: Calendar, onRightIconClick: () => !disabled && setIsOpen(!isOpen) }) })) }), _jsx(Popover.Portal, { container: typeof document !== 'undefined' ? document.body : undefined, children: _jsxs(Popover.Content, { ref: calendarRef, className: cn("z-[300] bg-[rgb(var(--bg-surface))] rounded-xl shadow-2xl border border-[rgb(var(--bd-default))] backdrop-blur-sm", "data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95", "data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95", "data-[side=bottom]:slide-in-from-top-2 data-[side=top]:slide-in-from-bottom-2", mode === 'range' ? 'w-[95vw] sm:w-auto sm:min-w-[580px] p-2' : 'w-[95vw] sm:w-auto sm:min-w-[280px] p-3', 'max-w-[calc(100vw-2rem)]'), side: "bottom", align: popoverAlign ?? (mode === 'range' ? 'end' : 'start'), sideOffset: 8, avoidCollisions: true, collisionPadding: 16, sticky: "always", onOpenAutoFocus: (e) => e.preventDefault(), onKeyDown: handleCalendarKeyDown, tabIndex: -1, onInteractOutside: (e) => {
|
|
671
671
|
// Prevent closing when interacting with nested Radix portals (like Dropdowns)
|
|
672
672
|
const target = e.target;
|
|
673
673
|
if (target?.closest('[data-radix-popper-content-wrapper]')) {
|
|
@@ -6,3 +6,5 @@ export { AppShell, Page, Grid } from './app-shell.js';
|
|
|
6
6
|
export type { AppShellProps, PageProps, GridProps } from './app-shell.js';
|
|
7
7
|
export { FloatingActionButton } from './floating-action-button.js';
|
|
8
8
|
export type { FABAction } from './floating-action-button.js';
|
|
9
|
+
export { SidePanel } from './side-panel.js';
|
|
10
|
+
export type { SidePanelProps, SidePanelCategory, SidePanelItem } from './side-panel.js';
|
package/package.json
CHANGED
|
@@ -1,182 +1,187 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "indas-ui",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "Indas UI — React component library for business apps: Tailwind design tokens, Radix primitives, Lucide icons, DataGrid, dashboards and charts.",
|
|
5
|
-
"license": "MIT",
|
|
6
|
-
"author": "Indas Analytics Pvt Ltd",
|
|
7
|
-
"contributors": [
|
|
8
|
-
"Shreyansh Patidar",
|
|
9
|
-
"Abhinav"
|
|
10
|
-
],
|
|
11
|
-
"repository": {
|
|
12
|
-
"type": "git",
|
|
13
|
-
"url": "git+https://github.com/ShreyanshPatidar/indas-ui.git",
|
|
14
|
-
"directory": "packages/indas-ui"
|
|
15
|
-
},
|
|
16
|
-
"homepage": "https://shreyanshpatidar.github.io/indas-ui",
|
|
17
|
-
"type": "module",
|
|
18
|
-
"main": "./dist/cjs/index.js",
|
|
19
|
-
"module": "./dist/index.js",
|
|
20
|
-
"types": "./dist/index.d.ts",
|
|
21
|
-
"exports": {
|
|
22
|
-
".": {
|
|
23
|
-
"types": "./dist/index.d.ts",
|
|
24
|
-
"import": "./dist/index.js",
|
|
25
|
-
"require": "./dist/cjs/index.js"
|
|
26
|
-
},
|
|
27
|
-
"./ui": {
|
|
28
|
-
"types": "./dist/components/ui/index.d.ts",
|
|
29
|
-
"import": "./dist/components/ui/index.js",
|
|
30
|
-
"require": "./dist/cjs/components/ui/index.js"
|
|
31
|
-
},
|
|
32
|
-
"./layout": {
|
|
33
|
-
"types": "./dist/components/layout/index.d.ts",
|
|
34
|
-
"import": "./dist/components/layout/index.js",
|
|
35
|
-
"require": "./dist/cjs/components/layout/index.js"
|
|
36
|
-
},
|
|
37
|
-
"./datagrid": {
|
|
38
|
-
"types": "./dist/components/datagrid/index.d.ts",
|
|
39
|
-
"import": "./dist/components/datagrid/index.js",
|
|
40
|
-
"require": "./dist/cjs/components/datagrid/index.js"
|
|
41
|
-
},
|
|
42
|
-
"./dashboard": {
|
|
43
|
-
"types": "./dist/components/dashboard/index.d.ts",
|
|
44
|
-
"import": "./dist/components/dashboard/index.js",
|
|
45
|
-
"require": "./dist/cjs/components/dashboard/index.js"
|
|
46
|
-
},
|
|
47
|
-
"./charts": {
|
|
48
|
-
"types": "./dist/components/dashboard/charts/index.d.ts",
|
|
49
|
-
"import": "./dist/components/dashboard/charts/index.js",
|
|
50
|
-
"require": "./dist/cjs/components/dashboard/charts/index.js"
|
|
51
|
-
},
|
|
52
|
-
"./kpi": {
|
|
53
|
-
"types": "./dist/components/dashboard/kpi/index.d.ts",
|
|
54
|
-
"import": "./dist/components/dashboard/kpi/index.js",
|
|
55
|
-
"require": "./dist/cjs/components/dashboard/kpi/index.js"
|
|
56
|
-
},
|
|
57
|
-
"./modals": {
|
|
58
|
-
"types": "./dist/components/modals/index.d.ts",
|
|
59
|
-
"import": "./dist/components/modals/index.js",
|
|
60
|
-
"require": "./dist/cjs/components/modals/index.js"
|
|
61
|
-
},
|
|
62
|
-
"./forms": {
|
|
63
|
-
"types": "./dist/components/forms/index.d.ts",
|
|
64
|
-
"import": "./dist/components/forms/index.js",
|
|
65
|
-
"require": "./dist/cjs/components/forms/index.js"
|
|
66
|
-
},
|
|
67
|
-
"./
|
|
68
|
-
"types": "./dist/
|
|
69
|
-
"import": "./dist/
|
|
70
|
-
"require": "./dist/cjs/
|
|
71
|
-
},
|
|
72
|
-
"./
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
"dist"
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
"
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
"
|
|
90
|
-
"
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
"
|
|
95
|
-
"
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
"@
|
|
99
|
-
"@
|
|
100
|
-
"@
|
|
101
|
-
"@
|
|
102
|
-
"@
|
|
103
|
-
"@radix-ui/react-
|
|
104
|
-
"@radix-ui/react-
|
|
105
|
-
"@radix-ui/react-
|
|
106
|
-
"@radix-ui/react-
|
|
107
|
-
"@radix-ui/react-
|
|
108
|
-
"@
|
|
109
|
-
"@
|
|
110
|
-
"@
|
|
111
|
-
"@
|
|
112
|
-
"
|
|
113
|
-
"
|
|
114
|
-
"
|
|
115
|
-
"
|
|
116
|
-
"
|
|
117
|
-
"
|
|
118
|
-
"
|
|
119
|
-
"
|
|
120
|
-
"
|
|
121
|
-
"
|
|
122
|
-
"
|
|
123
|
-
"
|
|
124
|
-
"
|
|
125
|
-
"
|
|
126
|
-
"
|
|
127
|
-
"react
|
|
128
|
-
"
|
|
129
|
-
"
|
|
130
|
-
"
|
|
131
|
-
"
|
|
132
|
-
"
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
"
|
|
136
|
-
"
|
|
137
|
-
"
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
"
|
|
143
|
-
"
|
|
144
|
-
"
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
"
|
|
148
|
-
"
|
|
149
|
-
"
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
"
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "indas-ui",
|
|
3
|
+
"version": "0.1.2",
|
|
4
|
+
"description": "Indas UI — React component library for business apps: Tailwind design tokens, Radix primitives, Lucide icons, DataGrid, dashboards and charts.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "Indas Analytics Pvt Ltd",
|
|
7
|
+
"contributors": [
|
|
8
|
+
"Shreyansh Patidar",
|
|
9
|
+
"Abhinav"
|
|
10
|
+
],
|
|
11
|
+
"repository": {
|
|
12
|
+
"type": "git",
|
|
13
|
+
"url": "git+https://github.com/ShreyanshPatidar/indas-ui.git",
|
|
14
|
+
"directory": "packages/indas-ui"
|
|
15
|
+
},
|
|
16
|
+
"homepage": "https://shreyanshpatidar.github.io/indas-ui",
|
|
17
|
+
"type": "module",
|
|
18
|
+
"main": "./dist/cjs/index.js",
|
|
19
|
+
"module": "./dist/index.js",
|
|
20
|
+
"types": "./dist/index.d.ts",
|
|
21
|
+
"exports": {
|
|
22
|
+
".": {
|
|
23
|
+
"types": "./dist/index.d.ts",
|
|
24
|
+
"import": "./dist/index.js",
|
|
25
|
+
"require": "./dist/cjs/index.js"
|
|
26
|
+
},
|
|
27
|
+
"./ui": {
|
|
28
|
+
"types": "./dist/components/ui/index.d.ts",
|
|
29
|
+
"import": "./dist/components/ui/index.js",
|
|
30
|
+
"require": "./dist/cjs/components/ui/index.js"
|
|
31
|
+
},
|
|
32
|
+
"./layout": {
|
|
33
|
+
"types": "./dist/components/layout/index.d.ts",
|
|
34
|
+
"import": "./dist/components/layout/index.js",
|
|
35
|
+
"require": "./dist/cjs/components/layout/index.js"
|
|
36
|
+
},
|
|
37
|
+
"./datagrid": {
|
|
38
|
+
"types": "./dist/components/datagrid/index.d.ts",
|
|
39
|
+
"import": "./dist/components/datagrid/index.js",
|
|
40
|
+
"require": "./dist/cjs/components/datagrid/index.js"
|
|
41
|
+
},
|
|
42
|
+
"./dashboard": {
|
|
43
|
+
"types": "./dist/components/dashboard/index.d.ts",
|
|
44
|
+
"import": "./dist/components/dashboard/index.js",
|
|
45
|
+
"require": "./dist/cjs/components/dashboard/index.js"
|
|
46
|
+
},
|
|
47
|
+
"./charts": {
|
|
48
|
+
"types": "./dist/components/dashboard/charts/index.d.ts",
|
|
49
|
+
"import": "./dist/components/dashboard/charts/index.js",
|
|
50
|
+
"require": "./dist/cjs/components/dashboard/charts/index.js"
|
|
51
|
+
},
|
|
52
|
+
"./kpi": {
|
|
53
|
+
"types": "./dist/components/dashboard/kpi/index.d.ts",
|
|
54
|
+
"import": "./dist/components/dashboard/kpi/index.js",
|
|
55
|
+
"require": "./dist/cjs/components/dashboard/kpi/index.js"
|
|
56
|
+
},
|
|
57
|
+
"./modals": {
|
|
58
|
+
"types": "./dist/components/modals/index.d.ts",
|
|
59
|
+
"import": "./dist/components/modals/index.js",
|
|
60
|
+
"require": "./dist/cjs/components/modals/index.js"
|
|
61
|
+
},
|
|
62
|
+
"./forms": {
|
|
63
|
+
"types": "./dist/components/forms/index.d.ts",
|
|
64
|
+
"import": "./dist/components/forms/index.js",
|
|
65
|
+
"require": "./dist/cjs/components/forms/index.js"
|
|
66
|
+
},
|
|
67
|
+
"./chat": {
|
|
68
|
+
"types": "./dist/components/chat/index.d.ts",
|
|
69
|
+
"import": "./dist/components/chat/index.js",
|
|
70
|
+
"require": "./dist/cjs/components/chat/index.js"
|
|
71
|
+
},
|
|
72
|
+
"./providers": {
|
|
73
|
+
"types": "./dist/providers.d.ts",
|
|
74
|
+
"import": "./dist/providers.js",
|
|
75
|
+
"require": "./dist/cjs/providers.js"
|
|
76
|
+
},
|
|
77
|
+
"./tokens.css": "./dist/styles/tokens.css",
|
|
78
|
+
"./styles/*": "./dist/styles/*",
|
|
79
|
+
"./package.json": "./package.json"
|
|
80
|
+
},
|
|
81
|
+
"files": [
|
|
82
|
+
"dist"
|
|
83
|
+
],
|
|
84
|
+
"sideEffects": [
|
|
85
|
+
"**/*.css"
|
|
86
|
+
],
|
|
87
|
+
"scripts": {
|
|
88
|
+
"build": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\" && tsc -p tsconfig.build.json && tsc-alias -p tsconfig.build.json --resolve-full-paths && tsc -p tsconfig.build.cjs.json && tsc-alias -p tsconfig.build.cjs.json --resolve-full-paths && node scripts/copy-assets.mjs",
|
|
89
|
+
"dev": "node scripts/dev.mjs",
|
|
90
|
+
"type-check": "tsc --noEmit",
|
|
91
|
+
"prepublishOnly": "npm run build"
|
|
92
|
+
},
|
|
93
|
+
"peerDependencies": {
|
|
94
|
+
"react": ">=18.0.0",
|
|
95
|
+
"react-dom": ">=18.0.0"
|
|
96
|
+
},
|
|
97
|
+
"dependencies": {
|
|
98
|
+
"@dnd-kit/core": "^6.3.1",
|
|
99
|
+
"@dnd-kit/modifiers": "^9.0.0",
|
|
100
|
+
"@dnd-kit/sortable": "^10.0.0",
|
|
101
|
+
"@dnd-kit/utilities": "^3.2.2",
|
|
102
|
+
"@microsoft/signalr": "^10.0.0",
|
|
103
|
+
"@radix-ui/react-collapsible": "^1.1.12",
|
|
104
|
+
"@radix-ui/react-dialog": "^1.1.15",
|
|
105
|
+
"@radix-ui/react-dropdown-menu": "^2.1.16",
|
|
106
|
+
"@radix-ui/react-icons": "^1.3.2",
|
|
107
|
+
"@radix-ui/react-popover": "^1.1.15",
|
|
108
|
+
"@radix-ui/react-progress": "^1.1.7",
|
|
109
|
+
"@radix-ui/react-select": "^2.2.6",
|
|
110
|
+
"@radix-ui/react-separator": "^1.1.7",
|
|
111
|
+
"@radix-ui/react-tabs": "^1.1.13",
|
|
112
|
+
"@radix-ui/react-tooltip": "^1.2.8",
|
|
113
|
+
"@tanstack/react-query": "^5.90.10",
|
|
114
|
+
"@tanstack/react-query-devtools": "^5.90.2",
|
|
115
|
+
"@tanstack/react-table": "^8.21.3",
|
|
116
|
+
"@tanstack/react-virtual": "^3.13.12",
|
|
117
|
+
"class-variance-authority": "^0.7.1",
|
|
118
|
+
"clsx": "^2.1.1",
|
|
119
|
+
"echarts": "^6.0.0",
|
|
120
|
+
"echarts-for-react": "^3.0.5",
|
|
121
|
+
"exceljs": "^4.4.0",
|
|
122
|
+
"file-saver": "^2.0.5",
|
|
123
|
+
"framer-motion": "^12.23.12",
|
|
124
|
+
"jspdf": "^3.0.2",
|
|
125
|
+
"jspdf-autotable": "^5.0.2",
|
|
126
|
+
"ldrs": "^1.1.9",
|
|
127
|
+
"lucide-react": "^0.562.0",
|
|
128
|
+
"next-auth": "^4.24.7",
|
|
129
|
+
"papaparse": "^5.5.3",
|
|
130
|
+
"react-hook-form": "^7.76.1",
|
|
131
|
+
"react-image-crop": "^11.0.10",
|
|
132
|
+
"react-markdown": "^10.1.0",
|
|
133
|
+
"rehype-highlight": "^7.0.2",
|
|
134
|
+
"rehype-raw": "^7.0.0",
|
|
135
|
+
"remark-gfm": "^4.0.1",
|
|
136
|
+
"svg2pdf.js": "^2.7.0",
|
|
137
|
+
"tailwind-merge": "^3.3.1"
|
|
138
|
+
},
|
|
139
|
+
"devDependencies": {
|
|
140
|
+
"@types/react": "^18.3.12",
|
|
141
|
+
"@types/react-dom": "^18.3.1",
|
|
142
|
+
"next": "^16.2.1",
|
|
143
|
+
"tsc-alias": "^1.9.4",
|
|
144
|
+
"typescript": "^5.7.2"
|
|
145
|
+
},
|
|
146
|
+
"keywords": [
|
|
147
|
+
"react",
|
|
148
|
+
"components",
|
|
149
|
+
"ui",
|
|
150
|
+
"tailwind",
|
|
151
|
+
"design-system",
|
|
152
|
+
"datagrid",
|
|
153
|
+
"indas",
|
|
154
|
+
"erp"
|
|
155
|
+
],
|
|
156
|
+
"typesVersions": {
|
|
157
|
+
"*": {
|
|
158
|
+
"ui": [
|
|
159
|
+
"./dist/components/ui/index.d.ts"
|
|
160
|
+
],
|
|
161
|
+
"layout": [
|
|
162
|
+
"./dist/components/layout/index.d.ts"
|
|
163
|
+
],
|
|
164
|
+
"datagrid": [
|
|
165
|
+
"./dist/components/datagrid/index.d.ts"
|
|
166
|
+
],
|
|
167
|
+
"dashboard": [
|
|
168
|
+
"./dist/components/dashboard/index.d.ts"
|
|
169
|
+
],
|
|
170
|
+
"charts": [
|
|
171
|
+
"./dist/components/dashboard/charts/index.d.ts"
|
|
172
|
+
],
|
|
173
|
+
"kpi": [
|
|
174
|
+
"./dist/components/dashboard/kpi/index.d.ts"
|
|
175
|
+
],
|
|
176
|
+
"modals": [
|
|
177
|
+
"./dist/components/modals/index.d.ts"
|
|
178
|
+
],
|
|
179
|
+
"forms": [
|
|
180
|
+
"./dist/components/forms/index.d.ts"
|
|
181
|
+
],
|
|
182
|
+
"providers": [
|
|
183
|
+
"./dist/providers.d.ts"
|
|
184
|
+
]
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|