@adecore/ui 0.53.2 → 0.54.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (180) hide show
  1. package/dist/Banner.d.ts +1 -1
  2. package/dist/ButtonGroup.js +1 -1
  3. package/dist/Checkbox.js +1 -1
  4. package/dist/ChoiceCards.d.ts +1 -1
  5. package/dist/ChoiceCards.js +2 -2
  6. package/dist/CloseButton.js +1 -1
  7. package/dist/ColorSwatch.d.ts +1 -1
  8. package/dist/ColorSwatch.js +1 -1
  9. package/dist/ColorWheelPicker.js +1 -1
  10. package/dist/CopyButton.js +1 -1
  11. package/dist/DockShell.js +1 -1
  12. package/dist/EmptyState.d.ts +1 -1
  13. package/dist/EmptyState.js +1 -1
  14. package/dist/ErrorBoundary.js +122 -112
  15. package/dist/Field.d.ts +1 -1
  16. package/dist/Field.js +2 -2
  17. package/dist/FileIcon.js +1 -1
  18. package/dist/Icon.d.ts +1 -1
  19. package/dist/IconButton.d.ts +3 -3
  20. package/dist/IconButton.js +2 -2
  21. package/dist/IconPicker.js +35 -32
  22. package/dist/Input.d.ts +1 -1
  23. package/dist/ListRow.js +1 -1
  24. package/dist/MiddleTruncate.js +2 -2
  25. package/dist/PanelEmpty.d.ts +1 -1
  26. package/dist/PanelHeader.d.ts +1 -1
  27. package/dist/PanelHeader.js +1 -1
  28. package/dist/ProjectSwitcher.js +1 -1
  29. package/dist/PromptDialog.d.ts +1 -1
  30. package/dist/ScrollArea.d.ts +12 -0
  31. package/dist/ScrollArea.js +144 -0
  32. package/dist/SectionLabel.js +1 -1
  33. package/dist/SegmentBar.js +1 -1
  34. package/dist/Segmented.d.ts +1 -1
  35. package/dist/Select.d.ts +1 -1
  36. package/dist/Select.js +22 -16
  37. package/dist/SelectSearch.js +49 -33
  38. package/dist/ShortcutHints.js +1 -1
  39. package/dist/Slider.js +2 -2
  40. package/dist/SlidingColumn.js +1 -1
  41. package/dist/SplitButton.js +1 -1
  42. package/dist/Surface.js +1 -1
  43. package/dist/Switch.js +1 -1
  44. package/dist/TextMenu.js +2 -2
  45. package/dist/Toasts.js +2 -2
  46. package/dist/Tooltip.d.ts +1 -1
  47. package/dist/Tooltip.js +1 -1
  48. package/dist/UIProvider.d.ts +1 -1
  49. package/dist/Waveform.js +1 -1
  50. package/dist/Wipe.js +2 -2
  51. package/dist/combobox/parts.d.ts +3 -3
  52. package/dist/combobox/parts.js +53 -32
  53. package/dist/command-palette/parts.d.ts +1 -1
  54. package/dist/command-palette/parts.js +22 -7
  55. package/dist/command-palette/virtual.js +4 -4
  56. package/dist/dialog/parts.d.ts +1 -1
  57. package/dist/dialog/parts.js +2 -2
  58. package/dist/file-tree/parts.d.ts +2 -2
  59. package/dist/file-tree/parts.js +3 -3
  60. package/dist/file-tree/use-file-tree-shift.d.ts +1 -1
  61. package/dist/file-tree/use-file-tree-shift.js +1 -1
  62. package/dist/index.d.ts +2 -0
  63. package/dist/index.js +2 -0
  64. package/dist/key-value-list/parts.js +1 -1
  65. package/dist/menu/parts.d.ts +3 -3
  66. package/dist/menu/parts.js +46 -30
  67. package/dist/popover/parts.d.ts +3 -3
  68. package/dist/popover/parts.js +110 -71
  69. package/dist/project-switcher-row.js +1 -1
  70. package/dist/scrollbar-geometry.d.ts +15 -0
  71. package/dist/scrollbar-geometry.js +48 -0
  72. package/dist/settings/MasterDetail.js +40 -30
  73. package/dist/settings/SettingsDialog.d.ts +1 -1
  74. package/dist/settings/SettingsDialog.js +27 -11
  75. package/dist/settings/SettingsRow.d.ts +1 -1
  76. package/dist/settings/SettingsRow.js +1 -1
  77. package/dist/settings/SettingsSection.d.ts +1 -1
  78. package/dist/tabs/parts.d.ts +1 -1
  79. package/dist/tabs/parts.js +3 -3
  80. package/dist/testing/dedupe.js +1 -1
  81. package/dist/theme.css +91 -1
  82. package/dist/tree/parts.js +2 -2
  83. package/dist/useOverlayScrollbars.d.ts +7 -0
  84. package/dist/useOverlayScrollbars.js +281 -0
  85. package/dist/workspace/PaneBar.js +2 -2
  86. package/dist/workspace/SplitView.d.ts +1 -1
  87. package/dist/workspace/SplitView.js +4 -4
  88. package/dist/workspace/TabStrip.d.ts +1 -1
  89. package/dist/workspace/TabStrip.js +2 -2
  90. package/dist/workspace/Workspace.d.ts +1 -1
  91. package/dist/workspace/Workspace.js +2 -2
  92. package/dist/workspace/WorkspaceRail.js +1 -1
  93. package/dist/workspace/WorkspaceTopRow.js +1 -1
  94. package/package.json +1 -1
  95. package/src/AccentSwatches.tsx +1 -1
  96. package/src/Banner.tsx +1 -1
  97. package/src/Button.tsx +1 -1
  98. package/src/ButtonGroup.tsx +1 -1
  99. package/src/Checkbox.tsx +2 -2
  100. package/src/ChoiceCards.tsx +3 -3
  101. package/src/CloseButton.tsx +2 -2
  102. package/src/ColorSwatch.tsx +2 -2
  103. package/src/ColorWheelPicker.tsx +1 -1
  104. package/src/ColumnResizeHandle.tsx +1 -1
  105. package/src/CopyButton.tsx +1 -1
  106. package/src/DockShell.tsx +1 -1
  107. package/src/EmptyState.tsx +2 -2
  108. package/src/ErrorBoundary.tsx +4 -3
  109. package/src/Field.tsx +2 -2
  110. package/src/FileIcon.tsx +1 -1
  111. package/src/Icon.tsx +2 -2
  112. package/src/IconButton.tsx +3 -3
  113. package/src/IconPicker.tsx +7 -6
  114. package/src/Input.tsx +2 -2
  115. package/src/Kbd.tsx +1 -1
  116. package/src/ListRow.tsx +1 -1
  117. package/src/Meter.tsx +1 -1
  118. package/src/MiddleTruncate.tsx +2 -2
  119. package/src/PanelEmpty.tsx +2 -2
  120. package/src/PanelHeader.tsx +2 -2
  121. package/src/Pill.tsx +1 -1
  122. package/src/ProjectSwitcher.tsx +2 -2
  123. package/src/PromptDialog.tsx +1 -1
  124. package/src/RelativeTime.tsx +1 -1
  125. package/src/ScrollArea.tsx +47 -0
  126. package/src/SectionLabel.tsx +1 -1
  127. package/src/SegmentBar.tsx +1 -1
  128. package/src/Segmented.tsx +1 -1
  129. package/src/Select.tsx +6 -2
  130. package/src/SelectSearch.tsx +19 -12
  131. package/src/Separator.tsx +1 -1
  132. package/src/ShortcutHints.tsx +1 -1
  133. package/src/Skeleton.tsx +1 -1
  134. package/src/Slider.tsx +2 -2
  135. package/src/SlidingColumn.tsx +1 -1
  136. package/src/Spinner.tsx +1 -1
  137. package/src/SplitButton.tsx +1 -1
  138. package/src/Stepper.tsx +1 -1
  139. package/src/Surface.tsx +1 -1
  140. package/src/Switch.tsx +2 -2
  141. package/src/TextMenu.tsx +2 -2
  142. package/src/Tile.tsx +1 -1
  143. package/src/Toasts.tsx +2 -2
  144. package/src/Tooltip.tsx +2 -2
  145. package/src/UIProvider.tsx +1 -1
  146. package/src/Waveform.tsx +1 -1
  147. package/src/Wipe.tsx +2 -2
  148. package/src/ZoomControls.tsx +1 -1
  149. package/src/combobox/parts.tsx +9 -4
  150. package/src/command-palette/parts.tsx +25 -19
  151. package/src/command-palette/virtual.tsx +4 -4
  152. package/src/dialog/parts.tsx +2 -2
  153. package/src/file-tree/parts.tsx +6 -6
  154. package/src/file-tree/use-empty-lines.ts +1 -1
  155. package/src/file-tree/use-file-tree-shift.tsx +2 -2
  156. package/src/file-tree/use-slots.ts +2 -2
  157. package/src/index.ts +2 -0
  158. package/src/key-value-list/parts.tsx +1 -1
  159. package/src/menu/parts.tsx +11 -6
  160. package/src/popover/parts.tsx +13 -5
  161. package/src/project-switcher-row.tsx +2 -2
  162. package/src/scrollbar-geometry.ts +67 -0
  163. package/src/select-shared.ts +1 -1
  164. package/src/settings/DetailHeader.tsx +1 -1
  165. package/src/settings/MasterDetail.tsx +9 -6
  166. package/src/settings/SettingsDialog.tsx +16 -9
  167. package/src/settings/SettingsRow.tsx +1 -1
  168. package/src/settings/SettingsSection.tsx +1 -1
  169. package/src/tabs/parts.tsx +4 -4
  170. package/src/testing/dedupe.ts +1 -1
  171. package/src/theme.css +91 -1
  172. package/src/tree/parts.tsx +2 -2
  173. package/src/useOverlayScrollbars.tsx +263 -0
  174. package/src/workspace/DropPreview.tsx +1 -1
  175. package/src/workspace/PaneBar.tsx +2 -2
  176. package/src/workspace/SplitView.tsx +5 -5
  177. package/src/workspace/TabStrip.tsx +3 -3
  178. package/src/workspace/Workspace.tsx +2 -2
  179. package/src/workspace/WorkspaceRail.tsx +1 -1
  180. package/src/workspace/WorkspaceTopRow.tsx +1 -1
package/dist/theme.css CHANGED
@@ -11,6 +11,11 @@
11
11
  --surface-raised: #ffffff;
12
12
  --surface-sunken: #ececef;
13
13
  --track: rgb(0 0 0 / 0.09);
14
+ /* The overlay scrollbars (`ScrollArea`): alphas, so a bar takes the color of whatever it floats over. */
15
+ --scrollbar-thumb: rgb(0 0 0 / 0.22);
16
+ --scrollbar-thumb-hover: rgb(0 0 0 / 0.38);
17
+ --scrollbar-thumb-active: rgb(0 0 0 / 0.5);
18
+ --scrollbar-track: rgb(0 0 0 / 0.04);
14
19
  /* A bar that is not the one in focus: between the sunken page behind it and a focused bar, so it
15
20
  still reads as a bar. The toolbar of a cell in the grid that does not have the keyboard. */
16
21
  --surface-idle: color-mix(in srgb, var(--surface) 50%, var(--surface-sunken));
@@ -122,6 +127,10 @@
122
127
  --surface-raised: #18181c;
123
128
  --surface-sunken: #0b0b0e;
124
129
  --track: rgb(255 255 255 / 0.11);
130
+ --scrollbar-thumb: rgb(255 255 255 / 0.22);
131
+ --scrollbar-thumb-hover: rgb(255 255 255 / 0.38);
132
+ --scrollbar-thumb-active: rgb(255 255 255 / 0.5);
133
+ --scrollbar-track: rgb(255 255 255 / 0.04);
125
134
  --surface-hover: #202024;
126
135
  --surface-active: #28282e;
127
136
  /* Derived, so an app that tints its surfaces tints its fields along. */
@@ -811,7 +820,7 @@
811
820
  position: absolute;
812
821
  inset-block: 0;
813
822
  border-radius: 999px;
814
- background: var(--text-faint);
823
+ background: var(--scrollbar-thumb);
815
824
  }
816
825
  @media (prefers-reduced-motion: reduce) {
817
826
  .adecore-tree-shift-track {
@@ -1083,3 +1092,84 @@
1083
1092
  /* The cut part stays in the text at no width, so a selection copies it and a find matches across the cut. */
1084
1093
  .middle-truncate-middle { display: inline-block; width: 0; overflow: hidden; vertical-align: top; }
1085
1094
  }
1095
+
1096
+ @layer components {
1097
+ /* `ScrollArea` and `useOverlayScrollbars`. The scroller stays native and hides its own bar; thin bars
1098
+ float over the content, hidden at rest and shown while it scrolls. */
1099
+ [data-overlay-scrollbars] { scrollbar-width: none; }
1100
+ [data-overlay-scrollbars]::-webkit-scrollbar { display: none; }
1101
+ /* A drag that strays over the content must not select it, nor may a long press on a bar. */
1102
+ [data-overlay-scrollbars][data-scrollbar-dragging], .ade-scrollbar { -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; }
1103
+ .ade-scroll-area { position: relative; display: flex; flex-direction: column; min-width: 0; min-height: 0; }
1104
+ /* Its own stacking layer, so a sticky header with a z-index inside never covers the bars. */
1105
+ /* `contain` lets the box bounce at its own end; the page's `overscroll-behavior: none` would take the bounce of a scroll chained up to it. */
1106
+ .ade-scroll-viewport { flex: 1 1 auto; min-height: 0; overflow: auto; isolation: isolate; overscroll-behavior: contain; }
1107
+ .ade-scroll-viewport[data-axis="y"] { overflow-x: hidden; }
1108
+ .ade-scroll-viewport[data-axis="x"] { overflow-y: hidden; }
1109
+ .ade-scrollbar {
1110
+ --scrollbar-size: 12px;
1111
+ position: absolute;
1112
+ z-index: 1;
1113
+ display: none;
1114
+ opacity: 0;
1115
+ pointer-events: none;
1116
+ transition: opacity 240ms ease;
1117
+ }
1118
+ .ade-scrollbar[data-overflow] { display: block; }
1119
+ /* A popup's bars lie beside it in its positioner; the ends keep clear of its rounded corners. */
1120
+ :is(.menu-popup, .picker-popup) ~ .ade-scrollbar { --scrollbar-inset: 4px; }
1121
+ .ade-scrollbar[data-visible] { opacity: 1; pointer-events: auto; transition-duration: 120ms; }
1122
+ /* `coveredBottom` lifts the bars of its own area only, never those of a scroller inside it. */
1123
+ .ade-scroll-viewport { --scrollbar-covered-bottom: 0px; }
1124
+ /* The two bars meet without overlapping: each stops a bar's width short of the corner. */
1125
+ .ade-scrollbar[data-orientation="vertical"] { top: var(--scrollbar-inset, 2px); bottom: calc(var(--scrollbar-covered-bottom, 0px) + var(--scrollbar-inset, 2px)); right: 0; width: var(--scrollbar-size); }
1126
+ .ade-scrollbar[data-orientation="vertical"][data-corner] { bottom: calc(var(--scrollbar-covered-bottom, 0px) + var(--scrollbar-size)); }
1127
+ .ade-scrollbar[data-orientation="horizontal"] { left: var(--scrollbar-inset, 2px); right: var(--scrollbar-inset, 2px); bottom: var(--scrollbar-covered-bottom, 0px); height: var(--scrollbar-size); }
1128
+ .ade-scrollbar[data-orientation="horizontal"][data-corner] { right: var(--scrollbar-size); }
1129
+ .ade-scrollbar::before {
1130
+ content: "";
1131
+ position: absolute;
1132
+ border-radius: 999px;
1133
+ background: var(--scrollbar-track);
1134
+ opacity: 0;
1135
+ transition: opacity 120ms ease;
1136
+ }
1137
+ /* The track is as thick as the widened pill, also on touch where the hit area is wider. */
1138
+ .ade-scrollbar[data-orientation="vertical"]::before { top: 0; bottom: 0; right: 2px; width: 8px; }
1139
+ .ade-scrollbar[data-orientation="horizontal"]::before { left: 0; right: 0; bottom: 2px; height: 8px; }
1140
+ /* The thumb spans the whole hit area across, so a press beside the pill still grabs it; the pill is its `::before`. */
1141
+ .ade-scrollbar-thumb { position: absolute; top: 0; left: 0; touch-action: none; }
1142
+ .ade-scrollbar[data-orientation="vertical"] .ade-scrollbar-thumb { right: 0; }
1143
+ .ade-scrollbar[data-orientation="horizontal"] .ade-scrollbar-thumb { bottom: 0; }
1144
+ .ade-scrollbar-thumb::before {
1145
+ content: "";
1146
+ position: absolute;
1147
+ border-radius: 999px;
1148
+ background: var(--scrollbar-thumb);
1149
+ transition: background-color 120ms ease, width 120ms ease, height 120ms ease, right 120ms ease, bottom 120ms ease;
1150
+ }
1151
+ .ade-scrollbar[data-orientation="vertical"] .ade-scrollbar-thumb::before { top: 0; bottom: 0; right: 3px; width: 6px; }
1152
+ .ade-scrollbar[data-orientation="horizontal"] .ade-scrollbar-thumb::before { left: 0; right: 0; bottom: 3px; height: 6px; }
1153
+ .ade-scrollbar[data-dragging]::before { opacity: 1; }
1154
+ .ade-scrollbar[data-dragging] .ade-scrollbar-thumb::before { background: var(--scrollbar-thumb-active); }
1155
+ .ade-scrollbar[data-orientation="vertical"][data-dragging] .ade-scrollbar-thumb::before { right: 2px; width: 8px; }
1156
+ .ade-scrollbar[data-orientation="horizontal"][data-dragging] .ade-scrollbar-thumb::before { bottom: 2px; height: 8px; }
1157
+ @media (hover: hover) {
1158
+ .ade-scrollbar:hover::before { opacity: 1; }
1159
+ .ade-scrollbar:hover:not([data-dragging]) .ade-scrollbar-thumb::before { background: var(--scrollbar-thumb-hover); }
1160
+ .ade-scrollbar[data-orientation="vertical"]:hover .ade-scrollbar-thumb::before { right: 2px; width: 8px; }
1161
+ .ade-scrollbar[data-orientation="horizontal"]:hover .ade-scrollbar-thumb::before { bottom: 2px; height: 8px; }
1162
+ }
1163
+ /* A finger needs a wider target and a thicker pill. Only the thumb takes a touch, so a tap near the
1164
+ edge still reaches the row under the bar. */
1165
+ @media (pointer: coarse) {
1166
+ .ade-scrollbar { --scrollbar-size: 20px; }
1167
+ .ade-scrollbar[data-visible] { pointer-events: none; }
1168
+ .ade-scrollbar[data-visible] .ade-scrollbar-thumb { pointer-events: auto; }
1169
+ .ade-scrollbar[data-orientation="vertical"] .ade-scrollbar-thumb::before { right: 2px; width: 8px; }
1170
+ .ade-scrollbar[data-orientation="horizontal"] .ade-scrollbar-thumb::before { bottom: 2px; height: 8px; }
1171
+ }
1172
+ @media (prefers-reduced-motion: reduce) {
1173
+ .ade-scrollbar, .ade-scrollbar::before, .ade-scrollbar-thumb::before { transition: none; }
1174
+ }
1175
+ }
@@ -1,8 +1,8 @@
1
1
  import { c as _c } from "react/compiler-runtime";
2
- import 'react';
3
- import clsx from 'clsx';
4
2
  import { useRender } from '@base-ui/react/use-render';
3
+ import clsx from 'clsx';
5
4
  import { ChevronRight } from 'lucide-react';
5
+ import 'react';
6
6
  import { useTranslation } from 'react-i18next';
7
7
  import { Checkbox as UICheckbox } from "../Checkbox.js";
8
8
  import { Icon } from "../Icon.js";
@@ -0,0 +1,7 @@
1
+ import { type ReactElement } from 'react';
2
+ export type ScrollAreaAxis = 'y' | 'x' | 'both';
3
+ export interface OverlayScrollbarsOptions {
4
+ axis?: ScrollAreaAxis;
5
+ }
6
+ export declare const SCROLLBAR_LINGER_MS = 600;
7
+ export declare function useOverlayScrollbars(viewport: HTMLElement | null, { axis }?: OverlayScrollbarsOptions): ReactElement;
@@ -0,0 +1,281 @@
1
+ import { c as _c } from "react/compiler-runtime";
2
+ import { useLayoutEffect, useState } from 'react';
3
+ import { overflows, pageToward, scrollAfterDrag, thumbOf } from './scrollbar-geometry.js';
4
+ /* How long the bars stay after the last scroll, or after the pointer left a bar. */
5
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
6
+ export const SCROLLBAR_LINGER_MS = 600;
7
+ /* The theme hides the native bar of a scroller that carries this attribute. */
8
+ const OVERLAY_ATTRIBUTE = 'data-overlay-scrollbars';
9
+ /*
10
+ * Draws thin bars over `viewport`, a scroller that stays native, so wheel, keys, `scrollIntoView` and
11
+ * a virtualizer keep working on it. Put the returned element in a positioned ancestor whose box is
12
+ * the viewport's: the bars lie along its right and bottom edges.
13
+ */
14
+ export function useOverlayScrollbars(viewport, t0) {
15
+ const $ = _c(14);
16
+ let t1;
17
+ if ($[0] !== t0) {
18
+ t1 = t0 === undefined ? {} : t0;
19
+ $[0] = t0;
20
+ $[1] = t1;
21
+ } else {
22
+ t1 = $[1];
23
+ }
24
+ const {
25
+ axis: t2
26
+ } = t1;
27
+ const axis = t2 === undefined ? "y" : t2;
28
+ const [vertical, setVertical] = useState(null);
29
+ const [horizontal, setHorizontal] = useState(null);
30
+ let t3;
31
+ let t4;
32
+ if ($[2] !== horizontal || $[3] !== vertical || $[4] !== viewport) {
33
+ t3 = () => {
34
+ if (viewport === null) {
35
+ return;
36
+ }
37
+ const bars = [vertical, horizontal].filter(_temp).map(element_0 => ({
38
+ element: element_0,
39
+ thumb: element_0.firstElementChild,
40
+ vertical: element_0 === vertical
41
+ }));
42
+ let overBar = false;
43
+ let dragging = false;
44
+ let lingering = false;
45
+ let lingerTimer = 0;
46
+ const metricsOf = bar => bar.vertical ? {
47
+ track: bar.element.clientHeight,
48
+ view: viewport.clientHeight,
49
+ content: viewport.scrollHeight
50
+ } : {
51
+ track: bar.element.clientWidth,
52
+ view: viewport.clientWidth,
53
+ content: viewport.scrollWidth
54
+ };
55
+ const positionOf = bar_0 => bar_0.vertical ? viewport.scrollTop : viewport.scrollLeft;
56
+ const show = () => {
57
+ const visible = overBar || dragging || lingering;
58
+ for (const bar_1 of bars) {
59
+ bar_1.element.toggleAttribute("data-visible", visible);
60
+ }
61
+ };
62
+ const layout = () => {
63
+ const overflowing = bars.map(bar_2 => bar_2.vertical ? overflows(viewport.clientHeight, viewport.scrollHeight) : overflows(viewport.clientWidth, viewport.scrollWidth));
64
+ const corner = overflowing.length === 2 && overflowing.every(Boolean);
65
+ bars.forEach((bar_3, index) => {
66
+ bar_3.element.toggleAttribute("data-overflow", overflowing[index]);
67
+ bar_3.element.toggleAttribute("data-corner", corner);
68
+ });
69
+ bars.forEach((bar_4, index_0) => {
70
+ if (!overflowing[index_0]) {
71
+ return;
72
+ }
73
+ const {
74
+ size,
75
+ offset
76
+ } = thumbOf(metricsOf(bar_4), positionOf(bar_4));
77
+ if (bar_4.vertical) {
78
+ bar_4.thumb.style.height = `${size}px`;
79
+ bar_4.thumb.style.translate = `0 ${offset}px`;
80
+ } else {
81
+ bar_4.thumb.style.width = `${size}px`;
82
+ bar_4.thumb.style.translate = `${offset}px 0`;
83
+ }
84
+ });
85
+ };
86
+ const linger = () => {
87
+ lingering = true;
88
+ window.clearTimeout(lingerTimer);
89
+ lingerTimer = window.setTimeout(() => {
90
+ lingering = false;
91
+ show();
92
+ }, SCROLLBAR_LINGER_MS);
93
+ show();
94
+ };
95
+ const onScroll = () => {
96
+ layout();
97
+ linger();
98
+ };
99
+ const onBarEnter = event => {
100
+ if (event.pointerType !== "touch") {
101
+ overBar = true;
102
+ show();
103
+ }
104
+ };
105
+ const onBarLeave = () => {
106
+ if (overBar) {
107
+ overBar = false;
108
+ linger();
109
+ }
110
+ };
111
+ const reducedMotion = _temp2;
112
+ const pressHandlers = bars.map(bar_5 => {
113
+ const onThumbDown = event_0 => {
114
+ if (event_0.button !== 0) {
115
+ return;
116
+ }
117
+ event_0.preventDefault();
118
+ event_0.stopPropagation();
119
+ bar_5.thumb.setPointerCapture(event_0.pointerId);
120
+ const metrics = metricsOf(bar_5);
121
+ const from = bar_5.vertical ? event_0.clientY : event_0.clientX;
122
+ const start = positionOf(bar_5);
123
+ dragging = true;
124
+ bar_5.element.setAttribute("data-dragging", "");
125
+ viewport.setAttribute("data-scrollbar-dragging", "");
126
+ show();
127
+ const onMove = move => {
128
+ const next = scrollAfterDrag(metrics, start, (bar_5.vertical ? move.clientY : move.clientX) - from);
129
+ if (bar_5.vertical) {
130
+ viewport.scrollTop = next;
131
+ } else {
132
+ viewport.scrollLeft = next;
133
+ }
134
+ };
135
+ const onEnd = () => {
136
+ bar_5.thumb.removeEventListener("pointermove", onMove);
137
+ bar_5.thumb.removeEventListener("pointerup", onEnd);
138
+ bar_5.thumb.removeEventListener("pointercancel", onEnd);
139
+ bar_5.thumb.removeEventListener("lostpointercapture", onEnd);
140
+ dragging = false;
141
+ bar_5.element.removeAttribute("data-dragging");
142
+ viewport.removeAttribute("data-scrollbar-dragging");
143
+ linger();
144
+ };
145
+ bar_5.thumb.addEventListener("pointermove", onMove);
146
+ bar_5.thumb.addEventListener("pointerup", onEnd);
147
+ bar_5.thumb.addEventListener("pointercancel", onEnd);
148
+ bar_5.thumb.addEventListener("lostpointercapture", onEnd);
149
+ };
150
+ const onThumbTouch = _temp3;
151
+ const onTrackDown = event_2 => {
152
+ if (event_2.button !== 0) {
153
+ return;
154
+ }
155
+ event_2.preventDefault();
156
+ const thumb = bar_5.thumb.getBoundingClientRect();
157
+ const delta = bar_5.vertical ? pageToward(event_2.clientY, thumb.top, thumb.bottom, viewport.clientHeight) : pageToward(event_2.clientX, thumb.left, thumb.right, viewport.clientWidth);
158
+ if (delta === 0) {
159
+ return;
160
+ }
161
+ const behavior = reducedMotion() ? "instant" : "smooth";
162
+ viewport.scrollBy(bar_5.vertical ? {
163
+ top: delta,
164
+ behavior
165
+ } : {
166
+ left: delta,
167
+ behavior
168
+ });
169
+ };
170
+ bar_5.thumb.addEventListener("pointerdown", onThumbDown);
171
+ bar_5.thumb.addEventListener("touchstart", onThumbTouch, {
172
+ passive: false
173
+ });
174
+ bar_5.element.addEventListener("pointerdown", onTrackDown);
175
+ bar_5.element.addEventListener("pointerenter", onBarEnter);
176
+ bar_5.element.addEventListener("pointerleave", onBarLeave);
177
+ return () => {
178
+ bar_5.thumb.removeEventListener("pointerdown", onThumbDown);
179
+ bar_5.thumb.removeEventListener("touchstart", onThumbTouch);
180
+ bar_5.element.removeEventListener("pointerdown", onTrackDown);
181
+ bar_5.element.removeEventListener("pointerenter", onBarEnter);
182
+ bar_5.element.removeEventListener("pointerleave", onBarLeave);
183
+ };
184
+ });
185
+ const sizes = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(layout);
186
+ sizes?.observe(viewport);
187
+ const observeContent = () => {
188
+ for (const child of viewport.children) {
189
+ sizes?.observe(child);
190
+ }
191
+ };
192
+ const content = typeof MutationObserver === "undefined" ? null : new MutationObserver(() => {
193
+ observeContent();
194
+ layout();
195
+ });
196
+ content?.observe(viewport, {
197
+ childList: true
198
+ });
199
+ observeContent();
200
+ viewport.setAttribute(OVERLAY_ATTRIBUTE, "");
201
+ viewport.addEventListener("scroll", onScroll, {
202
+ passive: true
203
+ });
204
+ layout();
205
+ return () => {
206
+ for (const release of pressHandlers) {
207
+ release();
208
+ }
209
+ sizes?.disconnect();
210
+ content?.disconnect();
211
+ window.clearTimeout(lingerTimer);
212
+ viewport.removeAttribute(OVERLAY_ATTRIBUTE);
213
+ viewport.removeAttribute("data-scrollbar-dragging");
214
+ viewport.removeEventListener("scroll", onScroll);
215
+ };
216
+ };
217
+ t4 = [viewport, vertical, horizontal];
218
+ $[2] = horizontal;
219
+ $[3] = vertical;
220
+ $[4] = viewport;
221
+ $[5] = t3;
222
+ $[6] = t4;
223
+ } else {
224
+ t3 = $[5];
225
+ t4 = $[6];
226
+ }
227
+ useLayoutEffect(t3, t4);
228
+ let t5;
229
+ if ($[7] !== axis) {
230
+ t5 = axis !== "x" && /*#__PURE__*/_jsx("div", {
231
+ ref: setVertical,
232
+ "aria-hidden": true,
233
+ className: "ade-scrollbar",
234
+ "data-orientation": "vertical",
235
+ children: /*#__PURE__*/_jsx("div", {
236
+ className: "ade-scrollbar-thumb"
237
+ })
238
+ });
239
+ $[7] = axis;
240
+ $[8] = t5;
241
+ } else {
242
+ t5 = $[8];
243
+ }
244
+ let t6;
245
+ if ($[9] !== axis) {
246
+ t6 = axis !== "y" && /*#__PURE__*/_jsx("div", {
247
+ ref: setHorizontal,
248
+ "aria-hidden": true,
249
+ className: "ade-scrollbar",
250
+ "data-orientation": "horizontal",
251
+ children: /*#__PURE__*/_jsx("div", {
252
+ className: "ade-scrollbar-thumb"
253
+ })
254
+ });
255
+ $[9] = axis;
256
+ $[10] = t6;
257
+ } else {
258
+ t6 = $[10];
259
+ }
260
+ let t7;
261
+ if ($[11] !== t5 || $[12] !== t6) {
262
+ t7 = /*#__PURE__*/_jsxs(_Fragment, {
263
+ children: [t5, t6]
264
+ });
265
+ $[11] = t5;
266
+ $[12] = t6;
267
+ $[13] = t7;
268
+ } else {
269
+ t7 = $[13];
270
+ }
271
+ return t7;
272
+ }
273
+ function _temp3(event_1) {
274
+ event_1.preventDefault();
275
+ }
276
+ function _temp2() {
277
+ return window.matchMedia?.("(prefers-reduced-motion: reduce)").matches ?? false;
278
+ }
279
+ function _temp(element) {
280
+ return element !== null;
281
+ }
@@ -1,8 +1,8 @@
1
1
  import { c as _c } from "react/compiler-runtime";
2
- import { useEffect, useRef, useState } from 'react';
3
- import { createPortal } from 'react-dom';
4
2
  import clsx from 'clsx';
5
3
  import { MoreHorizontal } from 'lucide-react';
4
+ import { useEffect, useRef, useState } from 'react';
5
+ import { createPortal } from 'react-dom';
6
6
  import { useTranslation } from 'react-i18next';
7
7
  import { CloseButton } from "../CloseButton.js";
8
8
  import * as ContextMenu from '../context-menu/index.parts.js';
@@ -1,5 +1,5 @@
1
- import { type DragEvent, type ReactNode } from 'react';
2
1
  import { useRender } from '@base-ui/react/use-render';
2
+ import { type DragEvent, type ReactNode } from 'react';
3
3
  import { type WorkspaceLayout } from './context.ts';
4
4
  import { type SplitEdges, type SplitMinimum, type SplitRect } from './geometry.ts';
5
5
  import { type SplitCommand, type SplitLayout, type SplitPane } from './model.ts';
@@ -1,16 +1,16 @@
1
1
  import { c as _c } from "react/compiler-runtime";
2
- import { useCallback, useContext, useEffect, useId, useLayoutEffect, useRef, useState } from 'react';
3
2
  import { useRender } from '@base-ui/react/use-render';
4
- import { GripVertical, Maximize2, Minimize2 } from 'lucide-react';
5
3
  import clsx from 'clsx';
4
+ import { GripVertical, Maximize2, Minimize2 } from 'lucide-react';
5
+ import { useCallback, useContext, useEffect, useId, useLayoutEffect, useRef, useState } from 'react';
6
6
  import { useTranslation } from 'react-i18next';
7
7
  import { IconButton } from "../IconButton.js";
8
8
  import { WorkspaceContext } from './context.js';
9
+ import { DropPreview } from "./DropPreview.js";
9
10
  import { paneRadius, resizeSplit, splitGeometry, splitSideAt, tabGapAt } from './geometry.js';
10
11
  import { splitPanes, updateSplitLayout } from './model.js';
11
- import { TabStrip } from "./TabStrip.js";
12
- import { DropPreview } from "./DropPreview.js";
13
12
  import { rectDropPreview, sameDropPreview, tabDropPreview } from './preview.js';
13
+ import { TabStrip } from "./TabStrip.js";
14
14
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
15
15
  const ZERO = {
16
16
  width: 0,
@@ -1,5 +1,5 @@
1
- import { type DragEvent, type MouseEvent, type ReactNode } from 'react';
2
1
  import { useRender } from '@base-ui/react/use-render';
2
+ import { type DragEvent, type MouseEvent, type ReactNode } from 'react';
3
3
  import { type IconButtonProps } from '../IconButton.tsx';
4
4
  export interface TabStripItem {
5
5
  id: string;
@@ -1,8 +1,8 @@
1
1
  import { c as _c } from "react/compiler-runtime";
2
- import { createContext, useContext, useEffect, useLayoutEffect, useRef, useState } from 'react';
3
2
  import { useRender } from '@base-ui/react/use-render';
4
- import { Pin, X } from 'lucide-react';
5
3
  import clsx from 'clsx';
4
+ import { Pin, X } from 'lucide-react';
5
+ import { createContext, useContext, useEffect, useLayoutEffect, useRef, useState } from 'react';
6
6
  import { useTranslation } from 'react-i18next';
7
7
  import { Icon } from "../Icon.js";
8
8
  import { IconButton } from "../IconButton.js";
@@ -1,5 +1,5 @@
1
- import { type ReactNode } from 'react';
2
1
  import { useRender } from '@base-ui/react/use-render';
2
+ import { type ReactNode } from 'react';
3
3
  import { type WorkspaceLayout } from './context.ts';
4
4
  export interface WorkspaceProps extends useRender.ComponentProps<'div'> {
5
5
  layout?: WorkspaceLayout;
@@ -1,7 +1,7 @@
1
1
  import { c as _c } from "react/compiler-runtime";
2
- import { useState } from 'react';
3
- import clsx from 'clsx';
4
2
  import { useRender } from '@base-ui/react/use-render';
3
+ import clsx from 'clsx';
4
+ import { useState } from 'react';
5
5
  import { TopRowSlotContext, WorkspaceContext } from './context.js';
6
6
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
7
7
  const isPresent = node => node !== undefined && node !== null && node !== false;
@@ -1,7 +1,7 @@
1
1
  import { c as _c } from "react/compiler-runtime";
2
+ import { useRender } from '@base-ui/react/use-render';
2
3
  import clsx from 'clsx';
3
4
  import { useTranslation } from 'react-i18next';
4
- import { useRender } from '@base-ui/react/use-render';
5
5
  /**
6
6
  * The column of buttons at the right edge of a `Workspace`, 48 pixels wide. Its first separator stands on
7
7
  * the top row's bottom line when one 32 pixel button comes before it. It makes no stacking context, so a
@@ -1,6 +1,6 @@
1
1
  import { c as _c } from "react/compiler-runtime";
2
- import { useContext } from 'react';
3
2
  import clsx from 'clsx';
3
+ import { useContext } from 'react';
4
4
  import { TopRowSlotContext } from './context.js';
5
5
  /**
6
6
  * The 47 pixel band at the top of a `Workspace`'s sheet, as its `toolbar`: the project, and beside it the
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adecore/ui",
3
- "version": "0.53.2",
3
+ "version": "0.54.0",
4
4
  "description": "React components, a theme, formatters and a settings dialog for desktop-grade apps on React 19, Base UI and Tailwind 4.",
5
5
  "license": "FSL-1.1-MIT",
6
6
  "author": "Bas Milius",
@@ -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
@@ -1,6 +1,6 @@
1
- import type { ReactNode, Ref } from 'react';
2
1
  import clsx from 'clsx';
3
2
  import type { LucideIcon } from 'lucide-react';
3
+ import type { ReactNode, Ref } from 'react';
4
4
  import { Icon } from './Icon.tsx';
5
5
  import { Surface } from './Surface.tsx';
6
6
 
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';
@@ -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
  export type ButtonGroupProps = useRender.ComponentProps<'div'>;
5
5
 
package/src/Checkbox.tsx CHANGED
@@ -1,7 +1,7 @@
1
- import type { Ref } from 'react';
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 { Checkbox as BaseCheckbox } from '@base-ui/react/checkbox';
4
+ import type { Ref } from 'react';
5
5
  import { Icon } from './Icon.tsx';
6
6
 
7
7
  export interface CheckboxProps {
@@ -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> {
@@ -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
 
@@ -1,7 +1,7 @@
1
- import type { ComponentProps } from 'react';
1
+ import { useRender } from '@base-ui/react/use-render';
2
2
  import clsx from 'clsx';
3
3
  import { Check } from 'lucide-react';
4
- import { useRender } from '@base-ui/react/use-render';
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. */
@@ -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 {
@@ -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. */
@@ -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