@webiny/admin-ui 0.0.0-unstable.9f53ea597d → 0.0.0-unstable.a4f3e4ea8b

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.
Files changed (59) hide show
  1. package/DataTable/DataTable.js +6 -3
  2. package/DataTable/DataTable.js.map +1 -1
  3. package/DataTable/components/ColumnsVisibility.js +1 -0
  4. package/DataTable/components/ColumnsVisibility.js.map +1 -1
  5. package/DatePicker/DatePicker.d.ts +5 -2
  6. package/DatePicker/DatePicker.js +10 -2
  7. package/DatePicker/DatePicker.js.map +1 -1
  8. package/DatePicker/primitives/DateTimePicker.js +9 -14
  9. package/DatePicker/primitives/DateTimePicker.js.map +1 -1
  10. package/DatePicker/utils/dateHelpers.d.ts +1 -1
  11. package/DatePicker/utils/dateHelpers.js +2 -1
  12. package/DatePicker/utils/dateHelpers.js.map +1 -1
  13. package/DatePicker/utils/timezoneHelpers.d.ts +3 -0
  14. package/DatePicker/utils/timezoneHelpers.js +32 -0
  15. package/DatePicker/utils/timezoneHelpers.js.map +1 -0
  16. package/DropdownMenu/components/DropdownMenuItem.d.ts +5 -0
  17. package/DropdownMenu/components/DropdownMenuItem.js +3 -2
  18. package/DropdownMenu/components/DropdownMenuItem.js.map +1 -1
  19. package/FilePicker/primitives/components/previews/ItemActions.js +1 -1
  20. package/FilePicker/primitives/components/previews/ItemActions.js.map +1 -1
  21. package/FilePicker/primitives/components/previews/RichItemPreview/FileType.d.ts +5 -0
  22. package/FilePicker/primitives/components/previews/RichItemPreview/FileType.js +45 -0
  23. package/FilePicker/primitives/components/previews/RichItemPreview/FileType.js.map +1 -0
  24. package/FilePicker/primitives/components/previews/RichItemPreview/Placeholder.d.ts +5 -0
  25. package/FilePicker/primitives/components/previews/RichItemPreview/Placeholder.js +14 -0
  26. package/FilePicker/primitives/components/previews/RichItemPreview/Placeholder.js.map +1 -0
  27. package/FilePicker/primitives/components/previews/RichItemPreview/RichItemPreview.js +52 -11
  28. package/FilePicker/primitives/components/previews/RichItemPreview/RichItemPreview.js.map +1 -1
  29. package/FilePicker/primitives/components/previews/RichItemPreview/RichItemThumbnail.d.ts +5 -4
  30. package/FilePicker/primitives/components/previews/RichItemPreview/RichItemThumbnail.js +9 -66
  31. package/FilePicker/primitives/components/previews/RichItemPreview/RichItemThumbnail.js.map +1 -1
  32. package/FilePicker/primitives/components/previews/RichItemPreview/Thumbnail.d.ts +11 -0
  33. package/FilePicker/primitives/components/previews/RichItemPreview/Thumbnail.js +24 -0
  34. package/FilePicker/primitives/components/previews/RichItemPreview/Thumbnail.js.map +1 -0
  35. package/FilePicker/primitives/components/previews/RichItemPreview/ThumbnailActions.d.ts +10 -0
  36. package/FilePicker/primitives/components/previews/RichItemPreview/ThumbnailActions.js +46 -0
  37. package/FilePicker/primitives/components/previews/RichItemPreview/ThumbnailActions.js.map +1 -0
  38. package/FilePicker/primitives/components/previews/TruncatedFileName.d.ts +7 -0
  39. package/FilePicker/primitives/components/previews/TruncatedFileName.js +20 -0
  40. package/FilePicker/primitives/components/previews/TruncatedFileName.js.map +1 -0
  41. package/FilePicker/primitives/components/previews/fileName.d.ts +4 -0
  42. package/FilePicker/primitives/components/previews/fileName.js +26 -0
  43. package/FilePicker/primitives/components/previews/fileName.js.map +1 -0
  44. package/FilePicker/primitives/components/previews/index.d.ts +1 -0
  45. package/FilePicker/primitives/components/previews/index.js +1 -0
  46. package/Link/Link.d.ts +1 -1
  47. package/Link/Link.js +1 -1
  48. package/Link/Link.js.map +1 -1
  49. package/Sidebar/components/SidebarContent.js +1 -1
  50. package/Sidebar/components/SidebarContent.js.map +1 -1
  51. package/Sidebar/components/SidebarRoot.js +1 -1
  52. package/Sidebar/components/SidebarRoot.js.map +1 -1
  53. package/Sidebar/components/items/SidebarMenuSubButton.js +8 -5
  54. package/Sidebar/components/items/SidebarMenuSubButton.js.map +1 -1
  55. package/Sidebar/components/items/SidebarMenuSubItem.js +3 -3
  56. package/Sidebar/components/items/SidebarMenuSubItem.js.map +1 -1
  57. package/Tree/useTree.js +6 -2
  58. package/Tree/useTree.js.map +1 -1
  59. package/package.json +6 -6
@@ -181,9 +181,12 @@ const DecoratableDataTable = ({ bordered, canSelectAllRows = true, columnVisibil
181
181
  });
182
182
  const getColumnWidth = useCallback((column)=>{
183
183
  if (!column.getCanResize()) return column.getSize();
184
- const tableSize = table.getTotalSize();
185
- const columnSize = column.getSize();
186
- return Math.ceil(columnSize * tableWidth / tableSize);
184
+ const visibleColumns = table.getVisibleLeafColumns();
185
+ const fixedTotal = visibleColumns.filter((col)=>!col.getCanResize()).reduce((total, col)=>total + col.getSize(), 0);
186
+ const resizableTotal = visibleColumns.filter((col)=>col.getCanResize()).reduce((total, col)=>total + col.getSize(), 0);
187
+ if (0 === resizableTotal) return column.getSize();
188
+ const available = Math.max(tableWidth - fixedTotal, 0);
189
+ return Math.ceil(column.getSize() * available / resizableTotal);
187
190
  }, [
188
191
  table,
189
192
  tableWidth
@@ -1 +1 @@
1
- {"version":3,"file":"DataTable/DataTable.js","sources":["../../src/DataTable/DataTable.tsx"],"sourcesContent":["import React, { memo, useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport type {\n Cell,\n Column,\n ColumnDef,\n ColumnSort,\n OnChangeFn,\n Row,\n RowSelectionState,\n SortingState,\n VisibilityState\n} from \"@tanstack/react-table\";\nimport {\n flexRender,\n getCoreRowModel,\n getSortedRowModel,\n useReactTable\n} from \"@tanstack/react-table\";\nimport { CheckboxPrimitive } from \"~/Checkbox/index.js\";\nimport { Skeleton } from \"~/Skeleton/index.js\";\nimport { Table } from \"~/Table/index.js\";\nimport { ColumnSorter, ColumnsVisibility } from \"./components/index.js\";\nimport { cn, makeDecoratable } from \"~/utils.js\";\n\ninterface DataTableColumn<T> {\n /*\n * Column header component.\n */\n header?: string | number | React.JSX.Element;\n /*\n * Cell renderer, receives the full row and returns the value to render inside the cell.\n */\n cell?: (row: T) => string | number | React.JSX.Element | null;\n /*\n * Column size.\n */\n size?: number;\n /*\n * Should truncate?\n */\n truncate?: boolean;\n /*\n * Column class names.\n */\n className?: string;\n /*\n * Enable column sorting.\n */\n enableSorting?: boolean;\n /*\n * Enable column resizing.\n */\n enableResizing?: boolean;\n /*\n * Enable column visibility toggling.\n */\n enableHiding?: boolean;\n /*\n * Accessor key for the column data path.\n */\n accessorKey?: string;\n}\n\ntype DataTableColumns<T> = {\n [P in keyof T]?: DataTableColumn<T>;\n};\n\ntype DataTableDefaultData = {\n id: string;\n /*\n * Define if a specific row can be selected.\n */\n $selectable?: boolean;\n};\n\ntype DataTableRow<T> = Row<DataTableDefaultData & T>;\n\ntype DataTableSorting = SortingState;\n\ntype DataTableColumnSort = ColumnSort;\n\ntype OnDataTableSortingChange = OnChangeFn<DataTableSorting>;\n\ntype DataTableColumnVisibility = VisibilityState;\n\ntype OnDataTableColumnVisibilityChange = OnChangeFn<DataTableColumnVisibility>;\n\ninterface DataTableProps<TEntry> {\n /**\n * Show or hide borders.\n */\n bordered?: boolean;\n /**\n * Controls whether \"select all\" action is allowed.\n */\n canSelectAllRows?: boolean;\n /**\n * Columns definition.\n */\n columns: DataTableColumns<TEntry>;\n /**\n * The column visibility state.\n */\n columnVisibility?: DataTableColumnVisibility;\n /**\n * Callback that receives current column visibility state.\n */\n onColumnVisibilityChange?: OnDataTableColumnVisibilityChange;\n /**\n * Data to display into DataTable body.\n */\n data: TEntry[];\n /**\n * Callback that is called to determine if the row is selectable.\n */\n isRowSelectable?: (row: Row<TEntry>) => boolean;\n /**\n * Render the skeleton state while data are loading.\n */\n loading?: boolean;\n /**\n * Callback that receives the selected rows.\n */\n onSelectRow?: (rows: TEntry[]) => void;\n /**\n * Callback that receives the toggled row.\n */\n onToggleRow?: (row: TEntry) => void;\n /**\n * Callback that receives current sorting state.\n */\n onSortingChange?: OnDataTableSortingChange;\n /**\n * Selected rows.\n */\n selectedRows?: TEntry[];\n /**\n * Sorting state.\n */\n sorting?: DataTableSorting;\n /**\n * Initial sorting state.\n */\n initialSorting?: DataTableSorting;\n /**\n * Enable sticky header.\n */\n stickyHeader?: boolean;\n}\n\ninterface DefineColumnsOptions<TEntry> {\n canSelectAllRows: boolean;\n onSelectRow?: DataTableProps<TEntry>[\"onSelectRow\"];\n onToggleRow: DataTableProps<TEntry>[\"onToggleRow\"];\n loading: DataTableProps<TEntry>[\"loading\"];\n}\n\nconst defineColumns = <T,>(\n columns: DataTableProps<T>[\"columns\"],\n options: DefineColumnsOptions<T>\n): ColumnDef<T>[] => {\n const { canSelectAllRows, onSelectRow, onToggleRow, loading } = options;\n\n return useMemo(() => {\n const columnsList = Object.keys(columns).map(key => ({\n id: key,\n ...columns[key as keyof typeof columns]\n }));\n\n const defaults: ColumnDef<T>[] = columnsList.map(column => {\n const {\n accessorKey,\n cell,\n className,\n enableHiding = true,\n enableResizing = true,\n enableSorting = false,\n header,\n truncate = true,\n id,\n size = 100\n } = column;\n\n return {\n id,\n accessorKey: accessorKey || id,\n header: () => header,\n cell: props => {\n if (cell && typeof cell === \"function\") {\n return cell(props.row.original);\n } else {\n // Automatically convert any cell value to a string for rendering,\n // ensuring the table displays values correctly. This aligns with React's\n // rendering, which expects JSX, strings or null.\n // https://github.com/TanStack/table/issues/1042\n return props.getValue() ? String(props.getValue()) : null;\n }\n },\n enableSorting,\n meta: {\n className,\n truncate\n },\n enableResizing,\n size,\n enableHiding\n };\n });\n\n let columnsDefs = defaults;\n const firstColumn = defaults[0];\n const isSelectable = onToggleRow || onSelectRow;\n\n if (isSelectable && firstColumn) {\n columnsDefs = [\n {\n ...firstColumn,\n accessorKey: firstColumn.id as string,\n header: props => {\n if (!props) {\n return null;\n }\n\n return (\n <div className={\"flex items-center gap-xl\"}>\n <CheckboxPrimitive\n indeterminate={props.table.getIsSomeRowsSelected()}\n checked={props.table.getIsAllRowsSelected()}\n onChange={props.table.toggleAllPageRowsSelected}\n aria-label=\"Select all\"\n disabled={!canSelectAllRows}\n onClick={e => e.stopPropagation()}\n />\n {firstColumn.header\n ? React.createElement(firstColumn.header, props)\n : null}\n </div>\n );\n },\n cell: props => {\n if (!props) {\n return null;\n }\n return (\n <div className={\"flex items-center gap-xl\"}>\n <CheckboxPrimitive\n checked={props.row.getIsSelected()}\n onChange={value => props.row.toggleSelected(!!value)}\n disabled={!props.row.getCanSelect()}\n aria-label=\"Select row\"\n className={cn(!props.row.getCanSelect() ? \"invisible\" : \"\")}\n />\n {firstColumn.cell\n ? React.createElement(firstColumn.cell, props)\n : null}\n </div>\n );\n }\n },\n ...defaults.slice(1)\n ];\n }\n\n return columnsDefs.map(column => {\n if (loading) {\n return {\n ...column,\n cell: () => <Skeleton type={\"text\"} size={\"md\"} />\n };\n }\n\n return column;\n });\n }, [columns, onSelectRow, onToggleRow, loading]);\n};\n\nconst typedMemo: <T>(component: T) => T = memo;\n\ninterface TableCellProps<T> {\n cell: Cell<T, unknown>;\n getColumnWidth: (column: Column<T>) => number;\n}\n\nconst TableCell = <T,>({ cell, getColumnWidth }: TableCellProps<T>) => {\n const width = getColumnWidth(cell.column);\n\n return (\n <Table.Cell {...cell.column.columnDef.meta} style={{ width, maxWidth: width }}>\n {flexRender(cell.column.columnDef.cell, cell.getContext())}\n </Table.Cell>\n );\n};\n\nconst MemoTableCell = typedMemo(TableCell);\n\ninterface TableRowProps<T> {\n selected: boolean;\n cells: Cell<T, unknown>[];\n getColumnWidth: (column: Column<T>) => number;\n}\n\nconst TableRow = <T,>({ selected, cells, getColumnWidth }: TableRowProps<T>) => {\n return (\n <Table.Row selected={selected}>\n {cells.map(cell => (\n <MemoTableCell<T> key={cell.id} cell={cell} getColumnWidth={getColumnWidth} />\n ))}\n </Table.Row>\n );\n};\n\nconst MemoTableRow = typedMemo(TableRow);\n\n/**\n * Empty array must be defined outside the React component so it does not force rerendering of the DataTable\n */\nconst emptyArray = Array(10).fill({});\n\nconst DecoratableDataTable = <T extends Record<string, any> & DataTableDefaultData>({\n bordered,\n canSelectAllRows = true,\n columnVisibility,\n columns: initialColumns,\n data: initialData,\n initialSorting,\n isRowSelectable,\n loading,\n onColumnVisibilityChange,\n onSelectRow,\n onSortingChange,\n onToggleRow,\n selectedRows = [],\n sorting,\n stickyHeader\n}: DataTableProps<T>) => {\n const tableRef = useRef<HTMLDivElement>(null);\n const [tableWidth, setTableWidth] = useState(1);\n\n const data = loading ? emptyArray : initialData;\n\n useEffect(() => {\n const updateElementWidth = () => {\n if (tableRef.current) {\n const width = tableRef.current.clientWidth;\n setTableWidth(width);\n }\n };\n\n updateElementWidth();\n\n window.addEventListener(\"resize\", updateElementWidth);\n\n return () => {\n window.removeEventListener(\"resize\", updateElementWidth);\n };\n }, [tableRef.current]);\n\n const rowSelection = useMemo(() => {\n return selectedRows.reduce<RowSelectionState>((acc, item) => {\n const recordIndex = data.findIndex(rec => rec.id === item.id);\n return { ...acc, [recordIndex]: true };\n }, {});\n }, [selectedRows, data]);\n\n const onRowSelectionChange: OnChangeFn<RowSelectionState> = updater => {\n const newSelection = typeof updater === \"function\" ? updater(rowSelection) : updater;\n\n /**\n * `@tanstack/react-table` isn't telling us what row was selected or deselected. It simply gives us\n * the new selection state (an object with row indexes that are currently selected).\n *\n * To figure out what row was toggled, we need to calculate the difference between the old selection\n * and the new selection. What we're doing here is:\n * - find all items that were present in the previous selection, but are no longer present in the new selection\n * - find all items that are present in the new selection, but were not present in the previous selection\n */\n const toggledRows = [\n ...Object.keys(rowSelection).filter(x => !(x in newSelection)),\n ...Object.keys(newSelection).filter(x => !(x in rowSelection))\n ];\n\n // If the difference is only 1 item, and `onToggleRow` is available, execute that.\n if (toggledRows.length === 1 && typeof onToggleRow === \"function\") {\n onToggleRow(data[parseInt(toggledRows[0])]);\n return;\n } else if (typeof onSelectRow === \"function\") {\n const selection = Object.keys(newSelection).map(key => data[parseInt(key)]);\n onSelectRow(selection);\n }\n };\n\n const tableSorting = useMemo(() => {\n if (!Array.isArray(sorting) || !sorting.length) {\n return initialSorting;\n }\n return sorting;\n }, [sorting]);\n\n const columns = defineColumns(initialColumns, {\n canSelectAllRows,\n onSelectRow,\n onToggleRow,\n loading\n });\n\n const table = useReactTable<T>({\n columnResizeMode: \"onChange\",\n columns,\n data,\n enableColumnResizing: true,\n enableHiding: !!onColumnVisibilityChange,\n enableRowSelection: isRowSelectable,\n enableSorting: !!onSortingChange,\n enableSortingRemoval: false,\n getCoreRowModel: getCoreRowModel(),\n getSortedRowModel: getSortedRowModel(),\n manualSorting: true,\n onColumnVisibilityChange,\n onRowSelectionChange,\n onSortingChange,\n state: {\n columnVisibility,\n rowSelection,\n sorting: tableSorting\n }\n });\n\n const getColumnWidth = useCallback(\n (column: Column<T>): number => {\n if (!column.getCanResize()) {\n return column.getSize();\n }\n\n const tableSize = table.getTotalSize();\n const columnSize = column.getSize();\n\n return Math.ceil((columnSize * tableWidth) / tableSize);\n },\n [table, tableWidth]\n );\n\n /**\n * Had to memoize the rows to avoid browser freeze.\n */\n const tableRows = useMemo(() => {\n return table.getRowModel().rows;\n }, [table, data, columns]);\n\n return (\n <div ref={tableRef}>\n <Table bordered={bordered} sticky={stickyHeader}>\n <Table.Header sticky={stickyHeader}>\n {table.getHeaderGroups().map(headerGroup => (\n <Table.Row key={headerGroup.id}>\n {headerGroup.headers.map((header, index) => {\n const isLastCell = index === headerGroup.headers.length - 1;\n const width = getColumnWidth(header.column);\n\n return (\n <Table.Head\n key={header.id}\n {...header.column.columnDef.meta}\n colSpan={header.colSpan}\n style={{ width, maxWidth: width }}\n >\n {header.isPlaceholder ? null : (\n <ColumnSorter\n onClick={header.column.getToggleSortingHandler()}\n sortable={header.column.getCanSort()}\n >\n <div\n className={cn({\n \"w-full overflow-hidden whitespace-nowrap\": true,\n truncate: !isLastCell\n })}\n >\n {flexRender(\n header.column.columnDef.header,\n header.getContext()\n )}\n </div>\n <Table.Direction\n direction={header.column.getIsSorted() || null}\n />\n {isLastCell && (\n <div className={\"h-md\"}>\n <ColumnsVisibility\n columns={table.getAllColumns()}\n />\n </div>\n )}\n </ColumnSorter>\n )}\n {header.column.getCanResize() && (\n <Table.Resizer\n onMouseDown={header.getResizeHandler()}\n onTouchStart={header.getResizeHandler()}\n isResizing={header.column.getIsResizing()}\n />\n )}\n </Table.Head>\n );\n })}\n </Table.Row>\n ))}\n </Table.Header>\n <Table.Body>\n {tableRows.map(row => {\n const id = row.original.id || row.id;\n return (\n <MemoTableRow<T>\n key={id}\n cells={row.getVisibleCells()}\n selected={row.getIsSelected()}\n getColumnWidth={getColumnWidth}\n />\n );\n })}\n </Table.Body>\n </Table>\n </div>\n );\n};\n\nconst DataTable = makeDecoratable(\"DataTable\", DecoratableDataTable);\n\nexport {\n DataTable,\n type DataTableProps,\n type DataTableColumn,\n type DataTableColumns,\n type DataTableDefaultData,\n type DataTableRow,\n type DataTableSorting,\n type DataTableColumnSort,\n type OnDataTableSortingChange,\n type DataTableColumnVisibility,\n type OnDataTableColumnVisibilityChange\n};\n"],"names":["defineColumns","columns","options","canSelectAllRows","onSelectRow","onToggleRow","loading","useMemo","columnsList","Object","key","defaults","column","accessorKey","cell","className","enableHiding","enableResizing","enableSorting","header","truncate","id","size","props","String","columnsDefs","firstColumn","isSelectable","CheckboxPrimitive","e","React","value","cn","Skeleton","typedMemo","memo","TableCell","getColumnWidth","width","Table","flexRender","MemoTableCell","TableRow","selected","cells","MemoTableRow","emptyArray","Array","DecoratableDataTable","bordered","columnVisibility","initialColumns","initialData","initialSorting","isRowSelectable","onColumnVisibilityChange","onSortingChange","selectedRows","sorting","stickyHeader","tableRef","useRef","tableWidth","setTableWidth","useState","data","useEffect","updateElementWidth","window","rowSelection","acc","item","recordIndex","rec","onRowSelectionChange","updater","newSelection","toggledRows","x","parseInt","selection","tableSorting","table","useReactTable","getCoreRowModel","getSortedRowModel","useCallback","tableSize","columnSize","Math","tableRows","headerGroup","index","isLastCell","ColumnSorter","ColumnsVisibility","row","DataTable","makeDecoratable"],"mappings":"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"}
1
+ {"version":3,"file":"DataTable/DataTable.js","sources":["../../src/DataTable/DataTable.tsx"],"sourcesContent":["import React, { memo, useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport type {\n Cell,\n Column,\n ColumnDef,\n ColumnSort,\n OnChangeFn,\n Row,\n RowSelectionState,\n SortingState,\n VisibilityState\n} from \"@tanstack/react-table\";\nimport {\n flexRender,\n getCoreRowModel,\n getSortedRowModel,\n useReactTable\n} from \"@tanstack/react-table\";\nimport { CheckboxPrimitive } from \"~/Checkbox/index.js\";\nimport { Skeleton } from \"~/Skeleton/index.js\";\nimport { Table } from \"~/Table/index.js\";\nimport { ColumnSorter, ColumnsVisibility } from \"./components/index.js\";\nimport { cn, makeDecoratable } from \"~/utils.js\";\n\ninterface DataTableColumn<T> {\n /*\n * Column header component.\n */\n header?: string | number | React.JSX.Element;\n /*\n * Cell renderer, receives the full row and returns the value to render inside the cell.\n */\n cell?: (row: T) => string | number | React.JSX.Element | null;\n /*\n * Column size.\n */\n size?: number;\n /*\n * Should truncate?\n */\n truncate?: boolean;\n /*\n * Column class names.\n */\n className?: string;\n /*\n * Enable column sorting.\n */\n enableSorting?: boolean;\n /*\n * Enable column resizing.\n */\n enableResizing?: boolean;\n /*\n * Enable column visibility toggling.\n */\n enableHiding?: boolean;\n /*\n * Accessor key for the column data path.\n */\n accessorKey?: string;\n}\n\ntype DataTableColumns<T> = {\n [P in keyof T]?: DataTableColumn<T>;\n};\n\ntype DataTableDefaultData = {\n id: string;\n /*\n * Define if a specific row can be selected.\n */\n $selectable?: boolean;\n};\n\ntype DataTableRow<T> = Row<DataTableDefaultData & T>;\n\ntype DataTableSorting = SortingState;\n\ntype DataTableColumnSort = ColumnSort;\n\ntype OnDataTableSortingChange = OnChangeFn<DataTableSorting>;\n\ntype DataTableColumnVisibility = VisibilityState;\n\ntype OnDataTableColumnVisibilityChange = OnChangeFn<DataTableColumnVisibility>;\n\ninterface DataTableProps<TEntry> {\n /**\n * Show or hide borders.\n */\n bordered?: boolean;\n /**\n * Controls whether \"select all\" action is allowed.\n */\n canSelectAllRows?: boolean;\n /**\n * Columns definition.\n */\n columns: DataTableColumns<TEntry>;\n /**\n * The column visibility state.\n */\n columnVisibility?: DataTableColumnVisibility;\n /**\n * Callback that receives current column visibility state.\n */\n onColumnVisibilityChange?: OnDataTableColumnVisibilityChange;\n /**\n * Data to display into DataTable body.\n */\n data: TEntry[];\n /**\n * Callback that is called to determine if the row is selectable.\n */\n isRowSelectable?: (row: Row<TEntry>) => boolean;\n /**\n * Render the skeleton state while data are loading.\n */\n loading?: boolean;\n /**\n * Callback that receives the selected rows.\n */\n onSelectRow?: (rows: TEntry[]) => void;\n /**\n * Callback that receives the toggled row.\n */\n onToggleRow?: (row: TEntry) => void;\n /**\n * Callback that receives current sorting state.\n */\n onSortingChange?: OnDataTableSortingChange;\n /**\n * Selected rows.\n */\n selectedRows?: TEntry[];\n /**\n * Sorting state.\n */\n sorting?: DataTableSorting;\n /**\n * Initial sorting state.\n */\n initialSorting?: DataTableSorting;\n /**\n * Enable sticky header.\n */\n stickyHeader?: boolean;\n}\n\ninterface DefineColumnsOptions<TEntry> {\n canSelectAllRows: boolean;\n onSelectRow?: DataTableProps<TEntry>[\"onSelectRow\"];\n onToggleRow: DataTableProps<TEntry>[\"onToggleRow\"];\n loading: DataTableProps<TEntry>[\"loading\"];\n}\n\nconst defineColumns = <T,>(\n columns: DataTableProps<T>[\"columns\"],\n options: DefineColumnsOptions<T>\n): ColumnDef<T>[] => {\n const { canSelectAllRows, onSelectRow, onToggleRow, loading } = options;\n\n return useMemo(() => {\n const columnsList = Object.keys(columns).map(key => ({\n id: key,\n ...columns[key as keyof typeof columns]\n }));\n\n const defaults: ColumnDef<T>[] = columnsList.map(column => {\n const {\n accessorKey,\n cell,\n className,\n enableHiding = true,\n enableResizing = true,\n enableSorting = false,\n header,\n truncate = true,\n id,\n size = 100\n } = column;\n\n return {\n id,\n accessorKey: accessorKey || id,\n header: () => header,\n cell: props => {\n if (cell && typeof cell === \"function\") {\n return cell(props.row.original);\n } else {\n // Automatically convert any cell value to a string for rendering,\n // ensuring the table displays values correctly. This aligns with React's\n // rendering, which expects JSX, strings or null.\n // https://github.com/TanStack/table/issues/1042\n return props.getValue() ? String(props.getValue()) : null;\n }\n },\n enableSorting,\n meta: {\n className,\n truncate\n },\n enableResizing,\n size,\n enableHiding\n };\n });\n\n let columnsDefs = defaults;\n const firstColumn = defaults[0];\n const isSelectable = onToggleRow || onSelectRow;\n\n if (isSelectable && firstColumn) {\n columnsDefs = [\n {\n ...firstColumn,\n accessorKey: firstColumn.id as string,\n header: props => {\n if (!props) {\n return null;\n }\n\n return (\n <div className={\"flex items-center gap-xl\"}>\n <CheckboxPrimitive\n indeterminate={props.table.getIsSomeRowsSelected()}\n checked={props.table.getIsAllRowsSelected()}\n onChange={props.table.toggleAllPageRowsSelected}\n aria-label=\"Select all\"\n disabled={!canSelectAllRows}\n onClick={e => e.stopPropagation()}\n />\n {firstColumn.header\n ? React.createElement(firstColumn.header, props)\n : null}\n </div>\n );\n },\n cell: props => {\n if (!props) {\n return null;\n }\n return (\n <div className={\"flex items-center gap-xl\"}>\n <CheckboxPrimitive\n checked={props.row.getIsSelected()}\n onChange={value => props.row.toggleSelected(!!value)}\n disabled={!props.row.getCanSelect()}\n aria-label=\"Select row\"\n className={cn(!props.row.getCanSelect() ? \"invisible\" : \"\")}\n />\n {firstColumn.cell\n ? React.createElement(firstColumn.cell, props)\n : null}\n </div>\n );\n }\n },\n ...defaults.slice(1)\n ];\n }\n\n return columnsDefs.map(column => {\n if (loading) {\n return {\n ...column,\n cell: () => <Skeleton type={\"text\"} size={\"md\"} />\n };\n }\n\n return column;\n });\n }, [columns, onSelectRow, onToggleRow, loading]);\n};\n\nconst typedMemo: <T>(component: T) => T = memo;\n\ninterface TableCellProps<T> {\n cell: Cell<T, unknown>;\n getColumnWidth: (column: Column<T>) => number;\n}\n\nconst TableCell = <T,>({ cell, getColumnWidth }: TableCellProps<T>) => {\n const width = getColumnWidth(cell.column);\n\n return (\n <Table.Cell {...cell.column.columnDef.meta} style={{ width, maxWidth: width }}>\n {flexRender(cell.column.columnDef.cell, cell.getContext())}\n </Table.Cell>\n );\n};\n\nconst MemoTableCell = typedMemo(TableCell);\n\ninterface TableRowProps<T> {\n selected: boolean;\n cells: Cell<T, unknown>[];\n getColumnWidth: (column: Column<T>) => number;\n}\n\nconst TableRow = <T,>({ selected, cells, getColumnWidth }: TableRowProps<T>) => {\n return (\n <Table.Row selected={selected}>\n {cells.map(cell => (\n <MemoTableCell<T> key={cell.id} cell={cell} getColumnWidth={getColumnWidth} />\n ))}\n </Table.Row>\n );\n};\n\nconst MemoTableRow = typedMemo(TableRow);\n\n/**\n * Empty array must be defined outside the React component so it does not force rerendering of the DataTable\n */\nconst emptyArray = Array(10).fill({});\n\nconst DecoratableDataTable = <T extends Record<string, any> & DataTableDefaultData>({\n bordered,\n canSelectAllRows = true,\n columnVisibility,\n columns: initialColumns,\n data: initialData,\n initialSorting,\n isRowSelectable,\n loading,\n onColumnVisibilityChange,\n onSelectRow,\n onSortingChange,\n onToggleRow,\n selectedRows = [],\n sorting,\n stickyHeader\n}: DataTableProps<T>) => {\n const tableRef = useRef<HTMLDivElement>(null);\n const [tableWidth, setTableWidth] = useState(1);\n\n const data = loading ? emptyArray : initialData;\n\n useEffect(() => {\n const updateElementWidth = () => {\n if (tableRef.current) {\n const width = tableRef.current.clientWidth;\n setTableWidth(width);\n }\n };\n\n updateElementWidth();\n\n window.addEventListener(\"resize\", updateElementWidth);\n\n return () => {\n window.removeEventListener(\"resize\", updateElementWidth);\n };\n }, [tableRef.current]);\n\n const rowSelection = useMemo(() => {\n return selectedRows.reduce<RowSelectionState>((acc, item) => {\n const recordIndex = data.findIndex(rec => rec.id === item.id);\n return { ...acc, [recordIndex]: true };\n }, {});\n }, [selectedRows, data]);\n\n const onRowSelectionChange: OnChangeFn<RowSelectionState> = updater => {\n const newSelection = typeof updater === \"function\" ? updater(rowSelection) : updater;\n\n /**\n * `@tanstack/react-table` isn't telling us what row was selected or deselected. It simply gives us\n * the new selection state (an object with row indexes that are currently selected).\n *\n * To figure out what row was toggled, we need to calculate the difference between the old selection\n * and the new selection. What we're doing here is:\n * - find all items that were present in the previous selection, but are no longer present in the new selection\n * - find all items that are present in the new selection, but were not present in the previous selection\n */\n const toggledRows = [\n ...Object.keys(rowSelection).filter(x => !(x in newSelection)),\n ...Object.keys(newSelection).filter(x => !(x in rowSelection))\n ];\n\n // If the difference is only 1 item, and `onToggleRow` is available, execute that.\n if (toggledRows.length === 1 && typeof onToggleRow === \"function\") {\n onToggleRow(data[parseInt(toggledRows[0])]);\n return;\n } else if (typeof onSelectRow === \"function\") {\n const selection = Object.keys(newSelection).map(key => data[parseInt(key)]);\n onSelectRow(selection);\n }\n };\n\n const tableSorting = useMemo(() => {\n if (!Array.isArray(sorting) || !sorting.length) {\n return initialSorting;\n }\n return sorting;\n }, [sorting]);\n\n const columns = defineColumns(initialColumns, {\n canSelectAllRows,\n onSelectRow,\n onToggleRow,\n loading\n });\n\n const table = useReactTable<T>({\n columnResizeMode: \"onChange\",\n columns,\n data,\n enableColumnResizing: true,\n enableHiding: !!onColumnVisibilityChange,\n enableRowSelection: isRowSelectable,\n enableSorting: !!onSortingChange,\n enableSortingRemoval: false,\n getCoreRowModel: getCoreRowModel(),\n getSortedRowModel: getSortedRowModel(),\n manualSorting: true,\n onColumnVisibilityChange,\n onRowSelectionChange,\n onSortingChange,\n state: {\n columnVisibility,\n rowSelection,\n sorting: tableSorting\n }\n });\n\n const getColumnWidth = useCallback(\n (column: Column<T>): number => {\n // Non-resizable columns (e.g. row-selection, actions) keep their fixed size.\n if (!column.getCanResize()) {\n return column.getSize();\n }\n\n /**\n * Resizable columns share the space left after the fixed columns, proportionally to\n * their own size. This makes the table always fill the full container width — even when\n * columns are hidden — so trailing content (e.g. the columns-visibility cog) stays\n * flush right instead of drifting left as columns are removed.\n */\n const visibleColumns = table.getVisibleLeafColumns();\n const fixedTotal = visibleColumns\n .filter(col => !col.getCanResize())\n .reduce((total, col) => total + col.getSize(), 0);\n const resizableTotal = visibleColumns\n .filter(col => col.getCanResize())\n .reduce((total, col) => total + col.getSize(), 0);\n\n if (resizableTotal === 0) {\n return column.getSize();\n }\n\n const available = Math.max(tableWidth - fixedTotal, 0);\n\n return Math.ceil((column.getSize() * available) / resizableTotal);\n },\n [table, tableWidth]\n );\n\n /**\n * Had to memoize the rows to avoid browser freeze.\n */\n const tableRows = useMemo(() => {\n return table.getRowModel().rows;\n }, [table, data, columns]);\n\n return (\n <div ref={tableRef}>\n <Table bordered={bordered} sticky={stickyHeader}>\n <Table.Header sticky={stickyHeader}>\n {table.getHeaderGroups().map(headerGroup => (\n <Table.Row key={headerGroup.id}>\n {headerGroup.headers.map((header, index) => {\n const isLastCell = index === headerGroup.headers.length - 1;\n const width = getColumnWidth(header.column);\n\n return (\n <Table.Head\n key={header.id}\n {...header.column.columnDef.meta}\n colSpan={header.colSpan}\n style={{ width, maxWidth: width }}\n >\n {header.isPlaceholder ? null : (\n <ColumnSorter\n onClick={header.column.getToggleSortingHandler()}\n sortable={header.column.getCanSort()}\n >\n <div\n className={cn({\n \"w-full overflow-hidden whitespace-nowrap\": true,\n truncate: !isLastCell\n })}\n >\n {flexRender(\n header.column.columnDef.header,\n header.getContext()\n )}\n </div>\n <Table.Direction\n direction={header.column.getIsSorted() || null}\n />\n {isLastCell && (\n <div className={\"h-md\"}>\n <ColumnsVisibility\n columns={table.getAllColumns()}\n />\n </div>\n )}\n </ColumnSorter>\n )}\n {header.column.getCanResize() && (\n <Table.Resizer\n onMouseDown={header.getResizeHandler()}\n onTouchStart={header.getResizeHandler()}\n isResizing={header.column.getIsResizing()}\n />\n )}\n </Table.Head>\n );\n })}\n </Table.Row>\n ))}\n </Table.Header>\n <Table.Body>\n {tableRows.map(row => {\n const id = row.original.id || row.id;\n return (\n <MemoTableRow<T>\n key={id}\n cells={row.getVisibleCells()}\n selected={row.getIsSelected()}\n getColumnWidth={getColumnWidth}\n />\n );\n })}\n </Table.Body>\n </Table>\n </div>\n );\n};\n\nconst DataTable = makeDecoratable(\"DataTable\", DecoratableDataTable);\n\nexport {\n DataTable,\n type DataTableProps,\n type DataTableColumn,\n type DataTableColumns,\n type DataTableDefaultData,\n type DataTableRow,\n type DataTableSorting,\n type DataTableColumnSort,\n type OnDataTableSortingChange,\n type DataTableColumnVisibility,\n type OnDataTableColumnVisibilityChange\n};\n"],"names":["defineColumns","columns","options","canSelectAllRows","onSelectRow","onToggleRow","loading","useMemo","columnsList","Object","key","defaults","column","accessorKey","cell","className","enableHiding","enableResizing","enableSorting","header","truncate","id","size","props","String","columnsDefs","firstColumn","isSelectable","CheckboxPrimitive","e","React","value","cn","Skeleton","typedMemo","memo","TableCell","getColumnWidth","width","Table","flexRender","MemoTableCell","TableRow","selected","cells","MemoTableRow","emptyArray","Array","DecoratableDataTable","bordered","columnVisibility","initialColumns","initialData","initialSorting","isRowSelectable","onColumnVisibilityChange","onSortingChange","selectedRows","sorting","stickyHeader","tableRef","useRef","tableWidth","setTableWidth","useState","data","useEffect","updateElementWidth","window","rowSelection","acc","item","recordIndex","rec","onRowSelectionChange","updater","newSelection","toggledRows","x","parseInt","selection","tableSorting","table","useReactTable","getCoreRowModel","getSortedRowModel","useCallback","visibleColumns","fixedTotal","col","total","resizableTotal","available","Math","tableRows","headerGroup","index","isLastCell","ColumnSorter","ColumnsVisibility","row","DataTable","makeDecoratable"],"mappings":"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"}
@@ -29,6 +29,7 @@ const ColumnsVisibility = (props)=>{
29
29
  text: "Display columns"
30
30
  }), options.map((option)=>/*#__PURE__*/ react.createElement(DropdownMenu.Item, {
31
31
  key: option.id,
32
+ preventClose: true,
32
33
  text: /*#__PURE__*/ react.createElement(Checkbox, {
33
34
  label: option.header,
34
35
  onChange: option.onChange,
@@ -1 +1 @@
1
- {"version":3,"file":"DataTable/components/ColumnsVisibility.js","sources":["../../../src/DataTable/components/ColumnsVisibility.tsx"],"sourcesContent":["import React, { useCallback, useMemo } from \"react\";\nimport { ReactComponent as SettingsIcon } from \"@webiny/icons/settings.svg\";\nimport type { Column } from \"@tanstack/react-table\";\nimport { IconButton } from \"~/Button/index.js\";\nimport { Checkbox } from \"~/Checkbox/index.js\";\nimport { DropdownMenu } from \"~/DropdownMenu/index.js\";\n\ninterface ColumnsVisibilityProps<T> {\n columns: Column<T>[];\n}\n\ninterface Option {\n id: string;\n header: string;\n onChange: (value?: boolean | undefined) => void;\n getValue: () => boolean;\n}\n\nexport const ColumnsVisibility = <T,>(props: ColumnsVisibilityProps<T>) => {\n /**\n * `@tanstack/react-table` does not have a simple method to return the header component.\n * The only possible way is to use `flexRenderer`, but this is not working with the current implementation\n * since we don't have access to the header context.\n */\n const getHeaderName = useCallback((column: Column<T>) => {\n const { header } = column.columnDef;\n\n if (typeof header === \"string\") {\n return header;\n }\n\n if (typeof header === \"function\") {\n // @ts-expect-error\n return header();\n }\n\n return column.id;\n }, []);\n\n const options: Option[] = useMemo(() => {\n return props.columns\n .filter(column => column.getCanHide())\n .map(column => {\n return {\n id: column.id,\n header: getHeaderName(column),\n onChange: column.toggleVisibility,\n getValue: column.getIsVisible\n };\n });\n }, [props.columns]);\n\n if (options.length === 0) {\n return null;\n }\n\n return (\n <DropdownMenu\n trigger={<IconButton icon={<SettingsIcon />} variant={\"ghost\"} size={\"xs\"} />}\n >\n <DropdownMenu.Label text={\"Display columns\"} />\n {options.map(option => {\n return (\n <DropdownMenu.Item\n key={option.id}\n text={\n <Checkbox\n label={option.header}\n onChange={option.onChange}\n checked={option.getValue()}\n />\n }\n />\n );\n })}\n </DropdownMenu>\n );\n};\n"],"names":["ColumnsVisibility","props","getHeaderName","useCallback","column","header","options","useMemo","DropdownMenu","IconButton","SettingsIcon","option","Checkbox"],"mappings":";;;;;AAkBO,MAAMA,oBAAoB,CAAKC;IAMlC,MAAMC,gBAAgBC,YAAY,CAACC;QAC/B,MAAM,EAAEC,MAAM,EAAE,GAAGD,OAAO,SAAS;QAEnC,IAAI,AAAkB,YAAlB,OAAOC,QACP,OAAOA;QAGX,IAAI,AAAkB,cAAlB,OAAOA,QAEP,OAAOA;QAGX,OAAOD,OAAO,EAAE;IACpB,GAAG,EAAE;IAEL,MAAME,UAAoBC,QAAQ,IACvBN,MAAM,OAAO,CACf,MAAM,CAACG,CAAAA,SAAUA,OAAO,UAAU,IAClC,GAAG,CAACA,CAAAA,SACM;gBACH,IAAIA,OAAO,EAAE;gBACb,QAAQF,cAAcE;gBACtB,UAAUA,OAAO,gBAAgB;gBACjC,UAAUA,OAAO,YAAY;YACjC,KAET;QAACH,MAAM,OAAO;KAAC;IAElB,IAAIK,AAAmB,MAAnBA,QAAQ,MAAM,EACd,OAAO;IAGX,OAAO,WAAP,GACI,oBAACE,cAAYA;QACT,uBAAS,oBAACC,YAAUA;YAAC,oBAAM,oBAACC,gBAAYA;YAAK,SAAS;YAAS,MAAM;;qBAErE,oBAACF,aAAa,KAAK;QAAC,MAAM;QACzBF,QAAQ,GAAG,CAACK,CAAAA,SACF,WAAP,GACI,oBAACH,aAAa,IAAI;YACd,KAAKG,OAAO,EAAE;YACd,oBACI,oBAACC,UAAQA;gBACL,OAAOD,OAAO,MAAM;gBACpB,UAAUA,OAAO,QAAQ;gBACzB,SAASA,OAAO,QAAQ;;;AAQxD"}
1
+ {"version":3,"file":"DataTable/components/ColumnsVisibility.js","sources":["../../../src/DataTable/components/ColumnsVisibility.tsx"],"sourcesContent":["import React, { useCallback, useMemo } from \"react\";\nimport { ReactComponent as SettingsIcon } from \"@webiny/icons/settings.svg\";\nimport type { Column } from \"@tanstack/react-table\";\nimport { IconButton } from \"~/Button/index.js\";\nimport { Checkbox } from \"~/Checkbox/index.js\";\nimport { DropdownMenu } from \"~/DropdownMenu/index.js\";\n\ninterface ColumnsVisibilityProps<T> {\n columns: Column<T>[];\n}\n\ninterface Option {\n id: string;\n header: string;\n onChange: (value?: boolean | undefined) => void;\n getValue: () => boolean;\n}\n\nexport const ColumnsVisibility = <T,>(props: ColumnsVisibilityProps<T>) => {\n /**\n * `@tanstack/react-table` does not have a simple method to return the header component.\n * The only possible way is to use `flexRenderer`, but this is not working with the current implementation\n * since we don't have access to the header context.\n */\n const getHeaderName = useCallback((column: Column<T>) => {\n const { header } = column.columnDef;\n\n if (typeof header === \"string\") {\n return header;\n }\n\n if (typeof header === \"function\") {\n // @ts-expect-error\n return header();\n }\n\n return column.id;\n }, []);\n\n const options: Option[] = useMemo(() => {\n return props.columns\n .filter(column => column.getCanHide())\n .map(column => {\n return {\n id: column.id,\n header: getHeaderName(column),\n onChange: column.toggleVisibility,\n getValue: column.getIsVisible\n };\n });\n }, [props.columns]);\n\n if (options.length === 0) {\n return null;\n }\n\n return (\n <DropdownMenu\n trigger={<IconButton icon={<SettingsIcon />} variant={\"ghost\"} size={\"xs\"} />}\n >\n <DropdownMenu.Label text={\"Display columns\"} />\n {options.map(option => {\n return (\n <DropdownMenu.Item\n key={option.id}\n preventClose\n text={\n <Checkbox\n label={option.header}\n onChange={option.onChange}\n checked={option.getValue()}\n />\n }\n />\n );\n })}\n </DropdownMenu>\n );\n};\n"],"names":["ColumnsVisibility","props","getHeaderName","useCallback","column","header","options","useMemo","DropdownMenu","IconButton","SettingsIcon","option","Checkbox"],"mappings":";;;;;AAkBO,MAAMA,oBAAoB,CAAKC;IAMlC,MAAMC,gBAAgBC,YAAY,CAACC;QAC/B,MAAM,EAAEC,MAAM,EAAE,GAAGD,OAAO,SAAS;QAEnC,IAAI,AAAkB,YAAlB,OAAOC,QACP,OAAOA;QAGX,IAAI,AAAkB,cAAlB,OAAOA,QAEP,OAAOA;QAGX,OAAOD,OAAO,EAAE;IACpB,GAAG,EAAE;IAEL,MAAME,UAAoBC,QAAQ,IACvBN,MAAM,OAAO,CACf,MAAM,CAACG,CAAAA,SAAUA,OAAO,UAAU,IAClC,GAAG,CAACA,CAAAA,SACM;gBACH,IAAIA,OAAO,EAAE;gBACb,QAAQF,cAAcE;gBACtB,UAAUA,OAAO,gBAAgB;gBACjC,UAAUA,OAAO,YAAY;YACjC,KAET;QAACH,MAAM,OAAO;KAAC;IAElB,IAAIK,AAAmB,MAAnBA,QAAQ,MAAM,EACd,OAAO;IAGX,OAAO,WAAP,GACI,oBAACE,cAAYA;QACT,uBAAS,oBAACC,YAAUA;YAAC,oBAAM,oBAACC,gBAAYA;YAAK,SAAS;YAAS,MAAM;;qBAErE,oBAACF,aAAa,KAAK;QAAC,MAAM;QACzBF,QAAQ,GAAG,CAACK,CAAAA,SACF,WAAP,GACI,oBAACH,aAAa,IAAI;YACd,KAAKG,OAAO,EAAE;YACd;YACA,oBACI,oBAACC,UAAQA;gBACL,OAAOD,OAAO,MAAM;gBACpB,UAAUA,OAAO,QAAQ;gBACzB,SAASA,OAAO,QAAQ;;;AAQxD"}
@@ -1,8 +1,11 @@
1
1
  import React from "react";
2
2
  import type { DatePickerPrimitiveProps } from "./primitives/index.js";
3
3
  import type { FormComponentProps } from "../FormComponent/index.js";
4
- type DatePickerProps = DatePickerPrimitiveProps & FormComponentProps;
5
- declare const DecoratableDatePicker: ({ label, description, note, hint, required, disabled, validation, ...props }: DatePickerProps) => React.JSX.Element;
4
+ interface DatePickerOwnProps {
5
+ showTimezone?: boolean;
6
+ }
7
+ type DatePickerProps = DatePickerPrimitiveProps & FormComponentProps & DatePickerOwnProps;
8
+ declare const DecoratableDatePicker: ({ label, description, note, hint, required, disabled, validation, showTimezone, ...props }: DatePickerProps) => React.JSX.Element;
6
9
  declare const DatePicker: typeof DecoratableDatePicker & {
7
10
  original: typeof DecoratableDatePicker;
8
11
  originalName: string;
@@ -2,7 +2,15 @@ import react, { useMemo } from "react";
2
2
  import { makeDecoratable } from "../utils.js";
3
3
  import { DatePickerPrimitive } from "./primitives/index.js";
4
4
  import { FormComponentDescription, FormComponentErrorMessage, FormComponentLabel, FormComponentNote } from "../FormComponent/index.js";
5
- const DecoratableDatePicker = ({ label, description, note, hint, required, disabled, validation, ...props })=>{
5
+ import { Text } from "../Text/index.js";
6
+ const TimezoneLabel = ()=>{
7
+ const timezone = useMemo(()=>Intl.DateTimeFormat().resolvedOptions().timeZone, []);
8
+ return /*#__PURE__*/ react.createElement(Text, {
9
+ size: "sm",
10
+ className: "text-neutral-strong mt-xxs"
11
+ }, "Timezone: ", timezone);
12
+ };
13
+ const DecoratableDatePicker = ({ label, description, note, hint, required, disabled, validation, showTimezone = false, ...props })=>{
6
14
  const { isValid: validationIsValid, message: validationMessage } = validation || {};
7
15
  const invalid = useMemo(()=>false === validationIsValid, [
8
16
  validationIsValid
@@ -22,7 +30,7 @@ const DecoratableDatePicker = ({ label, description, note, hint, required, disab
22
30
  ...props,
23
31
  disabled: disabled,
24
32
  invalid: invalid
25
- }), /*#__PURE__*/ react.createElement(FormComponentErrorMessage, {
33
+ }), showTimezone && /*#__PURE__*/ react.createElement(TimezoneLabel, null), /*#__PURE__*/ react.createElement(FormComponentErrorMessage, {
26
34
  text: validationMessage,
27
35
  invalid: invalid,
28
36
  disabled: disabled
@@ -1 +1 @@
1
- {"version":3,"file":"DatePicker/DatePicker.js","sources":["../../src/DatePicker/DatePicker.tsx"],"sourcesContent":["import React, { useMemo } from \"react\";\nimport { makeDecoratable } from \"~/utils.js\";\nimport type { DatePickerPrimitiveProps } from \"./primitives/index.js\";\nimport { DatePickerPrimitive } from \"./primitives/index.js\";\nimport type { FormComponentProps } from \"~/FormComponent/index.js\";\nimport {\n FormComponentDescription,\n FormComponentErrorMessage,\n FormComponentLabel,\n FormComponentNote\n} from \"~/FormComponent/index.js\";\n\ntype DatePickerProps = DatePickerPrimitiveProps & FormComponentProps;\n\nconst DecoratableDatePicker = ({\n label,\n description,\n note,\n hint,\n required,\n disabled,\n validation,\n ...props\n}: DatePickerProps) => {\n const { isValid: validationIsValid, message: validationMessage } = validation || {};\n const invalid = useMemo(() => validationIsValid === false, [validationIsValid]);\n\n return (\n <div className=\"w-full\">\n <FormComponentLabel\n text={label}\n hint={hint}\n required={required}\n disabled={disabled}\n invalid={invalid}\n />\n <FormComponentDescription text={description} disabled={disabled} />\n <DatePickerPrimitive\n {...(props as DatePickerPrimitiveProps)}\n disabled={disabled}\n invalid={invalid}\n />\n <FormComponentErrorMessage\n text={validationMessage}\n invalid={invalid}\n disabled={disabled}\n />\n <FormComponentNote text={note} disabled={disabled} />\n </div>\n );\n};\n\nconst DatePicker = makeDecoratable(\"DatePicker\", DecoratableDatePicker);\n\nexport { DatePicker, type DatePickerProps };\n"],"names":["DecoratableDatePicker","label","description","note","hint","required","disabled","validation","props","validationIsValid","validationMessage","invalid","useMemo","FormComponentLabel","FormComponentDescription","DatePickerPrimitive","FormComponentErrorMessage","FormComponentNote","DatePicker","makeDecoratable"],"mappings":";;;;AAcA,MAAMA,wBAAwB,CAAC,EAC3BC,KAAK,EACLC,WAAW,EACXC,IAAI,EACJC,IAAI,EACJC,QAAQ,EACRC,QAAQ,EACRC,UAAU,EACV,GAAGC,OACW;IACd,MAAM,EAAE,SAASC,iBAAiB,EAAE,SAASC,iBAAiB,EAAE,GAAGH,cAAc,CAAC;IAClF,MAAMI,UAAUC,QAAQ,IAAMH,AAAsB,UAAtBA,mBAA6B;QAACA;KAAkB;IAE9E,OAAO,WAAP,GACI,oBAAC;QAAI,WAAU;qBACX,oBAACI,oBAAkBA;QACf,MAAMZ;QACN,MAAMG;QACN,UAAUC;QACV,UAAUC;QACV,SAASK;sBAEb,oBAACG,0BAAwBA;QAAC,MAAMZ;QAAa,UAAUI;sBACvD,oBAACS,qBAAmBA;QACf,GAAIP,KAAK;QACV,UAAUF;QACV,SAASK;sBAEb,oBAACK,2BAAyBA;QACtB,MAAMN;QACN,SAASC;QACT,UAAUL;sBAEd,oBAACW,mBAAiBA;QAAC,MAAMd;QAAM,UAAUG;;AAGrD;AAEA,MAAMY,aAAaC,gBAAgB,cAAcnB"}
1
+ {"version":3,"file":"DatePicker/DatePicker.js","sources":["../../src/DatePicker/DatePicker.tsx"],"sourcesContent":["import React, { useMemo } from \"react\";\nimport { makeDecoratable } from \"~/utils.js\";\nimport type { DatePickerPrimitiveProps } from \"./primitives/index.js\";\nimport { DatePickerPrimitive } from \"./primitives/index.js\";\nimport type { FormComponentProps } from \"~/FormComponent/index.js\";\nimport {\n FormComponentDescription,\n FormComponentErrorMessage,\n FormComponentLabel,\n FormComponentNote\n} from \"~/FormComponent/index.js\";\nimport { Text } from \"~/Text/index.js\";\n\ninterface DatePickerOwnProps {\n showTimezone?: boolean;\n}\n\ntype DatePickerProps = DatePickerPrimitiveProps & FormComponentProps & DatePickerOwnProps;\n\nconst TimezoneLabel = () => {\n const timezone = useMemo(() => Intl.DateTimeFormat().resolvedOptions().timeZone, []);\n return (\n <Text size={\"sm\"} className={\"text-neutral-strong mt-xxs\"}>\n Timezone: {timezone}\n </Text>\n );\n};\n\nconst DecoratableDatePicker = ({\n label,\n description,\n note,\n hint,\n required,\n disabled,\n validation,\n showTimezone = false,\n ...props\n}: DatePickerProps) => {\n const { isValid: validationIsValid, message: validationMessage } = validation || {};\n const invalid = useMemo(() => validationIsValid === false, [validationIsValid]);\n\n return (\n <div className=\"w-full\">\n <FormComponentLabel\n text={label}\n hint={hint}\n required={required}\n disabled={disabled}\n invalid={invalid}\n />\n <FormComponentDescription text={description} disabled={disabled} />\n <DatePickerPrimitive\n {...(props as DatePickerPrimitiveProps)}\n disabled={disabled}\n invalid={invalid}\n />\n {showTimezone && <TimezoneLabel />}\n <FormComponentErrorMessage\n text={validationMessage}\n invalid={invalid}\n disabled={disabled}\n />\n <FormComponentNote text={note} disabled={disabled} />\n </div>\n );\n};\n\nconst DatePicker = makeDecoratable(\"DatePicker\", DecoratableDatePicker);\n\nexport { DatePicker, type DatePickerProps };\n"],"names":["TimezoneLabel","timezone","useMemo","Intl","Text","DecoratableDatePicker","label","description","note","hint","required","disabled","validation","showTimezone","props","validationIsValid","validationMessage","invalid","FormComponentLabel","FormComponentDescription","DatePickerPrimitive","FormComponentErrorMessage","FormComponentNote","DatePicker","makeDecoratable"],"mappings":";;;;;AAmBA,MAAMA,gBAAgB;IAClB,MAAMC,WAAWC,QAAQ,IAAMC,KAAK,cAAc,GAAG,eAAe,GAAG,QAAQ,EAAE,EAAE;IACnF,OAAO,WAAP,GACI,oBAACC,MAAIA;QAAC,MAAM;QAAM,WAAW;OAA8B,cAC5CH;AAGvB;AAEA,MAAMI,wBAAwB,CAAC,EAC3BC,KAAK,EACLC,WAAW,EACXC,IAAI,EACJC,IAAI,EACJC,QAAQ,EACRC,QAAQ,EACRC,UAAU,EACVC,eAAe,KAAK,EACpB,GAAGC,OACW;IACd,MAAM,EAAE,SAASC,iBAAiB,EAAE,SAASC,iBAAiB,EAAE,GAAGJ,cAAc,CAAC;IAClF,MAAMK,UAAUf,QAAQ,IAAMa,AAAsB,UAAtBA,mBAA6B;QAACA;KAAkB;IAE9E,OAAO,WAAP,GACI,oBAAC;QAAI,WAAU;qBACX,oBAACG,oBAAkBA;QACf,MAAMZ;QACN,MAAMG;QACN,UAAUC;QACV,UAAUC;QACV,SAASM;sBAEb,oBAACE,0BAAwBA;QAAC,MAAMZ;QAAa,UAAUI;sBACvD,oBAACS,qBAAmBA;QACf,GAAIN,KAAK;QACV,UAAUH;QACV,SAASM;QAEZJ,gBAAgB,WAAhBA,GAAgB,oBAACb,eAAaA,OAAAA,WAAAA,GAC/B,oBAACqB,2BAAyBA;QACtB,MAAML;QACN,SAASC;QACT,UAAUN;sBAEd,oBAACW,mBAAiBA;QAAC,MAAMd;QAAM,UAAUG;;AAGrD;AAEA,MAAMY,aAAaC,gBAAgB,cAAcnB"}
@@ -4,19 +4,14 @@ import { UTC_TIMEZONES } from "@webiny/utils";
4
4
  import { Calendar } from "../../Calendar/index.js";
5
5
  import { PopoverPrimitive } from "../../Popover/index.js";
6
6
  import { SelectPrimitive } from "../../Select/index.js";
7
- import { extractTimezone, formatDateForDisplay, formatTimeValue, getLocalTimezone, parseTimeValue, toIsoWithTz } from "../utils/dateHelpers.js";
7
+ import { extractTimezone, formatDateForDisplay, formatTimeValue, getLocalTimezone, parseTimeValue } from "../utils/dateHelpers.js";
8
+ import { naiveDateToUtcIso, parseToDate, utcToTimezoneDate } from "../utils/timezoneHelpers.js";
8
9
  import { DatePickerTrigger } from "./components/DatePickerTrigger.js";
9
10
  import { TimePicker } from "./components/TimePicker.js";
10
11
  const timezoneOptions = UTC_TIMEZONES.map((tz)=>({
11
12
  value: tz.value,
12
13
  label: tz.label
13
14
  }));
14
- function parseToDate(value) {
15
- if (!value) return;
16
- const d = new Date(value);
17
- if (Number.isNaN(d.getTime())) return;
18
- return d;
19
- }
20
15
  const DateTimePicker = ({ value, onChange, placeholder, disabled, size, variant, invalid, weekStartsOn, onOpenChange, className, withTimezone, displayFormat, minDate, maxDate })=>{
21
16
  const [open, setOpen] = useState(false);
22
17
  const existingTz = withTimezone && value ? extractTimezone(value) : void 0;
@@ -26,28 +21,28 @@ const DateTimePicker = ({ value, onChange, placeholder, disabled, size, variant,
26
21
  if (onOpenChange) onOpenChange(isOpen);
27
22
  };
28
23
  const currentDate = parseToDate(value);
29
- const displayValue = withTimezone ? formatDateForDisplay(value, "dateTimeTz", displayFormat) : formatDateForDisplay(value, "dateTimeLocal", displayFormat);
30
- const timeValue = currentDate ? formatTimeValue(currentDate) : "";
24
+ const displayDate = withTimezone && currentDate ? utcToTimezoneDate(currentDate, timezone) : currentDate;
25
+ const displayValue = withTimezone ? displayDate ? formatDateForDisplay(format(displayDate, "yyyy-MM-dd'T'HH:mm:ss") + timezone, "dateTimeTz", displayFormat) : void 0 : formatDateForDisplay(value, "dateTimeLocal", displayFormat);
26
+ const timeValue = displayDate ? formatTimeValue(displayDate) : "";
31
27
  const emitChange = (date, tz)=>{
32
28
  if (!onChange) return;
33
- withTimezone ? onChange(toIsoWithTz(date, tz || timezone)) : onChange(format(date, "yyyy-MM-dd'T'HH:mm:ss") + ".000Z");
29
+ withTimezone ? onChange(naiveDateToUtcIso(date, tz || timezone)) : onChange(format(date, "yyyy-MM-dd'T'HH:mm:ss") + ".000Z");
34
30
  };
35
31
  const handleDateSelect = (date)=>{
36
32
  if (!date) return;
37
- if (currentDate) date.setHours(currentDate.getHours(), currentDate.getMinutes());
33
+ if (displayDate) date.setHours(displayDate.getHours(), displayDate.getMinutes());
38
34
  emitChange(date);
39
35
  };
40
36
  const handleTimeChange = (time)=>{
41
37
  if (!time) return;
42
38
  const parsed = parseTimeValue(time);
43
39
  if (!parsed) return;
44
- const base = currentDate ? new Date(currentDate) : new Date();
40
+ const base = displayDate ? new Date(displayDate) : new Date();
45
41
  base.setHours(parsed.hours, parsed.minutes, 0, 0);
46
42
  emitChange(base);
47
43
  };
48
44
  const handleTimezoneChange = (tz)=>{
49
45
  setTimezone(tz);
50
- if (currentDate) emitChange(currentDate, tz);
51
46
  };
52
47
  return /*#__PURE__*/ react.createElement("div", {
53
48
  className: className
@@ -67,7 +62,7 @@ const DateTimePicker = ({ value, onChange, placeholder, disabled, size, variant,
67
62
  className: "flex flex-col gap-sm"
68
63
  }, /*#__PURE__*/ react.createElement(Calendar, {
69
64
  mode: "single",
70
- selected: currentDate,
65
+ selected: displayDate,
71
66
  onSelect: handleDateSelect,
72
67
  weekStartsOn: weekStartsOn,
73
68
  disabled: [
@@ -1 +1 @@
1
- {"version":3,"file":"DatePicker/primitives/DateTimePicker.js","sources":["../../../src/DatePicker/primitives/DateTimePicker.tsx"],"sourcesContent":["import React, { useState } from \"react\";\nimport { format } from \"date-fns\";\nimport { UTC_TIMEZONES } from \"@webiny/utils\";\nimport { Calendar } from \"~/Calendar/index.js\";\nimport { PopoverPrimitive } from \"~/Popover/index.js\";\nimport { SelectPrimitive } from \"~/Select/index.js\";\nimport type { DateTimeLocalPickerProps, DateTimeTzPickerProps } from \"../utils/types.js\";\nimport {\n extractTimezone,\n formatDateForDisplay,\n formatTimeValue,\n getLocalTimezone,\n parseTimeValue,\n toIsoWithTz\n} from \"../utils/dateHelpers.js\";\nimport { DatePickerTrigger } from \"./components/DatePickerTrigger.js\";\nimport { TimePicker } from \"./components/TimePicker.js\";\n\ntype DateTimePickerInternalProps = (DateTimeLocalPickerProps | DateTimeTzPickerProps) & {\n withTimezone: boolean;\n};\n\nconst timezoneOptions = UTC_TIMEZONES.map(tz => ({ value: tz.value, label: tz.label }));\n\nfunction parseToDate(value: string | undefined): Date | undefined {\n if (!value) {\n return undefined;\n }\n const d = new Date(value);\n if (Number.isNaN(d.getTime())) {\n return undefined;\n }\n return d;\n}\n\nconst DateTimePicker = ({\n value,\n onChange,\n placeholder,\n disabled,\n size,\n variant,\n invalid,\n weekStartsOn,\n onOpenChange,\n className,\n withTimezone,\n displayFormat,\n minDate,\n maxDate\n}: DateTimePickerInternalProps) => {\n const [open, setOpen] = useState(false);\n\n const existingTz = withTimezone && value ? extractTimezone(value as string) : undefined;\n const [timezone, setTimezone] = useState(existingTz || getLocalTimezone());\n\n const handleOpenChange = (isOpen: boolean) => {\n setOpen(isOpen);\n if (onOpenChange) {\n onOpenChange(isOpen);\n }\n };\n\n const currentDate = parseToDate(value);\n\n const displayValue = withTimezone\n ? formatDateForDisplay(value, \"dateTimeTz\", displayFormat)\n : formatDateForDisplay(value, \"dateTimeLocal\", displayFormat);\n\n const timeValue = currentDate ? formatTimeValue(currentDate) : \"\";\n\n const emitChange = (date: Date, tz?: string) => {\n if (!onChange) {\n return;\n }\n if (withTimezone) {\n onChange(toIsoWithTz(date, tz || timezone));\n } else {\n onChange(format(date, \"yyyy-MM-dd'T'HH:mm:ss\") + \".000Z\");\n }\n };\n\n const handleDateSelect = (date: Date | undefined) => {\n if (!date) {\n return;\n }\n if (currentDate) {\n date.setHours(currentDate.getHours(), currentDate.getMinutes());\n }\n emitChange(date);\n };\n\n const handleTimeChange = (time: string | undefined) => {\n if (!time) {\n return;\n }\n const parsed = parseTimeValue(time);\n if (!parsed) {\n return;\n }\n const base = currentDate ? new Date(currentDate) : new Date();\n base.setHours(parsed.hours, parsed.minutes, 0, 0);\n emitChange(base);\n };\n\n const handleTimezoneChange = (tz: string) => {\n setTimezone(tz);\n if (currentDate) {\n emitChange(currentDate, tz);\n }\n };\n\n return (\n <div className={className}>\n <PopoverPrimitive open={open} onOpenChange={handleOpenChange}>\n <DatePickerTrigger\n displayValue={displayValue}\n placeholder={placeholder ?? \"Pick date & time\"}\n disabled={disabled}\n size={size}\n variant={variant}\n invalid={invalid}\n />\n <PopoverPrimitive.Content align=\"start\">\n <div className=\"flex flex-col gap-sm\">\n <Calendar\n mode=\"single\"\n selected={currentDate}\n onSelect={handleDateSelect}\n weekStartsOn={weekStartsOn}\n disabled={[\n ...(minDate ? [{ before: minDate }] : []),\n ...(maxDate ? [{ after: maxDate }] : [])\n ]}\n />\n <div className=\"flex gap-sm px-md pb-md\">\n <div className=\"flex-1\">\n <TimePicker\n value={timeValue}\n onChange={handleTimeChange}\n disabled={disabled}\n size=\"md\"\n />\n </div>\n {withTimezone && (\n <div className=\"flex-1\">\n <SelectPrimitive\n value={timezone}\n onChange={handleTimezoneChange}\n options={timezoneOptions}\n disabled={disabled}\n size=\"md\"\n />\n </div>\n )}\n </div>\n </div>\n </PopoverPrimitive.Content>\n </PopoverPrimitive>\n </div>\n );\n};\n\nexport { DateTimePicker };\n"],"names":["timezoneOptions","UTC_TIMEZONES","tz","parseToDate","value","d","Date","Number","DateTimePicker","onChange","placeholder","disabled","size","variant","invalid","weekStartsOn","onOpenChange","className","withTimezone","displayFormat","minDate","maxDate","open","setOpen","useState","existingTz","extractTimezone","undefined","timezone","setTimezone","getLocalTimezone","handleOpenChange","isOpen","currentDate","displayValue","formatDateForDisplay","timeValue","formatTimeValue","emitChange","date","toIsoWithTz","format","handleDateSelect","handleTimeChange","time","parsed","parseTimeValue","base","handleTimezoneChange","PopoverPrimitive","DatePickerTrigger","Calendar","TimePicker","SelectPrimitive"],"mappings":";;;;;;;;;AAsBA,MAAMA,kBAAkBC,cAAc,GAAG,CAACC,CAAAA,KAAO;QAAE,OAAOA,GAAG,KAAK;QAAE,OAAOA,GAAG,KAAK;IAAC;AAEpF,SAASC,YAAYC,KAAyB;IAC1C,IAAI,CAACA,OACD;IAEJ,MAAMC,IAAI,IAAIC,KAAKF;IACnB,IAAIG,OAAO,KAAK,CAACF,EAAE,OAAO,KACtB;IAEJ,OAAOA;AACX;AAEA,MAAMG,iBAAiB,CAAC,EACpBJ,KAAK,EACLK,QAAQ,EACRC,WAAW,EACXC,QAAQ,EACRC,IAAI,EACJC,OAAO,EACPC,OAAO,EACPC,YAAY,EACZC,YAAY,EACZC,SAAS,EACTC,YAAY,EACZC,aAAa,EACbC,OAAO,EACPC,OAAO,EACmB;IAC1B,MAAM,CAACC,MAAMC,QAAQ,GAAGC,SAAS;IAEjC,MAAMC,aAAaP,gBAAgBd,QAAQsB,gBAAgBtB,SAAmBuB;IAC9E,MAAM,CAACC,UAAUC,YAAY,GAAGL,SAASC,cAAcK;IAEvD,MAAMC,mBAAmB,CAACC;QACtBT,QAAQS;QACR,IAAIhB,cACAA,aAAagB;IAErB;IAEA,MAAMC,cAAc9B,YAAYC;IAEhC,MAAM8B,eAAehB,eACfiB,qBAAqB/B,OAAO,cAAce,iBAC1CgB,qBAAqB/B,OAAO,iBAAiBe;IAEnD,MAAMiB,YAAYH,cAAcI,gBAAgBJ,eAAe;IAE/D,MAAMK,aAAa,CAACC,MAAYrC;QAC5B,IAAI,CAACO,UACD;QAEAS,eACAT,SAAS+B,YAAYD,MAAMrC,MAAM0B,aAEjCnB,SAASgC,OAAOF,MAAM,2BAA2B;IAEzD;IAEA,MAAMG,mBAAmB,CAACH;QACtB,IAAI,CAACA,MACD;QAEJ,IAAIN,aACAM,KAAK,QAAQ,CAACN,YAAY,QAAQ,IAAIA,YAAY,UAAU;QAEhEK,WAAWC;IACf;IAEA,MAAMI,mBAAmB,CAACC;QACtB,IAAI,CAACA,MACD;QAEJ,MAAMC,SAASC,eAAeF;QAC9B,IAAI,CAACC,QACD;QAEJ,MAAME,OAAOd,cAAc,IAAI3B,KAAK2B,eAAe,IAAI3B;QACvDyC,KAAK,QAAQ,CAACF,OAAO,KAAK,EAAEA,OAAO,OAAO,EAAE,GAAG;QAC/CP,WAAWS;IACf;IAEA,MAAMC,uBAAuB,CAAC9C;QAC1B2B,YAAY3B;QACZ,IAAI+B,aACAK,WAAWL,aAAa/B;IAEhC;IAEA,OAAO,WAAP,GACI,oBAAC;QAAI,WAAWe;qBACZ,oBAACgC,kBAAgBA;QAAC,MAAM3B;QAAM,cAAcS;qBACxC,oBAACmB,mBAAiBA;QACd,cAAchB;QACd,aAAaxB,eAAe;QAC5B,UAAUC;QACV,MAAMC;QACN,SAASC;QACT,SAASC;sBAEb,oBAACmC,iBAAiB,OAAO;QAAC,OAAM;qBAC5B,oBAAC;QAAI,WAAU;qBACX,oBAACE,UAAQA;QACL,MAAK;QACL,UAAUlB;QACV,UAAUS;QACV,cAAc3B;QACd,UAAU;eACFK,UAAU;gBAAC;oBAAE,QAAQA;gBAAQ;aAAE,GAAG,EAAE;eACpCC,UAAU;gBAAC;oBAAE,OAAOA;gBAAQ;aAAE,GAAG,EAAE;SAC1C;sBAEL,oBAAC;QAAI,WAAU;qBACX,oBAAC;QAAI,WAAU;qBACX,oBAAC+B,YAAUA;QACP,OAAOhB;QACP,UAAUO;QACV,UAAUhC;QACV,MAAK;SAGZO,gBAAgB,WAAhBA,GACG,oBAAC;QAAI,WAAU;qBACX,oBAACmC,iBAAeA;QACZ,OAAOzB;QACP,UAAUoB;QACV,SAAShD;QACT,UAAUW;QACV,MAAK;;AAU7C"}
1
+ {"version":3,"file":"DatePicker/primitives/DateTimePicker.js","sources":["../../../src/DatePicker/primitives/DateTimePicker.tsx"],"sourcesContent":["import React, { useState } from \"react\";\nimport { format } from \"date-fns\";\nimport { UTC_TIMEZONES } from \"@webiny/utils\";\nimport { Calendar } from \"~/Calendar/index.js\";\nimport { PopoverPrimitive } from \"~/Popover/index.js\";\nimport { SelectPrimitive } from \"~/Select/index.js\";\nimport type { DateTimeLocalPickerProps, DateTimeTzPickerProps } from \"../utils/types.js\";\nimport {\n extractTimezone,\n formatDateForDisplay,\n formatTimeValue,\n getLocalTimezone,\n parseTimeValue\n} from \"../utils/dateHelpers.js\";\nimport { naiveDateToUtcIso, parseToDate, utcToTimezoneDate } from \"../utils/timezoneHelpers.js\";\nimport { DatePickerTrigger } from \"./components/DatePickerTrigger.js\";\nimport { TimePicker } from \"./components/TimePicker.js\";\n\ntype DateTimePickerInternalProps = (DateTimeLocalPickerProps | DateTimeTzPickerProps) & {\n withTimezone: boolean;\n};\n\nconst timezoneOptions = UTC_TIMEZONES.map(tz => ({ value: tz.value, label: tz.label }));\n\nconst DateTimePicker = ({\n value,\n onChange,\n placeholder,\n disabled,\n size,\n variant,\n invalid,\n weekStartsOn,\n onOpenChange,\n className,\n withTimezone,\n displayFormat,\n minDate,\n maxDate\n}: DateTimePickerInternalProps) => {\n const [open, setOpen] = useState(false);\n\n const existingTz = withTimezone && value ? extractTimezone(value) : undefined;\n const [timezone, setTimezone] = useState(existingTz || getLocalTimezone());\n\n const handleOpenChange = (isOpen: boolean) => {\n setOpen(isOpen);\n if (onOpenChange) {\n onOpenChange(isOpen);\n }\n };\n\n const currentDate = parseToDate(value);\n\n const displayDate =\n withTimezone && currentDate ? utcToTimezoneDate(currentDate, timezone) : currentDate;\n\n const displayValue = withTimezone\n ? displayDate\n ? formatDateForDisplay(\n format(displayDate, \"yyyy-MM-dd'T'HH:mm:ss\") + timezone,\n \"dateTimeTz\",\n displayFormat\n )\n : undefined\n : formatDateForDisplay(value, \"dateTimeLocal\", displayFormat);\n\n const timeValue = displayDate ? formatTimeValue(displayDate) : \"\";\n\n const emitChange = (date: Date, tz?: string) => {\n if (!onChange) {\n return;\n }\n if (withTimezone) {\n onChange(naiveDateToUtcIso(date, tz || timezone));\n } else {\n onChange(format(date, \"yyyy-MM-dd'T'HH:mm:ss\") + \".000Z\");\n }\n };\n\n const handleDateSelect = (date: Date | undefined) => {\n if (!date) {\n return;\n }\n if (displayDate) {\n date.setHours(displayDate.getHours(), displayDate.getMinutes());\n }\n emitChange(date);\n };\n\n const handleTimeChange = (time: string | undefined) => {\n if (!time) {\n return;\n }\n const parsed = parseTimeValue(time);\n if (!parsed) {\n return;\n }\n const base = displayDate ? new Date(displayDate) : new Date();\n base.setHours(parsed.hours, parsed.minutes, 0, 0);\n emitChange(base);\n };\n\n const handleTimezoneChange = (tz: string) => {\n setTimezone(tz);\n };\n\n return (\n <div className={className}>\n <PopoverPrimitive open={open} onOpenChange={handleOpenChange}>\n <DatePickerTrigger\n displayValue={displayValue}\n placeholder={placeholder ?? \"Pick date & time\"}\n disabled={disabled}\n size={size}\n variant={variant}\n invalid={invalid}\n />\n <PopoverPrimitive.Content align=\"start\">\n <div className=\"flex flex-col gap-sm\">\n <Calendar\n mode=\"single\"\n selected={displayDate}\n onSelect={handleDateSelect}\n weekStartsOn={weekStartsOn}\n disabled={[\n ...(minDate ? [{ before: minDate }] : []),\n ...(maxDate ? [{ after: maxDate }] : [])\n ]}\n />\n <div className=\"flex gap-sm px-md pb-md\">\n <div className=\"flex-1\">\n <TimePicker\n value={timeValue}\n onChange={handleTimeChange}\n disabled={disabled}\n size=\"md\"\n />\n </div>\n {withTimezone && (\n <div className=\"flex-1\">\n <SelectPrimitive\n value={timezone}\n onChange={handleTimezoneChange}\n options={timezoneOptions}\n disabled={disabled}\n size=\"md\"\n />\n </div>\n )}\n </div>\n </div>\n </PopoverPrimitive.Content>\n </PopoverPrimitive>\n </div>\n );\n};\n\nexport { DateTimePicker };\n"],"names":["timezoneOptions","UTC_TIMEZONES","tz","DateTimePicker","value","onChange","placeholder","disabled","size","variant","invalid","weekStartsOn","onOpenChange","className","withTimezone","displayFormat","minDate","maxDate","open","setOpen","useState","existingTz","extractTimezone","undefined","timezone","setTimezone","getLocalTimezone","handleOpenChange","isOpen","currentDate","parseToDate","displayDate","utcToTimezoneDate","displayValue","formatDateForDisplay","format","timeValue","formatTimeValue","emitChange","date","naiveDateToUtcIso","handleDateSelect","handleTimeChange","time","parsed","parseTimeValue","base","Date","handleTimezoneChange","PopoverPrimitive","DatePickerTrigger","Calendar","TimePicker","SelectPrimitive"],"mappings":";;;;;;;;;;AAsBA,MAAMA,kBAAkBC,cAAc,GAAG,CAACC,CAAAA,KAAO;QAAE,OAAOA,GAAG,KAAK;QAAE,OAAOA,GAAG,KAAK;IAAC;AAEpF,MAAMC,iBAAiB,CAAC,EACpBC,KAAK,EACLC,QAAQ,EACRC,WAAW,EACXC,QAAQ,EACRC,IAAI,EACJC,OAAO,EACPC,OAAO,EACPC,YAAY,EACZC,YAAY,EACZC,SAAS,EACTC,YAAY,EACZC,aAAa,EACbC,OAAO,EACPC,OAAO,EACmB;IAC1B,MAAM,CAACC,MAAMC,QAAQ,GAAGC,SAAS;IAEjC,MAAMC,aAAaP,gBAAgBV,QAAQkB,gBAAgBlB,SAASmB;IACpE,MAAM,CAACC,UAAUC,YAAY,GAAGL,SAASC,cAAcK;IAEvD,MAAMC,mBAAmB,CAACC;QACtBT,QAAQS;QACR,IAAIhB,cACAA,aAAagB;IAErB;IAEA,MAAMC,cAAcC,YAAY1B;IAEhC,MAAM2B,cACFjB,gBAAgBe,cAAcG,kBAAkBH,aAAaL,YAAYK;IAE7E,MAAMI,eAAenB,eACfiB,cACIG,qBACIC,OAAOJ,aAAa,2BAA2BP,UAC/C,cACAT,iBAEJQ,SACJW,qBAAqB9B,OAAO,iBAAiBW;IAEnD,MAAMqB,YAAYL,cAAcM,gBAAgBN,eAAe;IAE/D,MAAMO,aAAa,CAACC,MAAYrC;QAC5B,IAAI,CAACG,UACD;QAEAS,eACAT,SAASmC,kBAAkBD,MAAMrC,MAAMsB,aAEvCnB,SAAS8B,OAAOI,MAAM,2BAA2B;IAEzD;IAEA,MAAME,mBAAmB,CAACF;QACtB,IAAI,CAACA,MACD;QAEJ,IAAIR,aACAQ,KAAK,QAAQ,CAACR,YAAY,QAAQ,IAAIA,YAAY,UAAU;QAEhEO,WAAWC;IACf;IAEA,MAAMG,mBAAmB,CAACC;QACtB,IAAI,CAACA,MACD;QAEJ,MAAMC,SAASC,eAAeF;QAC9B,IAAI,CAACC,QACD;QAEJ,MAAME,OAAOf,cAAc,IAAIgB,KAAKhB,eAAe,IAAIgB;QACvDD,KAAK,QAAQ,CAACF,OAAO,KAAK,EAAEA,OAAO,OAAO,EAAE,GAAG;QAC/CN,WAAWQ;IACf;IAEA,MAAME,uBAAuB,CAAC9C;QAC1BuB,YAAYvB;IAChB;IAEA,OAAO,WAAP,GACI,oBAAC;QAAI,WAAWW;qBACZ,oBAACoC,kBAAgBA;QAAC,MAAM/B;QAAM,cAAcS;qBACxC,oBAACuB,mBAAiBA;QACd,cAAcjB;QACd,aAAa3B,eAAe;QAC5B,UAAUC;QACV,MAAMC;QACN,SAASC;QACT,SAASC;sBAEb,oBAACuC,iBAAiB,OAAO;QAAC,OAAM;qBAC5B,oBAAC;QAAI,WAAU;qBACX,oBAACE,UAAQA;QACL,MAAK;QACL,UAAUpB;QACV,UAAUU;QACV,cAAc9B;QACd,UAAU;eACFK,UAAU;gBAAC;oBAAE,QAAQA;gBAAQ;aAAE,GAAG,EAAE;eACpCC,UAAU;gBAAC;oBAAE,OAAOA;gBAAQ;aAAE,GAAG,EAAE;SAC1C;sBAEL,oBAAC;QAAI,WAAU;qBACX,oBAAC;QAAI,WAAU;qBACX,oBAACmC,YAAUA;QACP,OAAOhB;QACP,UAAUM;QACV,UAAUnC;QACV,MAAK;SAGZO,gBAAgB,WAAhBA,GACG,oBAAC;QAAI,WAAU;qBACX,oBAACuC,iBAAeA;QACZ,OAAO7B;QACP,UAAUwB;QACV,SAAShD;QACT,UAAUO;QACV,MAAK;;AAU7C"}
@@ -15,7 +15,7 @@ export declare function parseTimeValue(time: string): {
15
15
  } | undefined;
16
16
  export declare function toIsoWithTz(date: Date, timezone?: string): string;
17
17
  export declare function getLocalTimezone(): string;
18
- export declare function extractTimezone(isoString: string): string | undefined;
18
+ export declare function extractTimezone(isoString: string | Date | unknown): string | undefined;
19
19
  export declare function toLocalNaive(isoString: string): Date;
20
20
  export declare function formatWeekValue(date: Date): string;
21
21
  export declare function parseWeekValue(value: string): {
@@ -12,7 +12,7 @@ function formatDateForDisplay(value, type, displayFormat) {
12
12
  case "dateTimeTz":
13
13
  {
14
14
  if (!value) return;
15
- const isoStr = value;
15
+ const isoStr = value instanceof Date ? value.toISOString() : value;
16
16
  const tzMatch = isoStr.match(/([+-]\d{2}:\d{2})$/);
17
17
  const tz = tzMatch ? `UTC${tzMatch[1]}` : "";
18
18
  const dateWithoutTz = isoStr.replace(/[+-]\d{2}:\d{2}$/, "");
@@ -127,6 +127,7 @@ function getLocalTimezone() {
127
127
  return `${sign}${hours}:${minutes}`;
128
128
  }
129
129
  function extractTimezone(isoString) {
130
+ if ("string" != typeof isoString) return;
130
131
  const match = isoString.match(/([+-]\d{2}:\d{2})$/);
131
132
  if (match) return match[1];
132
133
  }
@@ -1 +1 @@
1
- {"version":3,"file":"DatePicker/utils/dateHelpers.js","sources":["../../../src/DatePicker/utils/dateHelpers.ts"],"sourcesContent":["import { format, getISOWeek, getISOWeekYear, startOfISOWeek, endOfISOWeek } from \"date-fns\";\nimport { DEFAULT_YEAR_RANGE_SIZE, MONTH_NAMES_SHORT } from \"./constants.js\";\n\nexport function formatDateForDisplay(\n value:\n | Date\n | string\n | number\n | { from?: string; to?: string }\n | Date[]\n | string[]\n | number[]\n | undefined,\n type: string,\n displayFormat?: string\n): string | undefined {\n if (value === undefined || value === null) {\n return undefined;\n }\n\n switch (type) {\n case \"date\":\n return format(new Date(value as string), displayFormat ?? \"PPP\");\n case \"time\":\n return value as string;\n case \"dateTimeLocal\":\n return format(new Date(value as string), displayFormat ?? \"PPP p\");\n case \"dateTimeTz\": {\n if (!value) {\n return undefined;\n }\n const isoStr = value as string;\n const tzMatch = isoStr.match(/([+-]\\d{2}:\\d{2})$/);\n const tz = tzMatch ? `UTC${tzMatch[1]}` : \"\";\n const dateWithoutTz = isoStr.replace(/[+-]\\d{2}:\\d{2}$/, \"\");\n const parts = dateWithoutTz.split(\"T\");\n if (parts.length < 2) {\n return isoStr;\n }\n const datePart = new Date(parts[0] + \"T00:00:00\");\n const timeParts = parts[1].split(\":\");\n const hours = Number(timeParts[0]);\n const minutes = timeParts[1] ?? \"00\";\n const ampm = hours >= 12 ? \"PM\" : \"AM\";\n const h12 = hours % 12 || 12;\n if (displayFormat) {\n return `${format(datePart, displayFormat)} ${h12}:${minutes} ${ampm} (${tz})`;\n }\n return `${format(datePart, \"PPP\")} ${h12}:${minutes} ${ampm} (${tz})`;\n }\n case \"month\": {\n if (displayFormat) {\n const parsed = parseMonthValue(value as string);\n if (!parsed) {\n return undefined;\n }\n return format(new Date(parsed.year, parsed.month), displayFormat);\n }\n const parsed = parseMonthValue(value as string);\n if (!parsed) {\n return undefined;\n }\n return `${MONTH_NAMES_SHORT[parsed.month]} ${parsed.year}`;\n }\n case \"week\": {\n const parsed = parseWeekValue(value as string);\n if (!parsed) {\n return undefined;\n }\n const weekStart = startOfISOWeek(new Date(parsed.year, 0, 4 + (parsed.week - 1) * 7));\n const weekEnd = endOfISOWeek(weekStart);\n if (displayFormat) {\n return `${format(weekStart, displayFormat)} – ${format(weekEnd, displayFormat)}`;\n }\n return `Week ${parsed.week}, ${format(weekStart, \"MMM d\")} – ${format(weekEnd, \"MMM d, yyyy\")}`;\n }\n case \"year\":\n return String(value);\n case \"dateRange\": {\n const range = value as { from?: string; to?: string };\n const fmt = displayFormat ?? \"PPP\";\n if (!range.from) {\n return undefined;\n }\n if (!range.to) {\n return format(new Date(range.from), fmt);\n }\n return `${format(new Date(range.from), fmt)} – ${format(new Date(range.to), fmt)}`;\n }\n case \"multipleDates\": {\n const dates = value as string[];\n if (dates.length === 0) {\n return undefined;\n }\n return `${dates.length} date${dates.length > 1 ? \"s\" : \"\"} selected`;\n }\n case \"multipleMonths\": {\n const months = value as string[];\n if (months.length === 0) {\n return undefined;\n }\n return `${months.length} month${months.length > 1 ? \"s\" : \"\"} selected`;\n }\n case \"multipleYears\": {\n const years = value as number[];\n if (years.length === 0) {\n return undefined;\n }\n return `${years.length} year${years.length > 1 ? \"s\" : \"\"} selected`;\n }\n default:\n return undefined;\n }\n}\n\nexport function defaultYearRange(centerYear?: number): [number, number] {\n const center = centerYear ?? new Date().getFullYear();\n const half = Math.floor(DEFAULT_YEAR_RANGE_SIZE / 2);\n return [center - half, center + half - 1];\n}\n\nexport function formatMonthValue(year: number, month: number): string {\n return `${year}-${String(month + 1).padStart(2, \"0\")}`;\n}\n\nexport function parseMonthValue(value: string): { year: number; month: number } | undefined {\n const match = value.match(/^(\\d{4})-(\\d{2})$/);\n if (!match) {\n return undefined;\n }\n return { year: Number(match[1]), month: Number(match[2]) - 1 };\n}\n\nexport function formatTimeValue(date: Date): string {\n return format(date, \"HH:mm\");\n}\n\nexport function parseTimeValue(time: string): { hours: number; minutes: number } | undefined {\n const match = time.match(/^(\\d{2}):(\\d{2})$/);\n if (!match) {\n return undefined;\n }\n return { hours: Number(match[1]), minutes: Number(match[2]) };\n}\n\nexport function toIsoWithTz(date: Date, timezone?: string): string {\n if (timezone) {\n return format(date, \"yyyy-MM-dd'T'HH:mm:ss\") + timezone;\n }\n const offset = -date.getTimezoneOffset();\n const sign = offset >= 0 ? \"+\" : \"-\";\n const absOffset = Math.abs(offset);\n const hours = String(Math.floor(absOffset / 60)).padStart(2, \"0\");\n const minutes = String(absOffset % 60).padStart(2, \"0\");\n return format(date, \"yyyy-MM-dd'T'HH:mm:ss\") + `${sign}${hours}:${minutes}`;\n}\n\nexport function getLocalTimezone(): string {\n const offset = -new Date().getTimezoneOffset();\n const sign = offset >= 0 ? \"+\" : \"-\";\n const absOffset = Math.abs(offset);\n const hours = String(Math.floor(absOffset / 60)).padStart(2, \"0\");\n const minutes = String(absOffset % 60).padStart(2, \"0\");\n return `${sign}${hours}:${minutes}`;\n}\n\nexport function extractTimezone(isoString: string): string | undefined {\n const match = isoString.match(/([+-]\\d{2}:\\d{2})$/);\n if (match) {\n return match[1];\n }\n return undefined;\n}\n\nexport function toLocalNaive(isoString: string): Date {\n return new Date(isoString);\n}\n\nexport function formatWeekValue(date: Date): string {\n const week = getISOWeek(date);\n const year = getISOWeekYear(date);\n return `${year}-W${String(week).padStart(2, \"0\")}`;\n}\n\nexport function parseWeekValue(value: string): { year: number; week: number } | undefined {\n const match = value.match(/^(\\d{4})-W(\\d{2})$/);\n if (!match) {\n return undefined;\n }\n return { year: Number(match[1]), week: Number(match[2]) };\n}\n"],"names":["formatDateForDisplay","value","type","displayFormat","format","Date","isoStr","tzMatch","tz","dateWithoutTz","parts","datePart","timeParts","hours","Number","minutes","ampm","h12","parsed","parseMonthValue","MONTH_NAMES_SHORT","parseWeekValue","weekStart","startOfISOWeek","weekEnd","endOfISOWeek","String","range","fmt","dates","months","years","defaultYearRange","centerYear","center","half","Math","DEFAULT_YEAR_RANGE_SIZE","formatMonthValue","year","month","match","formatTimeValue","date","parseTimeValue","time","toIsoWithTz","timezone","offset","sign","absOffset","getLocalTimezone","extractTimezone","isoString","toLocalNaive","formatWeekValue","week","getISOWeek","getISOWeekYear"],"mappings":"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"}
1
+ {"version":3,"file":"DatePicker/utils/dateHelpers.js","sources":["../../../src/DatePicker/utils/dateHelpers.ts"],"sourcesContent":["import { format, getISOWeek, getISOWeekYear, startOfISOWeek, endOfISOWeek } from \"date-fns\";\nimport { DEFAULT_YEAR_RANGE_SIZE, MONTH_NAMES_SHORT } from \"./constants.js\";\n\nexport function formatDateForDisplay(\n value:\n | Date\n | string\n | number\n | { from?: string; to?: string }\n | Date[]\n | string[]\n | number[]\n | undefined,\n type: string,\n displayFormat?: string\n): string | undefined {\n if (value === undefined || value === null) {\n return undefined;\n }\n\n switch (type) {\n case \"date\":\n return format(new Date(value as string), displayFormat ?? \"PPP\");\n case \"time\":\n return value as string;\n case \"dateTimeLocal\":\n return format(new Date(value as string), displayFormat ?? \"PPP p\");\n case \"dateTimeTz\": {\n if (!value) {\n return undefined;\n }\n const isoStr = value instanceof Date ? value.toISOString() : (value as string);\n const tzMatch = isoStr.match(/([+-]\\d{2}:\\d{2})$/);\n const tz = tzMatch ? `UTC${tzMatch[1]}` : \"\";\n const dateWithoutTz = isoStr.replace(/[+-]\\d{2}:\\d{2}$/, \"\");\n const parts = dateWithoutTz.split(\"T\");\n if (parts.length < 2) {\n return isoStr;\n }\n const datePart = new Date(parts[0] + \"T00:00:00\");\n const timeParts = parts[1].split(\":\");\n const hours = Number(timeParts[0]);\n const minutes = timeParts[1] ?? \"00\";\n const ampm = hours >= 12 ? \"PM\" : \"AM\";\n const h12 = hours % 12 || 12;\n if (displayFormat) {\n return `${format(datePart, displayFormat)} ${h12}:${minutes} ${ampm} (${tz})`;\n }\n return `${format(datePart, \"PPP\")} ${h12}:${minutes} ${ampm} (${tz})`;\n }\n case \"month\": {\n if (displayFormat) {\n const parsed = parseMonthValue(value as string);\n if (!parsed) {\n return undefined;\n }\n return format(new Date(parsed.year, parsed.month), displayFormat);\n }\n const parsed = parseMonthValue(value as string);\n if (!parsed) {\n return undefined;\n }\n return `${MONTH_NAMES_SHORT[parsed.month]} ${parsed.year}`;\n }\n case \"week\": {\n const parsed = parseWeekValue(value as string);\n if (!parsed) {\n return undefined;\n }\n const weekStart = startOfISOWeek(new Date(parsed.year, 0, 4 + (parsed.week - 1) * 7));\n const weekEnd = endOfISOWeek(weekStart);\n if (displayFormat) {\n return `${format(weekStart, displayFormat)} – ${format(weekEnd, displayFormat)}`;\n }\n return `Week ${parsed.week}, ${format(weekStart, \"MMM d\")} – ${format(weekEnd, \"MMM d, yyyy\")}`;\n }\n case \"year\":\n return String(value);\n case \"dateRange\": {\n const range = value as { from?: string; to?: string };\n const fmt = displayFormat ?? \"PPP\";\n if (!range.from) {\n return undefined;\n }\n if (!range.to) {\n return format(new Date(range.from), fmt);\n }\n return `${format(new Date(range.from), fmt)} – ${format(new Date(range.to), fmt)}`;\n }\n case \"multipleDates\": {\n const dates = value as string[];\n if (dates.length === 0) {\n return undefined;\n }\n return `${dates.length} date${dates.length > 1 ? \"s\" : \"\"} selected`;\n }\n case \"multipleMonths\": {\n const months = value as string[];\n if (months.length === 0) {\n return undefined;\n }\n return `${months.length} month${months.length > 1 ? \"s\" : \"\"} selected`;\n }\n case \"multipleYears\": {\n const years = value as number[];\n if (years.length === 0) {\n return undefined;\n }\n return `${years.length} year${years.length > 1 ? \"s\" : \"\"} selected`;\n }\n default:\n return undefined;\n }\n}\n\nexport function defaultYearRange(centerYear?: number): [number, number] {\n const center = centerYear ?? new Date().getFullYear();\n const half = Math.floor(DEFAULT_YEAR_RANGE_SIZE / 2);\n return [center - half, center + half - 1];\n}\n\nexport function formatMonthValue(year: number, month: number): string {\n return `${year}-${String(month + 1).padStart(2, \"0\")}`;\n}\n\nexport function parseMonthValue(value: string): { year: number; month: number } | undefined {\n const match = value.match(/^(\\d{4})-(\\d{2})$/);\n if (!match) {\n return undefined;\n }\n return { year: Number(match[1]), month: Number(match[2]) - 1 };\n}\n\nexport function formatTimeValue(date: Date): string {\n return format(date, \"HH:mm\");\n}\n\nexport function parseTimeValue(time: string): { hours: number; minutes: number } | undefined {\n const match = time.match(/^(\\d{2}):(\\d{2})$/);\n if (!match) {\n return undefined;\n }\n return { hours: Number(match[1]), minutes: Number(match[2]) };\n}\n\nexport function toIsoWithTz(date: Date, timezone?: string): string {\n if (timezone) {\n return format(date, \"yyyy-MM-dd'T'HH:mm:ss\") + timezone;\n }\n const offset = -date.getTimezoneOffset();\n const sign = offset >= 0 ? \"+\" : \"-\";\n const absOffset = Math.abs(offset);\n const hours = String(Math.floor(absOffset / 60)).padStart(2, \"0\");\n const minutes = String(absOffset % 60).padStart(2, \"0\");\n return format(date, \"yyyy-MM-dd'T'HH:mm:ss\") + `${sign}${hours}:${minutes}`;\n}\n\nexport function getLocalTimezone(): string {\n const offset = -new Date().getTimezoneOffset();\n const sign = offset >= 0 ? \"+\" : \"-\";\n const absOffset = Math.abs(offset);\n const hours = String(Math.floor(absOffset / 60)).padStart(2, \"0\");\n const minutes = String(absOffset % 60).padStart(2, \"0\");\n return `${sign}${hours}:${minutes}`;\n}\n\nexport function extractTimezone(isoString: string | Date | unknown): string | undefined {\n if (typeof isoString !== \"string\") {\n return undefined;\n }\n const match = isoString.match(/([+-]\\d{2}:\\d{2})$/);\n if (match) {\n return match[1];\n }\n return undefined;\n}\n\nexport function toLocalNaive(isoString: string): Date {\n return new Date(isoString);\n}\n\nexport function formatWeekValue(date: Date): string {\n const week = getISOWeek(date);\n const year = getISOWeekYear(date);\n return `${year}-W${String(week).padStart(2, \"0\")}`;\n}\n\nexport function parseWeekValue(value: string): { year: number; week: number } | undefined {\n const match = value.match(/^(\\d{4})-W(\\d{2})$/);\n if (!match) {\n return undefined;\n }\n return { year: Number(match[1]), week: Number(match[2]) };\n}\n"],"names":["formatDateForDisplay","value","type","displayFormat","format","Date","isoStr","tzMatch","tz","dateWithoutTz","parts","datePart","timeParts","hours","Number","minutes","ampm","h12","parsed","parseMonthValue","MONTH_NAMES_SHORT","parseWeekValue","weekStart","startOfISOWeek","weekEnd","endOfISOWeek","String","range","fmt","dates","months","years","defaultYearRange","centerYear","center","half","Math","DEFAULT_YEAR_RANGE_SIZE","formatMonthValue","year","month","match","formatTimeValue","date","parseTimeValue","time","toIsoWithTz","timezone","offset","sign","absOffset","getLocalTimezone","extractTimezone","isoString","toLocalNaive","formatWeekValue","week","getISOWeek","getISOWeekYear"],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export declare function utcToTimezoneDate(utcDate: Date, timezone: string): Date;
2
+ export declare function naiveDateToUtcIso(date: Date, timezone: string): string;
3
+ export declare function parseToDate(value: string | Date | undefined): Date | undefined;
@@ -0,0 +1,32 @@
1
+ import { format } from "date-fns";
2
+ function parseOffset(tz) {
3
+ const match = tz.match(/^([+-])(\d{2}):(\d{2})$/);
4
+ if (!match) return null;
5
+ const sign = "+" === match[1] ? 1 : -1;
6
+ return {
7
+ sign,
8
+ minutes: sign * (60 * Number(match[2]) + Number(match[3]))
9
+ };
10
+ }
11
+ function utcToTimezoneDate(utcDate, timezone) {
12
+ const parsed = parseOffset(timezone);
13
+ if (!parsed) return utcDate;
14
+ const localOffsetMinutes = -utcDate.getTimezoneOffset();
15
+ const shiftMs = (parsed.minutes - localOffsetMinutes) * 60000;
16
+ return new Date(utcDate.getTime() + shiftMs);
17
+ }
18
+ function naiveDateToUtcIso(date, timezone) {
19
+ const naive = format(date, "yyyy-MM-dd'T'HH:mm:ss");
20
+ const parsed = parseOffset(timezone);
21
+ if (parsed) return new Date(`${naive}${timezone}`).toISOString();
22
+ return date.toISOString();
23
+ }
24
+ function parseToDate(value) {
25
+ if (!value) return;
26
+ const d = new Date(value);
27
+ if (Number.isNaN(d.getTime())) return;
28
+ return d;
29
+ }
30
+ export { naiveDateToUtcIso, parseToDate, utcToTimezoneDate };
31
+
32
+ //# sourceMappingURL=timezoneHelpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DatePicker/utils/timezoneHelpers.js","sources":["../../../src/DatePicker/utils/timezoneHelpers.ts"],"sourcesContent":["import { format } from \"date-fns\";\n\ninterface ParsedOffset {\n sign: number;\n minutes: number;\n}\n\nfunction parseOffset(tz: string): ParsedOffset | null {\n const match = tz.match(/^([+-])(\\d{2}):(\\d{2})$/);\n if (!match) {\n return null;\n }\n const sign = match[1] === \"+\" ? 1 : -1;\n return { sign, minutes: sign * (Number(match[2]) * 60 + Number(match[3])) };\n}\n\nexport function utcToTimezoneDate(utcDate: Date, timezone: string): Date {\n const parsed = parseOffset(timezone);\n if (!parsed) {\n return utcDate;\n }\n const localOffsetMinutes = -utcDate.getTimezoneOffset();\n const shiftMs = (parsed.minutes - localOffsetMinutes) * 60 * 1000;\n return new Date(utcDate.getTime() + shiftMs);\n}\n\nexport function naiveDateToUtcIso(date: Date, timezone: string): string {\n const naive = format(date, \"yyyy-MM-dd'T'HH:mm:ss\");\n const parsed = parseOffset(timezone);\n if (parsed) {\n return new Date(`${naive}${timezone}`).toISOString();\n }\n return date.toISOString();\n}\n\nexport function parseToDate(value: string | Date | undefined): Date | undefined {\n if (!value) {\n return undefined;\n }\n const d = new Date(value);\n if (Number.isNaN(d.getTime())) {\n return undefined;\n }\n return d;\n}\n"],"names":["parseOffset","tz","match","sign","Number","utcToTimezoneDate","utcDate","timezone","parsed","localOffsetMinutes","shiftMs","Date","naiveDateToUtcIso","date","naive","format","parseToDate","value","d"],"mappings":";AAOA,SAASA,YAAYC,EAAU;IAC3B,MAAMC,QAAQD,GAAG,KAAK,CAAC;IACvB,IAAI,CAACC,OACD,OAAO;IAEX,MAAMC,OAAOD,AAAa,QAAbA,KAAK,CAAC,EAAE,GAAW,IAAI;IACpC,OAAO;QAAEC;QAAM,SAASA,OAAQC,CAAAA,AAAmB,KAAnBA,OAAOF,KAAK,CAAC,EAAE,IAASE,OAAOF,KAAK,CAAC,EAAE;IAAG;AAC9E;AAEO,SAASG,kBAAkBC,OAAa,EAAEC,QAAgB;IAC7D,MAAMC,SAASR,YAAYO;IAC3B,IAAI,CAACC,QACD,OAAOF;IAEX,MAAMG,qBAAqB,CAACH,QAAQ,iBAAiB;IACrD,MAAMI,UAAWF,AAAAA,CAAAA,OAAO,OAAO,GAAGC,kBAAiB,IAAlCD;IACjB,OAAO,IAAIG,KAAKL,QAAQ,OAAO,KAAKI;AACxC;AAEO,SAASE,kBAAkBC,IAAU,EAAEN,QAAgB;IAC1D,MAAMO,QAAQC,OAAOF,MAAM;IAC3B,MAAML,SAASR,YAAYO;IAC3B,IAAIC,QACA,OAAO,IAAIG,KAAK,GAAGG,QAAQP,UAAU,EAAE,WAAW;IAEtD,OAAOM,KAAK,WAAW;AAC3B;AAEO,SAASG,YAAYC,KAAgC;IACxD,IAAI,CAACA,OACD;IAEJ,MAAMC,IAAI,IAAIP,KAAKM;IACnB,IAAIb,OAAO,KAAK,CAACc,EAAE,OAAO,KACtB;IAEJ,OAAOA;AACX"}
@@ -8,6 +8,11 @@ interface DropdownMenuItemBaseProps {
8
8
  text?: React.ReactNode;
9
9
  disabled?: boolean;
10
10
  onClick?: React.MouseEventHandler;
11
+ /**
12
+ * Keep the menu open after selecting this item. Useful for items that toggle a value
13
+ * (e.g. a checkbox), where the user expects to make multiple selections in one session.
14
+ */
15
+ preventClose?: boolean;
11
16
  }
12
17
  type DropdownMenuItemButtonProps = (DropdownMenuItemBaseProps & React.HTMLAttributes<HTMLDivElement>) & {
13
18
  to?: never;
@@ -30,7 +30,7 @@ const variants = cva([
30
30
  readOnly: false
31
31
  }
32
32
  });
33
- const DropdownMenuItemBase = /*#__PURE__*/ __rspack_external_react.forwardRef(({ className, icon, text, readOnly, variant, disabled, onClick, children, ...linkProps }, ref)=>{
33
+ const DropdownMenuItemBase = /*#__PURE__*/ __rspack_external_react.forwardRef(({ className, icon, text, readOnly, variant, disabled, onClick, preventClose, children, ...linkProps }, ref)=>{
34
34
  const { linkComponent: LinkComponent } = useAdminUi();
35
35
  if (children) return /*#__PURE__*/ __rspack_external_react.createElement(DropdownMenuSubRoot, null, /*#__PURE__*/ __rspack_external_react.createElement(DropdownMenuSubTrigger, null, icon, /*#__PURE__*/ __rspack_external_react.createElement("span", null, text)), /*#__PURE__*/ __rspack_external_react.createElement(DropdownMenuPortal, null, /*#__PURE__*/ __rspack_external_react.createElement(DropdownMenuSubContent, null, children)));
36
36
  const sharedProps = {
@@ -51,7 +51,8 @@ const DropdownMenuItemBase = /*#__PURE__*/ __rspack_external_react.forwardRef(({
51
51
  className: cn(variants({
52
52
  readOnly,
53
53
  variant
54
- }), className)
54
+ }), className),
55
+ onSelect: preventClose ? (event)=>event.preventDefault() : void 0
55
56
  }, content);
56
57
  });
57
58
  DropdownMenuItemBase.displayName = DropdownMenu.Item.displayName;
@@ -1 +1 @@
1
- {"version":3,"file":"DropdownMenu/components/DropdownMenuItem.js","sources":["../../../src/DropdownMenu/components/DropdownMenuItem.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { DropdownMenu as DropdownMenuPrimitive } from \"radix-ui\";\nimport { cn, cva, makeDecoratable } from \"~/utils.js\";\nimport { DropdownMenuSubRoot } from \"./DropdownMenuSubRoot.js\";\nimport { DropdownMenuSubTrigger } from \"./DropdownMenuSubTrigger.js\";\nimport { DropdownMenuPortal } from \"./DropdownMenuPortal.js\";\nimport { DropdownMenuSubContent } from \"./DropdownMenuSubContent.js\";\nimport { DropdownMenuItemIcon, type DropdownMenuItemIconProps } from \"./DropdownMenuItemIcon.js\";\nimport { LinkComponentProps, useAdminUi } from \"~/index.js\";\n\ninterface DropdownMenuItemBaseProps {\n icon?: React.ReactNode;\n readOnly?: boolean;\n variant?: \"destructive\";\n text?: React.ReactNode;\n disabled?: boolean;\n onClick?: React.MouseEventHandler;\n}\n\ntype DropdownMenuItemButtonProps = (DropdownMenuItemBaseProps &\n React.HTMLAttributes<HTMLDivElement>) & { to?: never };\ntype DropdownMenuItemLinkProps = DropdownMenuItemBaseProps & LinkComponentProps;\n\ntype DropdownMenuItemProps = DropdownMenuItemButtonProps | DropdownMenuItemLinkProps;\n\nconst variants = cva(\n [\n \"group relative cursor-default select-none items-center rounded-sm\",\n \"text-md text-neutral-primary no-underline!\",\n \"px-xs-plus outline-none transition-colors\",\n \"[&_svg]:fill-neutral-xstrong [&_svg]:pointer-events-none [&_svg]:size-md [&_svg]:shrink-0\",\n \"data-disabled:pointer-events-none data-disabled:text-neutral-disabled\",\n \"[&_a]:no-underline! [&_a]:text-neutral-primary!\"\n ],\n {\n variants: {\n variant: {\n destructive: [\"text-destructive-primary!\", \"[&_svg]:fill-destructive\"]\n },\n readOnly: {\n true: \"pointer-events-none\"\n }\n },\n defaultVariants: {\n readOnly: false\n }\n }\n);\n\nconst DropdownMenuItemBase = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.Item>,\n DropdownMenuItemProps\n>(\n (\n { className, icon, text, readOnly, variant, disabled, onClick, children, ...linkProps },\n ref\n ) => {\n const { linkComponent: LinkComponent } = useAdminUi();\n\n if (children) {\n return (\n <DropdownMenuSubRoot>\n <DropdownMenuSubTrigger>\n {icon}\n <span>{text}</span>\n </DropdownMenuSubTrigger>\n <DropdownMenuPortal>\n <DropdownMenuSubContent>{children}</DropdownMenuSubContent>\n </DropdownMenuPortal>\n </DropdownMenuSubRoot>\n );\n }\n const sharedProps = {\n className: cn(\n \"flex px-sm py-xs-plus gap-sm-extra items-center text-md rounded-sm transition-colors group-focus:bg-neutral-dimmed\",\n {\n \"[&_svg]:fill-neutral-disabled!\": disabled\n }\n )\n };\n\n const content = linkProps.to ? (\n <LinkComponent {...sharedProps} {...linkProps}>\n {icon}\n <span>{text}</span>\n </LinkComponent>\n ) : (\n <div {...sharedProps} onClick={onClick}>\n {icon}\n <span>{text}</span>\n </div>\n );\n\n return (\n <DropdownMenuPrimitive.Item\n disabled={disabled}\n ref={ref}\n className={cn(variants({ readOnly, variant }), className)}\n >\n {content}\n </DropdownMenuPrimitive.Item>\n );\n }\n);\n\nDropdownMenuItemBase.displayName = DropdownMenuPrimitive.Item.displayName;\n\nconst DecoratableDropdownMenuItem = makeDecoratable(\"DropdownMenuItem\", DropdownMenuItemBase);\n\nconst DropdownMenuItem = Object.assign(DecoratableDropdownMenuItem, {\n Icon: DropdownMenuItemIcon\n});\n\nexport {\n DropdownMenuItem,\n type DropdownMenuItemProps,\n type DropdownMenuItemButtonProps,\n type DropdownMenuItemLinkProps,\n type DropdownMenuItemIconProps\n};\n"],"names":["variants","cva","DropdownMenuItemBase","React","className","icon","text","readOnly","variant","disabled","onClick","children","linkProps","ref","LinkComponent","useAdminUi","DropdownMenuSubRoot","DropdownMenuSubTrigger","DropdownMenuPortal","DropdownMenuSubContent","sharedProps","cn","content","DropdownMenuPrimitive","DecoratableDropdownMenuItem","makeDecoratable","DropdownMenuItem","Object","DropdownMenuItemIcon"],"mappings":";;;;;;;;;AAyBA,MAAMA,WAAWC,IACb;IACI;IACA;IACA;IACA;IACA;IACA;CACH,EACD;IACI,UAAU;QACN,SAAS;YACL,aAAa;gBAAC;gBAA6B;aAA2B;QAC1E;QACA,UAAU;YACN,MAAM;QACV;IACJ;IACA,iBAAiB;QACb,UAAU;IACd;AACJ;AAGJ,MAAMC,uBAAuB,WAAHA,GAAGC,wBAAAA,UAAgB,CAIzC,CACI,EAAEC,SAAS,EAAEC,IAAI,EAAEC,IAAI,EAAEC,QAAQ,EAAEC,OAAO,EAAEC,QAAQ,EAAEC,OAAO,EAAEC,QAAQ,EAAE,GAAGC,WAAW,EACvFC;IAEA,MAAM,EAAE,eAAeC,aAAa,EAAE,GAAGC;IAEzC,IAAIJ,UACA,OAAO,WAAP,GACI,sCAACK,qBAAmBA,MAAAA,WAAAA,GAChB,sCAACC,wBAAsBA,MAClBZ,MAAAA,WAAAA,GACD,sCAAC,cAAMC,QAAAA,WAAAA,GAEX,sCAACY,oBAAkBA,MAAAA,WAAAA,GACf,sCAACC,wBAAsBA,MAAER;IAKzC,MAAMS,cAAc;QAChB,WAAWC,GACP,sHACA;YACI,kCAAkCZ;QACtC;IAER;IAEA,MAAMa,UAAUV,UAAU,EAAE,GAAG,WAAH,GACxB,sCAACE,eAAAA;QAAe,GAAGM,WAAW;QAAG,GAAGR,SAAS;OACxCP,MAAAA,WAAAA,GACD,sCAAC,cAAMC,SAAAA,WAAAA,GAGX,sCAAC;QAAK,GAAGc,WAAW;QAAE,SAASV;OAC1BL,MAAAA,WAAAA,GACD,sCAAC,cAAMC;IAIf,OAAO,WAAP,GACI,sCAACiB,aAAAA,IAA0B;QACvB,UAAUd;QACV,KAAKI;QACL,WAAWQ,GAAGrB,SAAS;YAAEO;YAAUC;QAAQ,IAAIJ;OAE9CkB;AAGb;AAGJpB,qBAAqB,WAAW,GAAGqB,aAAAA,IAAAA,CAAAA,WAAsC;AAEzE,MAAMC,8BAA8BC,gBAAgB,oBAAoBvB;AAExE,MAAMwB,mBAAmBC,OAAO,MAAM,CAACH,6BAA6B;IAChE,MAAMI;AACV"}
1
+ {"version":3,"file":"DropdownMenu/components/DropdownMenuItem.js","sources":["../../../src/DropdownMenu/components/DropdownMenuItem.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { DropdownMenu as DropdownMenuPrimitive } from \"radix-ui\";\nimport { cn, cva, makeDecoratable } from \"~/utils.js\";\nimport { DropdownMenuSubRoot } from \"./DropdownMenuSubRoot.js\";\nimport { DropdownMenuSubTrigger } from \"./DropdownMenuSubTrigger.js\";\nimport { DropdownMenuPortal } from \"./DropdownMenuPortal.js\";\nimport { DropdownMenuSubContent } from \"./DropdownMenuSubContent.js\";\nimport { DropdownMenuItemIcon, type DropdownMenuItemIconProps } from \"./DropdownMenuItemIcon.js\";\nimport { LinkComponentProps, useAdminUi } from \"~/index.js\";\n\ninterface DropdownMenuItemBaseProps {\n icon?: React.ReactNode;\n readOnly?: boolean;\n variant?: \"destructive\";\n text?: React.ReactNode;\n disabled?: boolean;\n onClick?: React.MouseEventHandler;\n /**\n * Keep the menu open after selecting this item. Useful for items that toggle a value\n * (e.g. a checkbox), where the user expects to make multiple selections in one session.\n */\n preventClose?: boolean;\n}\n\ntype DropdownMenuItemButtonProps = (DropdownMenuItemBaseProps &\n React.HTMLAttributes<HTMLDivElement>) & { to?: never };\ntype DropdownMenuItemLinkProps = DropdownMenuItemBaseProps & LinkComponentProps;\n\ntype DropdownMenuItemProps = DropdownMenuItemButtonProps | DropdownMenuItemLinkProps;\n\nconst variants = cva(\n [\n \"group relative cursor-default select-none items-center rounded-sm\",\n \"text-md text-neutral-primary no-underline!\",\n \"px-xs-plus outline-none transition-colors\",\n \"[&_svg]:fill-neutral-xstrong [&_svg]:pointer-events-none [&_svg]:size-md [&_svg]:shrink-0\",\n \"data-disabled:pointer-events-none data-disabled:text-neutral-disabled\",\n \"[&_a]:no-underline! [&_a]:text-neutral-primary!\"\n ],\n {\n variants: {\n variant: {\n destructive: [\"text-destructive-primary!\", \"[&_svg]:fill-destructive\"]\n },\n readOnly: {\n true: \"pointer-events-none\"\n }\n },\n defaultVariants: {\n readOnly: false\n }\n }\n);\n\nconst DropdownMenuItemBase = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.Item>,\n DropdownMenuItemProps\n>(\n (\n {\n className,\n icon,\n text,\n readOnly,\n variant,\n disabled,\n onClick,\n preventClose,\n children,\n ...linkProps\n },\n ref\n ) => {\n const { linkComponent: LinkComponent } = useAdminUi();\n\n if (children) {\n return (\n <DropdownMenuSubRoot>\n <DropdownMenuSubTrigger>\n {icon}\n <span>{text}</span>\n </DropdownMenuSubTrigger>\n <DropdownMenuPortal>\n <DropdownMenuSubContent>{children}</DropdownMenuSubContent>\n </DropdownMenuPortal>\n </DropdownMenuSubRoot>\n );\n }\n const sharedProps = {\n className: cn(\n \"flex px-sm py-xs-plus gap-sm-extra items-center text-md rounded-sm transition-colors group-focus:bg-neutral-dimmed\",\n {\n \"[&_svg]:fill-neutral-disabled!\": disabled\n }\n )\n };\n\n const content = linkProps.to ? (\n <LinkComponent {...sharedProps} {...linkProps}>\n {icon}\n <span>{text}</span>\n </LinkComponent>\n ) : (\n <div {...sharedProps} onClick={onClick}>\n {icon}\n <span>{text}</span>\n </div>\n );\n\n return (\n <DropdownMenuPrimitive.Item\n disabled={disabled}\n ref={ref}\n className={cn(variants({ readOnly, variant }), className)}\n onSelect={preventClose ? event => event.preventDefault() : undefined}\n >\n {content}\n </DropdownMenuPrimitive.Item>\n );\n }\n);\n\nDropdownMenuItemBase.displayName = DropdownMenuPrimitive.Item.displayName;\n\nconst DecoratableDropdownMenuItem = makeDecoratable(\"DropdownMenuItem\", DropdownMenuItemBase);\n\nconst DropdownMenuItem = Object.assign(DecoratableDropdownMenuItem, {\n Icon: DropdownMenuItemIcon\n});\n\nexport {\n DropdownMenuItem,\n type DropdownMenuItemProps,\n type DropdownMenuItemButtonProps,\n type DropdownMenuItemLinkProps,\n type DropdownMenuItemIconProps\n};\n"],"names":["variants","cva","DropdownMenuItemBase","React","className","icon","text","readOnly","variant","disabled","onClick","preventClose","children","linkProps","ref","LinkComponent","useAdminUi","DropdownMenuSubRoot","DropdownMenuSubTrigger","DropdownMenuPortal","DropdownMenuSubContent","sharedProps","cn","content","DropdownMenuPrimitive","event","undefined","DecoratableDropdownMenuItem","makeDecoratable","DropdownMenuItem","Object","DropdownMenuItemIcon"],"mappings":";;;;;;;;;AA8BA,MAAMA,WAAWC,IACb;IACI;IACA;IACA;IACA;IACA;IACA;CACH,EACD;IACI,UAAU;QACN,SAAS;YACL,aAAa;gBAAC;gBAA6B;aAA2B;QAC1E;QACA,UAAU;YACN,MAAM;QACV;IACJ;IACA,iBAAiB;QACb,UAAU;IACd;AACJ;AAGJ,MAAMC,uBAAuB,WAAHA,GAAGC,wBAAAA,UAAgB,CAIzC,CACI,EACIC,SAAS,EACTC,IAAI,EACJC,IAAI,EACJC,QAAQ,EACRC,OAAO,EACPC,QAAQ,EACRC,OAAO,EACPC,YAAY,EACZC,QAAQ,EACR,GAAGC,WACN,EACDC;IAEA,MAAM,EAAE,eAAeC,aAAa,EAAE,GAAGC;IAEzC,IAAIJ,UACA,OAAO,WAAP,GACI,sCAACK,qBAAmBA,MAAAA,WAAAA,GAChB,sCAACC,wBAAsBA,MAClBb,MAAAA,WAAAA,GACD,sCAAC,cAAMC,QAAAA,WAAAA,GAEX,sCAACa,oBAAkBA,MAAAA,WAAAA,GACf,sCAACC,wBAAsBA,MAAER;IAKzC,MAAMS,cAAc;QAChB,WAAWC,GACP,sHACA;YACI,kCAAkCb;QACtC;IAER;IAEA,MAAMc,UAAUV,UAAU,EAAE,GAAG,WAAH,GACxB,sCAACE,eAAAA;QAAe,GAAGM,WAAW;QAAG,GAAGR,SAAS;OACxCR,MAAAA,WAAAA,GACD,sCAAC,cAAMC,SAAAA,WAAAA,GAGX,sCAAC;QAAK,GAAGe,WAAW;QAAE,SAASX;OAC1BL,MAAAA,WAAAA,GACD,sCAAC,cAAMC;IAIf,OAAO,WAAP,GACI,sCAACkB,aAAAA,IAA0B;QACvB,UAAUf;QACV,KAAKK;QACL,WAAWQ,GAAGtB,SAAS;YAAEO;YAAUC;QAAQ,IAAIJ;QAC/C,UAAUO,eAAec,CAAAA,QAASA,MAAM,cAAc,KAAKC;OAE1DH;AAGb;AAGJrB,qBAAqB,WAAW,GAAGsB,aAAAA,IAAAA,CAAAA,WAAsC;AAEzE,MAAMG,8BAA8BC,gBAAgB,oBAAoB1B;AAExE,MAAM2B,mBAAmBC,OAAO,MAAM,CAACH,6BAA6B;IAChE,MAAMI;AACV"}
@@ -11,7 +11,7 @@ const ItemActions = ({ disabled, onRemoveItem, onEditItem, onReplaceItem, small,
11
11
  return /*#__PURE__*/ react.createElement("div", {
12
12
  ...props,
13
13
  className: cn("flex justify-center items-center gap-xs", className)
14
- }, small && onReplaceItem && /*#__PURE__*/ react.createElement(IconButton, {
14
+ }, onReplaceItem && /*#__PURE__*/ react.createElement(IconButton, {
15
15
  icon: /*#__PURE__*/ react.createElement(Icon, {
16
16
  icon: /*#__PURE__*/ react.createElement(ReactComponent, null),
17
17
  label: "Replace",