@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.
- package/dist/components/ai/PromptInput/PromptInput.js +3 -0
- package/dist/components/ai/PromptInput/VoiceRecorder.js +3 -0
- package/dist/components/core/Button/Button.theme.js +1 -1
- package/dist/components/core/Calendar/Calendar.theme.js +1 -1
- package/dist/components/core/CommandPalette/CommandItem.js +4 -5
- package/dist/components/core/CommandPalette/CommandPalette.js +1 -1
- package/dist/components/core/CommandPalette/CommandPalette.theme.js +11 -13
- package/dist/components/core/CommandPalette/CommandPalette.types.d.ts +0 -2
- package/dist/components/core/ContextMenu/ContextMenu.theme.js +13 -14
- package/dist/components/core/DotSeparator/DotSeparator.d.ts +3 -0
- package/dist/components/core/DotSeparator/DotSeparator.js +19 -0
- package/dist/components/core/DotSeparator/DotSeparator.theme.d.ts +2 -0
- package/dist/components/core/DotSeparator/DotSeparator.theme.js +10 -0
- package/dist/components/core/DotSeparator/DotSeparator.types.d.ts +25 -0
- package/dist/components/core/DotSeparator/index.d.ts +3 -0
- package/dist/components/core/Dropdown/Dropdown.theme.js +2 -3
- package/dist/components/core/Dropdown/DropdownItem.js +1 -1
- package/dist/components/core/Dropdown/DropdownMenu.js +1 -1
- package/dist/components/core/MenuItem/MenuItem.js +5 -2
- package/dist/components/core/MenuItem/MenuItem.theme.d.ts +6 -0
- package/dist/components/core/MenuItem/MenuItem.theme.js +19 -16
- package/dist/components/core/MenuItem/MenuItem.types.d.ts +2 -0
- package/dist/components/core/NavItem/NavItem.js +20 -4
- package/dist/components/core/NavItem/NavItem.theme.js +13 -2
- package/dist/components/core/Popover/Popover.types.d.ts +6 -2
- package/dist/components/core/Popover/PopoverBody.js +10 -3
- package/dist/components/core/Segmented/Segmented.theme.js +1 -1
- package/dist/components/core/Sidebar/Sidebar.d.ts +2 -0
- package/dist/components/core/Sidebar/Sidebar.js +15 -7
- package/dist/components/core/Sidebar/Sidebar.types.d.ts +92 -4
- package/dist/components/core/Sidebar/SidebarCard.d.ts +25 -0
- package/dist/components/core/Sidebar/SidebarCard.js +68 -0
- package/dist/components/core/Sidebar/SidebarCard.theme.d.ts +8 -0
- package/dist/components/core/Sidebar/SidebarCard.theme.js +18 -0
- package/dist/components/core/Sidebar/SidebarContent.js +5 -1
- package/dist/components/core/Sidebar/SidebarContext.js +1 -1
- package/dist/components/core/Sidebar/SidebarHeader.js +10 -2
- package/dist/components/core/Sidebar/SidebarLogo.js +38 -3
- package/dist/components/core/Sidebar/SidebarSearch.d.ts +22 -0
- package/dist/components/core/Sidebar/SidebarSearch.js +135 -0
- package/dist/components/core/Sidebar/SidebarToggle.js +1 -1
- package/dist/components/core/Sidebar/SidebarUserProfile.js +2 -2
- package/dist/components/core/Sidebar/index.d.ts +3 -1
- package/dist/components/core/Tag/Tag.js +29 -5
- package/dist/components/core/Tag/Tag.theme.js +13 -8
- package/dist/components/core/Tag/Tag.types.d.ts +7 -0
- package/dist/components/core/Tooltip/Tooltip.js +1 -1
- package/dist/components/core/Tooltip/Tooltip.theme.js +1 -2
- package/dist/components/core/index.d.ts +1 -0
- package/dist/components/core/index.js +4 -0
- package/dist/components/data-display/GanttChart/GanttChart.d.ts +1 -1
- package/dist/components/data-display/GanttChart/GanttChart.js +31 -4
- package/dist/components/data-display/GanttChart/GanttChart.theme.js +19 -17
- package/dist/components/data-display/GanttChart/GanttChart.types.d.ts +19 -0
- package/dist/components/data-display/GanttChart/GanttChart.utils.js +1 -1
- package/dist/components/data-display/GanttChart/GanttChartPanel.d.ts +1 -1
- package/dist/components/data-display/GanttChart/GanttChartPanel.js +3 -3
- package/dist/components/data-display/GanttChart/GanttDependencyArrows.js +7 -4
- package/dist/components/data-display/GanttChart/GanttMilestone.js +5 -5
- package/dist/components/data-display/GanttChart/GanttTablePanel.js +1 -1
- package/dist/components/data-display/GanttChart/GanttTableTaskRow.js +2 -2
- package/dist/components/data-display/GanttChart/GanttTaskBar.js +37 -16
- package/dist/components/data-display/GanttChart/GanttTimelineGrid.js +2 -1
- package/dist/components/data-display/GanttChart/GanttTimelineHeader.js +35 -11
- package/dist/components/data-display/GanttChart/GanttToolbar.js +2 -2
- package/dist/components/data-display/GanttChart/hooks/useGanttDrag.js +3 -2
- package/dist/components/data-display/GanttChart/index.d.ts +1 -1
- package/dist/components/data-display/Table/Table.theme.js +3 -5
- package/dist/components/effects/Aurora/Aurora.d.ts +6 -17
- package/dist/components/effects/Aurora/Aurora.js +297 -131
- package/dist/components/effects/Aurora/Aurora.types.d.ts +6 -0
- package/dist/components/forms/Combobox/Combobox.js +1 -1
- package/dist/components/forms/Combobox/Combobox.theme.js +2 -4
- package/dist/components/forms/CronInput/CronInput.js +1 -1
- package/dist/components/forms/CronInput/CronInput.theme.js +14 -23
- package/dist/components/forms/DatePicker/DatePicker.theme.js +11 -18
- package/dist/components/forms/DatePicker/DatePickerTrigger.js +1 -1
- package/dist/components/forms/DateRangePicker/DateRangePicker.theme.js +6 -13
- package/dist/components/forms/DateRangePicker/DateRangePickerTrigger.js +1 -1
- package/dist/components/forms/FileUpload/FileUpload.animations.d.ts +29 -0
- package/dist/components/forms/FileUpload/FileUpload.animations.js +19 -0
- package/dist/components/forms/FileUpload/FileUpload.js +87 -48
- package/dist/components/forms/FileUpload/FileUpload.theme.d.ts +2 -10
- package/dist/components/forms/FileUpload/FileUpload.theme.js +16 -30
- package/dist/components/forms/FileUpload/FileUpload.types.d.ts +26 -10
- package/dist/components/forms/Input/Input.theme.js +13 -10
- package/dist/components/forms/InputCounter/InputCounter.theme.js +1 -1
- package/dist/components/forms/Mention/Mention.js +152 -57
- package/dist/components/forms/Mention/Mention.theme.js +16 -23
- package/dist/components/forms/Mention/Mention.types.d.ts +12 -12
- package/dist/components/forms/Mention/Mention.utils.js +32 -4
- package/dist/components/forms/RichTextEditor/RichTextEditor.js +3 -3
- package/dist/components/forms/RichTextEditor/RichTextEditor.theme.js +5 -5
- package/dist/components/forms/Select/Select.js +2 -2
- package/dist/components/forms/Select/Select.theme.js +3 -3
- package/dist/components/forms/TimePicker/TimePickerContent.js +3 -0
- package/dist/components/forms/TimePicker/TimePickerTrigger.js +1 -1
- package/dist/components/forms/forms.theme.js +21 -16
- package/dist/components/forms/index.js +3 -0
- package/dist/components/layout/AppShell/AppShell.d.ts +10 -0
- package/dist/components/layout/AppShell/AppShell.js +84 -0
- package/dist/components/layout/AppShell/AppShell.theme.d.ts +3 -0
- package/dist/components/layout/AppShell/AppShell.theme.js +42 -0
- package/dist/components/layout/AppShell/AppShell.types.d.ts +127 -0
- package/dist/components/layout/AppShell/AppShellContext.d.ts +14 -0
- package/dist/components/layout/AppShell/AppShellContext.js +19 -0
- package/dist/components/layout/AppShell/AppShellFooter.d.ts +3 -0
- package/dist/components/layout/AppShell/AppShellFooter.js +12 -0
- package/dist/components/layout/AppShell/AppShellHeader.d.ts +3 -0
- package/dist/components/layout/AppShell/AppShellHeader.js +12 -0
- package/dist/components/layout/AppShell/AppShellMain.d.ts +3 -0
- package/dist/components/layout/AppShell/AppShellMain.js +19 -0
- package/dist/components/layout/AppShell/AppShellRightPanel.d.ts +3 -0
- package/dist/components/layout/AppShell/AppShellRightPanel.js +16 -0
- package/dist/components/layout/AppShell/AppShellSidebar.d.ts +3 -0
- package/dist/components/layout/AppShell/AppShellSidebar.js +16 -0
- package/dist/components/layout/AppShell/AppShellTopbar.d.ts +3 -0
- package/dist/components/layout/AppShell/AppShellTopbar.js +12 -0
- package/dist/components/layout/AppShell/index.d.ts +3 -0
- package/dist/components/layout/FormLayout/FormLayout.js +3 -0
- package/dist/components/layout/index.d.ts +1 -0
- package/dist/components/layout/index.js +2 -0
- package/dist/hooks/useSelectPortal.d.ts +10 -2
- package/dist/hooks/useSelectPortal.js +45 -24
- package/dist/index.js +6 -0
- package/dist/registry.json +10021 -0
- package/dist/styles.css +1 -1
- package/dist/utils/dateUtils.js +11 -1
- package/package.json +4 -2
- package/src/global.scss +29 -8
- 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,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,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,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,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,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';
|
|
@@ -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
|
|
173
|
-
//
|
|
174
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
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
|
|
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';
|