tc-dazzle-ui 1.7.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,17 +452,74 @@ 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) => {
459
- if (section.defaultExpanded !== false) {
460
- initialExpanded.add(section.id);
461
- }
462
+ initialExpanded.add(section.id);
462
463
  });
463
464
  return initialExpanded;
464
465
  });
465
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]);
466
523
  const toggleSection = (sectionId) => {
467
524
  setExpandedSections((prev) => {
468
525
  const newSet = new Set(prev);
@@ -494,16 +551,49 @@ const Sidebar = ({ sections, activeItemId, onItemClick, onSettingsClick, onExpan
494
551
  const classes = ['tc-sidebar'];
495
552
  if (className)
496
553
  classes.push(className);
554
+ if (isCollapsed)
555
+ classes.push('tc-sidebar--collapsed');
556
+ if (isResizing)
557
+ classes.push('tc-sidebar--resizing');
497
558
  return classes.join(' ');
498
559
  };
499
- 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) => {
500
569
  const isExpanded = expandedSections.has(section.id);
501
570
  const sectionActive = isSectionActive(section);
502
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) => {
503
572
  const itemActive = isItemActive(item.id);
504
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));
505
574
  }) }))] }, section.id));
506
- }) })] }));
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 }))] }));
507
597
  };
508
598
 
509
599
  var x = Object.defineProperty;
@@ -722,5 +812,5 @@ function registerWebComponents() {
722
812
  // Auto-register when loaded in browser
723
813
  registerWebComponents();
724
814
 
725
- 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 };
726
816
  //# sourceMappingURL=index.esm.js.map