@liiift-studio/mac-os9-ui 0.2.23 → 0.2.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -718,7 +718,45 @@ const Tabs = ({ children, defaultActiveTab = 0, activeTab: controlledActiveTab,
718
718
  };
719
719
  Tabs.displayName = 'Tabs';
720
720
 
721
- var styles$6 = {"window":"Window-module_window","window--active":"Window-module_window--active","window--inactive":"Window-module_window--inactive","titleBar":"Window-module_titleBar","titleCenter":"Window-module_titleCenter","controls":"Window-module_controls","controlButton":"Window-module_controlButton","closeBox":"Window-module_closeBox","minimizeBox":"Window-module_minimizeBox","maximizeBox":"Window-module_maximizeBox","titleText":"Window-module_titleText","content":"Window-module_content","resizeHandle":"Window-module_resizeHandle"};
721
+ // Utility for merging CSS class names
722
+ // Filters out falsy values and joins valid class names with spaces
723
+ /**
724
+ * Merges multiple class names into a single string
725
+ * Filters out undefined, null, false, and empty strings
726
+ *
727
+ * @param classes - Class names to merge
728
+ * @returns Merged class name string
729
+ *
730
+ * @example
731
+ * ```ts
732
+ * mergeClasses('base', isActive && 'active', undefined, 'custom')
733
+ * // Returns: "base active custom"
734
+ * ```
735
+ */
736
+ const mergeClasses = (...classes) => {
737
+ return classes.filter(Boolean).join(' ');
738
+ };
739
+ /**
740
+ * Creates a class name builder function with a base class
741
+ * Useful for component-level class management
742
+ *
743
+ * @param baseClass - Base class name
744
+ * @returns Function that merges additional classes with base
745
+ *
746
+ * @example
747
+ * ```ts
748
+ * const cn = createClassBuilder('button');
749
+ * cn('primary', isDisabled && 'disabled')
750
+ * // Returns: "button primary disabled"
751
+ * ```
752
+ */
753
+ const createClassBuilder = (baseClass) => {
754
+ return (...additionalClasses) => {
755
+ return mergeClasses(baseClass, ...additionalClasses);
756
+ };
757
+ };
758
+
759
+ var styles$6 = {"window":"Window-module_window","window--active":"Window-module_window--active","window--inactive":"Window-module_window--inactive","window--draggable":"Window-module_window--draggable","titleBar":"Window-module_titleBar","titleCenter":"Window-module_titleCenter","titleBar--draggable":"Window-module_titleBar--draggable","titleBar--dragging":"Window-module_titleBar--dragging","controls":"Window-module_controls","controlButton":"Window-module_controlButton","closeBox":"Window-module_closeBox","minimizeBox":"Window-module_minimizeBox","maximizeBox":"Window-module_maximizeBox","titleText":"Window-module_titleText","content":"Window-module_content","resizeHandle":"Window-module_resizeHandle"};
722
760
 
723
761
  /**
724
762
  * Mac OS 9 style Window component
@@ -731,6 +769,7 @@ var styles$6 = {"window":"Window-module_window","window--active":"Window-module_
731
769
  * - Active/inactive states
732
770
  * - Composable with custom TitleBar component
733
771
  * - Flexible sizing
772
+ * - Draggable windows (optional) - drag by title bar
734
773
  *
735
774
  * @example
736
775
  * ```tsx
@@ -752,18 +791,100 @@ var styles$6 = {"window":"Window-module_window","window--active":"Window-module_
752
791
  * >
753
792
  * <p>Content</p>
754
793
  * </Window>
794
+ *
795
+ * // Draggable window (uncontrolled)
796
+ * <Window title="Draggable" draggable>
797
+ * <p>Drag me by the title bar!</p>
798
+ * </Window>
799
+ *
800
+ * // Draggable window with initial position
801
+ * <Window
802
+ * title="Positioned"
803
+ * draggable
804
+ * defaultPosition={{ x: 100, y: 100 }}
805
+ * >
806
+ * <p>Starts at a specific position</p>
807
+ * </Window>
808
+ *
809
+ * // Controlled draggable window
810
+ * const [pos, setPos] = useState({ x: 0, y: 0 });
811
+ * <Window
812
+ * title="Controlled"
813
+ * draggable
814
+ * position={pos}
815
+ * onPositionChange={setPos}
816
+ * >
817
+ * <p>Parent controls position</p>
818
+ * </Window>
755
819
  * ```
756
820
  */
757
- const Window = React.forwardRef(({ children, title, titleBar, active = true, width = 'auto', height = 'auto', className = '', contentClassName = '', showControls = true, onClose, onMinimize, onMaximize, onMouseEnter, resizable = false, }, ref) => {
821
+ const Window = React.forwardRef(({ children, title, titleBar, active = true, width = 'auto', height = 'auto', className = '', contentClassName = '', classes, showControls = true, onClose, onMinimize, onMaximize, onMouseEnter, resizable = false, draggable = false, defaultPosition, position: controlledPosition, onPositionChange, }, ref) => {
822
+ // Drag state management
823
+ const [internalPosition, setInternalPosition] = React.useState(defaultPosition || null);
824
+ const [isDragging, setIsDragging] = React.useState(false);
825
+ const [hasBeenDragged, setHasBeenDragged] = React.useState(!!(defaultPosition || controlledPosition));
826
+ const dragStartRef = React.useRef(null);
827
+ // Use controlled position if provided, otherwise use internal state
828
+ const currentPosition = controlledPosition || internalPosition;
829
+ // Handle mouse down on title bar to start dragging
830
+ const handleTitleBarMouseDown = React.useCallback((event) => {
831
+ if (!draggable)
832
+ return;
833
+ // Don't start drag if clicking on buttons
834
+ if (event.target.closest('button')) {
835
+ return;
836
+ }
837
+ event.preventDefault();
838
+ const windowElement = event.currentTarget.closest(`.${styles$6.window}`);
839
+ if (!windowElement)
840
+ return;
841
+ const rect = windowElement.getBoundingClientRect();
842
+ // Store drag start info
843
+ dragStartRef.current = {
844
+ x: event.clientX - rect.left,
845
+ y: event.clientY - rect.top,
846
+ };
847
+ setIsDragging(true);
848
+ }, [draggable]);
849
+ // Handle mouse move during drag
850
+ React.useEffect(() => {
851
+ if (!isDragging || !dragStartRef.current)
852
+ return;
853
+ const handleMouseMove = (event) => {
854
+ event.preventDefault();
855
+ if (!dragStartRef.current)
856
+ return;
857
+ const newPosition = {
858
+ x: event.clientX - dragStartRef.current.x,
859
+ y: event.clientY - dragStartRef.current.y,
860
+ };
861
+ // Update position
862
+ if (controlledPosition && onPositionChange) {
863
+ onPositionChange(newPosition);
864
+ }
865
+ else {
866
+ setInternalPosition(newPosition);
867
+ }
868
+ // Mark as dragged
869
+ if (!hasBeenDragged) {
870
+ setHasBeenDragged(true);
871
+ }
872
+ };
873
+ const handleMouseUp = () => {
874
+ setIsDragging(false);
875
+ dragStartRef.current = null;
876
+ };
877
+ document.addEventListener('mousemove', handleMouseMove);
878
+ document.addEventListener('mouseup', handleMouseUp);
879
+ return () => {
880
+ document.removeEventListener('mousemove', handleMouseMove);
881
+ document.removeEventListener('mouseup', handleMouseUp);
882
+ };
883
+ }, [isDragging, controlledPosition, onPositionChange, hasBeenDragged]);
758
884
  // Class names
759
- const windowClassNames = [
760
- styles$6.window,
761
- active ? styles$6['window--active'] : styles$6['window--inactive'],
762
- className,
763
- ]
764
- .filter(Boolean)
765
- .join(' ');
766
- const contentClassNames = [styles$6.content, contentClassName].filter(Boolean).join(' ');
885
+ const windowClassNames = mergeClasses(styles$6.window, active ? styles$6['window--active'] : styles$6['window--inactive'], draggable && hasBeenDragged && styles$6['window--draggable'], className, classes?.root);
886
+ const contentClassNames = mergeClasses(styles$6.content, contentClassName, classes?.content);
887
+ const titleBarClassNames = mergeClasses(styles$6.titleBar, draggable && styles$6['titleBar--draggable'], isDragging && styles$6['titleBar--dragging'], classes?.titleBar);
767
888
  // Window style
768
889
  const windowStyle = {};
769
890
  if (width !== 'auto') {
@@ -772,13 +893,19 @@ const Window = React.forwardRef(({ children, title, titleBar, active = true, wid
772
893
  if (height !== 'auto') {
773
894
  windowStyle.height = typeof height === 'number' ? `${height}px` : height;
774
895
  }
896
+ // Apply position if draggable and has been dragged
897
+ if (draggable && hasBeenDragged && currentPosition) {
898
+ windowStyle.position = 'absolute';
899
+ windowStyle.left = `${currentPosition.x}px`;
900
+ windowStyle.top = `${currentPosition.y}px`;
901
+ }
775
902
  // Render title bar if title provided and no custom titleBar
776
903
  const renderTitleBar = () => {
777
904
  if (titleBar) {
778
905
  return titleBar;
779
906
  }
780
907
  if (title) {
781
- return (jsxRuntime.jsxs("div", { className: styles$6.titleBar, "data-numControls": [onClose, onMinimize, onMaximize].filter(Boolean).length, children: [showControls && (jsxRuntime.jsxs("div", { className: styles$6.controls, children: [onClose && (jsxRuntime.jsx("button", { type: "button", className: styles$6.controlButton, onClick: onClose, "aria-label": "Close", title: "Close", children: jsxRuntime.jsx("div", { className: styles$6.closeBox }) })), onMinimize && (jsxRuntime.jsx("button", { type: "button", className: styles$6.controlButton, onClick: onMinimize, "aria-label": "Minimize", title: "Minimize", children: jsxRuntime.jsx("div", { className: styles$6.minimizeBox }) })), onMaximize && (jsxRuntime.jsx("button", { type: "button", className: styles$6.controlButton, onClick: onMaximize, "aria-label": "Maximize", title: "Maximize", children: jsxRuntime.jsx("div", { className: styles$6.maximizeBox }) }))] })), jsxRuntime.jsxs("div", { className: styles$6.titleCenter, children: [jsxRuntime.jsxs("svg", { width: "132", height: "13", viewBox: "0 0 132 13", fill: "none", preserveAspectRatio: "none", xmlns: "http://www.w3.org/2000/svg", children: [jsxRuntime.jsx("rect", { width: "130.517", height: "13", fill: "#DDDDDD" }), jsxRuntime.jsx("rect", { width: "1", height: "13", fill: "#EEEEEE" }), jsxRuntime.jsx("rect", { x: "130", width: "1", height: "13", fill: "#C5C5C5" }), jsxRuntime.jsx("rect", { y: "1", width: "131.268", height: "1", fill: "#999999" }), jsxRuntime.jsx("rect", { y: "5", width: "131.268", height: "1", fill: "#999999" }), jsxRuntime.jsx("rect", { y: "9", width: "131.268", height: "1", fill: "#999999" }), jsxRuntime.jsx("rect", { y: "3", width: "131.268", height: "1", fill: "#999999" }), jsxRuntime.jsx("rect", { y: "7", width: "131.268", height: "1", fill: "#999999" }), jsxRuntime.jsx("rect", { y: "11", width: "131.268", height: "1", fill: "#999999" })] }), jsxRuntime.jsx("div", { className: `${styles$6.titleText} bold`, children: title }), jsxRuntime.jsxs("svg", { width: "132", height: "13", viewBox: "0 0 132 13", fill: "none", preserveAspectRatio: "none", xmlns: "http://www.w3.org/2000/svg", children: [jsxRuntime.jsx("rect", { width: "130.517", height: "13", fill: "#DDDDDD" }), jsxRuntime.jsx("rect", { width: "1", height: "13", fill: "#EEEEEE" }), jsxRuntime.jsx("rect", { x: "130", width: "1", height: "13", fill: "#C5C5C5" }), jsxRuntime.jsx("rect", { y: "1", width: "131.268", height: "1", fill: "#999999" }), jsxRuntime.jsx("rect", { y: "5", width: "131.268", height: "1", fill: "#999999" }), jsxRuntime.jsx("rect", { y: "9", width: "131.268", height: "1", fill: "#999999" }), jsxRuntime.jsx("rect", { y: "3", width: "131.268", height: "1", fill: "#999999" }), jsxRuntime.jsx("rect", { y: "7", width: "131.268", height: "1", fill: "#999999" }), jsxRuntime.jsx("rect", { y: "11", width: "131.268", height: "1", fill: "#999999" })] })] })] }));
908
+ return (jsxRuntime.jsxs("div", { className: titleBarClassNames, "data-numControls": [onClose, onMinimize, onMaximize].filter(Boolean).length, onMouseDown: handleTitleBarMouseDown, children: [showControls && (jsxRuntime.jsxs("div", { className: mergeClasses(styles$6.controls, classes?.controls), children: [onClose && (jsxRuntime.jsx("button", { type: "button", className: mergeClasses(styles$6.controlButton, classes?.controlButton), onClick: onClose, "aria-label": "Close", title: "Close", children: jsxRuntime.jsx("div", { className: styles$6.closeBox }) })), onMinimize && (jsxRuntime.jsx("button", { type: "button", className: mergeClasses(styles$6.controlButton, classes?.controlButton), onClick: onMinimize, "aria-label": "Minimize", title: "Minimize", children: jsxRuntime.jsx("div", { className: styles$6.minimizeBox }) })), onMaximize && (jsxRuntime.jsx("button", { type: "button", className: mergeClasses(styles$6.controlButton, classes?.controlButton), onClick: onMaximize, "aria-label": "Maximize", title: "Maximize", children: jsxRuntime.jsx("div", { className: styles$6.maximizeBox }) }))] })), jsxRuntime.jsxs("div", { className: styles$6.titleCenter, children: [jsxRuntime.jsxs("svg", { width: "132", height: "13", viewBox: "0 0 132 13", fill: "none", preserveAspectRatio: "none", xmlns: "http://www.w3.org/2000/svg", children: [jsxRuntime.jsx("rect", { width: "130.517", height: "13", fill: "#DDDDDD" }), jsxRuntime.jsx("rect", { width: "1", height: "13", fill: "#EEEEEE" }), jsxRuntime.jsx("rect", { x: "130", width: "1", height: "13", fill: "#C5C5C5" }), jsxRuntime.jsx("rect", { y: "1", width: "131.268", height: "1", fill: "#999999" }), jsxRuntime.jsx("rect", { y: "5", width: "131.268", height: "1", fill: "#999999" }), jsxRuntime.jsx("rect", { y: "9", width: "131.268", height: "1", fill: "#999999" }), jsxRuntime.jsx("rect", { y: "3", width: "131.268", height: "1", fill: "#999999" }), jsxRuntime.jsx("rect", { y: "7", width: "131.268", height: "1", fill: "#999999" }), jsxRuntime.jsx("rect", { y: "11", width: "131.268", height: "1", fill: "#999999" })] }), jsxRuntime.jsx("div", { className: mergeClasses(styles$6.titleText, classes?.titleText, 'bold'), children: title }), jsxRuntime.jsxs("svg", { width: "132", height: "13", viewBox: "0 0 132 13", fill: "none", preserveAspectRatio: "none", xmlns: "http://www.w3.org/2000/svg", children: [jsxRuntime.jsx("rect", { width: "130.517", height: "13", fill: "#DDDDDD" }), jsxRuntime.jsx("rect", { width: "1", height: "13", fill: "#EEEEEE" }), jsxRuntime.jsx("rect", { x: "130", width: "1", height: "13", fill: "#C5C5C5" }), jsxRuntime.jsx("rect", { y: "1", width: "131.268", height: "1", fill: "#999999" }), jsxRuntime.jsx("rect", { y: "5", width: "131.268", height: "1", fill: "#999999" }), jsxRuntime.jsx("rect", { y: "9", width: "131.268", height: "1", fill: "#999999" }), jsxRuntime.jsx("rect", { y: "3", width: "131.268", height: "1", fill: "#999999" }), jsxRuntime.jsx("rect", { y: "7", width: "131.268", height: "1", fill: "#999999" }), jsxRuntime.jsx("rect", { y: "11", width: "131.268", height: "1", fill: "#999999" })] })] })] }));
782
909
  }
783
910
  return null;
784
911
  };
@@ -1384,11 +1511,13 @@ var styles$1 = {"listView":"ListView-module_listView","header":"ListView-module_
1384
1511
  * />
1385
1512
  * ```
1386
1513
  */
1387
- const ListView = React.forwardRef(({ columns, items, selectedIds = [], onSelectionChange, onItemOpen, onItemMouseEnter, onSort, className = '', height = 'auto', }, ref) => {
1514
+ const ListView = React.forwardRef(({ columns, items, selectedIds = [], onSelectionChange, onItemOpen, onItemMouseEnter, onItemMouseLeave, onSort, className = '', height = 'auto', classes, renderRow, renderCell, renderHeaderCell, onCellClick, onCellMouseEnter, onCellMouseLeave, }, ref) => {
1388
1515
  const [sortColumn, setSortColumn] = React.useState(null);
1389
1516
  const [sortDirection, setSortDirection] = React.useState('asc');
1517
+ const [hoveredRow, setHoveredRow] = React.useState(null);
1518
+ const [hoveredCell, setHoveredCell] = React.useState(null);
1390
1519
  // Class names
1391
- const classNames = [styles$1.listView, className].filter(Boolean).join(' ');
1520
+ const classNames = mergeClasses(styles$1.listView, className, classes?.root);
1392
1521
  // Handle column header click
1393
1522
  const handleColumnClick = React.useCallback((columnKey, sortable = true) => {
1394
1523
  if (!sortable || !onSort)
@@ -1433,7 +1562,7 @@ const ListView = React.forwardRef(({ columns, items, selectedIds = [], onSelecti
1433
1562
  }
1434
1563
  }, [onItemOpen]);
1435
1564
  // Handle row mouse enter
1436
- const handleRowMouseEnter = React.useCallback((item) => {
1565
+ React.useCallback((item) => {
1437
1566
  if (onItemMouseEnter) {
1438
1567
  onItemMouseEnter(item);
1439
1568
  }
@@ -1443,17 +1572,108 @@ const ListView = React.forwardRef(({ columns, items, selectedIds = [], onSelecti
1443
1572
  if (height !== 'auto') {
1444
1573
  containerStyle.height = typeof height === 'number' ? `${height}px` : height;
1445
1574
  }
1446
- return (jsxRuntime.jsxs("div", { ref: ref, className: classNames, style: containerStyle, children: [jsxRuntime.jsx("div", { className: styles$1.header, children: columns.map((column) => (jsxRuntime.jsxs("div", { className: `${styles$1.headerCell} ${column.sortable !== false ? styles$1.sortable : ''}`, style: {
1447
- width: typeof column.width === 'number'
1448
- ? `${column.width}px`
1449
- : column.width,
1450
- }, onClick: () => handleColumnClick(column.key, column.sortable), children: [column.label, sortColumn === column.key && (jsxRuntime.jsx("span", { className: styles$1.sortIndicator, children: sortDirection === 'asc' ? '▲' : '▼' }))] }, column.key))) }), jsxRuntime.jsx("div", { className: styles$1.body, children: items.map((item) => {
1575
+ return (jsxRuntime.jsxs("div", { ref: ref, className: classNames, style: containerStyle, children: [jsxRuntime.jsx("div", { className: mergeClasses(styles$1.header, classes?.header), children: columns.map((column) => {
1576
+ const isSorted = sortColumn === column.key;
1577
+ const headerState = {
1578
+ isSorted,
1579
+ sortDirection: isSorted ? sortDirection : undefined,
1580
+ };
1581
+ const headerDefaultProps = {
1582
+ key: column.key,
1583
+ className: mergeClasses(styles$1.headerCell, column.sortable !== false && styles$1.sortable, classes?.headerCell),
1584
+ style: {
1585
+ width: typeof column.width === 'number'
1586
+ ? `${column.width}px`
1587
+ : column.width,
1588
+ },
1589
+ onClick: () => handleColumnClick(column.key, column.sortable),
1590
+ 'data-column': column.key,
1591
+ 'data-sortable': column.sortable !== false,
1592
+ ...(isSorted && {
1593
+ 'data-sorted': true,
1594
+ 'data-sort-direction': sortDirection,
1595
+ }),
1596
+ };
1597
+ // Use custom render or default
1598
+ if (renderHeaderCell) {
1599
+ return renderHeaderCell(column, headerState, headerDefaultProps);
1600
+ }
1601
+ // Default header cell rendering
1602
+ return (jsxRuntime.jsxs("div", { ...headerDefaultProps, children: [column.label, isSorted && (jsxRuntime.jsx("span", { className: styles$1.sortIndicator, children: sortDirection === 'asc' ? '▲' : '▼' }))] }));
1603
+ }) }), jsxRuntime.jsx("div", { className: mergeClasses(styles$1.body, classes?.body), children: items.map((item, rowIndex) => {
1451
1604
  const isSelected = selectedIds.includes(item.id);
1452
- return (jsxRuntime.jsx("div", { className: `${styles$1.row} ${isSelected ? styles$1.selected : ''}`, onClick: (e) => handleRowClick(item.id, e), onDoubleClick: () => handleRowDoubleClick(item), onMouseEnter: () => handleRowMouseEnter(item), children: columns.map((column, index) => (jsxRuntime.jsxs("div", { className: styles$1.cell, style: {
1453
- width: typeof column.width === 'number'
1454
- ? `${column.width}px`
1455
- : column.width,
1456
- }, children: [index === 0 && item.icon && (jsxRuntime.jsx("span", { className: styles$1.icon, children: item.icon })), item[column.key]] }, column.key))) }, item.id));
1605
+ const isHovered = hoveredRow === item.id;
1606
+ const rowState = {
1607
+ isSelected,
1608
+ isHovered,
1609
+ index: rowIndex,
1610
+ };
1611
+ const rowDefaultProps = {
1612
+ key: item.id,
1613
+ className: mergeClasses(styles$1.row, isSelected && styles$1.selected, classes?.row),
1614
+ onClick: (e) => handleRowClick(item.id, e),
1615
+ onDoubleClick: () => handleRowDoubleClick(item),
1616
+ onMouseEnter: () => {
1617
+ setHoveredRow(item.id);
1618
+ onItemMouseEnter?.(item);
1619
+ },
1620
+ onMouseLeave: () => {
1621
+ setHoveredRow(null);
1622
+ setHoveredCell(null);
1623
+ onItemMouseLeave?.(item);
1624
+ },
1625
+ 'data-selected': isSelected,
1626
+ 'data-index': rowIndex,
1627
+ 'data-item-id': item.id,
1628
+ };
1629
+ // Use custom row render or default
1630
+ if (renderRow) {
1631
+ return renderRow(item, rowState, rowDefaultProps);
1632
+ }
1633
+ // Default row rendering
1634
+ return (jsxRuntime.jsx("div", { ...rowDefaultProps, children: columns.map((column, columnIndex) => {
1635
+ const value = item[column.key];
1636
+ const isCellHovered = hoveredCell?.rowId === item.id &&
1637
+ hoveredCell?.columnKey === column.key;
1638
+ const cellState = {
1639
+ isHovered: isCellHovered,
1640
+ isRowSelected: isSelected,
1641
+ columnIndex,
1642
+ rowIndex,
1643
+ };
1644
+ // Cell event handlers
1645
+ const handleCellClick = (e) => {
1646
+ if (onCellClick) {
1647
+ onCellClick(item, column, e);
1648
+ }
1649
+ };
1650
+ const handleCellMouseEnter = () => {
1651
+ setHoveredCell({ rowId: item.id, columnKey: column.key });
1652
+ if (onCellMouseEnter) {
1653
+ onCellMouseEnter(item, column);
1654
+ }
1655
+ };
1656
+ const handleCellMouseLeave = () => {
1657
+ setHoveredCell(null);
1658
+ if (onCellMouseLeave) {
1659
+ onCellMouseLeave(item, column);
1660
+ }
1661
+ };
1662
+ // Use custom cell render or default
1663
+ if (renderCell) {
1664
+ return (jsxRuntime.jsx("div", { className: mergeClasses(styles$1.cell, classes?.cell), style: {
1665
+ width: typeof column.width === 'number'
1666
+ ? `${column.width}px`
1667
+ : column.width,
1668
+ }, "data-column": column.key, "data-hovered": isCellHovered, onClick: handleCellClick, onMouseEnter: handleCellMouseEnter, onMouseLeave: handleCellMouseLeave, children: renderCell(value, item, column, cellState) }, column.key));
1669
+ }
1670
+ // Default cell rendering
1671
+ return (jsxRuntime.jsxs("div", { className: mergeClasses(styles$1.cell, classes?.cell), style: {
1672
+ width: typeof column.width === 'number'
1673
+ ? `${column.width}px`
1674
+ : column.width,
1675
+ }, "data-column": column.key, "data-hovered": isCellHovered, onClick: handleCellClick, onMouseEnter: handleCellMouseEnter, onMouseLeave: handleCellMouseLeave, children: [columnIndex === 0 && item.icon && (jsxRuntime.jsx("span", { className: styles$1.icon, children: item.icon })), value] }, column.key));
1676
+ }) }));
1457
1677
  }) })] }));
1458
1678
  });
1459
1679
  ListView.displayName = 'ListView';
@@ -1470,6 +1690,7 @@ var styles = {"folderListContent":"FolderList-module_folderListContent","listVie
1470
1690
  *
1471
1691
  * @example
1472
1692
  * ```tsx
1693
+ * // Basic folder list
1473
1694
  * <FolderList
1474
1695
  * title="My Documents"
1475
1696
  * items={[
@@ -1479,8 +1700,14 @@ var styles = {"folderListContent":"FolderList-module_folderListContent","listVie
1479
1700
  * selectedIds={['1']}
1480
1701
  * onSelectionChange={(ids) => console.log('Selected:', ids)}
1481
1702
  * onItemOpen={(item) => console.log('Open:', item.name)}
1482
- * onItemMouseEnter={(item) => console.log('Hovering:', item.name)}
1483
- * onMouseEnter={(e) => console.log('Mouse entered folder list')}
1703
+ * />
1704
+ *
1705
+ * // Draggable folder list
1706
+ * <FolderList
1707
+ * title="My Documents"
1708
+ * items={items}
1709
+ * draggable
1710
+ * defaultPosition={{ x: 100, y: 100 }}
1484
1711
  * />
1485
1712
  * ```
1486
1713
  */
@@ -1488,9 +1715,18 @@ const FolderList = React.forwardRef(({ columns = [
1488
1715
  { key: 'name', label: 'Name', width: '40%' },
1489
1716
  { key: 'modified', label: 'Date Modified', width: '30%' },
1490
1717
  { key: 'size', label: 'Size', width: '30%' },
1491
- ], items, selectedIds, onSelectionChange, onItemOpen, onItemMouseEnter, onSort, onMouseEnter, listHeight = 400, ...windowProps }, ref) => {
1718
+ ], items, selectedIds, onSelectionChange, onItemOpen, onItemMouseEnter, onItemMouseLeave, onSort, onMouseEnter, listHeight = 400, classes, renderRow, renderCell, renderHeaderCell, onCellClick, onCellMouseEnter, onCellMouseLeave, ...windowProps }, ref) => {
1719
+ // Build ListView classes from FolderList classes
1720
+ const listViewClasses = classes ? {
1721
+ root: classes.listView,
1722
+ header: classes.header,
1723
+ headerCell: classes.headerCell,
1724
+ body: classes.body,
1725
+ row: classes.row,
1726
+ cell: classes.cell,
1727
+ } : undefined;
1492
1728
  // Window content with ListView
1493
- return (jsxRuntime.jsx(Window, { ref: ref, contentClassName: styles.folderListContent, onMouseEnter: onMouseEnter, ...windowProps, children: jsxRuntime.jsx(ListView, { columns: columns, items: items, selectedIds: selectedIds, onSelectionChange: onSelectionChange, onItemOpen: onItemOpen, onItemMouseEnter: onItemMouseEnter, onSort: onSort, height: listHeight, className: styles.listView }) }));
1729
+ return (jsxRuntime.jsx(Window, { ref: ref, contentClassName: styles.folderListContent, onMouseEnter: onMouseEnter, className: classes?.root, ...windowProps, children: jsxRuntime.jsx(ListView, { columns: columns, items: items, selectedIds: selectedIds, onSelectionChange: onSelectionChange, onItemOpen: onItemOpen, onItemMouseEnter: onItemMouseEnter, onItemMouseLeave: onItemMouseLeave, onSort: onSort, height: listHeight, className: styles.listView, classes: listViewClasses, renderRow: renderRow, renderCell: renderCell, renderHeaderCell: renderHeaderCell, onCellClick: onCellClick, onCellMouseEnter: onCellMouseEnter, onCellMouseLeave: onCellMouseLeave }) }));
1494
1730
  });
1495
1731
  FolderList.displayName = 'FolderList';
1496
1732
 
@@ -1733,6 +1969,8 @@ exports.TextField = TextField;
1733
1969
  exports.Window = Window;
1734
1970
  exports.borders = borders;
1735
1971
  exports.colors = colors;
1972
+ exports.createClassBuilder = createClassBuilder;
1973
+ exports.mergeClasses = mergeClasses;
1736
1974
  exports.shadows = shadows;
1737
1975
  exports.spacing = spacing;
1738
1976
  exports.tokens = tokens;