@surflane/ui 0.12.0 → 0.13.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 (126) hide show
  1. package/dist/alert-dialog.d.ts +25 -7
  2. package/dist/alert-dialog.js +9 -4
  3. package/dist/autocomplete.d.ts +2 -6
  4. package/dist/avatar.d.ts +7 -7
  5. package/dist/avatar.js +2 -2
  6. package/dist/bar-list.js +7 -1
  7. package/dist/button.d.ts +6 -11
  8. package/dist/button.js +8 -8
  9. package/dist/card.d.ts +15 -10
  10. package/dist/card.js +7 -2
  11. package/dist/chart.d.ts +6 -4
  12. package/dist/chart.js +83 -19
  13. package/dist/choice.d.ts +2 -2
  14. package/dist/class-names.d.ts +0 -4
  15. package/dist/class-names.js +0 -14
  16. package/dist/code.d.ts +19 -7
  17. package/dist/code.js +32 -38
  18. package/dist/combobox.d.ts +2 -8
  19. package/dist/combobox.js +2 -2
  20. package/dist/context-menu.d.ts +2 -8
  21. package/dist/context-menu.js +2 -2
  22. package/dist/css/rules/alert-dialog.css +4 -2
  23. package/dist/css/rules/app-shell.css +47 -10
  24. package/dist/css/rules/bar-list.css +2 -2
  25. package/dist/css/rules/bar.css +5 -12
  26. package/dist/css/rules/bottom-navigation.css +5 -2
  27. package/dist/css/rules/breadcrumbs.css +0 -6
  28. package/dist/css/rules/button.css +4 -12
  29. package/dist/css/rules/card.css +14 -0
  30. package/dist/css/rules/chart.css +13 -5
  31. package/dist/css/rules/choice.css +26 -2
  32. package/dist/css/rules/combobox.css +17 -16
  33. package/dist/css/rules/dashboard.css +53 -1
  34. package/dist/css/rules/date-picker.css +50 -27
  35. package/dist/css/rules/dialog.css +38 -9
  36. package/dist/css/rules/disclosure.css +17 -3
  37. package/dist/css/rules/field-control.css +9 -6
  38. package/dist/css/rules/file-upload.css +9 -5
  39. package/dist/css/rules/filter-bar.css +24 -1
  40. package/dist/css/rules/gauge.css +2 -2
  41. package/dist/css/rules/icon.css +0 -5
  42. package/dist/css/rules/input-group.css +23 -8
  43. package/dist/css/rules/link.css +0 -6
  44. package/dist/css/rules/menu.css +5 -2
  45. package/dist/css/rules/menubar.css +1 -1
  46. package/dist/css/rules/navigation-menu.css +31 -26
  47. package/dist/css/rules/number-field.css +8 -1
  48. package/dist/css/rules/otp-field.css +13 -3
  49. package/dist/css/rules/page-header.css +10 -0
  50. package/dist/css/rules/panel.css +51 -10
  51. package/dist/css/rules/popup.css +50 -0
  52. package/dist/css/rules/preview-card.css +0 -21
  53. package/dist/css/rules/scroll-area.css +20 -1
  54. package/dist/css/rules/select.css +4 -1
  55. package/dist/css/rules/sizing.css +15 -3
  56. package/dist/css/rules/skeleton.css +1 -1
  57. package/dist/css/rules/slider.css +16 -8
  58. package/dist/css/rules/spinner.css +1 -1
  59. package/dist/css/rules/stat.css +9 -0
  60. package/dist/css/rules/tabs.css +14 -6
  61. package/dist/css/rules/textarea.css +28 -0
  62. package/dist/css/rules/toast.css +3 -1
  63. package/dist/css/rules/toggle.css +10 -3
  64. package/dist/css/rules/toolbar.css +10 -3
  65. package/dist/css/rules/tree.css +29 -4
  66. package/dist/dashboard.d.ts +19 -7
  67. package/dist/dashboard.js +30 -5
  68. package/dist/date-picker.d.ts +32 -3
  69. package/dist/date-picker.js +43 -4
  70. package/dist/dialog.d.ts +25 -7
  71. package/dist/dialog.js +9 -4
  72. package/dist/drawer.d.ts +10 -2
  73. package/dist/drawer.js +6 -3
  74. package/dist/icon.d.ts +5 -5
  75. package/dist/icon.js +5 -3
  76. package/dist/index.d.ts +3 -3
  77. package/dist/index.js +2 -2
  78. package/dist/inline-message.d.ts +2 -2
  79. package/dist/inline-message.js +7 -2
  80. package/dist/input.d.ts +2 -2
  81. package/dist/layout.d.ts +1 -3
  82. package/dist/layout.js +2 -2
  83. package/dist/native-select.d.ts +2 -2
  84. package/dist/navigation-menu.d.ts +16 -0
  85. package/dist/navigation-menu.js +6 -1
  86. package/dist/page-header.d.ts +10 -2
  87. package/dist/page-header.js +3 -3
  88. package/dist/panel.d.ts +6 -3
  89. package/dist/panel.js +2 -2
  90. package/dist/parts.d.ts +7 -3
  91. package/dist/parts.js +12 -4
  92. package/dist/popover.d.ts +6 -6
  93. package/dist/popover.js +3 -2
  94. package/dist/preview-card.d.ts +2 -8
  95. package/dist/preview-card.js +2 -2
  96. package/dist/select.d.ts +7 -4
  97. package/dist/select.js +23 -8
  98. package/dist/sheet.d.ts +10 -2
  99. package/dist/sheet.js +6 -3
  100. package/dist/size.d.ts +8 -6
  101. package/dist/size.js +2 -7
  102. package/dist/sizing.d.ts +13 -6
  103. package/dist/sizing.js +13 -4
  104. package/dist/sparkline.d.ts +2 -2
  105. package/dist/sparkline.js +2 -2
  106. package/dist/spinner.d.ts +2 -2
  107. package/dist/spinner.js +2 -2
  108. package/dist/stat.d.ts +6 -2
  109. package/dist/stat.js +2 -2
  110. package/dist/table.d.ts +12 -4
  111. package/dist/table.js +8 -3
  112. package/dist/textarea.d.ts +6 -3
  113. package/dist/textarea.js +2 -2
  114. package/dist/time-range-picker.d.ts +2 -2
  115. package/dist/time-range-picker.js +2 -2
  116. package/dist/toggle.d.ts +2 -2
  117. package/dist/toggle.js +2 -2
  118. package/dist/toolbar.d.ts +11 -10
  119. package/dist/toolbar.js +23 -1
  120. package/dist/tooltip.d.ts +1 -3
  121. package/dist/tooltip.js +4 -2
  122. package/dist/tree.d.ts +1 -3
  123. package/dist/tree.js +2 -2
  124. package/dist/typography.d.ts +10 -3
  125. package/dist/typography.js +4 -3
  126. package/package.json +3 -3
package/dist/select.js CHANGED
@@ -4,9 +4,21 @@ import * as React from 'react';
4
4
  import { Icon } from './icon.js';
5
5
  import { useComponentSize } from './sizing.js';
6
6
  import { Select as BaseSelect } from '@base-ui/react/select';
7
- import { sizeName, cx } from './parts.js';
7
+ import { cx, usePortalDirection } from './parts.js';
8
8
  const isGroup = (item) => 'options' in item;
9
9
  const flatten = (items) => items.flatMap((item) => (isGroup(item) ? item.options : [item]));
10
+ /** What a form reset reports: it has already happened, so it can't be canceled. */
11
+ function resetDetails(event) {
12
+ return {
13
+ reason: 'none',
14
+ event,
15
+ trigger: undefined,
16
+ cancel() { },
17
+ allowPropagation() { },
18
+ isCanceled: false,
19
+ isPropagationAllowed: false,
20
+ };
21
+ }
10
22
  const multipleLabels = {
11
23
  all: 'All',
12
24
  none: 'None',
@@ -19,6 +31,7 @@ const ALL = '\u0000all';
19
31
  export const Select = function Select(allProps) {
20
32
  const { options: items, className, inputRef, triggerRef, size, width = 'fill', ref, multiple, value: _value, defaultValue: _defaultValue, onValueChange: _onValueChange, labels: _labels, ...props } = allProps;
21
33
  const scheme = useComponentSize(size);
34
+ const dir = usePortalDirection();
22
35
  const options = flatten(items);
23
36
  // One stable callback, so the trigger ref is not detached on every render.
24
37
  const setTrigger = React.useCallback((node) => {
@@ -51,7 +64,7 @@ export const Select = function Select(allProps) {
51
64
  setLocalValue(initialValue);
52
65
  resetCallback.current?.((Array.isArray(initialValue)
53
66
  ? [...initialValue]
54
- : initialValue));
67
+ : initialValue), resetDetails(event));
55
68
  }, 0);
56
69
  pending.add(timer);
57
70
  };
@@ -101,7 +114,7 @@ export const Select = function Select(allProps) {
101
114
  ...options.map((option) => option.label),
102
115
  ]
103
116
  : options.map((option) => option.label);
104
- return (_jsx("span", { className: cx('surf-select', className), "data-size": sizeName(size), "data-ui-size": scheme, "data-width": width, "data-disabled": disabled || undefined, children: _jsxs(BaseSelect.Root, { items: options, multiple: multiple, value: selected, onValueChange: (next) => {
117
+ return (_jsx("span", { className: cx('surf-select', className), "data-size": size, "data-ui-size": scheme, "data-width": width, "data-disabled": disabled || undefined, children: _jsxs(BaseSelect.Root, { items: options, multiple: multiple, value: selected, onValueChange: (next, eventDetails) => {
105
118
  if (many) {
106
119
  const list = next ?? [];
107
120
  const toggledAll = list.includes(ALL) !== everything;
@@ -111,12 +124,14 @@ export const Select = function Select(allProps) {
111
124
  : choosable.map((option) => option.value)
112
125
  : // Unchecking one option of "all" leaves the others.
113
126
  list.filter((item) => item !== ALL);
114
- setLocalValue(values);
115
- many.onValueChange?.(values);
127
+ many.onValueChange?.(values, eventDetails);
128
+ if (!eventDetails.isCanceled)
129
+ setLocalValue(values);
116
130
  }
117
131
  else {
118
- setLocalValue(next ?? '');
119
- one.onValueChange?.(next ?? '');
132
+ one.onValueChange?.(next ?? '', eventDetails);
133
+ if (!eventDetails.isCanceled)
134
+ setLocalValue(next ?? '');
120
135
  }
121
136
  }, inputRef: setInput,
122
137
  // A multiple Select submits its own inputs, without the "all" value.
@@ -125,7 +140,7 @@ export const Select = function Select(allProps) {
125
140
  // trigger is as wide as the longest.
126
141
  _jsxs("span", { className: 'surf-select-sizer', children: [_jsx("span", { className: 'surf-select-value', children: value }), sizes.map((label, index) => (_jsx("span", { "aria-hidden": 'true', children: label }, index)))] })) : many ? (_jsx("span", { className: 'surf-select-value', children: value })) : (value), _jsx(BaseSelect.Icon, { className: 'surf-select-icon', children: _jsx(Icon, { name: 'chevron-down' }) })] }), many &&
127
142
  name &&
128
- chosen.map((item) => (_jsx("input", { type: 'hidden', name: name, value: item, form: form }, item))), _jsx(BaseSelect.Portal, { children: _jsx(BaseSelect.Positioner, { className: 'surf-positioner', sideOffset: 6, alignItemWithTrigger: false, children: _jsx(BaseSelect.Popup, { className: 'surf-select-popup', "data-ui-size": scheme, children: _jsxs(BaseSelect.List, { children: [many && (_jsxs(_Fragment, { children: [renderOption({
143
+ chosen.map((item) => (_jsx("input", { type: 'hidden', name: name, value: item, form: form }, item))), _jsx(BaseSelect.Portal, { children: _jsx(BaseSelect.Positioner, { dir: dir, className: 'surf-positioner', sideOffset: 6, alignItemWithTrigger: false, children: _jsx(BaseSelect.Popup, { className: 'surf-select-popup', "data-ui-size": scheme, children: _jsxs(BaseSelect.List, { children: [many && (_jsxs(_Fragment, { children: [renderOption({
129
144
  value: ALL,
130
145
  label: text.all,
131
146
  disabled: choosable.length === 0,
package/dist/sheet.d.ts CHANGED
@@ -4,14 +4,22 @@ import { Footer, Header, type PanelOptions, type PanelSide } from './panel.js';
4
4
  declare function SheetRoot({ side, modal, ...props }: React.ComponentProps<typeof BaseDialog.Root> & {
5
5
  side?: PanelSide;
6
6
  }): React.JSX.Element;
7
- declare const SheetContent: ({ size, flush, closeLabel, className, children, ref, ...props }: React.ComponentPropsWithoutRef<typeof BaseDialog.Popup> & PanelOptions & {
7
+ declare const SheetContent: ({ size, flush, closeLabel, focusBoundaryLabel, className, children, ref, ...props }: React.ComponentPropsWithoutRef<typeof BaseDialog.Popup> & PanelOptions & {
8
+ /** Names the focus guards at the panel's edges, which VoiceOver reaches past
9
+ * the last control, as Dialog's do. */
10
+ focusBoundaryLabel?: string;
11
+ } & {
8
12
  ref?: React.Ref<HTMLDivElement>;
9
13
  }) => React.JSX.Element;
10
14
  declare function SheetTitle({ className, ...props }: React.ComponentProps<typeof BaseDialog.Title>): React.JSX.Element;
11
15
  declare function SheetDescription({ className, ...props }: React.ComponentProps<typeof BaseDialog.Description>): React.JSX.Element;
12
16
  export declare const Sheet: {
13
17
  Root: typeof SheetRoot;
14
- Content: ({ size, flush, closeLabel, className, children, ref, ...props }: React.ComponentPropsWithoutRef<typeof BaseDialog.Popup> & PanelOptions & {
18
+ Content: ({ size, flush, closeLabel, focusBoundaryLabel, className, children, ref, ...props }: React.ComponentPropsWithoutRef<typeof BaseDialog.Popup> & PanelOptions & {
19
+ /** Names the focus guards at the panel's edges, which VoiceOver reaches past
20
+ * the last control, as Dialog's do. */
21
+ focusBoundaryLabel?: string;
22
+ } & {
15
23
  ref?: React.Ref<HTMLDivElement>;
16
24
  }) => React.JSX.Element;
17
25
  Header: typeof Header;
package/dist/sheet.js CHANGED
@@ -2,7 +2,8 @@
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import * as React from 'react';
4
4
  import { Icon } from './icon.js';
5
- import { skin } from './parts.js';
5
+ import { useDialogFocusBoundary } from './dialog-focus.js';
6
+ import { skin, usePortalDirection } from './parts.js';
6
7
  import { useComponentSize, normalizeSize } from './sizing.js';
7
8
  import { Dialog as BaseDialog } from '@base-ui/react/dialog';
8
9
  import { Body, Footer, Header, } from './panel.js';
@@ -13,10 +14,12 @@ const SheetSide = /* @__PURE__ */ React.createContext({
13
14
  function SheetRoot({ side = 'right', modal = true, ...props }) {
14
15
  return (_jsx(SheetSide.Provider, { value: { side, modal }, children: _jsx(BaseDialog.Root, { ...props, modal: modal }) }));
15
16
  }
16
- const SheetContent = function SheetContent({ size, flush, closeLabel = 'Close panel', className, children, ref, ...props }) {
17
+ const SheetContent = function SheetContent({ size, flush, closeLabel = 'Close panel', focusBoundaryLabel = 'Continue panel navigation', className, children, ref, ...props }) {
17
18
  const scheme = useComponentSize(size);
19
+ const dir = usePortalDirection();
20
+ const portalRef = useDialogFocusBoundary(focusBoundaryLabel);
18
21
  const { side, modal } = React.useContext(SheetSide);
19
- return (_jsx(BaseDialog.Portal, { children: _jsxs("div", { className: 'surf-panel-layer', "data-ui-size": scheme, children: [modal === true && (_jsx(BaseDialog.Backdrop, { className: 'surf-panel-backdrop' })), _jsx("div", { className: 'surf-panel-viewport', "data-side": side, "data-flush": flush || undefined, children: _jsxs(BaseDialog.Popup, { ...props, ref: ref, className: skin('surf-panel', className), "data-side": side, "data-size": normalizeSize(size) ?? 'default', "data-flush": flush || undefined, children: [_jsx(BaseDialog.Close, { className: 'surf-panel-close surf-icon-button', "aria-label": closeLabel, children: _jsx(Icon, { name: 'close' }) }), children] }) })] }) }));
22
+ return (_jsx(BaseDialog.Portal, { ref: portalRef, children: _jsxs("div", { className: 'surf-panel-layer', "data-ui-size": scheme, children: [modal === true && (_jsx(BaseDialog.Backdrop, { className: 'surf-panel-backdrop' })), _jsx("div", { className: 'surf-panel-viewport', "data-side": side, "data-flush": flush || undefined, children: _jsxs(BaseDialog.Popup, { dir: dir, ...props, ref: ref, className: skin('surf-panel', className), "data-side": side, "data-size": normalizeSize(size) ?? 'default', "data-flush": flush || undefined, children: [_jsx(BaseDialog.Close, { className: 'surf-panel-close surf-icon-button', "aria-label": closeLabel, children: _jsx(Icon, { name: 'close' }) }), children] }) })] }) }));
20
23
  };
21
24
  function SheetTitle({ className, ...props }) {
22
25
  return (_jsx(BaseDialog.Title, { ...props, className: skin('surf-panel-title', className) }));
package/dist/size.d.ts CHANGED
@@ -1,7 +1,9 @@
1
1
  export type ComponentSize = 'small' | 'default' | 'large';
2
- /**
3
- * @deprecated The short spellings sm, md and lg render as small, default and large.
4
- * Write the full names; the aliases are removed in a later minor.
5
- */
6
- export type ComponentSizeAlias = ComponentSize | 'sm' | 'md' | 'lg';
7
- export declare function normalizeSize(size?: ComponentSizeAlias): ComponentSize | undefined;
2
+ /** How tightly a screen packs its blocks: compact tightens gaps, insets and touch growth. */
3
+ export type ComponentDensity = 'default' | 'compact';
4
+ /** @deprecated The short spellings sm, md and lg were removed in 0.13, so this is
5
+ * ComponentSize under its former name. Write ComponentSize; this name is removed in a
6
+ * later minor. */
7
+ export type ComponentSizeAlias = ComponentSize;
8
+ /** A component's size: the one place components read it, kept for server components. */
9
+ export declare function normalizeSize(size?: ComponentSize): ComponentSize | undefined;
package/dist/size.js CHANGED
@@ -1,9 +1,4 @@
1
+ /** A component's size: the one place components read it, kept for server components. */
1
2
  export function normalizeSize(size) {
2
- return size === 'sm'
3
- ? 'small'
4
- : size === 'md'
5
- ? 'default'
6
- : size === 'lg'
7
- ? 'large'
8
- : size;
3
+ return size;
9
4
  }
package/dist/sizing.d.ts CHANGED
@@ -1,13 +1,20 @@
1
1
  import * as React from 'react';
2
- import { normalizeSize, type ComponentSize, type ComponentSizeAlias } from './size.js';
3
- export { normalizeSize, type ComponentSize, type ComponentSizeAlias };
2
+ import { normalizeSize, type ComponentDensity, type ComponentSize, type ComponentSizeAlias } from './size.js';
3
+ export { normalizeSize, type ComponentDensity, type ComponentSize, type ComponentSizeAlias, };
4
4
  export declare const ComponentSizeContext: React.Context<ComponentSize | undefined>;
5
5
  /** Explicit sizes override the surrounding scheme; portals retain React context. */
6
- export declare function useComponentSize(size?: ComponentSizeAlias): ComponentSize | undefined;
6
+ export declare function useComponentSize(size?: ComponentSize): ComponentSize | undefined;
7
+ export declare const ComponentDensityContext: React.Context<ComponentDensity | undefined>;
8
+ /** A component's own density, else the surrounding one, else default. */
9
+ export declare function useComponentDensity(density?: ComponentDensity): ComponentDensity;
7
10
  /** No layout box: grid/flex items and semantic children retain their own layout.
8
- * For table internals, place the provider outside the table, never inside tbody. */
9
- export declare function SizeProvider({ size, children, }: {
10
- size: ComponentSize;
11
+ * For table internals, place the provider outside the table, never inside tbody.
12
+ * Either prop may be left out to keep the surrounding size or density. */
13
+ export declare function SizeProvider({ size, density, children, }: {
14
+ size?: ComponentSize;
15
+ /** compact tightens the gaps and insets of the blocks inside, and keeps controls
16
+ * at their size on touch screens instead of growing them to 44px. */
17
+ density?: ComponentDensity;
11
18
  children: React.ReactNode;
12
19
  }): React.JSX.Element;
13
20
  /** The size context for a part a server component renders with an explicit size, so
package/dist/sizing.js CHANGED
@@ -2,17 +2,26 @@
2
2
  import { jsx as _jsx } from "react/jsx-runtime";
3
3
  import * as React from 'react';
4
4
  import { normalizeSize, } from './size.js';
5
- export { normalizeSize };
5
+ export { normalizeSize, };
6
6
  export const ComponentSizeContext = /* @__PURE__ */ React.createContext(undefined);
7
7
  /** Explicit sizes override the surrounding scheme; portals retain React context. */
8
8
  export function useComponentSize(size) {
9
9
  const inherited = React.useContext(ComponentSizeContext);
10
10
  return normalizeSize(size) ?? inherited;
11
11
  }
12
+ export const ComponentDensityContext = /* @__PURE__ */ React.createContext(undefined);
13
+ /** A component's own density, else the surrounding one, else default. */
14
+ export function useComponentDensity(density) {
15
+ const inherited = React.useContext(ComponentDensityContext);
16
+ return density ?? inherited ?? 'default';
17
+ }
12
18
  /** No layout box: grid/flex items and semantic children retain their own layout.
13
- * For table internals, place the provider outside the table, never inside tbody. */
14
- export function SizeProvider({ size, children, }) {
15
- return (_jsx(ComponentSizeContext.Provider, { value: size, children: _jsx("div", { className: 'surf-size-scope', "data-ui-size": size, children: children }) }));
19
+ * For table internals, place the provider outside the table, never inside tbody.
20
+ * Either prop may be left out to keep the surrounding size or density. */
21
+ export function SizeProvider({ size, density, children, }) {
22
+ const inheritedSize = React.useContext(ComponentSizeContext);
23
+ const inheritedDensity = React.useContext(ComponentDensityContext);
24
+ return (_jsx(ComponentSizeContext.Provider, { value: size ?? inheritedSize, children: _jsx(ComponentDensityContext.Provider, { value: density ?? inheritedDensity, children: _jsx("div", { className: 'surf-size-scope', "data-ui-size": size, "data-ui-density": density, children: children }) }) }));
16
25
  }
17
26
  /** The size context for a part a server component renders with an explicit size, so
18
27
  * the popups it portals keep that size. */
@@ -1,5 +1,5 @@
1
1
  import * as React from 'react';
2
- import type { ComponentSizeAlias } from './size.js';
2
+ import type { ComponentSize } from './size.js';
3
3
  export type SparklineTrend = 'auto' | 'up' | 'down' | 'flat' | 'neutral';
4
4
  export type SparklineProps = Omit<React.ComponentPropsWithoutRef<'svg'>, 'children' | 'role' | 'aria-label'> & {
5
5
  /** Values in order. A missing value leaves a gap. */
@@ -8,7 +8,7 @@ export type SparklineProps = Omit<React.ComponentPropsWithoutRef<'svg'>, 'childr
8
8
  * line is an image; this is its name. */
9
9
  label: string;
10
10
  /** 24, 32 or 48px tall. Set --surf-sparkline-height for another height. */
11
- size?: ComponentSizeAlias;
11
+ size?: ComponentSize;
12
12
  /** A reference line: a value, the first value, or none. */
13
13
  baseline?: number | 'first' | 'none';
14
14
  /** Marks the last value with a dot. */
package/dist/sparkline.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { cx, sizeName } from './class-names.js';
2
+ import { cx } from './class-names.js';
3
3
  const finite = (value) => typeof value === 'number' && Number.isFinite(value);
4
4
  /** A small trend line for cards and table cells: no axes, legend or tooltip. Use Chart
5
5
  * when people need to read values. */
@@ -41,7 +41,7 @@ export const Sparkline = function Sparkline({ data, label, size, baseline = 'non
41
41
  let end = data.length - 1;
42
42
  while (end >= 0 && !finite(data[end]))
43
43
  end--;
44
- return (_jsxs("svg", { ...props, ref: ref, role: 'img', "aria-label": label, className: cx('surf-sparkline', className), "data-size": sizeName(size), "data-tone": tone, viewBox: '0 0 100 100', preserveAspectRatio: 'none', focusable: 'false', children: [finite(reference) && (_jsx("path", { className: 'surf-sparkline-baseline', d: `M0 ${y(reference)}H100`, vectorEffect: 'non-scaling-stroke' })), _jsx("path", { className: 'surf-sparkline-line', d: path, vectorEffect: 'non-scaling-stroke' }), marker && end >= 0 && (
44
+ return (_jsxs("svg", { ...props, ref: ref, role: 'img', "aria-label": label, className: cx('surf-sparkline', className), "data-size": size, "data-tone": tone, viewBox: '0 0 100 100', preserveAspectRatio: 'none', focusable: 'false', children: [finite(reference) && (_jsx("path", { className: 'surf-sparkline-baseline', d: `M0 ${y(reference)}H100`, vectorEffect: 'non-scaling-stroke' })), _jsx("path", { className: 'surf-sparkline-line', d: path, vectorEffect: 'non-scaling-stroke' }), marker && end >= 0 && (
45
45
  // A zero-length segment with a round cap stays a circle however the
46
46
  // line stretches.
47
47
  _jsx("path", { className: 'surf-sparkline-marker', d: `M${x(end)} ${y(data[end])}h0`, vectorEffect: 'non-scaling-stroke' }))] }));
package/dist/spinner.d.ts CHANGED
@@ -1,9 +1,9 @@
1
1
  import * as React from 'react';
2
- import { type ComponentSizeAlias } from './size.js';
2
+ import { type ComponentSize } from './size.js';
3
3
  export type SpinnerProps = Omit<React.ComponentPropsWithoutRef<'span'>, 'children'> & {
4
4
  label?: string;
5
5
  decorative?: boolean;
6
- size?: ComponentSizeAlias;
6
+ size?: ComponentSize;
7
7
  };
8
8
  /** Use decorative within a loading region that already owns the announcement. */
9
9
  export declare const Spinner: ({ label, decorative, size, className, ref, ...props }: SpinnerProps & {
package/dist/spinner.js CHANGED
@@ -1,9 +1,9 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { normalizeSize } from './size.js';
3
- import { sizeName, cx } from './class-names.js';
3
+ import { cx } from './class-names.js';
4
4
  /** Use decorative within a loading region that already owns the announcement. */
5
5
  export const Spinner = function Spinner({ label = 'Loading', decorative = false, size, className, ref, ...props }) {
6
6
  // An omitted size follows the surrounding size scope through CSS.
7
7
  const scheme = normalizeSize(size);
8
- return (_jsxs("span", { ...props, ref: ref, className: cx('surf-spinner', className), "data-size": sizeName(size), "data-ui-size": scheme, role: decorative ? undefined : 'status', "aria-hidden": decorative || undefined, children: [_jsxs("svg", { viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor', strokeWidth: '2', "aria-hidden": 'true', children: [_jsx("circle", { cx: '12', cy: '12', r: '9', opacity: '.2' }), _jsx("path", { d: 'M12 3a9 9 0 0 1 9 9', strokeLinecap: 'round' })] }), !decorative && _jsx("span", { className: 'surf-feedback-sr', children: label })] }));
8
+ return (_jsxs("span", { ...props, ref: ref, className: cx('surf-spinner', className), "data-size": size, "data-ui-size": scheme, role: decorative ? undefined : 'status', "aria-hidden": decorative || undefined, children: [_jsxs("svg", { viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor', strokeWidth: '2', "aria-hidden": 'true', children: [_jsx("circle", { cx: '12', cy: '12', r: '9', opacity: '.2' }), _jsx("path", { d: 'M12 3a9 9 0 0 1 9 9', strokeLinecap: 'round' })] }), !decorative && _jsx("span", { className: 'surf-feedback-sr', children: label })] }));
9
9
  };
package/dist/stat.d.ts CHANGED
@@ -20,6 +20,10 @@ export type StatGroupProps = React.ComponentPropsWithoutRef<'div'> & {
20
20
  /** What every value in the group measures, such as "GPU temperature". It shows
21
21
  * above them and names the group. */
22
22
  label: string;
23
+ /** Names the group without showing the label, where a heading above already says
24
+ * it, such as the title of the Dashboard.Panel that holds the group. Give it a
25
+ * name of its own, such as "Free disk by node", so the two groups read apart. */
26
+ labelHidden?: boolean;
23
27
  };
24
28
  /** A key figure: what it measures, its value, how it moved and what it covers. Renders
25
29
  * a description list, so the label names the value for assistive technology. */
@@ -46,7 +50,7 @@ export declare const Stat: {
46
50
  size?: import("./size.js").ComponentSize;
47
51
  ref?: React.Ref<HTMLElement> | undefined;
48
52
  }) => React.JSX.Element;
49
- Group: ({ label, className, children, ref, ...props }: StatGroupProps & {
53
+ Group: ({ label, labelHidden, className, children, ref, ...props }: StatGroupProps & {
50
54
  ref?: React.Ref<HTMLDivElement>;
51
55
  }) => React.JSX.Element;
52
56
  };
@@ -66,6 +70,6 @@ export declare const StatRoot: ({ className, size, ref, ...rest }: Omit<Omit<Rea
66
70
  }) => React.JSX.Element, StatCaption: ({ className, size, ref, ...rest }: Omit<Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement>, "ref">, "size"> & {
67
71
  size?: import("./size.js").ComponentSize;
68
72
  ref?: React.Ref<HTMLElement> | undefined;
69
- }) => React.JSX.Element, StatGroup: ({ label, className, children, ref, ...props }: StatGroupProps & {
73
+ }) => React.JSX.Element, StatGroup: ({ label, labelHidden, className, children, ref, ...props }: StatGroupProps & {
70
74
  ref?: React.Ref<HTMLDivElement>;
71
75
  }) => React.JSX.Element;
package/dist/stat.js CHANGED
@@ -21,8 +21,8 @@ const StatusPart = function StatStatus({ tone, className, children, ref, ...prop
21
21
  };
22
22
  /** Several values of one measure side by side, such as one per node: a shared label
23
23
  * over Stat.Roots whose own labels name each. */
24
- const GroupPart = function StatGroup({ label, className, children, ref, ...props }) {
25
- return (_jsxs("div", { role: 'group', "aria-label": label, ...props, ref: ref, className: cx('surf-stat-group', className), children: [_jsx("span", { className: 'surf-stat-group-label', "aria-hidden": 'true', children: label }), _jsx("div", { className: 'surf-stat-group-items', children: children })] }));
24
+ const GroupPart = function StatGroup({ label, labelHidden = false, className, children, ref, ...props }) {
25
+ return (_jsxs("div", { role: 'group', "aria-label": label, ...props, ref: ref, className: cx('surf-stat-group', className), children: [!labelHidden && (_jsx("span", { className: 'surf-stat-group-label', "aria-hidden": 'true', children: label })), _jsx("div", { className: 'surf-stat-group-items', children: children })] }));
26
26
  };
27
27
  /** A key figure: what it measures, its value, how it moved and what it covers. Renders
28
28
  * a description list, so the label names the value for assistive technology. */
package/dist/table.d.ts CHANGED
@@ -15,7 +15,8 @@ declare const RootPart: ({ className, size, ref, ...rest }: Omit<Omit<React.Deta
15
15
  export type TableDensity = 'default' | 'compact';
16
16
  export type TableVariant = 'plain' | 'lined' | 'grid' | 'striped';
17
17
  declare const TableRoot: ({ density, variant, stickyHeader, ref, ...props }: React.ComponentPropsWithoutRef<typeof RootPart> & {
18
- /** compact tightens rows for scanning many records with a pointer. */
18
+ /** compact tightens rows for scanning many records with a pointer. Without it the
19
+ * table follows a SizeProvider density; default keeps it roomy inside a compact one. */
19
20
  density?: TableDensity;
20
21
  /**
21
22
  * plain separates rows by space; lined draws lines between rows, grid between
@@ -56,7 +57,10 @@ declare const TableSortHeader: ({ sort, onSort, disabled, children, className, r
56
57
  ref?: React.Ref<HTMLTableCellElement>;
57
58
  }) => React.JSX.Element;
58
59
  /** One-line text that ends in an ellipsis. String content also becomes the title. */
59
- declare const TableTruncate: ({ className, title, children, ref, ...props }: React.ComponentPropsWithoutRef<"span"> & {
60
+ declare const TableTruncate: ({ measure, className, title, style, children, ref, ...props }: React.ComponentPropsWithoutRef<"span"> & {
61
+ /** The widest it gets before the ellipsis, such as '44ch' for long image
62
+ * references; 32ch without it. */
63
+ measure?: string;
60
64
  ref?: React.Ref<HTMLSpanElement>;
61
65
  }) => React.JSX.Element;
62
66
  /** A full-width body row for loading, empty, error and permission messages. It has no hover. */
@@ -80,7 +84,8 @@ export declare const Table: {
80
84
  ref?: React.Ref<HTMLDivElement>;
81
85
  }) => React.JSX.Element;
82
86
  Root: ({ density, variant, stickyHeader, ref, ...props }: React.ComponentPropsWithoutRef<typeof RootPart> & {
83
- /** compact tightens rows for scanning many records with a pointer. */
87
+ /** compact tightens rows for scanning many records with a pointer. Without it the
88
+ * table follows a SizeProvider density; default keeps it roomy inside a compact one. */
84
89
  density?: TableDensity;
85
90
  /**
86
91
  * plain separates rows by space; lined draws lines between rows, grid between
@@ -126,7 +131,10 @@ export declare const Table: {
126
131
  Cell: ({ align, numeric, ref, ...props }: Omit<React.ComponentPropsWithoutRef<typeof CellPart>, "align"> & CellLayout & {
127
132
  ref?: React.Ref<HTMLTableCellElement>;
128
133
  }) => React.JSX.Element;
129
- Truncate: ({ className, title, children, ref, ...props }: React.ComponentPropsWithoutRef<"span"> & {
134
+ Truncate: ({ measure, className, title, style, children, ref, ...props }: React.ComponentPropsWithoutRef<"span"> & {
135
+ /** The widest it gets before the ellipsis, such as '44ch' for long image
136
+ * references; 32ch without it. */
137
+ measure?: string;
130
138
  ref?: React.Ref<HTMLSpanElement>;
131
139
  }) => React.JSX.Element;
132
140
  Message: ({ className, ref, ...props }: React.ComponentPropsWithoutRef<"td"> & {
package/dist/table.js CHANGED
@@ -9,7 +9,7 @@ const TableContainer = function TableContainer({ bleed, rootClassName, ref, ...p
9
9
  };
10
10
  const RootPart = /* @__PURE__ */ elementPart('table', 'surf-table');
11
11
  const TableRoot = function TableRoot({ density, variant, stickyHeader, ref, ...props }) {
12
- return (_jsx(RootPart, { ...props, ref: ref, "data-density": density === 'compact' ? 'compact' : undefined, "data-variant": variant && variant !== 'plain' ? variant : undefined, "data-sticky-header": stickyHeader || undefined }));
12
+ return (_jsx(RootPart, { ...props, ref: ref, "data-density": density, "data-variant": variant && variant !== 'plain' ? variant : undefined, "data-sticky-header": stickyHeader || undefined }));
13
13
  };
14
14
  const layout = ({ align, numeric }) => ({
15
15
  'data-align': numeric ? 'end' : align,
@@ -36,8 +36,13 @@ const TableSortHeader = function TableSortHeader({ sort, onSort, disabled, child
36
36
  return (_jsx(TableHeaderCell, { ...props, ref: ref, scope: 'col', "aria-sort": sort, className: cx('surf-table-sort-header', className), children: _jsxs(Button, { variant: 'ghost', className: 'surf-table-sort', "data-sort": sort, disabled: disabled, onClick: onSort, children: [_jsx("span", { children: children }), _jsx(SortIcon, { sort: sort })] }) }));
37
37
  };
38
38
  /** One-line text that ends in an ellipsis. String content also becomes the title. */
39
- const TableTruncate = function TableTruncate({ className, title, children, ref, ...props }) {
40
- return (_jsx("span", { ...props, ref: ref, title: title ?? (typeof children === 'string' ? children : undefined), className: cx('surf-table-truncate', className), children: children }));
39
+ const TableTruncate = function TableTruncate({ measure, className, title, style, children, ref, ...props }) {
40
+ return (_jsx("span", { ...props, ref: ref, title: title ?? (typeof children === 'string' ? children : undefined), style: measure
41
+ ? {
42
+ ...style,
43
+ '--surf-table-truncate-measure': measure,
44
+ }
45
+ : style, className: cx('surf-table-truncate', className), children: children }));
41
46
  };
42
47
  /** A full-width body row for loading, empty, error and permission messages. It has no hover. */
43
48
  const TableMessage = function TableMessage({ className, ref, ...props }) {
@@ -1,9 +1,12 @@
1
1
  import * as React from 'react';
2
- import { type ComponentSizeAlias } from './sizing.js';
2
+ import { type ComponentSize } from './sizing.js';
3
3
  /** A multi-line text field. Inside Field.Root it takes the label, description and
4
4
  * error from the field, as Input does. */
5
- export declare const Textarea: ({ className, size, rows, cols, wrap, ref, ...props }: React.ComponentPropsWithoutRef<"textarea"> & {
6
- size?: ComponentSizeAlias;
5
+ export declare const Textarea: ({ className, size, variant, rows, cols, wrap, ref, ...props }: React.ComponentPropsWithoutRef<"textarea"> & {
6
+ size?: ComponentSize;
7
+ /** `embedded` fills the pane it sits in, such as an editor beside a preview: no
8
+ * edge or corners of its own, and focus as a ring inside it. */
9
+ variant?: "default" | "embedded";
7
10
  } & {
8
11
  ref?: React.Ref<HTMLTextAreaElement>;
9
12
  }) => React.JSX.Element;
package/dist/textarea.js CHANGED
@@ -5,7 +5,7 @@ import { Field as BaseField } from '@base-ui/react/field';
5
5
  import { cx } from './parts.js';
6
6
  /** A multi-line text field. Inside Field.Root it takes the label, description and
7
7
  * error from the field, as Input does. */
8
- export const Textarea = function Textarea({ className, size, rows, cols, wrap, ref, ...props }) {
8
+ export const Textarea = function Textarea({ className, size, variant = 'default', rows, cols, wrap, ref, ...props }) {
9
9
  const scheme = useComponentSize(size);
10
- return (_jsx(BaseField.Control, { ...props, ref: ref, "data-ui-size": scheme, render: _jsx("textarea", { rows: rows, cols: cols, wrap: wrap }), className: cx('surf-input surf-textarea', className) }));
10
+ return (_jsx(BaseField.Control, { ...props, ref: ref, "data-ui-size": scheme, "data-variant": variant === 'embedded' ? variant : undefined, render: _jsx("textarea", { rows: rows, cols: cols, wrap: wrap }), className: cx('surf-input surf-textarea', className) }));
11
11
  };
@@ -1,5 +1,5 @@
1
1
  import * as React from 'react';
2
- import type { ComponentSizeAlias } from './size.js';
2
+ import type { ComponentSize } from './size.js';
3
3
  /** A span of time back from now, or a refresh interval, in milliseconds. */
4
4
  export type TimeRangeOption = {
5
5
  value: number;
@@ -32,7 +32,7 @@ export type TimeRangePickerProps = Omit<React.ComponentPropsWithoutRef<'div'>, '
32
32
  * Leave it out for no refresh button. */
33
33
  onRefresh?: () => void;
34
34
  labels?: Partial<TimeRangePickerLabels>;
35
- size?: ComponentSizeAlias;
35
+ size?: ComponentSize;
36
36
  };
37
37
  /** The span a monitoring screen shows, back from now, with how often it refreshes and
38
38
  * a button to refresh now. For a fixed span between two dates, put a DateRangePicker
@@ -61,9 +61,9 @@ export const TimeRangePicker = function TimeRangePicker({ label, range, onRangeC
61
61
  value: String(option.value),
62
62
  label: option.label,
63
63
  }));
64
- return (_jsxs("div", { role: 'group', "aria-label": label, ...props, ref: ref, className: cx('surf-time-range', className), children: [_jsx(Select, { width: 'content', size: size, options: options(ranges), value: String(range), onValueChange: (value) => onRangeChange(Number(value)), "aria-label": text.range }), refreshInterval !== undefined && (_jsx(Select, { width: 'content', size: size, options: options(intervals), value: String(refreshInterval), onValueChange: (value) => onRefreshIntervalChange?.(Number(value)), "aria-label": text.refresh })), onRefresh && (_jsx(Button, { variant: 'outline', size: size === 'small' || size === 'sm'
64
+ return (_jsxs("div", { role: 'group', "aria-label": label, ...props, ref: ref, className: cx('surf-time-range', className), children: [_jsx(Select, { width: 'content', size: size, options: options(ranges), value: String(range), onValueChange: (value) => onRangeChange(Number(value)), "aria-label": text.range }), refreshInterval !== undefined && (_jsx(Select, { width: 'content', size: size, options: options(intervals), value: String(refreshInterval), onValueChange: (value) => onRefreshIntervalChange?.(Number(value)), "aria-label": text.refresh })), onRefresh && (_jsx(Button, { variant: 'outline', size: size === 'small'
65
65
  ? 'icon-small'
66
- : size === 'large' || size === 'lg'
66
+ : size === 'large'
67
67
  ? 'icon-large'
68
68
  : 'icon', "aria-label": text.refreshNow, onClick: () => onRefresh(), children: _jsx(Icon, { name: 'refresh' }) }))] }));
69
69
  };
package/dist/toggle.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as React from 'react';
2
- import { type ComponentSizeAlias } from './sizing.js';
2
+ import { type ComponentSize } from './sizing.js';
3
3
  import { Toggle as BaseToggle } from '@base-ui/react/toggle';
4
4
  export declare function Toggle<Value extends string>({ className, size, ref, ...props }: BaseToggle.Props<Value> & {
5
- size?: ComponentSizeAlias | 'icon';
5
+ size?: ComponentSize | 'icon';
6
6
  ref?: React.Ref<HTMLButtonElement>;
7
7
  }): React.JSX.Element;
package/dist/toggle.js CHANGED
@@ -2,8 +2,8 @@
2
2
  import { jsx as _jsx } from "react/jsx-runtime";
3
3
  import { useComponentSize } from './sizing.js';
4
4
  import { Toggle as BaseToggle } from '@base-ui/react/toggle';
5
- import { sizeName, skin } from './parts.js';
5
+ import { skin } from './parts.js';
6
6
  export function Toggle({ className, size, ref, ...props }) {
7
7
  const scheme = useComponentSize(size === 'icon' ? undefined : size);
8
- return (_jsx(BaseToggle, { ...props, ref: ref, className: skin('surf-button surf-toggle', className), "data-size": sizeName(size), "data-ui-size": scheme }));
8
+ return (_jsx(BaseToggle, { ...props, ref: ref, className: skin('surf-button surf-toggle', className), "data-size": size, "data-ui-size": scheme }));
9
9
  }
package/dist/toolbar.d.ts CHANGED
@@ -1,10 +1,14 @@
1
1
  import * as React from 'react';
2
+ declare const RootPart: ({ ref, ...props }: Omit<Omit<Omit<import("@base-ui/react/toolbar").ToolbarRootProps, "ref"> & React.RefAttributes<HTMLDivElement>, "ref">, "size"> & {
3
+ size?: import("./size.js").ComponentSize;
4
+ } & {
5
+ ref?: React.Ref<HTMLDivElement> | undefined;
6
+ }) => React.JSX.Element;
7
+ /** Home and End reach the first and last item, as they do in ToggleGroup, Tabs and
8
+ * Menubar; Base UI's toolbar leaves them out. Inside an input they move the caret. */
9
+ declare function Root({ onKeyDown, ...props }: React.ComponentProps<typeof RootPart>): React.JSX.Element;
2
10
  export declare const Toolbar: {
3
- Root: ({ ref, ...props }: Omit<Omit<Omit<import("@base-ui/react/toolbar").ToolbarRootProps, "ref"> & React.RefAttributes<HTMLDivElement>, "ref">, "size"> & {
4
- size?: import("./size.js").ComponentSize;
5
- } & {
6
- ref?: React.Ref<HTMLDivElement> | undefined;
7
- }) => React.JSX.Element;
11
+ Root: typeof Root;
8
12
  Group: ({ ref, ...props }: Omit<Omit<Omit<import("@base-ui/react/toolbar").ToolbarGroupProps, "ref"> & React.RefAttributes<HTMLDivElement>, "ref">, "size"> & {
9
13
  size?: import("./size.js").ComponentSize;
10
14
  } & {
@@ -47,12 +51,9 @@ export declare const ToolbarButton: ({ ref, ...props }: Omit<Omit<Omit<import("@
47
51
  size?: import("./size.js").ComponentSize;
48
52
  } & {
49
53
  ref?: React.Ref<HTMLAnchorElement> | undefined;
50
- }) => React.JSX.Element, ToolbarRoot: ({ ref, ...props }: Omit<Omit<Omit<import("@base-ui/react/toolbar").ToolbarRootProps, "ref"> & React.RefAttributes<HTMLDivElement>, "ref">, "size"> & {
51
- size?: import("./size.js").ComponentSize;
52
- } & {
53
- ref?: React.Ref<HTMLDivElement> | undefined;
54
- }) => React.JSX.Element, ToolbarSeparator: ({ ref, ...props }: Omit<Omit<Omit<import("@base-ui/react/toolbar").ToolbarSeparatorProps, "ref"> & React.RefAttributes<HTMLDivElement>, "ref">, "size"> & {
54
+ }) => React.JSX.Element, ToolbarRoot: typeof Root, ToolbarSeparator: ({ ref, ...props }: Omit<Omit<Omit<import("@base-ui/react/toolbar").ToolbarSeparatorProps, "ref"> & React.RefAttributes<HTMLDivElement>, "ref">, "size"> & {
55
55
  size?: import("./size.js").ComponentSize;
56
56
  } & {
57
57
  ref?: React.Ref<HTMLDivElement> | undefined;
58
58
  }) => React.JSX.Element;
59
+ export {};
package/dist/toolbar.js CHANGED
@@ -1,9 +1,31 @@
1
1
  'use client';
2
+ import { jsx as _jsx } from "react/jsx-runtime";
2
3
  import { Toolbar as BaseToolbar } from '@base-ui/react/toolbar';
3
4
  import { part } from './parts.js';
5
+ const RootPart = /* @__PURE__ */ part(BaseToolbar.Root, 'surf-toolbar');
6
+ /** Home and End reach the first and last item, as they do in ToggleGroup, Tabs and
7
+ * Menubar; Base UI's toolbar leaves them out. Inside an input they move the caret. */
8
+ function Root({ onKeyDown, ...props }) {
9
+ return (_jsx(RootPart, { ...props, onKeyDown: (event) => {
10
+ onKeyDown?.(event);
11
+ const toolbar = event.currentTarget;
12
+ if (event.defaultPrevented ||
13
+ (event.key !== 'Home' && event.key !== 'End') ||
14
+ event.target.matches('input, textarea'))
15
+ return;
16
+ const items = [
17
+ ...toolbar.querySelectorAll('[tabindex]'),
18
+ ].filter((item) => item.closest('[role="toolbar"]') === toolbar);
19
+ const item = event.key === 'Home' ? items[0] : items.at(-1);
20
+ if (!item)
21
+ return;
22
+ event.preventDefault();
23
+ item.focus();
24
+ } }));
25
+ }
4
26
  export const Toolbar = {
5
27
  ...BaseToolbar,
6
- Root: /* @__PURE__ */ part(BaseToolbar.Root, 'surf-toolbar'),
28
+ Root,
7
29
  Group: /* @__PURE__ */ part(BaseToolbar.Group, 'surf-toolbar-group'),
8
30
  Button: /* @__PURE__ */ part(BaseToolbar.Button, 'surf-button surf-toolbar-button'),
9
31
  Link: /* @__PURE__ */ part(BaseToolbar.Link, 'surf-button surf-toolbar-link'),
package/dist/tooltip.d.ts CHANGED
@@ -14,8 +14,6 @@ export type TooltipProps = {
14
14
  shortcut?: string;
15
15
  /** Keeps the tooltip from opening while the trigger stays as it is. */
16
16
  disabled?: boolean;
17
- /** @deprecated Use `disabled`. Removed in a later minor. */
18
- enabled?: boolean;
19
17
  children: React.ReactElement;
20
18
  } & Pick<React.ComponentPropsWithoutRef<typeof BaseTooltip.Positioner>, 'side' | 'align' | 'sideOffset'>;
21
- export declare function Tooltip({ label, shortcut, disabled, enabled, side, align, sideOffset, children, }: TooltipProps): React.JSX.Element;
19
+ export declare function Tooltip({ label, shortcut, disabled, side, align, sideOffset, children, }: TooltipProps): React.JSX.Element;
package/dist/tooltip.js CHANGED
@@ -1,13 +1,15 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { useComponentSize } from './sizing.js';
4
+ import { usePortalDirection } from './parts.js';
4
5
  import { Tooltip as BaseTooltip } from '@base-ui/react/tooltip';
5
6
  export function TooltipProvider({ delayDuration = 150, skipDelayDuration = 300, children, }) {
6
7
  return (_jsx(BaseTooltip.Provider, { delay: delayDuration, closeDelay: 0, timeout: skipDelayDuration, children: children }));
7
8
  }
8
- export function Tooltip({ label, shortcut, disabled = false, enabled = true, side = 'right', align, sideOffset = 10, children, }) {
9
+ export function Tooltip({ label, shortcut, disabled = false, side = 'right', align, sideOffset = 10, children, }) {
9
10
  const scheme = useComponentSize();
11
+ const dir = usePortalDirection();
10
12
  // Disabling keeps the trigger mounted, so turning the tooltip on or off never
11
13
  // moves focus.
12
- return (_jsxs(BaseTooltip.Root, { disabled: disabled || !enabled, children: [_jsx(BaseTooltip.Trigger, { render: children }), _jsx(BaseTooltip.Portal, { children: _jsx(BaseTooltip.Positioner, { side: side, align: align, sideOffset: sideOffset, collisionPadding: 8, className: 'surf-positioner surf-tooltip-positioner', children: _jsxs(BaseTooltip.Popup, { className: 'surf-tooltip', "data-ui-size": scheme, children: [label, shortcut && (_jsx("kbd", { className: 'surf-tooltip-shortcut', children: shortcut }))] }) }) })] }));
14
+ return (_jsxs(BaseTooltip.Root, { disabled: disabled, children: [_jsx(BaseTooltip.Trigger, { render: children }), _jsx(BaseTooltip.Portal, { children: _jsx(BaseTooltip.Positioner, { dir: dir, side: side, align: align, sideOffset: sideOffset, collisionPadding: 8, className: 'surf-positioner surf-tooltip-positioner', children: _jsxs(BaseTooltip.Popup, { className: 'surf-tooltip', "data-ui-size": scheme, children: [label, shortcut && (_jsx("kbd", { className: 'surf-tooltip-shortcut', children: shortcut }))] }) }) })] }));
13
15
  }
package/dist/tree.d.ts CHANGED
@@ -30,10 +30,8 @@ export type TreeProps = {
30
30
  size?: ComponentSize;
31
31
  virtualized?: boolean;
32
32
  labels?: Partial<TreeLabels>;
33
- /** @deprecated Use `labels.empty`. Removed in a later minor. */
34
- emptyLabel?: string;
35
33
  dir?: 'ltr' | 'rtl';
36
34
  className?: string;
37
35
  };
38
36
  /** Loaded, immutable hierarchy. Remote loading, permission checks and mutations remain caller-owned. */
39
- export declare function Tree({ nodes, label, expandedIds, defaultExpandedIds, onExpandedIdsChange, selectedIds, defaultSelectedIds, onSelectedIdsChange, selectionMode, height, rowHeight: explicitRowHeight, size, virtualized, labels, emptyLabel, dir, className, }: TreeProps): React.JSX.Element;
37
+ export declare function Tree({ nodes, label, expandedIds, defaultExpandedIds, onExpandedIdsChange, selectedIds, defaultSelectedIds, onSelectedIdsChange, selectionMode, height, rowHeight: explicitRowHeight, size, virtualized, labels, dir, className, }: TreeProps): React.JSX.Element;