pillardash-ui-react 0.1.142 → 0.1.144
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/Form/Input/Input.js +1 -1
- package/dist/cjs/components/Form/Input/Input.js.map +1 -1
- package/dist/cjs/components/Form/Input/InputWithPrefix.js +1 -1
- package/dist/cjs/components/Form/Input/InputWithPrefix.js.map +1 -1
- package/dist/cjs/components/Form/Input/TagInput.js +1 -1
- package/dist/cjs/components/Form/Input/TagInput.js.map +1 -1
- package/dist/cjs/components/Form/Search/Search.js +1 -1
- package/dist/cjs/components/Form/Search/Search.js.map +1 -1
- package/dist/cjs/components/Form/Select/Select.js +1 -1
- package/dist/cjs/components/Form/Select/Select.js.map +1 -1
- package/dist/cjs/components/Form/Select/SelectButton.js +1 -1
- package/dist/cjs/components/Form/Select/SelectButton.js.map +1 -1
- package/dist/cjs/components/Modal/Modal.js +1 -1
- package/dist/cjs/components/Modal/Modal.js.map +1 -1
- package/dist/cjs/components/Table/Pagination.js +1 -1
- package/dist/cjs/components/Table/Pagination.js.map +1 -1
- package/dist/cjs/components/Table/Table.js +1 -1
- package/dist/cjs/components/Table/Table.js.map +1 -1
- package/dist/cjs/components/Table/TableDropdown.js +1 -1
- package/dist/cjs/components/Table/TableDropdown.js.map +1 -1
- package/dist/cjs/components/Table/TableSkeleton.js +1 -1
- package/dist/cjs/components/Table/TableSkeleton.js.map +1 -1
- package/dist/esm/components/Form/Input/Input.mjs +1 -1
- package/dist/esm/components/Form/Input/Input.mjs.map +1 -1
- package/dist/esm/components/Form/Input/InputWithPrefix.mjs +1 -1
- package/dist/esm/components/Form/Input/InputWithPrefix.mjs.map +1 -1
- package/dist/esm/components/Form/Input/TagInput.mjs +1 -1
- package/dist/esm/components/Form/Input/TagInput.mjs.map +1 -1
- package/dist/esm/components/Form/Search/Search.mjs +1 -1
- package/dist/esm/components/Form/Search/Search.mjs.map +1 -1
- package/dist/esm/components/Form/Select/Select.mjs +1 -1
- package/dist/esm/components/Form/Select/Select.mjs.map +1 -1
- package/dist/esm/components/Form/Select/SelectButton.mjs +1 -1
- package/dist/esm/components/Form/Select/SelectButton.mjs.map +1 -1
- package/dist/esm/components/Modal/Modal.mjs +1 -1
- package/dist/esm/components/Modal/Modal.mjs.map +1 -1
- package/dist/esm/components/Table/Pagination.mjs +1 -1
- package/dist/esm/components/Table/Pagination.mjs.map +1 -1
- package/dist/esm/components/Table/Table.mjs +1 -1
- package/dist/esm/components/Table/Table.mjs.map +1 -1
- package/dist/esm/components/Table/TableDropdown.mjs +1 -1
- package/dist/esm/components/Table/TableDropdown.mjs.map +1 -1
- package/dist/esm/components/Table/TableSkeleton.mjs +1 -1
- package/dist/esm/components/Table/TableSkeleton.mjs.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Table.js","sources":["../../../../src/components/Table/Table.tsx"],"sourcesContent":["import {ReactNode, useMemo, useState} from \"react\";\nimport {ArrowDown, ArrowUp, ArrowUpDown, ChevronDown, ChevronRight} from \"lucide-react\";\n\nimport { Pagination } from \"./Pagination\";\nimport {ExpandableTableProps, Column} from \"./types\";\nimport { TableSkeleton } from \"./TableSkeleton\";\nimport { EmptyStateCard } from \"../Cards\";\nimport React from \"react\";\n\ntype SortOrder = \"asc\" | \"desc\" | null;\n\nexport default function Table<T>({\n data,\n columns,\n itemsPerPage = 20,\n onViewChange,\n totalItems,\n currentPage = 1,\n onPageChange,\n loading = false,\n showPagination = true,\n onRowClick,\n useCardLayout = false,\n emptyState,\n expandableRows = false,\n expandedRowRender,\n onRowToggle,\n defaultExpandedRows = new Set(),\n getRowKey = (item: T, index: number) => index,\n paginationMeta,\n defaultSortKey,\n defaultSortOrder = \"asc\",\n onSort,\n}: ExpandableTableProps<T>) {\n const [expandedRows, setExpandedRows] =\n useState<Set<string | number>>(defaultExpandedRows);\n const [sortKey, setSortKey] = useState<string | null>(defaultSortKey || null);\n const [sortOrder, setSortOrder] = useState<SortOrder>(\n defaultSortKey ? defaultSortOrder : null,\n );\n\n // Pagination calculations\n const totalItemsCount = paginationMeta?.total || totalItems || data.length;\n const totalPages =\n paginationMeta?.last_page || Math.ceil(totalItemsCount / itemsPerPage);\n const currentPageNumber = paginationMeta?.current_page || currentPage;\n const perPage = paginationMeta?.per_page || itemsPerPage;\n\n // Sorting logic\n const sortedData = useMemo(() => {\n if (!sortKey || !sortOrder) return data;\n\n const sorted = [...data].sort((a, b) => {\n const column = columns.find(\n (col) => (col.sortKey || col.value) === sortKey,\n );\n if (!column) return 0;\n\n let aValue: any;\n let bValue: any;\n\n if (typeof column.value === \"function\") {\n // For function-based columns, use the sortKey to get raw values\n aValue = (a as any)[sortKey];\n bValue = (b as any)[sortKey];\n } else {\n aValue = a[column.value];\n bValue = b[column.value];\n }\n\n // Handle null/undefined\n if (aValue == null && bValue == null) return 0;\n if (aValue == null) return 1;\n if (bValue == null) return -1;\n\n // Handle different types\n if (typeof aValue === \"string\" && typeof bValue === \"string\") {\n return sortOrder === \"asc\"\n ? aValue.localeCompare(bValue)\n : bValue.localeCompare(aValue);\n }\n\n if (typeof aValue === \"number\" && typeof bValue === \"number\") {\n return sortOrder === \"asc\" ? aValue - bValue : bValue - aValue;\n }\n\n // Default comparison\n return sortOrder === \"asc\"\n ? String(aValue).localeCompare(String(bValue))\n : String(bValue).localeCompare(String(aValue));\n });\n\n return sorted;\n }, [data, sortKey, sortOrder, columns]);\n\n const currentItems = sortedData;\n\n // Sorting handler\n const handleSort = (column: Column<T>) => {\n if (!column.sortable) return;\n\n const key = String(column.sortKey || column.value);\n let newOrder: SortOrder = \"asc\";\n\n if (sortKey === key) {\n if (sortOrder === \"asc\") newOrder = \"desc\";\n else if (sortOrder === \"desc\") newOrder = null;\n else newOrder = \"asc\";\n }\n\n setSortKey(newOrder ? key : null);\n setSortOrder(newOrder);\n\n if (onSort && newOrder) {\n onSort(key, newOrder);\n }\n };\n\n const getSortIcon = (column: Column<T>) => {\n if (!column.sortable) return null;\n\n const key = String(column.sortKey || column.value);\n if (sortKey !== key) {\n return <ArrowUpDown size={14} className=\"text-gray-400\" />;\n }\n\n return sortOrder === \"asc\" ? (\n <ArrowUp size={14} className=\"text-blue-600\" />\n ) : (\n <ArrowDown size={14} className=\"text-blue-600\" />\n );\n };\n\n // Row expansion logic\n const handleRowClick = (item: T, index: number) => {\n if (expandableRows && expandedRowRender) {\n toggleRow(item, index);\n } else if (onRowClick) {\n onRowClick(item);\n }\n };\n\n const toggleRow = (item: T, index: number) => {\n const rowKey = getRowKey(item, index);\n const newExpandedRows = new Set(expandedRows);\n const isCurrentlyExpanded = expandedRows.has(rowKey);\n\n if (isCurrentlyExpanded) {\n newExpandedRows.delete(rowKey);\n } else {\n newExpandedRows.add(rowKey);\n }\n\n setExpandedRows(newExpandedRows);\n\n if (onRowToggle) {\n onRowToggle(item, !isCurrentlyExpanded);\n }\n };\n\n const isRowExpanded = (item: T, index: number) => {\n const rowKey = getRowKey(item, index);\n return expandedRows.has(rowKey);\n };\n\n const defaultEmptyState = <EmptyStateCard title=\"No Record found\" />;\n\n const getAlignmentClass = (align?: \"left\" | \"center\" | \"right\") => {\n switch (align) {\n case \"center\":\n return \"text-center\";\n case \"right\":\n return \"text-right\";\n default:\n return \"text-left\";\n }\n };\n\n // Card Layout Renderer\n const renderCardLayout = () => (\n <div className=\"grid gap-4 grid-cols-1 sm:grid-cols-2 lg:grid-cols-3\">\n {loading &&\n Array.from({ length: perPage }).map((_, index) => (\n <div\n key={index}\n className=\"bg-white rounded-lg border border-gray-200 p-4 animate-pulse\"\n >\n <div className=\"space-y-3\">\n {columns.slice(0, 3).map((_, colIndex) => (\n <div\n key={colIndex}\n className=\"flex justify-between items-center\"\n >\n <div className=\"h-4 bg-gray-200 rounded w-1/3\"></div>\n <div className=\"h-4 bg-gray-200 rounded w-1/2\"></div>\n </div>\n ))}\n </div>\n </div>\n ))}\n {currentItems.length > 0\n ? currentItems.map((item: T, rowIndex) => {\n const expanded = isRowExpanded(item, rowIndex);\n return (\n <div\n key={rowIndex}\n className=\"bg-white rounded-lg border border-gray-200\"\n >\n <div\n onClick={() => handleRowClick(item, rowIndex)}\n className={`p-4 transition-all duration-200 hover:shadow-md hover:border-gray-300 ${\n onRowClick || expandableRows ? \"cursor-pointer\" : \"\"\n } ${loading ? \"opacity-50\" : \"\"} ${\n expandableRows\n ? \"border-b border-gray-100 last:border-b-0\"\n : \"\"\n }`}\n >\n <div className=\"space-y-3\">\n {expandableRows && (\n <div className=\"flex items-center justify-between mb-2\">\n <div className=\"flex items-center text-sm text-gray-500\">\n {expanded ? (\n <ChevronDown size={16} className=\"mr-1\" />\n ) : (\n <ChevronRight size={16} className=\"mr-1\" />\n )}\n <span>\n {expanded ? \"Hide details\" : \"Show details\"}\n </span>\n </div>\n </div>\n )}\n {columns.map((column, colIndex) => (\n <div\n key={colIndex}\n className=\"flex justify-between items-start\"\n >\n <span className=\"text-sm font-medium text-gray-500 flex-shrink-0 mr-3\">\n {column.title}:\n </span>\n <span className=\"text-sm text-gray-800 text-right\">\n {typeof column.value === \"function\"\n ? column.value(item)\n : (item[column.value] as ReactNode)}\n </span>\n </div>\n ))}\n </div>\n </div>\n {expandableRows && expanded && expandedRowRender && (\n <div className=\"p-4 bg-gray-50 border-t border-gray-100 rounded-b-lg\">\n {expandedRowRender(item)}\n </div>\n )}\n </div>\n );\n })\n : !loading && (\n <div className=\"col-span-full\">\n {emptyState || defaultEmptyState}\n </div>\n )}\n </div>\n );\n\n // Table Layout Renderer\n const renderTableLayout = () => (\n <div className=\"relative overflow-x-auto\">\n <table className=\"w-full\">\n <thead>\n <tr>\n {expandableRows && (\n <th className=\"bg-gray-100 px-6 py-3 text-left text-sm font-semibold tracking-wider text-gray-500 w-12 rounded-bl-xl rounded-tl-xl\">\n {/* Toggle column */}\n </th>\n )}\n {columns.map((column, index) => (\n <th\n key={index}\n onClick={() => handleSort(column)}\n className={`bg-gray-100 px-6 py-3 text-sm font-semibold tracking-wider text-gray-500 ${\n column.width || \"\"\n } ${getAlignmentClass(column.align)} ${\n column.sortable\n ? \"cursor-pointer select-none hover:bg-gray-200\"\n : \"\"\n } ${!expandableRows && index === 0 ? \"rounded-bl-xl rounded-tl-xl\" : \"\"} ${\n index === columns.length - 1\n ? \"rounded-br-xl rounded-tr-xl\"\n : \"\"\n } ${column.className || \"\"}`}\n style={column.width ? { width: column.width } : undefined}\n >\n <div className=\"flex items-center gap-2 justify-between\">\n <span>{column.title}</span>\n {getSortIcon(column)}\n </div>\n </th>\n ))}\n </tr>\n </thead>\n <tbody\n className={`divide-y divide-gray-200 bg-white ${loading ? \"opacity-50\" : \"\"} ${\n onRowClick || expandableRows ? \"cursor-pointer\" : \"\"\n }`}\n >\n {loading && (\n <TableSkeleton\n columns={columns.length + (expandableRows ? 1 : 0)}\n rows={perPage}\n />\n )}\n {currentItems.length > 0\n ? currentItems.map((item: T, rowIndex) => {\n const expanded = isRowExpanded(item, rowIndex);\n return (\n <React.Fragment key={rowIndex}>\n <tr\n onClick={() => handleRowClick(item, rowIndex)}\n className={`hover:bg-gray-50 transition-colors duration-150 ${\n expanded ? \"bg-blue-50\" : \"\"\n }`}\n >\n {expandableRows && (\n <td className=\"whitespace-nowrap px-6 py-4 text-sm font-medium text-gray-800\">\n <div className=\"flex items-center justify-center\">\n {expanded ? (\n <ChevronDown\n size={16}\n className=\"text-gray-500\"\n />\n ) : (\n <ChevronRight\n size={16}\n className=\"text-gray-500\"\n />\n )}\n </div>\n </td>\n )}\n {columns.map((column, colIndex) => (\n <td\n key={colIndex}\n className={`whitespace-nowrap px-6 py-4 text-sm font-medium text-gray-800 ${getAlignmentClass(\n column.align,\n )} ${column.className || \"\"}`}\n style={\n column.width ? { width: column.width } : undefined\n }\n >\n {typeof column.value === \"function\"\n ? column.value(item)\n : (item[column.value] as ReactNode)}\n </td>\n ))}\n </tr>\n {expandableRows && expanded && expandedRowRender && (\n <tr key={`${rowIndex}-expanded`} className=\"bg-gray-50\">\n <td colSpan={columns.length + 1} className=\"px-6 py-4\">\n <div className=\"animate-fade-in\">\n {expandedRowRender(item)}\n </div>\n </td>\n </tr>\n )}\n </React.Fragment>\n );\n })\n : !loading && (\n <tr>\n <td\n colSpan={columns.length + (expandableRows ? 1 : 0)}\n className=\"px-6 py-12 text-center\"\n >\n {emptyState || defaultEmptyState}\n </td>\n </tr>\n )}\n </tbody>\n </table>\n </div>\n );\n\n return (\n <>\n {useCardLayout ? (\n renderCardLayout()\n ) : (\n <>\n <div className=\"hidden md:block\">{renderTableLayout()}</div>\n <div className=\"block md:hidden\">{renderCardLayout()}</div>\n </>\n )}\n\n {showPagination && (\n <Pagination\n currentPage={currentPageNumber}\n totalPages={totalPages}\n totalItems={totalItemsCount}\n itemsPerPage={perPage}\n onPageChange={onPageChange}\n onViewChange={onViewChange}\n loading={loading}\n />\n )}\n </>\n );\n}\n"],"names":["_a","data","columns","_b","itemsPerPage","onViewChange","totalItems","_c","currentPage","onPageChange","_d","loading","_e","showPagination","onRowClick","_f","useCardLayout","emptyState","_g","expandableRows","expandedRowRender","onRowToggle","_h","defaultExpandedRows","Set","_j","getRowKey","item","index","paginationMeta","defaultSortKey","_k","defaultSortOrder","onSort","_l","useState","expandedRows","setExpandedRows","_m","sortKey","setSortKey","_o","sortOrder","setSortOrder","totalItemsCount","total","length","totalPages","last_page","Math","ceil","currentPageNumber","current_page","perPage","per_page","currentItems","useMemo","__spreadArray","sort","a","b","aValue","bValue","column","find","col","value","localeCompare","String","getSortIcon","sortable","key","_jsx","ArrowUpDown","size","className","ArrowUp","ArrowDown","handleRowClick","toggleRow","rowKey","newExpandedRows","isCurrentlyExpanded","has","delete","add","isRowExpanded","defaultEmptyState","EmptyStateCard","title","getAlignmentClass","align","renderCardLayout","_jsxs","children","Array","from","map","_","slice","colIndex","rowIndex","expanded","onClick","concat","ChevronDown","ChevronRight","_Fragment","newOrder","handleSort","width","style","undefined","TableSkeleton","rows","React","Fragment","colSpan","Pagination"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Table.js","sources":["../../../../src/components/Table/Table.tsx"],"sourcesContent":["import { ReactNode, useMemo, useState } from \"react\";\nimport {\n ArrowDown,\n ArrowUp,\n ArrowUpDown,\n ChevronDown,\n ChevronRight,\n} from \"lucide-react\";\n\nimport { Pagination } from \"./Pagination\";\nimport { ExpandableTableProps, Column } from \"./types\";\nimport { TableSkeleton } from \"./TableSkeleton\";\nimport { EmptyStateCard } from \"../Cards\";\nimport React from \"react\";\n\ntype SortOrder = \"asc\" | \"desc\" | null;\n\nexport default function Table<T>({\n data,\n columns,\n itemsPerPage = 20,\n onViewChange,\n totalItems,\n currentPage = 1,\n onPageChange,\n loading = false,\n showPagination = true,\n onRowClick,\n useCardLayout = false,\n emptyState,\n expandableRows = false,\n expandedRowRender,\n onRowToggle,\n defaultExpandedRows = new Set(),\n getRowKey = (item: T, index: number) => index,\n paginationMeta,\n defaultSortKey,\n defaultSortOrder = \"asc\",\n onSort,\n}: ExpandableTableProps<T>) {\n const [expandedRows, setExpandedRows] =\n useState<Set<string | number>>(defaultExpandedRows);\n const [sortKey, setSortKey] = useState<string | null>(defaultSortKey || null);\n const [sortOrder, setSortOrder] = useState<SortOrder>(\n defaultSortKey ? defaultSortOrder : null,\n );\n\n // Pagination calculations\n const totalItemsCount = paginationMeta?.total || totalItems || data.length;\n const totalPages =\n paginationMeta?.last_page || Math.ceil(totalItemsCount / itemsPerPage);\n const currentPageNumber = paginationMeta?.current_page || currentPage;\n const perPage = paginationMeta?.per_page || itemsPerPage;\n\n // Sorting logic\n const sortedData = useMemo(() => {\n if (!sortKey || !sortOrder) return data;\n\n const sorted = [...data].sort((a, b) => {\n const column = columns.find(\n (col) => (col.sortKey || col.value) === sortKey,\n );\n if (!column) return 0;\n\n let aValue: any;\n let bValue: any;\n\n if (typeof column.value === \"function\") {\n // For function-based columns, use the sortKey to get raw values\n aValue = (a as any)[sortKey];\n bValue = (b as any)[sortKey];\n } else {\n aValue = a[column.value];\n bValue = b[column.value];\n }\n\n // Handle null/undefined\n if (aValue == null && bValue == null) return 0;\n if (aValue == null) return 1;\n if (bValue == null) return -1;\n\n // Handle different types\n if (typeof aValue === \"string\" && typeof bValue === \"string\") {\n return sortOrder === \"asc\"\n ? aValue.localeCompare(bValue)\n : bValue.localeCompare(aValue);\n }\n\n if (typeof aValue === \"number\" && typeof bValue === \"number\") {\n return sortOrder === \"asc\" ? aValue - bValue : bValue - aValue;\n }\n\n // Default comparison\n return sortOrder === \"asc\"\n ? String(aValue).localeCompare(String(bValue))\n : String(bValue).localeCompare(String(aValue));\n });\n\n return sorted;\n }, [data, sortKey, sortOrder, columns]);\n\n const currentItems = sortedData;\n\n // Sorting handler\n const handleSort = (column: Column<T>) => {\n if (!column.sortable) return;\n\n const key = String(column.sortKey || column.value);\n let newOrder: SortOrder = \"asc\";\n\n if (sortKey === key) {\n if (sortOrder === \"asc\") newOrder = \"desc\";\n else if (sortOrder === \"desc\") newOrder = null;\n else newOrder = \"asc\";\n }\n\n setSortKey(newOrder ? key : null);\n setSortOrder(newOrder);\n\n if (onSort && newOrder) {\n onSort(key, newOrder);\n }\n };\n\n const getSortIcon = (column: Column<T>) => {\n if (!column.sortable) return null;\n\n const key = String(column.sortKey || column.value);\n if (sortKey !== key) {\n return (\n <ArrowUpDown size={14} className=\"text-gray-400 dark:text-gray-500\" />\n );\n }\n\n return sortOrder === \"asc\" ? (\n <ArrowUp size={14} className=\"text-blue-600\" />\n ) : (\n <ArrowDown size={14} className=\"text-blue-600\" />\n );\n };\n\n // Row expansion logic\n const handleRowClick = (item: T, index: number) => {\n if (expandableRows && expandedRowRender) {\n toggleRow(item, index);\n } else if (onRowClick) {\n onRowClick(item);\n }\n };\n\n const toggleRow = (item: T, index: number) => {\n const rowKey = getRowKey(item, index);\n const newExpandedRows = new Set(expandedRows);\n const isCurrentlyExpanded = expandedRows.has(rowKey);\n\n if (isCurrentlyExpanded) {\n newExpandedRows.delete(rowKey);\n } else {\n newExpandedRows.add(rowKey);\n }\n\n setExpandedRows(newExpandedRows);\n\n if (onRowToggle) {\n onRowToggle(item, !isCurrentlyExpanded);\n }\n };\n\n const isRowExpanded = (item: T, index: number) => {\n const rowKey = getRowKey(item, index);\n return expandedRows.has(rowKey);\n };\n\n const defaultEmptyState = <EmptyStateCard title=\"No Record found\" />;\n\n const getAlignmentClass = (align?: \"left\" | \"center\" | \"right\") => {\n switch (align) {\n case \"center\":\n return \"text-center\";\n case \"right\":\n return \"text-right\";\n default:\n return \"text-left\";\n }\n };\n\n // Card Layout Renderer\n const renderCardLayout = () => (\n <div className=\"grid gap-4 grid-cols-1 sm:grid-cols-2 lg:grid-cols-3\">\n {loading &&\n Array.from({ length: perPage }).map((_, index) => (\n <div\n key={index}\n className=\"rounded-lg border border-gray-200 bg-white p-4 animate-pulse dark:border-gray-700 dark:bg-gray-800\"\n >\n <div className=\"space-y-3\">\n {columns.slice(0, 3).map((_, colIndex) => (\n <div\n key={colIndex}\n className=\"flex justify-between items-center\"\n >\n <div className=\"h-4 w-1/3 rounded bg-gray-200 dark:bg-gray-700\"></div>\n <div className=\"h-4 w-1/2 rounded bg-gray-200 dark:bg-gray-700\"></div>\n </div>\n ))}\n </div>\n </div>\n ))}\n {currentItems.length > 0\n ? currentItems.map((item: T, rowIndex) => {\n const expanded = isRowExpanded(item, rowIndex);\n return (\n <div\n key={rowIndex}\n className=\"rounded-lg border border-gray-200 bg-white dark:border-gray-700 dark:bg-gray-800\"\n >\n <div\n onClick={() => handleRowClick(item, rowIndex)}\n className={`p-4 transition-all duration-200 hover:border-gray-300 hover:shadow-md dark:hover:border-gray-600 ${\n onRowClick || expandableRows ? \"cursor-pointer\" : \"\"\n } ${loading ? \"opacity-50\" : \"\"} ${\n expandableRows\n ? \"border-b border-gray-100 last:border-b-0 dark:border-gray-700\"\n : \"\"\n }`}\n >\n <div className=\"space-y-3\">\n {expandableRows && (\n <div className=\"flex items-center justify-between mb-2\">\n <div className=\"flex items-center text-sm text-gray-500 dark:text-gray-400\">\n {expanded ? (\n <ChevronDown size={16} className=\"mr-1\" />\n ) : (\n <ChevronRight size={16} className=\"mr-1\" />\n )}\n <span>\n {expanded ? \"Hide details\" : \"Show details\"}\n </span>\n </div>\n </div>\n )}\n {columns.map((column, colIndex) => (\n <div\n key={colIndex}\n className=\"flex justify-between items-start\"\n >\n <span className=\"mr-3 flex-shrink-0 text-sm font-medium text-gray-500 dark:text-gray-400\">\n {column.title}:\n </span>\n <span className=\"text-right text-sm text-gray-800 dark:text-gray-100\">\n {typeof column.value === \"function\"\n ? column.value(item)\n : (item[column.value] as ReactNode)}\n </span>\n </div>\n ))}\n </div>\n </div>\n {expandableRows && expanded && expandedRowRender && (\n <div className=\"rounded-b-lg border-t border-gray-100 bg-gray-50 p-4 dark:border-gray-700 dark:bg-gray-900/50\">\n {expandedRowRender(item)}\n </div>\n )}\n </div>\n );\n })\n : !loading && (\n <div className=\"col-span-full\">\n {emptyState || defaultEmptyState}\n </div>\n )}\n </div>\n );\n\n // Table Layout Renderer\n const renderTableLayout = () => (\n <div className=\"relative overflow-x-auto\">\n <table className=\"w-full\">\n <thead>\n <tr>\n {expandableRows && (\n <th className=\"w-12 rounded-bl-xl rounded-tl-xl bg-gray-100 px-6 py-3 text-left text-sm font-semibold tracking-wider text-gray-500 dark:bg-gray-800 dark:text-gray-300\">\n {/* Toggle column */}\n </th>\n )}\n {columns.map((column, index) => (\n <th\n key={index}\n onClick={() => handleSort(column)}\n className={`bg-gray-100 px-6 py-3 text-sm font-semibold tracking-wider text-gray-500 dark:bg-gray-800 dark:text-gray-300 ${\n column.width || \"\"\n } ${getAlignmentClass(column.align)} ${\n column.sortable\n ? \"cursor-pointer select-none hover:bg-gray-200 dark:hover:bg-gray-700\"\n : \"\"\n } ${!expandableRows && index === 0 ? \"rounded-bl-xl rounded-tl-xl\" : \"\"} ${\n index === columns.length - 1\n ? \"rounded-br-xl rounded-tr-xl\"\n : \"\"\n } ${column.className || \"\"}`}\n style={column.width ? { width: column.width } : undefined}\n >\n <div className=\"flex items-center gap-2 justify-between\">\n <span>{column.title}</span>\n {getSortIcon(column)}\n </div>\n </th>\n ))}\n </tr>\n </thead>\n <tbody\n className={`divide-y divide-gray-200 dark:divide-gray-700 ${loading ? \"opacity-50\" : \"\"} ${\n onRowClick || expandableRows ? \"cursor-pointer\" : \"\"\n }`}\n >\n {loading && (\n <TableSkeleton\n columns={columns.length + (expandableRows ? 1 : 0)}\n rows={perPage}\n />\n )}\n {currentItems.length > 0\n ? currentItems.map((item: T, rowIndex) => {\n const expanded = isRowExpanded(item, rowIndex);\n return (\n <React.Fragment key={rowIndex}>\n <tr\n onClick={() => handleRowClick(item, rowIndex)}\n className={`transition-colors duration-150 hover:bg-gray-50 dark:hover:bg-gray-800 ${\n expanded ? \"bg-blue-50 dark:bg-blue-950/40\" : \"\"\n }`}\n >\n {expandableRows && (\n <td className=\"whitespace-nowrap px-6 py-4 text-sm font-medium text-gray-800 dark:text-gray-100\">\n <div className=\"flex items-center justify-center\">\n {expanded ? (\n <ChevronDown\n size={16}\n className=\"text-gray-500 dark:text-gray-400\"\n />\n ) : (\n <ChevronRight\n size={16}\n className=\"text-gray-500 dark:text-gray-400\"\n />\n )}\n </div>\n </td>\n )}\n {columns.map((column, colIndex) => (\n <td\n key={colIndex}\n className={`whitespace-nowrap px-6 py-4 text-sm font-medium text-gray-800 dark:text-gray-100 ${getAlignmentClass(\n column.align,\n )} ${column.className || \"\"}`}\n style={\n column.width ? { width: column.width } : undefined\n }\n >\n {typeof column.value === \"function\"\n ? column.value(item)\n : (item[column.value] as ReactNode)}\n </td>\n ))}\n </tr>\n {expandableRows && expanded && expandedRowRender && (\n <tr\n key={`${rowIndex}-expanded`}\n className=\"bg-gray-50 dark:bg-gray-900/50\"\n >\n <td colSpan={columns.length + 1} className=\"px-6 py-4\">\n <div className=\"animate-fade-in\">\n {expandedRowRender(item)}\n </div>\n </td>\n </tr>\n )}\n </React.Fragment>\n );\n })\n : !loading && (\n <tr>\n <td\n colSpan={columns.length + (expandableRows ? 1 : 0)}\n className=\"px-6 py-12 text-center\"\n >\n {emptyState || defaultEmptyState}\n </td>\n </tr>\n )}\n </tbody>\n </table>\n </div>\n );\n\n return (\n <>\n {useCardLayout ? (\n renderCardLayout()\n ) : (\n <>\n <div className=\"hidden md:block\">{renderTableLayout()}</div>\n <div className=\"block md:hidden\">{renderCardLayout()}</div>\n </>\n )}\n\n {showPagination && (\n <Pagination\n currentPage={currentPageNumber}\n totalPages={totalPages}\n totalItems={totalItemsCount}\n itemsPerPage={perPage}\n onPageChange={onPageChange}\n onViewChange={onViewChange}\n loading={loading}\n />\n )}\n </>\n );\n}\n"],"names":["_a","data","columns","_b","itemsPerPage","onViewChange","totalItems","_c","currentPage","onPageChange","_d","loading","_e","showPagination","onRowClick","_f","useCardLayout","emptyState","_g","expandableRows","expandedRowRender","onRowToggle","_h","defaultExpandedRows","Set","_j","getRowKey","item","index","paginationMeta","defaultSortKey","_k","defaultSortOrder","onSort","_l","useState","expandedRows","setExpandedRows","_m","sortKey","setSortKey","_o","sortOrder","setSortOrder","totalItemsCount","total","length","totalPages","last_page","Math","ceil","currentPageNumber","current_page","perPage","per_page","currentItems","useMemo","__spreadArray","sort","a","b","aValue","bValue","column","find","col","value","localeCompare","String","getSortIcon","sortable","key","_jsx","ArrowUpDown","size","className","ArrowUp","ArrowDown","handleRowClick","toggleRow","rowKey","newExpandedRows","isCurrentlyExpanded","has","delete","add","isRowExpanded","defaultEmptyState","EmptyStateCard","title","getAlignmentClass","align","renderCardLayout","_jsxs","children","Array","from","map","_","slice","colIndex","rowIndex","expanded","onClick","concat","ChevronDown","ChevronRight","_Fragment","newOrder","handleSort","width","style","undefined","TableSkeleton","rows","React","Fragment","colSpan","Pagination"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var e=require("react/jsx-runtime"),t=require("react"),
|
|
1
|
+
"use strict";var e=require("react/jsx-runtime"),t=require("react"),r=require("react-dom"),n=require("lucide-react");module.exports=function(o){var a=o.actions,i=o.trigger,c=o.className,d=void 0===c?"":c,s=o.dropdownClassName,l=void 0===s?"":s,u=t.useState(!1),f=u[0],g=u[1],m=t.useState({top:0,left:0}),x=m[0],v=m[1],w=t.useRef(null),p=t.useRef(null),h=function(){g(!f)},y=function(){g(!1)};t.useEffect((function(){if(f&&p.current){var e=p.current.getBoundingClientRect(),t=window.innerHeight-e.bottom,r=e.top;v({top:t<300&&r>t?e.top-300+window.scrollY:e.bottom+window.scrollY,left:e.right-192+window.scrollX})}}),[f]),t.useEffect((function(){var e=function(e){w.current&&!w.current.contains(e.target)&&p.current&&!p.current.contains(e.target)&&y()};return f&&document.addEventListener("mousedown",e),function(){document.removeEventListener("mousedown",e)}}),[f]),t.useEffect((function(){var e=function(e){"Escape"===e.key&&y()};return f&&document.addEventListener("keydown",e),function(){document.removeEventListener("keydown",e)}}),[f]),t.useEffect((function(){var e=function(){if(f&&p.current){var e=p.current.getBoundingClientRect(),t=window.innerHeight-e.bottom,r=e.top;v({top:t<300&&r>t?e.top-300+window.scrollY:e.bottom+window.scrollY,left:e.right-192+window.scrollX})}};return f&&window.addEventListener("scroll",e,!0),function(){window.removeEventListener("scroll",e,!0)}}),[f]);var b=f&&e.jsx("div",{ref:w,className:"fixed z-[9999] w-48 rounded-md bg-white shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none dark:bg-gray-800 dark:ring-gray-700 ".concat(l),style:{top:"".concat(x.top,"px"),left:"".concat(x.left,"px")},children:e.jsxs("div",{className:"py-1",role:"menu","aria-orientation":"vertical",children:[a.map((function(t,r){return e.jsxs("button",{className:"flex w-full items-center px-4 py-2 text-left text-sm transition-colors duration-150 ".concat(t.disabled?"cursor-not-allowed bg-gray-50 text-gray-400 dark:bg-gray-700 dark:text-gray-500":"danger"===t.variant?"text-red-700 hover:bg-red-50 hover:text-red-900 dark:text-red-400 dark:hover:bg-red-950/40 dark:hover:text-red-300":"text-gray-700 hover:bg-gray-100 hover:text-gray-900 dark:text-gray-200 dark:hover:bg-gray-700 dark:hover:text-white"," "),onClick:function(){return function(e){e.disabled||(e.onClick(),y())}(t)},disabled:t.disabled,role:"menuitem",children:[t.icon&&e.jsx("span",{className:"mr-3 flex-shrink-0",children:t.icon}),t.label]},r)})),0===a.length&&e.jsx("div",{className:"px-4 py-2 text-sm text-gray-500 dark:text-gray-300",children:"No actions available"})]})});return e.jsxs("div",{className:"relative inline-block ".concat(d),children:[e.jsx("div",{ref:p,className:"flex",children:i?e.jsx("div",{onClick:h,className:"cursor-pointer",children:i}):e.jsx("button",{className:"rounded-md border border-gray-300 bg-white px-2 py-2 text-sm font-medium text-gray-700 transition-colors duration-200 focus:ring-offset-2 dark:border-gray-600 dark:bg-gray-800 dark:text-gray-200",onClick:h,"aria-expanded":f,"aria-haspopup":"true",children:e.jsx(n.MoreVertical,{className:"h-4 w-4"})})}),"undefined"!=typeof document&&b&&r.createPortal(b,document.body)]})};
|
|
2
2
|
//# sourceMappingURL=TableDropdown.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TableDropdown.js","sources":["../../../../src/components/Table/TableDropdown.tsx"],"sourcesContent":["import React, { useEffect, useRef, useState } from \"react\";\nimport { createPortal } from \"react-dom\";\n\nimport { MoreVertical } from \"lucide-react\";\nimport { TableDropdownProps } from \"./types\";\n\nexport default function TableDropdown({\n actions,\n trigger,\n className = \"\",\n dropdownClassName = \"\",\n}: TableDropdownProps) {\n const [isOpen, setIsOpen] = useState(false);\n const [dropdownPosition, setDropdownPosition] = useState({ top: 0, left: 0 });\n const dropdownRef = useRef<HTMLDivElement>(null);\n const triggerRef = useRef<HTMLDivElement>(null);\n\n const toggleDropdown = () => {\n setIsOpen(!isOpen);\n };\n\n const closeDropdown = () => {\n setIsOpen(false);\n };\n\n // Calculate dropdown position when opened\n useEffect(() => {\n if (isOpen && triggerRef.current) {\n const rect = triggerRef.current.getBoundingClientRect();\n const dropdownHeight = 300; // Approximate max height\n const spaceBelow = window.innerHeight - rect.bottom;\n const spaceAbove = rect.top;\n\n // Determine if dropdown should open above or below\n const shouldOpenAbove =\n spaceBelow < dropdownHeight && spaceAbove > spaceBelow;\n\n setDropdownPosition({\n top: shouldOpenAbove\n ? rect.top - dropdownHeight + window.scrollY\n : rect.bottom + window.scrollY,\n left: rect.right - 192 + window.scrollX, // 192px is the dropdown width (w-48)\n });\n }\n }, [isOpen]);\n\n // Close dropdown when clicking outside\n useEffect(() => {\n const handleClickOutside = (event: MouseEvent) => {\n if (\n dropdownRef.current &&\n !dropdownRef.current.contains(event.target as Node) &&\n triggerRef.current &&\n !triggerRef.current.contains(event.target as Node)\n ) {\n closeDropdown();\n }\n };\n\n if (isOpen) {\n document.addEventListener(\"mousedown\", handleClickOutside);\n }\n\n return () => {\n document.removeEventListener(\"mousedown\", handleClickOutside);\n };\n }, [isOpen]);\n\n // Close dropdown on escape key\n useEffect(() => {\n const handleEscapeKey = (event: KeyboardEvent) => {\n if (event.key === \"Escape\") {\n closeDropdown();\n }\n };\n\n if (isOpen) {\n document.addEventListener(\"keydown\", handleEscapeKey);\n }\n\n return () => {\n document.removeEventListener(\"keydown\", handleEscapeKey);\n };\n }, [isOpen]);\n\n // Handle scroll to reposition dropdown\n useEffect(() => {\n const handleScroll = () => {\n if (isOpen && triggerRef.current) {\n const rect = triggerRef.current.getBoundingClientRect();\n const dropdownHeight = 300;\n const spaceBelow = window.innerHeight - rect.bottom;\n const spaceAbove = rect.top;\n const shouldOpenAbove =\n spaceBelow < dropdownHeight && spaceAbove > spaceBelow;\n\n setDropdownPosition({\n top: shouldOpenAbove\n ? rect.top - dropdownHeight + window.scrollY\n : rect.bottom + window.scrollY,\n left: rect.right - 192 + window.scrollX,\n });\n }\n };\n\n if (isOpen) {\n window.addEventListener(\"scroll\", handleScroll, true);\n }\n\n return () => {\n window.removeEventListener(\"scroll\", handleScroll, true);\n };\n }, [isOpen]);\n\n const handleActionClick = (action: (typeof actions)[0]) => {\n if (!action.disabled) {\n action.onClick();\n closeDropdown();\n }\n };\n\n const dropdownContent = isOpen && (\n <div\n ref={dropdownRef}\n className={`fixed z-[9999] w-48 rounded-md bg-white shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none ${dropdownClassName}`}\n style={{\n top: `${dropdownPosition.top}px`,\n left: `${dropdownPosition.left}px`,\n }}\n >\n <div className=\"py-1\" role=\"menu\" aria-orientation=\"vertical\">\n {actions.map((action, index) => (\n <button\n key={index}\n className={`flex w-full items-center px-4 py-2 text-left text-sm transition-colors duration-150 ${\n action.disabled\n ? \"cursor-not-allowed bg-gray-50 text-gray-400\"\n : action.variant === \"danger\"\n ? \"text-red-700 hover:bg-red-50 hover:text-red-900\"\n : \"text-gray-700 hover:bg-gray-100 hover:text-gray-900\"\n } `}\n onClick={() => handleActionClick(action)}\n disabled={action.disabled}\n role=\"menuitem\"\n >\n {action.icon && (\n <span className=\"mr-3 flex-shrink-0\">{action.icon}</span>\n )}\n {action.label}\n </button>\n ))}\n\n {actions.length === 0 && (\n <div className=\"px-4 py-2 text-sm text-gray-500\">\n No actions available\n </div>\n )}\n </div>\n </div>\n );\n\n return (\n <div className={`relative inline-block ${className}`}>\n {/* Trigger Button */}\n <div ref={triggerRef} className=\"flex\">\n {trigger ? (\n <div onClick={toggleDropdown} className=\"cursor-pointer\">\n {trigger}\n </div>\n ) : (\n <button\n className=\"rounded-md border-gray-300 bg-white px-2 py-2 text-sm font-medium text-gray-700 transition-colors duration-200 focus:ring-offset-2\"\n onClick={toggleDropdown}\n aria-expanded={isOpen}\n aria-haspopup=\"true\"\n >\n <MoreVertical className=\"h-4 w-4\" />\n </button>\n )}\n </div>\n\n {/* Render dropdown in a portal */}\n {typeof document !== \"undefined\" &&\n dropdownContent &&\n createPortal(dropdownContent, document.body)}\n </div>\n );\n}\n"],"names":["_a","actions","trigger","_b","className","_c","dropdownClassName","_d","useState","isOpen","setIsOpen","_e","top","left","dropdownPosition","setDropdownPosition","dropdownRef","useRef","triggerRef","toggleDropdown","closeDropdown","useEffect","current","rect","getBoundingClientRect","spaceBelow","window","innerHeight","bottom","spaceAbove","scrollY","right","scrollX","handleClickOutside","event","contains","target","document","addEventListener","removeEventListener","handleEscapeKey","key","handleScroll","dropdownContent","_jsx","ref","concat","style","children","_jsxs","role","map","action","index","disabled","variant","onClick","handleActionClick","icon","label","length","MoreVertical","createPortal","body"],"mappings":"mIAMc,SAAwBA,GACpC,IAAAC,YACAC,EAAOF,EAAAE,QACPC,cAAAC,OAAS,IAAAD,EAAG,KACZE,EAAAL,EAAAM,kBAAAA,OAAiB,IAAAD,EAAG,GAAEA,EAEhBE,EAAsBC,EAAAA,UAAS,GAA9BC,EAAMF,EAAA,GAAEG,EAASH,EAAA,GAClBI,EAA0CH,EAAAA,SAAS,CAAEI,IAAK,EAAGC,KAAM,IAAlEC,OAAkBC,OACnBC,EAAcC,EAAAA,OAAuB,MACrCC,EAAaD,EAAAA,OAAuB,MAEpCE,EAAiB,WACrBT,GAAWD,EACb,EAEMW,EAAgB,WACpBV,GAAU,EACZ,EAGAW,EAAAA,WAAU,WACR,GAAIZ,GAAUS,EAAWI,QAAS,CAChC,IAAMC,EAAOL,EAAWI,QAAQE,wBAE1BC,EAAaC,OAAOC,YAAcJ,EAAKK,OACvCC,EAAaN,EAAKX,IAMxBG,EAAoB,CAClBH,IAHAa,EANqB,KAMUI,EAAaJ,EAIxCF,EAAKX,IAVY,IAUWc,OAAOI,QACnCP,EAAKK,OAASF,OAAOI,QACzBjB,KAAMU,EAAKQ,MAAQ,IAAML,OAAOM,SAEpC,CACF,GAAG,CAACvB,IAGJY,EAAAA,WAAU,WACR,IAAMY,EAAqB,SAACC,GAExBlB,EAAYM,UACXN,EAAYM,QAAQa,SAASD,EAAME,SACpClB,EAAWI,UACVJ,EAAWI,QAAQa,SAASD,EAAME,SAEnChB,GAEJ,EAMA,OAJIX,GACF4B,SAASC,iBAAiB,YAAaL,GAGlC,WACLI,SAASE,oBAAoB,YAAaN,EAC5C,CACF,GAAG,CAACxB,IAGJY,EAAAA,WAAU,WACR,IAAMmB,EAAkB,SAACN,GACL,WAAdA,EAAMO,KACRrB,GAEJ,EAMA,OAJIX,GACF4B,SAASC,iBAAiB,UAAWE,GAGhC,WACLH,SAASE,oBAAoB,UAAWC,EAC1C,CACF,GAAG,CAAC/B,IAGJY,EAAAA,WAAU,WACR,IAAMqB,EAAe,WACnB,GAAIjC,GAAUS,EAAWI,QAAS,CAChC,IAAMC,EAAOL,EAAWI,QAAQE,wBAE1BC,EAAaC,OAAOC,YAAcJ,EAAKK,OACvCC,EAAaN,EAAKX,IAIxBG,EAAoB,CAClBH,IAHAa,EAJqB,KAIUI,EAAaJ,EAIxCF,EAAKX,IARY,IAQWc,OAAOI,QACnCP,EAAKK,OAASF,OAAOI,QACzBjB,KAAMU,EAAKQ,MAAQ,IAAML,OAAOM,SAEpC,CACF,EAMA,OAJIvB,GACFiB,OAAOY,iBAAiB,SAAUI,GAAc,GAG3C,WACLhB,OAAOa,oBAAoB,SAAUG,GAAc,EACrD,CACF,GAAG,CAACjC,IAEJ,IAOMkC,EAAkBlC,GACtBmC,aACEC,IAAK7B,EACLZ,UAAW,
|
|
1
|
+
{"version":3,"file":"TableDropdown.js","sources":["../../../../src/components/Table/TableDropdown.tsx"],"sourcesContent":["import React, { useEffect, useRef, useState } from \"react\";\nimport { createPortal } from \"react-dom\";\n\nimport { MoreVertical } from \"lucide-react\";\nimport { TableDropdownProps } from \"./types\";\n\nexport default function TableDropdown({\n actions,\n trigger,\n className = \"\",\n dropdownClassName = \"\",\n}: TableDropdownProps) {\n const [isOpen, setIsOpen] = useState(false);\n const [dropdownPosition, setDropdownPosition] = useState({ top: 0, left: 0 });\n const dropdownRef = useRef<HTMLDivElement>(null);\n const triggerRef = useRef<HTMLDivElement>(null);\n\n const toggleDropdown = () => {\n setIsOpen(!isOpen);\n };\n\n const closeDropdown = () => {\n setIsOpen(false);\n };\n\n // Calculate dropdown position when opened\n useEffect(() => {\n if (isOpen && triggerRef.current) {\n const rect = triggerRef.current.getBoundingClientRect();\n const dropdownHeight = 300; // Approximate max height\n const spaceBelow = window.innerHeight - rect.bottom;\n const spaceAbove = rect.top;\n\n // Determine if dropdown should open above or below\n const shouldOpenAbove =\n spaceBelow < dropdownHeight && spaceAbove > spaceBelow;\n\n setDropdownPosition({\n top: shouldOpenAbove\n ? rect.top - dropdownHeight + window.scrollY\n : rect.bottom + window.scrollY,\n left: rect.right - 192 + window.scrollX, // 192px is the dropdown width (w-48)\n });\n }\n }, [isOpen]);\n\n // Close dropdown when clicking outside\n useEffect(() => {\n const handleClickOutside = (event: MouseEvent) => {\n if (\n dropdownRef.current &&\n !dropdownRef.current.contains(event.target as Node) &&\n triggerRef.current &&\n !triggerRef.current.contains(event.target as Node)\n ) {\n closeDropdown();\n }\n };\n\n if (isOpen) {\n document.addEventListener(\"mousedown\", handleClickOutside);\n }\n\n return () => {\n document.removeEventListener(\"mousedown\", handleClickOutside);\n };\n }, [isOpen]);\n\n // Close dropdown on escape key\n useEffect(() => {\n const handleEscapeKey = (event: KeyboardEvent) => {\n if (event.key === \"Escape\") {\n closeDropdown();\n }\n };\n\n if (isOpen) {\n document.addEventListener(\"keydown\", handleEscapeKey);\n }\n\n return () => {\n document.removeEventListener(\"keydown\", handleEscapeKey);\n };\n }, [isOpen]);\n\n // Handle scroll to reposition dropdown\n useEffect(() => {\n const handleScroll = () => {\n if (isOpen && triggerRef.current) {\n const rect = triggerRef.current.getBoundingClientRect();\n const dropdownHeight = 300;\n const spaceBelow = window.innerHeight - rect.bottom;\n const spaceAbove = rect.top;\n const shouldOpenAbove =\n spaceBelow < dropdownHeight && spaceAbove > spaceBelow;\n\n setDropdownPosition({\n top: shouldOpenAbove\n ? rect.top - dropdownHeight + window.scrollY\n : rect.bottom + window.scrollY,\n left: rect.right - 192 + window.scrollX,\n });\n }\n };\n\n if (isOpen) {\n window.addEventListener(\"scroll\", handleScroll, true);\n }\n\n return () => {\n window.removeEventListener(\"scroll\", handleScroll, true);\n };\n }, [isOpen]);\n\n const handleActionClick = (action: (typeof actions)[0]) => {\n if (!action.disabled) {\n action.onClick();\n closeDropdown();\n }\n };\n\n const dropdownContent = isOpen && (\n <div\n ref={dropdownRef}\n className={`fixed z-[9999] w-48 rounded-md bg-white shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none dark:bg-gray-800 dark:ring-gray-700 ${dropdownClassName}`}\n style={{\n top: `${dropdownPosition.top}px`,\n left: `${dropdownPosition.left}px`,\n }}\n >\n <div className=\"py-1\" role=\"menu\" aria-orientation=\"vertical\">\n {actions.map((action, index) => (\n <button\n key={index}\n className={`flex w-full items-center px-4 py-2 text-left text-sm transition-colors duration-150 ${\n action.disabled\n ? \"cursor-not-allowed bg-gray-50 text-gray-400 dark:bg-gray-700 dark:text-gray-500\"\n : action.variant === \"danger\"\n ? \"text-red-700 hover:bg-red-50 hover:text-red-900 dark:text-red-400 dark:hover:bg-red-950/40 dark:hover:text-red-300\"\n : \"text-gray-700 hover:bg-gray-100 hover:text-gray-900 dark:text-gray-200 dark:hover:bg-gray-700 dark:hover:text-white\"\n } `}\n onClick={() => handleActionClick(action)}\n disabled={action.disabled}\n role=\"menuitem\"\n >\n {action.icon && (\n <span className=\"mr-3 flex-shrink-0\">{action.icon}</span>\n )}\n {action.label}\n </button>\n ))}\n\n {actions.length === 0 && (\n <div className=\"px-4 py-2 text-sm text-gray-500 dark:text-gray-300\">\n No actions available\n </div>\n )}\n </div>\n </div>\n );\n\n return (\n <div className={`relative inline-block ${className}`}>\n {/* Trigger Button */}\n <div ref={triggerRef} className=\"flex\">\n {trigger ? (\n <div onClick={toggleDropdown} className=\"cursor-pointer\">\n {trigger}\n </div>\n ) : (\n <button\n className=\"rounded-md border border-gray-300 bg-white px-2 py-2 text-sm font-medium text-gray-700 transition-colors duration-200 focus:ring-offset-2 dark:border-gray-600 dark:bg-gray-800 dark:text-gray-200\"\n onClick={toggleDropdown}\n aria-expanded={isOpen}\n aria-haspopup=\"true\"\n >\n <MoreVertical className=\"h-4 w-4\" />\n </button>\n )}\n </div>\n\n {/* Render dropdown in a portal */}\n {typeof document !== \"undefined\" &&\n dropdownContent &&\n createPortal(dropdownContent, document.body)}\n </div>\n );\n}\n"],"names":["_a","actions","trigger","_b","className","_c","dropdownClassName","_d","useState","isOpen","setIsOpen","_e","top","left","dropdownPosition","setDropdownPosition","dropdownRef","useRef","triggerRef","toggleDropdown","closeDropdown","useEffect","current","rect","getBoundingClientRect","spaceBelow","window","innerHeight","bottom","spaceAbove","scrollY","right","scrollX","handleClickOutside","event","contains","target","document","addEventListener","removeEventListener","handleEscapeKey","key","handleScroll","dropdownContent","_jsx","ref","concat","style","children","_jsxs","role","map","action","index","disabled","variant","onClick","handleActionClick","icon","label","length","MoreVertical","createPortal","body"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var r=require("react/jsx-runtime");exports.TableSkeleton=function(e){var n=e.columns,t=void 0===n?5:n,a=e.rows,c=void 0===a?3:a;return r.jsx(r.Fragment,{children:Array.from({length:c}).map((function(e,n){return r.jsx("tr",{children:Array.from({length:t}).map((function(e,t){return r.jsx("td",{className:"whitespace-nowrap px-6 py-4",children:r.jsx("div",{className:"h-4 animate-pulse rounded bg-gray-200 dark:bg-gray-700"})},"skeleton-cell-".concat(n,"-").concat(t))}))},"skeleton-row-".concat(n))}))})};
|
|
2
2
|
//# sourceMappingURL=TableSkeleton.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TableSkeleton.js","sources":["../../../../src/components/Table/TableSkeleton.tsx"],"sourcesContent":["export function TableSkeleton({ columns = 5, rows = 3 }: { columns?: number; rows?: number }) {\n return (\n <>\n {Array.from({ length: rows }).map((_, rowIndex) => (\n <tr key={`skeleton-row-${rowIndex}`}>\n {Array.from({ length: columns }).map((_, colIndex) => (\n <td\n key={`skeleton-cell-${rowIndex}-${colIndex}`}\n className='whitespace-nowrap px-6 py-4'\n >\n <div className='h-4 animate-pulse rounded bg-gray-200'></div>\n </td>\n ))}\n </tr>\n ))}\n </>\n );\n}\n"],"names":["_a","_b","columns","_c","rows","_jsx","_Fragment","children","Array","from","length","map","_","rowIndex","colIndex","className","concat"],"mappings":"sEAAM,SAAwBA,OAAEC,EAAAD,EAAAE,QAAAA,OAAO,IAAAD,EAAG,EAACA,EAAEE,EAAAH,EAAAI,KAAAA,OAAI,IAAAD,EAAG,EAACA,EACjD,OACIE,EAAAA,IAAAC,EAAAA,SAAA,CAAAC,SACKC,MAAMC,KAAK,CAAEC,OAAQN,IAAQO,KAAI,SAACC,EAAGC,GAAa,OAC/CR,EAAAA,IAAA,KAAA,CAAAE,SACKC,MAAMC,KAAK,CAAEC,OAAQR,IAAWS,KAAI,SAACC,EAAGE,GAAa,OAClDT,MAAA,KAAA,CAEIU,UAAU,8BAA6BR,SAEvCF,EAAAA,IAAA,MAAA,CAAKU,UAAU,
|
|
1
|
+
{"version":3,"file":"TableSkeleton.js","sources":["../../../../src/components/Table/TableSkeleton.tsx"],"sourcesContent":["export function TableSkeleton({ columns = 5, rows = 3 }: { columns?: number; rows?: number }) {\n return (\n <>\n {Array.from({ length: rows }).map((_, rowIndex) => (\n <tr key={`skeleton-row-${rowIndex}`}>\n {Array.from({ length: columns }).map((_, colIndex) => (\n <td\n key={`skeleton-cell-${rowIndex}-${colIndex}`}\n className='whitespace-nowrap px-6 py-4'\n >\n <div className='h-4 animate-pulse rounded bg-gray-200 dark:bg-gray-700'></div>\n </td>\n ))}\n </tr>\n ))}\n </>\n );\n}\n"],"names":["_a","_b","columns","_c","rows","_jsx","_Fragment","children","Array","from","length","map","_","rowIndex","colIndex","className","concat"],"mappings":"sEAAM,SAAwBA,OAAEC,EAAAD,EAAAE,QAAAA,OAAO,IAAAD,EAAG,EAACA,EAAEE,EAAAH,EAAAI,KAAAA,OAAI,IAAAD,EAAG,EAACA,EACjD,OACIE,EAAAA,IAAAC,EAAAA,SAAA,CAAAC,SACKC,MAAMC,KAAK,CAAEC,OAAQN,IAAQO,KAAI,SAACC,EAAGC,GAAa,OAC/CR,EAAAA,IAAA,KAAA,CAAAE,SACKC,MAAMC,KAAK,CAAEC,OAAQR,IAAWS,KAAI,SAACC,EAAGE,GAAa,OAClDT,MAAA,KAAA,CAEIU,UAAU,8BAA6BR,SAEvCF,EAAAA,IAAA,MAAA,CAAKU,UAAU,4DAHV,wBAAiBF,EAAQ,KAAAG,OAAIF,GAFY,KADjD,gBAAAE,OAAgBH,GADsB,KAc/D"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{__rest as e,__assign as
|
|
1
|
+
import{__rest as e,__assign as a}from"../../../node_modules/tslib/tslib.es6.mjs";import{jsxs as t,jsx as r}from"react/jsx-runtime";var l=function(l){var o=l.id,i=l.label,c=l.value,n=l.size,s=void 0===n?"md":n,d=l.onChange,m=l.placeholder,p=l.error,x=l.required,g=void 0!==x&&x,h=l.helpText,b=l.type,y=void 0===b?"text":b,u=l.className,v=void 0===u?"":u,f=l.disabled,N=void 0!==f&&f,k=l.icon,w=l.iconPosition,z=void 0===w?"left":w,C=l.rightIcon,j=l.block,q=e(l,["id","label","value","size","onChange","placeholder","error","required","helpText","type","className","disabled","icon","iconPosition","rightIcon","block"]),I={id:o,value:c,onChange:function(e){d&&d(e)},placeholder:m,disabled:N,className:"w-full rounded-[12px] border ".concat({sm:"text-xs px-3 py-1.5 text-sm min-h-[32px]",md:"text-sm px-4 py-2 text-base min-h-[40px]",lg:"text-base px-4 py-3 text-lg min-h-[48px]"}[s]," ").concat(p?"border-red-500":"border-gray-200"," ").concat(N?"bg-gray-100 text-gray-500 placeholder-gray-300 dark:bg-gray-800 dark:text-gray-500 dark:placeholder-gray-600":"bg-gray-100 placeholder-gray-400 text-dark dark:bg-gray-800 dark:text-gray-100 dark:placeholder-gray-500"," focus:outline-none focus:ring-1 focus:ring-primary ").concat(v," ").concat(k&&"left"===z?"pl-10":""," ").concat(k&&"right"===z?"pr-10":""),"aria-invalid":!!p,"aria-describedby":p?"".concat(o,"-error"):h?"".concat(o,"-help"):void 0};return t("div",{className:"mb-4 ".concat(j&&"w-full"),children:[i&&t("label",{htmlFor:o,className:"mb-1 block text-sm font-medium text-gray-600 dark:text-gray-300",children:[i,g&&r("span",{className:"ml-1 text-red-500",children:"*"})]}),t("div",{className:"relative",children:[k&&"left"===z&&r("div",{className:"pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3",children:k}),"textarea"==y?r("textarea",a({},I,{rows:4,className:"".concat(I.className," resize-none")},q)):r("input",a({},I,{type:y},q)),k&&"right"===z&&r("div",{className:"pointer-events-none absolute inset-y-0 right-0 flex items-center pr-3",children:k}),C&&r("div",{className:"absolute right-3 top-1/2 -translate-y-1/2 cursor-pointer",children:C})]}),h&&!p&&r("p",{id:"".concat(o,"-help"),className:"mt-1 text-sm text-gray-500 dark:text-gray-400",children:h}),p&&r("p",{id:"".concat(o,"-error"),className:"mt-1 text-sm text-red-500",children:p})]})};export{l as default};
|
|
2
2
|
//# sourceMappingURL=Input.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Input.mjs","sources":["../../../../../src/components/Form/Input/Input.tsx"],"sourcesContent":["import React, { ChangeEvent, InputHTMLAttributes, TextareaHTMLAttributes } from \"react\";\nexport type InputElement = HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement;\nexport interface InputProps\n extends Omit<\n InputHTMLAttributes<HTMLInputElement> & TextareaHTMLAttributes<HTMLTextAreaElement>,\n \"onChange\" | \"size\"\n > {\n id?: string;\n value: string;\n onChange?: (value: React.ChangeEvent<InputElement>) => void;\n placeholder?: string;\n error?: string;\n label?: string;\n required?: boolean;\n helpText?: string;\n icon?: React.ReactNode;\n iconPosition?: \"left\" | \"right\";\n rightIcon?: React.ReactNode;\n className?: string;\n size?: \"sm\" | \"md\" | \"lg\";\n block?: boolean\n}\n\nconst Input: React.FC<InputProps> = ({\n id,\n label,\n value,\n size = \"md\",\n onChange,\n placeholder,\n error,\n required = false,\n helpText,\n type = \"text\",\n className = \"\",\n disabled = false,\n icon,\n iconPosition = \"left\",\n rightIcon,\n block,\n\n ...restProps\n}) => {\n // Handle input change\n const handleChange = (e: ChangeEvent<InputElement>) => {\n if (onChange) {\n onChange(e);\n }\n };\n\n const sizeClasses = {\n sm: \"text-xs px-3 py-1.5 text-sm min-h-[32px]\",\n md: \"text-sm px-4 py-2 text-base min-h-[40px]\",\n lg: \"text-base px-4 py-3 text-lg min-h-[48px]\",\n };\n\n // const iconSizeClasses = {\n // sm: \"h-4 w-4\",\n // md: \"h-5 w-5\",\n // lg: \"h-6 w-6\",\n // };\n\n const commonProps = {\n id,\n value,\n onChange: handleChange,\n placeholder,\n disabled,\n className: `w-full rounded-[12px] border ${\n sizeClasses[size]\n } ${\n error ? \"border-red-500\" : \"border-gray-200\"\n } ${\n disabled\n ? \"bg-gray-100 text-gray-500 placeholder-gray-300\"\n : \"bg-gray-100 placeholder-gray-400 text-dark\"\n } focus:outline-none focus:ring-1 focus:ring-primary ${className} ${\n icon && iconPosition === \"left\" ? \"pl-10\" : \"\"\n } ${icon && iconPosition === \"right\" ? \"pr-10\" : \"\"}`,\n \"aria-invalid\": !!error,\n \"aria-describedby\": error ? `${id}-error` : helpText ? `${id}-help` : undefined,\n };\n\n return (\n <div className={`mb-4 ${block && \"w-full\"}`}>\n {label && <label htmlFor={id} className='mb-1 block text-sm font-medium text-gray-600'>\n {label}\n {required && <span className='ml-1 text-red-500'>*</span>}\n </label>}\n\n <div className='relative'>\n {icon && iconPosition === \"left\" && (\n <div className='pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3'>\n {icon}\n </div>\n )}\n {type == \"textarea\" ? (\n <textarea\n {...commonProps}\n rows={4}\n className={`${commonProps.className} resize-none`}\n {...(restProps as TextareaHTMLAttributes<HTMLTextAreaElement>)}\n />\n ) : (\n <input\n {...commonProps}\n type={type}\n {...(restProps as InputHTMLAttributes<HTMLInputElement>)}\n />\n )}\n\n {icon && iconPosition === \"right\" && (\n <div className='pointer-events-none absolute inset-y-0 right-0 flex items-center pr-3'>\n {icon}\n </div>\n )}\n {rightIcon && (\n <div className='absolute right-3 top-1/2 -translate-y-1/2 cursor-pointer'>\n {rightIcon}\n </div>\n )}\n </div>\n\n {helpText && !error && (\n <p id={`${id}-help`} className='mt-1 text-sm text-gray-500'>\n {helpText}\n </p>\n )}\n\n {error && (\n <p id={`${id}-error`} className='mt-1 text-sm text-red-500'>\n {error}\n </p>\n )}\n </div>\n );\n};\n\nexport default Input;\n"],"names":["Input","_a","id","label","value","_b","size","onChange","placeholder","error","_c","required","helpText","_d","type","_e","className","_f","disabled","icon","_g","iconPosition","rightIcon","block","restProps","__rest","commonProps","e","concat","sm","md","lg","undefined","_jsxs","children","htmlFor","_jsx","__assign","rows"],"mappings":"mIAuBA,IAAMA,EAA8B,SAACC,GACjC,IAAAC,EAAED,EAAAC,GACFC,UACAC,EAAKH,EAAAG,MACLC,SAAAC,OAAI,IAAAD,EAAG,OACPE,EAAQN,EAAAM,SACRC,EAAWP,EAAAO,YACXC,EAAKR,EAAAQ,MACLC,EAAAT,EAAAU,SAAAA,OAAQ,IAAAD,GAAQA,EAChBE,EAAQX,EAAAW,SACRC,EAAAZ,EAAAa,KAAAA,OAAI,IAAAD,EAAG,OAAMA,EACbE,EAAAd,EAAAe,UAAAA,OAAS,IAAAD,EAAG,GAAEA,EACdE,aAAAC,OAAQ,IAAAD,KACRE,EAAIlB,EAAAkB,KACJC,iBAAAC,OAAY,IAAAD,EAAG,SACfE,EAASrB,EAAAqB,UACTC,EAAKtB,EAAAsB,MAEFC,EAASC,EAAAxB,EAlBqB,8JAuC3ByB,EAAc,CAChBxB,GAAEA,EACFE,MAAKA,EACLG,SArBiB,SAACoB,GACdpB,GACAA,EAASoB,EAEjB,EAkBInB,YAAWA,EACXU,SAAQA,EACRF,UAAW,gCAAAY,OAlBK,CAChBC,GAAI,2CACJC,GAAI,2CACJC,GAAI,4CAgBYzB,GAAK,KAAAsB,OAEjBnB,EAAQ,iBAAmB,8BAE3BS,EACM,
|
|
1
|
+
{"version":3,"file":"Input.mjs","sources":["../../../../../src/components/Form/Input/Input.tsx"],"sourcesContent":["import React, { ChangeEvent, InputHTMLAttributes, TextareaHTMLAttributes } from \"react\";\nexport type InputElement = HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement;\nexport interface InputProps\n extends Omit<\n InputHTMLAttributes<HTMLInputElement> & TextareaHTMLAttributes<HTMLTextAreaElement>,\n \"onChange\" | \"size\"\n > {\n id?: string;\n value: string;\n onChange?: (value: React.ChangeEvent<InputElement>) => void;\n placeholder?: string;\n error?: string;\n label?: string;\n required?: boolean;\n helpText?: string;\n icon?: React.ReactNode;\n iconPosition?: \"left\" | \"right\";\n rightIcon?: React.ReactNode;\n className?: string;\n size?: \"sm\" | \"md\" | \"lg\";\n block?: boolean\n}\n\nconst Input: React.FC<InputProps> = ({\n id,\n label,\n value,\n size = \"md\",\n onChange,\n placeholder,\n error,\n required = false,\n helpText,\n type = \"text\",\n className = \"\",\n disabled = false,\n icon,\n iconPosition = \"left\",\n rightIcon,\n block,\n\n ...restProps\n}) => {\n // Handle input change\n const handleChange = (e: ChangeEvent<InputElement>) => {\n if (onChange) {\n onChange(e);\n }\n };\n\n const sizeClasses = {\n sm: \"text-xs px-3 py-1.5 text-sm min-h-[32px]\",\n md: \"text-sm px-4 py-2 text-base min-h-[40px]\",\n lg: \"text-base px-4 py-3 text-lg min-h-[48px]\",\n };\n\n // const iconSizeClasses = {\n // sm: \"h-4 w-4\",\n // md: \"h-5 w-5\",\n // lg: \"h-6 w-6\",\n // };\n\n const commonProps = {\n id,\n value,\n onChange: handleChange,\n placeholder,\n disabled,\n className: `w-full rounded-[12px] border ${\n sizeClasses[size]\n } ${\n error ? \"border-red-500\" : \"border-gray-200\"\n } ${\n disabled\n ? \"bg-gray-100 text-gray-500 placeholder-gray-300 dark:bg-gray-800 dark:text-gray-500 dark:placeholder-gray-600\"\n : \"bg-gray-100 placeholder-gray-400 text-dark dark:bg-gray-800 dark:text-gray-100 dark:placeholder-gray-500\"\n } focus:outline-none focus:ring-1 focus:ring-primary ${className} ${\n icon && iconPosition === \"left\" ? \"pl-10\" : \"\"\n } ${icon && iconPosition === \"right\" ? \"pr-10\" : \"\"}`,\n \"aria-invalid\": !!error,\n \"aria-describedby\": error ? `${id}-error` : helpText ? `${id}-help` : undefined,\n };\n\n return (\n <div className={`mb-4 ${block && \"w-full\"}`}>\n {label && <label htmlFor={id} className='mb-1 block text-sm font-medium text-gray-600 dark:text-gray-300'>\n {label}\n {required && <span className='ml-1 text-red-500'>*</span>}\n </label>}\n\n <div className='relative'>\n {icon && iconPosition === \"left\" && (\n <div className='pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3'>\n {icon}\n </div>\n )}\n {type == \"textarea\" ? (\n <textarea\n {...commonProps}\n rows={4}\n className={`${commonProps.className} resize-none`}\n {...(restProps as TextareaHTMLAttributes<HTMLTextAreaElement>)}\n />\n ) : (\n <input\n {...commonProps}\n type={type}\n {...(restProps as InputHTMLAttributes<HTMLInputElement>)}\n />\n )}\n\n {icon && iconPosition === \"right\" && (\n <div className='pointer-events-none absolute inset-y-0 right-0 flex items-center pr-3'>\n {icon}\n </div>\n )}\n {rightIcon && (\n <div className='absolute right-3 top-1/2 -translate-y-1/2 cursor-pointer'>\n {rightIcon}\n </div>\n )}\n </div>\n\n {helpText && !error && (\n <p id={`${id}-help`} className='mt-1 text-sm text-gray-500 dark:text-gray-400'>\n {helpText}\n </p>\n )}\n\n {error && (\n <p id={`${id}-error`} className='mt-1 text-sm text-red-500'>\n {error}\n </p>\n )}\n </div>\n );\n};\n\nexport default Input;\n"],"names":["Input","_a","id","label","value","_b","size","onChange","placeholder","error","_c","required","helpText","_d","type","_e","className","_f","disabled","icon","_g","iconPosition","rightIcon","block","restProps","__rest","commonProps","e","concat","sm","md","lg","undefined","_jsxs","children","htmlFor","_jsx","__assign","rows"],"mappings":"mIAuBA,IAAMA,EAA8B,SAACC,GACjC,IAAAC,EAAED,EAAAC,GACFC,UACAC,EAAKH,EAAAG,MACLC,SAAAC,OAAI,IAAAD,EAAG,OACPE,EAAQN,EAAAM,SACRC,EAAWP,EAAAO,YACXC,EAAKR,EAAAQ,MACLC,EAAAT,EAAAU,SAAAA,OAAQ,IAAAD,GAAQA,EAChBE,EAAQX,EAAAW,SACRC,EAAAZ,EAAAa,KAAAA,OAAI,IAAAD,EAAG,OAAMA,EACbE,EAAAd,EAAAe,UAAAA,OAAS,IAAAD,EAAG,GAAEA,EACdE,aAAAC,OAAQ,IAAAD,KACRE,EAAIlB,EAAAkB,KACJC,iBAAAC,OAAY,IAAAD,EAAG,SACfE,EAASrB,EAAAqB,UACTC,EAAKtB,EAAAsB,MAEFC,EAASC,EAAAxB,EAlBqB,8JAuC3ByB,EAAc,CAChBxB,GAAEA,EACFE,MAAKA,EACLG,SArBiB,SAACoB,GACdpB,GACAA,EAASoB,EAEjB,EAkBInB,YAAWA,EACXU,SAAQA,EACRF,UAAW,gCAAAY,OAlBK,CAChBC,GAAI,2CACJC,GAAI,2CACJC,GAAI,4CAgBYzB,GAAK,KAAAsB,OAEjBnB,EAAQ,iBAAmB,8BAE3BS,EACM,+GACA,2GAA0G,wDAAAU,OAC7DZ,cACnDG,GAAyB,SAAjBE,EAA0B,QAAU,GAAE,KAAAO,OAC9CT,GAAyB,UAAjBE,EAA2B,QAAU,IACjD,iBAAkBZ,EAClB,mBAAoBA,EAAQ,GAAAmB,OAAG1B,YAAaU,EAAW,GAAAgB,OAAG1B,EAAE,cAAU8B,GAG1E,OACIC,EAAA,MAAA,CAAKjB,UAAW,QAAAY,OAAQL,GAAS,UAAUW,SAAA,CACtC/B,GAAS8B,EAAA,QAAA,CAAOE,QAASjC,EAAIc,UAAU,4EACnCb,EACAQ,GAAYyB,UAAMpB,UAAU,oBAAmBkB,SAAA,SAGpDD,EAAA,MAAA,CAAKjB,UAAU,qBACVG,GAAyB,SAAjBE,GACLe,EAAA,MAAA,CAAKpB,UAAU,uEAAsEkB,SAChFf,IAGA,YAARL,EACGsB,EAAA,WAAAC,EAAA,CAAA,EACQX,GACJY,KAAM,EACNtB,UAAW,GAAAY,OAAGF,EAAYV,UAAS,iBAC9BQ,IAGTY,EAAA,QAAAC,EAAA,CAAA,EACQX,EAAW,CACfZ,KAAMA,GACDU,IAIZL,GAAyB,UAAjBE,GACLe,EAAA,MAAA,CAAKpB,UAAU,wEAAuEkB,SACjFf,IAGRG,GACGc,EAAA,MAAA,CAAKpB,UAAU,oEACVM,OAKZV,IAAaH,GACV2B,EAAA,IAAA,CAAGlC,GAAI,GAAA0B,OAAG1B,EAAE,SAASc,UAAU,gDAA+CkB,SACzEtB,IAIRH,GACG2B,EAAA,IAAA,CAAGlC,GAAI,GAAA0B,OAAG1B,EAAE,UAAUc,UAAU,4BAA2BkB,SACtDzB,MAKrB"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{__rest as e,__assign as
|
|
1
|
+
import{__rest as e,__assign as r}from"../../../node_modules/tslib/tslib.es6.mjs";import{jsxs as a,jsx as t}from"react/jsx-runtime";import"react";import"lucide-react";var n=function(n){var l=n.id,o=n.label,d=n.value,c=n.size,i=void 0===c?"md":c,s=n.onChange,m=n.placeholder,x=n.error,p=n.required,g=void 0!==p&&p,b=n.helpText,h=n.type,y=void 0===h?"text":h,v=n.className,u=void 0===v?"":v,f=n.disabled,N=void 0!==f&&f,k=n.icon,C=n.iconPosition,z=void 0===C?"left":C,P=n.rightIcon,j=n.prefixContent,q=n.prefixClassName,w=void 0===q?"":q;n.onPrefixChange;var I,T,F=e(n,["id","label","value","size","onChange","placeholder","error","required","helpText","type","className","disabled","icon","iconPosition","rightIcon","prefixContent","prefixClassName","onPrefixChange"]),_="\n flex-1 rounded-none rounded-r-[12px] border-l-0 ".concat({sm:"text-xs py-1.5 text-sm min-h-[32px]",md:"text-sm py-2 text-base min-h-[40px]",lg:"text-base py-3 text-lg min-h-[48px]"}[i]," \n ").concat(x?"border-red-500":"border-gray-200 dark:border-gray-700","\n ").concat(N?"bg-gray-100 text-gray-500 placeholder-gray-300 dark:bg-gray-800 dark:text-gray-500 dark:placeholder-gray-600":"bg-gray-100 placeholder-gray-400 text-dark dark:bg-gray-800 dark:text-gray-100 dark:placeholder-gray-500","\n focus:outline-none\n ").concat((I="",T="",k&&"left"===z&&(I="pl-10"),k&&"right"===z&&(T="pr-10"),P&&(T="pr-10"),"".concat(I," ").concat(T)),"\n ").concat(u,"\n "),A="\n flex items-center rounded-l-[12px] border border-r-0 ".concat({sm:"px-1 text-xs",md:"px-2 text-sm",lg:"px-4 text-base"}[i],"\n ").concat(x?"border-red-500":"border-gray-200 dark:border-gray-700","\n ").concat(N?"bg-gray-50 dark:bg-gray-800":"bg-gray-100 dark:bg-gray-800 text-gray-700 dark:text-gray-200","\n ").concat(w,"\n "),B={id:l,value:d,onChange:function(e){s&&s(e)},placeholder:m,disabled:N,className:_,"aria-invalid":!!x,"aria-describedby":x?"".concat(l,"-error"):b?"".concat(l,"-help"):void 0};return a("div",{className:"mb-4",children:[o&&a("label",{htmlFor:l,className:"mb-1 block text-sm font-medium text-gray-600 dark:text-gray-300",children:[o,g&&t("span",{className:"ml-1 text-red-500",children:"*"})]}),t("div",{className:"relative",children:a("div",{className:"flex",children:[j&&t("div",{className:A,children:j}),a("div",{className:"relative ".concat(j?"flex-1":"w-full"),children:[k&&"left"===z&&t("div",{className:"pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3 z-10",children:k}),t("input",r({},B,{type:y,className:"".concat(B.className," ").concat(j?"w-full border px-3":"rounded-l-[12px] border-l")},F)),k&&"right"===z&&t("div",{className:"pointer-events-none absolute inset-y-0 right-0 flex items-center pr-3 z-10",children:k}),P&&t("div",{className:"absolute right-3 top-1/2 -translate-y-1/2 cursor-pointer z-10",children:P})]})]})}),b&&!x&&t("p",{id:"".concat(l,"-help"),className:"mt-1 text-sm text-gray-500 dark:text-gray-400",children:b}),x&&t("p",{id:"".concat(l,"-error"),className:"mt-1 text-sm text-red-500",children:x})]})};export{n as default};
|
|
2
2
|
//# sourceMappingURL=InputWithPrefix.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InputWithPrefix.mjs","sources":["../../../../../src/components/Form/Input/InputWithPrefix.tsx"],"sourcesContent":["import React, { ChangeEvent, InputHTMLAttributes, TextareaHTMLAttributes, useState } from \"react\";\nimport { ChevronDown, DollarSign, Phone, User } from \"lucide-react\";\n\nexport interface InputWithPrefixProps\n extends Omit<\n InputHTMLAttributes<HTMLInputElement> & TextareaHTMLAttributes<HTMLTextAreaElement>,\n \"onChange\" | \"size\" | \"prefix\"\n > {\n id?: string;\n value: string;\n onChange?: (value: React.ChangeEvent<HTMLInputElement>) => void;\n placeholder?: string;\n error?: string;\n label?: string;\n required?: boolean;\n helpText?: string;\n icon?: React.ReactNode;\n iconPosition?: \"left\" | \"right\";\n rightIcon?: React.ReactNode;\n className?: string;\n size?: \"sm\" | \"md\" | \"lg\";\n\n // New props for prefix functionality\n prefixContent?: React.ReactNode;\n prefixClassName?: string;\n onPrefixChange?: (value: any) => void;\n}\n\nconst InputWithPrefix: React.FC<InputWithPrefixProps> = ({\n id,\n label,\n value,\n size = \"md\",\n onChange,\n placeholder,\n error,\n required = false,\n helpText,\n type = \"text\",\n className = \"\",\n disabled = false,\n icon,\n iconPosition = \"left\",\n rightIcon,\n prefixContent,\n prefixClassName = \"\",\n onPrefixChange,\n ...restProps\n }) => {\n // Handle input change\n const handleChange = (e: ChangeEvent<HTMLInputElement>) => {\n if (onChange) {\n onChange(e);\n }\n };\n\n const sizeClasses = {\n sm: \"text-xs py-1.5 text-sm min-h-[32px]\",\n md: \"text-sm py-2 text-base min-h-[40px]\",\n lg: \"text-base py-3 text-lg min-h-[48px]\",\n };\n\n const prefixSizeClasses = {\n sm: \"px-1 text-xs\",\n md: \"px-2 text-sm\",\n lg: \"px-4 text-base\",\n };\n\n const inputPaddingClasses = {\n sm: \"pl-3 pr-3\",\n md: \"pl-4 pr-4\",\n lg: \"pl-4 pr-4\",\n };\n\n // Determine if we need extra padding for icons\n const getIconPadding = () => {\n let leftPadding = \"\";\n let rightPadding = \"\";\n\n if (icon && iconPosition === \"left\") {\n leftPadding = \"pl-10\";\n }\n if (icon && iconPosition === \"right\") {\n rightPadding = \"pr-10\";\n }\n if (rightIcon) {\n rightPadding = \"pr-10\";\n }\n\n return `${leftPadding} ${rightPadding}`;\n };\n\n const baseInputClasses = `\n flex-1 rounded-none rounded-r-[12px] border-l-0 ${sizeClasses[size]} \n ${error ? \"border-red-500\" : \"border-gray-200\"}\n ${disabled ? \"bg-gray-100 text-gray-500 placeholder-gray-300\" : \"bg-gray-100 placeholder-gray-400 text-dark\"}\n focus:outline-none\n ${getIconPadding()}\n ${className}\n `;\n\n const prefixClasses = `\n flex items-center rounded-l-[12px] border border-r-0 ${prefixSizeClasses[size]}\n ${error ? \"border-red-500\" : \"border-gray-200\"}\n ${disabled ? \"bg-gray-50\" : \"\"}\n ${prefixClassName}\n `;\n\n const commonInputProps = {\n id,\n value,\n onChange: handleChange,\n placeholder,\n disabled,\n className: baseInputClasses,\n \"aria-invalid\": !!error,\n \"aria-describedby\": error ? `${id}-error` : helpText ? `${id}-help` : undefined,\n };\n\n return (\n <div className='mb-4'>\n {label && (\n <label htmlFor={id} className='mb-1 block text-sm font-medium text-gray-600'>\n {label}\n {required && <span className='ml-1 text-red-500'>*</span>}\n </label>\n )}\n\n <div className='relative'>\n <div className='flex'>\n {/* Prefix Section */}\n {prefixContent && (\n <div className={prefixClasses}>\n {prefixContent}\n </div>\n )}\n\n {/* Input Section */}\n <div className={`relative ${prefixContent ? \"flex-1\" : \"w-full\"}`}>\n {icon && iconPosition === \"left\" && (\n <div className=\"pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3 z-10\">\n {icon}\n </div>\n )}\n\n <input\n {...commonInputProps}\n type={type}\n className={`${commonInputProps.className} ${!prefixContent ? \"rounded-l-[12px] border-l\" : \"w-full border px-3\"}`}\n {...(restProps as InputHTMLAttributes<HTMLInputElement>)}\n />\n\n {icon && iconPosition === \"right\" && (\n <div className=\"pointer-events-none absolute inset-y-0 right-0 flex items-center pr-3 z-10\">\n {icon}\n </div>\n )}\n\n {rightIcon && (\n <div className=\"absolute right-3 top-1/2 -translate-y-1/2 cursor-pointer z-10\">\n {rightIcon}\n </div>\n )}\n </div>\n </div>\n </div>\n\n {helpText && !error && (\n <p id={`${id}-help`} className=\"mt-1 text-sm text-gray-500\">\n {helpText}\n </p>\n )}\n\n {error && (\n <p id={`${id}-error`} className=\"mt-1 text-sm text-red-500\">\n {error}\n </p>\n )}\n </div>\n );\n};\n\n\nexport default InputWithPrefix;\n\nexport const InputWithPrefixDemo = () => {\n const [phoneNumber, setPhoneNumber] = useState('');\n const [amount, setAmount] = useState('');\n const [username, setUsername] = useState('');\n const [selectedCountry, setSelectedCountry] = useState('+234');\n const [selectedCurrency, setSelectedCurrency] = useState('USD');\n\n const countries = [\n { code: '+234', flag: '🇳🇬', country: 'Nigeria' },\n { code: '+1', flag: '🇺🇸', country: 'United States' },\n { code: '+44', flag: '🇬🇧', country: 'United Kingdom' },\n { code: '+91', flag: '🇮🇳', country: 'India' },\n { code: '+86', flag: '🇨🇳', country: 'China' },\n ];\n\n const currencies = ['USD', 'EUR', 'GBP', 'NGN', 'JPY'];\n\n return (\n <div className=\"max-w-2xl mx-auto p-8 bg-gray-50 min-h-screen\">\n <h1 className=\"text-3xl font-bold text-gray-900 mb-8\">InputWithPrefix Component Demo</h1>\n\n <div className=\"bg-white rounded-lg shadow-sm p-6 space-y-6\">\n {/* Phone Number with Country Code Selector */}\n <div>\n <h2 className=\"text-lg font-semibold text-gray-800 mb-4\">Phone Number with Country Code</h2>\n <InputWithPrefix\n id=\"phone\"\n label=\"Phone Number\"\n value={phoneNumber}\n onChange={(e) => setPhoneNumber(e.target.value)}\n placeholder=\"Enter your phone number\"\n icon={<Phone className=\"h-5 w-5 text-gray-400\" />}\n iconPosition=\"right\"\n required\n prefixContent={\n <div className=\"flex items-center\">\n <select\n value={selectedCountry}\n onChange={(e) => setSelectedCountry(e.target.value)}\n className=\"bg-transparent border-none outline-none text-sm font-medium text-gray-700 pr-2\"\n >\n {countries.map((country) => (\n <option key={country.code} value={country.code}>\n {country.flag} {country.code}\n </option>\n ))}\n </select>\n <ChevronDown className=\"h-4 w-4 text-gray-400\" />\n </div>\n }\n prefixClassName=\"min-w-[120px] justify-between\"\n />\n </div>\n\n {/* Amount with Currency Selector */}\n <div>\n <h2 className=\"text-lg font-semibold text-gray-800 mb-4\">Amount with Currency</h2>\n <InputWithPrefix\n id=\"amount\"\n label=\"Amount\"\n value={amount}\n onChange={(e) => setAmount(e.target.value)}\n placeholder=\"0.00\"\n type=\"number\"\n prefixContent={\n <div className=\"flex items-center\">\n <select\n value={selectedCurrency}\n onChange={(e) => setSelectedCurrency(e.target.value)}\n className=\"bg-transparent border-none outline-none text-sm font-medium text-gray-700 pr-2\"\n >\n {currencies.map((currency) => (\n <option key={currency} value={currency}>\n {currency}\n </option>\n ))}\n </select>\n <ChevronDown className=\"h-4 w-4 text-gray-400\" />\n </div>\n }\n prefixClassName=\"min-w-[80px] justify-between\"\n />\n </div>\n\n {/* Username with @ symbol */}\n <div>\n <h2 className=\"text-lg font-semibold text-gray-800 mb-4\">Username with @ Symbol</h2>\n <InputWithPrefix\n id=\"username\"\n label=\"Username\"\n value={username}\n onChange={(e) => setUsername(e.target.value)}\n placeholder=\"your-username\"\n icon={<User className=\"h-5 w-5 text-gray-400\" />}\n iconPosition=\"right\"\n prefixContent={\n <span className=\"text-gray-600 font-medium\">@</span>\n }\n helpText=\"Choose a unique username\"\n />\n </div>\n\n {/* Static Currency Symbol */}\n <div>\n <h2 className=\"text-lg font-semibold text-gray-800 mb-4\">Price with Static Currency</h2>\n <InputWithPrefix\n id=\"price\"\n label=\"Price\"\n value=\"\"\n onChange={() => {}}\n placeholder=\"0.00\"\n type=\"number\"\n prefixContent={\n <DollarSign className=\"h-5 w-5 text-gray-600\" />\n }\n prefixClassName=\"min-w-[50px] justify-center\"\n />\n </div>\n\n {/* Custom HTML in Prefix */}\n <div>\n <h2 className=\"text-lg font-semibold text-gray-800 mb-4\">Custom Prefix Content</h2>\n <InputWithPrefix\n id=\"custom\"\n label=\"Website URL\"\n value=\"\"\n onChange={() => {}}\n placeholder=\"your-site\"\n prefixContent={\n <div className=\"flex items-center space-x-1\">\n <span className=\"text-blue-600 font-medium\">https://</span>\n <div className=\"h-4 w-px bg-gray-300\"></div>\n </div>\n }\n prefixClassName=\"min-w-[90px]\"\n />\n </div>\n </div>\n </div>\n );\n};\n"],"names":["InputWithPrefix","_a","id","label","value","_b","size","onChange","placeholder","error","_c","required","helpText","_d","type","_e","className","_f","disabled","icon","_g","iconPosition","rightIcon","prefixContent","_h","prefixClassName","onPrefixChange","leftPadding","rightPadding","restProps","__rest","baseInputClasses","concat","sm","md","lg","prefixClasses","commonInputProps","e","undefined","_jsxs","children","htmlFor","_jsx","__assign"],"mappings":"sKA4BA,IAAMA,EAAkD,SAACC,GACI,IAAAC,EAAED,EAAAC,GACFC,EAAKF,EAAAE,MACLC,EAAKH,EAAAG,MACLC,EAAAJ,EAAAK,KAAAA,OAAI,IAAAD,EAAG,OACPE,aACAC,EAAWP,EAAAO,YACXC,EAAKR,EAAAQ,MACLC,aAAAC,cAAgBD,EAChBE,aACAC,EAAAZ,EAAAa,KAAAA,OAAI,IAAAD,EAAG,OAAMA,EACbE,EAAAd,EAAAe,UAAAA,OAAS,IAAAD,EAAG,KACZE,EAAAhB,EAAAiB,SAAAA,OAAQ,IAAAD,GAAQA,EAChBE,EAAIlB,EAAAkB,KACJC,EAAAnB,EAAAoB,aAAAA,OAAY,IAAAD,EAAG,OAAMA,EACrBE,EAASrB,EAAAqB,UACTC,EAAatB,EAAAsB,cACbC,oBAAAC,aAAkB,GAAED,EACNvB,EAAAyB,mBA8B/DC,EACAC,EA9BoDC,EAASC,EAAA7B,EAnBhB,yMAgE/C8B,EAAmB,6DAAAC,OApCL,CAChBC,GAAI,sCACJC,GAAI,sCACJC,GAAI,uCAkC0D7B,GAAK,eAAA0B,OACjEvB,EAAQ,iBAAmB,kBAAiB,cAAAuB,OAC5Cd,EAAW,iDAAmD,+FAnB5DS,EAAc,GACdC,EAAe,GAEfT,GAAyB,SAAjBE,IACRM,EAAc,SAEdR,GAAyB,UAAjBE,IACRO,EAAe,SAEfN,IACAM,EAAe,SAGZ,GAAAI,OAAGL,EAAW,KAAAK,OAAIJ,IAQP,cAAAI,OAChBhB,YAGAoB,EAAgB,kEAAAJ,OAvCI,CACtBC,GAAI,eACJC,GAAI,eACJC,GAAI,kBAqCqE7B,GAAK,cAAA0B,OAC5EvB,EAAQ,iBAAmB,kBAAiB,cAAAuB,OAC5Cd,EAAW,aAAe,GAAE,cAAAc,OAC5BP,YAGAY,EAAmB,CACrBnC,GAAEA,EACFE,MAAKA,EACLG,SA7DiB,SAAC+B,GACd/B,GACAA,EAAS+B,EAEjB,EA0DI9B,YAAWA,EACXU,SAAQA,EACRF,UAAWe,EACX,iBAAkBtB,EAClB,mBAAoBA,EAAQ,GAAAuB,OAAG9B,YAAaU,EAAW,GAAAoB,OAAG9B,EAAE,cAAUqC,GAG1E,OACIC,EAAA,MAAA,CAAKxB,UAAU,OAAMyB,SAAA,CAChBtC,GACGqC,WAAOE,QAASxC,EAAIc,UAAU,+CAA8CyB,SAAA,CACvEtC,EACAQ,GAAYgC,EAAA,OAAA,CAAM3B,UAAU,sCAIrC2B,EAAA,MAAA,CAAK3B,UAAU,WAAUyB,SACrBD,SAAKxB,UAAU,OAAMyB,SAAA,CAEhBlB,GACGoB,EAAA,MAAA,CAAK3B,UAAWoB,EAAaK,SACxBlB,IAKTiB,SAAKxB,UAAW,mBAAYO,EAAgB,SAAW,UAAUkB,SAAA,CAC5DtB,GAAyB,SAAjBE,GACLsB,EAAA,MAAA,CAAK3B,UAAU,4EAA2EyB,SACrFtB,IAITwB,EAAA,QAAAC,EAAA,CAAA,EACQP,GACJvB,KAAMA,EACNE,UAAW,GAAAgB,OAAGK,EAAiBrB,sBAAcO,EAA8C,qBAA9B,8BACxDM,IAGRV,GAAyB,UAAjBE,GACLsB,EAAA,MAAA,CAAK3B,UAAU,sFACVG,IAIRG,GACGqB,EAAA,MAAA,CAAK3B,UAAU,yEACVM,YAOpBV,IAAaH,GACVkC,OAAGzC,GAAI,UAAGA,EAAE,SAASc,UAAU,6BAA4ByB,SACtD7B,IAIRH,GACGkC,OAAGzC,GAAI,UAAGA,EAAE,UAAUc,UAAU,4BAA2ByB,SACtDhC,MAKrB"}
|
|
1
|
+
{"version":3,"file":"InputWithPrefix.mjs","sources":["../../../../../src/components/Form/Input/InputWithPrefix.tsx"],"sourcesContent":["import React, { ChangeEvent, InputHTMLAttributes, TextareaHTMLAttributes, useState } from \"react\";\nimport { ChevronDown, DollarSign, Phone, User } from \"lucide-react\";\n\nexport interface InputWithPrefixProps\n extends Omit<\n InputHTMLAttributes<HTMLInputElement> & TextareaHTMLAttributes<HTMLTextAreaElement>,\n \"onChange\" | \"size\" | \"prefix\"\n > {\n id?: string;\n value: string;\n onChange?: (value: React.ChangeEvent<HTMLInputElement>) => void;\n placeholder?: string;\n error?: string;\n label?: string;\n required?: boolean;\n helpText?: string;\n icon?: React.ReactNode;\n iconPosition?: \"left\" | \"right\";\n rightIcon?: React.ReactNode;\n className?: string;\n size?: \"sm\" | \"md\" | \"lg\";\n\n // New props for prefix functionality\n prefixContent?: React.ReactNode;\n prefixClassName?: string;\n onPrefixChange?: (value: any) => void;\n}\n\nconst InputWithPrefix: React.FC<InputWithPrefixProps> = ({\n id,\n label,\n value,\n size = \"md\",\n onChange,\n placeholder,\n error,\n required = false,\n helpText,\n type = \"text\",\n className = \"\",\n disabled = false,\n icon,\n iconPosition = \"left\",\n rightIcon,\n prefixContent,\n prefixClassName = \"\",\n onPrefixChange,\n ...restProps\n }) => {\n // Handle input change\n const handleChange = (e: ChangeEvent<HTMLInputElement>) => {\n if (onChange) {\n onChange(e);\n }\n };\n\n const sizeClasses = {\n sm: \"text-xs py-1.5 text-sm min-h-[32px]\",\n md: \"text-sm py-2 text-base min-h-[40px]\",\n lg: \"text-base py-3 text-lg min-h-[48px]\",\n };\n\n const prefixSizeClasses = {\n sm: \"px-1 text-xs\",\n md: \"px-2 text-sm\",\n lg: \"px-4 text-base\",\n };\n\n const inputPaddingClasses = {\n sm: \"pl-3 pr-3\",\n md: \"pl-4 pr-4\",\n lg: \"pl-4 pr-4\",\n };\n\n // Determine if we need extra padding for icons\n const getIconPadding = () => {\n let leftPadding = \"\";\n let rightPadding = \"\";\n\n if (icon && iconPosition === \"left\") {\n leftPadding = \"pl-10\";\n }\n if (icon && iconPosition === \"right\") {\n rightPadding = \"pr-10\";\n }\n if (rightIcon) {\n rightPadding = \"pr-10\";\n }\n\n return `${leftPadding} ${rightPadding}`;\n };\n\n const baseInputClasses = `\n flex-1 rounded-none rounded-r-[12px] border-l-0 ${sizeClasses[size]} \n ${error ? \"border-red-500\" : \"border-gray-200 dark:border-gray-700\"}\n ${disabled ? \"bg-gray-100 text-gray-500 placeholder-gray-300 dark:bg-gray-800 dark:text-gray-500 dark:placeholder-gray-600\" : \"bg-gray-100 placeholder-gray-400 text-dark dark:bg-gray-800 dark:text-gray-100 dark:placeholder-gray-500\"}\n focus:outline-none\n ${getIconPadding()}\n ${className}\n `;\n\n const prefixClasses = `\n flex items-center rounded-l-[12px] border border-r-0 ${prefixSizeClasses[size]}\n ${error ? \"border-red-500\" : \"border-gray-200 dark:border-gray-700\"}\n ${disabled ? \"bg-gray-50 dark:bg-gray-800\" : \"bg-gray-100 dark:bg-gray-800 text-gray-700 dark:text-gray-200\"}\n ${prefixClassName}\n `;\n\n const commonInputProps = {\n id,\n value,\n onChange: handleChange,\n placeholder,\n disabled,\n className: baseInputClasses,\n \"aria-invalid\": !!error,\n \"aria-describedby\": error ? `${id}-error` : helpText ? `${id}-help` : undefined,\n };\n\n return (\n <div className='mb-4'>\n {label && (\n <label htmlFor={id} className='mb-1 block text-sm font-medium text-gray-600 dark:text-gray-300'>\n {label}\n {required && <span className='ml-1 text-red-500'>*</span>}\n </label>\n )}\n\n <div className='relative'>\n <div className='flex'>\n {/* Prefix Section */}\n {prefixContent && (\n <div className={prefixClasses}>\n {prefixContent}\n </div>\n )}\n\n {/* Input Section */}\n <div className={`relative ${prefixContent ? \"flex-1\" : \"w-full\"}`}>\n {icon && iconPosition === \"left\" && (\n <div className=\"pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3 z-10\">\n {icon}\n </div>\n )}\n\n <input\n {...commonInputProps}\n type={type}\n className={`${commonInputProps.className} ${!prefixContent ? \"rounded-l-[12px] border-l\" : \"w-full border px-3\"}`}\n {...(restProps as InputHTMLAttributes<HTMLInputElement>)}\n />\n\n {icon && iconPosition === \"right\" && (\n <div className=\"pointer-events-none absolute inset-y-0 right-0 flex items-center pr-3 z-10\">\n {icon}\n </div>\n )}\n\n {rightIcon && (\n <div className=\"absolute right-3 top-1/2 -translate-y-1/2 cursor-pointer z-10\">\n {rightIcon}\n </div>\n )}\n </div>\n </div>\n </div>\n\n {helpText && !error && (\n <p id={`${id}-help`} className=\"mt-1 text-sm text-gray-500 dark:text-gray-400\">\n {helpText}\n </p>\n )}\n\n {error && (\n <p id={`${id}-error`} className=\"mt-1 text-sm text-red-500\">\n {error}\n </p>\n )}\n </div>\n );\n};\n\n\nexport default InputWithPrefix;\n\nexport const InputWithPrefixDemo = () => {\n const [phoneNumber, setPhoneNumber] = useState('');\n const [amount, setAmount] = useState('');\n const [username, setUsername] = useState('');\n const [selectedCountry, setSelectedCountry] = useState('+234');\n const [selectedCurrency, setSelectedCurrency] = useState('USD');\n\n const countries = [\n { code: '+234', flag: '🇳🇬', country: 'Nigeria' },\n { code: '+1', flag: '🇺🇸', country: 'United States' },\n { code: '+44', flag: '🇬🇧', country: 'United Kingdom' },\n { code: '+91', flag: '🇮🇳', country: 'India' },\n { code: '+86', flag: '🇨🇳', country: 'China' },\n ];\n\n const currencies = ['USD', 'EUR', 'GBP', 'NGN', 'JPY'];\n\n return (\n <div className=\"max-w-2xl mx-auto p-8 bg-gray-50 min-h-screen\">\n <h1 className=\"text-3xl font-bold text-gray-900 mb-8\">InputWithPrefix Component Demo</h1>\n\n <div className=\"bg-white rounded-lg shadow-sm p-6 space-y-6\">\n {/* Phone Number with Country Code Selector */}\n <div>\n <h2 className=\"text-lg font-semibold text-gray-800 mb-4\">Phone Number with Country Code</h2>\n <InputWithPrefix\n id=\"phone\"\n label=\"Phone Number\"\n value={phoneNumber}\n onChange={(e) => setPhoneNumber(e.target.value)}\n placeholder=\"Enter your phone number\"\n icon={<Phone className=\"h-5 w-5 text-gray-400\" />}\n iconPosition=\"right\"\n required\n prefixContent={\n <div className=\"flex items-center\">\n <select\n value={selectedCountry}\n onChange={(e) => setSelectedCountry(e.target.value)}\n className=\"bg-transparent border-none outline-none text-sm font-medium text-gray-700 pr-2\"\n >\n {countries.map((country) => (\n <option key={country.code} value={country.code}>\n {country.flag} {country.code}\n </option>\n ))}\n </select>\n <ChevronDown className=\"h-4 w-4 text-gray-400\" />\n </div>\n }\n prefixClassName=\"min-w-[120px] justify-between\"\n />\n </div>\n\n {/* Amount with Currency Selector */}\n <div>\n <h2 className=\"text-lg font-semibold text-gray-800 mb-4\">Amount with Currency</h2>\n <InputWithPrefix\n id=\"amount\"\n label=\"Amount\"\n value={amount}\n onChange={(e) => setAmount(e.target.value)}\n placeholder=\"0.00\"\n type=\"number\"\n prefixContent={\n <div className=\"flex items-center\">\n <select\n value={selectedCurrency}\n onChange={(e) => setSelectedCurrency(e.target.value)}\n className=\"bg-transparent border-none outline-none text-sm font-medium text-gray-700 pr-2\"\n >\n {currencies.map((currency) => (\n <option key={currency} value={currency}>\n {currency}\n </option>\n ))}\n </select>\n <ChevronDown className=\"h-4 w-4 text-gray-400\" />\n </div>\n }\n prefixClassName=\"min-w-[80px] justify-between\"\n />\n </div>\n\n {/* Username with @ symbol */}\n <div>\n <h2 className=\"text-lg font-semibold text-gray-800 mb-4\">Username with @ Symbol</h2>\n <InputWithPrefix\n id=\"username\"\n label=\"Username\"\n value={username}\n onChange={(e) => setUsername(e.target.value)}\n placeholder=\"your-username\"\n icon={<User className=\"h-5 w-5 text-gray-400\" />}\n iconPosition=\"right\"\n prefixContent={\n <span className=\"text-gray-600 font-medium\">@</span>\n }\n helpText=\"Choose a unique username\"\n />\n </div>\n\n {/* Static Currency Symbol */}\n <div>\n <h2 className=\"text-lg font-semibold text-gray-800 mb-4\">Price with Static Currency</h2>\n <InputWithPrefix\n id=\"price\"\n label=\"Price\"\n value=\"\"\n onChange={() => {}}\n placeholder=\"0.00\"\n type=\"number\"\n prefixContent={\n <DollarSign className=\"h-5 w-5 text-gray-600\" />\n }\n prefixClassName=\"min-w-[50px] justify-center\"\n />\n </div>\n\n {/* Custom HTML in Prefix */}\n <div>\n <h2 className=\"text-lg font-semibold text-gray-800 mb-4\">Custom Prefix Content</h2>\n <InputWithPrefix\n id=\"custom\"\n label=\"Website URL\"\n value=\"\"\n onChange={() => {}}\n placeholder=\"your-site\"\n prefixContent={\n <div className=\"flex items-center space-x-1\">\n <span className=\"text-blue-600 font-medium\">https://</span>\n <div className=\"h-4 w-px bg-gray-300\"></div>\n </div>\n }\n prefixClassName=\"min-w-[90px]\"\n />\n </div>\n </div>\n </div>\n );\n};\n"],"names":["InputWithPrefix","_a","id","label","value","_b","size","onChange","placeholder","error","_c","required","helpText","_d","type","_e","className","_f","disabled","icon","_g","iconPosition","rightIcon","prefixContent","_h","prefixClassName","onPrefixChange","leftPadding","rightPadding","restProps","__rest","baseInputClasses","concat","sm","md","lg","prefixClasses","commonInputProps","e","undefined","_jsxs","children","htmlFor","_jsx","__assign"],"mappings":"sKA4BA,IAAMA,EAAkD,SAACC,GACI,IAAAC,EAAED,EAAAC,GACFC,EAAKF,EAAAE,MACLC,EAAKH,EAAAG,MACLC,EAAAJ,EAAAK,KAAAA,OAAI,IAAAD,EAAG,OACPE,aACAC,EAAWP,EAAAO,YACXC,EAAKR,EAAAQ,MACLC,aAAAC,cAAgBD,EAChBE,aACAC,EAAAZ,EAAAa,KAAAA,OAAI,IAAAD,EAAG,OAAMA,EACbE,EAAAd,EAAAe,UAAAA,OAAS,IAAAD,EAAG,KACZE,EAAAhB,EAAAiB,SAAAA,OAAQ,IAAAD,GAAQA,EAChBE,EAAIlB,EAAAkB,KACJC,EAAAnB,EAAAoB,aAAAA,OAAY,IAAAD,EAAG,OAAMA,EACrBE,EAASrB,EAAAqB,UACTC,EAAatB,EAAAsB,cACbC,oBAAAC,aAAkB,GAAED,EACNvB,EAAAyB,mBA8B/DC,EACAC,EA9BoDC,EAASC,EAAA7B,EAnBhB,yMAgE/C8B,EAAmB,6DAAAC,OApCL,CAChBC,GAAI,sCACJC,GAAI,sCACJC,GAAI,uCAkC0D7B,GAAK,eAAA0B,OACjEvB,EAAQ,iBAAmB,uCAAsC,cAAAuB,OACjEd,EAAW,+GAAiH,6JAnB1HS,EAAc,GACdC,EAAe,GAEfT,GAAyB,SAAjBE,IACRM,EAAc,SAEdR,GAAyB,UAAjBE,IACRO,EAAe,SAEfN,IACAM,EAAe,SAGZ,GAAAI,OAAGL,EAAW,KAAAK,OAAIJ,IAQP,cAAAI,OAChBhB,YAGAoB,EAAgB,kEAAAJ,OAvCI,CACtBC,GAAI,eACJC,GAAI,eACJC,GAAI,kBAqCqE7B,GAAK,cAAA0B,OAC5EvB,EAAQ,iBAAmB,uCAAsC,cAAAuB,OACjEd,EAAW,8BAAgC,gEAA+D,cAAAc,OAC1GP,YAGAY,EAAmB,CACrBnC,GAAEA,EACFE,MAAKA,EACLG,SA7DiB,SAAC+B,GACd/B,GACAA,EAAS+B,EAEjB,EA0DI9B,YAAWA,EACXU,SAAQA,EACRF,UAAWe,EACX,iBAAkBtB,EAClB,mBAAoBA,EAAQ,GAAAuB,OAAG9B,YAAaU,EAAW,GAAAoB,OAAG9B,EAAE,cAAUqC,GAG1E,OACIC,EAAA,MAAA,CAAKxB,UAAU,OAAMyB,SAAA,CAChBtC,GACGqC,WAAOE,QAASxC,EAAIc,UAAU,kEAAiEyB,SAAA,CAC1FtC,EACAQ,GAAYgC,EAAA,OAAA,CAAM3B,UAAU,sCAIrC2B,EAAA,MAAA,CAAK3B,UAAU,WAAUyB,SACrBD,SAAKxB,UAAU,OAAMyB,SAAA,CAEhBlB,GACGoB,EAAA,MAAA,CAAK3B,UAAWoB,EAAaK,SACxBlB,IAKTiB,SAAKxB,UAAW,mBAAYO,EAAgB,SAAW,UAAUkB,SAAA,CAC5DtB,GAAyB,SAAjBE,GACLsB,EAAA,MAAA,CAAK3B,UAAU,4EAA2EyB,SACrFtB,IAITwB,EAAA,QAAAC,EAAA,CAAA,EACQP,GACJvB,KAAMA,EACNE,UAAW,GAAAgB,OAAGK,EAAiBrB,sBAAcO,EAA8C,qBAA9B,8BACxDM,IAGRV,GAAyB,UAAjBE,GACLsB,EAAA,MAAA,CAAK3B,UAAU,sFACVG,IAIRG,GACGqB,EAAA,MAAA,CAAK3B,UAAU,yEACVM,YAOpBV,IAAaH,GACVkC,OAAGzC,GAAI,UAAGA,EAAE,SAASc,UAAU,gDAA+CyB,SACzE7B,IAIRH,GACGkC,OAAGzC,GAAI,UAAGA,EAAE,UAAUc,UAAU,4BAA2ByB,SACtDhC,MAKrB"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{__rest as e,__spreadArray as
|
|
1
|
+
import{__rest as e,__spreadArray as a}from"../../../node_modules/tslib/tslib.es6.mjs";import{jsxs as r,jsx as t,Fragment as l}from"react/jsx-runtime";import{useState as n,useRef as o,useMemo as i,useEffect as d}from"react";var s=function(s){var c=s.id,u=s.label,m=s.value,g=void 0===m?[]:m,p=s.size,b=void 0===p?"md":p,h=s.onChange,x=s.placeholder,v=void 0===x?"Type to search or add tags...":x,f=s.error,y=s.required,w=void 0!==y&&y,N=s.helpText,k=s.className,C=void 0===k?"":k,T=s.disabled,L=void 0!==T&&T,j=s.predefinedTags,S=void 0===j?[]:j,z=s.tagBackgroundColor,E=void 0===z?"bg-primary":z,A=s.tagTextColor,B=void 0===A?"text-white":A,M=s.maxTags,R=s.allowCustomTags,D=void 0===R||R;e(s,["id","label","value","size","onChange","placeholder","error","required","helpText","className","disabled","predefinedTags","tagBackgroundColor","tagTextColor","maxTags","allowCustomTags"]);var I=n(""),J=I[0],q=I[1],F=n(!1),H=F[0],O=F[1],P=o(null),U=o(null),V={sm:"text-xs px-2 py-0.5",md:"text-sm px-2 py-1",lg:"text-base px-3 py-1.5"},W=i((function(){return J?S.filter((function(e){return e.label.toLowerCase().includes(J.toLowerCase())&&!g.some((function(a){return a===e.value}))})):S.filter((function(e){return!g.some((function(a){return a===e.value}))}))}),[J,S,g]);d((function(){var e=function(e){U.current&&!U.current.contains(e.target)&&O(!1)};return document.addEventListener("mousedown",e),function(){return document.removeEventListener("mousedown",e)}}),[]);var G=function(e){if(e&&!(M&&g.length>=M)&&!g.find((function(a){return a.toLowerCase()===e.toLowerCase()}))){var r,t=S.find((function(a){return a.label.toLowerCase()===e.toLowerCase()||a.value.toLowerCase()===e.toLowerCase()}));if(t)r=t.value;else{if(!D)return;r=e}var l=a(a([],g,!0),[r],!1);null==h||h(l),q(""),O(!1)}},K=function(e){var a=g.filter((function(a){return a!==e}));null==h||h(a)};return r("div",{className:"mb-4",children:[u&&r("label",{htmlFor:c,className:"mb-1 block text-sm font-medium text-gray-600 dark:text-gray-300",children:[u,w&&t("span",{className:"ml-1 text-red-500",children:"*"})]}),r("div",{className:"relative",ref:U,children:[r("div",{className:"w-full rounded-[12px] border ".concat(f?"border-red-500":"border-gray-200 dark:border-gray-700"," ").concat(L?"bg-gray-100 text-gray-500 dark:bg-gray-800 dark:text-gray-500":"bg-gray-100 text-dark dark:bg-gray-800 dark:text-gray-100"," focus-within:outline-none focus-within:ring-1 focus-within:ring-primary ").concat(C," ").concat({sm:"text-xs px-3 py-1.5 text-sm min-h-[32px]",md:"text-sm px-4 py-2 text-base min-h-[40px]",lg:"text-base px-4 py-3 text-lg min-h-[48px]"}[b]," flex flex-wrap items-center gap-1"),children:[g.map((function(e){return r("span",{className:"inline-flex items-center rounded-full ".concat(E," ").concat(B," ").concat(V[b]," font-medium"),children:[e,!L&&t("button",{type:"button",onClick:function(){return K(e)},className:"ml-1 inline-flex h-4 w-4 items-center justify-center rounded-full hover:bg-black hover:bg-opacity-20",children:t("svg",{className:"h-3 w-3",fill:"currentColor",viewBox:"0 0 20 20",children:t("path",{fillRule:"evenodd",d:"M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z",clipRule:"evenodd"})})})]},e)})),t("input",{ref:P,id:c,type:"text",value:J,onChange:function(e){var a=e.target.value;q(a),O(!0)},onKeyDown:function(e){"Enter"===e.key&&J.trim()?(e.preventDefault(),G(J.trim())):"Backspace"===e.key&&!J&&g.length>0?K(g[g.length-1]):"Escape"===e.key&&(O(!1),q(""))},onFocus:function(){O(!0)},placeholder:0===g.length?v:"",disabled:L||M&&g.length>=M,className:"min-w-[120px] flex-1 border-none bg-transparent outline-none placeholder-gray-400 dark:placeholder-gray-500","aria-invalid":!!f,"aria-describedby":f?"".concat(g,"-error"):N?"".concat(g,"-help"):void 0})]}),H&&!L&&(W.length>0||J&&D)&&r("div",{className:"absolute z-10 mt-1 max-h-60 w-full overflow-auto rounded-[12px] border border-gray-200 bg-white/95 p-4 shadow-lg backdrop-blur-sm dark:border-gray-700 dark:bg-gray-900/95",children:[W.length>0&&t("div",{className:"flex flex-wrap gap-2 mb-3",children:W.map((function(e){return t("button",{type:"button",onClick:function(){return function(e){G(e.value)}(e)},className:"inline-flex items-center rounded-full bg-gray-200 text-gray-700 transition-colors duration-200 hover:bg-gray-300 dark:bg-gray-700 dark:text-gray-200 dark:hover:bg-gray-600 ".concat(V[b]," font-medium"),children:e.label},e.value)}))}),J&&D&&!S.some((function(e){return e.label.toLowerCase()===J.toLowerCase()}))&&r(l,{children:[W.length>0&&t("div",{className:"mb-2 border-t border-gray-100 pt-3 dark:border-gray-700",children:t("span",{className:"text-xs font-medium text-gray-500 dark:text-gray-400",children:"CREATE NEW TAG"})}),t("div",{className:"flex flex-wrap gap-2",children:r("button",{type:"button",onClick:function(){return G(J)},className:"inline-flex items-center rounded-full bg-blue-100 text-blue-700 hover:bg-blue-200 transition-colors duration-200 ".concat(V[b]," font-medium border border-blue-200"),children:[t("svg",{className:"w-3 h-3 mr-1",fill:"currentColor",viewBox:"0 0 20 20",children:t("path",{fillRule:"evenodd",d:"M10 3a1 1 0 011 1v5h5a1 1 0 110 2h-5v5a1 1 0 11-2 0v-5H4a1 1 0 110-2h5V4a1 1 0 011-1z",clipRule:"evenodd"})}),J]})})]}),0===W.length&&(!J||!D)&&t("div",{className:"py-4 text-center text-sm text-gray-500 dark:text-gray-400",children:"No matching tags found"})]})]}),M&&r("div",{className:"mt-1 text-xs text-gray-500 dark:text-gray-400",children:[g.length,"/",M," tags"]}),N&&!f&&t("p",{id:"".concat(g,"-help"),className:"mt-1 text-sm text-gray-500 dark:text-gray-400",children:N}),f&&t("p",{id:"".concat(g,"-error"),className:"mt-1 text-sm text-red-500",children:f})]})},c=function(){var e=n([]),a=e[0],l=e[1],o=n([]),i=o[0],d=o[1];return r("div",{className:"max-w-2xl mx-auto p-6 bg-gray-50 min-h-screen",children:[t("h1",{className:"text-2xl font-bold mb-8 text-gray-900",children:"TagInput Component Demo"}),r("div",{className:"space-y-8",children:[t(s,{id:"skills",label:"Skills & Technologies",value:a,onChange:l,predefinedTags:[{label:"React",value:"react"},{label:"JavaScript",value:"javascript"},{label:"TypeScript",value:"typescript"},{label:"Node.js",value:"nodejs"},{label:"Python",value:"python"},{label:"CSS",value:"css"},{label:"HTML",value:"html"},{label:"Vue.js",value:"vuejs"},{label:"Angular",value:"angular"},{label:"Next.js",value:"nextjs"}],placeholder:"Search or add skills...",helpText:"Select from predefined options or add your own custom tags",size:"md"}),t(s,{id:"custom-tags",label:"Project Categories (Custom Colors)",value:i,onChange:d,predefinedTags:[{label:"Web Development",value:"web"},{label:"Mobile App",value:"mobile"},{label:"AI/ML",value:"ai"},{label:"UI/UX Design",value:"design"}],placeholder:"Add project categories...",tagBackgroundColor:"bg-purple-500",tagTextColor:"text-white",maxTags:5,size:"lg",helpText:"Maximum 5 tags allowed with custom purple styling"}),r("div",{className:"mt-8 p-4 bg-white rounded-lg border",children:[t("h3",{className:"font-medium mb-2",children:"Selected Skills:"}),t("pre",{className:"text-sm bg-gray-100 p-2 rounded",children:JSON.stringify(a,null,2)})]}),r("div",{className:"p-4 bg-white rounded-lg border",children:[t("h3",{className:"font-medium mb-2",children:"Selected Categories:"}),t("pre",{className:"text-sm bg-gray-100 p-2 rounded",children:JSON.stringify(i,null,2)})]})]})]})};export{c as TagInputDemo,s as default};
|
|
2
2
|
//# sourceMappingURL=TagInput.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TagInput.mjs","sources":["../../../../../src/components/Form/Input/TagInput.tsx"],"sourcesContent":["import React, {useState, useRef, useEffect, useMemo} from \"react\";\n\nexport interface Tag {\n value: string;\n label: string;\n}\n\nexport interface TagInputProps {\n id?: string;\n label?: string;\n value: string[];\n onChange?: (tags: string[]) => void;\n placeholder?: string;\n error?: string;\n required?: boolean;\n helpText?: string;\n className?: string;\n size?: \"sm\" | \"md\" | \"lg\";\n disabled?: boolean;\n predefinedTags?: Tag[];\n tagBackgroundColor?: string;\n tagTextColor?: string;\n maxTags?: number;\n allowCustomTags?: boolean;\n}\n\nconst TagInput: React.FC<TagInputProps> = ({\n id,\n label,\n value = [],\n size = \"md\",\n onChange,\n placeholder = \"Type to search or add tags...\",\n error,\n required = false,\n helpText,\n className = \"\",\n disabled = false,\n predefinedTags = [],\n tagBackgroundColor = \"bg-primary\",\n tagTextColor = \"text-white\",\n maxTags,\n allowCustomTags = true,\n ...restProps\n }) => {\n const [inputValue, setInputValue] = useState(\"\");\n const [isDropdownOpen, setIsDropdownOpen] = useState(false);\n const inputRef = useRef<HTMLInputElement>(null);\n const dropdownRef = useRef<HTMLDivElement>(null);\n\n const sizeClasses = {\n sm: \"text-xs px-3 py-1.5 text-sm min-h-[32px]\",\n md: \"text-sm px-4 py-2 text-base min-h-[40px]\",\n lg: \"text-base px-4 py-3 text-lg min-h-[48px]\",\n };\n\n const tagSizeClasses = {\n sm: \"text-xs px-2 py-0.5\",\n md: \"text-sm px-2 py-1\",\n lg: \"text-base px-3 py-1.5\",\n };\n\n const filteredTags = useMemo(() => {\n if (!inputValue) {\n return predefinedTags.filter(tag =>\n !value.some(selectedTag => selectedTag === tag.value)\n );\n }\n\n return predefinedTags.filter(tag =>\n tag.label.toLowerCase().includes(inputValue.toLowerCase()) &&\n !value.some(selectedTag => selectedTag === tag.value)\n );\n }, [inputValue, predefinedTags, value]);\n\n // Handle clicking outside to close dropdown\n useEffect(() => {\n const handleClickOutside = (event: MouseEvent) => {\n if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {\n setIsDropdownOpen(false);\n }\n };\n\n document.addEventListener(\"mousedown\", handleClickOutside);\n return () => document.removeEventListener(\"mousedown\", handleClickOutside);\n }, []);\n\n const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const newValue = e.target.value;\n setInputValue(newValue);\n setIsDropdownOpen(true);\n };\n\n const handleInputKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\n if (e.key === \"Enter\" && inputValue.trim()) {\n e.preventDefault();\n addTag(inputValue.trim());\n } else if (e.key === \"Backspace\" && !inputValue && value.length > 0) {\n // Remove last tag when backspace is pressed and input is empty\n removeTag(value[value.length - 1]);\n } else if (e.key === \"Escape\") {\n setIsDropdownOpen(false);\n setInputValue(\"\");\n }\n };\n\n const addTag = (tagValue: string) => {\n if (!tagValue || (maxTags && value.length >= maxTags)) return;\n\n // Check if tag already exists\n const existingTag = value.find(tag => tag.toLowerCase() === tagValue.toLowerCase());\n if (existingTag) return;\n\n // Check if it's a predefined tag\n const predefinedTag = predefinedTags.find(tag =>\n tag.label.toLowerCase() === tagValue.toLowerCase() ||\n tag.value.toLowerCase() === tagValue.toLowerCase()\n );\n\n let newTag: string;\n if (predefinedTag) {\n newTag = predefinedTag.value;\n } else if (allowCustomTags) {\n newTag = tagValue;\n } else {\n return; // Don't add if custom tags aren't allowed\n }\n\n const newTags = [...value, newTag];\n onChange?.(newTags);\n setInputValue(\"\");\n setIsDropdownOpen(false);\n };\n\n const removeTag = (tagId: string) => {\n const newTags = value.filter(tag => tag !== tagId);\n onChange?.(newTags);\n };\n\n const selectPredefinedTag = (tag: Tag) => {\n addTag(tag.value);\n };\n\n const handleInputFocus = () => {\n setIsDropdownOpen(true);\n };\n\n return (\n <div className=\"mb-4\">\n {label && (\n <label htmlFor={id} className=\"mb-1 block text-sm font-medium text-gray-600\">\n {label}\n {required && <span className=\"ml-1 text-red-500\">*</span>}\n </label>\n )}\n\n <div className=\"relative\" ref={dropdownRef}>\n <div\n className={`w-full rounded-[12px] border ${\n error ? \"border-red-500\" : \"border-gray-200\"\n } ${\n disabled\n ? \"bg-gray-100 text-gray-500\"\n : \"bg-gray-100 text-dark\"\n } focus-within:outline-none focus-within:ring-1 focus-within:ring-primary ${className} ${sizeClasses[size]} flex flex-wrap items-center gap-1`}\n >\n {/* Render selected tags */}\n {value.map((tag) => (\n <span\n key={tag}\n className={`inline-flex items-center rounded-full ${tagBackgroundColor} ${tagTextColor} ${tagSizeClasses[size]} font-medium`}\n >\n {tag}\n {!disabled && (\n <button\n type=\"button\"\n onClick={() => removeTag(tag)}\n className=\"ml-1 inline-flex h-4 w-4 items-center justify-center rounded-full hover:bg-black hover:bg-opacity-20\"\n >\n <svg className=\"h-3 w-3\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n <path\n fillRule=\"evenodd\"\n d=\"M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z\"\n clipRule=\"evenodd\"\n />\n </svg>\n </button>\n )}\n </span>\n ))}\n\n {/* Input field */}\n <input\n ref={inputRef}\n id={id}\n type=\"text\"\n value={inputValue}\n onChange={handleInputChange}\n onKeyDown={handleInputKeyDown}\n onFocus={handleInputFocus}\n placeholder={value.length === 0 ? placeholder : \"\"}\n disabled={disabled || (maxTags && value.length >= maxTags) as boolean}\n className=\"flex-1 border-none bg-transparent outline-none placeholder-gray-400 min-w-[120px]\"\n aria-invalid={!!error}\n aria-describedby={error ? `${value}-error` : helpText ? `${value}-help` : undefined}\n />\n </div>\n\n {/* Dropdown */}\n {isDropdownOpen && !disabled && (filteredTags.length > 0 || (inputValue && allowCustomTags)) && (\n <div className=\"absolute z-10 mt-1 w-full bg-white border border-gray-200 rounded-[12px] shadow-lg backdrop-blur-sm bg-white/95 max-h-60 overflow-auto p-4\">\n {/* Predefined tags */}\n {filteredTags.length > 0 && (\n <div className=\"flex flex-wrap gap-2 mb-3\">\n {filteredTags.map((tag) => (\n <button\n key={tag.value}\n type=\"button\"\n onClick={() => selectPredefinedTag(tag)}\n className={`inline-flex items-center rounded-full bg-gray-200 text-gray-700 hover:bg-gray-300 transition-colors duration-200 ${tagSizeClasses[size]} font-medium`}\n >\n {tag.label}\n </button>\n ))}\n </div>\n )}\n\n {/* Custom tag option */}\n {inputValue && allowCustomTags && !predefinedTags.some(tag =>\n tag.label.toLowerCase() === inputValue.toLowerCase()\n ) && (\n <>\n {filteredTags.length > 0 && (\n <div className=\"border-t border-gray-100 pt-3 mb-2\">\n <span className=\"text-xs text-gray-500 font-medium\">CREATE NEW TAG</span>\n </div>\n )}\n <div className=\"flex flex-wrap gap-2\">\n <button\n type=\"button\"\n onClick={() => addTag(inputValue)}\n className={`inline-flex items-center rounded-full bg-blue-100 text-blue-700 hover:bg-blue-200 transition-colors duration-200 ${tagSizeClasses[size]} font-medium border border-blue-200`}\n >\n <svg className=\"w-3 h-3 mr-1\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n <path fillRule=\"evenodd\" d=\"M10 3a1 1 0 011 1v5h5a1 1 0 110 2h-5v5a1 1 0 11-2 0v-5H4a1 1 0 110-2h5V4a1 1 0 011-1z\" clipRule=\"evenodd\" />\n </svg>\n {inputValue}\n </button>\n </div>\n </>\n )}\n\n {/* Empty state */}\n {filteredTags.length === 0 && (!inputValue || !allowCustomTags) && (\n <div className=\"text-center py-4 text-gray-500 text-sm\">\n No matching tags found\n </div>\n )}\n </div>\n )}\n </div>\n\n {maxTags && (\n <div className=\"mt-1 text-xs text-gray-500\">\n {value.length}/{maxTags} tags\n </div>\n )}\n\n {helpText && !error && (\n <p id={`${value}-help`} className=\"mt-1 text-sm text-gray-500\">\n {helpText}\n </p>\n )}\n\n {error && (\n <p id={`${value}-error`} className=\"mt-1 text-sm text-red-500\">\n {error}\n </p>\n )}\n </div>\n );\n};\n\n// Demo component to show usage\nexport const TagInputDemo = () => {\n const [selectedTags, setSelectedTags] = useState<string[]>([]);\n const [selectedTags2, setSelectedTags2] = useState<string[]>([]);\n\n const predefinedTags: Tag[] = [\n { label: \"React\", value: \"react\" },\n { label: \"JavaScript\", value: \"javascript\" },\n { label: \"TypeScript\", value: \"typescript\" },\n { label: \"Node.js\", value: \"nodejs\" },\n { label: \"Python\", value: \"python\" },\n { label: \"CSS\", value: \"css\" },\n { label: \"HTML\", value: \"html\" },\n { label: \"Vue.js\", value: \"vuejs\" },\n { label: \"Angular\", value: \"angular\" },\n { label: \"Next.js\", value: \"nextjs\" },\n ];\n\n return (\n <div className=\"max-w-2xl mx-auto p-6 bg-gray-50 min-h-screen\">\n <h1 className=\"text-2xl font-bold mb-8 text-gray-900\">TagInput Component Demo</h1>\n\n <div className=\"space-y-8\">\n <TagInput\n id=\"skills\"\n label=\"Skills & Technologies\"\n value={selectedTags}\n onChange={setSelectedTags}\n predefinedTags={predefinedTags}\n placeholder=\"Search or add skills...\"\n helpText=\"Select from predefined options or add your own custom tags\"\n size=\"md\"\n />\n\n <TagInput\n id=\"custom-tags\"\n label=\"Project Categories (Custom Colors)\"\n value={selectedTags2}\n onChange={setSelectedTags2}\n predefinedTags={[\n { label: \"Web Development\", value: \"web\" },\n { label: \"Mobile App\", value: \"mobile\" },\n { label: \"AI/ML\", value: \"ai\" },\n { label: \"UI/UX Design\", value: \"design\" },\n ]}\n placeholder=\"Add project categories...\"\n tagBackgroundColor=\"bg-purple-500\"\n tagTextColor=\"text-white\"\n maxTags={5}\n size=\"lg\"\n helpText=\"Maximum 5 tags allowed with custom purple styling\"\n />\n\n <div className=\"mt-8 p-4 bg-white rounded-lg border\">\n <h3 className=\"font-medium mb-2\">Selected Skills:</h3>\n <pre className=\"text-sm bg-gray-100 p-2 rounded\">\n {JSON.stringify(selectedTags, null, 2)}\n </pre>\n </div>\n\n <div className=\"p-4 bg-white rounded-lg border\">\n <h3 className=\"font-medium mb-2\">Selected Categories:</h3>\n <pre className=\"text-sm bg-gray-100 p-2 rounded\">\n {JSON.stringify(selectedTags2, null, 2)}\n </pre>\n </div>\n </div>\n </div>\n );\n};\n\nexport default TagInput;"],"names":["TagInput","_a","id","label","_b","value","_c","size","onChange","_d","placeholder","error","_e","required","helpText","_f","className","_g","disabled","_h","predefinedTags","_j","tagBackgroundColor","_k","tagTextColor","maxTags","_l","allowCustomTags","__rest","_m","useState","inputValue","setInputValue","_o","isDropdownOpen","setIsDropdownOpen","inputRef","useRef","dropdownRef","tagSizeClasses","sm","md","lg","filteredTags","useMemo","filter","tag","toLowerCase","includes","some","selectedTag","useEffect","handleClickOutside","event","current","contains","target","document","addEventListener","removeEventListener","addTag","tagValue","length","find","newTag","predefinedTag","newTags","__spreadArray","removeTag","tagId","_jsxs","htmlFor","children","_jsx","ref","concat","map","type","onClick","fill","viewBox","fillRule","d","clipRule","e","newValue","onKeyDown","key","trim","preventDefault","onFocus","undefined","selectPredefinedTag","_Fragment","TagInputDemo","selectedTags","setSelectedTags","selectedTags2","setSelectedTags2","JSON","stringify"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"TagInput.mjs","sources":["../../../../../src/components/Form/Input/TagInput.tsx"],"sourcesContent":["import React, {useState, useRef, useEffect, useMemo} from \"react\";\n\nexport interface Tag {\n value: string;\n label: string;\n}\n\nexport interface TagInputProps {\n id?: string;\n label?: string;\n value: string[];\n onChange?: (tags: string[]) => void;\n placeholder?: string;\n error?: string;\n required?: boolean;\n helpText?: string;\n className?: string;\n size?: \"sm\" | \"md\" | \"lg\";\n disabled?: boolean;\n predefinedTags?: Tag[];\n tagBackgroundColor?: string;\n tagTextColor?: string;\n maxTags?: number;\n allowCustomTags?: boolean;\n}\n\nconst TagInput: React.FC<TagInputProps> = ({\n id,\n label,\n value = [],\n size = \"md\",\n onChange,\n placeholder = \"Type to search or add tags...\",\n error,\n required = false,\n helpText,\n className = \"\",\n disabled = false,\n predefinedTags = [],\n tagBackgroundColor = \"bg-primary\",\n tagTextColor = \"text-white\",\n maxTags,\n allowCustomTags = true,\n ...restProps\n }) => {\n const [inputValue, setInputValue] = useState(\"\");\n const [isDropdownOpen, setIsDropdownOpen] = useState(false);\n const inputRef = useRef<HTMLInputElement>(null);\n const dropdownRef = useRef<HTMLDivElement>(null);\n\n const sizeClasses = {\n sm: \"text-xs px-3 py-1.5 text-sm min-h-[32px]\",\n md: \"text-sm px-4 py-2 text-base min-h-[40px]\",\n lg: \"text-base px-4 py-3 text-lg min-h-[48px]\",\n };\n\n const tagSizeClasses = {\n sm: \"text-xs px-2 py-0.5\",\n md: \"text-sm px-2 py-1\",\n lg: \"text-base px-3 py-1.5\",\n };\n\n const filteredTags = useMemo(() => {\n if (!inputValue) {\n return predefinedTags.filter(tag =>\n !value.some(selectedTag => selectedTag === tag.value)\n );\n }\n\n return predefinedTags.filter(tag =>\n tag.label.toLowerCase().includes(inputValue.toLowerCase()) &&\n !value.some(selectedTag => selectedTag === tag.value)\n );\n }, [inputValue, predefinedTags, value]);\n\n // Handle clicking outside to close dropdown\n useEffect(() => {\n const handleClickOutside = (event: MouseEvent) => {\n if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {\n setIsDropdownOpen(false);\n }\n };\n\n document.addEventListener(\"mousedown\", handleClickOutside);\n return () => document.removeEventListener(\"mousedown\", handleClickOutside);\n }, []);\n\n const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const newValue = e.target.value;\n setInputValue(newValue);\n setIsDropdownOpen(true);\n };\n\n const handleInputKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\n if (e.key === \"Enter\" && inputValue.trim()) {\n e.preventDefault();\n addTag(inputValue.trim());\n } else if (e.key === \"Backspace\" && !inputValue && value.length > 0) {\n // Remove last tag when backspace is pressed and input is empty\n removeTag(value[value.length - 1]);\n } else if (e.key === \"Escape\") {\n setIsDropdownOpen(false);\n setInputValue(\"\");\n }\n };\n\n const addTag = (tagValue: string) => {\n if (!tagValue || (maxTags && value.length >= maxTags)) return;\n\n // Check if tag already exists\n const existingTag = value.find(tag => tag.toLowerCase() === tagValue.toLowerCase());\n if (existingTag) return;\n\n // Check if it's a predefined tag\n const predefinedTag = predefinedTags.find(tag =>\n tag.label.toLowerCase() === tagValue.toLowerCase() ||\n tag.value.toLowerCase() === tagValue.toLowerCase()\n );\n\n let newTag: string;\n if (predefinedTag) {\n newTag = predefinedTag.value;\n } else if (allowCustomTags) {\n newTag = tagValue;\n } else {\n return; // Don't add if custom tags aren't allowed\n }\n\n const newTags = [...value, newTag];\n onChange?.(newTags);\n setInputValue(\"\");\n setIsDropdownOpen(false);\n };\n\n const removeTag = (tagId: string) => {\n const newTags = value.filter(tag => tag !== tagId);\n onChange?.(newTags);\n };\n\n const selectPredefinedTag = (tag: Tag) => {\n addTag(tag.value);\n };\n\n const handleInputFocus = () => {\n setIsDropdownOpen(true);\n };\n\n return (\n <div className=\"mb-4\">\n {label && (\n <label htmlFor={id} className=\"mb-1 block text-sm font-medium text-gray-600 dark:text-gray-300\">\n {label}\n {required && <span className=\"ml-1 text-red-500\">*</span>}\n </label>\n )}\n\n <div className=\"relative\" ref={dropdownRef}>\n <div\n className={`w-full rounded-[12px] border ${\n error ? \"border-red-500\" : \"border-gray-200 dark:border-gray-700\"\n } ${\n disabled\n ? \"bg-gray-100 text-gray-500 dark:bg-gray-800 dark:text-gray-500\"\n : \"bg-gray-100 text-dark dark:bg-gray-800 dark:text-gray-100\"\n } focus-within:outline-none focus-within:ring-1 focus-within:ring-primary ${className} ${sizeClasses[size]} flex flex-wrap items-center gap-1`}\n >\n {/* Render selected tags */}\n {value.map((tag) => (\n <span\n key={tag}\n className={`inline-flex items-center rounded-full ${tagBackgroundColor} ${tagTextColor} ${tagSizeClasses[size]} font-medium`}\n >\n {tag}\n {!disabled && (\n <button\n type=\"button\"\n onClick={() => removeTag(tag)}\n className=\"ml-1 inline-flex h-4 w-4 items-center justify-center rounded-full hover:bg-black hover:bg-opacity-20\"\n >\n <svg className=\"h-3 w-3\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n <path\n fillRule=\"evenodd\"\n d=\"M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z\"\n clipRule=\"evenodd\"\n />\n </svg>\n </button>\n )}\n </span>\n ))}\n\n {/* Input field */}\n <input\n ref={inputRef}\n id={id}\n type=\"text\"\n value={inputValue}\n onChange={handleInputChange}\n onKeyDown={handleInputKeyDown}\n onFocus={handleInputFocus}\n placeholder={value.length === 0 ? placeholder : \"\"}\n disabled={disabled || (maxTags && value.length >= maxTags) as boolean}\n className=\"min-w-[120px] flex-1 border-none bg-transparent outline-none placeholder-gray-400 dark:placeholder-gray-500\"\n aria-invalid={!!error}\n aria-describedby={error ? `${value}-error` : helpText ? `${value}-help` : undefined}\n />\n </div>\n\n {/* Dropdown */}\n {isDropdownOpen && !disabled && (filteredTags.length > 0 || (inputValue && allowCustomTags)) && (\n <div className=\"absolute z-10 mt-1 max-h-60 w-full overflow-auto rounded-[12px] border border-gray-200 bg-white/95 p-4 shadow-lg backdrop-blur-sm dark:border-gray-700 dark:bg-gray-900/95\">\n {/* Predefined tags */}\n {filteredTags.length > 0 && (\n <div className=\"flex flex-wrap gap-2 mb-3\">\n {filteredTags.map((tag) => (\n <button\n key={tag.value}\n type=\"button\"\n onClick={() => selectPredefinedTag(tag)}\n className={`inline-flex items-center rounded-full bg-gray-200 text-gray-700 transition-colors duration-200 hover:bg-gray-300 dark:bg-gray-700 dark:text-gray-200 dark:hover:bg-gray-600 ${tagSizeClasses[size]} font-medium`}\n >\n {tag.label}\n </button>\n ))}\n </div>\n )}\n\n {/* Custom tag option */}\n {inputValue && allowCustomTags && !predefinedTags.some(tag =>\n tag.label.toLowerCase() === inputValue.toLowerCase()\n ) && (\n <>\n {filteredTags.length > 0 && (\n <div className=\"mb-2 border-t border-gray-100 pt-3 dark:border-gray-700\">\n <span className=\"text-xs font-medium text-gray-500 dark:text-gray-400\">CREATE NEW TAG</span>\n </div>\n )}\n <div className=\"flex flex-wrap gap-2\">\n <button\n type=\"button\"\n onClick={() => addTag(inputValue)}\n className={`inline-flex items-center rounded-full bg-blue-100 text-blue-700 hover:bg-blue-200 transition-colors duration-200 ${tagSizeClasses[size]} font-medium border border-blue-200`}\n >\n <svg className=\"w-3 h-3 mr-1\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n <path fillRule=\"evenodd\" d=\"M10 3a1 1 0 011 1v5h5a1 1 0 110 2h-5v5a1 1 0 11-2 0v-5H4a1 1 0 110-2h5V4a1 1 0 011-1z\" clipRule=\"evenodd\" />\n </svg>\n {inputValue}\n </button>\n </div>\n </>\n )}\n\n {/* Empty state */}\n {filteredTags.length === 0 && (!inputValue || !allowCustomTags) && (\n <div className=\"py-4 text-center text-sm text-gray-500 dark:text-gray-400\">\n No matching tags found\n </div>\n )}\n </div>\n )}\n </div>\n\n {maxTags && (\n <div className=\"mt-1 text-xs text-gray-500 dark:text-gray-400\">\n {value.length}/{maxTags} tags\n </div>\n )}\n\n {helpText && !error && (\n <p id={`${value}-help`} className=\"mt-1 text-sm text-gray-500 dark:text-gray-400\">\n {helpText}\n </p>\n )}\n\n {error && (\n <p id={`${value}-error`} className=\"mt-1 text-sm text-red-500\">\n {error}\n </p>\n )}\n </div>\n );\n};\n\n// Demo component to show usage\nexport const TagInputDemo = () => {\n const [selectedTags, setSelectedTags] = useState<string[]>([]);\n const [selectedTags2, setSelectedTags2] = useState<string[]>([]);\n\n const predefinedTags: Tag[] = [\n { label: \"React\", value: \"react\" },\n { label: \"JavaScript\", value: \"javascript\" },\n { label: \"TypeScript\", value: \"typescript\" },\n { label: \"Node.js\", value: \"nodejs\" },\n { label: \"Python\", value: \"python\" },\n { label: \"CSS\", value: \"css\" },\n { label: \"HTML\", value: \"html\" },\n { label: \"Vue.js\", value: \"vuejs\" },\n { label: \"Angular\", value: \"angular\" },\n { label: \"Next.js\", value: \"nextjs\" },\n ];\n\n return (\n <div className=\"max-w-2xl mx-auto p-6 bg-gray-50 min-h-screen\">\n <h1 className=\"text-2xl font-bold mb-8 text-gray-900\">TagInput Component Demo</h1>\n\n <div className=\"space-y-8\">\n <TagInput\n id=\"skills\"\n label=\"Skills & Technologies\"\n value={selectedTags}\n onChange={setSelectedTags}\n predefinedTags={predefinedTags}\n placeholder=\"Search or add skills...\"\n helpText=\"Select from predefined options or add your own custom tags\"\n size=\"md\"\n />\n\n <TagInput\n id=\"custom-tags\"\n label=\"Project Categories (Custom Colors)\"\n value={selectedTags2}\n onChange={setSelectedTags2}\n predefinedTags={[\n { label: \"Web Development\", value: \"web\" },\n { label: \"Mobile App\", value: \"mobile\" },\n { label: \"AI/ML\", value: \"ai\" },\n { label: \"UI/UX Design\", value: \"design\" },\n ]}\n placeholder=\"Add project categories...\"\n tagBackgroundColor=\"bg-purple-500\"\n tagTextColor=\"text-white\"\n maxTags={5}\n size=\"lg\"\n helpText=\"Maximum 5 tags allowed with custom purple styling\"\n />\n\n <div className=\"mt-8 p-4 bg-white rounded-lg border\">\n <h3 className=\"font-medium mb-2\">Selected Skills:</h3>\n <pre className=\"text-sm bg-gray-100 p-2 rounded\">\n {JSON.stringify(selectedTags, null, 2)}\n </pre>\n </div>\n\n <div className=\"p-4 bg-white rounded-lg border\">\n <h3 className=\"font-medium mb-2\">Selected Categories:</h3>\n <pre className=\"text-sm bg-gray-100 p-2 rounded\">\n {JSON.stringify(selectedTags2, null, 2)}\n </pre>\n </div>\n </div>\n </div>\n );\n};\n\nexport default TagInput;\n"],"names":["TagInput","_a","id","label","_b","value","_c","size","onChange","_d","placeholder","error","_e","required","helpText","_f","className","_g","disabled","_h","predefinedTags","_j","tagBackgroundColor","_k","tagTextColor","maxTags","_l","allowCustomTags","__rest","_m","useState","inputValue","setInputValue","_o","isDropdownOpen","setIsDropdownOpen","inputRef","useRef","dropdownRef","tagSizeClasses","sm","md","lg","filteredTags","useMemo","filter","tag","toLowerCase","includes","some","selectedTag","useEffect","handleClickOutside","event","current","contains","target","document","addEventListener","removeEventListener","addTag","tagValue","length","find","newTag","predefinedTag","newTags","__spreadArray","removeTag","tagId","_jsxs","htmlFor","children","_jsx","ref","concat","map","type","onClick","fill","viewBox","fillRule","d","clipRule","e","newValue","onKeyDown","key","trim","preventDefault","onFocus","undefined","selectPredefinedTag","_Fragment","TagInputDemo","selectedTags","setSelectedTags","selectedTags2","setSelectedTags2","JSON","stringify"],"mappings":"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"}
|