@flood-md/react 0.2.4 → 0.2.5

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/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { type ButtonHTMLAttributes, type InputHTMLAttributes, type TextareaHTMLAttributes, type SelectHTMLAttributes, type AnchorHTMLAttributes, type ReactNode, type HTMLAttributes, type CSSProperties, type LabelHTMLAttributes, type FieldsetHTMLAttributes, type RefCallback, type RefObject, type TableHTMLAttributes, type ImgHTMLAttributes } from "react";
1
+ import { type ButtonHTMLAttributes, type InputHTMLAttributes, type TextareaHTMLAttributes, type SelectHTMLAttributes, type AnchorHTMLAttributes, type ReactNode, type HTMLAttributes, type CSSProperties, type LabelHTMLAttributes, type FieldsetHTMLAttributes, type RefCallback, type RefObject, type TableHTMLAttributes, type ImgHTMLAttributes, type BlockquoteHTMLAttributes } from "react";
2
2
  export type ControlSize = "2xs" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl";
3
3
  export interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
4
4
  variant?: "solid" | "subtle" | "outline" | "ghost";
@@ -8,6 +8,16 @@ export interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
8
8
  export declare const Button: import("react").ForwardRefExoticComponent<ButtonProps & import("react").RefAttributes<HTMLButtonElement>>;
9
9
  export type FieldStatus = "error" | "warning" | "success" | "info";
10
10
  export type ContentSize = "sm" | "md" | "lg";
11
+ export interface TagProps extends HTMLAttributes<HTMLSpanElement> {
12
+ size?: ContentSize;
13
+ icon?: ReactNode;
14
+ disabled?: boolean;
15
+ onRemove?: () => void;
16
+ removeLabel?: string;
17
+ removeButtonProps?: Omit<ButtonHTMLAttributes<HTMLButtonElement>, "children" | "type" | "disabled" | "onClick" | "aria-label">;
18
+ }
19
+ /** @since 0.2.5 */
20
+ export declare const Tag: import("react").ForwardRefExoticComponent<TagProps & import("react").RefAttributes<HTMLSpanElement>>;
11
21
  export interface KbdProps extends HTMLAttributes<HTMLElement> {
12
22
  size?: ContentSize;
13
23
  }
@@ -216,6 +226,21 @@ export interface DialogProps extends Omit<HTMLAttributes<HTMLDialogElement>, "ch
216
226
  initialFocusRef?: RefObject<HTMLElement | null>;
217
227
  }
218
228
  export declare const Dialog: import("react").ForwardRefExoticComponent<DialogProps & import("react").RefAttributes<HTMLDialogElement>>;
229
+ export interface DrawerProps extends DialogProps {
230
+ side?: "start" | "end" | "top" | "bottom";
231
+ size?: "sm" | "md" | "lg";
232
+ footer?: ReactNode;
233
+ }
234
+ export declare const Drawer: import("react").ForwardRefExoticComponent<DrawerProps & import("react").RefAttributes<HTMLDialogElement>>;
235
+ export interface AlertDialogProps extends Omit<DialogProps, "children" | "role" | "description" | "closeLabel" | "closeOnOutsideClick" | "initialFocusRef"> {
236
+ description: string;
237
+ confirmLabel?: string;
238
+ cancelLabel?: string;
239
+ confirmDisabled?: boolean;
240
+ onConfirm: () => void;
241
+ onCancel?: () => void;
242
+ }
243
+ export declare const AlertDialog: import("react").ForwardRefExoticComponent<AlertDialogProps & import("react").RefAttributes<HTMLDialogElement>>;
219
244
  export interface CollapsibleProps extends Omit<HTMLAttributes<HTMLDivElement>, "title" | "onChange"> {
220
245
  title: string;
221
246
  open?: boolean;
@@ -292,6 +317,83 @@ export interface InputGroupProps extends Omit<InputProps, "children" | "type"> {
292
317
  }
293
318
  /** One real Input with host-owned logical start/end adornments. Ref and native attributes target the input. */
294
319
  export declare const InputGroup: import("react").ForwardRefExoticComponent<InputGroupProps & import("react").RefAttributes<HTMLInputElement>>;
320
+ export interface FileInputProps extends Omit<InputProps, "type" | "value" | "defaultValue" | "children" | "readOnly"> {
321
+ clearable?: boolean;
322
+ clearLabel?: string;
323
+ selectionLabel?: string;
324
+ removeFileLabel?: string;
325
+ onFilesChange?: (files: readonly File[]) => void;
326
+ }
327
+ export declare const FileInput: import("react").ForwardRefExoticComponent<FileInputProps & import("react").RefAttributes<HTMLInputElement>>;
328
+ export interface SearchInputProps extends Omit<InputProps, "type" | "children"> {
329
+ clearable?: boolean;
330
+ clearLabel?: string;
331
+ }
332
+ export declare const SearchInput: import("react").ForwardRefExoticComponent<SearchInputProps & import("react").RefAttributes<HTMLInputElement>>;
333
+ export interface PasswordInputProps extends Omit<InputProps, "type" | "children"> {
334
+ visible?: boolean;
335
+ defaultVisible?: boolean;
336
+ onVisibleChange?: (visible: boolean) => void;
337
+ showPasswordLabel?: string;
338
+ hidePasswordLabel?: string;
339
+ }
340
+ export declare const PasswordInput: import("react").ForwardRefExoticComponent<PasswordInputProps & import("react").RefAttributes<HTMLInputElement>>;
341
+ export interface ComboboxOption {
342
+ value: string;
343
+ label: string;
344
+ description?: string;
345
+ keywords?: readonly string[];
346
+ disabled?: boolean;
347
+ }
348
+ export interface ComboboxProps extends Omit<InputProps, "type" | "value" | "defaultValue" | "onChange" | "children"> {
349
+ options: readonly ComboboxOption[];
350
+ value?: string;
351
+ defaultValue?: string;
352
+ onValueChange?: (value: string) => void;
353
+ clearable?: boolean;
354
+ emptyMessage?: string;
355
+ listLabel?: string;
356
+ toggleLabel?: string;
357
+ clearLabel?: string;
358
+ invalidSelectionMessage?: string;
359
+ }
360
+ /** @since 0.2.5 */
361
+ export declare const Combobox: import("react").ForwardRefExoticComponent<ComboboxProps & import("react").RefAttributes<HTMLInputElement>>;
362
+ export interface MultiSelectProps extends Omit<ComboboxProps, "value" | "defaultValue" | "onValueChange"> {
363
+ value?: readonly string[];
364
+ defaultValue?: readonly string[];
365
+ onValueChange?: (value: string[]) => void;
366
+ removeItemLabel?: string;
367
+ }
368
+ /** @since 0.2.5 */
369
+ export declare const MultiSelect: import("react").ForwardRefExoticComponent<MultiSelectProps & import("react").RefAttributes<HTMLInputElement>>;
370
+ export interface NumberInputProps extends Omit<InputProps, "type" | "value" | "defaultValue" | "onChange" | "min" | "max" | "step" | "children"> {
371
+ value?: number | null;
372
+ defaultValue?: number | null;
373
+ onValueChange?: (value: number | null) => void;
374
+ min?: number;
375
+ max?: number;
376
+ step?: number;
377
+ decreaseLabel?: string;
378
+ increaseLabel?: string;
379
+ }
380
+ /** @since 0.2.5 */
381
+ export declare const NumberInput: import("react").ForwardRefExoticComponent<NumberInputProps & import("react").RefAttributes<HTMLInputElement>>;
382
+ export interface SliderProps extends Omit<FieldsetProps, "legend" | "children" | "defaultValue" | "onChange"> {
383
+ label: string;
384
+ value?: readonly number[];
385
+ defaultValue?: readonly number[];
386
+ onValueChange?: (value: number[]) => void;
387
+ min?: number;
388
+ max?: number;
389
+ step?: number;
390
+ thumbLabels?: readonly string[];
391
+ showValue?: boolean;
392
+ readOnly?: boolean;
393
+ controlSize?: "sm" | "md" | "lg" | "xl";
394
+ }
395
+ /** @since 0.2.5 */
396
+ export declare const Slider: import("react").ForwardRefExoticComponent<SliderProps & import("react").RefAttributes<HTMLFieldSetElement>>;
295
397
  export interface TextareaProps extends TextareaHTMLAttributes<HTMLTextAreaElement> {
296
398
  status?: FieldStatus;
297
399
  invalid?: boolean;
@@ -500,3 +602,223 @@ export interface ScrollAreaProps extends HTMLAttributes<HTMLDivElement> {
500
602
  }
501
603
  /** Native scrolling with inset overlay tracks; the ref targets the scrollable viewport. */
502
604
  export declare const ScrollArea: import("react").ForwardRefExoticComponent<ScrollAreaProps & import("react").RefAttributes<HTMLDivElement>>;
605
+ export interface CopyButtonProps extends Omit<ButtonProps, "children" | "value" | "type" | "onClick" | "loading"> {
606
+ value: string;
607
+ copyLabel?: string;
608
+ copiedLabel?: string;
609
+ errorLabel?: string;
610
+ resetDelay?: number;
611
+ onCopied?: () => void;
612
+ onCopyError?: (error: unknown) => void;
613
+ }
614
+ export declare const CopyButton: import("react").ForwardRefExoticComponent<CopyButtonProps & import("react").RefAttributes<HTMLButtonElement>>;
615
+ export interface ToastItem {
616
+ id: string;
617
+ title: string;
618
+ description?: string;
619
+ status?: FieldStatus | "neutral";
620
+ duration?: number;
621
+ action?: {
622
+ label: string;
623
+ onClick: () => void;
624
+ };
625
+ }
626
+ export interface ToastRegionProps extends Omit<HTMLAttributes<HTMLDivElement>, "children" | "role"> {
627
+ items: readonly ToastItem[];
628
+ onDismiss: (id: string) => void;
629
+ label?: string;
630
+ closeLabel?: string;
631
+ placement?: "top-start" | "top-end" | "bottom-start" | "bottom-end";
632
+ limit?: number;
633
+ inline?: boolean;
634
+ hotkey?: boolean;
635
+ }
636
+ export declare const ToastRegion: import("react").ForwardRefExoticComponent<ToastRegionProps & import("react").RefAttributes<HTMLDivElement>>;
637
+ export interface AvatarGroupItem {
638
+ id: string;
639
+ name: string;
640
+ src?: string;
641
+ fallback?: string;
642
+ }
643
+ export interface AvatarGroupProps extends Omit<HTMLAttributes<HTMLUListElement>, "children"> {
644
+ items: readonly AvatarGroupItem[];
645
+ label: string;
646
+ max?: number;
647
+ size?: ContentSize;
648
+ overflowLabel?: string;
649
+ }
650
+ export declare const AvatarGroup: import("react").ForwardRefExoticComponent<AvatarGroupProps & import("react").RefAttributes<HTMLUListElement>>;
651
+ export interface StatusIndicatorProps extends Omit<HTMLAttributes<HTMLSpanElement>, "children"> {
652
+ label: string;
653
+ tone?: SemanticTone;
654
+ size?: ContentSize;
655
+ announce?: boolean;
656
+ }
657
+ export declare const StatusIndicator: import("react").ForwardRefExoticComponent<StatusIndicatorProps & import("react").RefAttributes<HTMLSpanElement>>;
658
+ export interface FigureProps extends HTMLAttributes<HTMLElement> {
659
+ caption?: ReactNode;
660
+ captionPosition?: "before" | "after";
661
+ }
662
+ export declare const Figure: import("react").ForwardRefExoticComponent<FigureProps & import("react").RefAttributes<HTMLElement>>;
663
+ export interface BlockquoteProps extends BlockquoteHTMLAttributes<HTMLQuoteElement> {
664
+ attribution?: ReactNode;
665
+ }
666
+ export declare const Blockquote: import("react").ForwardRefExoticComponent<BlockquoteProps & import("react").RefAttributes<HTMLQuoteElement>>;
667
+ export interface InlineCodeProps extends HTMLAttributes<HTMLElement> {
668
+ size?: ContentSize;
669
+ wrap?: boolean;
670
+ }
671
+ export declare const InlineCode: import("react").ForwardRefExoticComponent<InlineCodeProps & import("react").RefAttributes<HTMLElement>>;
672
+ export interface MetricTrend {
673
+ label: string;
674
+ direction: "up" | "down" | "flat";
675
+ tone?: SemanticTone;
676
+ }
677
+ export interface MetricProps extends Omit<HTMLAttributes<HTMLDListElement>, "children"> {
678
+ label: string;
679
+ value: ReactNode;
680
+ hint?: ReactNode;
681
+ trend?: MetricTrend;
682
+ size?: ContentSize;
683
+ }
684
+ export declare const Metric: import("react").ForwardRefExoticComponent<MetricProps & import("react").RefAttributes<HTMLDListElement>>;
685
+ export interface TimelineItem {
686
+ id: string;
687
+ title: string;
688
+ description?: ReactNode;
689
+ state?: "complete" | "current" | "upcoming";
690
+ dateTime?: string;
691
+ timeLabel?: string;
692
+ icon?: ReactNode;
693
+ }
694
+ export interface TimelineProps extends Omit<HTMLAttributes<HTMLOListElement>, "children"> {
695
+ label: string;
696
+ items: readonly TimelineItem[];
697
+ stateLabels?: {
698
+ complete?: string;
699
+ current?: string;
700
+ upcoming?: string;
701
+ };
702
+ }
703
+ export declare const Timeline: import("react").ForwardRefExoticComponent<TimelineProps & import("react").RefAttributes<HTMLOListElement>>;
704
+ export interface NavigationListItem {
705
+ value: string;
706
+ label: string;
707
+ href: string;
708
+ description?: string;
709
+ icon?: ReactNode;
710
+ group?: string;
711
+ linkProps?: Omit<AnchorHTMLAttributes<HTMLAnchorElement>, "href" | "children" | "aria-current">;
712
+ }
713
+ export interface NavigationListProps extends Omit<HTMLAttributes<HTMLElement>, "children" | "role" | "aria-label"> {
714
+ label: string;
715
+ items: readonly NavigationListItem[];
716
+ currentValue?: string;
717
+ size?: ContentSize;
718
+ }
719
+ export declare const NavigationList: import("react").ForwardRefExoticComponent<NavigationListProps & import("react").RefAttributes<HTMLElement>>;
720
+ export interface StepItem {
721
+ value: string;
722
+ title: string;
723
+ description?: string;
724
+ status?: "complete" | "upcoming" | "error";
725
+ disabled?: boolean;
726
+ }
727
+ export interface StepsProps extends Omit<HTMLAttributes<HTMLOListElement>, "children" | "role" | "aria-label"> {
728
+ label: string;
729
+ items: readonly StepItem[];
730
+ currentValue?: string;
731
+ orientation?: "horizontal" | "vertical";
732
+ onStepChange?: (value: string) => void;
733
+ statusLabels?: {
734
+ complete: string;
735
+ current: string;
736
+ upcoming: string;
737
+ error: string;
738
+ };
739
+ }
740
+ export declare const Steps: import("react").ForwardRefExoticComponent<StepsProps & import("react").RefAttributes<HTMLOListElement>>;
741
+ export interface SectionProps extends Omit<HTMLAttributes<HTMLElement>, "title"> {
742
+ title: string;
743
+ description?: ReactNode;
744
+ actions?: ReactNode;
745
+ headingLevel?: 2 | 3 | 4 | 5 | 6;
746
+ headingSize?: "display" | "large" | "page" | "section";
747
+ }
748
+ export declare const Section: import("react").ForwardRefExoticComponent<SectionProps & import("react").RefAttributes<HTMLElement>>;
749
+ export interface SplitProps extends Omit<HTMLAttributes<HTMLDivElement>, "children"> {
750
+ main: ReactNode;
751
+ aside: ReactNode;
752
+ side?: "start" | "end";
753
+ ratio?: "balanced" | "main" | "aside";
754
+ collapseAt?: "sm" | "md" | "lg" | "never";
755
+ gap?: Space;
756
+ }
757
+ export declare const Split: import("react").ForwardRefExoticComponent<SplitProps & import("react").RefAttributes<HTMLDivElement>>;
758
+ export interface CenterProps extends HTMLAttributes<HTMLDivElement> {
759
+ inline?: boolean;
760
+ maxWidth?: string;
761
+ minHeight?: string;
762
+ }
763
+ export declare const Center: import("react").ForwardRefExoticComponent<CenterProps & import("react").RefAttributes<HTMLDivElement>>;
764
+ export interface SkipLinkProps extends Omit<AnchorHTMLAttributes<HTMLAnchorElement>, "href"> {
765
+ href: string;
766
+ }
767
+ export declare const SkipLink: import("react").ForwardRefExoticComponent<SkipLinkProps & import("react").RefAttributes<HTMLAnchorElement>>;
768
+ export interface ListBoxProps extends Omit<HTMLAttributes<HTMLDivElement>, "children" | "role" | "defaultValue" | "onChange"> {
769
+ label: string;
770
+ hideLabel?: boolean;
771
+ options: readonly ComboboxOption[];
772
+ value?: string | readonly string[];
773
+ defaultValue?: string | readonly string[];
774
+ onValueChange?: (value: string | string[]) => void;
775
+ multiple?: boolean;
776
+ disabled?: boolean;
777
+ readOnly?: boolean;
778
+ name?: string;
779
+ form?: string;
780
+ controlSize?: "sm" | "md" | "lg" | "xl";
781
+ }
782
+ export declare const ListBox: import("react").ForwardRefExoticComponent<ListBoxProps & import("react").RefAttributes<HTMLDivElement>>;
783
+ export interface PinInputProps extends Omit<InputProps, "type" | "children" | "value" | "defaultValue" | "onChange" | "pattern" | "size"> {
784
+ label: string;
785
+ hideLabel?: boolean;
786
+ length?: number;
787
+ value?: string;
788
+ defaultValue?: string;
789
+ onValueChange?: (value: string) => void;
790
+ mode?: "numeric" | "alphanumeric";
791
+ mask?: boolean;
792
+ }
793
+ export declare const PinInput: import("react").ForwardRefExoticComponent<PinInputProps & import("react").RefAttributes<HTMLInputElement>>;
794
+ export interface RatingProps extends Omit<FieldsetHTMLAttributes<HTMLFieldSetElement>, "children" | "onChange" | "defaultValue"> {
795
+ label: string;
796
+ hideLabel?: boolean;
797
+ value?: number;
798
+ defaultValue?: number;
799
+ max?: number;
800
+ onValueChange?: (value: number) => void;
801
+ getValueLabel?: (value: number, max: number) => string;
802
+ readOnly?: boolean;
803
+ required?: boolean;
804
+ name: string;
805
+ form?: string;
806
+ size?: ContentSize;
807
+ }
808
+ export declare const Rating: import("react").ForwardRefExoticComponent<RatingProps & import("react").RefAttributes<HTMLFieldSetElement>>;
809
+ export interface DropzoneProps extends Omit<FileInputProps, "onDragEnter" | "onDragLeave" | "onDragOver" | "onDrop"> {
810
+ label: string;
811
+ description?: string;
812
+ }
813
+ export declare const Dropzone: import("react").ForwardRefExoticComponent<DropzoneProps & import("react").RefAttributes<HTMLInputElement>>;
814
+ export interface CharacterCountProps extends HTMLAttributes<HTMLOutputElement> {
815
+ value?: string;
816
+ count?: number;
817
+ max?: number;
818
+ mode?: "count" | "remaining";
819
+ label?: string;
820
+ overLimitLabel?: string;
821
+ htmlFor?: string;
822
+ form?: string;
823
+ }
824
+ export declare const CharacterCount: import("react").ForwardRefExoticComponent<CharacterCountProps & import("react").RefAttributes<HTMLOutputElement>>;
package/dist/index.js CHANGED
@@ -15,10 +15,29 @@ import { ValueIndicator, FeedbackMessage } from "./feedback.js";
15
15
  import { DescribedData, TabularData } from "./data-display.js";
16
16
  import { ActionMenu } from "./menu.js";
17
17
  import { RovingToolbar } from "./toolbar.js";
18
+ import { NumericStepper } from "./numeric-input.js";
19
+ import { RangeControl } from "./slider.js";
20
+ import { GroupedAvatars, NamedStatus, CaptionedFigure, AttributedQuote, InlineCodeText, MeasuredValue, EventTimeline } from "./content-elements.js";
21
+ import { NavigationMenu, StepSequence, ContentSection, SplitLayout, CenterLayout, SkipNavigation } from "./navigation-layout.js";
22
+ import { CollectionListBox, SegmentedPinInput, StarRating, FileDropzone, SupportingCharacterCount } from "./form-controls.js";
23
+ import { ClipboardAction, NotificationRegion } from "./feedback-actions.js";
24
+ import { ConfirmationDialog } from "./alert-dialog.js";
25
+ import { FilePicker } from "./file-input.js";
26
+ import { SearchField, PasswordField } from "./text-inputs.js";
27
+ import { SearchSelection } from "./combobox.js";
18
28
  const classes = (...values) => values.filter(Boolean).join(" ");
19
29
  export const Button = forwardRef(function Button({ variant = "solid", size = "md", loading = false, disabled, type = "button", className, children, ...props }, ref) {
20
30
  return (_jsxs("button", { ...props, ref: ref, type: type, disabled: disabled || loading, "aria-busy": loading || undefined, className: classes("flood-button", `flood-button--${variant}`, `flood-button--${size}`, className), children: [loading && _jsx(Spinner, { decorative: true }), children] }));
21
31
  });
32
+ /** @since 0.2.5 */
33
+ export const Tag = forwardRef(function Tag({ size = "md", icon, disabled = false, onRemove, removeLabel, removeButtonProps, className, children, ...props }, ref) {
34
+ const label = removeLabel ?? (typeof children === "string" || typeof children === "number" ? `Remove ${children}` : "");
35
+ if (onRemove && !label.trim())
36
+ throw new Error("Flood Tag removal needs an accessible removeLabel for rich content");
37
+ const iconSize = size === "sm" ? "2xs" : size === "md" ? "xs" : "sm";
38
+ return _jsxs("span", { ...props, ref: ref, className: classes("flood-tag", className), "data-size": size, "data-disabled": disabled || undefined, children: [hasFieldContent(icon) && _jsx(IconSlot, { size: iconSize, children: icon }), _jsx("span", { className: "flood-tag__label", children: children }), onRemove && _jsx(IconButton, { ...removeButtonProps, type: "button", className: classes("flood-tag__remove", removeButtonProps?.className), label: label, variant: "ghost", size: iconSize, disabled: disabled, onClick: () => { if (!disabled)
39
+ onRemove(); }, children: _jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.75", strokeLinecap: "round", "aria-hidden": "true", children: _jsx("path", { d: "m6 6 12 12M18 6 6 18" }) }) })] });
40
+ });
22
41
  /** @since 0.2.4 */
23
42
  export const Kbd = forwardRef(function Kbd({ size = "sm", className, ...props }, ref) {
24
43
  return _jsx("kbd", { ...props, ref: ref, className: classes("flood-kbd", className), "data-size": size });
@@ -74,6 +93,12 @@ export const Menu = forwardRef(function Menu({ defaultOpen = false, disabled = f
74
93
  export const Tooltip = forwardRef(function Tooltip({ side = "top", align = "center", delay = 300, disabled = false, ...props }, ref) { return _jsx(AnchoredOverlay, { ...props, ref: ref, kind: "tooltip", side: side, align: align, delay: delay, disabled: disabled }); });
75
94
  export const Popover = forwardRef(function Popover({ side = "bottom", align = "start", defaultOpen = false, disabled = false, closeLabel = "Close", ...props }, ref) { return _jsx(AnchoredOverlay, { ...props, ref: ref, kind: "popover", side: side, align: align, defaultOpen: defaultOpen, disabled: disabled, closeLabel: closeLabel }); });
76
95
  export const Dialog = forwardRef(function Dialog({ defaultOpen = false, disabled = false, closeLabel = "Close", closeOnOutsideClick = true, ...props }, ref) { return _jsx(ModalOverlay, { ...props, ref: ref, defaultOpen: defaultOpen, disabled: disabled, closeLabel: closeLabel, closeOnOutsideClick: closeOnOutsideClick }); });
96
+ export const Drawer = forwardRef(function Drawer({ side = "end", size = "md", defaultOpen = false, closeLabel = "Close", closeOnOutsideClick = true, className, footer, ...props }, ref) {
97
+ return _jsx(ModalOverlay, { ...props, ref: ref, defaultOpen: defaultOpen, closeLabel: closeLabel, closeOnOutsideClick: closeOnOutsideClick, className: classes("flood-drawer", className), "data-side": side, "data-size": size, scrollBody: true, footer: footer });
98
+ });
99
+ export const AlertDialog = forwardRef(function AlertDialog({ defaultOpen = false, confirmLabel = "Continue", cancelLabel = "Cancel", confirmDisabled = false, ...props }, ref) {
100
+ return _jsx(ConfirmationDialog, { ...props, ref: ref, defaultOpen: defaultOpen, confirmLabel: confirmLabel, cancelLabel: cancelLabel, confirmDisabled: confirmDisabled });
101
+ });
77
102
  export const Collapsible = forwardRef(function Collapsible({ open, defaultOpen = false, onOpenChange, disabled = false, controlSize = "md", ...props }, ref) {
78
103
  const [local, setLocal] = useState(defaultOpen);
79
104
  return _jsx(Disclosure, { ...props, ref: ref, expanded: open ?? local, disabled: disabled, controlSize: controlSize, onExpandedChange: next => {
@@ -166,6 +191,31 @@ export const Input = forwardRef(function Input({ invalid, status, controlSize =
166
191
  export const InputGroup = forwardRef(function InputGroup({ start, end, controlSize = "md", className, style, invalid, status, disabled, readOnly, ...props }, ref) {
167
192
  return _jsxs("div", { hidden: props.hidden, dir: props.dir, lang: props.lang, className: classes("flood-input-group", `flood-control--${controlSize}`, className), style: style, "data-status": resolveFieldStatus(status, invalid, props["aria-invalid"]), "data-disabled": disabled || undefined, "data-readonly": readOnly || undefined, children: [hasFieldContent(start) && _jsx("div", { className: "flood-input-group__addon flood-input-group__addon--start", children: typeof start === "string" ? _jsx("bdi", { dir: "auto", children: start }) : start }), _jsx(Input, { ...props, ref: ref, controlSize: controlSize, invalid: invalid, status: status, disabled: disabled, readOnly: readOnly }), hasFieldContent(end) && _jsx("div", { className: "flood-input-group__addon flood-input-group__addon--end", children: typeof end === "string" ? _jsx("bdi", { dir: "auto", children: end }) : end })] });
168
193
  });
194
+ export const FileInput = forwardRef(function FileInput({ clearable = true, clearLabel = "Clear files", controlSize = "md", ...props }, ref) {
195
+ return _jsx(FilePicker, { ...props, ref: ref, clearable: clearable, clearLabel: clearLabel, controlSize: controlSize, actionComponent: IconButton, iconComponent: IconSlot });
196
+ });
197
+ export const SearchInput = forwardRef(function SearchInput({ clearable = true, clearLabel = "Clear search", controlSize = "md", ...props }, ref) {
198
+ return _jsx(SearchField, { ...props, ref: ref, clearable: clearable, clearLabel: clearLabel, controlSize: controlSize, group: InputGroup, action: IconButton, icon: IconSlot });
199
+ });
200
+ export const PasswordInput = forwardRef(function PasswordInput({ defaultVisible = false, showPasswordLabel = "Show password", hidePasswordLabel = "Hide password", controlSize = "md", ...props }, ref) {
201
+ return _jsx(PasswordField, { ...props, ref: ref, defaultVisible: defaultVisible, showPasswordLabel: showPasswordLabel, hidePasswordLabel: hidePasswordLabel, controlSize: controlSize, group: InputGroup, action: IconButton, icon: IconSlot });
202
+ });
203
+ /** @since 0.2.5 */
204
+ export const Combobox = forwardRef(function Combobox({ value, defaultValue = "", onValueChange, clearable = false, emptyMessage = "No results found.", listLabel = "Options", toggleLabel = "Show options", clearLabel = "Clear selection", invalidSelectionMessage = "Select an option.", controlSize = "md", ...props }, ref) {
205
+ return _jsx(SearchSelection, { ...props, ref: ref, multiple: false, selectedValues: value === undefined ? undefined : value ? [value] : [], initialValues: defaultValue ? [defaultValue] : [], onSelectionChange: next => onValueChange?.(next[0] ?? ""), clearable: clearable, emptyMessage: emptyMessage, listLabel: listLabel, toggleLabel: toggleLabel, clearLabel: clearLabel, invalidSelectionMessage: invalidSelectionMessage, controlSize: controlSize });
206
+ });
207
+ /** @since 0.2.5 */
208
+ export const MultiSelect = forwardRef(function MultiSelect({ value, defaultValue = [], onValueChange, removeItemLabel = "Remove", clearable = false, emptyMessage = "No results found.", listLabel = "Options", toggleLabel = "Show options", clearLabel = "Clear selection", invalidSelectionMessage = "Select at least one option.", controlSize = "md", ...props }, ref) {
209
+ return _jsx(SearchSelection, { ...props, ref: ref, multiple: true, selectedValues: value, initialValues: defaultValue, onSelectionChange: onValueChange, removeItemLabel: removeItemLabel, clearable: clearable, emptyMessage: emptyMessage, listLabel: listLabel, toggleLabel: toggleLabel, clearLabel: clearLabel, invalidSelectionMessage: invalidSelectionMessage, controlSize: controlSize });
210
+ });
211
+ /** @since 0.2.5 */
212
+ export const NumberInput = forwardRef(function NumberInput({ defaultValue = 0, step = 1, controlSize = "md", decreaseLabel = "Decrease value", increaseLabel = "Increase value", ...props }, ref) {
213
+ return _jsx(NumericStepper, { ...props, ref: ref, defaultValue: defaultValue, step: step, controlSize: controlSize, decreaseLabel: decreaseLabel, increaseLabel: increaseLabel, inputComponent: InputGroup, buttonComponent: IconButton });
214
+ });
215
+ /** @since 0.2.5 */
216
+ export const Slider = forwardRef(function Slider({ defaultValue = [50], min = 0, max = 100, step = 1, showValue = true, readOnly = false, controlSize = "md", ...props }, ref) {
217
+ return _jsx(RangeControl, { ...props, ref: ref, defaultValue: defaultValue, min: min, max: max, step: step, showValue: showValue, readOnly: readOnly, controlSize: controlSize, fieldsetComponent: Fieldset });
218
+ });
169
219
  export const Textarea = forwardRef(function Textarea({ invalid, status, controlSize = "md", className, ...props }, ref) {
170
220
  return (_jsx("textarea", { ...props, ref: ref, "data-status": resolveFieldStatus(status, invalid, props["aria-invalid"]), "aria-invalid": invalid || status === "error" || props["aria-invalid"], className: classes("flood-input", "flood-textarea", `flood-control--${controlSize}`, className) }));
171
221
  });
@@ -336,3 +386,31 @@ export const CodeSnippet = forwardRef(function CodeSnippet({ code, codeDirection
336
386
  export const ScrollArea = forwardRef(function ScrollArea({ orientation = "vertical", contentInset = "scrollbar", ...props }, ref) {
337
387
  return _jsx(OverlayScrollArea, { ...props, orientation: orientation, contentInset: contentInset, ref: ref });
338
388
  });
389
+ export const CopyButton = forwardRef(function CopyButton({ copyLabel = "Copy", copiedLabel = "Copied", errorLabel = "Failed", resetDelay = 2000, size = "md", variant = "subtle", ...props }, ref) {
390
+ return _jsx(ClipboardAction, { ...props, ref: ref, copyLabel: copyLabel, copiedLabel: copiedLabel, errorLabel: errorLabel, resetDelay: resetDelay, size: size, variant: variant });
391
+ });
392
+ export const ToastRegion = forwardRef(function ToastRegion({ label = "Notifications", closeLabel = "Dismiss notification", placement = "bottom-end", limit = 3, inline = false, hotkey = true, ...props }, ref) {
393
+ return _jsx(NotificationRegion, { ...props, ref: ref, label: label, closeLabel: closeLabel, placement: placement, limit: limit, inline: inline, hotkey: hotkey });
394
+ });
395
+ export const AvatarGroup = forwardRef(function AvatarGroup({ max = 4, size = "md", ...props }, ref) { return _jsx(GroupedAvatars, { ...props, ref: ref, max: max, size: size }); });
396
+ export const StatusIndicator = forwardRef(function StatusIndicator({ tone = "neutral", size = "md", announce = false, ...props }, ref) { return _jsx(NamedStatus, { ...props, ref: ref, tone: tone, size: size, announce: announce }); });
397
+ export const Figure = forwardRef(function Figure({ captionPosition = "after", ...props }, ref) { return _jsx(CaptionedFigure, { ...props, ref: ref, captionPosition: captionPosition }); });
398
+ export const Blockquote = forwardRef(function Blockquote(props, ref) {
399
+ return _jsx(AttributedQuote, { ...props, ref: ref });
400
+ });
401
+ export const InlineCode = forwardRef(function InlineCode({ size = "md", wrap = true, ...props }, ref) { return _jsx(InlineCodeText, { ...props, ref: ref, size: size, wrap: wrap }); });
402
+ export const Metric = forwardRef(function Metric({ size = "md", ...props }, ref) { return _jsx(MeasuredValue, { ...props, ref: ref, size: size }); });
403
+ export const Timeline = forwardRef(function Timeline(props, ref) {
404
+ return _jsx(EventTimeline, { ...props, ref: ref });
405
+ });
406
+ export const NavigationList = forwardRef(function NavigationList({ size = "md", ...props }, ref) { return _jsx(NavigationMenu, { ...props, ref: ref, size: size }); });
407
+ export const Steps = forwardRef(function Steps({ orientation = "horizontal", ...props }, ref) { return _jsx(StepSequence, { ...props, ref: ref, orientation: orientation }); });
408
+ export const Section = forwardRef(function Section({ headingLevel = 2, headingSize = "section", ...props }, ref) { return _jsx(ContentSection, { ...props, ref: ref, headingLevel: headingLevel, headingSize: headingSize }); });
409
+ export const Split = forwardRef(function Split({ side = "end", ratio = "main", collapseAt = "md", gap = "6", ...props }, ref) { return _jsx(SplitLayout, { ...props, ref: ref, side: side, ratio: ratio, collapseAt: collapseAt, gap: gap }); });
410
+ export const Center = forwardRef(function Center({ inline = false, ...props }, ref) { return _jsx(CenterLayout, { ...props, ref: ref, inline: inline }); });
411
+ export const SkipLink = forwardRef(function SkipLink({ children = "Skip to content", ...props }, ref) { return _jsx(SkipNavigation, { ...props, ref: ref, children: children }); });
412
+ export const ListBox = forwardRef(function ListBox({ multiple = false, disabled = false, readOnly = false, hideLabel = false, controlSize = "md", ...props }, ref) { return _jsx(CollectionListBox, { ...props, ref: ref, multiple: multiple, disabled: disabled, readOnly: readOnly, hideLabel: hideLabel, controlSize: controlSize }); });
413
+ export const PinInput = forwardRef(function PinInput({ length = 6, mode = "numeric", mask = false, hideLabel = false, controlSize = "md", ...props }, ref) { return _jsx(SegmentedPinInput, { ...props, ref: ref, length: length, mode: mode, mask: mask, hideLabel: hideLabel, controlSize: controlSize }); });
414
+ export const Rating = forwardRef(function Rating({ max = 5, defaultValue = 0, hideLabel = false, readOnly = false, size = "md", ...props }, ref) { return _jsx(StarRating, { ...props, ref: ref, max: max, defaultValue: defaultValue, hideLabel: hideLabel, readOnly: readOnly, size: size }); });
415
+ export const Dropzone = forwardRef(function Dropzone({ description = "Drop files here or choose from your device.", multiple = true, ...props }, ref) { return _jsx(FileDropzone, { ...props, ref: ref, description: description, multiple: multiple }); });
416
+ export const CharacterCount = forwardRef(function CharacterCount({ mode = "count", label = "Characters", overLimitLabel = "Over limit", ...props }, ref) { return _jsx(SupportingCharacterCount, { ...props, ref: ref, mode: mode, label: label, overLimitLabel: overLimitLabel }); });
@@ -0,0 +1,7 @@
1
+ import type { NavigationListProps, StepsProps, SectionProps, SplitProps, CenterProps, SkipLinkProps } from "./index.js";
2
+ export declare const NavigationMenu: import("react").ForwardRefExoticComponent<NavigationListProps & import("react").RefAttributes<HTMLElement>>;
3
+ export declare const StepSequence: import("react").ForwardRefExoticComponent<StepsProps & import("react").RefAttributes<HTMLOListElement>>;
4
+ export declare const ContentSection: import("react").ForwardRefExoticComponent<SectionProps & import("react").RefAttributes<HTMLElement>>;
5
+ export declare const SplitLayout: import("react").ForwardRefExoticComponent<SplitProps & import("react").RefAttributes<HTMLDivElement>>;
6
+ export declare const CenterLayout: import("react").ForwardRefExoticComponent<CenterProps & import("react").RefAttributes<HTMLDivElement>>;
7
+ export declare const SkipNavigation: import("react").ForwardRefExoticComponent<SkipLinkProps & import("react").RefAttributes<HTMLAnchorElement>>;
@@ -0,0 +1,77 @@
1
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { forwardRef, useId } from "react";
3
+ import { IconSlot, Heading } from "./index.js";
4
+ const classes = (...names) => names.filter(Boolean).join(" ");
5
+ function uniqueValues(items, component) {
6
+ if (items.some(item => !item.value.trim()) || new Set(items.map(item => item.value)).size !== items.length)
7
+ throw new Error(`Flood ${component} items require unique nonempty values`);
8
+ }
9
+ export const NavigationMenu = forwardRef(function NavigationMenu({ items, label, currentValue, size = "md", className, ...props }, ref) {
10
+ uniqueValues(items, "NavigationList");
11
+ if (!label.trim() || items.some(item => !item.label.trim() || !item.href.trim()))
12
+ throw new Error("Flood NavigationList requires a name and labelled links with destinations");
13
+ const id = useId();
14
+ const groups = [];
15
+ for (const item of items) {
16
+ const previous = groups.at(-1);
17
+ if (previous?.label === (item.group ?? ""))
18
+ previous.items.push(item);
19
+ else
20
+ groups.push({ label: item.group ?? "", items: [item] });
21
+ }
22
+ const links = (entries) => entries.map(item => _jsx("li", { children: _jsxs("a", { ...item.linkProps, href: item.href, "aria-current": item.value === currentValue ? "page" : undefined, className: classes("flood-navigation-list__link", item.linkProps?.className), children: [item.icon != null && _jsx(IconSlot, { size: size, children: item.icon }), _jsxs("span", { className: "flood-navigation-list__text", children: [_jsx("span", { className: "flood-navigation-list__label", children: item.label }), item.description && _jsx("span", { className: "flood-navigation-list__description", children: item.description })] })] }) }, item.value));
23
+ return _jsx("nav", { ...props, ref: ref, "aria-label": label, className: classes("flood-navigation-list", className), "data-size": size, children: _jsx("ul", { role: "list", className: "flood-navigation-list__groups", children: groups.map((group, index) => group.label ? _jsxs("li", { className: "flood-navigation-list__group", children: [_jsx("p", { className: "flood-navigation-list__group-title", id: `${id}-${index}`, children: group.label }), _jsx("ul", { role: "list", "aria-labelledby": `${id}-${index}`, children: links(group.items) })] }, index) : links(group.items)) }) });
24
+ });
25
+ export const StepSequence = forwardRef(function StepSequence({ items, label, currentValue = items[0]?.value, orientation = "horizontal", onStepChange, statusLabels = { complete: "Completed", current: "Current step", upcoming: "Upcoming", error: "Needs attention" }, className, ...props }, ref) {
26
+ uniqueValues(items, "Steps");
27
+ if (!label.trim() || items.some(item => !item.title.trim()))
28
+ throw new Error("Flood Steps requires a sequence name and step titles");
29
+ const currentIndex = items.findIndex(item => item.value === currentValue);
30
+ if (currentValue !== undefined && currentIndex < 0)
31
+ throw new Error("Flood Steps currentValue must identify a step");
32
+ return _jsx("ol", { ...props, ref: ref, role: "list", "aria-label": label, "data-orientation": orientation, className: classes("flood-steps", className), children: items.map((item, index) => {
33
+ const current = index === currentIndex;
34
+ const state = item.status === "error" ? "error" : current ? "current" : item.status ?? (index < currentIndex ? "complete" : "upcoming");
35
+ const content = _jsxs(_Fragment, { children: [_jsx("span", { className: "flood-steps__indicator", "aria-hidden": "true", children: state === "complete" ? _jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: _jsx("path", { d: "m5 12 4 4 10-10" }) }) : state === "error" ? "!" : index + 1 }), _jsxs("span", { className: "flood-steps__text", children: [_jsx("span", { className: "flood-steps__title", children: item.title }), _jsx("span", { className: "flood-visually-hidden", children: statusLabels[state] }), item.description && _jsx("span", { className: "flood-steps__description", children: item.description })] })] });
36
+ return _jsx("li", { "data-state": state, "aria-current": current ? "step" : undefined, children: onStepChange ? _jsx("button", { type: "button", className: "flood-steps__content flood-steps__action", disabled: item.disabled, onClick: () => onStepChange(item.value), children: content }) : _jsx("div", { className: "flood-steps__content", children: content }) }, item.value);
37
+ }) });
38
+ });
39
+ export const ContentSection = forwardRef(function ContentSection({ title, description, actions, headingLevel = 2, headingSize = "section", children, id: explicitId, className, "aria-labelledby": labelledBy, ...props }, ref) {
40
+ if (!title.trim() || ![2, 3, 4, 5, 6].includes(headingLevel))
41
+ throw new Error("Flood Section requires a nonempty title and headingLevel from 2 to 6");
42
+ const generated = useId(), headingId = `${explicitId ?? `flood-section-${generated}`}-title`;
43
+ return _jsxs("section", { ...props, ref: ref, id: explicitId, "aria-labelledby": labelledBy ?? headingId, className: classes("flood-section", className), children: [_jsxs("header", { className: "flood-section__header", children: [_jsxs("div", { className: "flood-section__heading", children: [_jsx(Heading, { id: headingId, level: headingLevel, size: headingSize, className: "flood-section__title", children: title }), description != null && _jsx("div", { className: "flood-section__description", children: description })] }), actions != null && _jsx("div", { className: "flood-section__actions", children: actions })] }), children != null && _jsx("div", { className: "flood-section__body", children: children })] });
44
+ });
45
+ export const SplitLayout = forwardRef(function SplitLayout({ main, aside, side = "end", ratio = "main", collapseAt = "md", gap = "6", className, style, ...props }, ref) {
46
+ const primary = _jsx("div", { className: "flood-split__main", children: main }, "main"), secondary = _jsx("div", { className: "flood-split__aside", children: aside }, "aside");
47
+ return _jsx("div", { ...props, ref: ref, className: classes("flood-split", className), style: { "--flood-layout-gap": `var(--flood-sys-space-${gap})`, ...style }, children: _jsx("div", { className: "flood-split__layout", "data-side": side, "data-ratio": ratio, "data-collapse": collapseAt, children: side === "start" ? [secondary, primary] : [primary, secondary] }) });
48
+ });
49
+ export const CenterLayout = forwardRef(function CenterLayout({ inline = false, maxWidth, minHeight, className, style, children, ...props }, ref) {
50
+ return _jsx("div", { ...props, ref: ref, className: classes("flood-center", className), "data-inline": inline || undefined, style: { minBlockSize: minHeight, "--flood-center-max": maxWidth, ...style }, children: _jsx("div", { className: "flood-center__content", children: children }) });
51
+ });
52
+ export const SkipNavigation = forwardRef(function SkipNavigation({ children = "Skip to content", className, onClick, href, ...props }, ref) {
53
+ if (!href.startsWith("#") || href.length < 2)
54
+ throw new Error("Flood SkipLink requires a nonempty same-page fragment href");
55
+ return _jsx("a", { ...props, ref: ref, href: href, className: classes("flood-skip-link", className), onClick: event => {
56
+ onClick?.(event);
57
+ if (event.defaultPrevented || event.button !== 0 || event.metaKey || event.ctrlKey || event.altKey || event.shiftKey || (props.target && props.target !== "_self"))
58
+ return;
59
+ const document = event.currentTarget.ownerDocument, view = document.defaultView;
60
+ let id;
61
+ try {
62
+ id = decodeURIComponent(href.slice(1));
63
+ }
64
+ catch {
65
+ return;
66
+ }
67
+ const target = document.getElementById(id);
68
+ if (!target || !view)
69
+ return;
70
+ view.requestAnimationFrame(() => {
71
+ if (!target.isConnected)
72
+ return;
73
+ target.focus({ preventScroll: true });
74
+ target.scrollIntoView({ block: "start", behavior: view.matchMedia("(prefers-reduced-motion: reduce)").matches ? "instant" : "auto" });
75
+ });
76
+ }, children: children });
77
+ });
@@ -0,0 +1,8 @@
1
+ import type { NumberInputProps, InputGroup, IconButton } from "./index.js";
2
+ interface Props extends NumberInputProps {
3
+ inputComponent: typeof InputGroup;
4
+ buttonComponent: typeof IconButton;
5
+ }
6
+ /** The browser owns decimal stepping, validity, editing and form submission. */
7
+ export declare const NumericStepper: import("react").ForwardRefExoticComponent<Props & import("react").RefAttributes<HTMLInputElement>>;
8
+ export {};
@@ -0,0 +1,68 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { forwardRef, useEffect, useImperativeHandle, useRef, useState } from "react";
3
+ /** The browser owns decimal stepping, validity, editing and form submission. */
4
+ export const NumericStepper = forwardRef(function NumericStepper({ inputComponent: Group, buttonComponent: Action, value, defaultValue = 0, onValueChange, min, max, step = 1, disabled, readOnly, controlSize = "md", decreaseLabel = "Decrease value", increaseLabel = "Increase value", className, onBlur, onKeyDown, ...props }, ref) {
5
+ if (!Number.isFinite(step) || step <= 0 || (min !== undefined && !Number.isFinite(min)) || (max !== undefined && !Number.isFinite(max)) || (min !== undefined && max !== undefined && min > max))
6
+ throw new Error("Flood NumberInput requires finite bounds and a positive step");
7
+ for (const number of [value, defaultValue])
8
+ if (number !== undefined && number !== null && !Number.isFinite(number))
9
+ throw new Error("Flood NumberInput value must be finite or null");
10
+ if (!decreaseLabel.trim() || !increaseLabel.trim())
11
+ throw new Error("Flood NumberInput step actions require accessible names");
12
+ const input = useRef(null);
13
+ useImperativeHandle(ref, () => input.current, []);
14
+ const initial = useRef(defaultValue === null ? "" : String(defaultValue));
15
+ const [local, setLocal] = useState(initial.current);
16
+ const [, refresh] = useState(0);
17
+ const current = value === undefined ? local : value === null ? "" : String(value);
18
+ const number = current === "" ? null : Number(current);
19
+ const publish = (text) => {
20
+ setLocal(text);
21
+ refresh(revision => revision + 1);
22
+ onValueChange?.(text === "" ? null : Number(text));
23
+ };
24
+ useEffect(() => {
25
+ const form = input.current?.form;
26
+ if (!form || value !== undefined)
27
+ return;
28
+ const reset = (event) => queueMicrotask(() => { if (!event.defaultPrevented)
29
+ setLocal(initial.current); });
30
+ form.addEventListener("reset", reset);
31
+ return () => form.removeEventListener("reset", reset);
32
+ }, [value, props.form]);
33
+ const move = (direction) => {
34
+ const node = input.current;
35
+ if (!node || disabled || readOnly || node.matches(":disabled"))
36
+ return;
37
+ const before = node.value;
38
+ if (direction > 0)
39
+ node.stepUp();
40
+ else
41
+ node.stepDown();
42
+ if (node.value !== before)
43
+ publish(node.value);
44
+ };
45
+ const glyph = (increase) => _jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.75", strokeLinecap: "round", "aria-hidden": "true", children: [_jsx("path", { d: "M5 12h14" }), increase && _jsx("path", { d: "M12 5v14" })] });
46
+ return _jsx(Group, { ...props, ref: input, type: "number", value: current, min: min, max: max, step: step, controlSize: controlSize, disabled: disabled, readOnly: readOnly, className: ["flood-number-input", className].filter(Boolean).join(" "), onChange: event => { if (!readOnly && !disabled)
47
+ publish(event.currentTarget.value); }, onBlur: event => {
48
+ onBlur?.(event);
49
+ if (event.defaultPrevented || readOnly || disabled || event.currentTarget.value === "")
50
+ return;
51
+ const node = event.currentTarget;
52
+ const before = node.value;
53
+ if (node.validity.rangeUnderflow && min !== undefined)
54
+ node.value = String(min);
55
+ if (node.validity.rangeOverflow && max !== undefined)
56
+ node.value = String(max);
57
+ if (node.value !== before)
58
+ publish(node.value);
59
+ }, onKeyDown: event => {
60
+ onKeyDown?.(event);
61
+ if (event.defaultPrevented || event.altKey || event.ctrlKey || event.metaKey || event.shiftKey || event.nativeEvent.isComposing || readOnly || disabled)
62
+ return;
63
+ if (event.key === "ArrowUp" || event.key === "ArrowDown") {
64
+ event.preventDefault();
65
+ move(event.key === "ArrowUp" ? 1 : -1);
66
+ }
67
+ }, start: _jsx(Action, { label: decreaseLabel, variant: "ghost", size: controlSize, disabled: disabled || readOnly || (number !== null && min !== undefined && number <= min), onClick: () => move(-1), children: glyph(false) }), end: _jsx(Action, { label: increaseLabel, variant: "ghost", size: controlSize, disabled: disabled || readOnly || (number !== null && max !== undefined && number >= max), onClick: () => move(1), children: glyph(true) }) });
68
+ });