UNPKG

@razorpay/blade

Version:

The Design System that powers Razorpay

1,222 lines (1,185 loc) 42.6 kB
import _defineProperty from '@babel/runtime/helpers/defineProperty'; import _slicedToArray from '@babel/runtime/helpers/slicedToArray'; import _taggedTemplateLiteral from '@babel/runtime/helpers/taggedTemplateLiteral'; import { memo, useMemo, useState } from 'react'; import { ErrorBoundary } from 'react-error-boundary'; import dayjs from 'dayjs'; import { formatNumber } from '@razorpay/i18nify-js'; import ReactMarkdown from 'react-markdown'; import { createGlobalStyle } from 'styled-components'; import { useGenUIAnimation, useGenUIAction } from './GenUIContext.web.js'; import { ComponentRenderer } from './GenUISchemaRenderer.web.js'; import { createRehypeAnimate } from './rehypeAnimate.js'; import '../Box/index.js'; import '../Typography/index.js'; import '../Skeleton/index.js'; import '../Card/index.js'; import '../Badge/index.js'; import '../Divider/index.js'; import '../Charts/index.js'; import '../Table/index.js'; import '../Link/index.js'; import '../Icons/index.js'; import '../InfoGroup/index.js'; import '../Button/index.js'; import '../Button/IconButton/index.js'; import '../Amount/index.js'; import '../Indicator/index.js'; import '../Alert/index.js'; import '../Tooltip/index.js'; import { jsx, jsxs, Fragment } from 'react/jsx-runtime'; import { Box } from '../Box/Box.js'; import { Text } from '../Typography/Text/Text.js'; import { Skeleton } from '../Skeleton/Skeleton.js'; import { Heading } from '../Typography/Heading/Heading.js'; import Link from '../Link/Link/Link.js'; import DotIcon from '../Icons/DotIcon/DotIcon.js'; import { Divider } from '../Divider/Divider.js'; import { ChartBarWrapper, ChartBar } from '../Charts/BarChart/BarChart.web.js'; import { ChartCartesianGrid, ChartXAxis, ChartYAxis, ChartLegend, ChartTooltip } from '../Charts/CommonChartComponents/CommonChartComponents.web.js'; import { ChartLineWrapper, ChartLine } from '../Charts/LineChart/LineChart.web.js'; import { ChartAreaWrapper, ChartArea } from '../Charts/AreaChart/AreaChart.web.js'; import { ChartDonutWrapper, ChartDonut } from '../Charts/DonutChart/DonutChart.web.js'; import { Tooltip } from '../Tooltip/Tooltip.web.js'; import { TooltipInteractiveWrapper } from '../Tooltip/TooltipInteractiveWrapper.web.js'; import { IconButton } from '../Button/IconButton/IconButton.js'; import CopyIcon from '../Icons/CopyIcon/CopyIcon.js'; import { Badge } from '../Badge/Badge.js'; import { Indicator } from '../Indicator/Indicator.js'; import { Amount } from '../Amount/Amount.js'; import CheckIcon from '../Icons/CheckIcon/CheckIcon.js'; import CloseIcon from '../Icons/CloseIcon/CloseIcon.js'; import EditIcon from '../Icons/EditIcon/EditIcon.js'; import TrashIcon from '../Icons/TrashIcon/TrashIcon.js'; import DownloadIcon from '../Icons/DownloadIcon/DownloadIcon.js'; import EyeIcon from '../Icons/EyeIcon/EyeIcon.js'; import Button from '../Button/Button/Button.js'; import { Table } from '../Table/Table.web.js'; import { TableHeader, TableHeaderRow, TableHeaderCell } from '../Table/TableHeader.web.js'; import { TableBody, TableRow, TableCell } from '../Table/TableBody.web.js'; import { Card, CardBody } from '../Card/Card.js'; import { CardHeader, CardHeaderLeading } from '../Card/CardHeader.js'; import { CardFooter, CardFooterLeading } from '../Card/CardFooter.js'; import { InfoGroup, InfoItem, InfoItemKey, InfoItemValue } from '../InfoGroup/InfoGroup.web.js'; import InfoIcon from '../Icons/InfoIcon/InfoIcon.js'; import AlertTriangleIcon from '../Icons/AlertTriangleIcon/AlertTriangleIcon.js'; import CheckCircleIcon from '../Icons/CheckCircleIcon/CheckCircleIcon.js'; import { Alert } from '../Alert/Alert.js'; var _templateObject; function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } var TextAnimationStyles = /*#__PURE__*/createGlobalStyle(_templateObject || (_templateObject = _taggedTemplateLiteral(["\n @keyframes animate-fadeIn {\n from {\n opacity: 0;\n color: #48D08C;\n filter: blur(2px);\n }\n to {\n opacity: 1;\n color: inherit;\n filter: blur(0px);\n }\n }\n\n [data-animate-word] {\n display: inline-block;\n animation: animate-fadeIn\n var(--animate-duration, 400ms)\n var(--animate-easing, ease) both;\n }\n"]))); /** * Built-in component types supported by GenUI */ var ComponentType = { TEXT: 'TEXT', CHART: 'CHART', TABLE: 'TABLE', CARD: 'CARD', BADGE: 'BADGE', SPACER: 'SPACER', DIVIDER: 'DIVIDER', STACK: 'STACK', GRID: 'GRID', INFO_GROUP: 'INFO_GROUP', BUTTON: 'BUTTON', LINK: 'LINK', ALERT: 'ALERT', AMOUNT: 'AMOUNT' }; /** * Valid feedback colors used across GenUI components (Badge, Indicator, Alert) * Used to validate streaming JSON where color values might be partial/incomplete */ var FeedbackColors = ['information', 'negative', 'neutral', 'notice', 'positive', 'primary']; var getValidFeedbackColor = function getValidFeedbackColor(color) { var fallback = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'neutral'; if (!color) return fallback; if (FeedbackColors.includes(color)) { return color; } return fallback; }; // Table cell component types (using component pattern) // Table row action schema type // Event payload dispatched when table row actions are triggered /** * Union type of all built-in UI components */ /** * Generic UI component type - can be extended with custom components */ var ComponentErrorFallback = function ComponentErrorFallback() { return /*#__PURE__*/jsx(Box, { textAlign: "center", display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", height: "100%", width: "100%", children: /*#__PURE__*/jsx(Text, { size: "medium", weight: "semibold", children: "Error rendering component" }) }); }; var ChartSkeletonLoader = function ChartSkeletonLoader(_ref) { var title = _ref.title, isTiny = _ref.isTiny, _ref$chartHeight = _ref.chartHeight, chartHeight = _ref$chartHeight === void 0 ? '350px' : _ref$chartHeight; return /*#__PURE__*/jsxs(Box, { width: "100%", display: "flex", flexDirection: "column", gap: "spacing.3", marginY: "spacing.3", children: [title && !isTiny ? /*#__PURE__*/jsx(Skeleton, { width: "200px", height: "24px", borderRadius: "medium", marginBottom: "spacing.3" }) : null, /*#__PURE__*/jsxs(Box, { width: "100%", height: chartHeight, display: "flex", flexDirection: "column", gap: "spacing.3", children: [/*#__PURE__*/jsxs(Box, { display: "flex", flexDirection: "row", gap: "spacing.3", height: "100%", children: [/*#__PURE__*/jsx(Skeleton, { width: "40px", height: "100%", borderRadius: "medium" }), /*#__PURE__*/jsx(Skeleton, { width: "100%", height: "100%", borderRadius: "medium" })] }), /*#__PURE__*/jsx(Skeleton, { width: "100%", height: "40px", borderRadius: "medium" })] })] }); }; /** * Stable components object for ReactMarkdown to prevent re-renders during streaming. * Defined outside the component to maintain referential equality. */ var markdownComponents = { h1: function h1(_ref2) { var children = _ref2.children; return /*#__PURE__*/jsx(Heading, { marginBottom: "spacing.4", size: "large", children: children }); }, h2: function h2(_ref3) { var children = _ref3.children; return /*#__PURE__*/jsx(Heading, { marginBottom: "spacing.3", size: "medium", children: children }); }, h3: function h3(_ref4) { var children = _ref4.children; return /*#__PURE__*/jsx(Heading, { marginBottom: "spacing.3", size: "small", children: children }); }, h4: function h4(_ref5) { var children = _ref5.children; return /*#__PURE__*/jsx(Heading, { marginBottom: "spacing.3", size: "small", children: children }); }, b: function b(_ref6) { var children = _ref6.children; return /*#__PURE__*/jsx(Text, { size: "medium", weight: "semibold", color: "surface.text.gray.subtle", children: children }); }, a: function a(_ref7) { var href = _ref7.href, children = _ref7.children; return /*#__PURE__*/jsx(Link, { href: href, size: "medium", variant: "anchor", color: "primary", target: "_blank", rel: "noopener noreferrer", children: children }); }, li: function li(_ref8) { var children = _ref8.children; return /*#__PURE__*/jsxs(Text, { marginY: "spacing.3", size: "medium", children: [/*#__PURE__*/jsx(DotIcon, { marginBottom: "1px", size: "xsmall" }), " ", children] }); }, ol: function ol(_ref9) { var children = _ref9.children; return /*#__PURE__*/jsx(Box, { display: "flex", flexDirection: "column", marginLeft: "spacing.4", children: children }); }, ul: function ul(_ref0) { var children = _ref0.children; return /*#__PURE__*/jsx(Box, { display: "flex", flexDirection: "column", marginLeft: "spacing.4", children: children }); }, hr: function hr() { return /*#__PURE__*/jsx(Divider, { marginY: "spacing.4" }); }, i: function i(_ref1) { var children = _ref1.children; return /*#__PURE__*/jsx(Text, { size: "medium", variant: "caption", color: "surface.text.gray.subtle", children: children }); }, p: function p(_ref10) { var children = _ref10.children; return /*#__PURE__*/jsx(Text, { marginY: "spacing.2", size: "medium", color: "surface.text.gray.subtle", children: children }); } }; var RenderTextComponent = /*#__PURE__*/memo(function (_ref11) { var content = _ref11.content; var _useGenUIAnimation = useGenUIAnimation(), isAnimating = _useGenUIAnimation.isAnimating, animateOptions = _useGenUIAnimation.animateOptions; var rehypePlugins = useMemo(function () { if (!isAnimating) return []; return [createRehypeAnimate(animateOptions)]; }, [isAnimating, animateOptions]); if (!content) return null; return /*#__PURE__*/jsxs(Fragment, { children: [isAnimating ? /*#__PURE__*/jsx(TextAnimationStyles, {}) : null, /*#__PURE__*/jsx(ReactMarkdown, { skipHtml: true, rehypePlugins: rehypePlugins, components: markdownComponents, children: content })] }); }); var RenderChartComponent = /*#__PURE__*/memo(function (_ref12) { var chartType = _ref12.chartType, title = _ref12.title, xAxis = _ref12.xAxis, data = _ref12.data, _ref12$unit = _ref12.unit, unit = _ref12$unit === void 0 ? '' : _ref12$unit, _ref12$variant = _ref12.variant, variant = _ref12$variant === void 0 ? 'full' : _ref12$variant, valueFormatter = _ref12.valueFormatter; var isTiny = variant === 'tiny'; var chartHeight = isTiny ? '100px' : '350px'; var minHeight = isTiny ? '100px' : '350px'; var isLoading = !chartType || !xAxis || !data || data.length === 0 || !valueFormatter || !valueFormatter.type; // Handle incomplete data during streaming if (isLoading) { return /*#__PURE__*/jsx(ChartSkeletonLoader, { title: title, isTiny: isTiny, chartHeight: chartHeight }); } // Filter out empty objects and incomplete data from streaming var validData = data.filter(function (item) { if (!item || Object.keys(item).length === 0) return false; // Check if xAxis key exists and has a valid value if (!item[xAxis] || item[xAxis] === '') return false; // Check if at least one numeric value exists var hasNumericValue = Object.keys(item).some(function (key) { return key !== xAxis && typeof item[key] === 'number' && !isNaN(Number(item[key])); }); return hasNumericValue; }); if (validData.length === 0) { return /*#__PURE__*/jsx(ChartSkeletonLoader, { title: title, isTiny: isTiny, chartHeight: chartHeight }); } // Auto-detect all numeric keys except xAxis for plotting var firstItem = validData[0]; var keysToPlot = Object.keys(firstItem).filter(function (key) { return key !== xAxis && typeof firstItem[key] === 'number'; }); if (keysToPlot.length === 0) { return /*#__PURE__*/jsx(ChartSkeletonLoader, { title: title, isTiny: isTiny, chartHeight: chartHeight }); } var tickFormatter = function tickFormatter(value) { var numValue = typeof value === 'string' ? parseFloat(value) : value; if (isNaN(numValue)) { return value.toString(); } // Use valueFormatter if provided, otherwise fall back to unit if (valueFormatter) { var type = valueFormatter.type, formatterCurrency = valueFormatter.currency, formatterSuffix = valueFormatter.suffix; var buildPrefixSuffixString = function buildPrefixSuffixString(v) { return "".concat(v).concat(formatterSuffix !== null && formatterSuffix !== void 0 ? formatterSuffix : ''); }; try { switch (type) { case 'currency': { var formatted = formatNumber(numValue, { currency: formatterCurrency || 'INR', intlOptions: { notation: 'compact', maximumFractionDigits: 1 } }); return buildPrefixSuffixString(formatted); } case 'percentage': { var _formatted = formatNumber(numValue / 100, { intlOptions: { style: 'percent', minimumFractionDigits: 0, maximumFractionDigits: 2 } }); if (formatterSuffix === '%') { return _formatted; } else { return buildPrefixSuffixString(_formatted); } } case 'number': { var numberFormatted = formatNumber(numValue, { intlOptions: { minimumFractionDigits: 0, maximumFractionDigits: 2 } }); return buildPrefixSuffixString(numberFormatted); } case 'string': { return buildPrefixSuffixString(numValue.toString()); } default: return numValue.toString(); } } catch (error) { console.error('[GenUI Chart]: Error formatting value:', error); return numValue.toString(); } } // Fallback to legacy unit formatting return "".concat(numValue.toString()).concat(unit); }; // TODO: Refactor into smaller components return /*#__PURE__*/jsx(ErrorBoundary, { FallbackComponent: ComponentErrorFallback, children: /*#__PURE__*/jsxs(Box, { width: "100%", display: "flex", flexDirection: "column", gap: "spacing.3", marginY: "spacing.3", minHeight: chartHeight, children: [title && !isTiny ? /*#__PURE__*/jsx(Text, { size: "large", weight: "semibold", color: "surface.text.gray.subtle", marginBottom: "spacing.3", children: title }) : null, /*#__PURE__*/jsx(Box, { width: "100%", height: chartHeight, minHeight: minHeight, children: chartType === 'bar' ? /*#__PURE__*/jsxs(ChartBarWrapper, { width: "100%", height: chartHeight, data: validData, colorTheme: "categorical", children: [!isTiny ? /*#__PURE__*/jsx(ChartCartesianGrid, {}) : null, !isTiny ? /*#__PURE__*/jsx(ChartXAxis, { dataKey: xAxis }) : null, !isTiny ? /*#__PURE__*/jsx(ChartYAxis, { tickFormatter: tickFormatter }) : null, keysToPlot.map(function (key) { return /*#__PURE__*/jsx(ChartBar, { dataKey: key, name: key }, key); }), !isTiny ? /*#__PURE__*/jsx(ChartLegend, {}) : null, !isTiny ? /*#__PURE__*/jsx(ChartTooltip, {}) : null] }) : chartType === 'line' ? /*#__PURE__*/jsxs(ChartLineWrapper, { width: "100%", height: chartHeight, minHeight: minHeight, data: validData, colorTheme: "categorical", children: [!isTiny ? /*#__PURE__*/jsx(ChartCartesianGrid, {}) : null, !isTiny ? /*#__PURE__*/jsx(ChartXAxis, { dataKey: xAxis }) : null, !isTiny ? /*#__PURE__*/jsx(ChartYAxis, { tickFormatter: tickFormatter }) : null, keysToPlot.map(function (key) { return /*#__PURE__*/jsx(ChartLine, { dataKey: key, name: key }, key); }), !isTiny ? /*#__PURE__*/jsx(ChartLegend, {}) : null, !isTiny ? /*#__PURE__*/jsx(ChartTooltip, {}) : null] }) : chartType === 'area' ? /*#__PURE__*/jsxs(ChartAreaWrapper, { width: "100%", height: chartHeight, minHeight: minHeight, data: validData, colorTheme: "categorical", children: [!isTiny ? /*#__PURE__*/jsx(ChartCartesianGrid, {}) : null, !isTiny ? /*#__PURE__*/jsx(ChartXAxis, { dataKey: xAxis }) : null, !isTiny ? /*#__PURE__*/jsx(ChartYAxis, { tickFormatter: tickFormatter }) : null, keysToPlot.map(function (key) { return /*#__PURE__*/jsx(ChartArea, { dataKey: key, name: key, type: "monotone" }, key); }), !isTiny ? /*#__PURE__*/jsx(ChartLegend, {}) : null, !isTiny ? /*#__PURE__*/jsx(ChartTooltip, {}) : null] }) : chartType === 'pie' ? /*#__PURE__*/jsxs(ChartDonutWrapper, { width: "100%", height: chartHeight, minHeight: minHeight, children: [/*#__PURE__*/jsx(ChartDonut, { dataKey: keysToPlot[0], nameKey: xAxis, data: validData, radius: "medium", type: "circle" }), !isTiny ? /*#__PURE__*/jsx(ChartLegend, {}) : null, !isTiny ? /*#__PURE__*/jsx(ChartTooltip, {}) : null] }) : null })] }) }); }, // Custom comparison - only re-render if data length or key fields change function (prevProps, nextProps) { var _prevProps$data, _nextProps$data, _prevProps$data2, _nextProps$data2; return prevProps.chartType === nextProps.chartType && prevProps.title === nextProps.title && prevProps.xAxis === nextProps.xAxis && prevProps.variant === nextProps.variant && ((_prevProps$data = prevProps.data) === null || _prevProps$data === void 0 ? void 0 : _prevProps$data.length) === ((_nextProps$data = nextProps.data) === null || _nextProps$data === void 0 ? void 0 : _nextProps$data.length) && JSON.stringify((_prevProps$data2 = prevProps.data) === null || _prevProps$data2 === void 0 ? void 0 : _prevProps$data2[prevProps.data.length - 1]) === JSON.stringify((_nextProps$data2 = nextProps.data) === null || _nextProps$data2 === void 0 ? void 0 : _nextProps$data2[nextProps.data.length - 1]) && JSON.stringify(prevProps.valueFormatter) === JSON.stringify(nextProps.valueFormatter); }); // Primitive copy button — just the icon + tooltip, no text label. // Compose this inside any cell that needs copy behaviour. var Copyable = function Copyable(_ref13) { var value = _ref13.value; var _useState = useState(false), _useState2 = _slicedToArray(_useState, 2), copied = _useState2[0], setCopied = _useState2[1]; var handleCopy = function handleCopy() { void navigator.clipboard.writeText(value !== null && value !== void 0 ? value : ''); setCopied(true); setTimeout(function () { return setCopied(false); }, 2000); }; return /*#__PURE__*/jsx(Tooltip, { content: copied ? 'Copied!' : 'Copy', placement: "top", children: /*#__PURE__*/jsx(TooltipInteractiveWrapper, { children: /*#__PURE__*/jsx(IconButton, { icon: CopyIcon, size: "medium", emphasis: "intense", accessibilityLabel: "Copy ".concat(value), onClick: handleCopy }) }) }); }; // Text + copy icon var CopyableText = function CopyableText(_ref14) { var value = _ref14.value; return /*#__PURE__*/jsxs(Box, { display: "flex", alignItems: "center", gap: "spacing.2", children: [/*#__PURE__*/jsx(Text, { size: "medium", children: value !== null && value !== void 0 ? value : '-' }), /*#__PURE__*/jsx(Copyable, { value: value })] }); }; // Table cell link renderer - fires action for consumer to handle var TableCellLinkRenderer = function TableCellLinkRenderer(_ref15) { var _cell$text; var cell = _ref15.cell; var onActionClick = useGenUIAction(); var linkNode = cell !== null && cell !== void 0 && cell.action ? /*#__PURE__*/jsx(Link, { variant: "button", onClick: function onClick() { if (onActionClick && cell.action) { onActionClick(cell.action); } }, children: (_cell$text = cell.text) !== null && _cell$text !== void 0 ? _cell$text : '' }) : /*#__PURE__*/jsx(Text, { size: "medium", children: cell === null || cell === void 0 ? void 0 : cell.text }); if (cell !== null && cell !== void 0 && cell.copyable && cell !== null && cell !== void 0 && cell.text) { return /*#__PURE__*/jsxs(Box, { display: "flex", alignItems: "center", gap: "spacing.2", children: [linkNode, /*#__PURE__*/jsx(Copyable, { value: cell.text })] }); } return linkNode; }; // Helper to render a single table cell based on its component type var RenderTableCellContent = function RenderTableCellContent(_ref16) { var cell = _ref16.cell; if (!cell) { return /*#__PURE__*/jsx(Text, { size: "medium", children: "-" }); } // Handle incomplete cell object during streaming if (!cell.component) { return /*#__PURE__*/jsx(Text, { size: "medium", children: "-" }); } // Handle component-based cell types switch (cell.component) { case 'TEXT': { var _cell$value; if (cell.copyable && cell.value) { return /*#__PURE__*/jsx(CopyableText, { value: cell.value }); } return /*#__PURE__*/jsx(Text, { size: "medium", children: (_cell$value = cell.value) !== null && _cell$value !== void 0 ? _cell$value : '-' }); } case 'AMOUNT': { var currency = cell.currency || 'INR'; // Ensure value is a valid number (handle streaming where value might be string/undefined) var numValue = typeof cell.value === 'string' ? parseFloat(cell.value) : cell.value; if (typeof numValue !== 'number' || isNaN(numValue)) { return /*#__PURE__*/jsx(Text, { size: "medium", children: "-" }); } return /*#__PURE__*/jsx(Amount, { value: numValue, currency: currency, size: "medium" }); } case 'INDICATOR': { // Handle streaming where value might be incomplete if (!cell.value) { return /*#__PURE__*/jsx(Text, { size: "medium", children: "-" }); } var indicatorColor = getValidFeedbackColor(cell.color, 'neutral'); return /*#__PURE__*/jsxs(Box, { display: "flex", alignItems: "center", gap: "spacing.3", children: [/*#__PURE__*/jsx(Indicator, { accessibilityLabel: cell.value, color: indicatorColor }), /*#__PURE__*/jsx(Text, { size: "medium", children: cell.value })] }); } case 'BADGE': { var badgeColor = getValidFeedbackColor(cell.color, 'neutral'); return /*#__PURE__*/jsx(Badge, { color: badgeColor, emphasis: "subtle", children: cell.value || '-' }); } case 'DATE': { // Handle streaming where value might be incomplete if (!cell.value) { return /*#__PURE__*/jsx(Text, { size: "medium", children: "-" }); } // Parse the date value using dayjs var dateValue = dayjs(cell.value); // Check if date is valid if (!dateValue.isValid()) { return /*#__PURE__*/jsx(Text, { size: "medium", children: cell.value }); } // Use custom dateFormat if provided, otherwise use default // Format tokens: https://day.js.org/docs/en/display/format var defaultFormat = 'DD MMM YYYY, HH:mm'; var formatted = dateValue.format(cell.dateFormat || defaultFormat); return /*#__PURE__*/jsx(Text, { size: "medium", children: formatted }); } case 'LINK': { // Handle streaming where text might be incomplete if (!cell.text) { return /*#__PURE__*/jsx(Text, { size: "medium", children: "-" }); } return /*#__PURE__*/jsx(TableCellLinkRenderer, { cell: cell }); } default: // Handle unknown component types during streaming return /*#__PURE__*/jsx(Text, { size: "medium", children: String(cell.value || '-') }); } }; // Icon mapping for row actions var rowActionIconMap = { check: CheckIcon, close: CloseIcon, edit: EditIcon, "delete": TrashIcon, download: DownloadIcon, view: EyeIcon, copy: CopyIcon }; // Separate component for table row hover actions to avoid render issues var TableRowHoverActions = function TableRowHoverActions(_ref17) { var rowActions = _ref17.rowActions, rowIndex = _ref17.rowIndex, rowData = _ref17.rowData; var onActionClick = useGenUIAction(); var createActionEvent = function createActionEvent(eventName) { return { type: 'TABLE_ROW_ACTION', eventName: eventName, data: { rowIndex: rowIndex, rowData: rowData } }; }; return /*#__PURE__*/jsx(Fragment, { children: rowActions.map(function (rowAction, index) { // Guard: Skip incomplete button actions during streaming if (rowAction.type === 'BUTTON') { if (!rowAction.text) return null; return /*#__PURE__*/jsx(Button, { variant: "tertiary", size: "xsmall", onClick: function onClick() { var _rowAction$action; if ((_rowAction$action = rowAction.action) !== null && _rowAction$action !== void 0 && _rowAction$action.eventName && onActionClick) { onActionClick(createActionEvent(rowAction.action.eventName)); } }, children: rowAction.text }, index); } // Guard: Skip incomplete icon button actions during streaming if (rowAction.type === 'ICON_BUTTON') { var IconComponent = rowAction.icon ? rowActionIconMap[rowAction.icon] : null; if (!IconComponent || !rowAction.accessibilityLabel) return null; return /*#__PURE__*/jsx(IconButton, { icon: IconComponent, size: "medium", emphasis: "intense", accessibilityLabel: rowAction.accessibilityLabel, onClick: function onClick() { var _rowAction$action2; if ((_rowAction$action2 = rowAction.action) !== null && _rowAction$action2 !== void 0 && _rowAction$action2.eventName && onActionClick) { onActionClick(createActionEvent(rowAction.action.eventName)); } } }, index); } return null; }) }); }; // Produces column widths using minmax(max-content, 1fr) so columns: // 1. Never shrink below their content width (no text wrapping) // 2. Expand proportionally to fill available width when space permits var calculateColumnWidths = function calculateColumnWidths(headers, _rows) { return headers.map(function () { return 'minmax(max-content, 1fr)'; }); }; var RenderTableComponent = /*#__PURE__*/memo(function (_ref18) { var headers = _ref18.headers, rows = _ref18.rows, rowActions = _ref18.rowActions; var columnWidths = useMemo(function () { return headers && rows ? calculateColumnWidths(headers, rows) : []; }, [headers, rows]); if (!headers || !rows || headers.length === 0 || rows.length === 0) { return null; } // Transform rows into table data format with id var tableData = { nodes: rows.map(function (row, index) { return { id: "row-".concat(index), cells: row }; }) }; return /*#__PURE__*/jsx(Box, { display: "flex", flexDirection: "column", gap: "spacing.3", children: /*#__PURE__*/jsx(Table, { data: tableData, backgroundColor: "transparent", rowDensity: "compact", gridTemplateColumns: columnWidths.join(' '), children: function children(data) { return /*#__PURE__*/jsxs(Fragment, { children: [/*#__PURE__*/jsx(TableHeader, { children: /*#__PURE__*/jsx(TableHeaderRow, { children: headers.map(function (header, index) { return /*#__PURE__*/jsx(TableHeaderCell, { children: header }, index); }) }) }), /*#__PURE__*/jsx(TableBody, { children: data.map(function (item, rowIndex) { return /*#__PURE__*/jsx(TableRow, { item: item // eslint-disable-next-line @typescript-eslint/no-empty-function , onHover: rowActions && rowActions.length > 0 ? function () {} : undefined, hoverActions: rowActions && rowActions.length > 0 ? /*#__PURE__*/jsx(TableRowHoverActions, { rowActions: rowActions, rowIndex: rowIndex, rowData: item.cells }) : undefined, children: item.cells.map(function (cell, cellIndex) { return /*#__PURE__*/jsx(TableCell, { children: /*#__PURE__*/jsx(RenderTableCellContent, { cell: cell }) }, cellIndex); }) }, rowIndex); }) })] }); } }) }); }); var RenderCardComponent = /*#__PURE__*/memo(function (_ref19) { var title = _ref19.title, description = _ref19.description, footer = _ref19.footer, children = _ref19.children; var hasHeader = title || description; return /*#__PURE__*/jsx(Box, { height: "100%", display: "flex", flexDirection: "column", gap: "spacing.3", children: /*#__PURE__*/jsxs(Card, { width: "100%", height: "100%", padding: "spacing.7", children: [hasHeader ? /*#__PURE__*/jsx(CardHeader, { children: /*#__PURE__*/jsx(CardHeaderLeading, { title: title || '', subtitle: description || '' }) }) : null, children && children.length > 0 ? /*#__PURE__*/jsx(CardBody, { height: "100%", children: /*#__PURE__*/jsx(Box, { display: "flex", flexDirection: "column", gap: "spacing.5", children: children.map(function (child, index) { return /*#__PURE__*/jsx(GenUIComponentRenderer, { component: child, index: index }, index); }) }) }) : null, footer ? /*#__PURE__*/jsx(CardFooter, { showDivider: true, children: /*#__PURE__*/jsx(CardFooterLeading, { subtitle: footer }) }) : null] }) }); }); var RenderBadgeComponent = /*#__PURE__*/memo(function (_ref20) { var text = _ref20.text, color = _ref20.color; if (!text) return null; return /*#__PURE__*/jsx(Badge, { color: color || 'neutral', emphasis: "subtle", children: text }); }); var RenderSpacerComponent = /*#__PURE__*/memo(function (_ref21) { var size = _ref21.size; if (!size) return null; var sizeMap = { small: 'spacing.2', medium: 'spacing.4', large: 'spacing.5' }; return /*#__PURE__*/jsx(Box, { height: sizeMap[size], width: sizeMap[size] }); }); var RenderDividerComponent = /*#__PURE__*/memo(function (_ref22) { var _ref22$orientation = _ref22.orientation, orientation = _ref22$orientation === void 0 ? 'horizontal' : _ref22$orientation; return /*#__PURE__*/jsx(Box, { display: "flex", paddingY: "spacing.4", children: /*#__PURE__*/jsx(Divider, _objectSpread({ orientation: orientation }, orientation === 'vertical' ? { height: '24px' } : {})) }); }); var RenderStackComponent = /*#__PURE__*/memo(function (_ref23) { var _ref23$direction = _ref23.direction, direction = _ref23$direction === void 0 ? 'vertical' : _ref23$direction, gap = _ref23.gap, children = _ref23.children; if (!children || children.length === 0) { return null; } var sizeMap = { small: 'spacing.2', medium: 'spacing.4', large: 'spacing.5' }; return /*#__PURE__*/jsx(Box, { display: "flex", width: "100%", paddingY: "spacing.3", flexDirection: direction === 'vertical' ? 'column' : 'row', gap: sizeMap[gap !== null && gap !== void 0 ? gap : 'small'], children: children.map(function (child, index) { return /*#__PURE__*/jsx(GenUIComponentRenderer, { component: child, index: index }, index); }) }); }); var RenderGridComponent = /*#__PURE__*/memo(function (_ref24) { var columns = _ref24.columns, gap = _ref24.gap, children = _ref24.children; if (!columns || !children || children.length === 0) { return null; } var sizeMap = { small: 'spacing.2', medium: 'spacing.4', large: 'spacing.5' }; return /*#__PURE__*/jsx(Box, { display: "grid", width: "100%", marginY: "spacing.3", gridTemplateColumns: "repeat(".concat(columns, ", 1fr)"), gap: sizeMap[gap !== null && gap !== void 0 ? gap : 'small'], children: children.map(function (child, index) { return /*#__PURE__*/jsx(GenUIComponentRenderer, { component: child, index: index }, index); }) }); }); var RenderInfoGroupComponent = /*#__PURE__*/memo(function (_ref25) { var items = _ref25.items; if (!items || items.length === 0) { return null; } // Filter out invalid items during streaming // Filters out: null, undefined, and empty string children var validItems = items.filter(function (item) { var _item$value, _item$key; var children = (_item$value = item.value) === null || _item$value === void 0 ? void 0 : _item$value.children; if (!((_item$key = item.key) !== null && _item$key !== void 0 && _item$key.children) || children == null) return false; return typeof children !== 'string' || children !== ''; }); if (validItems.length === 0) { return null; } return /*#__PURE__*/jsx(InfoGroup, { marginY: "spacing.3", itemOrientation: "horizontal", size: "medium", valueAlign: "left", children: validItems.map(function (item, index) { var _item$key4, _item$key5; var value = item.value; var isString = typeof value.children === 'string'; if (isString) { var _item$key2, _item$key3; return /*#__PURE__*/jsxs(InfoItem, { children: [/*#__PURE__*/jsx(InfoItemKey, { helpText: item === null || item === void 0 || (_item$key2 = item.key) === null || _item$key2 === void 0 ? void 0 : _item$key2.helpText, children: item === null || item === void 0 || (_item$key3 = item.key) === null || _item$key3 === void 0 ? void 0 : _item$key3.children }), /*#__PURE__*/jsx(InfoItemValue, { helpText: value.helpText, children: value.children })] }, index); } return /*#__PURE__*/jsxs(InfoItem, { children: [/*#__PURE__*/jsx(InfoItemKey, { helpText: item === null || item === void 0 || (_item$key4 = item.key) === null || _item$key4 === void 0 ? void 0 : _item$key4.helpText, children: item === null || item === void 0 || (_item$key5 = item.key) === null || _item$key5 === void 0 ? void 0 : _item$key5.children }), /*#__PURE__*/jsx(InfoItemValue, { helpText: value.helpText, children: /*#__PURE__*/jsx(GenUIComponentRenderer, { component: value.children, index: index }) })] }, index); }) }); }); var RenderButtonComponent = /*#__PURE__*/memo(function (_ref26) { var text = _ref26.text, action = _ref26.action; var onActionClick = useGenUIAction(); if (!text) return null; var handleClick = function handleClick() { if (action && onActionClick) { onActionClick(action); } }; return /*#__PURE__*/jsx(Button, { marginTop: "spacing.2", variant: "tertiary", onClick: handleClick, children: text }); }); var RenderLinkComponent = /*#__PURE__*/memo(function (_ref27) { var text = _ref27.text, action = _ref27.action; var onActionClick = useGenUIAction(); if (!text) return null; if (!action) { return /*#__PURE__*/jsx(Box, { marginBottom: "spacing.2", children: /*#__PURE__*/jsx(Text, { size: "medium", children: text }) }); } return /*#__PURE__*/jsx(Box, { marginBottom: "spacing.2", children: /*#__PURE__*/jsx(Link, { variant: "button", onClick: function onClick() { if (onActionClick) { onActionClick(action); } }, children: text }) }); }); var RenderAlertComponent = /*#__PURE__*/memo(function (_ref28) { var _actions$primary, _actions$secondary; var title = _ref28.title, description = _ref28.description, _ref28$color = _ref28.color, color = _ref28$color === void 0 ? 'neutral' : _ref28$color, actions = _ref28.actions; var onActionClick = useGenUIAction(); if (!title && !description) return null; // Validate color during streaming - show placeholder for invalid colors var validColor = getValidFeedbackColor(color); if (validColor !== color) { return /*#__PURE__*/jsx(Box, { marginY: "spacing.3", width: "100%" }); } var iconMap = { information: InfoIcon, negative: AlertTriangleIcon, neutral: InfoIcon, notice: InfoIcon, positive: CheckCircleIcon }; var Icon = iconMap[validColor]; return /*#__PURE__*/jsx(Alert, { emphasis: "subtle", title: title, icon: Icon, description: description, color: validColor, isDismissible: false, marginY: "spacing.4", actions: { primary: actions !== null && actions !== void 0 && (_actions$primary = actions.primary) !== null && _actions$primary !== void 0 && _actions$primary.text ? { text: actions.primary.text, onClick: function onClick() { var _actions$primary2; if ((_actions$primary2 = actions.primary) !== null && _actions$primary2 !== void 0 && _actions$primary2.action && onActionClick) { onActionClick(actions.primary.action); } } } : undefined, secondary: actions !== null && actions !== void 0 && (_actions$secondary = actions.secondary) !== null && _actions$secondary !== void 0 && _actions$secondary.text ? { text: actions.secondary.text, onClick: function onClick() { var _actions$secondary2; if ((_actions$secondary2 = actions.secondary) !== null && _actions$secondary2 !== void 0 && _actions$secondary2.action && onActionClick) { onActionClick(actions.secondary.action); } } } : undefined } }); }); var RenderAmountComponent = /*#__PURE__*/memo(function (_ref29) { var value = _ref29.value, currency = _ref29.currency; var resolvedCurrency = currency || 'INR'; var numValue = typeof value === 'string' ? parseFloat(value) : value; if (typeof numValue !== 'number' || isNaN(numValue)) { return /*#__PURE__*/jsx(Text, { size: "medium", children: "-" }); } return /*#__PURE__*/jsx(Amount, { value: numValue, currency: resolvedCurrency }); }); // Alias for internal use in built-in renderers var GenUIComponentRenderer = ComponentRenderer; /** * Default registry of built-in components */ var createBuiltInRegistry = function createBuiltInRegistry() { var _ref30; return _ref30 = {}, _defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_ref30, ComponentType.TEXT, { renderer: RenderTextComponent }), ComponentType.CHART, { renderer: RenderChartComponent }), ComponentType.TABLE, { renderer: RenderTableComponent }), ComponentType.CARD, { renderer: RenderCardComponent }), ComponentType.BADGE, { renderer: RenderBadgeComponent }), ComponentType.SPACER, { renderer: RenderSpacerComponent }), ComponentType.DIVIDER, { renderer: RenderDividerComponent }), ComponentType.STACK, { renderer: RenderStackComponent }), ComponentType.GRID, { renderer: RenderGridComponent }), ComponentType.INFO_GROUP, { renderer: RenderInfoGroupComponent }), _defineProperty(_defineProperty(_defineProperty(_defineProperty(_ref30, ComponentType.BUTTON, { renderer: RenderButtonComponent }), ComponentType.LINK, { renderer: RenderLinkComponent }), ComponentType.ALERT, { renderer: RenderAlertComponent }), ComponentType.AMOUNT, { renderer: RenderAmountComponent }); }; export { ComponentType, createBuiltInRegistry }; //# sourceMappingURL=GenUIComponents.web.js.map