@galaxy-io/dls 2.0.0 → 2.0.2

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 (40) hide show
  1. package/dist/charts/BarChart.js +29 -13
  2. package/dist/charts/ChartCategoryTargets.d.ts +2 -2
  3. package/dist/charts/ChartCategoryTargets.js +2 -1
  4. package/dist/charts/ChartFrame.d.ts +7 -5
  5. package/dist/charts/ChartFrame.js +151 -76
  6. package/dist/charts/ChartLegend.d.ts +14 -4
  7. package/dist/charts/ChartLegend.js +90 -53
  8. package/dist/charts/ChartMarkTargets.d.ts +2 -2
  9. package/dist/charts/ChartMarkTargets.js +2 -1
  10. package/dist/charts/Heatmap.js +19 -7
  11. package/dist/charts/LineChart.js +19 -8
  12. package/dist/charts/PieChart.js +16 -7
  13. package/dist/charts/chartSelection.d.ts +15 -0
  14. package/dist/charts/chartSelection.js +22 -0
  15. package/dist/charts/constants.d.ts +4 -0
  16. package/dist/charts/constants.js +6 -2
  17. package/dist/charts/types.d.ts +10 -1
  18. package/dist/charts/useChartInteraction.d.ts +25 -3
  19. package/dist/charts/useChartInteraction.js +56 -10
  20. package/dist/drawer/Drawer.d.ts +3 -1
  21. package/dist/drawer/Drawer.js +43 -14
  22. package/dist/feedback/Alert.d.ts +1 -1
  23. package/dist/inputs/CheckboxGroup.js +1 -1
  24. package/dist/inputs/CheckboxInput.js +1 -1
  25. package/dist/inputs/ColorInput.js +1 -1
  26. package/dist/inputs/CronInput.js +1 -1
  27. package/dist/inputs/DateInput.js +1 -1
  28. package/dist/inputs/KeyValueInput.js +1 -1
  29. package/dist/inputs/SelectInput.js +1 -1
  30. package/dist/inputs/SwitchInput.js +1 -1
  31. package/dist/inputs/TextAreaInput.js +6 -0
  32. package/dist/inputs/internal/ownField.js +1 -1
  33. package/dist/styles.css +1 -1
  34. package/dist/table/InfiniteSpreadsheet.js +1 -1
  35. package/dist/table/TableCore.js +69 -14
  36. package/dist/theme/tokens/light.js +4 -4
  37. package/dist/timeline/Timeline.d.ts +22 -1
  38. package/dist/timeline/Timeline.js +75 -43
  39. package/dist/tokens.css +4 -4
  40. package/package.json +5 -1
@@ -1,4 +1,6 @@
1
+ import { useControlledState } from "../hooks/useControlledState.js";
1
2
  import { ChartMarkState } from "./types.js";
3
+ import { isSameSelection, toSelectionList, toggleSelection } from "./chartSelection.js";
2
4
  import { ChartGroupContext } from "./ChartGroupProvider.js";
3
5
  import { useCallback, useContext, useEffect, useId, useMemo, useRef, useState } from "react";
4
6
  //#region src/charts/useChartInteraction.ts
@@ -15,10 +17,12 @@ import { useCallback, useContext, useEffect, useId, useMemo, useRef, useState }
15
17
  * follows the category a sibling engages (matched by raw label). Following emphasizes; it opens
16
18
  * the tooltip only when the provider shares tooltips. Series hover never syncs.
17
19
  *
18
- * And **selection**, supplied by the caller and never written here: it outranks hover. Clicks do
19
- * not pin anything; they only report (the 1.x rationale).
20
+ * And **selection**: the marks that hold full strength while the rest recede. Without
21
+ * `isFilterable` it is the caller's, presentational, and clicks only report. With `isFilterable`
22
+ * it is the chart's filter (controlled or not): legend and plot clicks toggle descriptors in it, and
23
+ * the filter chips' × or Escape clear it. A pinned selection outranks category hover; hovering a legend entry
24
+ * previews that series over it.
20
25
  */
21
- var NO_SELECTION = [];
22
26
  var NO_SELECTED_INDICES = /* @__PURE__ */ new Set();
23
27
  /** @internal The next index for a navigation key, stopping at the ends (no wrap). */
24
28
  function getNextCategoryIndex(current, key, count, grid) {
@@ -37,7 +41,7 @@ function getNextCategoryIndex(current, key, count, grid) {
37
41
  }
38
42
  }
39
43
  /** @internal Shared interaction model; see the module comment. */
40
- function useChartInteraction({ categoryCount, seriesKeys, categoryKeys, enableGroupSync = true, selection, categoryMuteState = ChartMarkState.MUTED, isDisabled = false, isLoading = false, grid }) {
44
+ function useChartInteraction({ categoryCount, seriesKeys, categoryKeys, enableGroupSync = true, selection, isFilterable = false, defaultSelection, onSelectionChange, categoryMuteState = ChartMarkState.MUTED, isDisabled = false, isLoading = false, grid }) {
41
45
  const [pointerIndex, setPointerIndex] = useState(null);
42
46
  const [keyboardIndex, setKeyboardIndex] = useState(null);
43
47
  const [hoveredSeriesKey, setHoveredSeriesKey] = useState(null);
@@ -116,12 +120,31 @@ function useChartInteraction({ categoryCount, seriesKeys, categoryKeys, enableGr
116
120
  setKeyboardIndex(null);
117
121
  }, []);
118
122
  const onKeyboardBlur = useCallback(() => setKeyboardIndex(null), []);
119
- const selectionList = useMemo(() => {
120
- if (selection === void 0 || selection === null) return NO_SELECTION;
121
- if (!Array.isArray(selection)) return [selection];
122
- return selection.length === 0 ? NO_SELECTION : selection;
123
- }, [selection]);
123
+ const [selectionList, setSelectionList] = useControlledState({
124
+ value: useMemo(() => selection === void 0 ? void 0 : toSelectionList(selection), [selection]),
125
+ defaultValue: isFilterable ? toSelectionList(defaultSelection) : [],
126
+ onChange: onSelectionChange
127
+ });
124
128
  const hasSelection = selectionList.length > 0;
129
+ const toggleSelection$1 = useCallback((descriptor, isAdditive) => {
130
+ if (!isFilterable) return;
131
+ setSelectionList(toggleSelection(selectionList, descriptor, isAdditive));
132
+ }, [
133
+ isFilterable,
134
+ selectionList,
135
+ setSelectionList
136
+ ]);
137
+ const setSelection = useCallback((next) => {
138
+ if (isFilterable) setSelectionList(next);
139
+ }, [isFilterable, setSelectionList]);
140
+ const clearSelection = useCallback(() => {
141
+ if (!isFilterable || selectionList.length === 0) return;
142
+ setSelectionList([]);
143
+ }, [
144
+ isFilterable,
145
+ selectionList,
146
+ setSelectionList
147
+ ]);
125
148
  /** A descriptor is a conjunction of the fields it carries; a field the mark lacks never excludes it. */
126
149
  const matchesSelection = useCallback(({ categoryIndex, seriesKey }) => {
127
150
  if (!hasSelection) return true;
@@ -151,24 +174,39 @@ function useChartInteraction({ categoryCount, seriesKeys, categoryKeys, enableGr
151
174
  ]);
152
175
  const getMarkState = useCallback(({ categoryIndex, seriesKey }) => {
153
176
  if (isLoading) return ChartMarkState.MUTED;
177
+ if (seriesKey !== void 0 && safeHoveredSeries !== null) return seriesKey === safeHoveredSeries ? ChartMarkState.ACTIVE : ChartMarkState.MUTED;
154
178
  if (!matchesSelection({
155
179
  categoryIndex,
156
180
  seriesKey
157
181
  })) return ChartMarkState.MUTED;
158
- if (seriesKey !== void 0 && safeHoveredSeries !== null && seriesKey !== safeHoveredSeries) return ChartMarkState.MUTED;
182
+ if (hasSelection) return ChartMarkState.ACTIVE;
159
183
  return categoryIndex !== void 0 && activeIndex !== null && categoryIndex !== activeIndex ? categoryMuteState : ChartMarkState.ACTIVE;
160
184
  }, [
161
185
  isLoading,
162
186
  matchesSelection,
163
187
  safeHoveredSeries,
188
+ hasSelection,
164
189
  activeIndex,
165
190
  categoryMuteState
166
191
  ]);
192
+ const getSeriesState = useCallback((seriesKey) => {
193
+ if (safeHoveredSeries !== null) return seriesKey === safeHoveredSeries ? ChartMarkState.ACTIVE : ChartMarkState.MUTED;
194
+ return matchesSelection({ seriesKey }) ? ChartMarkState.ACTIVE : ChartMarkState.MUTED;
195
+ }, [safeHoveredSeries, matchesSelection]);
196
+ const isSeriesPinned = useCallback((seriesKey) => isFilterable && selectionList.some((item) => isSameSelection(item, { seriesKey })), [isFilterable, selectionList]);
167
197
  return useMemo(() => ({
168
198
  activeIndex,
169
199
  showTooltip,
170
200
  hoveredSeriesKey: safeHoveredSeries,
171
201
  selectedCategoryIndices,
202
+ isFilterable,
203
+ hasSelection,
204
+ selection: selectionList,
205
+ toggleSelection: toggleSelection$1,
206
+ setSelection,
207
+ clearSelection,
208
+ getSeriesState,
209
+ isSeriesPinned,
172
210
  getMarkState,
173
211
  onCategoryEnter,
174
212
  onCategoryLeave,
@@ -183,6 +221,14 @@ function useChartInteraction({ categoryCount, seriesKeys, categoryKeys, enableGr
183
221
  showTooltip,
184
222
  safeHoveredSeries,
185
223
  selectedCategoryIndices,
224
+ isFilterable,
225
+ hasSelection,
226
+ selectionList,
227
+ toggleSelection$1,
228
+ setSelection,
229
+ clearSelection,
230
+ getSeriesState,
231
+ isSeriesPinned,
186
232
  getMarkState,
187
233
  onCategoryEnter,
188
234
  onCategoryLeave,
@@ -18,8 +18,10 @@ export declare enum DrawerSize {
18
18
  interface DrawerBaseProps extends AriaAttributes {
19
19
  /** The body. It scrolls when it is taller than the panel. A string or number renders as `Text`. */
20
20
  children?: ReactNode;
21
- /** The actions row, end-aligned with an 8px gap. */
21
+ /** The actions row, end-aligned with an 8px gap: what finishes the drawer's task (Cancel, then the `PRIMARY` Save). */
22
22
  footer?: ReactNode;
23
+ /** Controls in the title row, before the close button, for the thing the drawer shows: one or two icon-only `TERTIARY` `SMALL` buttons and a ⋯ `Menu` for the rest. Not for Save or Cancel (those are `footer`). */
24
+ actions?: ReactNode;
23
25
  /**
24
26
  * The edge the drawer sits on and slides from.
25
27
  * @default Side.RIGHT
@@ -8,6 +8,7 @@ import { OverlayLayer, useOverlay } from "../overlay/useOverlay.js";
8
8
  import { usePrefersReducedMotion } from "../hooks/usePrefersReducedMotion.js";
9
9
  import { OverlayNode } from "../overlay/OverlayProvider.js";
10
10
  import Button, { ButtonSize, ButtonVariant } from "../buttons/Button.js";
11
+ import { isDevelopment, useDevWarning } from "../inputs/internal/devWarn.js";
11
12
  import ResizeHandle from "../layout/ResizeHandle.js";
12
13
  import Fade from "../transform/Fade.js";
13
14
  /* empty css */
@@ -24,6 +25,11 @@ import { AnimatePresence, motion } from "framer-motion";
24
25
  * three regions (a title row, a scrolling body and an actions row), sits on any `side`, takes a
25
26
  * `size`, and with `isResizable` the user drags or keys its inner edge to resize it.
26
27
  *
28
+ * Actions split by what they do. `actions` in the title row, before the close button, act on the
29
+ * thing the drawer shows: one or two icon-only `TERTIARY` `SMALL` buttons (open in full page, copy
30
+ * link) and a ⋯ `Menu` for the rest (rename, duplicate, delete). `footer` finishes the drawer's
31
+ * task (Cancel, then the `PRIMARY` Save); a read-only detail drawer usually has no footer.
32
+ *
27
33
  * By default it is modal, like `Modal`: a portal over a dimmed, locked page with a focus trap,
28
34
  * stacked through the overlay stack, closing on Escape or a backdrop click. With
29
35
  * `isModal={false}` it is a docked panel: it renders in place in the layout and pushes the content
@@ -177,25 +183,37 @@ var Header = /*#__PURE__*/ styled("div")({
177
183
  });
178
184
  /** While the close button shows: a long title never runs under it. */
179
185
  var HAS_CLOSE_CSS = "gx-Drawer-HAS_CLOSE_CSS-hov58xm";
186
+ /** With `actions`, the close button joins them: the same 4px apart, one group at the row's end. */
187
+ var HAS_CLOSE_WITH_ACTIONS_CSS = "gx-Drawer-HAS_CLOSE_WITH_ACTIONS_CSS-hckczr5";
180
188
  /** A node `header`: takes the row and may shrink. */
181
189
  var HeaderNode = /*#__PURE__*/ styled("div")({
182
190
  name: "HeaderNode",
183
- class: "gx-Drawer-HeaderNode-hckczr5",
191
+ class: "gx-Drawer-HeaderNode-h1v64nx4",
192
+ propsAsIs: false
193
+ });
194
+ /** A string `header` takes the row too, so `actions` sit at its end. */
195
+ var HEADER_TITLE_CSS = "gx-Drawer-HEADER_TITLE_CSS-ht6k1c3";
196
+ /** `actions`: at the end of the title row, 4px apart and 4px before the close button. */
197
+ var HeaderActions = /*#__PURE__*/ styled("div")({
198
+ name: "HeaderActions",
199
+ class: "gx-Drawer-HeaderActions-h15lcrsa",
184
200
  propsAsIs: false
185
201
  });
202
+ /** More header controls than this crowd the title: the rest belong in the ⋯ menu. */
203
+ var DRAWER_MAX_HEADER_ACTIONS = 3;
186
204
  var Body = /*#__PURE__*/ styled("div")({
187
205
  name: "Body",
188
- class: "gx-Drawer-Body-b1v64nx4",
206
+ class: "gx-Drawer-Body-b1ob4oh8",
189
207
  propsAsIs: false
190
208
  });
191
209
  var Footer = /*#__PURE__*/ styled("div")({
192
210
  name: "Footer",
193
- class: "gx-Drawer-Footer-ft6k1c3",
211
+ class: "gx-Drawer-Footer-f14nwavk",
194
212
  propsAsIs: false
195
213
  });
196
214
  var CloseSlot = /*#__PURE__*/ styled("span")({
197
215
  name: "CloseSlot",
198
- class: "gx-Drawer-CloseSlot-c15lcrsa",
216
+ class: "gx-Drawer-CloseSlot-c1ifjfam",
199
217
  propsAsIs: false
200
218
  });
201
219
  /**
@@ -204,17 +222,17 @@ var CloseSlot = /*#__PURE__*/ styled("span")({
204
222
  * the stylesheet.
205
223
  */
206
224
  var DRAWER_SIDE_TO_HANDLE_CSS_MAP = {
207
- [Side.RIGHT]: "gx-Drawer-Side_RIGHT-s1ob4oh8",
208
- [Side.LEFT]: "gx-Drawer-Side_LEFT-s14nwavk",
209
- [Side.TOP]: "gx-Drawer-Side_TOP-s1ifjfam",
210
- [Side.BOTTOM]: "gx-Drawer-Side_BOTTOM-sv6fh8e"
225
+ [Side.RIGHT]: "gx-Drawer-Side_RIGHT-sv6fh8e",
226
+ [Side.LEFT]: "gx-Drawer-Side_LEFT-s1c8bwjq",
227
+ [Side.TOP]: "gx-Drawer-Side_TOP-s1vq4aq7",
228
+ [Side.BOTTOM]: "gx-Drawer-Side_BOTTOM-svqv727"
211
229
  };
212
230
  /** The viewport length on the side's axis, less the 48px strip. */
213
231
  function readMaxSize(side) {
214
232
  return (DRAWER_SIDE_TO_IS_HORIZONTAL_MAP[side] ? window.innerWidth : window.innerHeight) - DRAWER_VIEWPORT_GAP_PX;
215
233
  }
216
234
  /** A panel that slides in from an edge: title row, scrolling body, actions row. */
217
- var Drawer = forwardRef(function Drawer({ children, header, footer, side = Side.RIGHT, size = "MEDIUM", isResizable = false, isModal = true, isDismissable = true, isOpen: isOpenProp, defaultIsOpen = false, onOpenChange, ariaLabel, id, className, style, ...rest }, ref) {
235
+ var Drawer = forwardRef(function Drawer({ children, header, footer, actions, side = Side.RIGHT, size = "MEDIUM", isResizable = false, isModal = true, isDismissable = true, isOpen: isOpenProp, defaultIsOpen = false, onOpenChange, ariaLabel, id, className, style, ...rest }, ref) {
218
236
  const generatedId = useId();
219
237
  const titleId = useId();
220
238
  const panelId = id ?? generatedId;
@@ -261,22 +279,33 @@ var Drawer = forwardRef(function Drawer({ children, header, footer, side = Side.
261
279
  isBackdropPressRef.current = false;
262
280
  if (isBackdropPress && isDismissable) close();
263
281
  };
264
- const hasHeaderRow = header !== void 0 || isDismissable;
282
+ const hasHeaderRow = header !== void 0 || isDismissable || actions !== void 0;
283
+ const actionsRef = useRef(null);
284
+ const [actionCount, setActionCount] = useState(0);
285
+ useEffect(() => {
286
+ if (!isOpen || actions === void 0 || !isDevelopment()) return;
287
+ setActionCount(actionsRef.current?.querySelectorAll("button, a[href]").length ?? 0);
288
+ }, [isOpen, actions]);
289
+ useDevWarning(actionCount > DRAWER_MAX_HEADER_ACTIONS, "[@galaxy-io/dls] Drawer has more than three header `actions`. Keep one or two icon buttons and a ⋯ Menu, and move the rest into the menu.");
265
290
  const labelling = ariaLabel !== void 0 ? { "aria-label": ariaLabel } : rest["aria-labelledby"] !== void 0 || header === void 0 ? {} : { "aria-labelledby": titleId };
266
291
  const sizeStyle = { "--gx-drawer-size": `${currentSize}px` };
267
292
  const regions = /* @__PURE__ */ jsxs(Fragment$1, { children: [
268
- hasHeaderRow && /* @__PURE__ */ jsx(Header, {
269
- className: cx(isDismissable && HAS_CLOSE_CSS),
270
- children: typeof header === "string" ? /* @__PURE__ */ jsx(Text, {
293
+ hasHeaderRow && /* @__PURE__ */ jsxs(Header, {
294
+ className: cx(isDismissable && (actions === void 0 ? HAS_CLOSE_CSS : HAS_CLOSE_WITH_ACTIONS_CSS)),
295
+ children: [typeof header === "string" ? /* @__PURE__ */ jsx(Text, {
271
296
  as: "h2",
272
297
  size: TextSize.BODY_LG,
273
298
  weight: TextWeight.MEDIUM,
274
299
  id: titleId,
300
+ className: HEADER_TITLE_CSS,
275
301
  children: header
276
302
  }) : header !== void 0 ? /* @__PURE__ */ jsx(HeaderNode, {
277
303
  id: titleId,
278
304
  children: header
279
- }) : null
305
+ }) : /* @__PURE__ */ jsx(HeaderNode, {}), actions !== void 0 && /* @__PURE__ */ jsx(HeaderActions, {
306
+ ref: actionsRef,
307
+ children: actions
308
+ })]
280
309
  }),
281
310
  /* @__PURE__ */ jsx(Body, { children: typeof children === "string" || typeof children === "number" ? /* @__PURE__ */ jsx(Text, { children }) : children }),
282
311
  footer !== void 0 && /* @__PURE__ */ jsx(Footer, { children: footer }),
@@ -26,7 +26,7 @@ export interface AlertProps extends AriaAttributes {
26
26
  * @default the variant's icon
27
27
  */
28
28
  icon?: PhosphorIcon;
29
- /** The way out, usually one `Button` at `ButtonSize.SMALL`. A row under the body inline; trailing in a banner. */
29
+ /** The way out: one `ButtonVariant.PRIMARY` button at `ButtonSize.SMALL`, any second action `TERTIARY`. A row under the body inline; trailing in a banner. */
30
30
  actions?: ReactNode;
31
31
  /** Shows a dismiss button and is called when it is pressed. The host unmounts the Alert. */
32
32
  onDismiss?: () => void;
@@ -1,7 +1,7 @@
1
1
  import { Orientation } from "../theme/enums.js";
2
2
  import { useControlledState } from "../hooks/useControlledState.js";
3
- import { FieldContext } from "../hooks/useField.js";
4
3
  import { useDevWarning } from "./internal/devWarn.js";
4
+ import { FieldContext } from "../hooks/useField.js";
5
5
  import { useFieldWiring } from "./internal/fieldWiring.js";
6
6
  import CheckboxInput, { CheckboxInputSize, CheckboxInputVariant } from "./CheckboxInput.js";
7
7
  import Field, { FieldSize } from "./Field.js";
@@ -1,9 +1,9 @@
1
1
  import Text, { TextSize, TextVariant } from "../text/Text.js";
2
2
  import { useControlledState } from "../hooks/useControlledState.js";
3
3
  import Icon, { IconVariant, IconWeight } from "../icons/Icon.js";
4
+ import { useDevWarning } from "./internal/devWarn.js";
4
5
  import { useField } from "../hooks/useField.js";
5
6
  import RequiredMarker from "../text/RequiredMarker.js";
6
- import { useDevWarning } from "./internal/devWarn.js";
7
7
  import { hasContent, isFilled } from "./internal/predicates.js";
8
8
  import { joinIds } from "./internal/fieldWiring.js";
9
9
  /* empty css */
@@ -8,9 +8,9 @@ import Popover, { PopoverRole, PopoverTrigger, PopoverVariant } from "../overlay
8
8
  import Icon, { IconVariant } from "../icons/Icon.js";
9
9
  import Rotate from "../transform/Rotate.js";
10
10
  import Button, { ButtonSize, ButtonVariant } from "../buttons/Button.js";
11
+ import { isDevelopment, useDevWarning } from "./internal/devWarn.js";
11
12
  import { FieldContext } from "../hooks/useField.js";
12
13
  import { contrastRatio, hexToHsva, hexToRgb, hsvaToHex, rgbToHex } from "../utils/colors.js";
13
- import { isDevelopment, useDevWarning } from "./internal/devWarn.js";
14
14
  import { useFieldWiring } from "./internal/fieldWiring.js";
15
15
  import Field, { FieldSize } from "./Field.js";
16
16
  import { rootStyle, useOwnField } from "./internal/ownField.js";
@@ -4,8 +4,8 @@ import { useControlledState } from "../hooks/useControlledState.js";
4
4
  import Flex, { AlignItems } from "../layout/Flex.js";
5
5
  import Button, { ButtonSize, ButtonVariant } from "../buttons/Button.js";
6
6
  import ButtonGroup from "../buttons/ButtonGroup.js";
7
- import { FieldContext } from "../hooks/useField.js";
8
7
  import { useDevWarning } from "./internal/devWarn.js";
8
+ import { FieldContext } from "../hooks/useField.js";
9
9
  import { useFieldWiring } from "./internal/fieldWiring.js";
10
10
  import Field, { FieldSize } from "./Field.js";
11
11
  import { rootStyle, useOwnField } from "./internal/ownField.js";
@@ -10,8 +10,8 @@ import Popover, { PopoverRole, PopoverTrigger, PopoverVariant } from "../overlay
10
10
  import Icon, { IconVariant } from "../icons/Icon.js";
11
11
  import Button, { ButtonSize, ButtonVariant } from "../buttons/Button.js";
12
12
  import FlexItem from "../layout/FlexItem.js";
13
- import { FieldContext } from "../hooks/useField.js";
14
13
  import { useDevWarning } from "./internal/devWarn.js";
14
+ import { FieldContext } from "../hooks/useField.js";
15
15
  import { useFieldWiring } from "./internal/fieldWiring.js";
16
16
  import Field, { FieldSize } from "./Field.js";
17
17
  import { rootStyle, useOwnField } from "./internal/ownField.js";
@@ -1,8 +1,8 @@
1
1
  import { FontFamily } from "../theme/enums.js";
2
2
  import { useControlledState } from "../hooks/useControlledState.js";
3
3
  import Button, { ButtonSize, ButtonVariant } from "../buttons/Button.js";
4
- import { FieldContext } from "../hooks/useField.js";
5
4
  import { useDevWarning } from "./internal/devWarn.js";
5
+ import { FieldContext } from "../hooks/useField.js";
6
6
  import { isFilled } from "./internal/predicates.js";
7
7
  import { useFieldWiring } from "./internal/fieldWiring.js";
8
8
  import Field, { FieldSize } from "./Field.js";
@@ -11,10 +11,10 @@ import Popover, { PopoverRole, PopoverTrigger, PopoverVariant } from "../overlay
11
11
  import Icon, { IconVariant } from "../icons/Icon.js";
12
12
  import Rotate from "../transform/Rotate.js";
13
13
  import Button, { ButtonSize, ButtonVariant } from "../buttons/Button.js";
14
+ import { isDevelopment, useDevWarning } from "./internal/devWarn.js";
14
15
  import Spinner, { SpinnerSize } from "../feedback/Spinner.js";
15
16
  import { useDebouncedValue } from "../hooks/useDebouncedValue.js";
16
17
  import Span from "../text/Span.js";
17
- import { isDevelopment, useDevWarning } from "./internal/devWarn.js";
18
18
  import { hasContent, isFilled } from "./internal/predicates.js";
19
19
  import { useFieldWiring } from "./internal/fieldWiring.js";
20
20
  import Field, { FieldSize } from "./Field.js";
@@ -1,8 +1,8 @@
1
1
  import Text, { TextSize, TextVariant } from "../text/Text.js";
2
2
  import { useControlledState } from "../hooks/useControlledState.js";
3
+ import { useDevWarning } from "./internal/devWarn.js";
3
4
  import { useField } from "../hooks/useField.js";
4
5
  import Spinner, { SpinnerSize, SpinnerVariant } from "../feedback/Spinner.js";
5
- import { useDevWarning } from "./internal/devWarn.js";
6
6
  import { hasContent, isFilled } from "./internal/predicates.js";
7
7
  import { joinIds } from "./internal/fieldWiring.js";
8
8
  import { useIsBareField } from "./internal/bareField.js";
@@ -65,6 +65,12 @@ var Root = /*#__PURE__*/ styled("div")({
65
65
  * The field itself: the bordered element, so focus (`FIELD_FOCUS` on any focus: `border.focused` at 1px inside) and
66
66
  * the resize handle sit on the frame.
67
67
  */
68
+ /**
69
+ * What the padding gives back for the transparent hairline border. Chrome draws a 0.5px border a
70
+ * whole pixel wide, so padding that subtracted only 0.5px left two rows a pixel taller than the
71
+ * box: the textarea scrolled that pixel and swallowed the wheel instead of the page. Subtracting
72
+ * the full pixel fits exactly in Chrome and leaves half a pixel spare where the border is 0.5px.
73
+ */
68
74
  var Control = /*#__PURE__*/ styled("textarea")({
69
75
  name: "Control",
70
76
  class: "gx-TextAreaInput-Control-cu0hnok",
@@ -1,5 +1,5 @@
1
- import { useField } from "../../hooks/useField.js";
2
1
  import { useDevWarning } from "./devWarn.js";
2
+ import { useField } from "../../hooks/useField.js";
3
3
  import { isFilled } from "./predicates.js";
4
4
  import { cx } from "@linaria/core";
5
5
  //#region src/inputs/internal/ownField.tsx