twico-ui 1.0.2 → 1.1.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.
package/dist/index.d.cts CHANGED
@@ -1900,6 +1900,24 @@ interface TreeViewProps extends React.HTMLAttributes<HTMLDivElement> {
1900
1900
 
1901
1901
  declare function TreeView(props: TreeViewProps): React.JSX.Element;
1902
1902
 
1903
+ interface AppShellProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "children"> {
1904
+ /** The sidebar element (e.g. a `<Sidebar/>`), rendered full-height on the inline-start side. */
1905
+ sidebar?: React.ReactNode;
1906
+ /**
1907
+ * Topbar content, rendered in a fixed header above the scrollable content. The header is a flex
1908
+ * row with `space-between`, so pass two groups (left/right) and they spread to the edges.
1909
+ */
1910
+ header?: React.ReactNode;
1911
+ /** Main content — fills the remaining space and scrolls independently of the sidebar/header. */
1912
+ children?: React.ReactNode;
1913
+ /** Overall shell height (CSS length). Use a fixed value to embed the shell in a smaller region. @default "100dvh" */
1914
+ height?: string | number;
1915
+ /** Pad the scrollable content region. @default true */
1916
+ padded?: boolean;
1917
+ }
1918
+
1919
+ declare function AppShell(props: AppShellProps): React.JSX.Element;
1920
+
1903
1921
  /** Generic, token-styled element — the building block for non-flex layout. */
1904
1922
  interface BoxProps extends React.HTMLAttributes<HTMLElement> {
1905
1923
  /** Element/tag to render. @default "div" */
@@ -2186,4 +2204,4 @@ declare function useScrollLock(locked?: boolean): void;
2186
2204
  /** A stable, SSR-safe unique id (optionally prefixed). */
2187
2205
  declare function useId(prefix?: string): string;
2188
2206
 
2189
- export { Accordion, type AccordionItem, type AccordionProps, Alert, type AlertProps, Avatar, AvatarMenu, type AvatarMenuProps, type AvatarProps, Badge, type BadgeProps, Box, type BoxProps, Breadcrumb, type BreadcrumbItem, type BreadcrumbProps, Button, type ButtonProps, Card, type CardProps, Carousel, type CarouselProps, Chart, type ChartDatum, type ChartProps, Checkbox, type CheckboxProps, Code, type CodeProps, ColorPicker, type ColorPickerProps, Combobox, type ComboboxGroup, type ComboboxOption, type ComboboxProps, type Command, CommandPalette, type CommandPaletteProps, Container, type ContainerProps, Currency, CurrencyField, type CurrencyFieldProps, type CurrencyOption, type CurrencyProps, Datatable, type DatatableBatchAction, type DatatableColumn, type DatatableProps, type DatatableQuery, type DatatableRowAction, DatePicker, type DatePickerProps, type DateRange, DateRangePicker, type DateRangePickerProps, Dialog, type DialogProps, Divider, type DividerProps, Drawer, type DrawerProps, EmptyState, type EmptyStateProps, Field, type FieldProps, FileUpload, type FileUploadProps, Grid, type GridProps, Heading, type HeadingProps, IconButton, type IconButtonProps, Input, type InputProps, Kanban, type KanbanCard, type KanbanColumn, type KanbanProps, List, type ListItemData, type ListProps, Menu, type MenuItemDef, type MenuProps, MultiSelect, type MultiSelectGroup, type MultiSelectOption, type MultiSelectProps, Navbar, type NavbarLink, type NavbarProps, Pagination, type PaginationProps, Popover, type PopoverProps, Progress, type ProgressProps, Radio, type RadioProps, Rating, type RatingProps, Select, type SelectGroup, type SelectOption, type SelectProps, Sidebar, type SidebarItem, type SidebarProps, Skeleton, type SkeletonProps, Slider, type SliderProps, Spinner, type SpinnerProps, Stack, type StackProps, Stat, type StatProps, type Step, Stepper, type StepperProps, Switch, type SwitchProps, type TabItem, Table, type TableColumn, type TableProps, Tabs, type TabsProps, Tag, type TagProps, Text, type TextProps, Textarea, type TextareaProps, Timeline, type TimelineItem, type TimelineProps, Toast, type ToastApi, type ToastOptions, type ToastProps, ToastProvider, type ToastProviderProps, ToastViewport, type ToastViewportProps, Tooltip, type TooltipProps, type TreeNode, TreeView, type TreeViewProps, type UseColorSchemeOptions, type UseKeyPressOptions, runDatatableQuery, useClickOutside, useColorScheme, useControllableState, useCopyToClipboard, useDebouncedCallback, useDebouncedValue, useDisclosure, useEventListener, useHover, useId, useIntersectionObserver, useInterval, useIsomorphicLayoutEffect, useKeyPress, useLocalStorage, useMediaQuery, useMounted, usePrefersReducedMotion, usePrevious, useScrollLock, useTimeout, useToast, useToggle, useWindowSize };
2207
+ export { Accordion, type AccordionItem, type AccordionProps, Alert, type AlertProps, AppShell, type AppShellProps, Avatar, AvatarMenu, type AvatarMenuProps, type AvatarProps, Badge, type BadgeProps, Box, type BoxProps, Breadcrumb, type BreadcrumbItem, type BreadcrumbProps, Button, type ButtonProps, Card, type CardProps, Carousel, type CarouselProps, Chart, type ChartDatum, type ChartProps, Checkbox, type CheckboxProps, Code, type CodeProps, ColorPicker, type ColorPickerProps, Combobox, type ComboboxGroup, type ComboboxOption, type ComboboxProps, type Command, CommandPalette, type CommandPaletteProps, Container, type ContainerProps, Currency, CurrencyField, type CurrencyFieldProps, type CurrencyOption, type CurrencyProps, Datatable, type DatatableBatchAction, type DatatableColumn, type DatatableProps, type DatatableQuery, type DatatableRowAction, DatePicker, type DatePickerProps, type DateRange, DateRangePicker, type DateRangePickerProps, Dialog, type DialogProps, Divider, type DividerProps, Drawer, type DrawerProps, EmptyState, type EmptyStateProps, Field, type FieldProps, FileUpload, type FileUploadProps, Grid, type GridProps, Heading, type HeadingProps, IconButton, type IconButtonProps, Input, type InputProps, Kanban, type KanbanCard, type KanbanColumn, type KanbanProps, List, type ListItemData, type ListProps, Menu, type MenuItemDef, type MenuProps, MultiSelect, type MultiSelectGroup, type MultiSelectOption, type MultiSelectProps, Navbar, type NavbarLink, type NavbarProps, Pagination, type PaginationProps, Popover, type PopoverProps, Progress, type ProgressProps, Radio, type RadioProps, Rating, type RatingProps, Select, type SelectGroup, type SelectOption, type SelectProps, Sidebar, type SidebarItem, type SidebarProps, Skeleton, type SkeletonProps, Slider, type SliderProps, Spinner, type SpinnerProps, Stack, type StackProps, Stat, type StatProps, type Step, Stepper, type StepperProps, Switch, type SwitchProps, type TabItem, Table, type TableColumn, type TableProps, Tabs, type TabsProps, Tag, type TagProps, Text, type TextProps, Textarea, type TextareaProps, Timeline, type TimelineItem, type TimelineProps, Toast, type ToastApi, type ToastOptions, type ToastProps, ToastProvider, type ToastProviderProps, ToastViewport, type ToastViewportProps, Tooltip, type TooltipProps, type TreeNode, TreeView, type TreeViewProps, type UseColorSchemeOptions, type UseKeyPressOptions, runDatatableQuery, useClickOutside, useColorScheme, useControllableState, useCopyToClipboard, useDebouncedCallback, useDebouncedValue, useDisclosure, useEventListener, useHover, useId, useIntersectionObserver, useInterval, useIsomorphicLayoutEffect, useKeyPress, useLocalStorage, useMediaQuery, useMounted, usePrefersReducedMotion, usePrevious, useScrollLock, useTimeout, useToast, useToggle, useWindowSize };
package/dist/index.d.ts CHANGED
@@ -1900,6 +1900,24 @@ interface TreeViewProps extends React.HTMLAttributes<HTMLDivElement> {
1900
1900
 
1901
1901
  declare function TreeView(props: TreeViewProps): React.JSX.Element;
1902
1902
 
1903
+ interface AppShellProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "children"> {
1904
+ /** The sidebar element (e.g. a `<Sidebar/>`), rendered full-height on the inline-start side. */
1905
+ sidebar?: React.ReactNode;
1906
+ /**
1907
+ * Topbar content, rendered in a fixed header above the scrollable content. The header is a flex
1908
+ * row with `space-between`, so pass two groups (left/right) and they spread to the edges.
1909
+ */
1910
+ header?: React.ReactNode;
1911
+ /** Main content — fills the remaining space and scrolls independently of the sidebar/header. */
1912
+ children?: React.ReactNode;
1913
+ /** Overall shell height (CSS length). Use a fixed value to embed the shell in a smaller region. @default "100dvh" */
1914
+ height?: string | number;
1915
+ /** Pad the scrollable content region. @default true */
1916
+ padded?: boolean;
1917
+ }
1918
+
1919
+ declare function AppShell(props: AppShellProps): React.JSX.Element;
1920
+
1903
1921
  /** Generic, token-styled element — the building block for non-flex layout. */
1904
1922
  interface BoxProps extends React.HTMLAttributes<HTMLElement> {
1905
1923
  /** Element/tag to render. @default "div" */
@@ -2186,4 +2204,4 @@ declare function useScrollLock(locked?: boolean): void;
2186
2204
  /** A stable, SSR-safe unique id (optionally prefixed). */
2187
2205
  declare function useId(prefix?: string): string;
2188
2206
 
2189
- export { Accordion, type AccordionItem, type AccordionProps, Alert, type AlertProps, Avatar, AvatarMenu, type AvatarMenuProps, type AvatarProps, Badge, type BadgeProps, Box, type BoxProps, Breadcrumb, type BreadcrumbItem, type BreadcrumbProps, Button, type ButtonProps, Card, type CardProps, Carousel, type CarouselProps, Chart, type ChartDatum, type ChartProps, Checkbox, type CheckboxProps, Code, type CodeProps, ColorPicker, type ColorPickerProps, Combobox, type ComboboxGroup, type ComboboxOption, type ComboboxProps, type Command, CommandPalette, type CommandPaletteProps, Container, type ContainerProps, Currency, CurrencyField, type CurrencyFieldProps, type CurrencyOption, type CurrencyProps, Datatable, type DatatableBatchAction, type DatatableColumn, type DatatableProps, type DatatableQuery, type DatatableRowAction, DatePicker, type DatePickerProps, type DateRange, DateRangePicker, type DateRangePickerProps, Dialog, type DialogProps, Divider, type DividerProps, Drawer, type DrawerProps, EmptyState, type EmptyStateProps, Field, type FieldProps, FileUpload, type FileUploadProps, Grid, type GridProps, Heading, type HeadingProps, IconButton, type IconButtonProps, Input, type InputProps, Kanban, type KanbanCard, type KanbanColumn, type KanbanProps, List, type ListItemData, type ListProps, Menu, type MenuItemDef, type MenuProps, MultiSelect, type MultiSelectGroup, type MultiSelectOption, type MultiSelectProps, Navbar, type NavbarLink, type NavbarProps, Pagination, type PaginationProps, Popover, type PopoverProps, Progress, type ProgressProps, Radio, type RadioProps, Rating, type RatingProps, Select, type SelectGroup, type SelectOption, type SelectProps, Sidebar, type SidebarItem, type SidebarProps, Skeleton, type SkeletonProps, Slider, type SliderProps, Spinner, type SpinnerProps, Stack, type StackProps, Stat, type StatProps, type Step, Stepper, type StepperProps, Switch, type SwitchProps, type TabItem, Table, type TableColumn, type TableProps, Tabs, type TabsProps, Tag, type TagProps, Text, type TextProps, Textarea, type TextareaProps, Timeline, type TimelineItem, type TimelineProps, Toast, type ToastApi, type ToastOptions, type ToastProps, ToastProvider, type ToastProviderProps, ToastViewport, type ToastViewportProps, Tooltip, type TooltipProps, type TreeNode, TreeView, type TreeViewProps, type UseColorSchemeOptions, type UseKeyPressOptions, runDatatableQuery, useClickOutside, useColorScheme, useControllableState, useCopyToClipboard, useDebouncedCallback, useDebouncedValue, useDisclosure, useEventListener, useHover, useId, useIntersectionObserver, useInterval, useIsomorphicLayoutEffect, useKeyPress, useLocalStorage, useMediaQuery, useMounted, usePrefersReducedMotion, usePrevious, useScrollLock, useTimeout, useToast, useToggle, useWindowSize };
2207
+ export { Accordion, type AccordionItem, type AccordionProps, Alert, type AlertProps, AppShell, type AppShellProps, Avatar, AvatarMenu, type AvatarMenuProps, type AvatarProps, Badge, type BadgeProps, Box, type BoxProps, Breadcrumb, type BreadcrumbItem, type BreadcrumbProps, Button, type ButtonProps, Card, type CardProps, Carousel, type CarouselProps, Chart, type ChartDatum, type ChartProps, Checkbox, type CheckboxProps, Code, type CodeProps, ColorPicker, type ColorPickerProps, Combobox, type ComboboxGroup, type ComboboxOption, type ComboboxProps, type Command, CommandPalette, type CommandPaletteProps, Container, type ContainerProps, Currency, CurrencyField, type CurrencyFieldProps, type CurrencyOption, type CurrencyProps, Datatable, type DatatableBatchAction, type DatatableColumn, type DatatableProps, type DatatableQuery, type DatatableRowAction, DatePicker, type DatePickerProps, type DateRange, DateRangePicker, type DateRangePickerProps, Dialog, type DialogProps, Divider, type DividerProps, Drawer, type DrawerProps, EmptyState, type EmptyStateProps, Field, type FieldProps, FileUpload, type FileUploadProps, Grid, type GridProps, Heading, type HeadingProps, IconButton, type IconButtonProps, Input, type InputProps, Kanban, type KanbanCard, type KanbanColumn, type KanbanProps, List, type ListItemData, type ListProps, Menu, type MenuItemDef, type MenuProps, MultiSelect, type MultiSelectGroup, type MultiSelectOption, type MultiSelectProps, Navbar, type NavbarLink, type NavbarProps, Pagination, type PaginationProps, Popover, type PopoverProps, Progress, type ProgressProps, Radio, type RadioProps, Rating, type RatingProps, Select, type SelectGroup, type SelectOption, type SelectProps, Sidebar, type SidebarItem, type SidebarProps, Skeleton, type SkeletonProps, Slider, type SliderProps, Spinner, type SpinnerProps, Stack, type StackProps, Stat, type StatProps, type Step, Stepper, type StepperProps, Switch, type SwitchProps, type TabItem, Table, type TableColumn, type TableProps, Tabs, type TabsProps, Tag, type TagProps, Text, type TextProps, Textarea, type TextareaProps, Timeline, type TimelineItem, type TimelineProps, Toast, type ToastApi, type ToastOptions, type ToastProps, ToastProvider, type ToastProviderProps, ToastViewport, type ToastViewportProps, Tooltip, type TooltipProps, type TreeNode, TreeView, type TreeViewProps, type UseColorSchemeOptions, type UseKeyPressOptions, runDatatableQuery, useClickOutside, useColorScheme, useControllableState, useCopyToClipboard, useDebouncedCallback, useDebouncedValue, useDisclosure, useEventListener, useHover, useId, useIntersectionObserver, useInterval, useIsomorphicLayoutEffect, useKeyPress, useLocalStorage, useMediaQuery, useMounted, usePrefersReducedMotion, usePrevious, useScrollLock, useTimeout, useToast, useToggle, useWindowSize };
package/dist/index.mjs CHANGED
@@ -8670,6 +8670,135 @@ function Rating({
8670
8670
  }
8671
8671
  );
8672
8672
  }
8673
+ var TOOLTIP_CSS = `
8674
+ .twc-tooltip-wrap { display: inline-flex; }
8675
+ .twc-tooltip {
8676
+ position: fixed; z-index: var(--z-tooltip); pointer-events: none;
8677
+ padding: 6px 10px; border-radius: var(--radius-md);
8678
+ background: var(--color-text); color: var(--color-surface);
8679
+ font-family: var(--font-sans); font-size: var(--text-xs); font-weight: var(--font-medium);
8680
+ line-height: 1.3; white-space: nowrap; box-shadow: var(--shadow-md);
8681
+ opacity: 0; transform: scale(0.9); transition: opacity var(--duration-fast) var(--ease-out), transform var(--duration-fast) var(--ease-spring);
8682
+ }
8683
+ .twc-tooltip[data-show="true"] { opacity: 1; transform: scale(1); }
8684
+ .twc-tooltip[data-place="top"] { transform-origin: bottom center; translate: -50% 0; }
8685
+ .twc-tooltip[data-place="bottom"] { transform-origin: top center; translate: -50% 0; }
8686
+ .twc-tooltip[data-place="left"] { transform-origin: right center; translate: 0 -50%; }
8687
+ .twc-tooltip[data-place="right"] { transform-origin: left center; translate: 0 -50%; }
8688
+ .twc-tooltip[data-show="true"][data-place="top"], .twc-tooltip[data-show="true"][data-place="bottom"] { transform: scale(1); }
8689
+ .twc-tooltip__arrow { position: absolute; width: 7px; height: 7px; background: var(--color-text); transform: rotate(45deg); }
8690
+ .twc-tooltip[data-place="top"] .twc-tooltip__arrow { bottom: -3px; left: 50%; margin-left: -3.5px; }
8691
+ .twc-tooltip[data-place="bottom"] .twc-tooltip__arrow { top: -3px; left: 50%; margin-left: -3.5px; }
8692
+ .twc-tooltip[data-place="left"] .twc-tooltip__arrow { right: -3px; top: 50%; margin-top: -3.5px; }
8693
+ .twc-tooltip[data-place="right"] .twc-tooltip__arrow { left: -3px; top: 50%; margin-top: -3.5px; }
8694
+ @media (prefers-reduced-motion: reduce) { .twc-tooltip { transition: opacity var(--duration-fast) linear; transform: none; } }
8695
+ `;
8696
+ function Tooltip({
8697
+ children,
8698
+ label,
8699
+ placement = "top",
8700
+ delay = 120,
8701
+ className = "",
8702
+ ...rest
8703
+ }) {
8704
+ const __twcStyles = useScopedStyles("twc-tooltip-styles", TOOLTIP_CSS);
8705
+ const id = React23__default.useId();
8706
+ const [show, setShow] = React23__default.useState(false);
8707
+ const [coords, setCoords] = React23__default.useState(null);
8708
+ const timer = React23__default.useRef(null);
8709
+ const wrapRef = React23__default.useRef(null);
8710
+ const tipRef = React23__default.useRef(null);
8711
+ const open = () => {
8712
+ clearTimeout(timer.current);
8713
+ timer.current = setTimeout(() => setShow(true), delay);
8714
+ };
8715
+ const close = () => {
8716
+ clearTimeout(timer.current);
8717
+ setShow(false);
8718
+ };
8719
+ React23__default.useEffect(() => () => clearTimeout(timer.current), []);
8720
+ const place = React23__default.useCallback(() => {
8721
+ const el = wrapRef.current;
8722
+ if (!el) return;
8723
+ const r = el.getBoundingClientRect();
8724
+ const cx = Math.round(r.left + r.width / 2), cy = Math.round(r.top + r.height / 2);
8725
+ const vw = window.innerWidth, vh = window.innerHeight, gap = 8, margin = 8;
8726
+ const tip = tipRef.current;
8727
+ const tw = tip ? tip.offsetWidth : 0, th = tip ? tip.offsetHeight : 0;
8728
+ const clampX = (c) => tw ? Math.round(Math.min(Math.max(c, margin + tw / 2), vw - margin - tw / 2)) : c;
8729
+ const clampY = (c) => th ? Math.round(Math.min(Math.max(c, margin + th / 2), vh - margin - th / 2)) : c;
8730
+ const base = { left: "auto", right: "auto", top: "auto", bottom: "auto" };
8731
+ if (placement === "bottom") setCoords({ ...base, left: clampX(cx), top: Math.round(r.bottom + gap) });
8732
+ else if (placement === "left") setCoords({ ...base, top: clampY(cy), right: Math.round(vw - r.left + gap) });
8733
+ else if (placement === "right") setCoords({ ...base, top: clampY(cy), left: Math.round(r.right + gap) });
8734
+ else setCoords({ ...base, left: clampX(cx), bottom: Math.round(vh - r.top + gap) });
8735
+ }, [placement]);
8736
+ React23__default.useEffect(() => {
8737
+ place();
8738
+ }, [place]);
8739
+ React23__default.useEffect(() => {
8740
+ if (!show) return void 0;
8741
+ place();
8742
+ const onMove = () => place();
8743
+ window.addEventListener("scroll", onMove, true);
8744
+ window.addEventListener("resize", onMove);
8745
+ return () => {
8746
+ window.removeEventListener("scroll", onMove, true);
8747
+ window.removeEventListener("resize", onMove);
8748
+ };
8749
+ }, [show, place]);
8750
+ React23__default.useEffect(() => {
8751
+ if (!show) return;
8752
+ const onKeyDown = (e) => {
8753
+ if (e.key === "Escape") {
8754
+ clearTimeout(timer.current);
8755
+ setShow(false);
8756
+ }
8757
+ };
8758
+ document.addEventListener("keydown", onKeyDown);
8759
+ return () => document.removeEventListener("keydown", onKeyDown);
8760
+ }, [show]);
8761
+ const describedBy = show ? id : void 0;
8762
+ const trigger = React23__default.isValidElement(children) && children.type !== React23__default.Fragment ? React23__default.cloneElement(children, {
8763
+ "aria-describedby": [children.props["aria-describedby"], describedBy].filter(Boolean).join(" ") || void 0
8764
+ }) : /* @__PURE__ */ jsx("span", { "aria-describedby": describedBy, children });
8765
+ return /* @__PURE__ */ jsxs(
8766
+ "span",
8767
+ {
8768
+ ref: wrapRef,
8769
+ className: `twc-tooltip-wrap ${className}`,
8770
+ onMouseEnter: open,
8771
+ onMouseLeave: close,
8772
+ onFocus: open,
8773
+ onBlur: close,
8774
+ ...rest,
8775
+ children: [
8776
+ __twcStyles,
8777
+ trigger,
8778
+ coords ? createPortal(
8779
+ /* @__PURE__ */ jsxs(
8780
+ "span",
8781
+ {
8782
+ ref: tipRef,
8783
+ id,
8784
+ className: "twc-tooltip",
8785
+ "data-place": placement,
8786
+ "data-show": show || void 0,
8787
+ role: "tooltip",
8788
+ "aria-hidden": show ? void 0 : "true",
8789
+ style: { position: "fixed", left: coords.left, right: coords.right, top: coords.top, bottom: coords.bottom },
8790
+ children: [
8791
+ label,
8792
+ /* @__PURE__ */ jsx("span", { className: "twc-tooltip__arrow", "aria-hidden": "true" })
8793
+ ]
8794
+ }
8795
+ ),
8796
+ document.body
8797
+ ) : null
8798
+ ]
8799
+ }
8800
+ );
8801
+ }
8673
8802
  var SIDEBAR_CSS = `
8674
8803
  .twc-sidebar { display: flex; flex-direction: column; height: 100%; font-family: var(--font-sans);
8675
8804
  background: var(--color-surface); border-inline-end: var(--border-thin) solid var(--color-border);
@@ -8753,10 +8882,10 @@ function Sidebar({
8753
8882
  "data-active": it.active || void 0,
8754
8883
  "aria-current": it.active ? "page" : void 0,
8755
8884
  onClick: it.onClick,
8756
- title: collapsed && labelStr != null ? labelStr : void 0,
8757
8885
  "aria-label": collapsed && labelStr != null ? labelStr : void 0
8758
8886
  };
8759
- return href != null ? /* @__PURE__ */ jsx("a", { href, ...common, children: inner }, i) : /* @__PURE__ */ jsx("button", { type: "button", ...common, children: inner }, i);
8887
+ const node = href != null ? /* @__PURE__ */ jsx("a", { href, ...common, children: inner }, i) : /* @__PURE__ */ jsx("button", { type: "button", ...common, children: inner }, i);
8888
+ return collapsed && labelStr != null ? /* @__PURE__ */ jsx(Tooltip, { label: labelStr, placement: "right", style: { display: "block" }, children: node }, i) : node;
8760
8889
  })()
8761
8890
  ) }),
8762
8891
  footer || collapsible ? /* @__PURE__ */ jsxs("div", { className: "twc-sidebar__foot", children: [
@@ -9898,135 +10027,6 @@ function ToastProvider({ children, limit = 4, duration = 4500, ...viewportProps
9898
10027
  )) })
9899
10028
  ] });
9900
10029
  }
9901
- var TOOLTIP_CSS = `
9902
- .twc-tooltip-wrap { display: inline-flex; }
9903
- .twc-tooltip {
9904
- position: fixed; z-index: var(--z-tooltip); pointer-events: none;
9905
- padding: 6px 10px; border-radius: var(--radius-md);
9906
- background: var(--color-text); color: var(--color-surface);
9907
- font-family: var(--font-sans); font-size: var(--text-xs); font-weight: var(--font-medium);
9908
- line-height: 1.3; white-space: nowrap; box-shadow: var(--shadow-md);
9909
- opacity: 0; transform: scale(0.9); transition: opacity var(--duration-fast) var(--ease-out), transform var(--duration-fast) var(--ease-spring);
9910
- }
9911
- .twc-tooltip[data-show="true"] { opacity: 1; transform: scale(1); }
9912
- .twc-tooltip[data-place="top"] { transform-origin: bottom center; translate: -50% 0; }
9913
- .twc-tooltip[data-place="bottom"] { transform-origin: top center; translate: -50% 0; }
9914
- .twc-tooltip[data-place="left"] { transform-origin: right center; translate: 0 -50%; }
9915
- .twc-tooltip[data-place="right"] { transform-origin: left center; translate: 0 -50%; }
9916
- .twc-tooltip[data-show="true"][data-place="top"], .twc-tooltip[data-show="true"][data-place="bottom"] { transform: scale(1); }
9917
- .twc-tooltip__arrow { position: absolute; width: 7px; height: 7px; background: var(--color-text); transform: rotate(45deg); }
9918
- .twc-tooltip[data-place="top"] .twc-tooltip__arrow { bottom: -3px; left: 50%; margin-left: -3.5px; }
9919
- .twc-tooltip[data-place="bottom"] .twc-tooltip__arrow { top: -3px; left: 50%; margin-left: -3.5px; }
9920
- .twc-tooltip[data-place="left"] .twc-tooltip__arrow { right: -3px; top: 50%; margin-top: -3.5px; }
9921
- .twc-tooltip[data-place="right"] .twc-tooltip__arrow { left: -3px; top: 50%; margin-top: -3.5px; }
9922
- @media (prefers-reduced-motion: reduce) { .twc-tooltip { transition: opacity var(--duration-fast) linear; transform: none; } }
9923
- `;
9924
- function Tooltip({
9925
- children,
9926
- label,
9927
- placement = "top",
9928
- delay = 120,
9929
- className = "",
9930
- ...rest
9931
- }) {
9932
- const __twcStyles = useScopedStyles("twc-tooltip-styles", TOOLTIP_CSS);
9933
- const id = React23__default.useId();
9934
- const [show, setShow] = React23__default.useState(false);
9935
- const [coords, setCoords] = React23__default.useState(null);
9936
- const timer = React23__default.useRef(null);
9937
- const wrapRef = React23__default.useRef(null);
9938
- const tipRef = React23__default.useRef(null);
9939
- const open = () => {
9940
- clearTimeout(timer.current);
9941
- timer.current = setTimeout(() => setShow(true), delay);
9942
- };
9943
- const close = () => {
9944
- clearTimeout(timer.current);
9945
- setShow(false);
9946
- };
9947
- React23__default.useEffect(() => () => clearTimeout(timer.current), []);
9948
- const place = React23__default.useCallback(() => {
9949
- const el = wrapRef.current;
9950
- if (!el) return;
9951
- const r = el.getBoundingClientRect();
9952
- const cx = Math.round(r.left + r.width / 2), cy = Math.round(r.top + r.height / 2);
9953
- const vw = window.innerWidth, vh = window.innerHeight, gap = 8, margin = 8;
9954
- const tip = tipRef.current;
9955
- const tw = tip ? tip.offsetWidth : 0, th = tip ? tip.offsetHeight : 0;
9956
- const clampX = (c) => tw ? Math.round(Math.min(Math.max(c, margin + tw / 2), vw - margin - tw / 2)) : c;
9957
- const clampY = (c) => th ? Math.round(Math.min(Math.max(c, margin + th / 2), vh - margin - th / 2)) : c;
9958
- const base = { left: "auto", right: "auto", top: "auto", bottom: "auto" };
9959
- if (placement === "bottom") setCoords({ ...base, left: clampX(cx), top: Math.round(r.bottom + gap) });
9960
- else if (placement === "left") setCoords({ ...base, top: clampY(cy), right: Math.round(vw - r.left + gap) });
9961
- else if (placement === "right") setCoords({ ...base, top: clampY(cy), left: Math.round(r.right + gap) });
9962
- else setCoords({ ...base, left: clampX(cx), bottom: Math.round(vh - r.top + gap) });
9963
- }, [placement]);
9964
- React23__default.useEffect(() => {
9965
- place();
9966
- }, [place]);
9967
- React23__default.useEffect(() => {
9968
- if (!show) return void 0;
9969
- place();
9970
- const onMove = () => place();
9971
- window.addEventListener("scroll", onMove, true);
9972
- window.addEventListener("resize", onMove);
9973
- return () => {
9974
- window.removeEventListener("scroll", onMove, true);
9975
- window.removeEventListener("resize", onMove);
9976
- };
9977
- }, [show, place]);
9978
- React23__default.useEffect(() => {
9979
- if (!show) return;
9980
- const onKeyDown = (e) => {
9981
- if (e.key === "Escape") {
9982
- clearTimeout(timer.current);
9983
- setShow(false);
9984
- }
9985
- };
9986
- document.addEventListener("keydown", onKeyDown);
9987
- return () => document.removeEventListener("keydown", onKeyDown);
9988
- }, [show]);
9989
- const describedBy = show ? id : void 0;
9990
- const trigger = React23__default.isValidElement(children) && children.type !== React23__default.Fragment ? React23__default.cloneElement(children, {
9991
- "aria-describedby": [children.props["aria-describedby"], describedBy].filter(Boolean).join(" ") || void 0
9992
- }) : /* @__PURE__ */ jsx("span", { "aria-describedby": describedBy, children });
9993
- return /* @__PURE__ */ jsxs(
9994
- "span",
9995
- {
9996
- ref: wrapRef,
9997
- className: `twc-tooltip-wrap ${className}`,
9998
- onMouseEnter: open,
9999
- onMouseLeave: close,
10000
- onFocus: open,
10001
- onBlur: close,
10002
- ...rest,
10003
- children: [
10004
- __twcStyles,
10005
- trigger,
10006
- coords ? createPortal(
10007
- /* @__PURE__ */ jsxs(
10008
- "span",
10009
- {
10010
- ref: tipRef,
10011
- id,
10012
- className: "twc-tooltip",
10013
- "data-place": placement,
10014
- "data-show": show || void 0,
10015
- role: "tooltip",
10016
- "aria-hidden": show ? void 0 : "true",
10017
- style: { position: "fixed", left: coords.left, right: coords.right, top: coords.top, bottom: coords.bottom },
10018
- children: [
10019
- label,
10020
- /* @__PURE__ */ jsx("span", { className: "twc-tooltip__arrow", "aria-hidden": "true" })
10021
- ]
10022
- }
10023
- ),
10024
- document.body
10025
- ) : null
10026
- ]
10027
- }
10028
- );
10029
- }
10030
10030
  var TREE_CSS = `
10031
10031
  .twc-tree { font-family: var(--font-sans); font-size: var(--text-sm); user-select: none; }
10032
10032
  .twc-tree__group { list-style: none; margin: 0; padding: 0; }
@@ -10197,6 +10197,34 @@ function TreeView({
10197
10197
  )) })
10198
10198
  ] });
10199
10199
  }
10200
+ var SHELL_CSS = `
10201
+ .twc-shell { display: flex; overflow: hidden; background: var(--color-bg); color: var(--color-text); font-family: var(--font-sans); }
10202
+ .twc-shell__main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; height: 100%; }
10203
+ .twc-shell__header { flex: none; display: flex; align-items: center; justify-content: space-between; gap: var(--space-4);
10204
+ min-height: 60px; padding-inline: var(--space-5); border-bottom: var(--border-thin) solid var(--color-border); background: var(--color-surface); }
10205
+ .twc-shell__content { flex: 1 1 auto; min-height: 0; overflow: auto; }
10206
+ .twc-shell__content[data-padded="true"] { padding: var(--space-6) var(--space-5); }
10207
+ `;
10208
+ function AppShell({
10209
+ sidebar,
10210
+ header,
10211
+ children,
10212
+ height = "100dvh",
10213
+ padded = true,
10214
+ className = "",
10215
+ style,
10216
+ ...rest
10217
+ }) {
10218
+ const __twcStyles = useScopedStyles("twc-shell-styles", SHELL_CSS);
10219
+ return /* @__PURE__ */ jsxs("div", { className: `twc-shell ${className}`.trim(), style: { height, ...style }, ...rest, children: [
10220
+ __twcStyles,
10221
+ sidebar,
10222
+ /* @__PURE__ */ jsxs("div", { className: "twc-shell__main", children: [
10223
+ header != null ? /* @__PURE__ */ jsx("header", { className: "twc-shell__header", children: header }) : null,
10224
+ /* @__PURE__ */ jsx("main", { className: "twc-shell__content", "data-padded": padded ? "true" : void 0, children })
10225
+ ] })
10226
+ ] });
10227
+ }
10200
10228
  function sp(v) {
10201
10229
  if (v == null) return void 0;
10202
10230
  return typeof v === "number" ? `var(--space-${String(v).replace(".", "-")})` : v;
@@ -10833,6 +10861,6 @@ function useId(prefix = "twc") {
10833
10861
  return prefix ? `${prefix}-${raw.replace(/:/g, "")}` : raw;
10834
10862
  }
10835
10863
 
10836
- export { Accordion, Alert, Avatar, AvatarMenu, Badge, Box, Breadcrumb, Button, Card, Carousel, Chart, Checkbox, Code, ColorPicker, Combobox, CommandPalette, Container, Currency, CurrencyField, Datatable, DatePicker, DateRangePicker, Dialog, Divider, Drawer, EmptyState, Field, FileUpload, Grid, Heading, IconButton, Input, Kanban, List, Menu, MultiSelect, Navbar, Pagination, Popover, Progress, Radio, Rating, Select, Sidebar, Skeleton, Slider, Spinner, Stack, Stat, Stepper, Switch, Table, Tabs, Tag, Text, Textarea, Timeline, Toast, ToastProvider, ToastViewport, Tooltip, TreeView, runDatatableQuery, useClickOutside, useColorScheme, useControllableState, useCopyToClipboard, useDebouncedCallback, useDebouncedValue, useDisclosure, useEventListener, useHover, useId, useIntersectionObserver, useInterval, useIsomorphicLayoutEffect, useKeyPress, useLocalStorage, useMediaQuery, useMounted, usePrefersReducedMotion, usePrevious, useScrollLock, useTimeout, useToast, useToggle, useWindowSize };
10864
+ export { Accordion, Alert, AppShell, Avatar, AvatarMenu, Badge, Box, Breadcrumb, Button, Card, Carousel, Chart, Checkbox, Code, ColorPicker, Combobox, CommandPalette, Container, Currency, CurrencyField, Datatable, DatePicker, DateRangePicker, Dialog, Divider, Drawer, EmptyState, Field, FileUpload, Grid, Heading, IconButton, Input, Kanban, List, Menu, MultiSelect, Navbar, Pagination, Popover, Progress, Radio, Rating, Select, Sidebar, Skeleton, Slider, Spinner, Stack, Stat, Stepper, Switch, Table, Tabs, Tag, Text, Textarea, Timeline, Toast, ToastProvider, ToastViewport, Tooltip, TreeView, runDatatableQuery, useClickOutside, useColorScheme, useControllableState, useCopyToClipboard, useDebouncedCallback, useDebouncedValue, useDisclosure, useEventListener, useHover, useId, useIntersectionObserver, useInterval, useIsomorphicLayoutEffect, useKeyPress, useLocalStorage, useMediaQuery, useMounted, usePrefersReducedMotion, usePrevious, useScrollLock, useTimeout, useToast, useToggle, useWindowSize };
10837
10865
  //# sourceMappingURL=index.mjs.map
10838
10866
  //# sourceMappingURL=index.mjs.map