@flikk/ui 1.0.0-beta.26 → 1.0.0-beta.27

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 (131) hide show
  1. package/dist/components/ai/PromptInput/PromptInput.js +3 -0
  2. package/dist/components/ai/PromptInput/VoiceRecorder.js +3 -0
  3. package/dist/components/core/Button/Button.theme.js +1 -1
  4. package/dist/components/core/Calendar/Calendar.theme.js +1 -1
  5. package/dist/components/core/CommandPalette/CommandItem.js +4 -5
  6. package/dist/components/core/CommandPalette/CommandPalette.js +1 -1
  7. package/dist/components/core/CommandPalette/CommandPalette.theme.js +11 -13
  8. package/dist/components/core/CommandPalette/CommandPalette.types.d.ts +0 -2
  9. package/dist/components/core/ContextMenu/ContextMenu.theme.js +13 -14
  10. package/dist/components/core/DotSeparator/DotSeparator.d.ts +3 -0
  11. package/dist/components/core/DotSeparator/DotSeparator.js +19 -0
  12. package/dist/components/core/DotSeparator/DotSeparator.theme.d.ts +2 -0
  13. package/dist/components/core/DotSeparator/DotSeparator.theme.js +10 -0
  14. package/dist/components/core/DotSeparator/DotSeparator.types.d.ts +25 -0
  15. package/dist/components/core/DotSeparator/index.d.ts +3 -0
  16. package/dist/components/core/Dropdown/Dropdown.theme.js +2 -3
  17. package/dist/components/core/Dropdown/DropdownItem.js +1 -1
  18. package/dist/components/core/Dropdown/DropdownMenu.js +1 -1
  19. package/dist/components/core/MenuItem/MenuItem.js +5 -2
  20. package/dist/components/core/MenuItem/MenuItem.theme.d.ts +6 -0
  21. package/dist/components/core/MenuItem/MenuItem.theme.js +19 -16
  22. package/dist/components/core/MenuItem/MenuItem.types.d.ts +2 -0
  23. package/dist/components/core/NavItem/NavItem.js +20 -4
  24. package/dist/components/core/NavItem/NavItem.theme.js +13 -2
  25. package/dist/components/core/Popover/Popover.types.d.ts +6 -2
  26. package/dist/components/core/Popover/PopoverBody.js +10 -3
  27. package/dist/components/core/Segmented/Segmented.theme.js +1 -1
  28. package/dist/components/core/Sidebar/Sidebar.d.ts +2 -0
  29. package/dist/components/core/Sidebar/Sidebar.js +15 -7
  30. package/dist/components/core/Sidebar/Sidebar.types.d.ts +92 -4
  31. package/dist/components/core/Sidebar/SidebarCard.d.ts +25 -0
  32. package/dist/components/core/Sidebar/SidebarCard.js +68 -0
  33. package/dist/components/core/Sidebar/SidebarCard.theme.d.ts +8 -0
  34. package/dist/components/core/Sidebar/SidebarCard.theme.js +18 -0
  35. package/dist/components/core/Sidebar/SidebarContent.js +5 -1
  36. package/dist/components/core/Sidebar/SidebarContext.js +1 -1
  37. package/dist/components/core/Sidebar/SidebarHeader.js +10 -2
  38. package/dist/components/core/Sidebar/SidebarLogo.js +38 -3
  39. package/dist/components/core/Sidebar/SidebarSearch.d.ts +22 -0
  40. package/dist/components/core/Sidebar/SidebarSearch.js +135 -0
  41. package/dist/components/core/Sidebar/SidebarToggle.js +1 -1
  42. package/dist/components/core/Sidebar/SidebarUserProfile.js +2 -2
  43. package/dist/components/core/Sidebar/index.d.ts +3 -1
  44. package/dist/components/core/Tag/Tag.js +29 -5
  45. package/dist/components/core/Tag/Tag.theme.js +13 -8
  46. package/dist/components/core/Tag/Tag.types.d.ts +7 -0
  47. package/dist/components/core/Tooltip/Tooltip.js +1 -1
  48. package/dist/components/core/Tooltip/Tooltip.theme.js +1 -2
  49. package/dist/components/core/index.d.ts +1 -0
  50. package/dist/components/core/index.js +4 -0
  51. package/dist/components/data-display/GanttChart/GanttChart.d.ts +1 -1
  52. package/dist/components/data-display/GanttChart/GanttChart.js +31 -4
  53. package/dist/components/data-display/GanttChart/GanttChart.theme.js +19 -17
  54. package/dist/components/data-display/GanttChart/GanttChart.types.d.ts +19 -0
  55. package/dist/components/data-display/GanttChart/GanttChart.utils.js +1 -1
  56. package/dist/components/data-display/GanttChart/GanttChartPanel.d.ts +1 -1
  57. package/dist/components/data-display/GanttChart/GanttChartPanel.js +3 -3
  58. package/dist/components/data-display/GanttChart/GanttDependencyArrows.js +7 -4
  59. package/dist/components/data-display/GanttChart/GanttMilestone.js +5 -5
  60. package/dist/components/data-display/GanttChart/GanttTablePanel.js +1 -1
  61. package/dist/components/data-display/GanttChart/GanttTableTaskRow.js +2 -2
  62. package/dist/components/data-display/GanttChart/GanttTaskBar.js +37 -16
  63. package/dist/components/data-display/GanttChart/GanttTimelineGrid.js +2 -1
  64. package/dist/components/data-display/GanttChart/GanttTimelineHeader.js +35 -11
  65. package/dist/components/data-display/GanttChart/GanttToolbar.js +2 -2
  66. package/dist/components/data-display/GanttChart/hooks/useGanttDrag.js +3 -2
  67. package/dist/components/data-display/GanttChart/index.d.ts +1 -1
  68. package/dist/components/data-display/Table/Table.theme.js +3 -5
  69. package/dist/components/effects/Aurora/Aurora.d.ts +6 -17
  70. package/dist/components/effects/Aurora/Aurora.js +297 -131
  71. package/dist/components/effects/Aurora/Aurora.types.d.ts +6 -0
  72. package/dist/components/forms/Combobox/Combobox.js +1 -1
  73. package/dist/components/forms/Combobox/Combobox.theme.js +2 -4
  74. package/dist/components/forms/CronInput/CronInput.js +1 -1
  75. package/dist/components/forms/CronInput/CronInput.theme.js +14 -23
  76. package/dist/components/forms/DatePicker/DatePicker.theme.js +11 -18
  77. package/dist/components/forms/DatePicker/DatePickerTrigger.js +1 -1
  78. package/dist/components/forms/DateRangePicker/DateRangePicker.theme.js +6 -13
  79. package/dist/components/forms/DateRangePicker/DateRangePickerTrigger.js +1 -1
  80. package/dist/components/forms/FileUpload/FileUpload.animations.d.ts +29 -0
  81. package/dist/components/forms/FileUpload/FileUpload.animations.js +19 -0
  82. package/dist/components/forms/FileUpload/FileUpload.js +87 -48
  83. package/dist/components/forms/FileUpload/FileUpload.theme.d.ts +2 -10
  84. package/dist/components/forms/FileUpload/FileUpload.theme.js +16 -30
  85. package/dist/components/forms/FileUpload/FileUpload.types.d.ts +26 -10
  86. package/dist/components/forms/Input/Input.theme.js +13 -10
  87. package/dist/components/forms/InputCounter/InputCounter.theme.js +1 -1
  88. package/dist/components/forms/Mention/Mention.js +152 -57
  89. package/dist/components/forms/Mention/Mention.theme.js +16 -23
  90. package/dist/components/forms/Mention/Mention.types.d.ts +12 -12
  91. package/dist/components/forms/Mention/Mention.utils.js +32 -4
  92. package/dist/components/forms/RichTextEditor/RichTextEditor.js +3 -3
  93. package/dist/components/forms/RichTextEditor/RichTextEditor.theme.js +5 -5
  94. package/dist/components/forms/Select/Select.js +2 -2
  95. package/dist/components/forms/Select/Select.theme.js +3 -3
  96. package/dist/components/forms/TimePicker/TimePickerContent.js +3 -0
  97. package/dist/components/forms/TimePicker/TimePickerTrigger.js +1 -1
  98. package/dist/components/forms/forms.theme.js +21 -16
  99. package/dist/components/forms/index.js +3 -0
  100. package/dist/components/layout/AppShell/AppShell.d.ts +10 -0
  101. package/dist/components/layout/AppShell/AppShell.js +84 -0
  102. package/dist/components/layout/AppShell/AppShell.theme.d.ts +3 -0
  103. package/dist/components/layout/AppShell/AppShell.theme.js +42 -0
  104. package/dist/components/layout/AppShell/AppShell.types.d.ts +127 -0
  105. package/dist/components/layout/AppShell/AppShellContext.d.ts +14 -0
  106. package/dist/components/layout/AppShell/AppShellContext.js +19 -0
  107. package/dist/components/layout/AppShell/AppShellFooter.d.ts +3 -0
  108. package/dist/components/layout/AppShell/AppShellFooter.js +12 -0
  109. package/dist/components/layout/AppShell/AppShellHeader.d.ts +3 -0
  110. package/dist/components/layout/AppShell/AppShellHeader.js +12 -0
  111. package/dist/components/layout/AppShell/AppShellMain.d.ts +3 -0
  112. package/dist/components/layout/AppShell/AppShellMain.js +19 -0
  113. package/dist/components/layout/AppShell/AppShellRightPanel.d.ts +3 -0
  114. package/dist/components/layout/AppShell/AppShellRightPanel.js +16 -0
  115. package/dist/components/layout/AppShell/AppShellSidebar.d.ts +3 -0
  116. package/dist/components/layout/AppShell/AppShellSidebar.js +16 -0
  117. package/dist/components/layout/AppShell/AppShellTopbar.d.ts +3 -0
  118. package/dist/components/layout/AppShell/AppShellTopbar.js +12 -0
  119. package/dist/components/layout/AppShell/index.d.ts +3 -0
  120. package/dist/components/layout/FormLayout/FormLayout.js +3 -0
  121. package/dist/components/layout/index.d.ts +1 -0
  122. package/dist/components/layout/index.js +2 -0
  123. package/dist/hooks/useSelectPortal.d.ts +10 -2
  124. package/dist/hooks/useSelectPortal.js +45 -24
  125. package/dist/index.js +6 -0
  126. package/dist/registry.json +10021 -0
  127. package/dist/styles.css +1 -1
  128. package/dist/utils/dateUtils.js +11 -1
  129. package/package.json +4 -2
  130. package/src/global.scss +29 -8
  131. package/src/styles/theme.css +51 -12
@@ -0,0 +1,12 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import React__default from 'react';
3
+ import { cn } from '../../../utils/cn.js';
4
+ import { getAppShellTheme } from './AppShell.theme.js';
5
+
6
+ const AppShellFooter = React__default.forwardRef(({ sticky = true, className, theme: customTheme, children, ...props }, ref) => {
7
+ const theme = getAppShellTheme(customTheme);
8
+ return (jsx("footer", { ref: ref, className: cn(theme.footer, sticky && "sticky bottom-0 z-20", className), ...props, children: children }));
9
+ });
10
+ AppShellFooter.displayName = "AppShell.Footer";
11
+
12
+ export { AppShellFooter };
@@ -0,0 +1,3 @@
1
+ import React from "react";
2
+ import type { AppShellHeaderProps } from "./AppShell.types";
3
+ export declare const AppShellHeader: React.ForwardRefExoticComponent<AppShellHeaderProps & React.RefAttributes<HTMLElement>>;
@@ -0,0 +1,12 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import React__default from 'react';
3
+ import { cn } from '../../../utils/cn.js';
4
+ import { getAppShellTheme } from './AppShell.theme.js';
5
+
6
+ const AppShellHeader = React__default.forwardRef(({ sticky = true, className, theme: customTheme, children, ...props }, ref) => {
7
+ const theme = getAppShellTheme(customTheme);
8
+ return (jsx("header", { ref: ref, className: cn(theme.header, sticky && "sticky top-0 z-10", className), ...props, children: children }));
9
+ });
10
+ AppShellHeader.displayName = "AppShell.Header";
11
+
12
+ export { AppShellHeader };
@@ -0,0 +1,3 @@
1
+ import React from "react";
2
+ import type { AppShellMainProps } from "./AppShell.types";
3
+ export declare const AppShellMain: React.ForwardRefExoticComponent<AppShellMainProps & React.RefAttributes<HTMLElement>>;
@@ -0,0 +1,19 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import React__default from 'react';
3
+ import { cn } from '../../../utils/cn.js';
4
+ import { ScrollArea } from '../../core/ScrollArea/ScrollArea.js';
5
+ import '../../core/ScrollArea/smooth/SmoothScrollEngine.js';
6
+ import { getAppShellTheme } from './AppShell.theme.js';
7
+ import { useAppShellContext } from './AppShellContext.js';
8
+
9
+ const AppShellMain = React__default.forwardRef(({ className, theme: customTheme, contentWidth, contentPadding, children, ...props }, ref) => {
10
+ const theme = getAppShellTheme(customTheme);
11
+ const ctx = useAppShellContext();
12
+ const resolvedWidth = contentWidth !== null && contentWidth !== void 0 ? contentWidth : ctx.contentWidth;
13
+ const resolvedPadding = contentPadding !== null && contentPadding !== void 0 ? contentPadding : ctx.contentPadding;
14
+ const inner = (jsx("div", { className: cn(theme.mainInner, theme.contentWidth[resolvedWidth], theme.contentPadding[resolvedPadding]), children: children }));
15
+ return (jsx("main", { ref: ref, className: cn(theme.main, className), ...props, children: ctx.scroll === "viewport" ? (jsx(ScrollArea, { type: "hover", size: "thin", className: theme.mainScroll, children: inner })) : (inner) }));
16
+ });
17
+ AppShellMain.displayName = "AppShell.Main";
18
+
19
+ export { AppShellMain };
@@ -0,0 +1,3 @@
1
+ import React from "react";
2
+ import type { AppShellRightPanelProps } from "./AppShell.types";
3
+ export declare const AppShellRightPanel: React.ForwardRefExoticComponent<AppShellRightPanelProps & React.RefAttributes<HTMLElement>>;
@@ -0,0 +1,16 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import React__default from 'react';
3
+ import { cn } from '../../../utils/cn.js';
4
+ import { ScrollArea } from '../../core/ScrollArea/ScrollArea.js';
5
+ import '../../core/ScrollArea/smooth/SmoothScrollEngine.js';
6
+ import { getAppShellTheme } from './AppShell.theme.js';
7
+ import { useAppShellContext } from './AppShellContext.js';
8
+
9
+ const AppShellRightPanel = React__default.forwardRef(({ width = "20rem", className, theme: customTheme, style, children, "aria-label": ariaLabel = "Secondary", ...props }, ref) => {
10
+ const theme = getAppShellTheme(customTheme);
11
+ const ctx = useAppShellContext();
12
+ return (jsx("aside", { ref: ref, "aria-label": ariaLabel, className: cn(theme.rightPanel, className), style: { width, ...style }, ...props, children: ctx.scroll === "viewport" ? (jsx(ScrollArea, { type: "hover", size: "thin", className: theme.rightPanelScroll, children: children })) : (children) }));
13
+ });
14
+ AppShellRightPanel.displayName = "AppShell.RightPanel";
15
+
16
+ export { AppShellRightPanel };
@@ -0,0 +1,3 @@
1
+ import React from "react";
2
+ import type { AppShellSidebarProps } from "./AppShell.types";
3
+ export declare const AppShellSidebar: React.ForwardRefExoticComponent<AppShellSidebarProps & React.RefAttributes<HTMLElement>>;
@@ -0,0 +1,16 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import React__default from 'react';
3
+ import { cn } from '../../../utils/cn.js';
4
+ import { ScrollArea } from '../../core/ScrollArea/ScrollArea.js';
5
+ import '../../core/ScrollArea/smooth/SmoothScrollEngine.js';
6
+ import { getAppShellTheme } from './AppShell.theme.js';
7
+ import { useAppShellContext } from './AppShellContext.js';
8
+
9
+ const AppShellSidebar = React__default.forwardRef(({ width = "16rem", collapsedOnMobile = true, className, theme: customTheme, style, children, "aria-label": ariaLabel = "Primary", ...props }, ref) => {
10
+ const theme = getAppShellTheme(customTheme);
11
+ const ctx = useAppShellContext();
12
+ return (jsx("aside", { ref: ref, "aria-label": ariaLabel, className: cn(theme.sidebar, collapsedOnMobile && theme.sidebarCollapsed, className), style: { width, ...style }, ...props, children: ctx.scroll === "viewport" ? (jsx(ScrollArea, { type: "hover", size: "thin", className: theme.sidebarScroll, children: children })) : (children) }));
13
+ });
14
+ AppShellSidebar.displayName = "AppShell.Sidebar";
15
+
16
+ export { AppShellSidebar };
@@ -0,0 +1,3 @@
1
+ import React from "react";
2
+ import type { AppShellTopbarProps } from "./AppShell.types";
3
+ export declare const AppShellTopbar: React.ForwardRefExoticComponent<AppShellTopbarProps & React.RefAttributes<HTMLElement>>;
@@ -0,0 +1,12 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import React__default from 'react';
3
+ import { cn } from '../../../utils/cn.js';
4
+ import { getAppShellTheme } from './AppShell.theme.js';
5
+
6
+ const AppShellTopbar = React__default.forwardRef(({ sticky = true, className, theme: customTheme, children, ...props }, ref) => {
7
+ const theme = getAppShellTheme(customTheme);
8
+ return (jsx("header", { ref: ref, className: cn(theme.topbar, sticky && "sticky top-0 z-20", className), ...props, children: children }));
9
+ });
10
+ AppShellTopbar.displayName = "AppShell.Topbar";
11
+
12
+ export { AppShellTopbar };
@@ -0,0 +1,3 @@
1
+ export { AppShell } from "./AppShell";
2
+ export type { AppShellProps, AppShellTopbarProps, AppShellSidebarProps, AppShellHeaderProps, AppShellMainProps, AppShellRightPanelProps, AppShellFooterProps, AppShellScroll, AppShellSpan, AppShellContentWidth, AppShellContentPadding, AppShellTheme, AppShellThemeOverrides, } from "./AppShell.types";
3
+ export { appShellTheme, getAppShellTheme } from "./AppShell.theme";
@@ -30,6 +30,7 @@ import '../../core/Dropdown/DropdownItem.js';
30
30
  import '../../core/Dropdown/DropdownSection.js';
31
31
  import '../../core/Dropdown/DropdownSeparator.js';
32
32
  import '../../core/Dropdown/Dropdown.theme.js';
33
+ import '../../core/DotSeparator/DotSeparator.js';
33
34
  import '../../core/Kbd/Kbd.js';
34
35
  import '../../core/MenuItem/MenuItem.js';
35
36
  import '../../core/Link/Link.js';
@@ -81,6 +82,8 @@ import '../../core/Sidebar/SidebarToggle.js';
81
82
  import '../../core/Sidebar/SidebarMobileTrigger.js';
82
83
  import '../../core/Sidebar/SidebarUserProfile.js';
83
84
  import '../../core/Sidebar/SidebarLogo.js';
85
+ import '../../core/Sidebar/SidebarSearch.js';
86
+ import '../../core/Sidebar/SidebarCard.js';
84
87
  import '../../core/Sidebar/SidebarContext.js';
85
88
  import '../../core/OfflineIndicator/OfflineIndicator.js';
86
89
  import '../../core/ContextMenu/ContextMenu.js';
@@ -1,2 +1,3 @@
1
1
  export * from "./FormLayout";
2
2
  export * from "./PageLayout";
3
+ export * from "./AppShell";
@@ -2,3 +2,5 @@ export { FormLayout } from './FormLayout/FormLayout.js';
2
2
  export { formLayoutTheme } from './FormLayout/FormLayout.theme.js';
3
3
  export { PageLayout } from './PageLayout/PageLayout.js';
4
4
  export { pageLayoutTheme } from './PageLayout/PageLayout.theme.js';
5
+ export { AppShell } from './AppShell/AppShell.js';
6
+ export { appShellTheme, getAppShellTheme } from './AppShell/AppShell.theme.js';
@@ -8,6 +8,14 @@ export interface UseSimpleDropdownOptions {
8
8
  autoWidth?: boolean;
9
9
  onClose?: () => void;
10
10
  stickyTracking?: boolean;
11
+ /**
12
+ * Clamp the dropdown horizontally so it never overflows the viewport edges.
13
+ * Runs even when `stickyTracking` is on, because horizontal position is
14
+ * independent of vertical scroll and so cannot fight the scroll-follow
15
+ * behavior. Vertical clamping remains gated on `!stickyTracking`.
16
+ * @default true
17
+ */
18
+ clampToViewport?: boolean;
11
19
  }
12
20
  export interface SimpleDropdownReturn {
13
21
  position: {
@@ -26,5 +34,5 @@ export interface SimpleDropdownReturn {
26
34
  * Uses position: fixed with pure viewport coordinates to properly follow scroll
27
35
  * Fixes critical issues: dropdown not following scroll & multiple dropdowns not working
28
36
  */
29
- export declare const useSimpleDropdown: ({ triggerRef, isOpen, placement, offset, estimatedWidth, autoWidth, onClose, stickyTracking, }: UseSimpleDropdownOptions) => SimpleDropdownReturn;
30
- export declare const useSelectPortal: ({ triggerRef, isOpen, placement, offset, estimatedWidth, autoWidth, onClose, stickyTracking, }: UseSimpleDropdownOptions) => SimpleDropdownReturn;
37
+ export declare const useSimpleDropdown: ({ triggerRef, isOpen, placement, offset, estimatedWidth, autoWidth, onClose, stickyTracking, clampToViewport, }: UseSimpleDropdownOptions) => SimpleDropdownReturn;
38
+ export declare const useSelectPortal: ({ triggerRef, isOpen, placement, offset, estimatedWidth, autoWidth, onClose, stickyTracking, clampToViewport, }: UseSimpleDropdownOptions) => SimpleDropdownReturn;
@@ -6,7 +6,7 @@ const useIsomorphicLayoutEffect = typeof window !== 'undefined' ? useLayoutEffec
6
6
  * Uses position: fixed with pure viewport coordinates to properly follow scroll
7
7
  * Fixes critical issues: dropdown not following scroll & multiple dropdowns not working
8
8
  */
9
- const useSimpleDropdown = ({ triggerRef, isOpen, placement = "bottom-start", offset = 4, estimatedWidth, autoWidth = false, onClose, stickyTracking = false, }) => {
9
+ const useSimpleDropdown = ({ triggerRef, isOpen, placement = "bottom-start", offset = 4, estimatedWidth, autoWidth = false, onClose, stickyTracking = false, clampToViewport = true, }) => {
10
10
  const contentRef = useRef(null);
11
11
  const [position, setPosition] = useState({ top: -9999, left: -9999, width: 0 });
12
12
  const [cssVariables, setCssVariables] = useState({});
@@ -169,28 +169,31 @@ const useSimpleDropdown = ({ triggerRef, isOpen, placement = "bottom-start", off
169
169
  left = rect.right + offset;
170
170
  }
171
171
  }
172
- // Collision detection - handle both horizontal and vertical overflow
173
- // Skip clamping for stickyTracking so the dropdown follows the trigger past viewport edges
174
- if (!stickyTracking) {
172
+ // Collision detection. Horizontal clamping runs whenever `clampToViewport`
173
+ // is on (default) even with stickyTracking because horizontal position
174
+ // is independent of vertical scroll and so cannot fight scroll-follow.
175
+ // Vertical clamping stays gated on `!stickyTracking` so the dropdown can
176
+ // follow the trigger past the top/bottom viewport edges during scroll.
177
+ if (clampToViewport) {
175
178
  // Horizontal bounds checking
176
179
  const rightEdge = left + dropdownWidth;
177
180
  const overflow = rightEdge - (viewportWidth - margin);
178
181
  if (overflow > 0) {
179
182
  // Shift left just enough to fit
180
183
  const shiftedLeft = left - overflow;
181
- if (shiftedLeft >= margin) {
182
- left = shiftedLeft;
183
- }
184
- else {
185
- // Clamp to viewport margin
186
- left = margin;
187
- }
184
+ left = shiftedLeft >= margin ? shiftedLeft : margin;
188
185
  }
189
186
  // Handle left edge overflow
190
187
  if (left < margin) {
191
188
  left = margin;
192
189
  }
193
- // Vertical bounds checking
190
+ }
191
+ {
192
+ // Vertical clamp runs on every calculatePosition — initial open, resize,
193
+ // and the non-sticky scroll path. The sticky scroll-follow path
194
+ // (updatePositionInDOM) stays unclamped so the popover tracks the trigger
195
+ // past the top/bottom edges during scroll. Clamping here means a sticky
196
+ // popover still OPENS fully on-screen even in a short viewport.
194
197
  const bottomEdge = top + dropdownHeight;
195
198
  const verticalOverflow = bottomEdge - (viewportHeight - margin);
196
199
  if (verticalOverflow > 0) {
@@ -210,13 +213,19 @@ const useSimpleDropdown = ({ triggerRef, isOpen, placement = "bottom-start", off
210
213
  }
211
214
  }
212
215
  setPosition({ top, left, width: dropdownWidth });
213
- // Calculate available space based on placement direction
216
+ // Calculate available space (drives the scrollable max-height var).
217
+ // Sticky overlays (Popover/Dropdown) clamp their open position to the
218
+ // viewport, so they can occupy the full usable viewport height regardless
219
+ // of which side of the trigger they sit on — size against that, not just
220
+ // the cramped space below. Non-sticky dropdowns (Select) keep per-side
221
+ // space so they never grow over their trigger.
222
+ const usableViewportHeight = viewportHeight - margin * 2 - offset;
214
223
  let availableSpace = 0;
215
224
  if (finalPlacement.startsWith("top")) {
216
- availableSpace = spaceAbove - offset;
225
+ availableSpace = stickyTracking ? usableViewportHeight : spaceAbove - offset;
217
226
  }
218
227
  else if (finalPlacement.startsWith("bottom")) {
219
- availableSpace = spaceBelow - offset;
228
+ availableSpace = stickyTracking ? usableViewportHeight : spaceBelow - offset;
220
229
  }
221
230
  else if (finalPlacement.startsWith("left")) {
222
231
  availableSpace = spaceLeft - offset;
@@ -240,7 +249,7 @@ const useSimpleDropdown = ({ triggerRef, isOpen, placement = "bottom-start", off
240
249
  }
241
250
  setCssVariables(cssVars);
242
251
  // Mark initial render as complete after first calculation
243
- }, [measureDropdownHeight, measureDropdownWidth, offset, placement, triggerRef, stickyTracking]);
252
+ }, [measureDropdownHeight, measureDropdownWidth, offset, placement, triggerRef, stickyTracking, clampToViewport]);
244
253
  // Direct DOM mutation for stickyTracking — bypasses React state for zero-lag scroll tracking
245
254
  const updatePositionInDOM = useCallback(() => {
246
255
  if (!triggerRef.current || !contentRef.current)
@@ -285,9 +294,22 @@ const useSimpleDropdown = ({ triggerRef, isOpen, placement = "bottom-start", off
285
294
  left = rect.right + offset;
286
295
  }
287
296
  }
297
+ // Keep horizontal clamping consistent with calculatePosition so the popover
298
+ // doesn't re-overflow the right edge when scroll-tracking recomputes position.
299
+ if (clampToViewport) {
300
+ const margin = 16;
301
+ const viewportWidth = window.innerWidth;
302
+ const overflow = left + dropdownWidth - (viewportWidth - margin);
303
+ if (overflow > 0) {
304
+ const shiftedLeft = left - overflow;
305
+ left = shiftedLeft >= margin ? shiftedLeft : margin;
306
+ }
307
+ if (left < margin)
308
+ left = margin;
309
+ }
288
310
  contentRef.current.style.top = `${top}px`;
289
311
  contentRef.current.style.left = `${left}px`;
290
- }, [triggerRef, measureDropdownHeight, measureDropdownWidth, offset]);
312
+ }, [triggerRef, measureDropdownHeight, measureDropdownWidth, offset, clampToViewport]);
291
313
  // Reset initial render flag when dropdown opens
292
314
  useIsomorphicLayoutEffect(() => {
293
315
  if (typeof window === 'undefined')
@@ -395,18 +417,17 @@ const useSimpleDropdown = ({ triggerRef, isOpen, placement = "bottom-start", off
395
417
  if (typeof ResizeObserver === "undefined")
396
418
  return;
397
419
  const observer = new ResizeObserver(() => {
398
- if (stickyTracking) {
399
- updatePositionInDOM();
400
- }
401
- else {
402
- calculatePosition();
403
- }
420
+ // Content resize (incl. the initial settle right after open) goes through
421
+ // calculatePosition so the popover re-fits and stays vertically clamped to
422
+ // the viewport. Only the scroll path uses the unclamped updatePositionInDOM
423
+ // follow — otherwise the resize-on-open would immediately undo the clamp.
424
+ calculatePosition();
404
425
  });
405
426
  observer.observe(contentRef.current);
406
427
  return () => {
407
428
  observer.disconnect();
408
429
  };
409
- }, [isOpen, calculatePosition, stickyTracking, updatePositionInDOM]);
430
+ }, [isOpen, calculatePosition]);
410
431
  return {
411
432
  position,
412
433
  cssVariables,
package/dist/index.js CHANGED
@@ -32,6 +32,8 @@ export { DropdownItem } from './components/core/Dropdown/DropdownItem.js';
32
32
  export { DropdownSection } from './components/core/Dropdown/DropdownSection.js';
33
33
  export { DropdownSeparator } from './components/core/Dropdown/DropdownSeparator.js';
34
34
  export { dropdownTheme } from './components/core/Dropdown/Dropdown.theme.js';
35
+ export { DotSeparator } from './components/core/DotSeparator/DotSeparator.js';
36
+ export { dotSeparatorTheme } from './components/core/DotSeparator/DotSeparator.theme.js';
35
37
  export { Kbd } from './components/core/Kbd/Kbd.js';
36
38
  export { MenuItem } from './components/core/MenuItem/MenuItem.js';
37
39
  export { menuItemTheme } from './components/core/MenuItem/MenuItem.theme.js';
@@ -100,6 +102,8 @@ export { SidebarToggle } from './components/core/Sidebar/SidebarToggle.js';
100
102
  export { SidebarMobileTrigger } from './components/core/Sidebar/SidebarMobileTrigger.js';
101
103
  export { SidebarUserProfile } from './components/core/Sidebar/SidebarUserProfile.js';
102
104
  export { SidebarLogo } from './components/core/Sidebar/SidebarLogo.js';
105
+ export { SidebarSearch } from './components/core/Sidebar/SidebarSearch.js';
106
+ export { SidebarCard } from './components/core/Sidebar/SidebarCard.js';
103
107
  export { SidebarProvider, useSidebarContext } from './components/core/Sidebar/SidebarContext.js';
104
108
  export { OfflineIndicator } from './components/core/OfflineIndicator/OfflineIndicator.js';
105
109
  export { offlineIndicatorTheme } from './components/core/OfflineIndicator/OfflineIndicator.theme.js';
@@ -200,6 +204,8 @@ export { FormLayout } from './components/layout/FormLayout/FormLayout.js';
200
204
  export { formLayoutTheme } from './components/layout/FormLayout/FormLayout.theme.js';
201
205
  export { PageLayout } from './components/layout/PageLayout/PageLayout.js';
202
206
  export { pageLayoutTheme } from './components/layout/PageLayout/PageLayout.theme.js';
207
+ export { AppShell } from './components/layout/AppShell/AppShell.js';
208
+ export { appShellTheme, getAppShellTheme } from './components/layout/AppShell/AppShell.theme.js';
203
209
  export { debounce } from './utils/debounce.js';
204
210
  export { useClickOutside } from './hooks/useClickOutside.js';
205
211
  export { useOverlay } from './hooks/useOverlay.js';