@xenosystem/elements-react 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +18 -0
- package/README.md +41 -0
- package/dist/XenoElement.d.ts +39 -0
- package/dist/XenoElement.js +25 -0
- package/dist/containers/Avatar.d.ts +42 -0
- package/dist/containers/Avatar.js +29 -0
- package/dist/containers/Badges.d.ts +61 -0
- package/dist/containers/Badges.js +43 -0
- package/dist/containers/Card.d.ts +24 -0
- package/dist/containers/Card.js +5 -0
- package/dist/containers/Chip.d.ts +34 -0
- package/dist/containers/Chip.js +17 -0
- package/dist/containers/DataTable.d.ts +28 -0
- package/dist/containers/DataTable.js +13 -0
- package/dist/containers/ListRow.d.ts +37 -0
- package/dist/containers/ListRow.js +40 -0
- package/dist/containers/MessageBubble.d.ts +33 -0
- package/dist/containers/MessageBubble.js +9 -0
- package/dist/containers/Panel.d.ts +24 -0
- package/dist/containers/Panel.js +6 -0
- package/dist/containers/Table.d.ts +39 -0
- package/dist/containers/Table.js +20 -0
- package/dist/containers/Tile.d.ts +19 -0
- package/dist/containers/Tile.js +7 -0
- package/dist/content/Callout.d.ts +32 -0
- package/dist/content/Callout.js +10 -0
- package/dist/content/Caret.d.ts +9 -0
- package/dist/content/Caret.js +5 -0
- package/dist/content/CodeBlock.d.ts +36 -0
- package/dist/content/CodeBlock.js +50 -0
- package/dist/content/Collapsible.d.ts +24 -0
- package/dist/content/Collapsible.js +19 -0
- package/dist/content/InlineCode.d.ts +12 -0
- package/dist/content/InlineCode.js +5 -0
- package/dist/content/ModelPicker.d.ts +45 -0
- package/dist/content/ModelPicker.js +124 -0
- package/dist/content/SourceCard.d.ts +23 -0
- package/dist/content/SourceCard.js +18 -0
- package/dist/content/SourcesDisclosure.d.ts +26 -0
- package/dist/content/SourcesDisclosure.js +20 -0
- package/dist/controls/Button.d.ts +39 -0
- package/dist/controls/Button.js +16 -0
- package/dist/controls/ConfirmButton.d.ts +22 -0
- package/dist/controls/ConfirmButton.js +22 -0
- package/dist/controls/IconButton.d.ts +45 -0
- package/dist/controls/IconButton.js +15 -0
- package/dist/controls/Switch.d.ts +11 -0
- package/dist/controls/Switch.js +23 -0
- package/dist/controls/TextInput.d.ts +13 -0
- package/dist/controls/TextInput.js +6 -0
- package/dist/controls/Textarea.d.ts +8 -0
- package/dist/controls/Textarea.js +5 -0
- package/dist/controls/ToggleButton.d.ts +23 -0
- package/dist/controls/ToggleButton.js +23 -0
- package/dist/controls/util.d.ts +48 -0
- package/dist/controls/util.js +23 -0
- package/dist/forms/Checkbox.d.ts +18 -0
- package/dist/forms/Checkbox.js +28 -0
- package/dist/forms/RadioGroup.d.ts +51 -0
- package/dist/forms/RadioGroup.js +83 -0
- package/dist/index.d.ts +75 -0
- package/dist/index.js +81 -0
- package/dist/layout/ResizablePanel.d.ts +40 -0
- package/dist/layout/ResizablePanel.js +108 -0
- package/dist/nav/Sidebar.d.ts +60 -0
- package/dist/nav/Sidebar.js +84 -0
- package/dist/overlays/DateTimePicker.d.ts +71 -0
- package/dist/overlays/DateTimePicker.js +191 -0
- package/dist/overlays/Menu.d.ts +28 -0
- package/dist/overlays/Menu.js +32 -0
- package/dist/overlays/MenuItem.d.ts +71 -0
- package/dist/overlays/MenuItem.js +15 -0
- package/dist/overlays/Modal.d.ts +36 -0
- package/dist/overlays/Modal.js +27 -0
- package/dist/overlays/PickerField.d.ts +32 -0
- package/dist/overlays/PickerField.js +40 -0
- package/dist/overlays/PillFilter.d.ts +25 -0
- package/dist/overlays/PillFilter.js +41 -0
- package/dist/overlays/Popover.d.ts +32 -0
- package/dist/overlays/Popover.js +38 -0
- package/dist/overlays/Reveal.d.ts +20 -0
- package/dist/overlays/Reveal.js +45 -0
- package/dist/overlays/SegmentedControl.d.ts +23 -0
- package/dist/overlays/SegmentedControl.js +43 -0
- package/dist/overlays/Tabs.d.ts +32 -0
- package/dist/overlays/Tabs.js +142 -0
- package/dist/overlays/Tooltip.d.ts +23 -0
- package/dist/overlays/Tooltip.js +61 -0
- package/dist/status/ProgressBar.d.ts +20 -0
- package/dist/status/ProgressBar.js +11 -0
- package/dist/status/Spinner.d.ts +16 -0
- package/dist/status/Spinner.js +12 -0
- package/dist/status/StatusIndicator.d.ts +19 -0
- package/dist/status/StatusIndicator.js +11 -0
- package/dist/status/StepTimeline.d.ts +26 -0
- package/dist/status/StepTimeline.js +16 -0
- package/dist/status/ThinkingCube.d.ts +24 -0
- package/dist/status/ThinkingCube.js +11 -0
- package/dist/useDialog.d.ts +45 -0
- package/dist/useDialog.js +122 -0
- package/dist/useGooPill.d.ts +57 -0
- package/dist/useGooPill.js +76 -0
- package/dist/useMenu.d.ts +50 -0
- package/dist/useMenu.js +119 -0
- package/dist/useTabs.d.ts +88 -0
- package/dist/useTabs.js +93 -0
- package/package.json +58 -0
- package/src/chrome-separated.css +132 -0
- package/src/chrome-unified.css +72 -0
- package/src/containers/Badges.css +116 -0
- package/src/containers/avatar.css +70 -0
- package/src/containers/card.css +75 -0
- package/src/containers/chip.css +103 -0
- package/src/containers/list-row.css +132 -0
- package/src/containers/message-bubble.css +112 -0
- package/src/containers/panel.css +120 -0
- package/src/containers/table.css +102 -0
- package/src/containers/tile.css +17 -0
- package/src/content/callout.css +77 -0
- package/src/content/caret.css +30 -0
- package/src/content/code-block.css +159 -0
- package/src/content/collapsible.css +80 -0
- package/src/content/inline-code.css +14 -0
- package/src/content/model-picker.css +219 -0
- package/src/content/source-card.css +99 -0
- package/src/content/sources-disclosure.css +118 -0
- package/src/controls.css +453 -0
- package/src/fonts.css +34 -0
- package/src/forms/Checkbox.css +114 -0
- package/src/forms/RadioGroup.css +115 -0
- package/src/goo.css +97 -0
- package/src/icon-motion.css +1909 -0
- package/src/layout/ResizablePanel.css +79 -0
- package/src/nav/sidebar.css +296 -0
- package/src/overlays/date-time-picker.css +238 -0
- package/src/overlays/menu.css +195 -0
- package/src/overlays/modal.css +167 -0
- package/src/overlays/picker-field.css +81 -0
- package/src/overlays/pill-filter.css +129 -0
- package/src/overlays/reveal.css +56 -0
- package/src/overlays/segmented-control.css +185 -0
- package/src/overlays/tabs.css +143 -0
- package/src/overlays/tooltip.css +126 -0
- package/src/scrollbar.css +184 -0
- package/src/size.css +179 -0
- package/src/status/progress-bar.css +88 -0
- package/src/status/spinner.css +33 -0
- package/src/status/statusindicator.css +65 -0
- package/src/status/steptimeline.css +137 -0
- package/src/status/thinkingcube.css +75 -0
- package/src/xeno-element.css +60 -0
- package/src/xeno-elements.css +71 -0
- package/src/xeno-theme.css +99 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { forwardRef } from 'react';
|
|
3
|
+
import { XenoElement } from '../XenoElement.js';
|
|
4
|
+
import { sizeAttr, iconPx, cx } from './util.js';
|
|
5
|
+
/**
|
|
6
|
+
* Ref-forwarding, and it is load-bearing rather than tidy. These buttons anchor things: a popover
|
|
7
|
+
* positions against the one that opened it, a focus-restore puts focus back on it after a dialog
|
|
8
|
+
* closes. On React 19 `ref` is an ordinary prop and a plain function component would pass it through;
|
|
9
|
+
* on React 18 — still inside this package's peer range — `createElement` STRIPS it, so the consumer's
|
|
10
|
+
* `ref.current` stays null and the anchor silently lands at 0,0. Same reasoning as `RadioRow`.
|
|
11
|
+
*/
|
|
12
|
+
export const Button = forwardRef(function Button({ variant = 'secondary', size = 'md', leadingIcon, trailingIcon, busy = false, enter = false, disabled = false, className, children, type = 'button', ...rest }, ref) {
|
|
13
|
+
const availability = disabled ? 'disabled' : busy ? 'busy' : 'enabled';
|
|
14
|
+
const glyph = iconPx(size);
|
|
15
|
+
return (_jsxs("button", { ref: ref, type: type, className: cx('xeno-btn', className), "data-variant": variant, "data-availability": availability, "data-enter": enter ? '' : undefined, disabled: disabled, "aria-busy": busy || undefined, ...sizeAttr(size), ...rest, children: [leadingIcon && _jsx(XenoElement, { decl: leadingIcon, size: glyph }), children, trailingIcon && _jsx(XenoElement, { decl: trailingIcon, size: glyph })] }));
|
|
16
|
+
});
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { ReactElement } from 'react';
|
|
2
|
+
import type { ElementDeclaration } from '@xenosystem/elements/schema';
|
|
3
|
+
import { type IconButtonProps } from './IconButton.js';
|
|
4
|
+
/**
|
|
5
|
+
* `<ConfirmButton>` — an {@link IconButton} that, on activate, swaps its glyph to a confirmation (a
|
|
6
|
+
* check by default) for a beat, then reverts. Generalises the copy→check affordance the CodeBlock
|
|
7
|
+
* hand-rolls, so any action can acknowledge itself. The confirmed glyph pops in on the overshoot easing;
|
|
8
|
+
* the swap and `aria-label` update announce success to a screen reader.
|
|
9
|
+
*/
|
|
10
|
+
export interface ConfirmButtonProps extends Omit<IconButtonProps, 'icon'> {
|
|
11
|
+
/** The resting glyph (e.g. `xeno.copy`). */
|
|
12
|
+
readonly icon: ElementDeclaration;
|
|
13
|
+
/** The glyph shown after activating. Default `xeno.check`. */
|
|
14
|
+
readonly confirmIcon?: ElementDeclaration;
|
|
15
|
+
/** How long the confirmation shows, ms. Default 1500. */
|
|
16
|
+
readonly confirmMs?: number;
|
|
17
|
+
/** `aria-label` while confirmed (e.g. "Copied"). Falls back to the resting label. */
|
|
18
|
+
readonly confirmLabel?: string;
|
|
19
|
+
/** Fired when the action is taken (do the copy/etc. here). */
|
|
20
|
+
readonly onConfirm?: () => void;
|
|
21
|
+
}
|
|
22
|
+
export declare function ConfirmButton({ icon, confirmIcon, confirmMs, confirmLabel, onConfirm, onClick, 'aria-label': ariaLabel, ...rest }: ConfirmButtonProps): ReactElement;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useRef, useState } from 'react';
|
|
3
|
+
import Check from '@xenosystem/elements/elements/check';
|
|
4
|
+
import { IconButton } from './IconButton.js';
|
|
5
|
+
export function ConfirmButton({ icon, confirmIcon = Check, confirmMs = 1500, confirmLabel, onConfirm, onClick, 'aria-label': ariaLabel, ...rest }) {
|
|
6
|
+
const [confirmed, setConfirmed] = useState(false);
|
|
7
|
+
const timer = useRef(null);
|
|
8
|
+
useEffect(() => () => {
|
|
9
|
+
if (timer.current)
|
|
10
|
+
clearTimeout(timer.current);
|
|
11
|
+
}, []);
|
|
12
|
+
return (_jsx(IconButton, { icon: confirmed ? confirmIcon : icon, "aria-label": confirmed ? (confirmLabel ?? ariaLabel) : ariaLabel, "data-confirmed": confirmed ? '' : undefined, onClick: (e) => {
|
|
13
|
+
onClick?.(e);
|
|
14
|
+
if (e.defaultPrevented)
|
|
15
|
+
return;
|
|
16
|
+
onConfirm?.();
|
|
17
|
+
setConfirmed(true);
|
|
18
|
+
if (timer.current)
|
|
19
|
+
clearTimeout(timer.current);
|
|
20
|
+
timer.current = setTimeout(() => setConfirmed(false), confirmMs);
|
|
21
|
+
}, ...rest }));
|
|
22
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { ButtonHTMLAttributes } from 'react';
|
|
2
|
+
import type { ElementDeclaration } from '@xenosystem/elements/schema';
|
|
3
|
+
import { type ControlSizeToken } from './util.js';
|
|
4
|
+
import type { ButtonVariant } from './Button.js';
|
|
5
|
+
/**
|
|
6
|
+
* `<IconButton>` — a square, icon-only control (the single most-duplicated pattern in the chat, found
|
|
7
|
+
* at 4 sizes × 2 colour families). `aria-label` is REQUIRED because there is no text label. The glyph
|
|
8
|
+
* is a declaration, drawn by the shared renderer, so it inherits the button's monochrome ink.
|
|
9
|
+
*/
|
|
10
|
+
export interface IconButtonProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'style'> {
|
|
11
|
+
readonly icon: ElementDeclaration;
|
|
12
|
+
readonly 'aria-label': string;
|
|
13
|
+
readonly variant?: ButtonVariant;
|
|
14
|
+
readonly size?: ControlSizeToken;
|
|
15
|
+
readonly busy?: boolean;
|
|
16
|
+
/** Play the entrance animation on mount (fade + slide + scale up). */
|
|
17
|
+
readonly enter?: boolean;
|
|
18
|
+
/**
|
|
19
|
+
* The glyph's px, when the size token's own is not what this control wants.
|
|
20
|
+
*
|
|
21
|
+
* Every other metric a control has — height, padding, gap, font — is a CSS variable that a surface
|
|
22
|
+
* can redefine once at the root. The glyph was the exception: computed in JS from the size token and
|
|
23
|
+
* therefore the one number a consumer could not reach.
|
|
24
|
+
*
|
|
25
|
+
* That gap is what stalled a real adoption. A chat with fifty-one icon buttons drew its glyphs at
|
|
26
|
+
* 13, 14, 15 and 16 px, and this component could offer only the scale's own 15/16/16/18 — so taking
|
|
27
|
+
* the component meant taking a restyle of every one of them in the same commit, with no way to tell
|
|
28
|
+
* afterwards which change someone disliked. A component swap and a resize are two edits and belong
|
|
29
|
+
* in two commits.
|
|
30
|
+
*
|
|
31
|
+
* Not an invitation to drift. The set already holds two deliberate exceptions — the chip's remove ×
|
|
32
|
+
* and the model picker's are `glyph - 2` — so the honest thing is a named door rather than a rule
|
|
33
|
+
* that says nobody ever needs one. Omit it and the scale decides, which is what should usually
|
|
34
|
+
* happen.
|
|
35
|
+
*/
|
|
36
|
+
readonly iconSize?: number;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Ref-forwarding, and it is load-bearing rather than tidy. These buttons anchor things: a popover
|
|
40
|
+
* positions against the one that opened it, a focus-restore puts focus back on it after a dialog
|
|
41
|
+
* closes. On React 19 `ref` is an ordinary prop and a plain function component would pass it through;
|
|
42
|
+
* on React 18 — still inside this package's peer range — `createElement` STRIPS it, so the consumer's
|
|
43
|
+
* `ref.current` stays null and the anchor silently lands at 0,0. Same reasoning as `RadioRow`.
|
|
44
|
+
*/
|
|
45
|
+
export declare const IconButton: import("react").ForwardRefExoticComponent<IconButtonProps & import("react").RefAttributes<HTMLButtonElement>>;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { forwardRef } from 'react';
|
|
3
|
+
import { XenoElement } from '../XenoElement.js';
|
|
4
|
+
import { sizeAttr, iconPx, cx } from './util.js';
|
|
5
|
+
/**
|
|
6
|
+
* Ref-forwarding, and it is load-bearing rather than tidy. These buttons anchor things: a popover
|
|
7
|
+
* positions against the one that opened it, a focus-restore puts focus back on it after a dialog
|
|
8
|
+
* closes. On React 19 `ref` is an ordinary prop and a plain function component would pass it through;
|
|
9
|
+
* on React 18 — still inside this package's peer range — `createElement` STRIPS it, so the consumer's
|
|
10
|
+
* `ref.current` stays null and the anchor silently lands at 0,0. Same reasoning as `RadioRow`.
|
|
11
|
+
*/
|
|
12
|
+
export const IconButton = forwardRef(function IconButton({ icon, variant = 'ghost', size = 'md', busy = false, enter = false, iconSize, disabled = false, className, type = 'button', ...rest }, ref) {
|
|
13
|
+
const availability = disabled ? 'disabled' : busy ? 'busy' : 'enabled';
|
|
14
|
+
return (_jsx("button", { ref: ref, type: type, className: cx('xeno-btn', 'xeno-icon-btn', className), "data-variant": variant, "data-availability": availability, "data-enter": enter ? '' : undefined, disabled: disabled, "aria-busy": busy || undefined, ...sizeAttr(size), ...rest, children: _jsx(XenoElement, { decl: icon, size: iconSize ?? iconPx(size) }) }));
|
|
15
|
+
});
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type ButtonHTMLAttributes, type ReactElement } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* `<Switch>` — a track+knob on/off control. Grammar-consistent: the track is a rounded SQUARE
|
|
4
|
+
* (`radius.md`) and the knob a smaller rounded square (`radius.xs`) — never circles, matching the
|
|
5
|
+
* chat's locked square switch. Honours `selection` (data-selection / aria-checked) and `availability`.
|
|
6
|
+
*/
|
|
7
|
+
export interface SwitchProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'onChange' | 'children'> {
|
|
8
|
+
readonly checked: boolean;
|
|
9
|
+
readonly onCheckedChange?: (checked: boolean) => void;
|
|
10
|
+
}
|
|
11
|
+
export declare function Switch({ checked, onCheckedChange, disabled, className, onClick, ...rest }: SwitchProps): ReactElement;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useState } from 'react';
|
|
3
|
+
import { cx } from './util.js';
|
|
4
|
+
export function Switch({ checked, onCheckedChange, disabled = false, className, onClick, ...rest }) {
|
|
5
|
+
/**
|
|
6
|
+
* The knob's throw is a KEYFRAME, and a keyframe plays the moment its rule starts matching — so a
|
|
7
|
+
* switch that mounts in the "off" state would bounce on page load, unprompted. Arm the motion on the
|
|
8
|
+
* first render where `checked` actually CHANGES (whoever moved it — the click, or the parent), and
|
|
9
|
+
* leave it armed; before that the switch is simply drawn in whichever state it was handed.
|
|
10
|
+
*/
|
|
11
|
+
const [armed, setArmed] = useState(false);
|
|
12
|
+
const [seen, setSeen] = useState(checked);
|
|
13
|
+
if (seen !== checked) {
|
|
14
|
+
setSeen(checked);
|
|
15
|
+
if (!armed)
|
|
16
|
+
setArmed(true);
|
|
17
|
+
}
|
|
18
|
+
return (_jsx("button", { type: "button", role: "switch", "aria-checked": checked, className: cx('xeno-switch', className), "data-selection": checked ? 'on' : 'off', "data-availability": disabled ? 'disabled' : 'enabled', ...(armed ? { 'data-motion': 'ready' } : {}), disabled: disabled, onClick: (e) => {
|
|
19
|
+
onClick?.(e);
|
|
20
|
+
if (!e.defaultPrevented)
|
|
21
|
+
onCheckedChange?.(!checked);
|
|
22
|
+
}, ...rest, children: _jsx("span", { className: "xeno-switch-knob", "aria-hidden": "true" }) }));
|
|
23
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { InputHTMLAttributes, ReactElement } from 'react';
|
|
2
|
+
import type { ElementDeclaration } from '@xenosystem/elements/schema';
|
|
3
|
+
import { type ControlSizeToken } from './util.js';
|
|
4
|
+
/**
|
|
5
|
+
* `<TextInput>` — a single-line field. With `leadingIcon` set to `xeno.search` it is the SearchInput
|
|
6
|
+
* the chat hand-rolls ~7×. The icon is a declaration drawn by the shared renderer; the field is a bare
|
|
7
|
+
* native `<input>` so the wrapper owns the box and the input owns the text.
|
|
8
|
+
*/
|
|
9
|
+
export interface TextInputProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'size' | 'style'> {
|
|
10
|
+
readonly size?: ControlSizeToken;
|
|
11
|
+
readonly leadingIcon?: ElementDeclaration;
|
|
12
|
+
}
|
|
13
|
+
export declare function TextInput({ size, leadingIcon, disabled, className, ...rest }: TextInputProps): ReactElement;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { XenoElement } from '../XenoElement.js';
|
|
3
|
+
import { sizeAttr, iconPx, cx } from './util.js';
|
|
4
|
+
export function TextInput({ size = 'md', leadingIcon, disabled = false, className, ...rest }) {
|
|
5
|
+
return (_jsxs("div", { className: cx('xeno-input', className), "data-availability": disabled ? 'disabled' : 'enabled', ...sizeAttr(size), children: [leadingIcon && (_jsx("span", { className: "xeno-input-icon", "aria-hidden": "true", children: _jsx(XenoElement, { decl: leadingIcon, size: iconPx(size) }) })), _jsx("input", { className: "xeno-input-field", disabled: disabled, ...rest })] }));
|
|
6
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ReactElement, TextareaHTMLAttributes } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* `<Textarea>` — a multi-line field (card-radius, transparent-ish, focus tightens the border). The base
|
|
4
|
+
* of the chat composer; the full composer (tool rail + action row) is a Tier-2 container built on top.
|
|
5
|
+
*/
|
|
6
|
+
export interface TextareaProps extends Omit<TextareaHTMLAttributes<HTMLTextAreaElement>, 'style'> {
|
|
7
|
+
}
|
|
8
|
+
export declare function Textarea({ disabled, className, ...rest }: TextareaProps): ReactElement;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { cx } from './util.js';
|
|
3
|
+
export function Textarea({ disabled = false, className, ...rest }) {
|
|
4
|
+
return (_jsx("textarea", { className: cx('xeno-textarea', className), "data-availability": disabled ? 'disabled' : 'enabled', disabled: disabled, ...rest }));
|
|
5
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { type ButtonHTMLAttributes, type ReactElement, type ReactNode } from 'react';
|
|
2
|
+
import type { ElementDeclaration } from '@xenosystem/elements/schema';
|
|
3
|
+
import { type ControlSizeToken } from './util.js';
|
|
4
|
+
/**
|
|
5
|
+
* `<ToggleButton>` — a button-shaped on/off control (the chat's skills On/Off, byte-identical in two
|
|
6
|
+
* files). It honours the `selection` axis via `data-selection` and `aria-pressed` — the SAME axis the
|
|
7
|
+
* bookmark icon uses. Persistent selection, not a transient press.
|
|
8
|
+
*/
|
|
9
|
+
export interface ToggleButtonProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'style' | 'onChange'> {
|
|
10
|
+
readonly pressed: boolean;
|
|
11
|
+
readonly onPressedChange?: (pressed: boolean) => void;
|
|
12
|
+
readonly size?: ControlSizeToken;
|
|
13
|
+
readonly leadingIcon?: ElementDeclaration;
|
|
14
|
+
/** The label when OFF (and the only label, if `pressedChildren` is not given). */
|
|
15
|
+
readonly children?: ReactNode;
|
|
16
|
+
/**
|
|
17
|
+
* The label when ON — `Following` to a `Follow`, `Pinned` to a `Pin`. Give BOTH and the button holds
|
|
18
|
+
* one width for both: the longer word is what it is sized to, in either state, so pressing it never
|
|
19
|
+
* makes it jump. Omit it and the one label is used throughout.
|
|
20
|
+
*/
|
|
21
|
+
readonly pressedChildren?: ReactNode;
|
|
22
|
+
}
|
|
23
|
+
export declare function ToggleButton({ pressed, onPressedChange, size, leadingIcon, disabled, className, children, pressedChildren, onClick, ...rest }: ToggleButtonProps): ReactElement;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState } from 'react';
|
|
3
|
+
import { XenoElement } from '../XenoElement.js';
|
|
4
|
+
import { sizeAttr, iconPx, cx } from './util.js';
|
|
5
|
+
export function ToggleButton({ pressed, onPressedChange, size = 'md', leadingIcon, disabled = false, className, children, pressedChildren, onClick, ...rest }) {
|
|
6
|
+
/**
|
|
7
|
+
* The fill pours in on a KEYFRAME, and a keyframe plays as soon as its rule starts matching — so a
|
|
8
|
+
* toggle that mounts already pressed would pour itself in on page load. Arm on the first render where
|
|
9
|
+
* `pressed` actually CHANGES (from the click, or from the parent), and stay armed.
|
|
10
|
+
*/
|
|
11
|
+
const [armed, setArmed] = useState(false);
|
|
12
|
+
const [seen, setSeen] = useState(pressed);
|
|
13
|
+
if (seen !== pressed) {
|
|
14
|
+
setSeen(pressed);
|
|
15
|
+
if (!armed)
|
|
16
|
+
setArmed(true);
|
|
17
|
+
}
|
|
18
|
+
return (_jsxs("button", { type: "button", className: cx('xeno-btn', 'xeno-toggle', className), "data-selection": pressed ? 'on' : 'off', "data-availability": disabled ? 'disabled' : 'enabled', ...(armed ? { 'data-motion': 'ready' } : {}), "aria-pressed": pressed, disabled: disabled, ...sizeAttr(size), onClick: (e) => {
|
|
19
|
+
onClick?.(e);
|
|
20
|
+
if (!e.defaultPrevented)
|
|
21
|
+
onPressedChange?.(!pressed);
|
|
22
|
+
}, ...rest, children: [leadingIcon && (_jsx(XenoElement, { decl: leadingIcon, size: iconPx(size), state: { selection: pressed ? 'on' : 'off' } })), pressedChildren === undefined ? (children) : (_jsxs("span", { className: "xeno-toggle-labels", children: [_jsx("span", { className: "xeno-toggle-label", "data-when": "off", "aria-hidden": pressed || undefined, children: children }), _jsx("span", { className: "xeno-toggle-label", "data-when": "on", "aria-hidden": !pressed || undefined, children: pressedChildren })] }))] }));
|
|
23
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { type ControlSizeToken } from '@xenosystem/elements/tokens';
|
|
2
|
+
export type { ControlSizeToken };
|
|
3
|
+
/**
|
|
4
|
+
* Name the control's size on the element; `size.css` turns that into the four metric variables the
|
|
5
|
+
* control styles read (`--xeno-h/-padx/-gap/-font`).
|
|
6
|
+
*
|
|
7
|
+
* These used to be emitted here as INLINE custom properties. Inline is the one place nothing can
|
|
8
|
+
* override, so a surface — a product rendering the same controls for touch rather than a mouse — had
|
|
9
|
+
* no way to reach them. As an attribute they are ambient: a surface redefines the variables once at
|
|
10
|
+
* the root and every control follows, with nothing changed at any call site.
|
|
11
|
+
*
|
|
12
|
+
* The attribute is namespaced so it cannot collide with a host application's own `data-size`.
|
|
13
|
+
*/
|
|
14
|
+
export declare const sizeAttr: (size: ControlSizeToken) => {
|
|
15
|
+
readonly "data-xeno-size": ControlSizeToken;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* The same metrics as an object, for the rare caller that needs the NUMBERS rather than the styling —
|
|
19
|
+
* a measurement, a canvas, a layout calculation. Not for styling: use {@link sizeAttr}.
|
|
20
|
+
*/
|
|
21
|
+
export declare const sizeMetrics: (size: ControlSizeToken) => {
|
|
22
|
+
readonly height: 24;
|
|
23
|
+
readonly padX: 8;
|
|
24
|
+
readonly gap: 5;
|
|
25
|
+
readonly icon: 15;
|
|
26
|
+
readonly font: 12;
|
|
27
|
+
} | {
|
|
28
|
+
readonly height: 28;
|
|
29
|
+
readonly padX: 10;
|
|
30
|
+
readonly gap: 6;
|
|
31
|
+
readonly icon: 16;
|
|
32
|
+
readonly font: 13;
|
|
33
|
+
} | {
|
|
34
|
+
readonly height: 32;
|
|
35
|
+
readonly padX: 12;
|
|
36
|
+
readonly gap: 6;
|
|
37
|
+
readonly icon: 16;
|
|
38
|
+
readonly font: 14;
|
|
39
|
+
} | {
|
|
40
|
+
readonly height: 36;
|
|
41
|
+
readonly padX: 14;
|
|
42
|
+
readonly gap: 7;
|
|
43
|
+
readonly icon: 18;
|
|
44
|
+
readonly font: 14;
|
|
45
|
+
};
|
|
46
|
+
/** Glyph px for a control size — so a button's leading icon scales with the button. */
|
|
47
|
+
export declare const iconPx: (size: ControlSizeToken) => number;
|
|
48
|
+
export declare const cx: (...parts: (string | false | undefined)[]) => string;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { controlSize } from '@xenosystem/elements/tokens';
|
|
2
|
+
/**
|
|
3
|
+
* Name the control's size on the element; `size.css` turns that into the four metric variables the
|
|
4
|
+
* control styles read (`--xeno-h/-padx/-gap/-font`).
|
|
5
|
+
*
|
|
6
|
+
* These used to be emitted here as INLINE custom properties. Inline is the one place nothing can
|
|
7
|
+
* override, so a surface — a product rendering the same controls for touch rather than a mouse — had
|
|
8
|
+
* no way to reach them. As an attribute they are ambient: a surface redefines the variables once at
|
|
9
|
+
* the root and every control follows, with nothing changed at any call site.
|
|
10
|
+
*
|
|
11
|
+
* The attribute is namespaced so it cannot collide with a host application's own `data-size`.
|
|
12
|
+
*/
|
|
13
|
+
export const sizeAttr = (size) => ({
|
|
14
|
+
'data-xeno-size': size,
|
|
15
|
+
});
|
|
16
|
+
/**
|
|
17
|
+
* The same metrics as an object, for the rare caller that needs the NUMBERS rather than the styling —
|
|
18
|
+
* a measurement, a canvas, a layout calculation. Not for styling: use {@link sizeAttr}.
|
|
19
|
+
*/
|
|
20
|
+
export const sizeMetrics = (size) => controlSize[size];
|
|
21
|
+
/** Glyph px for a control size — so a button's leading icon scales with the button. */
|
|
22
|
+
export const iconPx = (size) => controlSize[size].icon;
|
|
23
|
+
export const cx = (...parts) => parts.filter(Boolean).join(' ');
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type ButtonHTMLAttributes, type ReactElement, type ReactNode } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* `<Checkbox>` — a rounded-SQUARE box (never a circle). CSS-first: the `selection` axis drives paint via
|
|
4
|
+
* `data-selection="off|on|mixed"`, matching `aria-checked`. Checked fills with `--xeno-text` and stamps a
|
|
5
|
+
* check glyph in `--xeno-on-accent`; indeterminate stamps a minus glyph. An optional label sits to the
|
|
6
|
+
* right and is part of the button, so clicking the word toggles too. Controlled: owns nothing, reports
|
|
7
|
+
* the next boolean through `onCheckedChange` (a mixed box resolves to `true` on click).
|
|
8
|
+
*/
|
|
9
|
+
export type CheckboxState = boolean | 'mixed';
|
|
10
|
+
export interface CheckboxProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'onChange' | 'children'> {
|
|
11
|
+
/** Tri-state: `true`, `false`, or `'mixed'` (indeterminate). */
|
|
12
|
+
readonly checked: CheckboxState;
|
|
13
|
+
/** Fires with the next boolean value (mixed → true). */
|
|
14
|
+
readonly onCheckedChange?: (checked: boolean) => void;
|
|
15
|
+
/** Optional clickable label rendered to the right of the box. */
|
|
16
|
+
readonly label?: ReactNode;
|
|
17
|
+
}
|
|
18
|
+
export declare function Checkbox({ checked, onCheckedChange, label, disabled, className, onClick, ...rest }: CheckboxProps): ReactElement;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState } from 'react';
|
|
3
|
+
import { XenoElement } from '../XenoElement.js';
|
|
4
|
+
import { cx } from '../controls/util.js';
|
|
5
|
+
import Check from '@xenosystem/elements/elements/check';
|
|
6
|
+
import Minus from '@xenosystem/elements/elements/minus';
|
|
7
|
+
/** Glyph px inside the ~17px box — small enough to breathe within the marker. */
|
|
8
|
+
const GLYPH_PX = 13;
|
|
9
|
+
export function Checkbox({ checked, onCheckedChange, label, disabled = false, className, onClick, ...rest }) {
|
|
10
|
+
const selection = checked === 'mixed' ? 'mixed' : checked ? 'on' : 'off';
|
|
11
|
+
/**
|
|
12
|
+
* The tick DRAWS itself when it appears, and a CSS animation starts the moment its element exists —
|
|
13
|
+
* so a form that mounts with boxes already ticked would draw every one of them on page load. Arm on
|
|
14
|
+
* the first render where `checked` actually changes, and leave it armed.
|
|
15
|
+
*/
|
|
16
|
+
const [armed, setArmed] = useState(false);
|
|
17
|
+
const [seen, setSeen] = useState(checked);
|
|
18
|
+
if (seen !== checked) {
|
|
19
|
+
setSeen(checked);
|
|
20
|
+
if (!armed)
|
|
21
|
+
setArmed(true);
|
|
22
|
+
}
|
|
23
|
+
return (_jsxs("button", { type: "button", role: "checkbox", "aria-checked": checked === 'mixed' ? 'mixed' : checked, className: cx('xeno-checkbox', className), "data-selection": selection, "data-availability": disabled ? 'disabled' : 'enabled', ...(armed ? { 'data-motion': 'ready' } : {}), disabled: disabled, onClick: (e) => {
|
|
24
|
+
onClick?.(e);
|
|
25
|
+
if (!e.defaultPrevented)
|
|
26
|
+
onCheckedChange?.(checked !== true);
|
|
27
|
+
}, ...rest, children: [_jsx("span", { className: "xeno-checkbox-box", "aria-hidden": "true", children: checked === 'mixed' ? (_jsx(XenoElement, { decl: Minus, size: GLYPH_PX })) : checked ? (_jsx(XenoElement, { decl: Check, size: GLYPH_PX })) : null }), label !== undefined && _jsx("span", { className: "xeno-checkbox-label", children: label })] }));
|
|
28
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { ButtonHTMLAttributes, HTMLAttributes, ReactElement, ReactNode } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* `<RadioRow>` — one selectable row in a radio group. A rounded-SQUARE marker (never a circle) holds a
|
|
4
|
+
* smaller inner square that scales in when selected. CSS-first: the `selection` axis (`data-selection`)
|
|
5
|
+
* mirrors `aria-checked`. Usable standalone or, more usually, mapped by {@link RadioGroup}. Controlled:
|
|
6
|
+
* reports its own `value` up through `onSelect`.
|
|
7
|
+
*/
|
|
8
|
+
export interface RadioRowProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'onChange' | 'children' | 'onSelect'> {
|
|
9
|
+
/** The value this row represents. */
|
|
10
|
+
readonly value: string;
|
|
11
|
+
/** Whether this row is the selected one. */
|
|
12
|
+
readonly checked: boolean;
|
|
13
|
+
/** Fires with this row's `value` when chosen. */
|
|
14
|
+
readonly onSelect?: (value: string) => void;
|
|
15
|
+
/** Label rendered to the right of the marker. */
|
|
16
|
+
readonly label?: ReactNode;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* The ref is FORWARDED rather than taken as a plain prop. Accepting `ref` in the props object is React
|
|
20
|
+
* 19 only; on React 18 — which this package's peer range still allows — `createElement` strips it, so
|
|
21
|
+
* the group's `refs.current[i]` would stay null and `focus()` after an arrow key would be a silent
|
|
22
|
+
* no-op: selection would move and focus would not, which is precisely the roving-tabindex contract.
|
|
23
|
+
*/
|
|
24
|
+
export declare const RadioRow: import("react").ForwardRefExoticComponent<RadioRowProps & import("react").RefAttributes<HTMLButtonElement>>;
|
|
25
|
+
/** One choice in a {@link RadioGroup}. */
|
|
26
|
+
export interface RadioOption {
|
|
27
|
+
readonly value: string;
|
|
28
|
+
readonly label: ReactNode;
|
|
29
|
+
readonly disabled?: boolean;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* `<RadioGroup>` — a controlled `role="radiogroup"` that maps `options` to {@link RadioRow}s. Keyboard is
|
|
33
|
+
* hand-rolled to the WAI-ARIA radio pattern: Arrow keys move selection (and focus) to the next/previous
|
|
34
|
+
* enabled option and wrap; Home/End jump to the first/last; disabled options are skipped. Roving
|
|
35
|
+
* tabindex keeps exactly one row in the tab order.
|
|
36
|
+
*/
|
|
37
|
+
export interface RadioGroupProps extends Omit<HTMLAttributes<HTMLDivElement>, 'onChange'> {
|
|
38
|
+
/** The selected value. */
|
|
39
|
+
readonly value: string;
|
|
40
|
+
/** Fires with the newly selected value. */
|
|
41
|
+
readonly onValueChange?: (value: string) => void;
|
|
42
|
+
/** The choices, in order. */
|
|
43
|
+
readonly options: readonly RadioOption[];
|
|
44
|
+
/** Shared group name, forwarded to each row. */
|
|
45
|
+
readonly name: string;
|
|
46
|
+
/** Disable the whole group. */
|
|
47
|
+
readonly disabled?: boolean;
|
|
48
|
+
/** Layout axis. */
|
|
49
|
+
readonly orientation?: 'vertical' | 'horizontal';
|
|
50
|
+
}
|
|
51
|
+
export declare function RadioGroup({ value, onValueChange, options, name, disabled, orientation, className, onKeyDown, ...rest }: RadioGroupProps): ReactElement;
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { forwardRef, useRef, useState } from 'react';
|
|
3
|
+
import { cx } from '../controls/util.js';
|
|
4
|
+
/**
|
|
5
|
+
* The ref is FORWARDED rather than taken as a plain prop. Accepting `ref` in the props object is React
|
|
6
|
+
* 19 only; on React 18 — which this package's peer range still allows — `createElement` strips it, so
|
|
7
|
+
* the group's `refs.current[i]` would stay null and `focus()` after an arrow key would be a silent
|
|
8
|
+
* no-op: selection would move and focus would not, which is precisely the roving-tabindex contract.
|
|
9
|
+
*/
|
|
10
|
+
export const RadioRow = forwardRef(function RadioRow({ value, checked, onSelect, label, disabled = false, className, onClick, ...rest }, ref) {
|
|
11
|
+
return (_jsxs("button", { type: "button", role: "radio", "aria-checked": checked, ref: ref, className: cx('xeno-radio', className), "data-selection": checked ? 'on' : 'off', "data-availability": disabled ? 'disabled' : 'enabled', disabled: disabled, onClick: (e) => {
|
|
12
|
+
onClick?.(e);
|
|
13
|
+
if (!e.defaultPrevented)
|
|
14
|
+
onSelect?.(value);
|
|
15
|
+
}, ...rest, children: [_jsx("span", { className: "xeno-radio-marker", "aria-hidden": "true", children: _jsx("span", { className: "xeno-radio-dot" }) }), label !== undefined && _jsx("span", { className: "xeno-radio-label", children: label })] }));
|
|
16
|
+
});
|
|
17
|
+
export function RadioGroup({ value, onValueChange, options, name, disabled = false, orientation = 'vertical', className, onKeyDown, ...rest }) {
|
|
18
|
+
const refs = useRef([]);
|
|
19
|
+
const select = (v) => onValueChange?.(v);
|
|
20
|
+
// First enabled index reached by stepping `dir` from `start` (exclusive), wrapping; -1 if none.
|
|
21
|
+
const nextEnabled = (start, dir) => {
|
|
22
|
+
const n = options.length;
|
|
23
|
+
for (let step = 1; step <= n; step++) {
|
|
24
|
+
const j = (((start + dir * step) % n) + n) % n;
|
|
25
|
+
const opt = options[j];
|
|
26
|
+
if (opt && opt.disabled !== true)
|
|
27
|
+
return j;
|
|
28
|
+
}
|
|
29
|
+
return -1;
|
|
30
|
+
};
|
|
31
|
+
const handleKeyDown = (e) => {
|
|
32
|
+
onKeyDown?.(e);
|
|
33
|
+
if (e.defaultPrevented || disabled || options.length === 0)
|
|
34
|
+
return;
|
|
35
|
+
const curr = options.findIndex((o) => o.value === value);
|
|
36
|
+
let target = -1;
|
|
37
|
+
switch (e.key) {
|
|
38
|
+
case 'ArrowDown':
|
|
39
|
+
case 'ArrowRight':
|
|
40
|
+
target = nextEnabled(curr < 0 ? -1 : curr, 1);
|
|
41
|
+
break;
|
|
42
|
+
case 'ArrowUp':
|
|
43
|
+
case 'ArrowLeft':
|
|
44
|
+
target = nextEnabled(curr < 0 ? 0 : curr, -1);
|
|
45
|
+
break;
|
|
46
|
+
case 'Home':
|
|
47
|
+
target = nextEnabled(-1, 1);
|
|
48
|
+
break;
|
|
49
|
+
case 'End':
|
|
50
|
+
target = nextEnabled(0, -1);
|
|
51
|
+
break;
|
|
52
|
+
default:
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
e.preventDefault();
|
|
56
|
+
const opt = options[target];
|
|
57
|
+
if (!opt)
|
|
58
|
+
return;
|
|
59
|
+
select(opt.value);
|
|
60
|
+
refs.current[target]?.focus();
|
|
61
|
+
};
|
|
62
|
+
// Roving tabindex: the selected row is tabbable; if nothing is selected, the first enabled row is.
|
|
63
|
+
const selectedIdx = options.findIndex((o) => o.value === value);
|
|
64
|
+
const firstEnabled = disabled ? -1 : options.findIndex((o) => o.disabled !== true);
|
|
65
|
+
const rovingIdx = selectedIdx >= 0 ? selectedIdx : firstEnabled;
|
|
66
|
+
/**
|
|
67
|
+
* The mark stamps itself in on a keyframe, which plays as soon as its rule matches — so a group that
|
|
68
|
+
* mounts with a choice already made would stamp it on page load. Arm on the first render where
|
|
69
|
+
* `value` genuinely changes. The flag lives on the GROUP rather than the row, which is only safe
|
|
70
|
+
* because exactly one radio can be on: the sole rule that starts matching when the group arms belongs
|
|
71
|
+
* to the row that just changed.
|
|
72
|
+
*/
|
|
73
|
+
const [armed, setArmed] = useState(false);
|
|
74
|
+
const [seen, setSeen] = useState(value);
|
|
75
|
+
if (seen !== value) {
|
|
76
|
+
setSeen(value);
|
|
77
|
+
if (!armed)
|
|
78
|
+
setArmed(true);
|
|
79
|
+
}
|
|
80
|
+
return (_jsx("div", { role: "radiogroup", "aria-disabled": disabled || undefined, "data-orientation": orientation, "data-availability": disabled ? 'disabled' : 'enabled', ...(armed ? { 'data-motion': 'ready' } : {}), className: cx('xeno-radiogroup', className), onKeyDown: handleKeyDown, ...rest, children: options.map((opt, i) => (_jsx(RadioRow, { value: opt.value, checked: opt.value === value, onSelect: select, label: opt.label, disabled: disabled || opt.disabled === true, name: name, tabIndex: i === rovingIdx ? 0 : -1, ref: (el) => {
|
|
81
|
+
refs.current[i] = el;
|
|
82
|
+
} }, opt.value))) }));
|
|
83
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@xenosystem/elements-react` — the XENO web renderer (React + SVG).
|
|
3
|
+
*
|
|
4
|
+
* - {@link XenoElement} renders any element DECLARATION (icons + stateful glyphs) from data.
|
|
5
|
+
* - Tier-1 CONTROLS (Button, IconButton, ToggleButton, Switch, TextInput, Textarea) are the first
|
|
6
|
+
* non-icon elements — styled from the design tokens, CSS-first, behaviour hand-rolled (Base UI later).
|
|
7
|
+
* - Tier-2 ELEMENTS (containers, overlays, forms, content, nav, layout, status) compose the controls
|
|
8
|
+
* and the renderer into the surfaces a chat/agent product needs.
|
|
9
|
+
*
|
|
10
|
+
* Import the styles once:
|
|
11
|
+
* `@xenosystem/elements-react/xeno-elements.css` (theme tokens + element + control + every element style)
|
|
12
|
+
* or à la carte:
|
|
13
|
+
* `@xenosystem/elements-react/xeno-theme.css` (tokens as CSS vars; scope with a `.xeno` element)
|
|
14
|
+
* `@xenosystem/elements-react/controls.css` (control styles)
|
|
15
|
+
*
|
|
16
|
+
* Glyphs are DATA: import each per-id from `@xenosystem/elements/elements/<id>`. No barrel.
|
|
17
|
+
*
|
|
18
|
+
* @module
|
|
19
|
+
*/
|
|
20
|
+
export { XenoElement, type XenoElementProps } from './XenoElement.js';
|
|
21
|
+
export { useDialog, type UseDialogOptions, type UseDialogResult } from './useDialog.js';
|
|
22
|
+
export { useTabs, type UseTabsOptions, type UseTabsResult } from './useTabs.js';
|
|
23
|
+
export { useMenu, type UseMenuOptions, type UseMenuResult } from './useMenu.js';
|
|
24
|
+
export { useGooPill, type UseGooPillOptions, type UseGooPillResult, } from './useGooPill.js';
|
|
25
|
+
export { Button, type ButtonProps, type ButtonVariant } from './controls/Button.js';
|
|
26
|
+
export { IconButton, type IconButtonProps } from './controls/IconButton.js';
|
|
27
|
+
export { ConfirmButton, type ConfirmButtonProps } from './controls/ConfirmButton.js';
|
|
28
|
+
export { ToggleButton, type ToggleButtonProps } from './controls/ToggleButton.js';
|
|
29
|
+
export { Switch, type SwitchProps } from './controls/Switch.js';
|
|
30
|
+
export { TextInput, type TextInputProps } from './controls/TextInput.js';
|
|
31
|
+
export { Textarea, type TextareaProps } from './controls/Textarea.js';
|
|
32
|
+
export type { ControlSizeToken } from './controls/util.js';
|
|
33
|
+
export { Card, type CardProps, type CardVariant } from './containers/Card.js';
|
|
34
|
+
export { Panel, type PanelProps } from './containers/Panel.js';
|
|
35
|
+
export { Chip, type ChipProps, type ChipSize } from './containers/Chip.js';
|
|
36
|
+
export { Tile, type TileProps } from './containers/Tile.js';
|
|
37
|
+
export { MessageBubble, type MessageBubbleProps, type MessageRole } from './containers/MessageBubble.js';
|
|
38
|
+
export { Badge, type BadgeProps } from './containers/Badges.js';
|
|
39
|
+
export { StatusPill, type StatusPillProps, type StatusTone } from './containers/Badges.js';
|
|
40
|
+
export { CountBadge, type CountBadgeProps } from './containers/Badges.js';
|
|
41
|
+
export { CitationBadge, type CitationBadgeProps } from './containers/Badges.js';
|
|
42
|
+
export { Avatar, type AvatarProps } from './containers/Avatar.js';
|
|
43
|
+
export { AvatarStack, type AvatarStackProps, type AvatarStackItem } from './containers/Avatar.js';
|
|
44
|
+
export { ListRow, type ListRowProps } from './containers/ListRow.js';
|
|
45
|
+
export { Table, type TableProps, THead, type THeadProps, TBody, type TBodyProps, Tr, type TrProps, Th, type ThProps, Td, type TdProps, type ColumnAlign, } from './containers/Table.js';
|
|
46
|
+
export { DataTable, type DataTableProps, type DataTableColumn } from './containers/DataTable.js';
|
|
47
|
+
export { Popover, type PopoverProps } from './overlays/Popover.js';
|
|
48
|
+
export { Menu, type MenuProps } from './overlays/Menu.js';
|
|
49
|
+
export { MenuItem, type MenuItemProps, type MenuItemVariant } from './overlays/MenuItem.js';
|
|
50
|
+
export { Modal, Sheet, type ModalProps, type SheetProps, type ModalVariant } from './overlays/Modal.js';
|
|
51
|
+
export { Tabs, type TabsProps, type TabItem } from './overlays/Tabs.js';
|
|
52
|
+
export { SegmentedControl, type SegmentedControlProps, type SegmentedOption } from './overlays/SegmentedControl.js';
|
|
53
|
+
export { PillFilter, type PillFilterProps, type PillOption } from './overlays/PillFilter.js';
|
|
54
|
+
export { Tooltip, type TooltipProps, type TooltipSide } from './overlays/Tooltip.js';
|
|
55
|
+
export { PickerField, type PickerFieldProps } from './overlays/PickerField.js';
|
|
56
|
+
export { Reveal, type RevealProps } from './overlays/Reveal.js';
|
|
57
|
+
export { DatePicker, type DatePickerProps, TimePicker, type TimePickerProps } from './overlays/DateTimePicker.js';
|
|
58
|
+
export type { DateParts, MonthParts, TimeValue, Meridiem } from './overlays/DateTimePicker.js';
|
|
59
|
+
export { Checkbox, type CheckboxProps, type CheckboxState } from './forms/Checkbox.js';
|
|
60
|
+
export { RadioGroup, type RadioGroupProps, RadioRow, type RadioRowProps, type RadioOption } from './forms/RadioGroup.js';
|
|
61
|
+
export { CodeBlock, type CodeBlockProps, type CodeBlockOutput, type CodeBlockOutputStatus, } from './content/CodeBlock.js';
|
|
62
|
+
export { SourceCard, type SourceCardProps } from './content/SourceCard.js';
|
|
63
|
+
export { SourcesDisclosure, type SourcesDisclosureProps, type SourceRef } from './content/SourcesDisclosure.js';
|
|
64
|
+
export { ModelPicker, type ModelPickerProps, type ModelOption, type ModelPickerLayout } from './content/ModelPicker.js';
|
|
65
|
+
export { InlineCode, type InlineCodeProps } from './content/InlineCode.js';
|
|
66
|
+
export { Callout, type CalloutProps, type CalloutTone } from './content/Callout.js';
|
|
67
|
+
export { Collapsible, type CollapsibleProps } from './content/Collapsible.js';
|
|
68
|
+
export { Caret, type CaretProps } from './content/Caret.js';
|
|
69
|
+
export { Sidebar, type SidebarProps, type SidebarItem, type SidebarSection } from './nav/Sidebar.js';
|
|
70
|
+
export { ResizablePanel, type ResizablePanelProps, type ResizablePanelSide } from './layout/ResizablePanel.js';
|
|
71
|
+
export { ThinkingCube, type ThinkingCubeProps, type ThinkingCubeState } from './status/ThinkingCube.js';
|
|
72
|
+
export { Spinner, type SpinnerProps } from './status/Spinner.js';
|
|
73
|
+
export { ProgressBar, type ProgressBarProps } from './status/ProgressBar.js';
|
|
74
|
+
export { StepTimeline, type StepTimelineProps, type Step, type StepStatus } from './status/StepTimeline.js';
|
|
75
|
+
export { StatusIndicator, type StatusIndicatorProps, type StatusIndicatorTone } from './status/StatusIndicator.js';
|