@flikk/ui 1.0.0-beta.25 → 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/CodeBlock/CodeBlock.theme.js +2 -2
- package/dist/components/ai/PromptInput/PromptInput.js +4 -0
- package/dist/components/ai/PromptInput/VoiceRecorder.js +4 -0
- package/dist/components/ai/StreamingResponse/MarkdownRenderer.js +1 -1
- package/dist/components/ai/TokenCounter/TokenCounter.theme.js +1 -1
- package/dist/components/charts/BarChart/BarChart.js +2 -2
- package/dist/components/charts/StackedBarChart/StackedBarChart.js +1 -1
- package/dist/components/charts/shared/BarRenderer/BarRenderer.js +2 -2
- package/dist/components/core/Breadcrumbs/Breadcrumbs.theme.js +1 -1
- package/dist/components/core/Button/Button.js +1 -1
- package/dist/components/core/Button/Button.theme.js +5 -5
- package/dist/components/core/Calendar/Calendar.theme.js +1 -1
- package/dist/components/core/Calendar/CalendarMini/CalendarMini.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/Drawer/Drawer.theme.js +2 -2
- package/dist/components/core/Dropdown/Dropdown.theme.js +4 -5
- package/dist/components/core/Dropdown/DropdownItem.js +1 -1
- package/dist/components/core/Dropdown/DropdownMenu.js +1 -1
- package/dist/components/core/Empty/Empty.js +1 -1
- package/dist/components/core/ImagePlaceholder/ImagePlaceholder.d.ts +14 -0
- package/dist/components/core/ImagePlaceholder/ImagePlaceholder.js +28 -0
- package/dist/components/core/ImagePlaceholder/ImagePlaceholder.theme.d.ts +6 -0
- package/dist/components/core/ImagePlaceholder/ImagePlaceholder.theme.js +8 -0
- package/dist/components/core/ImagePlaceholder/ImagePlaceholder.types.d.ts +32 -0
- package/dist/components/core/ImagePlaceholder/index.d.ts +2 -0
- 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/Message/Message.theme.js +1 -1
- package/dist/components/core/Modal/Modal.theme.js +1 -1
- package/dist/components/core/NavItem/NavItem.d.ts +1 -1
- package/dist/components/core/NavItem/NavItem.js +187 -68
- package/dist/components/core/NavItem/NavItem.theme.js +31 -12
- package/dist/components/core/NavItem/NavItem.types.d.ts +17 -39
- package/dist/components/core/Pagination/Pagination.theme.js +3 -3
- package/dist/components/core/Popover/Popover.theme.js +1 -1
- package/dist/components/core/Popover/Popover.types.d.ts +6 -2
- package/dist/components/core/Popover/PopoverBody.js +10 -3
- package/dist/components/core/Progress/Progress.theme.js +1 -1
- package/dist/components/core/ScrollArea/ScrollArea.js +2 -2
- package/dist/components/core/ScrollArea/ScrollArea.theme.js +1 -1
- package/dist/components/core/Segmented/Segmented.js +8 -6
- package/dist/components/core/Segmented/Segmented.theme.js +3 -3
- package/dist/components/core/Sidebar/Sidebar.d.ts +3 -1
- package/dist/components/core/Sidebar/Sidebar.js +53 -16
- package/dist/components/core/Sidebar/Sidebar.theme.js +5 -7
- package/dist/components/core/Sidebar/Sidebar.types.d.ts +125 -8
- 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 +10 -6
- package/dist/components/core/Sidebar/SidebarContext.d.ts +17 -16
- package/dist/components/core/Sidebar/SidebarContext.js +43 -20
- package/dist/components/core/Sidebar/SidebarFooter.js +4 -6
- package/dist/components/core/Sidebar/SidebarHeader.js +12 -9
- package/dist/components/core/Sidebar/SidebarLogo.js +39 -8
- package/dist/components/core/Sidebar/SidebarNav.js +4 -3
- package/dist/components/core/Sidebar/SidebarNavGroup.js +4 -7
- 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 +6 -1
- package/dist/components/core/Sidebar/SidebarUserProfile.js +33 -17
- package/dist/components/core/Sidebar/index.d.ts +4 -3
- package/dist/components/core/Skeleton/Skeleton.theme.js +1 -1
- package/dist/components/core/Spinner/Spinner.theme.js +1 -1
- package/dist/components/core/Tabs/Tabs.js +6 -1
- package/dist/components/core/Tabs/Tabs.types.d.ts +2 -0
- package/dist/components/core/Tabs/TabsBody.js +5 -3
- package/dist/components/core/Tag/Tag.js +29 -5
- package/dist/components/core/Tag/Tag.theme.js +14 -9
- 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 +2 -0
- package/dist/components/core/index.js +6 -2
- 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/GanttTableGroupRow.js +1 -1
- 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/KPI/KPI.js +13 -3
- package/dist/components/data-display/KPI/KPI.theme.js +3 -3
- package/dist/components/data-display/Metric/Metric.theme.js +3 -3
- package/dist/components/data-display/Table/Table.js +4 -3
- package/dist/components/data-display/Table/Table.theme.js +14 -6
- package/dist/components/data-display/Table/Table.types.d.ts +15 -0
- package/dist/components/data-display/Table/TableColumnManager.js +1 -1
- package/dist/components/data-display/Table/index.d.ts +2 -2
- package/dist/components/effects/Aurora/Aurora.d.ts +6 -17
- package/dist/components/effects/Aurora/Aurora.js +310 -105
- package/dist/components/effects/Aurora/Aurora.types.d.ts +6 -0
- package/dist/components/effects/InteractiveCharacters/InteractiveCharacters.js +3 -3
- package/dist/components/effects/InteractiveCharacters/characters/BlobCharacter.js +13 -4
- package/dist/components/effects/InteractiveCharacters/characters/SmallCharacter.js +13 -4
- package/dist/components/effects/InteractiveCharacters/characters/TallCharacter.js +14 -4
- package/dist/components/effects/MorphingText/MorphingText.js +40 -7
- package/dist/components/effects/StripePattern/StripePattern.d.ts +18 -0
- package/dist/components/effects/StripePattern/StripePattern.js +54 -0
- package/dist/components/effects/StripePattern/StripePattern.types.d.ts +53 -0
- package/dist/components/effects/StripePattern/index.d.ts +2 -0
- package/dist/components/effects/index.d.ts +2 -0
- package/dist/components/effects/index.js +1 -0
- package/dist/components/forms/Checkbox/Checkbox.theme.js +1 -1
- 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 +22 -31
- 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 +7 -14
- 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 +88 -49
- 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/FileUpload/FileUploadProgress.js +27 -20
- package/dist/components/forms/FileUpload/FileUploadProgress.theme.js +2 -2
- package/dist/components/forms/Input/Input.theme.js +16 -15
- 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/Radio/Radio.theme.js +1 -1
- package/dist/components/forms/RichTextEditor/RichTextEditor.d.ts +18 -0
- package/dist/components/forms/RichTextEditor/RichTextEditor.js +1231 -236
- package/dist/components/forms/RichTextEditor/RichTextEditor.theme.d.ts +53 -1
- package/dist/components/forms/RichTextEditor/RichTextEditor.theme.js +99 -25
- package/dist/components/forms/RichTextEditor/RichTextEditor.types.d.ts +42 -3
- package/dist/components/forms/RichTextEditor/index.d.ts +2 -2
- package/dist/components/forms/Select/Select.js +2 -2
- package/dist/components/forms/Select/Select.theme.js +3 -3
- package/dist/components/forms/Slider/Slider.theme.js +1 -1
- package/dist/components/forms/Switch/Switch.theme.js +1 -1
- package/dist/components/forms/TimePicker/TimePicker.theme.js +2 -2
- package/dist/components/forms/TimePicker/TimePickerContent.js +4 -0
- package/dist/components/forms/TimePicker/TimePickerTrigger.js +1 -1
- package/dist/components/forms/forms.theme.js +24 -19
- package/dist/components/forms/index.js +4 -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 +9 -4
- package/dist/components/layout/FormLayout/FormLayout.types.d.ts +3 -3
- package/dist/components/layout/FormLayout/FormLayoutSection.js +6 -1
- package/dist/components/layout/PageLayout/PageLayout.d.ts +2 -2
- package/dist/components/layout/PageLayout/PageLayout.js +23 -5
- package/dist/components/layout/PageLayout/PageLayout.theme.d.ts +2 -1
- package/dist/components/layout/PageLayout/PageLayout.theme.js +35 -6
- package/dist/components/layout/PageLayout/PageLayout.types.d.ts +45 -0
- package/dist/components/layout/PageLayout/PageLayoutContent.js +6 -4
- package/dist/components/layout/PageLayout/PageLayoutHeader.js +3 -3
- package/dist/components/layout/PageLayout/PageLayoutSidebar.js +5 -3
- package/dist/components/layout/PageLayout/index.d.ts +1 -1
- 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 +8 -2
- 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 +174 -100
- package/dist/components/core/Sidebar/SidebarSubmenu.d.ts +0 -7
- package/dist/components/core/Sidebar/SidebarSubmenu.js +0 -12
|
@@ -2,15 +2,12 @@ import { jsxs, jsx } from 'react/jsx-runtime';
|
|
|
2
2
|
import React__default from 'react';
|
|
3
3
|
import { cn } from '../../../utils/cn.js';
|
|
4
4
|
import { AnimatePresence, motion } from 'motion/react';
|
|
5
|
-
import {
|
|
5
|
+
import { useSidebarCollapsed } from './SidebarContext.js';
|
|
6
6
|
|
|
7
7
|
const SidebarNavGroup = React__default.forwardRef(({ title, showTitleWhenCollapsed = false, children, className, ...props }, ref) => {
|
|
8
|
-
const
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
const isCollapsedView = collapsed && !isMobile;
|
|
12
|
-
const showTitle = title && (!isCollapsedView || showTitleWhenCollapsed);
|
|
13
|
-
return (jsxs("div", { ref: ref, className: cn("space-y-1", className), ...props, children: [jsx(AnimatePresence, { initial: false, children: showTitle && (jsx(motion.div, { initial: { opacity: 0, height: 0 }, animate: { opacity: 1, height: "auto" }, exit: { opacity: 0, height: 0 }, transition: { duration: 0.15, ease: "easeInOut" }, className: "overflow-hidden", children: jsx("div", { className: "px-2 py-1", children: jsx("h3", { className: "text-xs font-semibold text-[var(--color-text-muted)] uppercase tracking-wider", children: title }) }) }, "title")) }), jsx(AnimatePresence, { initial: false, children: isCollapsedView && !showTitleWhenCollapsed && (jsx(motion.div, { initial: { opacity: 0 }, animate: { opacity: 1 }, exit: { opacity: 0 }, transition: { duration: 0.15 }, className: "h-px bg-[var(--color-border)] mx-2 my-1" }, "sep")) }), jsx("div", { className: "space-y-1", children: children })] }));
|
|
8
|
+
const { isCollapsedView } = useSidebarCollapsed();
|
|
9
|
+
const showTitleText = title && (!isCollapsedView || showTitleWhenCollapsed);
|
|
10
|
+
return (jsxs("div", { ref: ref, className: cn("space-y-1", className), ...props, children: [title && (jsx("div", { className: "h-6 flex items-center relative overflow-hidden", children: jsx(AnimatePresence, { initial: false, children: showTitleText ? (jsx(motion.div, { initial: { opacity: 0, x: -4 }, animate: { opacity: 1, x: 0 }, exit: { opacity: 0, x: -4 }, transition: { duration: 0.2, ease: [0.4, 0, 0.2, 1] }, className: "w-full px-2 py-1 absolute left-0", children: jsx("h3", { className: "text-[10px] font-bold text-[var(--color-text-muted)]/70 uppercase", children: title }) }, "title-text")) : (jsx(motion.div, { initial: { opacity: 0 }, animate: { opacity: 1 }, exit: { opacity: 0 }, transition: { duration: 0.2, ease: [0.4, 0, 0.2, 1] }, className: "w-full px-2 absolute left-0", children: jsx("div", { className: "h-px bg-[var(--color-border)] w-full" }) }, "title-separator")) }) })), jsx("div", { className: "space-y-1", children: children })] }));
|
|
14
11
|
});
|
|
15
12
|
SidebarNavGroup.displayName = "SidebarNavGroup";
|
|
16
13
|
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { SidebarSearchProps } from "./Sidebar.types";
|
|
3
|
+
/**
|
|
4
|
+
* Optional search field for the Sidebar. Emits the typed query via `onChange`
|
|
5
|
+
* (or via the controlled `value` prop) — does NOT filter the Sidebar tree itself.
|
|
6
|
+
* Consumers wire `onChange` to whatever surfaces results (popover, command palette,
|
|
7
|
+
* side panel, route, …) so the Sidebar stays visually clean.
|
|
8
|
+
*
|
|
9
|
+
* The collapse animation mirrors NavItem (single rendered structure across both
|
|
10
|
+
* states, icon always present in a fixed flex slot, the expanded content
|
|
11
|
+
* animates in/out via AnimatePresence). The field's border + surface fill fade
|
|
12
|
+
* out via a CSS transition so the collapsed rail just shows the icon — same
|
|
13
|
+
* look as the NavItem rows above it. Click the icon to expand the sidebar and
|
|
14
|
+
* focus the input. Opt out of the collapsed affordance with `hideWhenCollapsed`.
|
|
15
|
+
*
|
|
16
|
+
* Implementation note: this uses a small inline field instead of the shared
|
|
17
|
+
* `<Input>` so the icon + animated input can be siblings under one wrapper
|
|
18
|
+
* (Input's internal layout wouldn't permit the NavItem-style animation). The
|
|
19
|
+
* border/focus styling matches `formsBaseTheme.inputGroupBaseStyle` (inset
|
|
20
|
+
* box-shadow + ring) so it reads as a normal form control when expanded.
|
|
21
|
+
*/
|
|
22
|
+
export declare const SidebarSearch: React.ForwardRefExoticComponent<SidebarSearchProps & React.RefAttributes<HTMLInputElement>>;
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
+
import React__default, { useState, useRef, useEffect } from 'react';
|
|
3
|
+
import { motion, AnimatePresence } from 'motion/react';
|
|
4
|
+
import { MagnifyingGlassIcon } from '@heroicons/react/24/outline';
|
|
5
|
+
import { cn } from '../../../utils/cn.js';
|
|
6
|
+
import { Tooltip } from '../Tooltip/Tooltip.js';
|
|
7
|
+
import '../Tooltip/Tooltip.animations.js';
|
|
8
|
+
import { useSidebarContext, useSidebarCollapsed } from './SidebarContext.js';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Optional search field for the Sidebar. Emits the typed query via `onChange`
|
|
12
|
+
* (or via the controlled `value` prop) — does NOT filter the Sidebar tree itself.
|
|
13
|
+
* Consumers wire `onChange` to whatever surfaces results (popover, command palette,
|
|
14
|
+
* side panel, route, …) so the Sidebar stays visually clean.
|
|
15
|
+
*
|
|
16
|
+
* The collapse animation mirrors NavItem (single rendered structure across both
|
|
17
|
+
* states, icon always present in a fixed flex slot, the expanded content
|
|
18
|
+
* animates in/out via AnimatePresence). The field's border + surface fill fade
|
|
19
|
+
* out via a CSS transition so the collapsed rail just shows the icon — same
|
|
20
|
+
* look as the NavItem rows above it. Click the icon to expand the sidebar and
|
|
21
|
+
* focus the input. Opt out of the collapsed affordance with `hideWhenCollapsed`.
|
|
22
|
+
*
|
|
23
|
+
* Implementation note: this uses a small inline field instead of the shared
|
|
24
|
+
* `<Input>` so the icon + animated input can be siblings under one wrapper
|
|
25
|
+
* (Input's internal layout wouldn't permit the NavItem-style animation). The
|
|
26
|
+
* border/focus styling matches `formsBaseTheme.inputGroupBaseStyle` (inset
|
|
27
|
+
* box-shadow + ring) so it reads as a normal form control when expanded.
|
|
28
|
+
*/
|
|
29
|
+
const SidebarSearch = React__default.forwardRef(({ value: controlledValue, defaultValue = "", onChange, placeholder = "Search…", size = "md", iconStart, collapsedLabel = "Search", hideWhenCollapsed = false, className, inputGroupClassName, ...props }, ref) => {
|
|
30
|
+
const context = useSidebarContext();
|
|
31
|
+
const { isCollapsedView } = useSidebarCollapsed();
|
|
32
|
+
const isControlled = controlledValue !== undefined;
|
|
33
|
+
const [internalValue, setInternalValue] = useState(defaultValue);
|
|
34
|
+
const value = isControlled ? controlledValue : internalValue;
|
|
35
|
+
// Compose the user's forwarded ref with our local ref so we can focus
|
|
36
|
+
// the input after the rail expands.
|
|
37
|
+
const inputRef = useRef(null);
|
|
38
|
+
const setInputRef = (el) => {
|
|
39
|
+
inputRef.current = el;
|
|
40
|
+
if (typeof ref === "function")
|
|
41
|
+
ref(el);
|
|
42
|
+
else if (ref)
|
|
43
|
+
ref.current = el;
|
|
44
|
+
};
|
|
45
|
+
// Focus the input on the frame *after* collapse→expand transitions, but only
|
|
46
|
+
// when the user triggered it from the icon click (not e.g. via Sidebar.Toggle,
|
|
47
|
+
// where stealing focus would be surprising).
|
|
48
|
+
const pendingFocusRef = useRef(false);
|
|
49
|
+
const wasCollapsedRef = useRef(isCollapsedView);
|
|
50
|
+
useEffect(() => {
|
|
51
|
+
if (wasCollapsedRef.current && !isCollapsedView && pendingFocusRef.current) {
|
|
52
|
+
const id = requestAnimationFrame(() => { var _a; return (_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.focus(); });
|
|
53
|
+
pendingFocusRef.current = false;
|
|
54
|
+
wasCollapsedRef.current = isCollapsedView;
|
|
55
|
+
return () => cancelAnimationFrame(id);
|
|
56
|
+
}
|
|
57
|
+
wasCollapsedRef.current = isCollapsedView;
|
|
58
|
+
}, [isCollapsedView]);
|
|
59
|
+
const handleChange = (e) => {
|
|
60
|
+
const next = e.target.value;
|
|
61
|
+
if (!isControlled)
|
|
62
|
+
setInternalValue(next);
|
|
63
|
+
onChange === null || onChange === void 0 ? void 0 : onChange(next);
|
|
64
|
+
};
|
|
65
|
+
const handleExpand = () => {
|
|
66
|
+
if (!isCollapsedView)
|
|
67
|
+
return;
|
|
68
|
+
pendingFocusRef.current = true;
|
|
69
|
+
context === null || context === void 0 ? void 0 : context.setCollapsed(false);
|
|
70
|
+
};
|
|
71
|
+
const handleKeyDown = (e) => {
|
|
72
|
+
if (!isCollapsedView)
|
|
73
|
+
return;
|
|
74
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
75
|
+
e.preventDefault();
|
|
76
|
+
handleExpand();
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
if (isCollapsedView && hideWhenCollapsed)
|
|
80
|
+
return null;
|
|
81
|
+
// Form-field shell — same inset-shadow border + focus ring as the shared
|
|
82
|
+
// forms.theme.ts (inputGroupBaseStyle), kept in sync intentionally. CSS
|
|
83
|
+
// transitions on background + box-shadow let the field fade out cleanly
|
|
84
|
+
// as the rail collapses; AnimatePresence handles the input itself.
|
|
85
|
+
const shellExpanded = "bg-[var(--color-surface)] shadow-[inset_0_0_0_1px_var(--color-border)] " +
|
|
86
|
+
"focus-within:shadow-[inset_0_0_0_1px_var(--color-primary-600)] " +
|
|
87
|
+
"focus-within:ring-4 focus-within:ring-[var(--color-primary)]/10 " +
|
|
88
|
+
"not-focus-within:hover:shadow-[inset_0_0_0_1px_var(--color-border-secondary)] " +
|
|
89
|
+
"dark:focus-within:shadow-[inset_0_0_0_1px_var(--color-primary-500)] dark:focus-within:ring-[var(--color-primary-500)]/20";
|
|
90
|
+
// Collapsed: keep the surface fill so the icon reads as a search "button"
|
|
91
|
+
// (not a transparent row). Hover lifts to surface-hover.
|
|
92
|
+
const shellCollapsed = "bg-[var(--color-surface)] shadow-[inset_0_0_0_0_transparent] " +
|
|
93
|
+
"hover:bg-[var(--color-surface-hover)] cursor-pointer";
|
|
94
|
+
const tooltipPlacement = (context === null || context === void 0 ? void 0 : context.side) === "right" ? "left" : "right";
|
|
95
|
+
const field = (jsxs(motion.div, { role: isCollapsedView ? "button" : undefined, tabIndex: isCollapsedView ? 0 : undefined, "aria-label": isCollapsedView ? collapsedLabel : undefined, onClick: isCollapsedView ? handleExpand : undefined, onKeyDown: handleKeyDown, className: cn("relative flex items-center rounded-[var(--form-radius)]",
|
|
96
|
+
// 36px (h-9) in BOTH states so the search row sits at the exact
|
|
97
|
+
// same height as the NavItem rows below it — same look expanded,
|
|
98
|
+
// same 36×36 square collapsed. `size` prop is currently a no-op
|
|
99
|
+
// for height; kept on the API surface for forward compatibility.
|
|
100
|
+
"h-9",
|
|
101
|
+
// NOTE: do NOT toggle `justify-center` between states. Combined
|
|
102
|
+
// with the icon span's constant `pl-2`, the icon sits at the same
|
|
103
|
+
// field-x (8) in both states, so the *only* thing that animates
|
|
104
|
+
// on collapse/expand is the field width (via sidebar's motion
|
|
105
|
+
// width) and the input fading in/out via AnimatePresence. Adding
|
|
106
|
+
// a justify-* toggle here would snap the icon by 4px on frame 0
|
|
107
|
+
// of every transition.
|
|
108
|
+
"transition-[background-color,box-shadow] duration-200 ease-[cubic-bezier(0.4,0,0.2,1)]", "overflow-hidden", isCollapsedView ? shellCollapsed : shellExpanded, inputGroupClassName), children: [jsx("span", { className: cn("flex items-center justify-center flex-shrink-0 pl-2", "text-[var(--color-text-muted)] transition-colors duration-200"), "aria-hidden": !isCollapsedView || undefined, children: iconStart !== null && iconStart !== void 0 ? iconStart : jsx(MagnifyingGlassIcon, { className: "size-5" }) }), jsx(AnimatePresence, { initial: false, children: !isCollapsedView && (jsx(motion.div, { initial: { opacity: 0, x: -4 }, animate: { opacity: 1, x: 0 }, exit: { opacity: 0, x: -4 }, transition: {
|
|
109
|
+
opacity: { duration: 0.15, ease: [0.4, 0, 0.2, 1] },
|
|
110
|
+
x: { duration: 0.2, ease: [0.4, 0, 0.2, 1] },
|
|
111
|
+
}, className: "flex-1 min-w-0 flex items-center overflow-hidden", children: jsx("input", { ref: setInputRef, type: "search", value: value, onChange: handleChange, placeholder: placeholder, "aria-label": collapsedLabel, className: cn(
|
|
112
|
+
// Icon span pl-2 (8) + icon size-5 (20) = field-x 8-28.
|
|
113
|
+
// Input pl-3 (12) → text starts at field-x = 28 + 12 = 40,
|
|
114
|
+
// giving a 12px icon→text gap (matches <Input iconStart>'s
|
|
115
|
+
// pl-3 + pl-10 = 12px convention).
|
|
116
|
+
"w-full bg-transparent border-0 outline-none text-sm py-2 pl-3 pr-3", "text-[var(--color-text-primary)] placeholder:text-[var(--color-text-placeholder)]", "dark:placeholder:text-[var(--color-neutral-500)]") }) }, "search-input")) })] }));
|
|
117
|
+
return (
|
|
118
|
+
// Outer horizontal padding mirrors Sidebar.Content (px-3 collapsed,
|
|
119
|
+
// px-2.5 expanded) so the search row sits on the exact same horizontal
|
|
120
|
+
// track as the NavItem rows below it — both have a 36px interior on
|
|
121
|
+
// the 60px collapsed rail, producing identical 36×36 hit-areas.
|
|
122
|
+
jsx("div", { className: cn(
|
|
123
|
+
// py-1 keeps the search row in the same vertical rhythm as the
|
|
124
|
+
// NavGroup's `space-y-1` between nav rows.
|
|
125
|
+
"py-1 transition-[padding] duration-200 ease-[cubic-bezier(0.4,0,0.2,1)]", isCollapsedView ? "px-3" : "px-2.5", className), ...props, children: isCollapsedView ? (
|
|
126
|
+
// `triggerClassName="block w-full"` makes the Tooltip's wrapping div
|
|
127
|
+
// a full-width block instead of its default `inline-block` — without
|
|
128
|
+
// this, the field collapses to icon-width and sits left-aligned,
|
|
129
|
+
// leaving empty space on the right of the rail. Same fix NavItem
|
|
130
|
+
// uses for its collapsed-mode tooltip wrapper.
|
|
131
|
+
jsx(Tooltip, { content: collapsedLabel, placement: tooltipPlacement, triggerClassName: "block w-full", children: field })) : (field) }));
|
|
132
|
+
});
|
|
133
|
+
SidebarSearch.displayName = "SidebarSearch";
|
|
134
|
+
|
|
135
|
+
export { SidebarSearch };
|
|
@@ -7,6 +7,7 @@ import { useSidebarContext } from './SidebarContext.js';
|
|
|
7
7
|
import { Button } from '../Button/Button.js';
|
|
8
8
|
|
|
9
9
|
const SidebarToggle = React__default.forwardRef(({ expandIcon, collapseIcon, className, onClick, ...props }, ref) => {
|
|
10
|
+
var _a;
|
|
10
11
|
const sidebarContext = useSidebarContext();
|
|
11
12
|
if (!sidebarContext) {
|
|
12
13
|
if (process.env.NODE_ENV !== "production") {
|
|
@@ -20,7 +21,11 @@ const SidebarToggle = React__default.forwardRef(({ expandIcon, collapseIcon, cla
|
|
|
20
21
|
onClick === null || onClick === void 0 ? void 0 : onClick(e);
|
|
21
22
|
};
|
|
22
23
|
const { onAnimationStart, onAnimationEnd, onDrag, onDragStart, onDragEnd, color: _color, ...buttonProps } = props;
|
|
23
|
-
|
|
24
|
+
const side = (_a = sidebarContext.side) !== null && _a !== void 0 ? _a : "left";
|
|
25
|
+
const positionClasses = side === "left"
|
|
26
|
+
? "absolute right-0 translate-x-1/2 top-4 z-50"
|
|
27
|
+
: "absolute left-0 -translate-x-1/2 top-4 z-50";
|
|
28
|
+
return (jsx(Button, { ref: ref, iconOnly: true, variant: "ghost", className: cn("size-6 p-0 rounded-full border border-[var(--color-border)] bg-[var(--color-background)]/50 backdrop-blur-sm text-[var(--color-text-muted)] hover:text-[var(--color-text-secondary)] hover:shadow-md hover:bg-[var(--color-surface-hover)] opacity-100 transition-all duration-400", positionClasses, className), onClick: handleClick, "aria-label": collapsed ? "Expand sidebar" : "Collapse sidebar", title: collapsed ? "Expand sidebar" : "Collapse sidebar", ...buttonProps, children: jsx(motion.div, { initial: false, animate: { rotate: collapsed ? 180 : 0 }, transition: { duration: 0.2, ease: [0.4, 0, 0.2, 1] }, className: "flex items-center justify-center", children: jsx(ChevronLeftIcon, { className: "size-3", strokeWidth: 2.5 }) }) }));
|
|
24
29
|
});
|
|
25
30
|
SidebarToggle.displayName = "SidebarToggle";
|
|
26
31
|
|
|
@@ -1,30 +1,46 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
2
2
|
import React__default from 'react';
|
|
3
|
+
import { ChevronUpDownIcon } from '@heroicons/react/20/solid';
|
|
3
4
|
import { cn } from '../../../utils/cn.js';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
5
|
+
import { motion, AnimatePresence } from 'motion/react';
|
|
6
|
+
import { useSidebarCollapsed } from './SidebarContext.js';
|
|
6
7
|
import { Avatar } from '../Avatar/Avatar.js';
|
|
7
8
|
import { Tooltip } from '../Tooltip/Tooltip.js';
|
|
8
9
|
import '../Tooltip/Tooltip.animations.js';
|
|
10
|
+
import { Dropdown } from '../Dropdown/Dropdown.js';
|
|
11
|
+
import '../Dropdown/DropdownTrigger.js';
|
|
12
|
+
import '../Dropdown/DropdownMenu.js';
|
|
13
|
+
import '../Dropdown/DropdownItem.js';
|
|
14
|
+
import '../Dropdown/DropdownSection.js';
|
|
15
|
+
import '../Dropdown/DropdownSeparator.js';
|
|
16
|
+
import '../Dropdown/Dropdown.theme.js';
|
|
9
17
|
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
const SidebarUserProfile = React__default.forwardRef(({ name, email, avatar, status, dropdownContent, className, onClick, ...props }, ref) => {
|
|
17
|
-
const sidebarContext = useSidebarContext();
|
|
18
|
-
const collapsed = (sidebarContext === null || sidebarContext === void 0 ? void 0 : sidebarContext.collapsed) || false;
|
|
19
|
-
const isMobile = (sidebarContext === null || sidebarContext === void 0 ? void 0 : sidebarContext.isMobile) || false;
|
|
20
|
-
const isCollapsedView = collapsed && !isMobile;
|
|
21
|
-
const avatarElement = (jsxs("div", { className: "relative flex-shrink-0", children: [jsx(Avatar, { src: avatar, name: name, size: "sm" }), status && (jsx("span", { className: cn("absolute -bottom-0.5 -right-0.5 size-3 rounded-full ring-2 ring-[var(--color-background)]", statusColors[status]), "aria-label": `Status: ${status}` }))] }));
|
|
22
|
-
const content = (jsxs("div", { ref: ref, className: cn("flex items-center gap-3 rounded-[var(--radius-base)] cursor-pointer transition-colors duration-150 hover:bg-[var(--color-background-secondary)]", isCollapsedView ? "justify-center p-2" : "px-3 py-2", className), role: "button", tabIndex: 0, onClick: onClick, onKeyDown: (e) => {
|
|
18
|
+
const SidebarUserProfile = React__default.forwardRef(({ name, email, avatar, status, dropdownContent, children, className, onClick, ...props }, ref) => {
|
|
19
|
+
const { isCollapsedView } = useSidebarCollapsed();
|
|
20
|
+
// Strip drag/animation DOM handlers that collide with motion's prop types
|
|
21
|
+
const { onAnimationStart, onAnimationEnd, onDrag, onDragStart, onDragEnd, ...motionSafeProps } = props;
|
|
22
|
+
const avatarElement = (jsx(Avatar, { src: avatar, name: name, status: status !== null && status !== void 0 ? status : "none", className: "size-9" }));
|
|
23
|
+
const content = (jsxs(motion.div, { ref: ref, className: cn("flex w-full items-center rounded-[var(--radius-base)] cursor-pointer border border-transparent transition-[padding,gap,background-color,border-color,color,box-shadow] duration-200 ease-[cubic-bezier(0.4,0,0.2,1)] ", isCollapsedView ? "justify-center gap-0 px-1" : "gap-2 ", className), role: "button", tabIndex: 0, onClick: onClick, onKeyDown: (e) => {
|
|
23
24
|
if ((e.key === "Enter" || e.key === " ") && onClick) {
|
|
24
25
|
e.preventDefault();
|
|
25
26
|
e.currentTarget.click();
|
|
26
27
|
}
|
|
27
|
-
},
|
|
28
|
+
},
|
|
29
|
+
// whileHover={{ scale: 1.01, x: isCollapsedView ? 0 : 2 }}
|
|
30
|
+
whileTap: { scale: 0.98 }, transition: { type: "spring", stiffness: 400, damping: 25 }, ...motionSafeProps, children: [jsx(motion.div
|
|
31
|
+
// whileHover={{ scale: 1.05 }}
|
|
32
|
+
// transition={{ type: "spring", stiffness: 400, damping: 20 }}
|
|
33
|
+
, {
|
|
34
|
+
// whileHover={{ scale: 1.05 }}
|
|
35
|
+
// transition={{ type: "spring", stiffness: 400, damping: 20 }}
|
|
36
|
+
className: "flex-shrink-0", children: avatarElement }), jsx(AnimatePresence, { initial: false, children: !isCollapsedView && (jsxs(motion.div, { className: "flex flex-row items-center gap-2 flex-1 min-w-0 overflow-hidden whitespace-nowrap", initial: { opacity: 0, x: -4 }, animate: { opacity: 1, x: 0 }, exit: { opacity: 0, x: -4 }, transition: {
|
|
37
|
+
opacity: { duration: 0.15, ease: [0.4, 0, 0.2, 1] },
|
|
38
|
+
x: { duration: 0.2, ease: [0.4, 0, 0.2, 1] }
|
|
39
|
+
}, children: [children !== null && children !== void 0 ? children : (jsxs("div", { className: "flex-1 min-w-0", children: [jsx("div", { className: "text-sm font-medium text-[var(--color-text-primary)] truncate", children: name }), email && (jsx("div", { className: "text-xs text-[var(--color-text-secondary)]/80 truncate", children: email }))] })), dropdownContent && (jsx(ChevronUpDownIcon, { className: "size-4 flex-shrink-0 text-[var(--color-text-muted)]" }))] }, "profile-text")) })] }));
|
|
40
|
+
// When dropdownContent is provided, the profile acts as a menu trigger.
|
|
41
|
+
if (dropdownContent) {
|
|
42
|
+
return (jsxs(Dropdown, { placement: "right-end", offset: 8, children: [jsx(Dropdown.Trigger, { children: content }), jsx(Dropdown.Menu, { "aria-label": `${name} menu`, children: dropdownContent })] }));
|
|
43
|
+
}
|
|
28
44
|
return (jsx(Tooltip, { content: name, placement: "right", disabled: !isCollapsedView, triggerClassName: "block", children: content }));
|
|
29
45
|
});
|
|
30
46
|
SidebarUserProfile.displayName = "SidebarUserProfile";
|
|
@@ -4,10 +4,11 @@ export { SidebarContent } from "./SidebarContent";
|
|
|
4
4
|
export { SidebarFooter } from "./SidebarFooter";
|
|
5
5
|
export { SidebarNav } from "./SidebarNav";
|
|
6
6
|
export { SidebarNavGroup } from "./SidebarNavGroup";
|
|
7
|
-
export { SidebarSubmenu } from "./SidebarSubmenu";
|
|
8
7
|
export { SidebarToggle } from "./SidebarToggle";
|
|
9
8
|
export { SidebarMobileTrigger } from "./SidebarMobileTrigger";
|
|
10
9
|
export { SidebarUserProfile } from "./SidebarUserProfile";
|
|
11
10
|
export { SidebarLogo } from "./SidebarLogo";
|
|
12
|
-
export {
|
|
13
|
-
export
|
|
11
|
+
export { SidebarSearch } from "./SidebarSearch";
|
|
12
|
+
export { SidebarCard } from "./SidebarCard";
|
|
13
|
+
export { SidebarProvider, useSidebarContext } from "./SidebarContext";
|
|
14
|
+
export type { SidebarProps, SidebarHeaderProps, SidebarContentProps, SidebarFooterProps, SidebarNavProps, SidebarNavGroupProps, SidebarToggleProps, SidebarMobileTriggerProps, SidebarUserProfileProps, SidebarUserStatus, SidebarSide, SidebarVariant, SidebarDensity, SidebarContextValue, SidebarProviderProps, SidebarTheme, SidebarThemeOverrides, SidebarLogoProps, SidebarSearchProps, SidebarCardProps, SidebarCardTheme, SidebarCardThemeOverrides, } from "./Sidebar.types";
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
const skeletonTheme = {
|
|
6
6
|
// Base styles with background color and animation
|
|
7
|
-
baseStyle: "bg-[var(--color-
|
|
7
|
+
baseStyle: "bg-[var(--color-surface-sunken)] overflow-hidden",
|
|
8
8
|
// Shape variants
|
|
9
9
|
variants: {
|
|
10
10
|
text: "h-4 rounded",
|
|
@@ -15,7 +15,7 @@ const spinnerTheme = {
|
|
|
15
15
|
// Color variants
|
|
16
16
|
colors: {
|
|
17
17
|
...semanticSpinnerColors,
|
|
18
|
-
dark: "border-[var(--color-
|
|
18
|
+
dark: "border-[var(--color-surface-sunken)] border-t-transparent",
|
|
19
19
|
},
|
|
20
20
|
// Animation class with drop shadow
|
|
21
21
|
animation: "animate-[spin_1s_linear_infinite] rounded-full",
|
|
@@ -14,6 +14,9 @@ import { TabsBody } from './TabsBody.js';
|
|
|
14
14
|
*/
|
|
15
15
|
const TabsComponent = React__default.forwardRef(({ value, defaultValue, onValueChange, orientation = "horizontal", size = "md", disabled = false, children, className, darkMode = false, ...props }, ref) => {
|
|
16
16
|
const [currentValue, setCurrentValue] = useState(value || defaultValue || "");
|
|
17
|
+
// Track whether the user has switched tabs yet, so content only animates
|
|
18
|
+
// on an actual tab change and not on mount / page load.
|
|
19
|
+
const [hasSwitched, setHasSwitched] = useState(false);
|
|
17
20
|
// Unique instance prefix to scope all DOM IDs to this Tabs instance
|
|
18
21
|
const instanceId = useId();
|
|
19
22
|
// Track trigger elements for underline positioning
|
|
@@ -42,6 +45,7 @@ const TabsComponent = React__default.forwardRef(({ value, defaultValue, onValueC
|
|
|
42
45
|
// Safe value change handler with error handling
|
|
43
46
|
const handleValueChange = useCallback((newValue) => {
|
|
44
47
|
try {
|
|
48
|
+
setHasSwitched(true);
|
|
45
49
|
if (!isControlled) {
|
|
46
50
|
setCurrentValue(newValue);
|
|
47
51
|
}
|
|
@@ -71,7 +75,8 @@ const TabsComponent = React__default.forwardRef(({ value, defaultValue, onValueC
|
|
|
71
75
|
registerTrigger,
|
|
72
76
|
unregisterTrigger,
|
|
73
77
|
instanceId,
|
|
74
|
-
|
|
78
|
+
hasSwitched,
|
|
79
|
+
}), [activeValue, handleValueChange, orientation, size, disabled, registerTrigger, unregisterTrigger, instanceId, hasSwitched]);
|
|
75
80
|
// Memoize theme classes for performance
|
|
76
81
|
const themeClasses = useMemo(() => ({
|
|
77
82
|
baseStyle: tabsTheme.baseStyle,
|
|
@@ -141,4 +141,6 @@ export interface TabsContextValue {
|
|
|
141
141
|
unregisterTrigger: (value: string) => void;
|
|
142
142
|
/** Unique prefix scoping DOM IDs to this Tabs instance */
|
|
143
143
|
instanceId: string;
|
|
144
|
+
/** Whether the user has switched tabs yet (false until the first change). Used to suppress content animation on mount. */
|
|
145
|
+
hasSwitched: boolean;
|
|
144
146
|
}
|
|
@@ -10,7 +10,7 @@ import { getTabsBodyVariants } from './Tabs.animations.js';
|
|
|
10
10
|
* TabsBody component displays content panels for tabs with directional fade animations
|
|
11
11
|
*/
|
|
12
12
|
const TabsBody = React__default.forwardRef(({ value, forceMount = false, children, className, ...props }, ref) => {
|
|
13
|
-
const { value: selectedValue, orientation, instanceId } = useTabsContext();
|
|
13
|
+
const { value: selectedValue, orientation, instanceId, hasSwitched } = useTabsContext();
|
|
14
14
|
const shouldReduceMotion = useReducedMotion();
|
|
15
15
|
// Check if we're in Storybook and should disable animations
|
|
16
16
|
const isInStorybook = typeof window !== 'undefined' && window.__STORYBOOK_DISABLE_ANIMATIONS__;
|
|
@@ -32,9 +32,11 @@ const TabsBody = React__default.forwardRef(({ value, forceMount = false, childre
|
|
|
32
32
|
if (!shouldRender) {
|
|
33
33
|
return null;
|
|
34
34
|
}
|
|
35
|
-
// Determine animation props (user props will override due to spread order)
|
|
35
|
+
// Determine animation props (user props will override due to spread order).
|
|
36
|
+
// Until the user switches tabs, the panel snaps in (initial=false) so it does
|
|
37
|
+
// not animate on mount / page load — only actual tab changes animate.
|
|
36
38
|
const animationProps = shouldDisableAnimations ? {} : {
|
|
37
|
-
initial: "initial",
|
|
39
|
+
initial: hasSwitched ? "initial" : false,
|
|
38
40
|
animate: "animate",
|
|
39
41
|
exit: "exit",
|
|
40
42
|
variants: contentVariants,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
1
|
+
import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
|
|
2
2
|
import React__default from 'react';
|
|
3
3
|
import { motion } from 'motion/react';
|
|
4
4
|
import { XMarkIcon } from '@heroicons/react/24/outline';
|
|
@@ -18,7 +18,7 @@ import { tagVariants, tagLayoutTransition } from './Tag.animations.js';
|
|
|
18
18
|
* <Tag startContent={<CodeIcon className="size-4" />} onRemove={() => {}}>React</Tag>
|
|
19
19
|
* ```
|
|
20
20
|
*/
|
|
21
|
-
const Tag = React__default.forwardRef(({ children, size = "md", removable = true, onRemove, avatar, startContent, disabled = false, className, theme: customTheme, ...props }, ref) => {
|
|
21
|
+
const Tag = React__default.forwardRef(({ children, size = "md", removable = true, onRemove, avatar, startContent, disabled = false, animated = true, className, theme: customTheme, ...props }, ref) => {
|
|
22
22
|
var _a, _b, _c;
|
|
23
23
|
// Merge default theme with custom theme overrides
|
|
24
24
|
const theme = {
|
|
@@ -47,14 +47,38 @@ const Tag = React__default.forwardRef(({ children, size = "md", removable = true
|
|
|
47
47
|
// Avatar takes precedence over startContent
|
|
48
48
|
const renderLeadingContent = () => {
|
|
49
49
|
if (avatar) {
|
|
50
|
-
return (jsx("span", {
|
|
50
|
+
return (jsx("span", {
|
|
51
|
+
// leading-[0] collapses the inline line-box strut: the Avatar's
|
|
52
|
+
// inner circle is inline-flex, so a non-zero line-height adds
|
|
53
|
+
// descender space below it and pins the circle to the top of a
|
|
54
|
+
// taller line box — the visible photo then renders ~1.75px high.
|
|
55
|
+
// Zeroing the line-height makes the 16px circle define the box exactly.
|
|
56
|
+
className: cn("inline-flex items-center justify-center shrink-0 overflow-hidden rounded-full leading-[0]", theme.avatarSizes[size]), children: jsx(Avatar, { src: avatar.src, name: avatar.name, fallback: avatar.fallback, initialsCount: avatar.initialsCount, size: "xs", className: "bg-[var(--color-surface-hover)] border border-[var(--color-border)]" }) }));
|
|
51
57
|
}
|
|
52
58
|
if (startContent) {
|
|
53
|
-
return (jsx("span", {
|
|
59
|
+
return (jsx("span", {
|
|
60
|
+
// leading-[0]: same line-box collapse as the avatar wrapper above,
|
|
61
|
+
// so inline startContent (icons/emoji) stays vertically centered.
|
|
62
|
+
className: cn("inline-flex items-center justify-center shrink-0 leading-[0]", theme.startContentSizes[size]), children: startContent }));
|
|
54
63
|
}
|
|
55
64
|
return null;
|
|
56
65
|
};
|
|
57
|
-
|
|
66
|
+
const content = (jsxs(Fragment, { children: [renderLeadingContent(), children, showRemoveButton && (jsx("button", { type: "button", onClick: handleRemove, className: theme.removeButtonStyle, "aria-label": `Remove ${typeof children === "string" ? children : "tag"}`, children: jsx(XMarkIcon, { className: theme.removeIconSizes[size] }) }))] }));
|
|
67
|
+
const sharedProps = {
|
|
68
|
+
ref,
|
|
69
|
+
className: cn(theme.baseStyle, theme.sizes[size], hasLeadingContent && "pl-1", showRemoveButton && "pr-0.5", disabled && theme.disabledStyle, className),
|
|
70
|
+
"data-size": size,
|
|
71
|
+
"data-disabled": disabled ? "true" : "false",
|
|
72
|
+
"data-removable": removable ? "true" : "false",
|
|
73
|
+
"data-has-avatar": avatar ? "true" : "false",
|
|
74
|
+
...props,
|
|
75
|
+
};
|
|
76
|
+
// Plain span when animation is opted out (e.g. inside a contentEditable host,
|
|
77
|
+
// where Framer-Motion's layout FLIP fights the caret on every keystroke).
|
|
78
|
+
if (!animated) {
|
|
79
|
+
return jsx("span", { ...sharedProps, children: content });
|
|
80
|
+
}
|
|
81
|
+
return (jsx(motion.span, { ...sharedProps, layout: true, transition: tagLayoutTransition, variants: tagVariants, exit: "exit", children: content }));
|
|
58
82
|
});
|
|
59
83
|
Tag.displayName = "Tag";
|
|
60
84
|
|
|
@@ -1,22 +1,27 @@
|
|
|
1
1
|
const tagTheme = {
|
|
2
|
-
baseStyle: "inline-flex items-center gap-1 font-medium rounded-full " +
|
|
3
|
-
"bg-[var(--color-
|
|
2
|
+
baseStyle: "inline-flex items-center gap-1.5 font-medium rounded-full " +
|
|
3
|
+
"bg-[var(--color-surface-raised)] border border-[var(--color-border)] " +
|
|
4
4
|
"text-[var(--color-text-primary)]",
|
|
5
5
|
sizes: {
|
|
6
|
-
sm: "text-xs px-2
|
|
7
|
-
md: "text-sm px-2
|
|
6
|
+
sm: "text-xs px-2 py-0.5",
|
|
7
|
+
md: "text-sm px-2 py-0.5",
|
|
8
8
|
},
|
|
9
|
+
// No left margin here: the avatar/icon's left inset is owned by the tag's
|
|
10
|
+
// `pl-1` (applied when there's leading content), not by a per-size `ml-*`.
|
|
11
|
+
// Stacking `ml-*` on top of that padding pushed the avatar too far from the
|
|
12
|
+
// left edge and produced a lopsided pill. The avatar-to-text gap is handled
|
|
13
|
+
// by the base `gap-1`, not by this margin.
|
|
9
14
|
avatarSizes: {
|
|
10
|
-
sm: "size-4
|
|
11
|
-
md: "size-5
|
|
15
|
+
sm: "size-4",
|
|
16
|
+
md: "size-5",
|
|
12
17
|
},
|
|
13
18
|
startContentSizes: {
|
|
14
|
-
sm: "
|
|
15
|
-
md: "
|
|
19
|
+
sm: "",
|
|
20
|
+
md: "",
|
|
16
21
|
},
|
|
17
22
|
disabledStyle: "opacity-50 cursor-not-allowed",
|
|
18
23
|
removeButtonStyle: "inline-flex items-center justify-center rounded-full p-1 " +
|
|
19
|
-
"hover:bg-[var(--color-
|
|
24
|
+
"hover:bg-[var(--color-surface-hover)] " +
|
|
20
25
|
"text-[var(--color-text-muted)] hover:text-[var(--color-text-primary)] " +
|
|
21
26
|
"transition-all duration-300 cursor-pointer focus:outline-none " +
|
|
22
27
|
"focus-visible:ring-2 focus-visible:ring-[var(--color-primary)]",
|
|
@@ -30,6 +30,13 @@ export interface TagProps extends Omit<React.HTMLAttributes<HTMLSpanElement>, "o
|
|
|
30
30
|
startContent?: ReactNode;
|
|
31
31
|
/** Whether the tag is disabled */
|
|
32
32
|
disabled?: boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Whether to render with motion (layout + enter/exit animation). Default true.
|
|
35
|
+
* Set `false` to render a plain `<span>` — required when a Tag lives inside a
|
|
36
|
+
* contentEditable host (e.g. Mention chips), where Framer-Motion's `layout`
|
|
37
|
+
* FLIP re-measurement fights the browser's caret/selection on every keystroke.
|
|
38
|
+
*/
|
|
39
|
+
animated?: boolean;
|
|
33
40
|
/** Additional class name for the tag */
|
|
34
41
|
className?: string;
|
|
35
42
|
/** Theme overrides */
|
|
@@ -115,7 +115,7 @@ const Tooltip = ({ content, children, placement = "top", delay = 300, disabled =
|
|
|
115
115
|
})
|
|
116
116
|
: children;
|
|
117
117
|
return (jsxs("div", { className: cn("relative inline-block", triggerClassName), ref: triggerRef, ...triggerHandlers, "aria-describedby": isVisible && id ? id : undefined, children: [childWithFocusHandlers, isClient &&
|
|
118
|
-
createPortal(jsx("div", { className: darkMode || isDarkMode ? "dark" : undefined, children: tooltipContent }), document.body)] }));
|
|
118
|
+
createPortal(jsx("div", { "data-flikkui-portal": "", className: darkMode || isDarkMode ? "dark" : undefined, children: tooltipContent }), document.body)] }));
|
|
119
119
|
};
|
|
120
120
|
// Set display name for dev tools and Storybook
|
|
121
121
|
Tooltip.displayName = "Tooltip";
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
const tooltipTheme = {
|
|
2
2
|
// Base style for the tooltip - using fixed positioning for portal rendering
|
|
3
|
-
baseStyle: "fixed z-[99] rounded-[var(--tooltip-radius)] py-1 px-2 text-xs text-[var(--color-text-primary)] focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-primary)] focus-visible:ring-offset-2 pointer-events-none bg-
|
|
4
|
-
"dark:bg-[var(--color-neutral-800)]/90 dark:outline-[var(--color-border)]/80 dark:border-[var(--color-border)]",
|
|
3
|
+
baseStyle: "fixed z-[99] rounded-[var(--tooltip-radius)] py-1 px-2 text-xs text-[var(--color-text-primary)] focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-primary)] focus-visible:ring-offset-2 pointer-events-none bg-[var(--color-surface-overlay)]/90 backdrop-blur-md outline outline-[var(--color-border)] shadow-lg",
|
|
5
4
|
};
|
|
6
5
|
|
|
7
6
|
export { tooltipTheme };
|
|
@@ -15,6 +15,7 @@ export * from "./CommandPalette";
|
|
|
15
15
|
export * from "./Separator";
|
|
16
16
|
export * from "./Drawer";
|
|
17
17
|
export * from "./Dropdown";
|
|
18
|
+
export * from "./DotSeparator";
|
|
18
19
|
export * from "./Kbd";
|
|
19
20
|
export * from "./MenuItem";
|
|
20
21
|
export * from "./Link";
|
|
@@ -47,3 +48,4 @@ export * from "./OfflineIndicator";
|
|
|
47
48
|
export * from "./ContextMenu";
|
|
48
49
|
export * from "./Pill";
|
|
49
50
|
export * from "./Icon";
|
|
51
|
+
export * from "./ImagePlaceholder";
|
|
@@ -32,6 +32,8 @@ export { DropdownItem } from './Dropdown/DropdownItem.js';
|
|
|
32
32
|
export { DropdownSection } from './Dropdown/DropdownSection.js';
|
|
33
33
|
export { DropdownSeparator } from './Dropdown/DropdownSeparator.js';
|
|
34
34
|
export { dropdownTheme } from './Dropdown/Dropdown.theme.js';
|
|
35
|
+
export { DotSeparator } from './DotSeparator/DotSeparator.js';
|
|
36
|
+
export { dotSeparatorTheme } from './DotSeparator/DotSeparator.theme.js';
|
|
35
37
|
export { Kbd } from './Kbd/Kbd.js';
|
|
36
38
|
export { MenuItem } from './MenuItem/MenuItem.js';
|
|
37
39
|
export { menuItemTheme } from './MenuItem/MenuItem.theme.js';
|
|
@@ -96,12 +98,13 @@ export { SidebarContent } from './Sidebar/SidebarContent.js';
|
|
|
96
98
|
export { SidebarFooter } from './Sidebar/SidebarFooter.js';
|
|
97
99
|
export { SidebarNav } from './Sidebar/SidebarNav.js';
|
|
98
100
|
export { SidebarNavGroup } from './Sidebar/SidebarNavGroup.js';
|
|
99
|
-
export { SidebarSubmenu } from './Sidebar/SidebarSubmenu.js';
|
|
100
101
|
export { SidebarToggle } from './Sidebar/SidebarToggle.js';
|
|
101
102
|
export { SidebarMobileTrigger } from './Sidebar/SidebarMobileTrigger.js';
|
|
102
103
|
export { SidebarUserProfile } from './Sidebar/SidebarUserProfile.js';
|
|
103
104
|
export { SidebarLogo } from './Sidebar/SidebarLogo.js';
|
|
104
|
-
export {
|
|
105
|
+
export { SidebarSearch } from './Sidebar/SidebarSearch.js';
|
|
106
|
+
export { SidebarCard } from './Sidebar/SidebarCard.js';
|
|
107
|
+
export { SidebarProvider, useSidebarContext } from './Sidebar/SidebarContext.js';
|
|
105
108
|
export { OfflineIndicator } from './OfflineIndicator/OfflineIndicator.js';
|
|
106
109
|
export { offlineIndicatorTheme } from './OfflineIndicator/OfflineIndicator.theme.js';
|
|
107
110
|
export { ContextMenu } from './ContextMenu/ContextMenu.js';
|
|
@@ -110,6 +113,7 @@ export { Pill } from './Pill/Pill.js';
|
|
|
110
113
|
export { pillTheme } from './Pill/Pill.theme.js';
|
|
111
114
|
export { Icon } from './Icon/Icon.js';
|
|
112
115
|
export { fileTypes } from './Icon/data/fileTypes.js';
|
|
116
|
+
export { ImagePlaceholder } from './ImagePlaceholder/ImagePlaceholder.js';
|
|
113
117
|
export { AnimatePresence } from 'motion/react';
|
|
114
118
|
export { CardBody } from './Card/CardBody.js';
|
|
115
119
|
export { CardFooter } from './Card/CardFooter.js';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { GanttChartProps, GanttContextValue, GanttInteractionValue } from "./GanttChart.types";
|
|
2
2
|
export declare function useGanttContext(): GanttContextValue;
|
|
3
3
|
export declare function useGanttInteraction(): GanttInteractionValue;
|
|
4
|
-
declare function GanttChartComponent({ data, groups, columns, startDate, endDate, todayMarker, scrollToToday, readonly: readonlyProp, readonlyDates: readonlyDatesProp, readonlyProgress: readonlyProgressProp, zoom: zoomProp, defaultZoom, onZoomChange, collapsedGroups: collapsedProp, defaultCollapsedGroups, onCollapsedGroupsChange, hideCompleted: hideCompletedProp, defaultHideCompleted, onHideCompletedChange, tablePanelWidth: tablePanelWidthProp, defaultTablePanelWidth, onTablePanelWidthChange, onTaskUpdate, onTaskDelete, onTaskDuplicate, onTaskAdd, onGroupAdd, onTaskClick, holidays: holidaysProp, gridLines, className, theme: themeOverrides, rowHeight, }: GanttChartProps): import("react/jsx-runtime").JSX.Element;
|
|
4
|
+
declare function GanttChartComponent({ data, groups, columns, startDate, endDate, todayMarker, scrollToToday, toolbar, showTable, showDependencies, showTaskLabels, emptyState, readonly: readonlyProp, readonlyDates: readonlyDatesProp, readonlyProgress: readonlyProgressProp, zoom: zoomProp, defaultZoom, onZoomChange, collapsedGroups: collapsedProp, defaultCollapsedGroups, onCollapsedGroupsChange, hideCompleted: hideCompletedProp, defaultHideCompleted, onHideCompletedChange, tablePanelWidth: tablePanelWidthProp, defaultTablePanelWidth, onTablePanelWidthChange, onTaskUpdate, onTaskDelete, onTaskDuplicate, onTaskAdd, onGroupAdd, onTaskClick, holidays: holidaysProp, gridLines, className, theme: themeOverrides, rowHeight, }: GanttChartProps): import("react/jsx-runtime").JSX.Element;
|
|
5
5
|
declare namespace GanttChartComponent {
|
|
6
6
|
var displayName: string;
|
|
7
7
|
}
|