@surflane/ui 0.1.0 → 0.2.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.
- package/README.md +8 -8
- package/dist/advanced-forms.d.ts +2 -2
- package/dist/advanced-forms.js +39 -39
- package/dist/app-shell.d.ts +1 -1
- package/dist/app-shell.js +11 -11
- package/dist/button.d.ts +5 -5
- package/dist/button.js +12 -12
- package/dist/chart.d.ts +3 -3
- package/dist/chart.js +36 -34
- package/dist/commands.d.ts +5 -5
- package/dist/commands.js +17 -17
- package/dist/content.d.ts +2 -2
- package/dist/content.js +66 -28
- package/dist/context-overlays.d.ts +3 -3
- package/dist/context-overlays.js +11 -11
- package/dist/data.d.ts +1 -1
- package/dist/data.js +18 -18
- package/dist/date-picker.d.ts +8 -8
- package/dist/date-picker.js +18 -18
- package/dist/dialog-focus.js +7 -7
- package/dist/dialog.d.ts +5 -5
- package/dist/dialog.js +16 -16
- package/dist/feedback.d.ts +5 -5
- package/dist/feedback.js +20 -20
- package/dist/file-upload.d.ts +9 -9
- package/dist/file-upload.js +64 -63
- package/dist/filter-bar.d.ts +1 -1
- package/dist/filter-bar.js +9 -9
- package/dist/form-state.d.ts +1 -1
- package/dist/form-state.js +11 -11
- package/dist/forms.d.ts +5 -5
- package/dist/forms.js +32 -32
- package/dist/foundations.d.ts +10 -10
- package/dist/foundations.js +26 -26
- package/dist/icon.d.ts +7 -7
- package/dist/icon.js +22 -22
- package/dist/index.d.ts +37 -37
- package/dist/index.js +38 -38
- package/dist/input-extensions.d.ts +3 -3
- package/dist/input-extensions.js +21 -21
- package/dist/input.d.ts +2 -2
- package/dist/input.js +7 -7
- package/dist/markdown.d.ts +2 -2
- package/dist/markdown.js +38 -38
- package/dist/menu.d.ts +2 -2
- package/dist/menu.js +19 -19
- package/dist/messages.d.ts +2 -2
- package/dist/messages.js +18 -18
- package/dist/navigation-menu.d.ts +2 -2
- package/dist/navigation-menu.js +16 -16
- package/dist/navigation.d.ts +5 -5
- package/dist/navigation.js +40 -40
- package/dist/otp-field.d.ts +1 -1
- package/dist/otp-field.js +14 -14
- package/dist/pagination.d.ts +2 -2
- package/dist/pagination.js +12 -12
- package/dist/panels.d.ts +8 -8
- package/dist/panels.js +39 -39
- package/dist/parts.d.ts +2 -2
- package/dist/parts.js +8 -8
- package/dist/popover.d.ts +3 -3
- package/dist/popover.js +6 -6
- package/dist/scroll-area.d.ts +1 -1
- package/dist/scroll-area.js +20 -20
- package/dist/select.d.ts +8 -8
- package/dist/select.js +21 -21
- package/dist/sizing.d.ts +3 -3
- package/dist/sizing.js +9 -9
- package/dist/slot.d.ts +1 -1
- package/dist/slot.js +4 -4
- package/dist/status.d.ts +4 -4
- package/dist/status.js +8 -8
- package/dist/syntax-engine.js +43 -43
- package/dist/syntax-highlighter.d.ts +2 -2
- package/dist/syntax-highlighter.js +32 -32
- package/dist/toast.d.ts +4 -4
- package/dist/toast.js +33 -33
- package/dist/tone-transition.d.ts +1 -1
- package/dist/tone-transition.js +17 -17
- package/dist/tooltip.d.ts +1 -1
- package/dist/tooltip.js +4 -4
- package/dist/tree.d.ts +4 -4
- package/dist/tree.js +60 -60
- package/package.json +2 -2
- package/src/styles.css +233 -142
package/README.md
CHANGED
|
@@ -15,11 +15,11 @@ npm install @surflane/ui @surflane/design-tokens
|
|
|
15
15
|
Import the stylesheets once at the application root:
|
|
16
16
|
|
|
17
17
|
```css
|
|
18
|
-
@import
|
|
19
|
-
@import
|
|
20
|
-
@import
|
|
21
|
-
@import
|
|
22
|
-
@import
|
|
18
|
+
@import '@surflane/design-tokens/tokens.css';
|
|
19
|
+
@import '@surflane/design-tokens/controls.css';
|
|
20
|
+
@import '@surflane/design-tokens/foundations.css';
|
|
21
|
+
@import '@surflane/design-tokens/typography.css';
|
|
22
|
+
@import '@surflane/ui/styles.css';
|
|
23
23
|
```
|
|
24
24
|
|
|
25
25
|
Set `data-theme="light"` or `data-theme="dark"` on `<html>` before the first paint and add `pui-typography` to `<body>`.
|
|
@@ -31,17 +31,17 @@ import {
|
|
|
31
31
|
DialogRoot,
|
|
32
32
|
DialogTitle,
|
|
33
33
|
DialogTrigger,
|
|
34
|
-
} from
|
|
34
|
+
} from '@surflane/ui'
|
|
35
35
|
|
|
36
36
|
export function Example() {
|
|
37
37
|
return (
|
|
38
38
|
<DialogRoot>
|
|
39
|
-
<DialogTrigger render={<Button variant=
|
|
39
|
+
<DialogTrigger render={<Button variant='primary' />}>Open</DialogTrigger>
|
|
40
40
|
<DialogContent>
|
|
41
41
|
<DialogTitle>Surflane</DialogTitle>
|
|
42
42
|
</DialogContent>
|
|
43
43
|
</DialogRoot>
|
|
44
|
-
)
|
|
44
|
+
)
|
|
45
45
|
}
|
|
46
46
|
```
|
|
47
47
|
|
package/dist/advanced-forms.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import * as React from
|
|
2
|
-
import { Combobox as BaseCombobox } from
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { Combobox as BaseCombobox } from '@base-ui/react/combobox';
|
|
3
3
|
declare function ComboboxRoot<Value, Multiple extends boolean | undefined = false, Item = Value>({ children, form, ...props }: BaseCombobox.Root.Props<Value, Multiple, Item>): React.JSX.Element;
|
|
4
4
|
export declare const Combobox: {
|
|
5
5
|
Root: typeof ComboboxRoot;
|
package/dist/advanced-forms.js
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
|
|
1
|
+
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
import * as React from
|
|
4
|
-
import { Combobox as BaseCombobox } from
|
|
5
|
-
import { NumberField as BaseNumberField } from
|
|
6
|
-
import { skin, part } from
|
|
7
|
-
import { useRootRef, useResetValue } from
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
import { Combobox as BaseCombobox } from '@base-ui/react/combobox';
|
|
5
|
+
import { NumberField as BaseNumberField } from '@base-ui/react/number-field';
|
|
6
|
+
import { skin, part } from './parts.js';
|
|
7
|
+
import { useRootRef, useResetValue } from './form-state.js';
|
|
8
8
|
function Mark({ kind, }) {
|
|
9
|
-
const path = kind ===
|
|
10
|
-
?
|
|
11
|
-
: kind ===
|
|
12
|
-
?
|
|
13
|
-
: kind ===
|
|
14
|
-
?
|
|
15
|
-
: kind ===
|
|
16
|
-
?
|
|
17
|
-
:
|
|
18
|
-
return (_jsx("svg", { width:
|
|
9
|
+
const path = kind === 'check'
|
|
10
|
+
? 'm5 12 4 4L19 6'
|
|
11
|
+
: kind === 'clear'
|
|
12
|
+
? 'm6 6 12 12M6 18 18 6'
|
|
13
|
+
: kind === 'expand'
|
|
14
|
+
? 'm6 9 6 6 6-6'
|
|
15
|
+
: kind === 'plus'
|
|
16
|
+
? 'M5 12h14M12 5v14'
|
|
17
|
+
: 'M5 12h14';
|
|
18
|
+
return (_jsx("svg", { width: '16', height: '16', viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor', strokeWidth: '1.6', "aria-hidden": 'true', children: _jsx("path", { d: path }) }));
|
|
19
19
|
}
|
|
20
20
|
function ComboboxRoot({ children, form, ...props }) {
|
|
21
21
|
const anchor = React.useRef(null);
|
|
@@ -24,22 +24,22 @@ function ComboboxRoot({ children, form, ...props }) {
|
|
|
24
24
|
const [, , revision] = useResetValue(true, true, anchor, form);
|
|
25
25
|
return (_jsxs(BaseCombobox.Root, { ...props, form: form, children: [_jsx("span", { hidden: true, ref: anchor }), children] }, revision));
|
|
26
26
|
}
|
|
27
|
-
const ComboPopup = part(BaseCombobox.Popup,
|
|
28
|
-
const ComboPositioner = part(BaseCombobox.Positioner,
|
|
27
|
+
const ComboPopup = part(BaseCombobox.Popup, 'pui-combobox-popup');
|
|
28
|
+
const ComboPositioner = part(BaseCombobox.Positioner, 'pui-positioner');
|
|
29
29
|
const ComboContent = React.forwardRef(function ComboContent({ positionerProps, ...props }, ref) {
|
|
30
30
|
return (_jsx(BaseCombobox.Portal, { children: _jsx(ComboPositioner, { sideOffset: 6, ...positionerProps, children: _jsx(ComboPopup, { ...props, ref: ref }) }) }));
|
|
31
31
|
});
|
|
32
32
|
const ComboTrigger = React.forwardRef(function ComboTrigger({ children, className, ...props }, ref) {
|
|
33
|
-
return (_jsx(BaseCombobox.Trigger, { "aria-label":
|
|
33
|
+
return (_jsx(BaseCombobox.Trigger, { "aria-label": 'Show options', ...props, ref: ref, className: skin('pui-combobox-action', className), children: children ?? _jsx(Mark, { kind: 'expand' }) }));
|
|
34
34
|
});
|
|
35
35
|
const ComboClear = React.forwardRef(function ComboClear({ children, className, ...props }, ref) {
|
|
36
|
-
return (_jsx(BaseCombobox.Clear, { "aria-label":
|
|
36
|
+
return (_jsx(BaseCombobox.Clear, { "aria-label": 'Clear selection', ...props, ref: ref, className: skin('pui-combobox-action', className), children: children ?? _jsx(Mark, { kind: 'clear' }) }));
|
|
37
37
|
});
|
|
38
38
|
const ComboIndicator = React.forwardRef(function ComboIndicator({ children, className, ...props }, ref) {
|
|
39
|
-
return (_jsx(BaseCombobox.ItemIndicator, { keepMounted: true, ...props, ref: ref, className: skin(
|
|
39
|
+
return (_jsx(BaseCombobox.ItemIndicator, { keepMounted: true, ...props, ref: ref, className: skin('pui-combobox-indicator', className), children: children ?? _jsx(Mark, { kind: 'check' }) }));
|
|
40
40
|
});
|
|
41
41
|
const ComboRemove = React.forwardRef(function ComboRemove({ children, className, ...props }, ref) {
|
|
42
|
-
return (_jsx(BaseCombobox.ChipRemove, { ...props, ref: ref, className: skin(
|
|
42
|
+
return (_jsx(BaseCombobox.ChipRemove, { ...props, ref: ref, className: skin('pui-combobox-chip-remove', className), children: children ?? _jsx(Mark, { kind: 'clear' }) }));
|
|
43
43
|
});
|
|
44
44
|
export const Combobox = {
|
|
45
45
|
...BaseCombobox,
|
|
@@ -51,41 +51,41 @@ export const Combobox = {
|
|
|
51
51
|
Clear: ComboClear,
|
|
52
52
|
ItemIndicator: ComboIndicator,
|
|
53
53
|
ChipRemove: ComboRemove,
|
|
54
|
-
Input: part(BaseCombobox.Input,
|
|
55
|
-
InputGroup: part(BaseCombobox.InputGroup,
|
|
56
|
-
List: part(BaseCombobox.List,
|
|
57
|
-
Item: part(BaseCombobox.Item,
|
|
58
|
-
Empty: part(BaseCombobox.Empty,
|
|
59
|
-
Status: part(BaseCombobox.Status,
|
|
60
|
-
Group: part(BaseCombobox.Group,
|
|
61
|
-
GroupLabel: part(BaseCombobox.GroupLabel,
|
|
62
|
-
Separator: part(BaseCombobox.Separator,
|
|
63
|
-
Chips: part(BaseCombobox.Chips,
|
|
64
|
-
Chip: part(BaseCombobox.Chip,
|
|
54
|
+
Input: part(BaseCombobox.Input, 'pui-input pui-combobox-input'),
|
|
55
|
+
InputGroup: part(BaseCombobox.InputGroup, 'pui-combobox-group'),
|
|
56
|
+
List: part(BaseCombobox.List, 'pui-combobox-list scroll-area'),
|
|
57
|
+
Item: part(BaseCombobox.Item, 'pui-combobox-item'),
|
|
58
|
+
Empty: part(BaseCombobox.Empty, 'pui-combobox-empty'),
|
|
59
|
+
Status: part(BaseCombobox.Status, 'pui-combobox-status'),
|
|
60
|
+
Group: part(BaseCombobox.Group, 'pui-combobox-section'),
|
|
61
|
+
GroupLabel: part(BaseCombobox.GroupLabel, 'pui-combobox-section-label'),
|
|
62
|
+
Separator: part(BaseCombobox.Separator, 'pui-combobox-separator'),
|
|
63
|
+
Chips: part(BaseCombobox.Chips, 'pui-combobox-chips'),
|
|
64
|
+
Chip: part(BaseCombobox.Chip, 'pui-combobox-chip'),
|
|
65
65
|
};
|
|
66
66
|
const NumberRoot = React.forwardRef(function NumberRoot({ value, defaultValue, onValueChange, className, form, ...props }, ref) {
|
|
67
67
|
const [element, attach] = useRootRef(ref);
|
|
68
68
|
const [numeric, setNumeric] = useResetValue(value, defaultValue ?? null, element, form);
|
|
69
|
-
return (_jsx(BaseNumberField.Root, { ...props, form: form, ref: attach, value: numeric, className: skin(
|
|
69
|
+
return (_jsx(BaseNumberField.Root, { ...props, form: form, ref: attach, value: numeric, className: skin('pui-number-field', className), onValueChange: (next, event) => {
|
|
70
70
|
onValueChange?.(next, event);
|
|
71
71
|
if (value === undefined && !event.isCanceled)
|
|
72
72
|
setNumeric(next);
|
|
73
73
|
} }));
|
|
74
74
|
});
|
|
75
75
|
const NumberIncrement = React.forwardRef(function NumberIncrement({ className, children, ...props }, ref) {
|
|
76
|
-
return (_jsx(BaseNumberField.Increment, { "aria-label":
|
|
76
|
+
return (_jsx(BaseNumberField.Increment, { "aria-label": 'Increase value', ...props, ref: ref, className: skin('pui-number-step', className), children: children ?? _jsx(Mark, { kind: 'plus' }) }));
|
|
77
77
|
});
|
|
78
78
|
const NumberDecrement = React.forwardRef(function NumberDecrement({ className, children, ...props }, ref) {
|
|
79
|
-
return (_jsx(BaseNumberField.Decrement, { "aria-label":
|
|
79
|
+
return (_jsx(BaseNumberField.Decrement, { "aria-label": 'Decrease value', ...props, ref: ref, className: skin('pui-number-step', className), children: children ?? _jsx(Mark, { kind: 'minus' }) }));
|
|
80
80
|
});
|
|
81
81
|
export const NumberField = {
|
|
82
82
|
...BaseNumberField,
|
|
83
83
|
Root: NumberRoot,
|
|
84
84
|
Increment: NumberIncrement,
|
|
85
85
|
Decrement: NumberDecrement,
|
|
86
|
-
Group: part(BaseNumberField.Group,
|
|
87
|
-
Input: part(BaseNumberField.Input,
|
|
88
|
-
ScrubArea: part(BaseNumberField.ScrubArea,
|
|
86
|
+
Group: part(BaseNumberField.Group, 'pui-number-group'),
|
|
87
|
+
Input: part(BaseNumberField.Input, 'pui-number-input'),
|
|
88
|
+
ScrubArea: part(BaseNumberField.ScrubArea, 'pui-number-scrub'),
|
|
89
89
|
};
|
|
90
90
|
// Flat names for React Server Components, which cannot dot into client exports.
|
|
91
91
|
export { ComboboxRoot };
|
package/dist/app-shell.d.ts
CHANGED
package/dist/app-shell.js
CHANGED
|
@@ -1,28 +1,28 @@
|
|
|
1
|
-
|
|
1
|
+
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
import * as React from
|
|
4
|
-
const skin = (base, extra) => [base, extra].filter(Boolean).join(
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
const skin = (base, extra) => [base, extra].filter(Boolean).join(' ');
|
|
5
5
|
/** Layout only. Routing, session, theme and mobile disclosure belong to the caller. */
|
|
6
|
-
const Root = React.forwardRef(function AppShellRoot({ collapsed = false, layout =
|
|
7
|
-
return (_jsx("div", { ...props, ref: ref, "data-layout": layout, "data-sidebar": collapsed ?
|
|
6
|
+
const Root = React.forwardRef(function AppShellRoot({ collapsed = false, layout = 'header', className, ...props }, ref) {
|
|
7
|
+
return (_jsx("div", { ...props, ref: ref, "data-layout": layout, "data-sidebar": collapsed ? 'collapsed' : 'expanded', className: skin('pui-app-shell', className) }));
|
|
8
8
|
});
|
|
9
9
|
const Header = React.forwardRef(function AppShellHeader({ className, ...props }, ref) {
|
|
10
|
-
return (_jsx("div", { ...props, ref: ref, className: skin(
|
|
10
|
+
return (_jsx("div", { ...props, ref: ref, className: skin('pui-app-shell-header', className) }));
|
|
11
11
|
});
|
|
12
12
|
const Sidebar = React.forwardRef(function AppShellSidebar({ className, ...props }, ref) {
|
|
13
|
-
return (_jsx("aside", { ...props, ref: ref, className: skin(
|
|
13
|
+
return (_jsx("aside", { ...props, ref: ref, className: skin('pui-app-shell-sidebar', className) }));
|
|
14
14
|
});
|
|
15
15
|
const Content = React.forwardRef(function AppShellContent({ className, ...props }, ref) {
|
|
16
|
-
return (_jsx("div", { ...props, ref: ref, className: skin(
|
|
16
|
+
return (_jsx("div", { ...props, ref: ref, className: skin('pui-app-shell-content', className) }));
|
|
17
17
|
});
|
|
18
18
|
const Footer = React.forwardRef(function AppShellFooter({ className, ...props }, ref) {
|
|
19
|
-
return (_jsx("div", { ...props, ref: ref, className: skin(
|
|
19
|
+
return (_jsx("div", { ...props, ref: ref, className: skin('pui-app-shell-footer', className) }));
|
|
20
20
|
});
|
|
21
21
|
const Label = React.forwardRef(function AppShellLabel({ className, ...props }, ref) {
|
|
22
|
-
return (_jsx("span", { ...props, ref: ref, className: skin(
|
|
22
|
+
return (_jsx("span", { ...props, ref: ref, className: skin('pui-app-shell-label', className) }));
|
|
23
23
|
});
|
|
24
24
|
const Link = React.forwardRef(function AppShellLink({ icon, label, className, ...props }, ref) {
|
|
25
|
-
return (_jsxs("a", { ...props, ref: ref, "aria-label": props[
|
|
25
|
+
return (_jsxs("a", { ...props, ref: ref, "aria-label": props['aria-label'] ?? label, className: skin('pui-app-shell-link', className), children: [_jsx("span", { className: 'pui-app-shell-icon', "aria-hidden": 'true', children: icon }), _jsx(Label, { "aria-hidden": 'true', children: label })] }));
|
|
26
26
|
});
|
|
27
27
|
export const AppShell = { Root, Header, Sidebar, Content, Footer, Label, Link };
|
|
28
28
|
// Flat names for React Server Components, which cannot dot into client exports.
|
package/dist/button.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import * as React from
|
|
2
|
-
import { Button as BaseButton } from
|
|
3
|
-
import { type ComponentSizeAlias } from
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { Button as BaseButton } from '@base-ui/react/button';
|
|
3
|
+
import { type ComponentSizeAlias } from './sizing.js';
|
|
4
4
|
/** Visual priority. `default` remains a compatibility alias of `primary`. */
|
|
5
|
-
export type ButtonVariant =
|
|
6
|
-
export type ButtonSize = ComponentSizeAlias |
|
|
5
|
+
export type ButtonVariant = 'primary' | 'default' | 'secondary' | 'outline' | 'ghost' | 'destructive' | 'link';
|
|
6
|
+
export type ButtonSize = ComponentSizeAlias | 'xs' | 'icon' | 'icon-xs' | 'icon-sm' | 'icon-lg';
|
|
7
7
|
export type ButtonProps = React.ComponentProps<typeof BaseButton> & {
|
|
8
8
|
variant?: ButtonVariant;
|
|
9
9
|
size?: ButtonSize;
|
package/dist/button.js
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
|
|
1
|
+
'use client';
|
|
2
2
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
-
import * as React from
|
|
4
|
-
import { Button as BaseButton } from
|
|
5
|
-
import { useComponentSize } from
|
|
6
|
-
import { skin } from
|
|
7
|
-
export const Button = React.forwardRef(function Button({ className, variant =
|
|
8
|
-
const scheme = useComponentSize(size ===
|
|
9
|
-
?
|
|
10
|
-
: size ===
|
|
11
|
-
?
|
|
12
|
-
: size ===
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
import { Button as BaseButton } from '@base-ui/react/button';
|
|
5
|
+
import { useComponentSize } from './sizing.js';
|
|
6
|
+
import { skin } from './parts.js';
|
|
7
|
+
export const Button = React.forwardRef(function Button({ className, variant = 'default', size, ...props }, ref) {
|
|
8
|
+
const scheme = useComponentSize(size === 'icon-sm' || size === 'icon-xs'
|
|
9
|
+
? 'small'
|
|
10
|
+
: size === 'icon-lg'
|
|
11
|
+
? 'large'
|
|
12
|
+
: size === 'xs' || size === 'icon'
|
|
13
13
|
? undefined
|
|
14
14
|
: size);
|
|
15
|
-
return (_jsx(BaseButton, { ref: ref, ...props, className: skin(
|
|
15
|
+
return (_jsx(BaseButton, { ref: ref, ...props, className: skin('pui-button', className), "data-variant": variant, "data-size": size, "data-ui-size": scheme }));
|
|
16
16
|
});
|
package/dist/chart.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import * as React from
|
|
1
|
+
import * as React from 'react';
|
|
2
2
|
export type ChartDatum = {
|
|
3
3
|
id: string;
|
|
4
4
|
label: string;
|
|
@@ -8,7 +8,7 @@ export type ChartSeries = {
|
|
|
8
8
|
key: string;
|
|
9
9
|
label: string;
|
|
10
10
|
};
|
|
11
|
-
export type ChartProps = Omit<React.ComponentPropsWithoutRef<
|
|
11
|
+
export type ChartProps = Omit<React.ComponentPropsWithoutRef<'figure'>, 'children' | 'title'> & {
|
|
12
12
|
title: string;
|
|
13
13
|
description: string;
|
|
14
14
|
data: readonly ChartDatum[];
|
|
@@ -16,7 +16,7 @@ export type ChartProps = Omit<React.ComponentPropsWithoutRef<"figure">, "childre
|
|
|
16
16
|
unit: string;
|
|
17
17
|
xLabel: string;
|
|
18
18
|
yLabel: string;
|
|
19
|
-
type?:
|
|
19
|
+
type?: 'line' | 'bar' | 'area';
|
|
20
20
|
height?: number;
|
|
21
21
|
locale?: string;
|
|
22
22
|
formatValue?: (value: number) => string;
|
package/dist/chart.js
CHANGED
|
@@ -1,27 +1,27 @@
|
|
|
1
|
-
|
|
1
|
+
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
-
import * as React from
|
|
4
|
-
import { Area, Bar, CartesianGrid, ComposedChart, Line, ReferenceLine, ResponsiveContainer, Tooltip, XAxis, YAxis, } from
|
|
5
|
-
import { Table } from
|
|
6
|
-
import { Button } from
|
|
7
|
-
const dashes = [undefined,
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
import { Area, Bar, CartesianGrid, ComposedChart, Line, ReferenceLine, ResponsiveContainer, Tooltip, XAxis, YAxis, } from 'recharts';
|
|
5
|
+
import { Table } from './data.js';
|
|
6
|
+
import { Button } from './button.js';
|
|
7
|
+
const dashes = [undefined, '7 4', '2 4', '10 3 2 3', '12 5', '4 3'];
|
|
8
8
|
const colorFor = (index) => `var(--chart-series-${(index % 3) + 1})`;
|
|
9
9
|
function Marker({ cx, cy, color, index, }) {
|
|
10
|
-
if (typeof cx !==
|
|
11
|
-
typeof cy !==
|
|
10
|
+
if (typeof cx !== 'number' ||
|
|
11
|
+
typeof cy !== 'number' ||
|
|
12
12
|
!Number.isFinite(cx) ||
|
|
13
13
|
!Number.isFinite(cy))
|
|
14
14
|
return null;
|
|
15
|
-
const props = { fill:
|
|
15
|
+
const props = { fill: 'var(--canvas)', stroke: color, strokeWidth: 1.8 };
|
|
16
16
|
return index % 3 === 0 ? (_jsx("circle", { cx: cx, cy: cy, r: 3.5, ...props })) : index % 3 === 1 ? (_jsx("rect", { x: cx - 3.5, y: cy - 3.5, width: 7, height: 7, ...props })) : (_jsx("path", { d: `M${cx},${cy - 4.5}l4.5,8h-9Z`, ...props }));
|
|
17
17
|
}
|
|
18
18
|
function Pattern({ id, index, color, }) {
|
|
19
|
-
return (_jsxs("pattern", { id: id, patternUnits:
|
|
19
|
+
return (_jsxs("pattern", { id: id, patternUnits: 'userSpaceOnUse', width: '8', height: '8', children: [_jsx("rect", { width: '8', height: '8', fill: color }), index % 3 === 1 ? (_jsx("path", { d: 'M-2 2L2-2M0 8L8 0M6 10L10 6', stroke: 'var(--canvas)', strokeWidth: '1.5' })) : index % 3 === 2 ? (_jsx("circle", { cx: '4', cy: '4', r: '1.4', fill: 'var(--canvas)' })) : null] }));
|
|
20
20
|
}
|
|
21
21
|
/** Cartesian trends with a persistent, keyboard-readable tooltip region and a
|
|
22
22
|
* full data-table alternative. Missing values are gaps, never fabricated zeros. */
|
|
23
|
-
export const Chart = React.forwardRef(function Chart({ title, description, data, series, unit, xLabel, yLabel, type =
|
|
24
|
-
const id = React.useId().replace(/[^a-zA-Z0-9_-]/g,
|
|
23
|
+
export const Chart = React.forwardRef(function Chart({ title, description, data, series, unit, xLabel, yLabel, type = 'line', height = 280, locale = 'en-US', formatValue, missingLabel = 'Not available', emptyLabel = 'No numeric measurements to display.', hiddenSeries, defaultHiddenSeries = [], onHiddenSeriesChange, className, ...props }, ref) {
|
|
24
|
+
const id = React.useId().replace(/[^a-zA-Z0-9_-]/g, '_');
|
|
25
25
|
const [internalHidden, setInternalHidden] = React.useState(defaultHiddenSeries);
|
|
26
26
|
const hidden = new Set(hiddenSeries ?? internalHidden);
|
|
27
27
|
const visible = series.filter((s) => !hidden.has(s.key));
|
|
@@ -38,28 +38,28 @@ export const Chart = React.forwardRef(function Chart({ title, description, data,
|
|
|
38
38
|
}, [restoreRequested, visible.length]);
|
|
39
39
|
const number = React.useMemo(() => new Intl.NumberFormat(locale, { maximumFractionDigits: 2 }), [locale]);
|
|
40
40
|
const compact = React.useMemo(() => new Intl.NumberFormat(locale, {
|
|
41
|
-
notation:
|
|
41
|
+
notation: 'compact',
|
|
42
42
|
maximumFractionDigits: 1,
|
|
43
43
|
}), [locale]);
|
|
44
|
-
const format = (value) => typeof value ===
|
|
44
|
+
const format = (value) => typeof value === 'number' && Number.isFinite(value)
|
|
45
45
|
? `${formatValue ? formatValue(value) : number.format(value)} ${unit}`
|
|
46
46
|
: missingLabel;
|
|
47
47
|
const rows = React.useMemo(() => {
|
|
48
48
|
const ids = new Set(), keys = new Set();
|
|
49
49
|
for (const s of series) {
|
|
50
50
|
if (!s.key || keys.has(s.key))
|
|
51
|
-
throw new Error(
|
|
51
|
+
throw new Error('Chart series keys must be non-empty and unique');
|
|
52
52
|
keys.add(s.key);
|
|
53
53
|
}
|
|
54
54
|
return data.map((row) => {
|
|
55
55
|
if (!row.id || ids.has(row.id))
|
|
56
|
-
throw new Error(
|
|
56
|
+
throw new Error('Chart datum IDs must be non-empty and unique');
|
|
57
57
|
ids.add(row.id);
|
|
58
58
|
return {
|
|
59
59
|
...row,
|
|
60
60
|
values: Object.fromEntries(series.map((s) => [
|
|
61
61
|
s.key,
|
|
62
|
-
typeof row.values[s.key] ===
|
|
62
|
+
typeof row.values[s.key] === 'number' &&
|
|
63
63
|
Number.isFinite(row.values[s.key])
|
|
64
64
|
? row.values[s.key]
|
|
65
65
|
: null,
|
|
@@ -70,7 +70,7 @@ export const Chart = React.forwardRef(function Chart({ title, description, data,
|
|
|
70
70
|
const byId = new Map(rows.map((row) => [row.id, row]));
|
|
71
71
|
const values = rows
|
|
72
72
|
.flatMap((row) => visible.map((s) => row.values[s.key]))
|
|
73
|
-
.filter((value) => typeof value ===
|
|
73
|
+
.filter((value) => typeof value === 'number');
|
|
74
74
|
const min = values.reduce((a, b) => Math.min(a, b), 0), max = values.reduce((a, b) => Math.max(a, b), 0);
|
|
75
75
|
const hasValues = values.length > 0;
|
|
76
76
|
const changeHidden = (next) => {
|
|
@@ -82,28 +82,30 @@ export const Chart = React.forwardRef(function Chart({ title, description, data,
|
|
|
82
82
|
.filter((s) => (s.key === key ? !hidden.has(key) : hidden.has(s.key)))
|
|
83
83
|
.map((s) => s.key));
|
|
84
84
|
const chartHeight = Number.isFinite(height) ? Math.max(200, height) : 280;
|
|
85
|
-
return (_jsxs("figure", { ...props, ref: ref, className: [
|
|
86
|
-
if (event.key ===
|
|
85
|
+
return (_jsxs("figure", { ...props, ref: ref, className: ['pui-chart', className].filter(Boolean).join(' '), "aria-labelledby": `${id}-title`, children: [_jsxs("figcaption", { className: 'pui-chart-caption', children: [_jsx("strong", { id: `${id}-title`, children: title }), _jsx("p", { id: `${id}-summary`, children: description })] }), _jsx("ul", { className: 'pui-chart-legend', "aria-label": `${title} series`, children: series.map((s, index) => (_jsx("li", { children: _jsxs("button", { ref: index === 0 ? firstLegend : undefined, type: 'button', className: 'pui-chart-legend-button', "aria-label": `${s.label} series`, "aria-pressed": !hidden.has(s.key), onClick: () => toggle(s.key), children: [_jsx("svg", { width: '32', height: '20', viewBox: '0 0 32 20', "aria-hidden": 'true', children: type === 'bar' ? (_jsxs(_Fragment, { children: [_jsx("defs", { children: _jsx(Pattern, { id: `${id}-legend-${index}`, color: colorFor(index), index: index }) }), _jsx("rect", { x: '4', y: '3', width: '24', height: '14', rx: '2', fill: `url(#${id}-legend-${index})` })] })) : (_jsxs(_Fragment, { children: [_jsx("path", { d: 'M1 10h30', stroke: colorFor(index), strokeWidth: '2', strokeDasharray: dashes[index % dashes.length] }), _jsx(Marker, { cx: 16, cy: 10, index: index, color: colorFor(index) })] })) }), _jsx("span", { children: s.label })] }) }, s.key))) }), _jsxs("p", { className: 'pui-chart-axis-label', children: [yLabel, " (", unit, ")"] }), hasValues ? (_jsxs(_Fragment, { children: [_jsx("p", { className: 'pui-chart-help', id: `${id}-keys`, children: "Focus the chart and use Left/Right to inspect points. Escape clears details. The data table includes every series." }), _jsx("div", { className: 'pui-chart-plot', onKeyDownCapture: (event) => {
|
|
86
|
+
if (event.key === 'Escape')
|
|
87
87
|
setDismissed(true);
|
|
88
|
-
else if (event.key ===
|
|
88
|
+
else if (event.key === 'ArrowLeft' || event.key === 'ArrowRight')
|
|
89
89
|
setDismissed(false);
|
|
90
|
-
}, onMouseMoveCapture: () => setDismissed(false), onTouchStartCapture: () => setDismissed(false), onFocusCapture: () => setDismissed(false), children: _jsx(ResponsiveContainer, { width:
|
|
90
|
+
}, onMouseMoveCapture: () => setDismissed(false), onTouchStartCapture: () => setDismissed(false), onFocusCapture: () => setDismissed(false), children: _jsx(ResponsiveContainer, { width: '100%', height: chartHeight, minWidth: 0, initialDimension: { width: 320, height: chartHeight }, children: _jsxs(ComposedChart, { data: rows, accessibilityLayer: true, role: 'application', "aria-label": title, "aria-describedby": `${id}-summary ${id}-keys`, margin: { top: 16, right: 20, bottom: 8, left: 0 }, children: [_jsx("defs", { children: series.map((s, index) => (_jsx(Pattern, { id: `${id}-pattern-${index}`, index: index, color: colorFor(index) }, s.key))) }), _jsx(CartesianGrid, { vertical: false, stroke: 'var(--line)' }), _jsx(XAxis, { dataKey: 'id', tickFormatter: (value) => {
|
|
91
91
|
const label = byId.get(String(value))?.label ?? String(value);
|
|
92
|
-
|
|
93
|
-
|
|
92
|
+
// minTickGap already drops ticks that would overlap; the cap
|
|
93
|
+
// only keeps one very long label from crowding the axis.
|
|
94
|
+
return label.length > 24 ? label.slice(0, 23) + '…' : label;
|
|
95
|
+
}, tick: { fill: 'var(--ink-muted)', fontSize: 12 }, tickLine: false, axisLine: { stroke: 'var(--line)' }, minTickGap: 24, interval: 'preserveStartEnd' }), _jsx(YAxis, { width: 56, tickFormatter: (value) => compact.format(Number(value)), tick: { fill: 'var(--ink-muted)', fontSize: 12 }, tickLine: false, axisLine: false, domain: [min, max === min ? max + 1 : max] }), _jsx(ReferenceLine, { y: 0, stroke: 'var(--ink-muted)' }), host && (_jsx(Tooltip, { portal: host, isAnimationActive: false, active: dismissed ? false : undefined, filterNull: false, cursor: dismissed
|
|
94
96
|
? false
|
|
95
97
|
: {
|
|
96
|
-
stroke:
|
|
97
|
-
fill:
|
|
98
|
+
stroke: 'var(--control-border)',
|
|
99
|
+
fill: 'transparent',
|
|
98
100
|
}, wrapperStyle: {
|
|
99
|
-
position:
|
|
100
|
-
visibility:
|
|
101
|
-
pointerEvents:
|
|
101
|
+
position: 'static',
|
|
102
|
+
visibility: 'visible',
|
|
103
|
+
pointerEvents: 'auto',
|
|
102
104
|
}, content: (tooltip) => {
|
|
103
105
|
const row = tooltip.active && !dismissed
|
|
104
106
|
? byId.get(String(tooltip.label))
|
|
105
107
|
: undefined;
|
|
106
|
-
return (_jsx("div", { className:
|
|
108
|
+
return (_jsx("div", { className: 'pui-chart-readout', "data-chart-readout": row?.id, children: row ? (_jsxs(_Fragment, { children: [_jsx("strong", { children: row.label }), _jsx("ul", { children: visible.map((s) => (_jsxs("li", { children: [s.label, ": ", format(row.values[s.key])] }, s.key))) })] })) : (_jsx("span", { children: "Hover, touch or use chart arrow keys to inspect a measurement." })) }));
|
|
107
109
|
} })), series.map((s, index) => {
|
|
108
110
|
const common = {
|
|
109
111
|
name: s.label,
|
|
@@ -112,13 +114,13 @@ export const Chart = React.forwardRef(function Chart({ title, description, data,
|
|
|
112
114
|
isAnimationActive: false,
|
|
113
115
|
stroke: colorFor(index),
|
|
114
116
|
};
|
|
115
|
-
return type ===
|
|
117
|
+
return type === 'bar' ? (_jsx(Bar, { ...common, fill: `url(#${id}-pattern-${index})`, maxBarSize: 48 }, s.key)) : type === 'area' ? (_jsx(Area, { ...common, type: 'linear', strokeWidth: 2, strokeDasharray: dashes[index % dashes.length], fill: `url(#${id}-pattern-${index})`, fillOpacity: 0.12, connectNulls: false, dot: rows.length > 40
|
|
116
118
|
? false
|
|
117
|
-
: (dot) => (_jsx(Marker, { ...dot, color: colorFor(index), index: index })), activeDot: false }, s.key)) : (_jsx(Line, { ...common, type:
|
|
119
|
+
: (dot) => (_jsx(Marker, { ...dot, color: colorFor(index), index: index })), activeDot: false }, s.key)) : (_jsx(Line, { ...common, type: 'linear', strokeWidth: 2, strokeDasharray: dashes[index % dashes.length], connectNulls: false, dot: rows.length > 40
|
|
118
120
|
? false
|
|
119
121
|
: (dot) => (_jsx(Marker, { ...dot, color: colorFor(index), index: index })), activeDot: false }, s.key));
|
|
120
|
-
})] }) }) }), _jsx("p", { className:
|
|
122
|
+
})] }) }) }), _jsx("p", { className: 'pui-chart-axis-label pui-chart-x-label', children: xLabel })] })) : (_jsx("div", { className: 'pui-chart-empty', role: 'status', children: visible.length === 0 && series.length > 0 ? (_jsxs(_Fragment, { children: [_jsx("p", { children: "No series selected." }), _jsx(Button, { variant: 'outline', onClick: () => {
|
|
121
123
|
setRestoreRequested(true);
|
|
122
124
|
changeHidden([]);
|
|
123
|
-
}, children: "Show all series" })] })) : (_jsx("p", { children: emptyLabel })) })), _jsx("div", { className:
|
|
125
|
+
}, children: "Show all series" })] })) : (_jsx("p", { children: emptyLabel })) })), _jsx("div", { className: 'pui-chart-inspector', ref: setHost, role: 'status', "aria-live": 'polite', "aria-atomic": 'true', "aria-label": `${title} values`, hidden: !hasValues }), _jsxs("details", { className: 'pui-chart-table', children: [_jsx("summary", { children: "View data table" }), _jsx(Table.Container, { label: `${title} data table`, orientation: 'both', scrollChain: 'contain', style: { maxHeight: 320 }, children: _jsxs(Table.Root, { children: [_jsxs(Table.Caption, { children: ["All input measurements, including hidden series. Unit: ", unit, "."] }), _jsx(Table.Head, { children: _jsxs(Table.Row, { children: [_jsx(Table.HeaderCell, { scope: 'col', children: xLabel }), series.map((s) => (_jsxs(Table.HeaderCell, { scope: 'col', children: [s.label, " (", unit, ")"] }, s.key)))] }) }), _jsx(Table.Body, { children: rows.length ? (rows.map((row) => (_jsxs(Table.Row, { children: [_jsx(Table.HeaderCell, { scope: 'row', children: row.label }), series.map((s) => (_jsx(Table.Cell, { children: format(row.values[s.key]) }, s.key)))] }, row.id)))) : (_jsx(Table.Row, { children: _jsx(Table.Cell, { colSpan: series.length + 1, children: "No rows." }) })) })] }) })] })] }));
|
|
124
126
|
});
|
package/dist/commands.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import * as React from
|
|
2
|
-
import { type ComponentSizeAlias } from
|
|
3
|
-
import { Toggle as BaseToggle } from
|
|
4
|
-
import { ToggleGroup as BaseToggleGroup } from
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { type ComponentSizeAlias } from './sizing.js';
|
|
3
|
+
import { Toggle as BaseToggle } from '@base-ui/react/toggle';
|
|
4
|
+
import { ToggleGroup as BaseToggleGroup } from '@base-ui/react/toggle-group';
|
|
5
5
|
export declare function Toggle<Value extends string>({ className, size, ref, ...props }: BaseToggle.Props<Value> & {
|
|
6
|
-
size?: ComponentSizeAlias |
|
|
6
|
+
size?: ComponentSizeAlias | 'icon';
|
|
7
7
|
ref?: React.Ref<HTMLButtonElement>;
|
|
8
8
|
}): React.JSX.Element;
|
|
9
9
|
export declare function ToggleGroup<Value extends string>({ className, ref, ...props }: BaseToggleGroup.Props<Value> & {
|
package/dist/commands.js
CHANGED
|
@@ -1,27 +1,27 @@
|
|
|
1
|
-
|
|
1
|
+
'use client';
|
|
2
2
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
-
import { useComponentSize } from
|
|
4
|
-
import { Toggle as BaseToggle } from
|
|
5
|
-
import { ToggleGroup as BaseToggleGroup } from
|
|
6
|
-
import { Toolbar as BaseToolbar } from
|
|
7
|
-
import { Menubar as BaseMenubar } from
|
|
8
|
-
import { skin, part } from
|
|
3
|
+
import { useComponentSize } from './sizing.js';
|
|
4
|
+
import { Toggle as BaseToggle } from '@base-ui/react/toggle';
|
|
5
|
+
import { ToggleGroup as BaseToggleGroup } from '@base-ui/react/toggle-group';
|
|
6
|
+
import { Toolbar as BaseToolbar } from '@base-ui/react/toolbar';
|
|
7
|
+
import { Menubar as BaseMenubar } from '@base-ui/react/menubar';
|
|
8
|
+
import { skin, part } from './parts.js';
|
|
9
9
|
export function Toggle({ className, size, ref, ...props }) {
|
|
10
|
-
const scheme = useComponentSize(size ===
|
|
11
|
-
return (_jsx(BaseToggle, { ...props, ref: ref, className: skin(
|
|
10
|
+
const scheme = useComponentSize(size === 'icon' ? undefined : size);
|
|
11
|
+
return (_jsx(BaseToggle, { ...props, ref: ref, className: skin('pui-button pui-toggle', className), "data-size": size, "data-ui-size": scheme }));
|
|
12
12
|
}
|
|
13
13
|
export function ToggleGroup({ className, ref, ...props }) {
|
|
14
|
-
return (_jsx(BaseToggleGroup, { ...props, ref: ref, className: skin(
|
|
14
|
+
return (_jsx(BaseToggleGroup, { ...props, ref: ref, className: skin('pui-toggle-group', className) }));
|
|
15
15
|
}
|
|
16
16
|
export const Toolbar = {
|
|
17
17
|
...BaseToolbar,
|
|
18
|
-
Root: part(BaseToolbar.Root,
|
|
19
|
-
Group: part(BaseToolbar.Group,
|
|
20
|
-
Button: part(BaseToolbar.Button,
|
|
21
|
-
Link: part(BaseToolbar.Link,
|
|
22
|
-
Input: part(BaseToolbar.Input,
|
|
23
|
-
Separator: part(BaseToolbar.Separator,
|
|
18
|
+
Root: part(BaseToolbar.Root, 'pui-toolbar'),
|
|
19
|
+
Group: part(BaseToolbar.Group, 'pui-toolbar-group'),
|
|
20
|
+
Button: part(BaseToolbar.Button, 'pui-button pui-toolbar-button'),
|
|
21
|
+
Link: part(BaseToolbar.Link, 'pui-button pui-toolbar-link'),
|
|
22
|
+
Input: part(BaseToolbar.Input, 'pui-input pui-toolbar-input'),
|
|
23
|
+
Separator: part(BaseToolbar.Separator, 'pui-toolbar-separator'),
|
|
24
24
|
};
|
|
25
|
-
export const Menubar = part(BaseMenubar,
|
|
25
|
+
export const Menubar = part(BaseMenubar, 'pui-menubar');
|
|
26
26
|
// Flat names for React Server Components, which cannot dot into client exports.
|
|
27
27
|
export const { Button: ToolbarButton, Group: ToolbarGroup, Input: ToolbarInput, Link: ToolbarLink, Root: ToolbarRoot, Separator: ToolbarSeparator, } = Toolbar;
|
package/dist/content.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import * as React from
|
|
1
|
+
import * as React from 'react';
|
|
2
2
|
declare const CardRoot: React.ForwardRefExoticComponent<Omit<Omit<React.ClassAttributes<HTMLDivElement> & React.HTMLAttributes<HTMLDivElement> & {
|
|
3
3
|
tone?: "canvas" | "subtle";
|
|
4
4
|
padding?: import("./foundations.js").Space;
|
|
@@ -27,7 +27,7 @@ export declare const Card: {
|
|
|
27
27
|
size?: import("./sizing.js").ComponentSize;
|
|
28
28
|
} & React.RefAttributes<HTMLDivElement>>;
|
|
29
29
|
};
|
|
30
|
-
export type CodeBlockProps = Omit<React.ComponentPropsWithoutRef<
|
|
30
|
+
export type CodeBlockProps = Omit<React.ComponentPropsWithoutRef<'div'>, 'children' | 'onCopy'> & {
|
|
31
31
|
code: string;
|
|
32
32
|
label?: string;
|
|
33
33
|
language?: string;
|