tc-dazzle-ui 1.8.0 → 1.9.0

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.
@@ -17,6 +17,13 @@ export interface SidebarProps {
17
17
  onSettingsClick?: () => void;
18
18
  onExpandAllClick?: () => void;
19
19
  onCollapseAllClick?: () => void;
20
+ onCollapse?: () => void;
21
+ onExpand?: () => void;
22
+ onWidthChange?: (width: number) => void;
23
+ defaultWidth?: number;
24
+ minWidth?: number;
25
+ maxWidth?: number;
26
+ collapsible?: boolean;
20
27
  className?: string;
21
28
  }
22
29
  export declare const Sidebar: React.FC<SidebarProps>;
@@ -0,0 +1,16 @@
1
+ import React from 'react';
2
+ import './Layout.css';
3
+ export interface LayoutProps {
4
+ header?: React.ReactNode;
5
+ sidebar?: React.ReactNode;
6
+ main: React.ReactNode;
7
+ footer?: React.ReactNode;
8
+ actions?: React.ReactNode;
9
+ showSidebar?: boolean;
10
+ sidebarPosition?: 'left' | 'right';
11
+ sidebarWidth?: number | string;
12
+ maxContentWidth?: number | string;
13
+ className?: string;
14
+ }
15
+ export declare const Layout: React.FC<LayoutProps>;
16
+ export default Layout;
@@ -0,0 +1,2 @@
1
+ export { Layout } from './Layout';
2
+ export type { LayoutProps } from './Layout';
@@ -0,0 +1,2 @@
1
+ export { Layout } from './Layout';
2
+ export type { LayoutProps } from './Layout';
package/dist/index.esm.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
2
- import o, { forwardRef, useState, useRef, useEffect } from 'react';
2
+ import o, { forwardRef, useState, useRef, useEffect, useCallback } from 'react';
3
3
  import { createRoot } from 'react-dom/client';
4
4
 
5
5
  // Caret Down Icon SVG
@@ -452,7 +452,10 @@ const GlobalHeader = ({ tabs, activeTabId, onTabClick, onMenuClick, showMenuButt
452
452
  return (jsxs("header", { className: getHeaderClasses(), role: "navigation", children: [showMenuButton && (jsx(IconButton, { icon: jsx(MenuIcon, { size: "medium", color: "#ffffff" }), onClick: onMenuClick, ariaLabel: "Open menu", className: "tc-global-header__menu-button" })), jsx("nav", { className: "tc-global-header__tabs", role: "tablist", children: tabs.map((tab) => (jsx(Tab, { label: tab.label, isActive: activeTabId === tab.id, onClick: () => onTabClick === null || onTabClick === void 0 ? void 0 : onTabClick(tab) }, tab.id))) })] }));
453
453
  };
454
454
 
455
- const Sidebar = ({ sections, activeItemId, onItemClick, onSettingsClick, onExpandAllClick, onCollapseAllClick, className = '', }) => {
455
+ const MIN_WIDTH = 242;
456
+ const MAX_WIDTH = 1100;
457
+ const DEFAULT_WIDTH = 280;
458
+ const Sidebar = ({ sections, activeItemId, onItemClick, onSettingsClick, onExpandAllClick, onCollapseAllClick, onCollapse, onExpand, onWidthChange, defaultWidth = DEFAULT_WIDTH, minWidth = MIN_WIDTH, maxWidth = MAX_WIDTH, collapsible = true, className = '', }) => {
456
459
  const [expandedSections, setExpandedSections] = useState(() => {
457
460
  const initialExpanded = new Set();
458
461
  sections.forEach((section) => {
@@ -461,6 +464,62 @@ const Sidebar = ({ sections, activeItemId, onItemClick, onSettingsClick, onExpan
461
464
  return initialExpanded;
462
465
  });
463
466
  const [allExpanded, setAllExpanded] = useState(true);
467
+ const [sidebarWidth, setSidebarWidth] = useState(defaultWidth);
468
+ const [isCollapsed, setIsCollapsed] = useState(false);
469
+ const [isResizing, setIsResizing] = useState(false);
470
+ const sidebarRef = useRef(null);
471
+ const startXRef = useRef(0);
472
+ const startWidthRef = useRef(0);
473
+ const handleMouseDown = useCallback((e) => {
474
+ e.preventDefault();
475
+ setIsResizing(true);
476
+ startXRef.current = e.clientX;
477
+ startWidthRef.current = sidebarWidth;
478
+ }, [sidebarWidth]);
479
+ const handleMouseMove = useCallback((e) => {
480
+ if (!isResizing)
481
+ return;
482
+ const delta = e.clientX - startXRef.current;
483
+ let newWidth = startWidthRef.current + delta;
484
+ if (collapsible && newWidth < minWidth) {
485
+ setIsCollapsed(true);
486
+ setSidebarWidth(0);
487
+ onCollapse === null || onCollapse === void 0 ? void 0 : onCollapse();
488
+ onWidthChange === null || onWidthChange === void 0 ? void 0 : onWidthChange(0);
489
+ }
490
+ else {
491
+ if (isCollapsed && newWidth >= minWidth) {
492
+ setIsCollapsed(false);
493
+ onExpand === null || onExpand === void 0 ? void 0 : onExpand();
494
+ }
495
+ newWidth = Math.max(minWidth, Math.min(maxWidth, newWidth));
496
+ setSidebarWidth(newWidth);
497
+ onWidthChange === null || onWidthChange === void 0 ? void 0 : onWidthChange(newWidth);
498
+ }
499
+ }, [isResizing, minWidth, maxWidth, collapsible, isCollapsed, onCollapse, onExpand, onWidthChange]);
500
+ const handleMouseUp = useCallback(() => {
501
+ setIsResizing(false);
502
+ }, []);
503
+ useEffect(() => {
504
+ if (isResizing) {
505
+ document.addEventListener('mousemove', handleMouseMove);
506
+ document.addEventListener('mouseup', handleMouseUp);
507
+ document.body.style.cursor = 'col-resize';
508
+ document.body.style.userSelect = 'none';
509
+ }
510
+ return () => {
511
+ document.removeEventListener('mousemove', handleMouseMove);
512
+ document.removeEventListener('mouseup', handleMouseUp);
513
+ document.body.style.cursor = '';
514
+ document.body.style.userSelect = '';
515
+ };
516
+ }, [isResizing, handleMouseMove, handleMouseUp]);
517
+ const expandSidebar = useCallback(() => {
518
+ setIsCollapsed(false);
519
+ setSidebarWidth(defaultWidth);
520
+ onExpand === null || onExpand === void 0 ? void 0 : onExpand();
521
+ onWidthChange === null || onWidthChange === void 0 ? void 0 : onWidthChange(defaultWidth);
522
+ }, [defaultWidth, onExpand, onWidthChange]);
464
523
  const toggleSection = (sectionId) => {
465
524
  setExpandedSections((prev) => {
466
525
  const newSet = new Set(prev);
@@ -492,16 +551,49 @@ const Sidebar = ({ sections, activeItemId, onItemClick, onSettingsClick, onExpan
492
551
  const classes = ['tc-sidebar'];
493
552
  if (className)
494
553
  classes.push(className);
554
+ if (isCollapsed)
555
+ classes.push('tc-sidebar--collapsed');
556
+ if (isResizing)
557
+ classes.push('tc-sidebar--resizing');
495
558
  return classes.join(' ');
496
559
  };
497
- return (jsxs("aside", { className: getSidebarClasses(), children: [jsxs("div", { className: "tc-sidebar__header", children: [jsx(IconButton, { icon: jsx(SettingsIcon, { size: "medium" }), onClick: onSettingsClick, ariaLabel: "Settings", className: "tc-sidebar__settings-button" }), jsx("button", { type: "button", className: "tc-sidebar__toggle-button", onClick: allExpanded ? handleCollapseAll : handleExpandAll, children: allExpanded ? 'Collapse All' : 'Expand All' })] }), jsx("nav", { className: "tc-sidebar__nav", children: sections.map((section) => {
560
+ const sidebarStyle = {
561
+ width: isCollapsed ? 0 : sidebarWidth,
562
+ minWidth: isCollapsed ? 0 : minWidth,
563
+ maxWidth: maxWidth,
564
+ };
565
+ if (isCollapsed) {
566
+ return (jsx("aside", { ref: sidebarRef, className: getSidebarClasses(), style: { width: 0, minWidth: 0 }, children: jsx("div", { className: "tc-sidebar__resize-handle tc-sidebar__resize-handle--collapsed", onClick: expandSidebar, title: "Expand sidebar", children: jsx(ChevronDownIcon, { size: "small" }) }) }));
567
+ }
568
+ return (jsxs("aside", { ref: sidebarRef, className: getSidebarClasses(), style: sidebarStyle, children: [jsxs("div", { className: "tc-sidebar__header", children: [jsx(IconButton, { icon: jsx(SettingsIcon, { size: "medium" }), onClick: onSettingsClick, ariaLabel: "Settings", className: "tc-sidebar__settings-button" }), jsx("button", { type: "button", className: "tc-sidebar__toggle-button", onClick: allExpanded ? handleCollapseAll : handleExpandAll, children: allExpanded ? 'Collapse All' : 'Expand All' })] }), jsx("nav", { className: "tc-sidebar__nav", children: sections.map((section) => {
498
569
  const isExpanded = expandedSections.has(section.id);
499
570
  const sectionActive = isSectionActive(section);
500
571
  return (jsxs("div", { className: "tc-sidebar__section", children: [jsxs("button", { type: "button", className: `tc-sidebar__section-header ${sectionActive ? 'tc-sidebar__section-header--active' : ''}`, onClick: () => toggleSection(section.id), "aria-expanded": isExpanded, children: [jsx("span", { className: "tc-sidebar__section-arrow", children: isExpanded ? (jsx(ChevronDownIcon, { size: "small" })) : (jsx(ChevronUpIcon, { size: "small" })) }), jsx("span", { className: "tc-sidebar__section-title", children: section.title })] }), isExpanded && (jsx("ul", { className: "tc-sidebar__items", children: section.items.map((item) => {
501
572
  const itemActive = isItemActive(item.id);
502
573
  return (jsx("li", { children: jsx("button", { type: "button", className: `tc-sidebar__item ${itemActive ? 'tc-sidebar__item--active' : ''}`, onClick: () => onItemClick === null || onItemClick === void 0 ? void 0 : onItemClick(item, section), children: item.label }) }, item.id));
503
574
  }) }))] }, section.id));
504
- }) })] }));
575
+ }) }), jsx("div", { className: "tc-sidebar__resize-handle", onMouseDown: handleMouseDown, title: "Drag to resize" })] }));
576
+ };
577
+
578
+ const Layout = ({ header, sidebar, main, footer, actions, showSidebar = true, sidebarPosition = 'left', sidebarWidth = 280, maxContentWidth = '100%', className = '', }) => {
579
+ const getLayoutClasses = () => {
580
+ const classes = ['tc-layout'];
581
+ if (className)
582
+ classes.push(className);
583
+ if (!showSidebar || !sidebar)
584
+ classes.push('tc-layout--no-sidebar');
585
+ if (sidebarPosition === 'right')
586
+ classes.push('tc-layout--sidebar-right');
587
+ return classes.join(' ');
588
+ };
589
+ const sidebarStyle = {
590
+ width: typeof sidebarWidth === 'number' ? `${sidebarWidth}px` : sidebarWidth,
591
+ minWidth: typeof sidebarWidth === 'number' ? `${sidebarWidth}px` : sidebarWidth,
592
+ };
593
+ const mainContentStyle = {
594
+ maxWidth: typeof maxContentWidth === 'number' ? `${maxContentWidth}px` : maxContentWidth,
595
+ };
596
+ return (jsxs("div", { className: getLayoutClasses(), children: [header && (jsx("header", { className: "tc-layout__header", children: header })), jsxs("div", { className: "tc-layout__body", children: [sidebar && showSidebar && (jsx("aside", { className: "tc-layout__sidebar", style: sidebarStyle, children: jsx("div", { className: "tc-layout__sidebar-content", children: sidebar }) })), jsx("div", { className: "tc-layout__main-wrapper", children: jsxs("main", { className: "tc-layout__main", style: mainContentStyle, children: [actions && (jsx("div", { className: "tc-layout__actions", children: actions })), jsx("div", { className: "tc-layout__content", children: main })] }) })] }), footer && (jsx("footer", { className: "tc-layout__footer", children: footer }))] }));
505
597
  };
506
598
 
507
599
  var x = Object.defineProperty;
@@ -720,5 +812,5 @@ function registerWebComponents() {
720
812
  // Auto-register when loaded in browser
721
813
  registerWebComponents();
722
814
 
723
- export { Button, ButtonGroup, CaretDownIcon, ChevronDownIcon, ChevronUpIcon, DropdownMenu, FilterDropdown, GlobalHeader, GlobalSearch, HeaderMenu, IconButton, InfoIcon, Input, Logo, MainHeader, SearchIcon, Sidebar, TCButton, TCButtonGroup, TCInput, Tab, defaultIcons, registerWebComponents };
815
+ export { Button, ButtonGroup, CaretDownIcon, ChevronDownIcon, ChevronUpIcon, DropdownMenu, FilterDropdown, GlobalHeader, GlobalSearch, HeaderMenu, IconButton, InfoIcon, Input, Layout, Logo, MainHeader, SearchIcon, Sidebar, TCButton, TCButtonGroup, TCInput, Tab, defaultIcons, registerWebComponents };
724
816
  //# sourceMappingURL=index.esm.js.map