@adecore/ui 0.53.3 → 0.54.1
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/Banner.d.ts +1 -1
- package/dist/ButtonGroup.js +1 -1
- package/dist/Checkbox.js +1 -1
- package/dist/ChoiceCards.d.ts +1 -1
- package/dist/ChoiceCards.js +2 -2
- package/dist/CloseButton.js +1 -1
- package/dist/ColorSwatch.d.ts +1 -1
- package/dist/ColorSwatch.js +1 -1
- package/dist/ColorWheelPicker.js +1 -1
- package/dist/CopyButton.js +1 -1
- package/dist/DockShell.js +1 -1
- package/dist/EmptyState.d.ts +1 -1
- package/dist/EmptyState.js +1 -1
- package/dist/ErrorBoundary.js +122 -112
- package/dist/Field.d.ts +1 -1
- package/dist/Field.js +2 -2
- package/dist/FileIcon.d.ts +1 -1
- package/dist/FileIcon.js +44 -36
- package/dist/Icon.d.ts +1 -1
- package/dist/IconButton.d.ts +3 -3
- package/dist/IconButton.js +2 -2
- package/dist/IconPicker.js +35 -32
- package/dist/Input.d.ts +1 -1
- package/dist/ListRow.js +1 -1
- package/dist/MiddleTruncate.js +2 -2
- package/dist/PanelEmpty.d.ts +1 -1
- package/dist/PanelHeader.d.ts +1 -1
- package/dist/PanelHeader.js +1 -1
- package/dist/ProjectSwitcher.js +1 -1
- package/dist/PromptDialog.d.ts +1 -1
- package/dist/ScrollArea.d.ts +12 -0
- package/dist/ScrollArea.js +144 -0
- package/dist/SectionLabel.js +1 -1
- package/dist/SegmentBar.js +1 -1
- package/dist/Segmented.d.ts +1 -1
- package/dist/Select.d.ts +1 -1
- package/dist/Select.js +22 -16
- package/dist/SelectSearch.js +49 -33
- package/dist/ShortcutHints.js +1 -1
- package/dist/Slider.js +2 -2
- package/dist/SlidingColumn.js +1 -1
- package/dist/SplitButton.js +1 -1
- package/dist/Surface.js +1 -1
- package/dist/Switch.js +1 -1
- package/dist/TextMenu.js +2 -2
- package/dist/Toasts.js +2 -2
- package/dist/Tooltip.d.ts +1 -1
- package/dist/Tooltip.js +1 -1
- package/dist/UIProvider.d.ts +1 -1
- package/dist/Waveform.js +1 -1
- package/dist/Wipe.js +2 -2
- package/dist/combobox/parts.d.ts +3 -3
- package/dist/combobox/parts.js +53 -32
- package/dist/command-palette/parts.d.ts +1 -1
- package/dist/command-palette/parts.js +22 -7
- package/dist/command-palette/virtual.js +4 -4
- package/dist/dialog/parts.d.ts +1 -1
- package/dist/dialog/parts.js +2 -2
- package/dist/file-icon.d.ts +2 -0
- package/dist/file-icon.js +12 -0
- package/dist/file-tree/parts.d.ts +2 -2
- package/dist/file-tree/parts.js +3 -3
- package/dist/file-tree/use-file-tree-shift.d.ts +1 -1
- package/dist/file-tree/use-file-tree-shift.js +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/key-value-list/parts.js +1 -1
- package/dist/menu/parts.d.ts +3 -3
- package/dist/menu/parts.js +46 -30
- package/dist/popover/parts.d.ts +3 -3
- package/dist/popover/parts.js +110 -71
- package/dist/project-switcher-row.js +1 -1
- package/dist/scrollbar-geometry.d.ts +15 -0
- package/dist/scrollbar-geometry.js +48 -0
- package/dist/settings/MasterDetail.js +40 -30
- package/dist/settings/SettingsDialog.d.ts +1 -1
- package/dist/settings/SettingsDialog.js +27 -11
- package/dist/settings/SettingsRow.d.ts +1 -1
- package/dist/settings/SettingsRow.js +1 -1
- package/dist/settings/SettingsSection.d.ts +1 -1
- package/dist/tabs/parts.d.ts +1 -1
- package/dist/tabs/parts.js +3 -3
- package/dist/testing/dedupe.js +1 -1
- package/dist/theme.css +91 -1
- package/dist/tree/parts.js +2 -2
- package/dist/useOverlayScrollbars.d.ts +7 -0
- package/dist/useOverlayScrollbars.js +281 -0
- package/dist/workspace/PaneBar.js +2 -2
- package/dist/workspace/SplitView.d.ts +1 -1
- package/dist/workspace/SplitView.js +4 -4
- package/dist/workspace/TabStrip.d.ts +1 -1
- package/dist/workspace/TabStrip.js +2 -2
- package/dist/workspace/Workspace.d.ts +1 -1
- package/dist/workspace/Workspace.js +2 -2
- package/dist/workspace/WorkspaceRail.js +1 -1
- package/dist/workspace/WorkspaceTopRow.js +1 -1
- package/package.json +1 -1
- package/src/AccentSwatches.tsx +1 -1
- package/src/Banner.tsx +1 -1
- package/src/Button.tsx +1 -1
- package/src/ButtonGroup.tsx +1 -1
- package/src/Checkbox.tsx +2 -2
- package/src/ChoiceCards.tsx +3 -3
- package/src/CloseButton.tsx +2 -2
- package/src/ColorSwatch.tsx +2 -2
- package/src/ColorWheelPicker.tsx +1 -1
- package/src/ColumnResizeHandle.tsx +1 -1
- package/src/CopyButton.tsx +1 -1
- package/src/DockShell.tsx +1 -1
- package/src/EmptyState.tsx +2 -2
- package/src/ErrorBoundary.tsx +4 -3
- package/src/Field.tsx +2 -2
- package/src/FileIcon.tsx +15 -6
- package/src/Icon.tsx +2 -2
- package/src/IconButton.tsx +3 -3
- package/src/IconPicker.tsx +7 -6
- package/src/Input.tsx +2 -2
- package/src/Kbd.tsx +1 -1
- package/src/ListRow.tsx +1 -1
- package/src/Meter.tsx +1 -1
- package/src/MiddleTruncate.tsx +2 -2
- package/src/PanelEmpty.tsx +2 -2
- package/src/PanelHeader.tsx +2 -2
- package/src/Pill.tsx +1 -1
- package/src/ProjectSwitcher.tsx +2 -2
- package/src/PromptDialog.tsx +1 -1
- package/src/RelativeTime.tsx +1 -1
- package/src/ScrollArea.tsx +47 -0
- package/src/SectionLabel.tsx +1 -1
- package/src/SegmentBar.tsx +1 -1
- package/src/Segmented.tsx +1 -1
- package/src/Select.tsx +6 -2
- package/src/SelectSearch.tsx +19 -12
- package/src/Separator.tsx +1 -1
- package/src/ShortcutHints.tsx +1 -1
- package/src/Skeleton.tsx +1 -1
- package/src/Slider.tsx +2 -2
- package/src/SlidingColumn.tsx +1 -1
- package/src/Spinner.tsx +1 -1
- package/src/SplitButton.tsx +1 -1
- package/src/Stepper.tsx +1 -1
- package/src/Surface.tsx +1 -1
- package/src/Switch.tsx +2 -2
- package/src/TextMenu.tsx +2 -2
- package/src/Tile.tsx +1 -1
- package/src/Toasts.tsx +2 -2
- package/src/Tooltip.tsx +2 -2
- package/src/UIProvider.tsx +1 -1
- package/src/Waveform.tsx +1 -1
- package/src/Wipe.tsx +2 -2
- package/src/ZoomControls.tsx +1 -1
- package/src/combobox/parts.tsx +9 -4
- package/src/command-palette/parts.tsx +25 -19
- package/src/command-palette/virtual.tsx +4 -4
- package/src/dialog/parts.tsx +2 -2
- package/src/file-icon.ts +15 -0
- package/src/file-tree/parts.tsx +6 -6
- package/src/file-tree/use-empty-lines.ts +1 -1
- package/src/file-tree/use-file-tree-shift.tsx +2 -2
- package/src/file-tree/use-slots.ts +2 -2
- package/src/index.ts +2 -0
- package/src/key-value-list/parts.tsx +1 -1
- package/src/menu/parts.tsx +11 -6
- package/src/popover/parts.tsx +13 -5
- package/src/project-switcher-row.tsx +2 -2
- package/src/scrollbar-geometry.ts +67 -0
- package/src/select-shared.ts +1 -1
- package/src/settings/DetailHeader.tsx +1 -1
- package/src/settings/MasterDetail.tsx +9 -6
- package/src/settings/SettingsDialog.tsx +16 -9
- package/src/settings/SettingsRow.tsx +1 -1
- package/src/settings/SettingsSection.tsx +1 -1
- package/src/tabs/parts.tsx +4 -4
- package/src/testing/dedupe.ts +1 -1
- package/src/theme.css +91 -1
- package/src/tree/parts.tsx +2 -2
- package/src/useOverlayScrollbars.tsx +263 -0
- package/src/workspace/DropPreview.tsx +1 -1
- package/src/workspace/PaneBar.tsx +2 -2
- package/src/workspace/SplitView.tsx +5 -5
- package/src/workspace/TabStrip.tsx +3 -3
- package/src/workspace/Workspace.tsx +2 -2
- package/src/workspace/WorkspaceRail.tsx +1 -1
- package/src/workspace/WorkspaceTopRow.tsx +1 -1
package/src/AccentSwatches.tsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { Ref } from 'react';
|
|
2
1
|
import clsx from 'clsx';
|
|
3
2
|
import { Ellipsis } from 'lucide-react';
|
|
3
|
+
import type { Ref } from 'react';
|
|
4
4
|
import { useTranslation } from 'react-i18next';
|
|
5
5
|
import { ColorSwatch } from './ColorSwatch.tsx';
|
|
6
6
|
import { Icon } from './Icon.tsx';
|
package/src/Banner.tsx
CHANGED
package/src/Button.tsx
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { AnchorHTMLAttributes, ComponentProps, Ref } from 'react';
|
|
2
1
|
import clsx from 'clsx';
|
|
2
|
+
import type { AnchorHTMLAttributes, ComponentProps, Ref } from 'react';
|
|
3
3
|
import { buttonClass, type ButtonShape, type ButtonSize, type ButtonVariant } from './button-class.ts';
|
|
4
4
|
|
|
5
5
|
export type { ButtonShape, ButtonSize, ButtonVariant } from './button-class.ts';
|
package/src/ButtonGroup.tsx
CHANGED
package/src/Checkbox.tsx
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { Checkbox as BaseCheckbox } from '@base-ui/react/checkbox';
|
|
2
2
|
import clsx from 'clsx';
|
|
3
3
|
import { Check, Minus } from 'lucide-react';
|
|
4
|
-
import {
|
|
4
|
+
import type { Ref } from 'react';
|
|
5
5
|
import { Icon } from './Icon.tsx';
|
|
6
6
|
|
|
7
7
|
export interface CheckboxProps {
|
package/src/ChoiceCards.tsx
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { Fragment, useId, type ReactNode, type Ref } from 'react';
|
|
2
|
-
import clsx from 'clsx';
|
|
3
|
-
import type { LucideIcon } from 'lucide-react';
|
|
4
1
|
import { Radio } from '@base-ui/react/radio';
|
|
5
2
|
import { RadioGroup } from '@base-ui/react/radio-group';
|
|
3
|
+
import clsx from 'clsx';
|
|
4
|
+
import type { LucideIcon } from 'lucide-react';
|
|
5
|
+
import { Fragment, useId, type ReactNode, type Ref } from 'react';
|
|
6
6
|
import { Icon } from './Icon.tsx';
|
|
7
7
|
|
|
8
8
|
export interface Choice<Value extends string | number> {
|
package/src/CloseButton.tsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { Ref } from 'react';
|
|
2
|
-
import { X } from 'lucide-react';
|
|
3
1
|
import { Dialog } from '@base-ui/react/dialog';
|
|
2
|
+
import { X } from 'lucide-react';
|
|
3
|
+
import type { Ref } from 'react';
|
|
4
4
|
import { IconButton, type IconButtonSize } from './IconButton.tsx';
|
|
5
5
|
import type { Shortcut } from './shortcut.ts';
|
|
6
6
|
|
package/src/ColorSwatch.tsx
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { useRender } from '@base-ui/react/use-render';
|
|
2
2
|
import clsx from 'clsx';
|
|
3
3
|
import { Check } from 'lucide-react';
|
|
4
|
-
import {
|
|
4
|
+
import type { ComponentProps } from 'react';
|
|
5
5
|
import { Icon } from './Icon.tsx';
|
|
6
6
|
|
|
7
7
|
/* `focus-ring` for the swatch that is a menu item rather than a button, which the keyboard reaches all the same. */
|
package/src/ColorWheelPicker.tsx
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { useEffect, useId, useRef, useState, type KeyboardEvent, type Ref } from 'react';
|
|
2
1
|
import { ChevronDown } from 'lucide-react';
|
|
2
|
+
import { useEffect, useId, useRef, useState, type KeyboardEvent, type Ref } from 'react';
|
|
3
3
|
import { ColorSwatch } from './ColorSwatch.tsx';
|
|
4
4
|
import { Icon } from './Icon.tsx';
|
|
5
5
|
import { PopoverPopup, PopoverRoot, PopoverTrigger } from './popover/parts.tsx';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { CSSProperties, PointerEvent as ReactPointerEvent, Ref } from 'react';
|
|
2
1
|
import clsx from 'clsx';
|
|
2
|
+
import type { CSSProperties, PointerEvent as ReactPointerEvent, Ref } from 'react';
|
|
3
3
|
import type { ColumnEdge } from './useColumnResize.ts';
|
|
4
4
|
|
|
5
5
|
export interface ColumnResizeHandleProps {
|
package/src/CopyButton.tsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import { Check, Copy } from 'lucide-react';
|
|
1
2
|
import { useEffect, useState, type Ref } from 'react';
|
|
2
3
|
import { useTranslation } from 'react-i18next';
|
|
3
|
-
import { Check, Copy } from 'lucide-react';
|
|
4
4
|
import { Button, type ButtonSize, type ButtonVariant } from './Button.tsx';
|
|
5
5
|
import { copyText } from './clipboard.ts';
|
|
6
6
|
import { Icon } from './Icon.tsx';
|
package/src/DockShell.tsx
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { useEffect, useRef, useState, type HTMLAttributes, type ReactNode, type Ref } from 'react';
|
|
2
1
|
import clsx from 'clsx';
|
|
2
|
+
import { useEffect, useRef, useState, type HTMLAttributes, type ReactNode, type Ref } from 'react';
|
|
3
3
|
import { Surface } from './Surface.tsx';
|
|
4
4
|
|
|
5
5
|
/* How close to the bottom of the window the pointer has to come before a hidden dock slides back. */
|
package/src/EmptyState.tsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { cloneElement, isValidElement, type ReactElement, type ReactNode, type Ref } from 'react';
|
|
2
|
-
import type { LucideIcon } from 'lucide-react';
|
|
3
1
|
import clsx from 'clsx';
|
|
2
|
+
import type { LucideIcon } from 'lucide-react';
|
|
3
|
+
import { cloneElement, isValidElement, type ReactElement, type ReactNode, type Ref } from 'react';
|
|
4
4
|
import { Icon } from './Icon.tsx';
|
|
5
5
|
import { Spinner } from './Spinner.tsx';
|
|
6
6
|
|
package/src/ErrorBoundary.tsx
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
import { Component, type ErrorInfo, type ReactNode } from 'react';
|
|
2
1
|
import clsx from 'clsx';
|
|
3
2
|
import { RotateCw, TriangleAlert } from 'lucide-react';
|
|
3
|
+
import { Component, type ErrorInfo, type ReactNode } from 'react';
|
|
4
4
|
import { useTranslation } from 'react-i18next';
|
|
5
5
|
import { Button } from './Button.tsx';
|
|
6
6
|
import { ButtonGroup } from './ButtonGroup.tsx';
|
|
7
7
|
import { CopyButton } from './CopyButton.tsx';
|
|
8
8
|
import { errorMessageOf, errorReport, shouldReset, type ResetKeys } from './error-boundary.ts';
|
|
9
9
|
import { Icon } from './Icon.tsx';
|
|
10
|
+
import { ScrollArea } from './ScrollArea.tsx';
|
|
10
11
|
|
|
11
12
|
export interface ErrorBoundaryProps {
|
|
12
13
|
/* The first line of the message: "Could not show this view". */
|
|
@@ -49,7 +50,7 @@ function ErrorFallback({ label, error, componentStack, compact, reload, classNam
|
|
|
49
50
|
const { t } = useTranslation('ui');
|
|
50
51
|
|
|
51
52
|
return (
|
|
52
|
-
<
|
|
53
|
+
<ScrollArea role="alert" className={clsx('bg-surface', className)} viewportClassName={clsx('grid place-items-center', compact ? 'p-3' : 'p-6')}>
|
|
53
54
|
<div className={clsx('flex max-w-[360px] flex-col items-center text-center', compact ? 'gap-1' : 'gap-2')}>
|
|
54
55
|
{!compact && <Icon icon={TriangleAlert} size={20} className="text-status-error" />}
|
|
55
56
|
<p className="text-sm font-medium text-text">{label}</p>
|
|
@@ -69,7 +70,7 @@ function ErrorFallback({ label, error, componentStack, compact, reload, classNam
|
|
|
69
70
|
</ButtonGroup>
|
|
70
71
|
</div>
|
|
71
72
|
</div>
|
|
72
|
-
</
|
|
73
|
+
</ScrollArea>
|
|
73
74
|
);
|
|
74
75
|
}
|
|
75
76
|
|
package/src/Field.tsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { useId, type ReactNode, type Ref } from 'react';
|
|
2
|
-
import clsx from 'clsx';
|
|
3
1
|
import { useRender } from '@base-ui/react/use-render';
|
|
2
|
+
import clsx from 'clsx';
|
|
3
|
+
import { useId, type ReactNode, type Ref } from 'react';
|
|
4
4
|
import { FieldContext } from './field-context.ts';
|
|
5
5
|
import { SectionLabel } from './SectionLabel.tsx';
|
|
6
6
|
|
package/src/FileIcon.tsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { useInsertionEffect, type Ref } from 'react';
|
|
2
1
|
import clsx from 'clsx';
|
|
3
|
-
import {
|
|
2
|
+
import { useInsertionEffect, useSyncExternalStore, type Ref } from 'react';
|
|
3
|
+
import { fileIconFor, fileIconOverrideFor, fileIconOverrideVersion, mountFileIconSprite, subscribeFileIconOverride } from './file-icon.ts';
|
|
4
4
|
|
|
5
5
|
export interface FileIconProps {
|
|
6
6
|
/* Absolute or relative; only the last segment decides which icon this is. */
|
|
@@ -8,7 +8,9 @@ export interface FileIconProps {
|
|
|
8
8
|
|
|
9
9
|
size?: number;
|
|
10
10
|
className?: string;
|
|
11
|
-
|
|
11
|
+
|
|
12
|
+
/* An `<img>` when an override gives the file an icon of the app's own, the `<svg>` otherwise. */
|
|
13
|
+
ref?: Ref<SVGSVGElement | HTMLImageElement>;
|
|
12
14
|
}
|
|
13
15
|
|
|
14
16
|
/*
|
|
@@ -19,15 +21,22 @@ export function FileIcon({ path, size = 16, className, ref }: FileIconProps) {
|
|
|
19
21
|
// Before the browser paints, so a `<use>` never points at a symbol that is not in the document yet.
|
|
20
22
|
useInsertionEffect(mountFileIconSprite, []);
|
|
21
23
|
|
|
22
|
-
const
|
|
24
|
+
const version = useSyncExternalStore(subscribeFileIconOverride, fileIconOverrideVersion, fileIconOverrideVersion);
|
|
25
|
+
const own = overrideFor(path, version);
|
|
23
26
|
|
|
27
|
+
// React types a readonly ref object, so the union passes to neither element without a cast; each holds one of its members.
|
|
24
28
|
if (own !== null) {
|
|
25
|
-
return <img src={own} alt="" width={size} height={size} className={clsx('file-icon', className)} />;
|
|
29
|
+
return <img ref={ref as Ref<HTMLImageElement>} src={own} alt="" width={size} height={size} className={clsx('file-icon', className)} />;
|
|
26
30
|
}
|
|
27
31
|
|
|
28
32
|
return (
|
|
29
|
-
<svg ref={ref} className={clsx('file-icon', className)} width={size} height={size} viewBox="0 0 16 16" aria-hidden>
|
|
33
|
+
<svg ref={ref as Ref<SVGSVGElement>} className={clsx('file-icon', className)} width={size} height={size} viewBox="0 0 16 16" aria-hidden>
|
|
30
34
|
<use href={`#${fileIconFor(path)}`} />
|
|
31
35
|
</svg>
|
|
32
36
|
);
|
|
33
37
|
}
|
|
38
|
+
|
|
39
|
+
/* Takes the version so the compiler caches the result on it as well as on the path. */
|
|
40
|
+
function overrideFor(path: string, _version: number): string | null {
|
|
41
|
+
return fileIconOverrideFor(path);
|
|
42
|
+
}
|
package/src/Icon.tsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { Ref } from 'react';
|
|
2
|
-
import type { LucideIcon } from 'lucide-react';
|
|
3
1
|
import clsx from 'clsx';
|
|
2
|
+
import type { LucideIcon } from 'lucide-react';
|
|
3
|
+
import type { Ref } from 'react';
|
|
4
4
|
|
|
5
5
|
// The whole client draws at this weight. 2 is Lucide's default, but at 12 and 14 pixels next to
|
|
6
6
|
// text of the same size a hair thinner keeps the glyph from outweighing the words beside it.
|
package/src/IconButton.tsx
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { useRender } from '@base-ui/react/use-render';
|
|
2
2
|
import clsx from 'clsx';
|
|
3
3
|
import type { LucideIcon } from 'lucide-react';
|
|
4
|
-
import {
|
|
4
|
+
import type { ComponentProps, ReactElement, ReactNode } from 'react';
|
|
5
|
+
import { ICON_BUTTON_CLASS, ICON_BUTTON_ICON_SIZE, type IconButtonSize } from './icon-button-size.ts';
|
|
5
6
|
import { Icon } from './Icon.tsx';
|
|
6
7
|
import type { Shortcut } from './shortcut.ts';
|
|
7
8
|
import { Spinner } from './Spinner.tsx';
|
|
8
9
|
import { Tooltip, type TooltipSide } from './Tooltip.tsx';
|
|
9
|
-
import { ICON_BUTTON_CLASS, ICON_BUTTON_ICON_SIZE, type IconButtonSize } from './icon-button-size.ts';
|
|
10
10
|
|
|
11
11
|
export type { IconButtonSize };
|
|
12
12
|
|
package/src/IconPicker.tsx
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
|
-
import { useId, useLayoutEffect, useRef, useState, type KeyboardEvent, type Ref } from 'react';
|
|
2
1
|
import clsx from 'clsx';
|
|
3
2
|
import { Ban, ChevronDown, Search, X } from 'lucide-react';
|
|
3
|
+
import { useId, useLayoutEffect, useRef, useState, type KeyboardEvent, type Ref } from 'react';
|
|
4
4
|
import { useTranslation } from 'react-i18next';
|
|
5
5
|
import { Button } from './Button.tsx';
|
|
6
6
|
import { EmptyState } from './EmptyState.tsx';
|
|
7
7
|
import { formatNumber } from './format/number.ts';
|
|
8
|
+
import { cellForKey, escapeClearsSearch, filterSections, isGrouped, sectionsOf, tabStopOf, type IconPickerIcons, type IconSection } from './icon-picker.ts';
|
|
8
9
|
import { Icon } from './Icon.tsx';
|
|
9
10
|
import { IconButton } from './IconButton.tsx';
|
|
10
|
-
import { cellForKey, escapeClearsSearch, filterSections, isGrouped, sectionsOf, tabStopOf, type IconPickerIcons, type IconSection } from './icon-picker.ts';
|
|
11
11
|
import { PopoverPopup, PopoverRoot, PopoverTrigger } from './popover/parts.tsx';
|
|
12
|
+
import { ScrollArea } from './ScrollArea.tsx';
|
|
12
13
|
import { SectionLabel } from './SectionLabel.tsx';
|
|
13
14
|
import { Tooltip } from './Tooltip.tsx';
|
|
14
15
|
|
|
@@ -277,12 +278,12 @@ function IconPickerPanel({ id, name, sections, headed, value, keywords, searchab
|
|
|
277
278
|
)}
|
|
278
279
|
</div>
|
|
279
280
|
)}
|
|
280
|
-
<
|
|
281
|
-
|
|
281
|
+
<ScrollArea
|
|
282
|
+
viewportRef={area}
|
|
282
283
|
id={`${id}-grid`}
|
|
283
284
|
role="radiogroup"
|
|
284
285
|
aria-label={name}
|
|
285
|
-
|
|
286
|
+
viewportClassName={clsx('relative overscroll-contain', headed ? 'scroll-pt-7' : 'px-1.5 pt-1.5 pb-2')}
|
|
286
287
|
style={rows === undefined ? undefined : { height: rows * ROW_HEIGHT + (headed ? HEADED_EXTRA : BARE_EXTRA) }}
|
|
287
288
|
onScroll={(event) => markStuckHeadings(event.currentTarget)}
|
|
288
289
|
onKeyDown={moveFocus}
|
|
@@ -342,7 +343,7 @@ function IconPickerPanel({ id, name, sections, headed, value, keywords, searchab
|
|
|
342
343
|
);
|
|
343
344
|
})
|
|
344
345
|
)}
|
|
345
|
-
</
|
|
346
|
+
</ScrollArea>
|
|
346
347
|
{onClear && (
|
|
347
348
|
<div className="flex border-t border-border p-1">
|
|
348
349
|
<Button size="sm" disabled={disabled || value === null} onClick={onClear}>
|
package/src/Input.tsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { ComponentProps, ReactNode } from 'react';
|
|
2
|
-
import type { LucideIcon } from 'lucide-react';
|
|
3
1
|
import clsx from 'clsx';
|
|
2
|
+
import type { LucideIcon } from 'lucide-react';
|
|
3
|
+
import type { ComponentProps, ReactNode } from 'react';
|
|
4
4
|
import { fieldControlProps, useFieldControl } from './field-context.ts';
|
|
5
5
|
import { Icon } from './Icon.tsx';
|
|
6
6
|
|
package/src/Kbd.tsx
CHANGED
package/src/ListRow.tsx
CHANGED
package/src/Meter.tsx
CHANGED
package/src/MiddleTruncate.tsx
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { useLayoutEffect, useState, type Ref } from 'react';
|
|
2
1
|
import clsx from 'clsx';
|
|
3
|
-
import {
|
|
2
|
+
import { useLayoutEffect, useState, type Ref } from 'react';
|
|
4
3
|
import { mergeRefs } from './merge-refs.ts';
|
|
4
|
+
import { fitMiddle, type MiddleCut } from './middle-truncate.ts';
|
|
5
5
|
import { Tooltip } from './Tooltip.tsx';
|
|
6
6
|
|
|
7
7
|
export interface MiddleTruncateProps {
|
package/src/PanelEmpty.tsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { ReactNode, Ref } from 'react';
|
|
2
|
-
import type { LucideIcon } from 'lucide-react';
|
|
3
1
|
import clsx from 'clsx';
|
|
2
|
+
import type { LucideIcon } from 'lucide-react';
|
|
3
|
+
import type { ReactNode, Ref } from 'react';
|
|
4
4
|
import { EmptyState } from './EmptyState.tsx';
|
|
5
5
|
|
|
6
6
|
export interface PanelEmptyProps {
|
package/src/PanelHeader.tsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { ReactNode } from 'react';
|
|
2
|
-
import clsx from 'clsx';
|
|
3
1
|
import { useRender } from '@base-ui/react/use-render';
|
|
2
|
+
import clsx from 'clsx';
|
|
3
|
+
import type { ReactNode } from 'react';
|
|
4
4
|
import { SectionLabel } from './SectionLabel.tsx';
|
|
5
5
|
|
|
6
6
|
export type PanelHeaderProps = useRender.ComponentProps<'header'> & {
|
package/src/Pill.tsx
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { ReactNode, Ref } from 'react';
|
|
2
1
|
import clsx from 'clsx';
|
|
2
|
+
import type { ReactNode, Ref } from 'react';
|
|
3
3
|
|
|
4
4
|
/* Every ground is an alpha over whatever the pill stands on, the way a border is: a solid sunken ground read as a hole on a dark row. */
|
|
5
5
|
const TONES = {
|
package/src/ProjectSwitcher.tsx
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type { ComponentProps, MouseEvent, ReactNode, Ref } from 'react';
|
|
2
1
|
import clsx from 'clsx';
|
|
3
|
-
import { useTranslation } from 'react-i18next';
|
|
4
2
|
import { ChevronDown, History } from 'lucide-react';
|
|
3
|
+
import type { ComponentProps, MouseEvent, ReactNode, Ref } from 'react';
|
|
4
|
+
import { useTranslation } from 'react-i18next';
|
|
5
5
|
import { Icon } from './Icon.tsx';
|
|
6
6
|
import * as Menu from './menu/index.parts.ts';
|
|
7
7
|
import { ProjectSwitcherRow } from './project-switcher-row.tsx';
|
package/src/PromptDialog.tsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import type { LucideIcon } from 'lucide-react';
|
|
1
2
|
import { useState, type ReactNode, type Ref } from 'react';
|
|
2
3
|
import { useTranslation } from 'react-i18next';
|
|
3
|
-
import type { LucideIcon } from 'lucide-react';
|
|
4
4
|
import { Button } from './Button.tsx';
|
|
5
5
|
import { DialogDescription, DialogFooter, DialogPopup, DialogRoot, DialogTitle } from './dialog/parts.tsx';
|
|
6
6
|
import { Field, FormError } from './Field.tsx';
|
package/src/RelativeTime.tsx
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { Ref } from 'react';
|
|
2
1
|
import clsx from 'clsx';
|
|
2
|
+
import type { Ref } from 'react';
|
|
3
3
|
import { formatAge, formatDayClockWithYear, useFormatLocale } from './format/index.ts';
|
|
4
4
|
import { Tooltip, type TooltipSide } from './Tooltip.tsx';
|
|
5
5
|
import { useNow } from './useNow.ts';
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { useRender } from '@base-ui/react/use-render';
|
|
2
|
+
import clsx from 'clsx';
|
|
3
|
+
import { useState, type CSSProperties, type Ref } from 'react';
|
|
4
|
+
import { mergeRefs } from './merge-refs.ts';
|
|
5
|
+
import { useOverlayScrollbars, type ScrollAreaAxis } from './useOverlayScrollbars.tsx';
|
|
6
|
+
|
|
7
|
+
export type ScrollAreaProps = Omit<useRender.ComponentProps<'div'>, 'className' | 'ref'> & {
|
|
8
|
+
/* The directions the content scrolls in; the other one clips. */
|
|
9
|
+
axis?: ScrollAreaAxis;
|
|
10
|
+
|
|
11
|
+
/* The outer box, which holds the bars and takes the size. */
|
|
12
|
+
className?: string;
|
|
13
|
+
ref?: Ref<HTMLDivElement>;
|
|
14
|
+
|
|
15
|
+
/* The element that scrolls, for a virtualizer or code that sets the scroll position. */
|
|
16
|
+
viewportRef?: Ref<HTMLElement>;
|
|
17
|
+
|
|
18
|
+
/* Padding and layout of the content. `render` and the remaining props land on the viewport too. */
|
|
19
|
+
viewportClassName?: string;
|
|
20
|
+
|
|
21
|
+
/* Pixels of the bottom edge a layer over the area covers, such as a docked input. The bars end above it. */
|
|
22
|
+
coveredBottom?: number;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
/* A box that scrolls natively under thin bars that float over its content and show only while it scrolls. */
|
|
26
|
+
export function ScrollArea({ axis = 'y', className, viewportClassName, viewportRef, coveredBottom, ref, render, ...props }: ScrollAreaProps) {
|
|
27
|
+
const [viewport, setViewport] = useState<HTMLElement | null>(null);
|
|
28
|
+
const scrollbars = useOverlayScrollbars(viewport, { axis });
|
|
29
|
+
|
|
30
|
+
const content = useRender<Record<string, never>, HTMLElement>({
|
|
31
|
+
render,
|
|
32
|
+
ref: mergeRefs<HTMLElement>(setViewport, viewportRef),
|
|
33
|
+
defaultTagName: 'div',
|
|
34
|
+
props: { ...props, 'data-axis': axis, className: clsx('ade-scroll-viewport', viewportClassName) }
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
return (
|
|
38
|
+
<div
|
|
39
|
+
ref={ref}
|
|
40
|
+
className={clsx('ade-scroll-area', className)}
|
|
41
|
+
style={coveredBottom ? ({ '--scrollbar-covered-bottom': `${coveredBottom}px` } as CSSProperties) : undefined}
|
|
42
|
+
>
|
|
43
|
+
{content}
|
|
44
|
+
{scrollbars}
|
|
45
|
+
</div>
|
|
46
|
+
);
|
|
47
|
+
}
|
package/src/SectionLabel.tsx
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import clsx from 'clsx';
|
|
2
1
|
import { useRender } from '@base-ui/react/use-render';
|
|
2
|
+
import clsx from 'clsx';
|
|
3
3
|
|
|
4
4
|
/* A label takes the line height of the row it sits in, which is why the size carries `/[inherit]`. */
|
|
5
5
|
const SECTION_LABEL = 'text-xs/[inherit] font-medium text-text-faint';
|
package/src/SegmentBar.tsx
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { useEffect, useRef, useState, type Ref } from 'react';
|
|
2
1
|
import clsx from 'clsx';
|
|
2
|
+
import { useEffect, useRef, useState, type Ref } from 'react';
|
|
3
3
|
import { mergeRefs } from './merge-refs.ts';
|
|
4
4
|
import { Tooltip } from './Tooltip.tsx';
|
|
5
5
|
import { useMeasuredWidth } from './useMeasuredWidth.ts';
|
package/src/Segmented.tsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { KeyboardEvent, Ref } from 'react';
|
|
2
1
|
import clsx from 'clsx';
|
|
3
2
|
import type { LucideIcon } from 'lucide-react';
|
|
3
|
+
import type { KeyboardEvent, Ref } from 'react';
|
|
4
4
|
import { Icon } from './Icon.tsx';
|
|
5
5
|
import { segmentedStop, segmentedTarget } from './segmented-keys.ts';
|
|
6
6
|
import { Tooltip } from './Tooltip.tsx';
|
package/src/Select.tsx
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type { Ref } from 'react';
|
|
2
1
|
import { Select as BaseSelect } from '@base-ui/react/select';
|
|
3
2
|
import clsx from 'clsx';
|
|
4
3
|
import { ChevronDown } from 'lucide-react';
|
|
4
|
+
import { useState, type Ref } from 'react';
|
|
5
5
|
import { useTranslation } from 'react-i18next';
|
|
6
6
|
import { Icon } from './Icon.tsx';
|
|
7
7
|
import { MENU_LABEL } from './menu/parts.tsx';
|
|
@@ -9,6 +9,7 @@ import { renderPositioner } from './popup-layer.ts';
|
|
|
9
9
|
import { RowContent } from './select-row.tsx';
|
|
10
10
|
import { isGroup, rowClassName, triggerClassName, type SelectGroup, type SelectItem } from './select-shared.ts';
|
|
11
11
|
import { SelectSearch } from './SelectSearch.tsx';
|
|
12
|
+
import { useOverlayScrollbars } from './useOverlayScrollbars.tsx';
|
|
12
13
|
|
|
13
14
|
export type { SelectGroup, SelectItem };
|
|
14
15
|
|
|
@@ -74,6 +75,8 @@ function PlainSelect<T extends string>({
|
|
|
74
75
|
const groups = items.length > 0 && isGroup(items[0]!) ? (items as SelectGroup<T>[]) : null;
|
|
75
76
|
const flat = groups ? groups.flatMap((group) => group.items) : (items as SelectItem<T>[]);
|
|
76
77
|
const selected = flat.find((item) => item.value === value) ?? null;
|
|
78
|
+
const [list, setList] = useState<HTMLDivElement | null>(null);
|
|
79
|
+
const scrollbars = useOverlayScrollbars(list);
|
|
77
80
|
|
|
78
81
|
return (
|
|
79
82
|
<BaseSelect.Root
|
|
@@ -99,7 +102,7 @@ function PlainSelect<T extends string>({
|
|
|
99
102
|
alignItemWithTrigger={false}
|
|
100
103
|
>
|
|
101
104
|
<BaseSelect.Popup className="menu-popup">
|
|
102
|
-
<BaseSelect.List className="max-h-80 overflow-auto">
|
|
105
|
+
<BaseSelect.List ref={setList} className="max-h-80 overflow-auto">
|
|
103
106
|
{groups
|
|
104
107
|
? groups.map((group) => (
|
|
105
108
|
<BaseSelect.Group key={group.label}>
|
|
@@ -112,6 +115,7 @@ function PlainSelect<T extends string>({
|
|
|
112
115
|
: flat.map((item) => <Row key={item.value} item={item} picked={item.value === value} />)}
|
|
113
116
|
</BaseSelect.List>
|
|
114
117
|
</BaseSelect.Popup>
|
|
118
|
+
{scrollbars}
|
|
115
119
|
</BaseSelect.Positioner>
|
|
116
120
|
</BaseSelect.Portal>
|
|
117
121
|
</BaseSelect.Root>
|
package/src/SelectSearch.tsx
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
|
-
import { useState } from 'react';
|
|
2
1
|
import { Combobox } from '@base-ui/react/combobox';
|
|
3
2
|
import clsx from 'clsx';
|
|
4
3
|
import { ChevronDown, Search } from 'lucide-react';
|
|
4
|
+
import { useState } from 'react';
|
|
5
5
|
import { useTranslation } from 'react-i18next';
|
|
6
6
|
import { Icon } from './Icon.tsx';
|
|
7
7
|
import { MENU_LABEL } from './menu/parts.tsx';
|
|
8
8
|
import { renderPositioner } from './popup-layer.ts';
|
|
9
|
-
import type { SelectProps } from './Select.tsx';
|
|
10
9
|
import { RowContent } from './select-row.tsx';
|
|
11
10
|
import { isGroup, rowClassName, triggerClassName, type SelectGroup, type SelectItem } from './select-shared.ts';
|
|
11
|
+
import type { SelectProps } from './Select.tsx';
|
|
12
|
+
import { useOverlayScrollbars } from './useOverlayScrollbars.tsx';
|
|
12
13
|
|
|
13
14
|
/* The `Select` with a search field on top of its options, for lists too long to scan. A combobox of Base UI brings the filtering and the keyboard. */
|
|
14
15
|
export function SelectSearch<T extends string>({
|
|
@@ -38,6 +39,8 @@ export function SelectSearch<T extends string>({
|
|
|
38
39
|
: flat.map((item) => item.value);
|
|
39
40
|
|
|
40
41
|
const searchLabel = searchPlaceholder ?? t('select.search');
|
|
42
|
+
const [list, setList] = useState<HTMLDivElement | null>(null);
|
|
43
|
+
const scrollbars = useOverlayScrollbars(list);
|
|
41
44
|
|
|
42
45
|
const renderRow = (itemValue: T) => {
|
|
43
46
|
const item = byValue.get(itemValue)!;
|
|
@@ -87,16 +90,20 @@ export function SelectSearch<T extends string>({
|
|
|
87
90
|
/>
|
|
88
91
|
</label>
|
|
89
92
|
<Combobox.Empty className="px-3 py-4 text-center text-xs text-text-faint empty:hidden">{t('select.noMatch', { query })}</Combobox.Empty>
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
<Combobox.
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
93
|
+
{/* Out to the popup's edge on the right, so the bar lies where a menu's does. */}
|
|
94
|
+
<div className="relative -mr-1 flex min-h-0 flex-col">
|
|
95
|
+
<Combobox.List ref={setList} className="min-h-0 overflow-auto pr-1">
|
|
96
|
+
{groups
|
|
97
|
+
? (group: { value: string; items: T[] }) => (
|
|
98
|
+
<Combobox.Group key={group.value} items={group.items}>
|
|
99
|
+
<Combobox.GroupLabel className={MENU_LABEL}>{group.value}</Combobox.GroupLabel>
|
|
100
|
+
<Combobox.Collection>{renderRow}</Combobox.Collection>
|
|
101
|
+
</Combobox.Group>
|
|
102
|
+
)
|
|
103
|
+
: renderRow}
|
|
104
|
+
</Combobox.List>
|
|
105
|
+
{scrollbars}
|
|
106
|
+
</div>
|
|
100
107
|
</Combobox.Popup>
|
|
101
108
|
</Combobox.Positioner>
|
|
102
109
|
</Combobox.Portal>
|
package/src/Separator.tsx
CHANGED
package/src/ShortcutHints.tsx
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { useEffect, useLayoutEffect, useRef, useState, type CSSProperties } from 'react';
|
|
2
2
|
import { createPortal } from 'react-dom';
|
|
3
3
|
import { isApplePlatform } from './platform.ts';
|
|
4
|
-
import { formatShortcut } from './shortcut.ts';
|
|
5
4
|
import { ModifierHold, placeHint, shortcutHintTargets } from './shortcut-hints.ts';
|
|
5
|
+
import { formatShortcut } from './shortcut.ts';
|
|
6
6
|
|
|
7
7
|
interface PlacedHint {
|
|
8
8
|
id: number;
|
package/src/Skeleton.tsx
CHANGED
package/src/Slider.tsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { useId, type Ref } from 'react';
|
|
2
|
-
import clsx from 'clsx';
|
|
3
1
|
import { Slider as BaseSlider } from '@base-ui/react/slider';
|
|
2
|
+
import clsx from 'clsx';
|
|
3
|
+
import { useId, type Ref } from 'react';
|
|
4
4
|
import { formatFixed } from './format/number.ts';
|
|
5
5
|
import { placesOf } from './step-places.ts';
|
|
6
6
|
|
package/src/SlidingColumn.tsx
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { useEffect, useRef, useState, type KeyboardEvent as ReactKeyboardEvent, type ReactNode, type Ref, type RefObject } from 'react';
|
|
2
1
|
import clsx from 'clsx';
|
|
2
|
+
import { useEffect, useRef, useState, type KeyboardEvent as ReactKeyboardEvent, type ReactNode, type Ref, type RefObject } from 'react';
|
|
3
3
|
import { ColumnResizeHandle } from './ColumnResizeHandle.tsx';
|
|
4
4
|
import { mergeRefs } from './merge-refs.ts';
|
|
5
5
|
import { useColumnResize } from './useColumnResize.ts';
|
package/src/Spinner.tsx
CHANGED
package/src/SplitButton.tsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { useState, type ComponentProps, type ReactNode } from 'react';
|
|
2
1
|
import clsx from 'clsx';
|
|
3
2
|
import { ChevronDown } from 'lucide-react';
|
|
3
|
+
import { useState, type ComponentProps, type ReactNode } from 'react';
|
|
4
4
|
import { splitFrameClass, splitHalfClass, type ButtonSize, type ButtonVariant } from './button-class.ts';
|
|
5
5
|
import { Icon } from './Icon.tsx';
|
|
6
6
|
import { MenuPopup, MenuRoot, MenuTrigger, type MenuPopupProps } from './menu/parts.tsx';
|