diff --git a/.eslintrc b/.eslintrc index 3e8e9a6a5..a3f01bf46 100644 --- a/.eslintrc +++ b/.eslintrc @@ -21,7 +21,6 @@ } } ], - "parser": "@babel/eslint-parser", "rules": { "max-len": ["warn", { "code": 120 }], "no-console": ["error", { diff --git a/CHANGELOG.md b/CHANGELOG.md index 2a128fc8f..67d30db4a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ * Provide ability to disable an Icon Button. Refs STCOM-1028. * `MultiSelection` support for `aria-label`. Refs STCOM-977. * Fix regex matching of search options in ``. Fixes STCOM-1031. +* Export `staticFirstWeekDay` and `staticLangCountryCodes` from `Datepicker`. Refs STCOM-1038. ## [10.2.0](https://github.com/folio-org/stripes-components/tree/v10.2.0) (2022-06-14) [Full Changelog](https://github.com/folio-org/stripes-components/compare/v10.1.0...v10.2.0) @@ -65,6 +66,7 @@ * MultiSelection - fix exception when using special characters in search string. Fixes STCOM-1010. * Browse contributors > Second pane should not show a horizontal scrollbar. Fixes STCOM-1011. * Record detail panes are empty when printed. Refs STCOM-975. +* Add initial TypeScript definition files. Refs STCOM-1012. ## [10.1.5](https://github.com/folio-org/stripes-components/tree/v10.1.5) (2022-06-06) [Full Changelog](https://github.com/folio-org/stripes-components/compare/v10.1.4...v10.1.5) diff --git a/index.d.ts b/index.d.ts new file mode 100644 index 000000000..26d576703 --- /dev/null +++ b/index.d.ts @@ -0,0 +1,304 @@ +// lib/Accordion +export { + Accordion, + AccordionSet, + AccordionStatus, + DefaultAccordionHeader, + FilterAccordionHeader, + ExpandAllButton, + expandAllFunction, +} from './lib/Accordion'; + +// lib/AdvancedSearch + +// lib/AutoSuggest + +// lib/Avatar + +// lib/Badge +export { default as Badge, BadgeProps } from './lib/Badge'; + +// lib/Button +export { default as Button, ButtonProps } from './lib/Button'; + +// lib/ButtonGroup +export { default as ButtonGroup, ButtonGroupProps } from './lib/ButtonGroup'; + +// lib/Callout + +// lib/Card + +// lib/Checkbox +export { + default as Checkbox, + CheckboxProps, + CheckboxRenderProps, +} from './lib/Checkbox'; + +// lib/Commander + +// lib/ConfirmationModal +export { + default as ConfirmationModal, + ConfirmationModalProps, +} from './lib/ConfirmationModal'; + +// lib/ConflictDetectionBanner + +// lib/CountrySelection + +// lib/CurrencySelect + +// lib/Datepicker +export { + default as Datepicker, + DatepickerProps, + DatepickerFieldRenderProps, + staticFirstWeekDay, + staticLangCountryCodes, +} from './lib/Datepicker'; + +// lib/DateRangeWrapper + +// lib/Dropdown +export { Dropdown, UncontrolledDropdown, DropdownProps } from './lib/Dropdown'; + +// lib/DropdownButton +export { + default as DropdownButton, + DropdownButtonProps, +} from './lib/DropdownButton'; + +// lib/DropdownMenu +export { default as DropdownMenu, DropdownMenuProps } from './lib/DropdownMenu'; + +// lib/Editor + +// lib/EmptyMessage + +// lib/ErrorBoundary +export { + default as ErrorBoundary, + ErrorBoundaryProps, +} from './lib/ErrorBoundary'; + +// lib/ErrorModal + +// lib/ExportCsv + +// lib/FilterControlGroup + +// lib/FilterGroups + +// lib/FilterPaneSearch + +// lib/FocusLink + +// lib/FormattedDate + +// lib/FormattedTime + +// lib/FormattedUTCDate + +// lib/Headline +export { default as Headline, HeadlineProps } from './lib/Headline'; + +// lib/Highlighter + +// lib/HotKeys +export { HotKeys, HotKeysProps } from './lib/HotKeys'; + +// lib/Icon +export { default as Icon, IconProps } from './lib/Icon'; + +// lib/IconButton +export { default as IconButton, IconButtonProps } from './lib/IconButton'; + +// lib/InfoPopover + +// lib/KeyboardShortcutsModal + +// lib/KeyValue +export { default as KeyValue, KeyValueProps } from './lib/KeyValue'; + +// lib/Label + +// lib/Layer +export { default as Layer, LayerProps } from './lib/Layer'; + +// lib/Layout +export { default as Layout, LayoutProps } from './lib/Layout'; + +// lib/LayoutBox + +// lib/LayoutGrid +export { Grid, Row, Col } from './lib/LayoutGrid'; + +// lib/LayoutHeader + +// lib/List +export { default as List, ListProps } from './lib/List'; + +// lib/Loading +export { + Loading, + LoadingPane, + LoadingView, + LoadingProps, + LoadingPaneProps, + LoadingViewProps, +} from './lib/Loading'; + +// lib/MenuItem + +// lib/MenuSection +export { default as MenuSection, MenuSectionProps } from './lib/MenuSection'; + +// lib/MessageBanner + +// lib/MetaSection + +// lib/Modal +export { default as Modal, ModalProps } from './lib/Modal'; + +// lib/ModalFooter +export { default as ModalFooter, ModalFooterProps } from './lib/ModalFooter'; + +// lib/MultiColumnList +export { + default as MultiColumnList, + MultiColumnListProps, + MultiColumnListRowFormatterProps, +} from './lib/MultiColumnList'; + +// lib/MultiSelection +export { + default as MultiSelection, + MultiSelectionProps, + MultiSelectionFieldRenderProps, +} from './lib/MultiSelection'; + +// lib/NavList +export { default as NavList, NavListProps } from './lib/NavList'; + +// lib/NavListItem +export { default as NavListItem, NavListItemProps } from './lib/NavListItem'; + +// lib/NavListSection +export { + default as NavListSection, + NavListSectionProps, +} from './lib/NavListSection'; + +// lib/NoValue + +// lib/Pane +export { default as Pane, PaneProps } from './lib/Pane'; + +// lib/PaneBackLink +export { default as PaneBackLink, PaneBackLinkProps } from './lib/PaneBackLink'; + +// lib/PaneCloseLink +export { + default as PaneCloseLink, + PaneCloseLinkProps, +} from './lib/PaneCloseLink'; + +// lib/PaneFooter +export { default as PaneFooter, PaneFooterProps } from './lib/PaneFooter'; + +// lib/PaneHeader +export { default as PaneHeader, PaneHeaderProps } from './lib/PaneHeader'; + +// lib/PaneHeaderIconButton +export { + default as PaneHeaderIconButton, + PaneHeaderIconButtonProps, +} from './lib/PaneHeaderIconButton'; + +// lib/PaneMenu +export { default as PaneMenu, PaneMenuProps } from './lib/PaneMenu'; + +// lib/Paneset +export { default as Paneset, PanesetProps } from './lib/Paneset'; + +// lib/PaneSubheader +export { + default as PaneSubheader, + PaneSubheaderProps, +} from './lib/PaneSubheader'; + +// lib/PasswordStrength + +// lib/Popover + +// lib/Popper + +// lib/RadioButton + +// lib/RadioButtonGroup + +// lib/RepeatableField + +// lib/SearchField + +// lib/Select +export { + default as Select, + OptionType as SelectOptionType, + SelectProps, + SelectFieldRenderProps, +} from './lib/Select'; + +// lib/Selection +export { OptionSegment, OptionSegmentProps } from './lib/Selection'; + +// lib/Spinner + +// lib/SRStatus + +// lib/TextArea + +// lib/TextField +export { + default as TextField, + TextFieldProps, + TextFieldRenderProps, +} from './lib/TextField'; + +// lib/TextLink + +// lib/Timepicker +export { + default as Timepicker, + TimepickerProps, + TimepickerFieldRenderProps, +} from './lib/Timepicker'; + +// lib/Tooltip + +// hooks/useCurrencyOptions + +// hooks/useFormatDate + +// hooks/useFormatTime + +// util/countries + +// util/currencies + +// util/dateTimeUtils +export { + getLocaleDateFormat, + getLocalizedTimeFormatInfo, +} from './util/dateTimeUtils'; + +// util/getFocusableElements + +// util/languages + +// util/nativeChangeFieldValue + +// util/omitProps + +// util/RootCloseWrapper diff --git a/index.js b/index.js index aa4e29d27..2f349ec21 100644 --- a/index.js +++ b/index.js @@ -6,7 +6,12 @@ export { default as ButtonGroup } from './lib/ButtonGroup'; export { default as Checkbox } from './lib/Checkbox'; export { default as CurrencySelect } from './lib/CurrencySelect'; export { default as CountrySelection } from './lib/CountrySelection'; -export { default as Datepicker, Calendar } from './lib/Datepicker'; +export { + default as Datepicker, + Calendar, + staticFirstWeekDay, + staticLangCountryCodes +} from './lib/Datepicker'; export { getLocaleDateFormat, getLocalizedTimeFormatInfo } from './util/dateTimeUtils'; export { default as DateRangeWrapper } from './lib/DateRangeWrapper'; export { default as FormattedDate } from './lib/FormattedDate'; diff --git a/lib/Accordion/Accordion.d.ts b/lib/Accordion/Accordion.d.ts new file mode 100644 index 000000000..1508216d4 --- /dev/null +++ b/lib/Accordion/Accordion.d.ts @@ -0,0 +1,55 @@ +import { Component, CSSProperties, ReactNode, RefObject } from 'react'; +import { HotKeysProps } from '../HotKeys'; +import { DefaultAccordionHeaderProps } from './headers/DefaultAccordionHeader'; + +export interface AccordionProps extends Partial { + /** The containing accordionSet */ + accordionSet?: ReactNode; + /** The accordion's contents */ + children: ReactNode | ((open: boolean) => ReactNode); + /** Add class(es) to the component */ + className?: string; + /** If the accordion should be closed by default */ + closedByDefault?: boolean; + /** Sets the height of the accordion */ + contentHeight?: CSSProperties['height']; + /** The id of the content div */ + contentId?: string; + /** A reference to the content div */ + contentRef?: RefObject; + /** If the accordion should be disabled */ + disabled?: boolean; + /** Supplies a custom header */ + header?: ReactNode; + /** Adds props to the default header */ + headerProps?: Partial; + /** The id of the accordion */ + id?: string; + /** A label for the accordion */ + label: ReactNode; + /** A callback for when the header is clicked to toggle open/closed */ + onClickToggle?: (args: { id: string; label: string; open: boolean }) => void; + /** A callback for when the header is toggled (not just clicked, but external e.g. expand all) */ + onToggle?: (args: { id: string; label: string }) => void; + /** If the accordion is currently open */ + open?: boolean; + /** If the separator between header and contents should be drawn */ + separator?: boolean; + toggleKeyHandlers?: HotKeysProps['handlers']; + toggleKeyMap?: HotKeysProps['keyMap']; +} + +/** + * Displays information in an accordion + * @example + * + * + *

first content

+ *
+ * + *

second content

+ *
+ *
+ */ +export class Accordion extends Component {} +export default Accordion; diff --git a/lib/Accordion/AccordionSet.d.ts b/lib/Accordion/AccordionSet.d.ts new file mode 100644 index 000000000..28c440944 --- /dev/null +++ b/lib/Accordion/AccordionSet.d.ts @@ -0,0 +1,41 @@ +import { Component, ReactNode } from 'react'; +import { AccordionStatusRecord } from './types'; + +export interface AccordionSetBaseProps { + /** The accordions */ + children: ReactNode; + /** The initial accordion status */ + initialStatus?: AccordionStatusRecord; + /** Callback for when an accordion is toggled */ + onToggle?: (accordion: { id: string; label: string }) => void; + /** Callback for when the status is changed */ + setStatus?: (status: AccordionStatusRecord) => void; +} + +export type AccordionSetStatusProps = + | { + /** The current accordion status */ + accordionStatus?: AccordionStatusRecord; + inheritStatus: boolean; + } + | { + accordionStatus?: never; + inheritStatus?: false | never; + }; + +export type AccordionSetProps = AccordionSetBaseProps & AccordionSetStatusProps; + +/** + * Contains a set of accordions + * @example + * + * + *

first content

+ *
+ * + *

second content

+ *
+ *
+ */ +export class AccordionSet extends Component {} +export default AccordionSet; diff --git a/lib/Accordion/AccordionStatus.d.ts b/lib/Accordion/AccordionStatus.d.ts new file mode 100644 index 000000000..17f057d1a --- /dev/null +++ b/lib/Accordion/AccordionStatus.d.ts @@ -0,0 +1,29 @@ +import { Component, ReactNode } from 'react'; +import { AccordionStatusRecord } from './types'; + +export interface AccordionStatusProps { + /** The accordions */ + children: ReactNode; + /** The current accordion status */ + accordionStatus?: AccordionStatusRecord; + /** The initial accordion status */ + initialStatus?: AccordionStatusRecord; +} + +/** + * Allows an uncontrolled accordion to exist; this contains state for status/toggles + * @example + * + * + * + * + *

first content

+ *
+ * + *

second content

+ *
+ *
+ *
+ */ +export class AccordionStatus extends Component {} +export default AccordionStatus; diff --git a/lib/Accordion/ExpandAllButton.d.ts b/lib/Accordion/ExpandAllButton.d.ts new file mode 100644 index 000000000..5d8a9efaa --- /dev/null +++ b/lib/Accordion/ExpandAllButton.d.ts @@ -0,0 +1,36 @@ +import { FunctionComponent } from 'react'; +import { ButtonProps } from '../Button/Button'; +import { AccordionStatusRecord } from './types'; + +export interface ExpandAllButtonProps { + /** Manually specify the accordion's status */ + accordionStatus?: AccordionStatusRecord; + /** The label to use for a button that will collapse */ + collapseLabel?: ButtonProps['children']; + /** The label to use for a button that will expand */ + expandLabel?: ButtonProps['children']; + /** Add a custom ID to the button */ + id?: string; + /** Callback for when the status is changed */ + onToggle?: (status: AccordionStatusRecord) => void; + /** Callback for when the status is changed */ + setStatus?: (status: AccordionStatusRecord) => void; +} + +/** + * Controls a stack of accordions all at once + * @example + * + * + * + * + *

first content

+ *
+ * + *

second content

+ *
+ *
+ *
+ */ +export const ExpandAllButton: FunctionComponent; +export default ExpandAllButton; diff --git a/lib/Accordion/expandCollapseAll.d.ts b/lib/Accordion/expandCollapseAll.d.ts new file mode 100644 index 000000000..cf0d58ba4 --- /dev/null +++ b/lib/Accordion/expandCollapseAll.d.ts @@ -0,0 +1,9 @@ +import { AccordionStatusRecord } from './types'; + +/** + * Mark all values of `status` as `expand`, used for expanding or collapsing all accordions + */ +export default function ExpandCollapseAll( + status: AccordionStatusRecord, + expand: boolean +): AccordionStatusRecord; diff --git a/lib/Accordion/headers/DefaultAccordionHeader.d.ts b/lib/Accordion/headers/DefaultAccordionHeader.d.ts new file mode 100644 index 000000000..96468650f --- /dev/null +++ b/lib/Accordion/headers/DefaultAccordionHeader.d.ts @@ -0,0 +1,46 @@ +import React, { FunctionComponent, ReactNode } from 'react'; + +export interface DefaultAccordionHeaderProps { + /** If the header/button should autofocus on mount */ + autoFocus?: boolean; + /** Specify the ID of the content being controlled */ + contentId?: JSX.IntrinsicElements['button']['aria-controls']; + /** Extra text to display on the right side of the header when it is closed */ + displayWhenClosed?: ReactNode; + /** Extra text to display on the right side of the header when it is open */ + displayWhenOpen?: ReactNode; + /** Override header/button settings */ + headerProps?: { + /** Use a custom size */ + headingLevel?: 1 | 2 | 3 | 4 | 5 | 6; + } & Partial; + /** Sets a custom id */ + id?: string; + /** A label for the header */ + label: ReactNode; + /** Callback for when an accordion is toggled */ + onToggle?: (accordion: { id: string; label: string }) => void; + /** If the accordion is open */ + open?: boolean; + /** A ref for the internal `} + * > + *
    + *
  • All
  • + *
  • The
  • + *
  • Items!
  • + *
+ * + */ +export const DefaultAccordionHeader: FunctionComponent; +export default DefaultAccordionHeader; diff --git a/lib/Accordion/headers/FilterAccordionHeader.d.ts b/lib/Accordion/headers/FilterAccordionHeader.d.ts new file mode 100644 index 000000000..c97913e24 --- /dev/null +++ b/lib/Accordion/headers/FilterAccordionHeader.d.ts @@ -0,0 +1,30 @@ +import { FunctionComponent } from 'react'; +import { DefaultAccordionHeaderProps } from './DefaultAccordionHeader'; + +export interface FilterAccordionHeaderProps + extends DefaultAccordionHeaderProps { + /** If the filter field should be disabled */ + disabled?: boolean; + /** If the filter field should display a clear (x) button */ + displayClearButton?: boolean; + /** A name for the header */ + name?: string; + /** A callback for when the filter has been cleared */ + onClearFilter?: (name: string) => void; +} + +/** + * Renders a filtering header for an accordion + * @example + * } + * > + *
    + *
  • All
  • + *
  • The
  • + *
  • Items!
  • + *
+ *
+ */ +export const FilterAccordionHeader: FunctionComponent; +export default FilterAccordionHeader; diff --git a/lib/Accordion/index.d.ts b/lib/Accordion/index.d.ts new file mode 100644 index 000000000..ca147ed75 --- /dev/null +++ b/lib/Accordion/index.d.ts @@ -0,0 +1,19 @@ +export { default as Accordion, AccordionProps } from './Accordion'; +export { default as AccordionSet, AccordionSetProps } from './AccordionSet'; +export { + default as AccordionStatus, + AccordionStatusProps, +} from './AccordionStatus'; +export { + default as DefaultAccordionHeader, + DefaultAccordionHeaderProps, +} from './headers/DefaultAccordionHeader'; +export { + default as FilterAccordionHeader, + FilterAccordionHeaderProps, +} from './headers/FilterAccordionHeader'; +export { + default as ExpandAllButton, + ExpandAllButtonProps, +} from './ExpandAllButton'; +export { default as expandAllFunction } from './expandCollapseAll'; diff --git a/lib/Accordion/types.d.ts b/lib/Accordion/types.d.ts new file mode 100644 index 000000000..c1b46d0f4 --- /dev/null +++ b/lib/Accordion/types.d.ts @@ -0,0 +1,2 @@ +/** An object with keys representing accordion IDs and values representing if they are open/expanded */ +export type AccordionStatusRecord = Record; diff --git a/lib/Badge/Badge.d.ts b/lib/Badge/Badge.d.ts new file mode 100644 index 000000000..2ee215b9a --- /dev/null +++ b/lib/Badge/Badge.d.ts @@ -0,0 +1,20 @@ +import { FunctionComponent, ReactNode } from 'react'; + +export interface BadgeProps { + /** What should be displayed in the badge */ + children: ReactNode; + /** Adds a custom class to the badge */ + className?: string; + /** Sets the color of the badge */ + color?: 'default' | 'primary' | 'red'; + /** The size of the badge */ + size?: 'small' | 'medium'; +} + +/** + * Renders a badge for showing notifications, etc + * @example + * 3 + */ +export const Badge: FunctionComponent; +export default Badge; diff --git a/lib/Badge/index.d.ts b/lib/Badge/index.d.ts new file mode 100644 index 000000000..e130660f0 --- /dev/null +++ b/lib/Badge/index.d.ts @@ -0,0 +1 @@ +export { default, BadgeProps } from './Badge'; diff --git a/lib/Button/Button.d.ts b/lib/Button/Button.d.ts new file mode 100644 index 000000000..32745f5ce --- /dev/null +++ b/lib/Button/Button.d.ts @@ -0,0 +1,72 @@ +import { + AriaAttributes, + ForwardRefExoticComponent, + MouseEventHandler, + PropsWithoutRef, + ReactNode, + RefAttributes, +} from 'react'; +import { LinkProps } from 'react-router-dom'; +import { RequireOneOrNone } from '../../util/typeUtils'; + +export interface ButtonBaseProps extends AriaAttributes { + /** Changes the (flexbox) alignment of the button */ + align?: 'start' | 'center' | 'end'; + /** Allows the anchor's default onClick */ + allowAnchorClick?: boolean; + /** If this button should be automatically focused */ + autoFocus?: boolean; + /** Remove the margin from the bottom */ + bottomMargin0?: boolean; + /** Add a custom CSS class to the button */ + buttonClass?: string; + /** Sets the style of the button */ + buttonStyle?: + | 'default' + | 'primary' + | 'success' + | 'warning' + | 'danger' + | 'dropdownItem'; + /** The button for the label */ + children: ReactNode; + /** Forces the button to 100% width */ + fullWidth?: boolean; + /** Remove the margin from the bottom */ + marginBottom0?: boolean; + /** Handle an `onClick` event */ + onClick?: MouseEventHandler; + /** Remove the padding from all sides */ + paddingSide0?: boolean; + /** Adds a custom role to the button */ + role?: JSX.IntrinsicElements['button']['role']; +} + +// these are mutually exclusive (and can be entirely omitted, if needed) +export interface ButtonLinkProps { + /** Set the type of ` + */ +export const Button: ForwardRefExoticComponent< + PropsWithoutRef & + RefAttributes +>; +export default Button; diff --git a/lib/Button/index.d.ts b/lib/Button/index.d.ts new file mode 100644 index 000000000..d600dd4fb --- /dev/null +++ b/lib/Button/index.d.ts @@ -0,0 +1 @@ +export { default, ButtonProps } from './Button'; diff --git a/lib/ButtonGroup/ButtonGroup.d.ts b/lib/ButtonGroup/ButtonGroup.d.ts new file mode 100644 index 000000000..14c318956 --- /dev/null +++ b/lib/ButtonGroup/ButtonGroup.d.ts @@ -0,0 +1,29 @@ +import { + AriaAttributes, + ElementType, + FunctionComponent, + ReactNode, +} from 'react'; + +export interface ButtonGroupProps extends AriaAttributes { + /** Add a custom CSS class to the button group */ + className?: string; + /** A set of ` + * + * + * + */ +export const ButtonGroup: FunctionComponent; +export default ButtonGroup; diff --git a/lib/ButtonGroup/index.d.ts b/lib/ButtonGroup/index.d.ts new file mode 100644 index 000000000..d97e3cfc5 --- /dev/null +++ b/lib/ButtonGroup/index.d.ts @@ -0,0 +1 @@ +export { default, ButtonGroupProps } from './ButtonGroup'; diff --git a/lib/Checkbox/Checkbox.d.ts b/lib/Checkbox/Checkbox.d.ts new file mode 100644 index 000000000..feb27d829 --- /dev/null +++ b/lib/Checkbox/Checkbox.d.ts @@ -0,0 +1,93 @@ +import { + AriaAttributes, + ChangeEventHandler, + Component, + FocusEventHandler, + InputHTMLAttributes, + ReactNode, + RefObject, +} from 'react'; +import { FieldRenderProps } from 'react-final-form'; + +export interface CheckboxProps + extends AriaAttributes, + InputHTMLAttributes { + /** If the field should auto-focus on mount */ + autoFocus?: boolean; + /** If the checkbox is checked */ + checked?: boolean; + /** Apply class names to the root element */ + className?: string; + /** Adds info text below the checkbox */ + labelInfo?: ReactNode; + /** Adds a class to the info text */ + labelInfoClass?: string; + /** Disables the input field */ + disabled?: boolean; + /** An error to show for validation */ + error?: ReactNode; + /** If the field should stretch to fill its container */ + fullWidth?: boolean; + /** Adds a custom ID to the control */ + id?: string; + /** If the field should `display: inline` */ + inline?: boolean; + /** Add a class to the `` directly */ + innerClass?: string; + /** Ref to the internal field */ + inputRef?: RefObject; + /** The input's label */ + label?: ReactNode; + /** A custom class for the input's label */ + labelClass?: ReactNode; + /** The input's name */ + name?: string; + /** Fired when the user clicks out of/deselects the control */ + onBlur?: FocusEventHandler; + /** Fired anytime internal state changes */ + onChange?: ChangeEventHandler; + /** Fired when the user clicks into the control */ + onFocus?: FocusEventHandler; + /** If the control is readonly */ + readOnly?: boolean; + /** If the field is required */ + required?: boolean; + /** Renders the label above the checkbox */ + vertical?: boolean; + /** The field's value, sent as part of a HTML submit event */ + value?: string | number | readonly string[]; + /** Inline feedback for the user indicating a validation warning */ + warning?: ReactNode; +} + +export type CheckboxRenderProps = + FieldRenderProps; + +/** + * Basic HTML checkbox. If a value is provided, then `react-final-form`'s value + * will be an array containing the value if and only if the checkbox is checked. + * This allows for advanced usage with many checkboxes. Otherwise, the value + * is simply a boolean indicating if the box is checked + * @example + * { + * // consume event.target.value + * }} + * /> + * @example + * + */ +export default class Checkbox< + DataType extends boolean | readonly string[] = boolean, + AdditionalProps extends + | CheckboxProps + | CheckboxRenderProps = CheckboxProps +> extends Component {} diff --git a/lib/Checkbox/index.d.ts b/lib/Checkbox/index.d.ts new file mode 100644 index 000000000..6fe02589c --- /dev/null +++ b/lib/Checkbox/index.d.ts @@ -0,0 +1 @@ +export { default, CheckboxRenderProps, CheckboxProps } from './Checkbox'; diff --git a/lib/ConfirmationModal/ConfirmationModal.d.ts b/lib/ConfirmationModal/ConfirmationModal.d.ts new file mode 100644 index 000000000..77ec9f0e1 --- /dev/null +++ b/lib/ConfirmationModal/ConfirmationModal.d.ts @@ -0,0 +1,40 @@ +import { ElementType, FunctionComponent, ReactNode } from 'react'; +import { ButtonProps } from '../Button/Button'; + +export interface ConfirmationModalProps { + /** the top

of the modal; doubles as the aria-label */ + heading: ReactNode; + /** The message to display inside the modal */ + message?: ReactNode; + /** If the modal is open */ + open: boolean; + /** The cancel button's label */ + cancelLabel?: ReactNode; + /** The confirm button's label */ + confirmLabel?: ReactNode; + /** Callback for when the action is confirmed */ + onConfirm: () => void; + /** Callback for when the action is cancelled */ + onCancel: () => void; + /** Override the tag wrapping the modal's `message` */ + bodyTag?: ElementType; + /** Change the style of the confirm button */ + buttonStyle?: ButtonProps['buttonStyle']; + /** Change the style of the cancel button */ + cancelButtonStyle?: ButtonProps['buttonStyle']; +} + +/** + * A basic confirmation modal with props to support a heading (required), + * a brief message, and customizable 'cancel' and 'submit' action labeling. + * @example + * + */ +export const ConfirmationModal: FunctionComponent; +export default ConfirmationModal; diff --git a/lib/ConfirmationModal/index.d.ts b/lib/ConfirmationModal/index.d.ts new file mode 100644 index 000000000..44aa7ec99 --- /dev/null +++ b/lib/ConfirmationModal/index.d.ts @@ -0,0 +1 @@ +export { default, ConfirmationModalProps } from './ConfirmationModal'; diff --git a/lib/Datepicker/Datepicker.d.ts b/lib/Datepicker/Datepicker.d.ts new file mode 100644 index 000000000..5f3315926 --- /dev/null +++ b/lib/Datepicker/Datepicker.d.ts @@ -0,0 +1,104 @@ +import { Moment } from 'moment'; +import Popper from 'popper.js'; +import { + AriaAttributes, + Component, + FocusEventHandler, + ReactNode, + RefObject, +} from 'react'; +import { FieldRenderProps } from 'react-final-form'; + +export interface DatepickerBaseProps extends AriaAttributes { + /** If the field should auto-focus on mount */ + autoFocus?: boolean; + /** How backend dates should be parsed, e.g. `"ISO 8601"` */ + backendDateStandard?: string; + /** How the date should be formatted/localized, e.g. `YYYY.MM.DD` */ + dateFormat?: string; + /** Disables the input field */ + disabled?: boolean; + /** Disallows selection of dates that the function returns true */ + exclude?: (moment: Moment) => boolean; + /** If the picker should close once a date is clicked */ + hideOnChoose?: boolean; + /** Adds a custom ID to the control */ + id?: string; + /** Ref to the internal text field */ + inputRef?: RefObject | ((el: HTMLInputElement) => void); + /** Label the datepicker */ + label?: ReactNode; + /** Set the locale for use */ + locale?: string; + /** Remove bottom margin */ + marginBottom0?: boolean; + /** Popper modifiers */ + modifiers?: Popper.Modifiers; + /** Fired when the user clicks out of/deselects the control */ + onBlur?: FocusEventHandler; + /** Fired anytime internal state changes */ + onChange?: (e: Event, formatted: string, dateString: string) => void; + /** Fired when the user clicks into the control */ + onFocus?: FocusEventHandler; + /** When a date is chosen on the calendar */ + onSetDate?: (date: Moment) => void; + /** Parses a date for local display in the text field */ + parser?: (value: string) => string; + /** Where the overlay should be placed in relation to the field */ + placement?: Popper.Placement; + /** If the control is readonly */ + readOnly?: boolean; + /** If the field is required */ + required?: boolean; + /** Additional message to be read when the field is focused */ + screenReaderMessage?: boolean; + /** If the calendar should start off opened */ + showCalendar?: boolean; + /** Override the default timezone */ + timeZone?: string; + /** If focusing the text field should open the calendar popup */ + useFocus?: boolean; + /** If the field is being used within a final-form or similar */ + useInput?: boolean; + /** Render to the global overlay, if the dropdown may be cut off due to some containing elements's overflow */ + usePortal?: boolean; + /** The field's value */ + value?: string; +} + +export type DatepickerOutputProps = + | { + // /** Determines if the datepicker's value will be the formatted local string or one ready for the backend */ + outputBackendValue?: false; + outputFormatter?: never; + } + | { + // /** Determines if the datepicker's value will be the formatted local string or one ready for the backend */ + outputBackendValue: true; + // /** Formats a date for the backend */ + outputFormatter?: (date: Moment) => string; + }; + +// only allow `outputFormatter` if `outputBackendValue` is true +export type DatepickerProps = DatepickerBaseProps & DatepickerOutputProps; + +export type DatepickerFieldRenderProps = FieldRenderProps; + +/** + * A picker for dates with an optional calendar popup + * @example + * + * // or pass as component within a form... + * + * @example + * + */ +export default class Datepicker< + AdditionalProps extends + | DatepickerProps + | DatepickerFieldRenderProps = DatepickerProps +> extends Component {} diff --git a/lib/Datepicker/index.d.ts b/lib/Datepicker/index.d.ts new file mode 100644 index 000000000..e0055f8fd --- /dev/null +++ b/lib/Datepicker/index.d.ts @@ -0,0 +1,7 @@ +export { + default, + DatepickerFieldRenderProps, + DatepickerProps, +} from './Datepicker'; +export { default as staticFirstWeekDay } from './staticFirstWeekDay'; +export { default as staticLangCountryCodes } from './staticLangCountryCodes'; diff --git a/lib/Datepicker/index.js b/lib/Datepicker/index.js index 61aa17997..a774a7830 100644 --- a/lib/Datepicker/index.js +++ b/lib/Datepicker/index.js @@ -1,2 +1,4 @@ export { default as Calendar } from './Calendar'; +export { default as staticFirstWeekDay } from './staticFirstWeekDay'; +export { default as staticLangCountryCodes } from './staticLangCountryCodes'; export { default } from './Datepicker'; diff --git a/lib/Datepicker/staticFirstWeekDay.d.ts b/lib/Datepicker/staticFirstWeekDay.d.ts new file mode 100644 index 000000000..d37b32f07 --- /dev/null +++ b/lib/Datepicker/staticFirstWeekDay.d.ts @@ -0,0 +1,6 @@ +declare const data: Record< + 'sat' | 'sun' | 'mon' | 'tue' | 'wed' | 'thu' | 'fri', + string[] +>; + +export default data; diff --git a/lib/Datepicker/staticLangCountryCodes.d.ts b/lib/Datepicker/staticLangCountryCodes.d.ts new file mode 100644 index 000000000..57bb990d8 --- /dev/null +++ b/lib/Datepicker/staticLangCountryCodes.d.ts @@ -0,0 +1,3 @@ +declare const data: Record; + +export default data; diff --git a/lib/Dropdown/Dropdown.d.ts b/lib/Dropdown/Dropdown.d.ts new file mode 100644 index 000000000..d5585b13b --- /dev/null +++ b/lib/Dropdown/Dropdown.d.ts @@ -0,0 +1,160 @@ +import Popper from 'popper.js'; +import React, { + AriaAttributes, + Component, + ElementType, + FocusEventHandler, + KeyboardEventHandler, + ReactNode, + RefObject, +} from 'react'; +import { AllOrNone } from '../../util/typeUtils'; +import { ButtonProps } from '../Button/Button'; + +export interface DropdownBaseProps extends AriaAttributes { + /** Adds additional classes to the wrapping element */ + className?: string; + /** If the dropdown should be disabled/inactive */ + disabled?: boolean; + /** Custom handlers for when the dropdown is opened or closed */ + focusHandlers?: { + open?: ( + trigger?: React.RefObject, + menu?: HTMLElement, + firstItem?: HTMLElement + ) => void; + close?: ( + trigger?: React.RefObject, + menu?: HTMLElement + ) => void; + }; + /** Overrides the ID for the dropdown */ + id?: string; + /** Controls the addition of padding within the dropdown */ + hasPadding?: boolean; + /** Custom modifiers for how the popper should render */ + modifiers?: Popper.Modifiers; + /** Custom placement for the popper */ + placement?: Popper.Placement; + /** If `position: relative` should be applied */ + relativePosition?: boolean; + /** A custom tag for the main wrapping element */ + tag?: ElementType; + /** If the dropdown should be rendered to overall `#OverlayContainer` div */ + usePortal?: boolean; +} + +export interface DropdownTriggerBuiltinProps { + /** Additional props to add to the builtin button trigger */ + buttonProps?: Partial; + /** The label for the button trigger */ + label: ReactNode; +} + +export interface DropdownTriggerCustomProps { + /** A custom function to render the trigger */ + renderTrigger: (props: { + getTriggerProps: (opts: { + onFocus?: FocusEventHandler; + onBlur?: FocusEventHandler; + }) => void; + open: boolean; + triggerRef: RefObject; + onToggle: (e: Event) => void; + ariaProps: Partial; + keyHandler: KeyboardEventHandler; + buttonProps: Partial; + label: string; + }) => ReactNode; +} + +export interface DropdownMenuFunction { + (props: { + open: boolean; + onToggle: () => void; + keyHandler?: KeyboardEventHandler; + }): ReactNode; +} + +export interface DropdownMenuChildrenProps { + /** + * The dropdown's menu/contents, as children. + * A custom function may also be passed here + */ + children: ReactNode | DropdownMenuFunction; +} + +export interface DropdownMenuPropFunctionProps { + /** A custom function to render the menu/contents of the dropdown */ + renderMenu: DropdownMenuFunction; +} + +export interface DropdownControlledProps { + /** + * A function to be called when the dropdown should be toggled + * (e.g. from the Escape key or a click outside the popper) + */ + onToggle: () => void; + /** If the dropdown should currently be open */ + open: boolean; +} + +export type DropdownProps = DropdownBaseProps & + (DropdownTriggerBuiltinProps | DropdownTriggerCustomProps) & + (DropdownMenuChildrenProps | DropdownMenuPropFunctionProps) & + AllOrNone; + +/** + * Renders a dropdown for displaying links of lists and more + * @example + * The most straightforward use will cause the component to render its own + * control button and handle its own state: + * ``` + * + * + * + * + * + * ``` + * @example + * If more control is needed, state can be managed externally via `onToggle` + * and `open` props. Additionally, `renderMenu` and `renderTrigger` props + * allow custom render functions which will receive status information, + * handlers, and more: + * ``` + * const trigger = ({ triggerRef, toggleMenu, ariaProps, keyHandler }) => ( + * + * ); + * + * const menu = ({open, onToggle, keyHandler}) => { + * + * + * + * } + * + * this.state.open = !this.state.open} + * /> + * ``` + */ +export class Dropdown extends Component {} +export default Dropdown; diff --git a/lib/Dropdown/UncontrolledDropdown.d.ts b/lib/Dropdown/UncontrolledDropdown.d.ts new file mode 100644 index 000000000..1892eb2e0 --- /dev/null +++ b/lib/Dropdown/UncontrolledDropdown.d.ts @@ -0,0 +1,7 @@ +/** + * @deprecated + * This component is deprecated and `` should be used instead. + */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export const UncontrolledDropdown: any; +export default UncontrolledDropdown; diff --git a/lib/Dropdown/index.d.ts b/lib/Dropdown/index.d.ts new file mode 100644 index 000000000..04002a964 --- /dev/null +++ b/lib/Dropdown/index.d.ts @@ -0,0 +1,2 @@ +export { default as Dropdown, DropdownProps } from './Dropdown'; +export { default as UncontrolledDropdown } from './UncontrolledDropdown'; diff --git a/lib/DropdownButton/DropdownButton.d.ts b/lib/DropdownButton/DropdownButton.d.ts new file mode 100644 index 000000000..8f4c3c9d5 --- /dev/null +++ b/lib/DropdownButton/DropdownButton.d.ts @@ -0,0 +1,32 @@ +import { + ForwardRefExoticComponent, + PropsWithoutRef, + ReactNode, + RefAttributes, +} from 'react'; +import { ButtonProps } from '../Button/Button'; + +export type DropdownButtonProps = ButtonProps & { + /** Dropdown button contents */ + children: ReactNode; +}; + +/** + * Renders a button for a dropdown menu + * @example + * + * + * Toggle dropdown + * + * + * This is our dropdown + * + * + */ +export const DropdownButton: ForwardRefExoticComponent< + PropsWithoutRef & RefAttributes +>; +export default DropdownButton; diff --git a/lib/DropdownButton/index.d.ts b/lib/DropdownButton/index.d.ts new file mode 100644 index 000000000..d44dec56b --- /dev/null +++ b/lib/DropdownButton/index.d.ts @@ -0,0 +1 @@ +export { default, DropdownButtonProps } from './DropdownButton'; diff --git a/lib/DropdownMenu/DropdownMenu.d.ts b/lib/DropdownMenu/DropdownMenu.d.ts new file mode 100644 index 000000000..a91925e46 --- /dev/null +++ b/lib/DropdownMenu/DropdownMenu.d.ts @@ -0,0 +1,56 @@ +import { + AriaAttributes, + CSSProperties, + FunctionComponent, + ReactEventHandler, + ReactNode, +} from 'react'; +import { AllOrNone, RequireOneOrNone } from '../../util/typeUtils'; + +export interface DropdownMenuBaseProps extends AriaAttributes { + /** Menu contents */ + children: ReactNode; + /** A minimum width for the menu */ + minWidth?: CSSProperties['minWidth']; + /** Callback for when an item is selected */ + onSelect?: ReactEventHandler; + /** Callback for when an item is selected */ + onSelectItem?: ReactEventHandler; + /** Callback for when an item is selected */ + overrideStyle?: Partial; + /** If the menu should be pulled to the right side */ + pullRight?: boolean; + /** Force a given width */ + width?: CSSProperties['width']; +} + +export interface DropdownMenuControlledProps { + /** Callback for when the menu should toggle, for external state control */ + onToggle: ReactEventHandler; + /** If the menu is open, for external state control */ + open: boolean; +} + +export type DropdownMenuProps = RequireOneOrNone< + DropdownMenuBaseProps, + 'onSelect' | 'onSelectItem' +> & + AllOrNone; + +/** + * Renders a menu for a dropdown + * @example + * + * + * Toggle dropdown + * + * + * This is our dropdown + * + * + */ +export const DropdownMenu: FunctionComponent; +export default DropdownMenu; diff --git a/lib/DropdownMenu/index.d.ts b/lib/DropdownMenu/index.d.ts new file mode 100644 index 000000000..63c044c25 --- /dev/null +++ b/lib/DropdownMenu/index.d.ts @@ -0,0 +1 @@ +export { default, DropdownMenuProps } from './DropdownMenu'; diff --git a/lib/ErrorBoundary/ErrorBoundary.d.ts b/lib/ErrorBoundary/ErrorBoundary.d.ts new file mode 100644 index 000000000..dd633768d --- /dev/null +++ b/lib/ErrorBoundary/ErrorBoundary.d.ts @@ -0,0 +1,32 @@ +import { Component, ReactNode } from 'react'; + +export interface ErrorBoundaryProps { + /** The children to catch errors from */ + children: ReactNode; + /** Force production display even in development */ + forceProductionError?: boolean; + /** Callback for when an error occurs */ + onError?: Component['componentDidCatch']; + /** Callback when a user clicks the refresh/primary button */ + onReset?: () => void; + /** A custom label for the refresh/primary button */ + resetButtonLabel?: ReactNode; + /** The subtitle of the error message */ + subTitle?: ReactNode; + /** The main title of the error message */ + title?: ReactNode; +} + +/** + * Renders a component that will catch errors of interior components + * @example + * + * + * + */ +export default class ErrorBoundary extends Component {} diff --git a/lib/ErrorBoundary/index.d.ts b/lib/ErrorBoundary/index.d.ts new file mode 100644 index 000000000..9bb744dc0 --- /dev/null +++ b/lib/ErrorBoundary/index.d.ts @@ -0,0 +1 @@ +export { default, ErrorBoundaryProps } from './ErrorBoundary'; diff --git a/lib/Headline/Headline.d.ts b/lib/Headline/Headline.d.ts new file mode 100644 index 000000000..d89277b3f --- /dev/null +++ b/lib/Headline/Headline.d.ts @@ -0,0 +1,50 @@ +import { + ForwardRefExoticComponent, + PropsWithoutRef, + ReactNode, + RefAttributes, +} from 'react'; + +export interface HeadlineProps { + /** If the headline should have display: block */ + block?: boolean; + /** + * Makes the headline bold + * @deprecated use the weight prop instead + */ + bold?: boolean; + /** Sets the label of the headline */ + children: ReactNode; + /** Adds additional classes to the element */ + className?: string; + /** Adds a faded style (gray color) */ + faded?: boolean; + /** If the headline should have display: flex */ + flex?: boolean; + /** Controls the bottom margin of the headline, corresponds to the size prop */ + margin?: + | 'xx-small' + | 'x-small' + | 'small' + | 'medium' + | 'large' + | 'x-large' + | 'xx-large' + | 'none' + | ''; + /** The size of the headline */ + size?: 'small' | 'medium' | 'large' | 'x-large' | 'xx-large'; + /** The tag to render the headline as */ + tag?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'p' | 'div' | 'legend'; + /** Control the font-weight of the headline */ + weight?: 'regular' | 'medium' | 'bold' | 'black'; +} + +/** + * Renders headlines in different sizes and with different tags, margins and styles depending on props. + * @example foo + */ +export const Headline: ForwardRefExoticComponent< + PropsWithoutRef & RefAttributes +>; +export default Headline; diff --git a/lib/Headline/index.d.ts b/lib/Headline/index.d.ts new file mode 100644 index 000000000..f22bbcd1c --- /dev/null +++ b/lib/Headline/index.d.ts @@ -0,0 +1 @@ +export { default, HeadlineProps } from './Headline'; diff --git a/lib/HotKeys/index.d.ts b/lib/HotKeys/index.d.ts new file mode 100644 index 000000000..8429e3070 --- /dev/null +++ b/lib/HotKeys/index.d.ts @@ -0,0 +1,30 @@ +import { + Component, + ComponentType, + KeyboardEvent, + KeyboardEventHandler, + ReactNode, +} from 'react'; + +export interface HotKeysBaseProps { + /** Children to capture hotkey events on */ + children?: ReactNode; + /** An object with keys mapping custom key names to an array of real keys */ + keyMap?: Record; + /** An object mapping either custom key names {@link keyMap} or real key names to event handlers */ + handlers: Record; +} + +export type HotKeysWrapperProps = + | { + noWrapper?: false | undefined | never; + component?: ComponentType; + } + | { + noWrapper: true; + component?: never; + }; + +export type HotKeysProps = HotKeysBaseProps & HotKeysWrapperProps; + +export class HotKeys extends Component {} diff --git a/lib/Icon/Icon.d.ts b/lib/Icon/Icon.d.ts new file mode 100644 index 000000000..357d93c74 --- /dev/null +++ b/lib/Icon/Icon.d.ts @@ -0,0 +1,145 @@ +import { + AriaAttributes, + ComponentType, + ForwardRefExoticComponent, + PropsWithoutRef, + ReactNode, + RefAttributes, +} from 'react'; + +import { AllOrNone } from '../../util/typeUtils'; + +export type IconName = + | 'allocate' + | 'archive' + | 'arrow-down' + | 'arrow-left' + | 'arrow-right' + | 'arrow-up' + | 'bookmark' + | 'calendar' + | 'cancel' + | 'caret-down' + | 'caret-left' + | 'caret-right' + | 'caret-up' + | 'cart' + | 'check-circle' + | 'check-in' + | 'check-out' + | 'chevron-double-left' + | 'chevron-double-right' + | 'chevron-left' + | 'chevron-right' + | 'clipboard' + | 'clock' + | 'combine' + | 'comment' + | 'default' + | 'deselect-all' + | 'diacritic' + | 'document' + | 'download' + | 'drag-drop' + | 'duplicate' + | 'edit' + | 'ellipsis' + | 'end-mark' + | 'envelope' + | 'exclamation-circle' + | 'external-link' + | 'eye-closed' + | 'eye-open' + | 'flag' + | 'gear' + | 'house' + | 'indexes' + | 'info' + | 'lightning' + | 'link' + | 'lock' + | 'play' + | 'plus-sign' + | 'preview' + | 'print' + | 'profile' + | 'question-mark' + | 'receive' + | 'refresh' + | 'replace' + | 'report' + | 'save' + | 'search' + | 'select-all' + | 'source' + | 'spinner-ellipsis' + | 'tag' + | 'times-circle-solid' + | 'times-circle' + | 'times' + | 'transfer' + | 'trash' + | 'triangle-down' + | 'triangle-up' + | 'unlink'; + +/** + * Custom icons must accept the following props + * (and pass them onto their ``) + */ +export interface CustomIconProps { + className: string; + viewBox: string; + focusable: boolean | 'true' | 'false'; +} + +/** + * An icon, to be rendered by ``. This supports a known icon name + * (see {@link IconName}) or a custom component that takes SVG props and + * returns a ``. + */ +export type IconType = IconName | ComponentType; + +export interface IconPropsWithoutChildren extends AriaAttributes { + /** + * Specify an accessible label for the icon + * @deprecated use `aria-label` instead + */ + ariaLabel?: AriaAttributes['aria-label']; + /** The icon to render, or a component for custom icons */ + icon: IconType; + /** Applies a custom class name to the icon directly */ + iconClassName?: string; + /** Applies a class to the internal wrapper div around the icon; useful for hover effects */ + iconRootClass?: string; + /** Apply a style to the icon -- currently, `"action"` is the only supported style */ + iconStyle?: 'action'; + /** Set the outer element's ID */ + id?: string; + /** Control the size of the icon */ + size?: 'small' | 'medium' | 'large'; + /** Give the icon a specific coloration */ + status?: undefined | 'error' | 'warn' | 'success'; + /** Set a custom tabIndex of the element */ + tabIndex?: number; +} + +// ensure iconPosition cannot exist without children +// either children exists (and iconPosition optionally does), or neither. +export interface IconChildrenProps { + /** Adds content next to the icon, useful for adding a label */ + children: ReactNode; + /** Sets the position of the icon, for use with children */ + iconPosition?: 'start' | 'end'; +} + +export type IconProps = IconPropsWithoutChildren & AllOrNone; + +/** + * Renders a given icon + * @example + */ +export const Icon: ForwardRefExoticComponent< + PropsWithoutRef & RefAttributes +>; +export default Icon; diff --git a/lib/Icon/index.d.ts b/lib/Icon/index.d.ts new file mode 100644 index 000000000..cc539c3ab --- /dev/null +++ b/lib/Icon/index.d.ts @@ -0,0 +1 @@ +export { default, IconProps } from './Icon'; diff --git a/lib/IconButton/IconButton.d.ts b/lib/IconButton/IconButton.d.ts new file mode 100644 index 000000000..764750063 --- /dev/null +++ b/lib/IconButton/IconButton.d.ts @@ -0,0 +1,113 @@ +import { + AriaAttributes, + CSSProperties, + ForwardRefExoticComponent, + MouseEventHandler, + PropsWithoutRef, + RefAttributes, +} from 'react'; +import { LinkProps } from 'react-router-dom'; +import { AllOrNone, RequireOneOrNone } from '../../util/typeUtils'; +import { BadgeProps } from '../Badge/Badge'; +import { IconType } from '../Icon/Icon'; + +export interface IconButtonBaseProps extends AriaAttributes { + /** + * Indicates whether the element (or a grouping it controls) is expanded + * @deprecated use `aria-label` instead + */ + ariaExpanded?: AriaAttributes['aria-expanded']; + /** + * Indicates the availability and type of a popup element + * @deprecated use `aria-haspopup` instead + */ + ariaHasPopup?: AriaAttributes['aria-haspopup']; + /** + * Provides a custom label for the element + * @deprecated use `aria-label` instead + */ + ariaLabel?: AriaAttributes['aria-label']; + /** + * Identify the element which labels the current element + * @deprecated use `aria-labelledby` instead + */ + ariaLabelledby?: AriaAttributes['aria-labelledby']; + /** If this button should be automatically focused */ + autoFocus?: boolean; + /** Add a custom CSS class to the button */ + className?: string; + /** The icon to display */ + icon: IconType; + /** Adds a custom class name to the icon element */ + iconClassName?: string; + /** + * Defines the size of the icon inside the button + * @see size for the size of the button itself + */ + iconSize?: 'small' | 'medium'; + /** Adds a custom ID to the icon */ + id?: string; + /** + * Adds a custom class name to the middle element, between the outer + * button/anchor element and the icon itself + */ + innerClassName?: string; + /** Handle an `onClick` event */ + onClick?: MouseEventHandler; + /** Handle an `onMouseDown` event */ + onMouseDown?: MouseEventHandler; + /** + * Defines the size of the button itself + * @see iconSize for the size of the icon + */ + size?: 'small' | 'medium'; + /** Set custom styles for the button */ + style?: CSSProperties; + /** Control the tabIndex of the button */ + tabIndex?: number; +} + +// these are mutually exclusive (and can be entirely omitted, if needed) +export interface IconButtonButtonLinkProps { + /** Set the type of `Some node + * + */ +export const KeyValue: FunctionComponent; +export default KeyValue; diff --git a/lib/KeyValue/index.d.ts b/lib/KeyValue/index.d.ts new file mode 100644 index 000000000..dd93448a0 --- /dev/null +++ b/lib/KeyValue/index.d.ts @@ -0,0 +1 @@ +export { default, KeyValueProps } from './KeyValue'; diff --git a/lib/Layer/Layer.d.ts b/lib/Layer/Layer.d.ts new file mode 100644 index 000000000..040ec1c20 --- /dev/null +++ b/lib/Layer/Layer.d.ts @@ -0,0 +1,40 @@ +import { Component, ElementType, ReactNode } from 'react'; + +export interface LayerProps { + /** Callback after the layer is closed */ + afterClose?: () => void; + /** Callback after the layer is opened */ + afterOpen?: () => void; + /** If the layer should be focused on mount */ + autoFocus?: boolean; + /** The layer's contents */ + children?: ReactNode; + /** The containing element where the layer's DOM nodes should go */ + container?: ElementType; + /** A label for the content, for accessibility */ + contentLabel?: string; + /** If the layer should forcibly contain focus within it (recommended for accessibility) */ + enforceFocus?: boolean; + /** + * If the layer should be rendered in the root-most paneset it can find (no effect if + * {@link container} is supplied) + */ + inRootSet?: boolean; + /** If the layer is currently opened */ + isOpen: boolean; +} + +/** + * A new layer of panes, like a full-screen modal + * @example + * + * // Base Paneset contents ... + * + * + * //...Layered Paneset contents... + * + * + * + */ +export class Layer extends Component {} +export default Layer; diff --git a/lib/Layer/index.d.ts b/lib/Layer/index.d.ts new file mode 100644 index 000000000..b265ab48f --- /dev/null +++ b/lib/Layer/index.d.ts @@ -0,0 +1 @@ +export { default, LayerProps } from './Layer'; diff --git a/lib/Layout/Layout.d.ts b/lib/Layout/Layout.d.ts new file mode 100644 index 000000000..0adcac7b8 --- /dev/null +++ b/lib/Layout/Layout.d.ts @@ -0,0 +1,25 @@ +import { ElementType, FunctionComponent, ReactNode } from 'react'; + +export interface LayoutProps { + /** Adds children to the layout element */ + children?: ReactNode; + /** Adds additional classes to the element */ + className?: string; + /** Override the default element type of `div` */ + element?: ElementType; +} + +/** + * Helper component to easily add common layout-based CSS classes + * @example + * + * + * 1st column + * + * + * 2nd column + * + * + */ +export const Layout: FunctionComponent; +export default Layout; diff --git a/lib/Layout/index.d.ts b/lib/Layout/index.d.ts new file mode 100644 index 000000000..04ade5c72 --- /dev/null +++ b/lib/Layout/index.d.ts @@ -0,0 +1 @@ +export { default, LayoutProps } from './Layout'; diff --git a/lib/LayoutGrid/index.d.ts b/lib/LayoutGrid/index.d.ts new file mode 100644 index 000000000..a752c3a42 --- /dev/null +++ b/lib/LayoutGrid/index.d.ts @@ -0,0 +1,19 @@ +/* eslint-disable max-classes-per-file */ +import { Component, ReactNode } from 'react'; +import { GridProps, RowProps, ColProps } from 'react-flexbox-grid'; + +export class Grid extends Component< + GridProps & { + children?: ReactNode; + } +> {} +export class Row extends Component< + RowProps & { + children?: ReactNode; + } +> {} +export class Col extends Component< + ColProps & { + children?: ReactNode; + } +> {} diff --git a/lib/List/List.d.ts b/lib/List/List.d.ts new file mode 100644 index 000000000..819307f56 --- /dev/null +++ b/lib/List/List.d.ts @@ -0,0 +1,42 @@ +import { Component, ReactNode } from 'react'; + +export interface ListProps { + /** What should be displayed if the list is empty */ + isEmptyMessage?: ReactNode; + /** A custom formatter for rendering the generic `ItemType` */ + itemFormatter?: (item: ItemType, i: number) => ReactNode; + /** The list's items */ + items: ItemType[]; + /** Adds a custom class to the list */ + listClass?: string; + /** Sets the list's style */ + listStyle?: 'default' | 'bullets'; + /** Removes margin from the bottom of the list */ + marginBottom0?: boolean; +} + +/** + * Renders a list of items + * @example + * const items = ['Apples', 'Bananas', 'Strawberries', 'Oranges']; + * const itemFormatter = (item) => (
  • {item}
  • ); + * const isEmptyMessage = 'No items to show'; + * + * + * @example + * const items = [{foo: "bar"}, {foo: "baz"}]; + * { + * return
  • {item}
  • + * }} + * /> + */ +// must extend component as it's impossible to provide a proper export with FunctionComponent +export default class List extends Component< + ListProps +> {} diff --git a/lib/List/index.d.ts b/lib/List/index.d.ts new file mode 100644 index 000000000..773c476df --- /dev/null +++ b/lib/List/index.d.ts @@ -0,0 +1 @@ +export { default, ListProps } from './List'; diff --git a/lib/Loading/Loading.d.ts b/lib/Loading/Loading.d.ts new file mode 100644 index 000000000..e32a6f6a9 --- /dev/null +++ b/lib/Loading/Loading.d.ts @@ -0,0 +1,16 @@ +import { FunctionComponent } from 'react'; + +export interface LoadingProps { + /** The size of the loading icon (default medium) */ + size?: 'small' | 'medium' | 'large' | 'xlarge'; + /** If the current element's CSS text `color` should be used instead of the default grey */ + useCurrentColor?: boolean; +} + +/** + * Renders a basic, standalone loading icon/spinner + * @example + * + */ +export const Loading: FunctionComponent; +export default Loading; diff --git a/lib/Loading/LoadingPane.d.ts b/lib/Loading/LoadingPane.d.ts new file mode 100644 index 000000000..e5d27ff2f --- /dev/null +++ b/lib/Loading/LoadingPane.d.ts @@ -0,0 +1,20 @@ +import { FunctionComponent } from 'react'; +import { Optional } from '../../util/typeUtils'; +import { PaneProps } from '../Pane/Pane'; + +// The pane's children are replaced with a spinner so the prop should not be +// available. Additionally, defaultWidth is specified by default (`fill`) so +// is no longer required +export type LoadingPaneProps = Optional< + Omit, + 'defaultWidth' +>; + +/** + * Renders a pane containing a loading spinner with the given props; accepts + * the properties of Pane (minus `children`) + * @example + * + */ +export const LoadingPane: FunctionComponent; +export default LoadingPane; diff --git a/lib/Loading/LoadingView.d.ts b/lib/Loading/LoadingView.d.ts new file mode 100644 index 000000000..2693c4c05 --- /dev/null +++ b/lib/Loading/LoadingView.d.ts @@ -0,0 +1,16 @@ +import { FunctionComponent } from 'react'; +import { LoadingPaneProps } from './LoadingPane'; +import { PanesetProps } from '../Paneset/Paneset'; + +export type LoadingViewProps = LoadingPaneProps & { + panesetProps: PanesetProps; +}; + +/** + * Renders a paneset containing a loading spinner with the given props; accepts + * the properties of LoadingPane as well as Paneset (under prop `panesetProps`) + * @example + * + */ +export const LoadingView: FunctionComponent; +export default LoadingView; diff --git a/lib/Loading/index.d.ts b/lib/Loading/index.d.ts new file mode 100644 index 000000000..46fbe0816 --- /dev/null +++ b/lib/Loading/index.d.ts @@ -0,0 +1,3 @@ +export { default as Loading, LoadingProps } from './Loading'; +export { default as LoadingPane, LoadingPaneProps } from './LoadingPane'; +export { default as LoadingView, LoadingViewProps } from './LoadingView'; diff --git a/lib/MenuSection/MenuSection.d.ts b/lib/MenuSection/MenuSection.d.ts new file mode 100644 index 000000000..033cbc653 --- /dev/null +++ b/lib/MenuSection/MenuSection.d.ts @@ -0,0 +1,52 @@ +import { FunctionComponent, ReactNode } from 'react'; +import { AllOrNone } from '../../util/typeUtils'; +import { HeadlineProps } from '../Headline/Headline'; + +export interface MenuSectionBaseProps { + /** What should be displayed in the section */ + children?: ReactNode; + /** Adds a custom class to the section */ + className?: string; + /** Specifies a custom ID for the component */ + id?: string; +} + +export interface MenuSectionLabelProps { + /** Renders a label */ + label: HeadlineProps['children']; + /** Specifies a label's tag */ + labelTag?: HeadlineProps['tag']; +} + +export type MenuSectionProps = MenuSectionBaseProps & + AllOrNone; + +/** + * Defines menu sections with labels, such as for dropdown menus + * @example + * + * + * + * + * + * @example + * + * + * + * + * + * @example + * + * + * + * + * + */ +export const MenuSection: FunctionComponent; +export default MenuSection; diff --git a/lib/MenuSection/index.d.ts b/lib/MenuSection/index.d.ts new file mode 100644 index 000000000..6372807eb --- /dev/null +++ b/lib/MenuSection/index.d.ts @@ -0,0 +1 @@ +export { default, MenuSectionProps } from './MenuSection'; diff --git a/lib/Modal/Modal.d.ts b/lib/Modal/Modal.d.ts new file mode 100644 index 000000000..e15401f43 --- /dev/null +++ b/lib/Modal/Modal.d.ts @@ -0,0 +1,55 @@ +import { + AriaAttributes, + ElementType, + FunctionComponent, + ReactNode, +} from 'react'; + +export interface ModalProps extends AriaAttributes { + /** The contents to render in the modal */ + children: ReactNode; + /** If the modal should close if it's background is clicked */ + closeOnBackgroundClick?: boolean; + /** Add custom classes to the content wrapper */ + contentClass?: string; + /** If a `x` should render in the top left to dismiss the modal */ + dismissible?: boolean; + /** Attempt to steal focus from children each time one is clicked */ + enforceFocus?: boolean; + /** A `` */ + footer?: ReactNode; + /** A custom ID for the modal's div */ + id?: string; + /** A title for the top label */ + label: ReactNode; + /** Callback for when the modal should be closed */ + onClose?: () => void; + /** Callback for when the modal opens */ + onOpen?: () => void; + /** If the modal is open */ + open: boolean; + /** If the modal should return focus on close to where it was before it was opened */ + restoreFocus?: boolean; + /** If the modal should cover the main pane area (`module`), or the whole window (`root`) */ + scope?: 'module' | 'root'; + /** The modal's size */ + size?: 'small' | 'medium' | 'large'; + /** Changes the wrapping element (useful to make forms) */ + wrappingElement?: ElementType; +} + +/** + * Default modal interface for FOLIO + * @example + * const footer = ( + * + * + * + * ); + * + * + * + * + */ +export const Modal: FunctionComponent; +export default Modal; diff --git a/lib/Modal/index.d.ts b/lib/Modal/index.d.ts new file mode 100644 index 000000000..a1d24b437 --- /dev/null +++ b/lib/Modal/index.d.ts @@ -0,0 +1 @@ +export { default, ModalProps } from './Modal'; diff --git a/lib/ModalFooter/ModalFooter.d.ts b/lib/ModalFooter/ModalFooter.d.ts new file mode 100644 index 000000000..7003954f8 --- /dev/null +++ b/lib/ModalFooter/ModalFooter.d.ts @@ -0,0 +1,24 @@ +import { FunctionComponent, ReactNode } from 'react'; + +export interface ModalFooterProps { + /** The buttons to render in the footer */ + children: ReactNode; +} + +/** + * Default modal footer for the `` component + * @example + * + * + * + * + */ +export const ModalFooter: FunctionComponent; +export default ModalFooter; diff --git a/lib/ModalFooter/index.d.ts b/lib/ModalFooter/index.d.ts new file mode 100644 index 000000000..21afc11a5 --- /dev/null +++ b/lib/ModalFooter/index.d.ts @@ -0,0 +1 @@ +export { default, ModalFooterProps } from './ModalFooter'; diff --git a/lib/MultiColumnList/MultiColumnList.d.ts b/lib/MultiColumnList/MultiColumnList.d.ts new file mode 100644 index 000000000..73c0cc789 --- /dev/null +++ b/lib/MultiColumnList/MultiColumnList.d.ts @@ -0,0 +1,238 @@ +import { + Component, + CSSProperties, + FunctionComponent, + KeyboardEventHandler, + MouseEventHandler, + ReactNode, + RefObject, + UIEventHandler, +} from 'react'; +import { AllOrNone, RequireOneOrNone } from '../../util/typeUtils'; +import { HotKeysProps } from '../HotKeys'; + +export type DataFieldType = keyof object; +export type ColumnWidth = + | CSSProperties['width'] + | { + min: number; + max?: number; + }; +export interface PositionObject { + /** Number of pixels from the top of the screen to add above the item being scrolled to */ + localClientTop: number; + /** Selector to match the row, likely something like `[aria-rowindex="${rowIndex}"]` */ + selector: string; +} + +export type PagingType = 'click' | 'none' | 'prev-next' | 'scroll'; + +export interface MultiColumnListRowFormatterProps { + cells: ReactNode[]; + labelStrings: + | string[] + | ((props: MultiColumnListRowFormatterProps) => string[]); + rowClass: string; + rowData: DataShape; + rowIndex: number; + rowProps: { + onClick: MouseEventHandler; + onKeyDown: KeyboardEventHandler; + style: CSSProperties; + 'data-row-inner': number; + }; + rowWidth: number; +} + +export interface MultiColumnListBaseProps< + DataShape, + OmittedColumns extends string +> { + /** + * Adds a prefix to column header IDs (otherwise MCLs with conflicting column + * header names in the same view could cause issues) + */ + columnIdPrefix?: string; + /** Maps data fields to labels for column headers */ + columnMapping?: Record, ReactNode>; + /** If a column should show overflow */ + columnOverflow?: Record, boolean>; + /** Set widths for columns, either as direct widths or min/max pixels */ + columnWidths?: Record, ColumnWidth>; + /** A ref to the MCL's container */ + containerRef?: RefObject; + /** The list's data */ + contentData: DataShape[]; + /** Custom functions that render the nodes for each column */ + formatter?: Record< + keyof Omit, + (item: DataShape) => ReactNode + >; + /** Replaces the default classes with the result of this function */ + getCellClass?: ( + defaultClasses: string, + rowData: DataShape, + header: keyof Omit + ) => string; + /** Adds additional classes to the default header's classes */ + getHeaderCellClass?: ( + columnName: keyof Omit + ) => string; + /** Replaces the default row container classes with the result of this function */ + getRowContainerClass?: (defaultClasses: string) => string; + /** Adds horizontal margin to the rows and header */ + hasMargin?: boolean; + /** + * unknown, see + * https://folio-project.slack.com/archives/C210UCHQ9/p1655355343636399?thread_ts=1589556430.060600&cid=C210UCHQ9 + */ + headerMetadata?: unknown; + /** Adds a class to the header row */ + headerRowClass?: string; + /** Add custom hotkeys to the list */ + hotKeys?: { + keyMap?: HotKeysProps['keyMap']; + handlers?: HotKeysProps['handlers']; + }; + /** Override the default id for the MCL */ + id?: string; + /** Function to pass the instance to */ + instanceRef?: (instance: MultiColumnList) => void; + /** If rows should display as hoverable/clickable */ + interactive?: boolean; + /** The message to display if the MCL is empty */ + isEmptyMessage?: ReactNode; + /** Function to determine if a row should show as selected */ + isSelected?: (args: { item: DataShape; rowIndex: number }) => boolean; + /** If a loading icon should be shown at the bottom of the list */ + loading?: boolean; + /** A maximum height for the MCL, in pixels */ + maxHeight?: number; + /** The minimum height of any row, in pixels */ + minimumRowHeight?: number; + /** Callback for a row being focused */ + onMarkPosition?: (itemToView: PositionObject) => void; + /** Callback to request more data to be loaded */ + onNeedMoreData?: (askAmount: number, index: number) => void; + /** Callback for when a row is clicked */ + onRowClick?: (e: MouseEvent | KeyboardEvent, row: DataShape) => void; + /** Callback for when the list is scrolled */ + onScroll?: UIEventHandler; + /** The amount to request at a time from `onNeedMoreData` */ + pageAmount?: number; + /** The method for pagination */ + pagingType?: PagingType; + /** A custom formatter for an entire row */ + // TODO: add default formatter types/extension here + rowFormatter?: FunctionComponent>; + /** Keys in the data that should not be rendered */ + rowMetadata?: OmittedColumns[]; + /** + * A function that can force a row to re-render by changing its return. This return is passed + * directly to a pure row's props, so any change will cause a re-render. The actual value does + * not matter + */ + rowUpdater?: (rowData: DataShape, rowIndex: number) => unknown; + /** Override styles for selected rows */ + selectedClass?: string; + /** + * The selected row, should match a row from {@link contentData} + * @deprecated use {@link isSelected} instead + */ + selectedRow?: DataShape; + /** Which way a sorted column is sorted */ + sortDirection?: 'ascending' | 'descending'; + /** The column being styled as sorted */ + sortedColumn?: keyof Omit; + /** If alternating rows should have different colors, resulting in a striped appearance */ + striped?: boolean; + /** The total number of rows, for virtualization or pagination */ + totalCount?: number; + /** For large tables, do not render all rows into the DOM at once */ + virtualize?: boolean; + /** A list of columns that should be rendered, takes precedence over {@link rowMetadata} */ + visibleColumns?: (keyof Omit)[]; + /** Set the MCL's width */ + width?: number; + /** If cells should wrap within themselves */ + wrapCells?: boolean; +} + +export type MultiColumnListHeightProps = RequireOneOrNone<{ + /** If the list should fill the containing element (e.g. filling the full width/height of a pane) */ + autosize?: boolean; + /** Set the height of the container */ + height?: CSSProperties['height']; +}>; + +export type MultiColumnListHeaderClickProps< + DataShape, + OmittedColumns extends string +> = AllOrNone<{ + /** Columns to disallow clicking */ + nonInteractiveHeaders?: (keyof Omit)[]; + /** Callback for when a column is clicked */ + onHeaderClick: ( + e: MouseEvent, + meta: { name: keyof Omit; alias: ReactNode } + ) => void; +}>; + +export type MultiColumnListSpecialPagingTypes = + | AllOrNone<{ + pagingType: 'click'; + /** If there is no more data available */ + dataEndReached?: boolean; + /** A custom label for the load more button */ + pagingButtonLabel?: ReactNode; + }> + | AllOrNone<{ + pagingType: 'prev-next'; + pagingCanGoNext?: boolean; + pagingCanGoPrevious?: boolean; + hidePageIndices?: boolean; + }>; + +export type MultiColumnListMarkProps = AllOrNone<{ + /** Scroll to a given item */ + itemToView: PositionObject; + /** Callback for when a row from itemToView could not be focused */ + onMarkReset?: () => void; +}>; + +export type MultiColumnListProps< + DataShape, + OmittedColumns extends string +> = MultiColumnListBaseProps & + MultiColumnListHeightProps & + MultiColumnListHeaderClickProps & + MultiColumnListSpecialPagingTypes & + MultiColumnListMarkProps; + +/** + * Renders an array of data objects as a table where each object is a row and each property of the + * objects is a column. Capable of virtualizing rows in large collections of data. + * @example + * const catalogResults = [ + * {title:'Microbiology Today', author:'James Edward'}, + * {title:'Orange Book', author:'Philip Ramos'}, + * ] + * + * @example + * , + * actionDate: , + * dueDate: , + * itemStatus: , + * source: , + * }} + * /> + */ +export class MultiColumnList< + DataShape, + OmittedColumns extends string = '' +> extends Component> {} +export default MultiColumnList; diff --git a/lib/MultiColumnList/index.d.ts b/lib/MultiColumnList/index.d.ts new file mode 100644 index 000000000..4b3082550 --- /dev/null +++ b/lib/MultiColumnList/index.d.ts @@ -0,0 +1,5 @@ +export { + default, + MultiColumnListProps, + MultiColumnListRowFormatterProps, +} from './MultiColumnList'; diff --git a/lib/MultiSelection/MultiSelection.d.ts b/lib/MultiSelection/MultiSelection.d.ts new file mode 100644 index 000000000..0794c6b56 --- /dev/null +++ b/lib/MultiSelection/MultiSelection.d.ts @@ -0,0 +1,136 @@ +import Popper from 'popper.js'; +import { Component, FocusEventHandler, ReactNode } from 'react'; +import { FieldRenderProps } from 'react-final-form'; +import { RequireOneOrNone } from '../../util/typeUtils'; + +/** + * The default option type to be used, contains a label and potentially a value + */ +export interface MultiSelectionDefaultOptionType { + label: string; + value: ValueType; +} + +/** + * Props each action may accept + * @see https://github.com/folio-org/stripes-components/tree/master/lib/MultiSelection#actions + */ +export interface MultiSelectionActionItemProps< + OptionType = MultiSelectionDefaultOptionType +> { + /** The search term */ + filterValue: string; + /** If this search was an exact match */ + exactMatch: boolean; + /** A list of all rendered items */ + renderedItems: ReadonlyArray; +} + +export interface MultiSelectionBaseProps< + OptionType = MultiSelectionDefaultOptionType +> { + /** + * Custom actions, such as a "New" row + * @see https://github.com/folio-org/stripes-components/tree/master/lib/MultiSelection#actions + */ + actions?: { + onSelect: () => void; + render: (props: MultiSelectionActionItemProps) => ReactNode; + }[]; + /** Adds an accessible label if no `label` is provided */ + ariaLabelledBy?: string; + /** + * Allows {@link filter} to run asynchronously (e.g. on a server); with + * {@link dataOptions} undefined or null a loading spinner will show + */ + asyncFiltering?: boolean; + /** If the field should auto-focus on mount */ + autoFocus?: boolean; + /** If backspace should remove a selected items */ + backspaceDeletes?: boolean; + /** The items to choose from. If null or undefined, a loading spinner will be shown */ + dataOptions: OptionType[] | null | undefined; + /** Marks the field as changed, for styling */ + dirty?: boolean; + /** Disables the input field */ + disabled?: boolean; + /** The message to show when no items were found with a given search */ + emptyMessage?: string; + /** An error to show for validation */ + error?: ReactNode; + /** A custom filter function, either directly gives results or does something async */ + filter?: ( + filterText: string | undefined, + list: OptionType[] + ) => { renderedItems: OptionType[]; exactMatch?: boolean } | Promise; + /** A custom formatter to render each option */ + formatter?: (option: OptionType, searchTerm: string | undefined) => ReactNode; + /** Adds a custom ID to the control */ + id?: string; + /** If true, adds valid styles to the field */ + isValid?: boolean; + /** A custom formatter to get string representations of objects for accessibility */ + itemToString?: (option: OptionType) => string; + /** A label for the field */ + label?: ReactNode; + /** The maximum height for the options menu, in pixels */ + maxHeight?: number; + /** Modifiers for how the overlay should render */ + modifiers?: Popper.Modifiers; + /** Fired when the user clicks out of/deselects the control */ + onBlur?: FocusEventHandler; + /** Fired anytime internal state changes */ + onChange?: (selectedItems: OptionType[]) => void; + /** Fired when an item is removed */ + onRemove?: (removedItem: OptionType) => void; + /** A placeholder for the control when there is no value */ + placeholder?: string; + /** Render to the global overlay, if the dropdown may be cut off due to some containing elements's overflow */ + renderToOverlay?: boolean; + /** If the field is required */ + required?: boolean; + /** If validation styles should be rendered */ + validationEnabled?: boolean; + /** The selected objects */ + value?: OptionType[]; + /** Same as {@link formatter}, `formatter` should probably be used instead. */ + valueFormatter?: ( + option: OptionType, + searchTerm: string | undefined + ) => ReactNode; + /** Inline feedback for the user indicating a validation warning */ + warning?: ReactNode; +} + +export type MultiSelectionProps = + RequireOneOrNone< + MultiSelectionBaseProps, + 'valueFormatter' | 'formatter' + >; + +export type MultiSelectionFieldRenderProps = FieldRenderProps< + OptionType[] +>; + +/** + * Multiple selection control, allowing filtering of options + * @example + * const optionList = [ + * { value: 'test0', label: 'Option 0' }, + * { value: 'test1', label: 'Option 1' }, + * { value: 'test2', label: 'Option 2' }, + * // ... + * ]; + * + * + */ +export default class MultiSelection< + OptionType = MultiSelectionDefaultOptionType, + AdditionalProps extends + | MultiSelectionProps + | MultiSelectionFieldRenderProps = MultiSelectionProps +> extends Component & AdditionalProps> {} diff --git a/lib/MultiSelection/index.d.ts b/lib/MultiSelection/index.d.ts new file mode 100644 index 000000000..73eecefc5 --- /dev/null +++ b/lib/MultiSelection/index.d.ts @@ -0,0 +1,5 @@ +export { + default, + MultiSelectionProps, + MultiSelectionFieldRenderProps, +} from './MultiSelection'; diff --git a/lib/NavList/NavList.d.ts b/lib/NavList/NavList.d.ts new file mode 100644 index 000000000..044ce5e2b --- /dev/null +++ b/lib/NavList/NavList.d.ts @@ -0,0 +1,35 @@ +import { + AriaAttributes, + ForwardRefExoticComponent, + PropsWithoutRef, + ReactNode, + RefAttributes, +} from 'react'; + +export interface NavListProps extends AriaAttributes { + /** + * Specify an accessible label for the icon + * @deprecated use `aria-label` instead + */ + ariaLabel?: AriaAttributes['aria-label']; + /** The contents of the nav list */ + children: ReactNode; + /** Adds custom class(es) to the item */ + className?: string; +} + +/** + * Renders a navigation list + * @example + * + * + * Users + * Organization + * Circulation + * + * + */ +export const NavList: ForwardRefExoticComponent< + PropsWithoutRef & RefAttributes +>; +export default NavList; diff --git a/lib/NavList/index.d.ts b/lib/NavList/index.d.ts new file mode 100644 index 000000000..76bee80cd --- /dev/null +++ b/lib/NavList/index.d.ts @@ -0,0 +1 @@ +export { default, NavListProps } from './NavList'; diff --git a/lib/NavListItem/NavListItem.d.ts b/lib/NavListItem/NavListItem.d.ts new file mode 100644 index 000000000..8f0d29d0b --- /dev/null +++ b/lib/NavListItem/NavListItem.d.ts @@ -0,0 +1,47 @@ +import { + AriaAttributes, + ForwardRefExoticComponent, + MouseEventHandler, + PropsWithoutRef, + ReactNode, + RefAttributes, +} from 'react'; +import { LinkProps } from 'react-router-dom'; +import { RequireOneOrNone } from '../../util/typeUtils'; + +export interface NavListItemBaseProps extends AriaAttributes { + /** What should be displayed for this nav item */ + children: ReactNode; + /** Adds custom class(es) to the item */ + className?: string; + /** If this navigation item is currently active */ + isActive?: boolean; + /** Call a custom function when the item is clicked */ + onClick?: MouseEventHandler; +} +export interface NavListItemInteractiveProps { + /** Adds a link to the button, like a normal . Incompatible with `onClick` and `to`. */ + href: string; + /** + * Controls where the link should go, like for a ``. + * This prop is incompatible with `type` and `href`. + * @see + * https://github.com/remix-run/react-router/blob/f9c4a0e8ec022545b2679d381dc41652f1694804/docs/components/link.md + */ + to: LinkProps['to']; +} + +export type NavListItemProps = NavListItemBaseProps & + RequireOneOrNone; + +/** + * Renders an item in a nav list + * @example + * Users + * Organization + * Circulation + */ +export const NavListItem: ForwardRefExoticComponent< + PropsWithoutRef & RefAttributes +>; +export default NavListItem; diff --git a/lib/NavListItem/index.d.ts b/lib/NavListItem/index.d.ts new file mode 100644 index 000000000..c640bdbcf --- /dev/null +++ b/lib/NavListItem/index.d.ts @@ -0,0 +1 @@ +export { default, NavListItemProps } from './NavListItem'; diff --git a/lib/NavListSection/NavListSection.d.ts b/lib/NavListSection/NavListSection.d.ts new file mode 100644 index 000000000..6031335b1 --- /dev/null +++ b/lib/NavListSection/NavListSection.d.ts @@ -0,0 +1,38 @@ +import { + AriaAttributes, + ForwardRefExoticComponent, + PropsWithoutRef, + ReactNode, + RefAttributes, +} from 'react'; +import { LinkProps } from 'react-router-dom'; +import { HeadlineProps } from '../Headline/Headline'; + +export interface NavListSectionProps extends AriaAttributes { + /** The link currently being displayed */ + activeLink?: LinkProps['to'] | string; + /** {@link NavListItem}s to display */ + children: ReactNode; + /** Adds custom class(es) to the section */ + className?: string; + /** The label to display inside a {@link Headline} */ + label?: HeadlineProps['children']; + /** If the items should alternate colors */ + striped?: boolean; + /** The tag to render for the {@link Headline} */ + tag?: HeadlineProps['tag']; +} + +/** + * Renders a section of NavListItems + * @example + * + * Users + * Organization + * Circulation + * + */ +export const NavListSection: ForwardRefExoticComponent< + PropsWithoutRef & RefAttributes +>; +export default NavListSection; diff --git a/lib/NavListSection/NavListSectionContext.d.ts b/lib/NavListSection/NavListSectionContext.d.ts new file mode 100644 index 000000000..19d5f06a9 --- /dev/null +++ b/lib/NavListSection/NavListSectionContext.d.ts @@ -0,0 +1,10 @@ +import { Context } from 'react'; +import { LinkProps } from 'react-router-dom'; + +export interface NavListSectionContextContents { + activeLink: LinkProps['to'] | string; + striped: boolean; +} + +declare const toExport: Context; +export default toExport; diff --git a/lib/NavListSection/index.d.ts b/lib/NavListSection/index.d.ts new file mode 100644 index 000000000..ba2335bdf --- /dev/null +++ b/lib/NavListSection/index.d.ts @@ -0,0 +1 @@ +export { default, NavListSectionProps } from './NavListSection'; diff --git a/lib/Pane/Pane.d.ts b/lib/Pane/Pane.d.ts new file mode 100644 index 000000000..cd4afd17c --- /dev/null +++ b/lib/Pane/Pane.d.ts @@ -0,0 +1,147 @@ +import { + AriaAttributes, + Component, + CSSProperties, + ElementType, + ReactNode, + RefObject, +} from 'react'; +import { Optional } from '../../util/typeUtils'; +import { PaneHeaderDefaultProps } from '../PaneHeader/PaneHeader'; + +export interface PaneProps extends AriaAttributes { + /** + * Activates the action menu dropdown; function must return a node/component + * (probably a ``) + * @deprecated use {@link renderHeader} instead + */ + actionMenu?: PaneHeaderDefaultProps['actionMenu']; + /** + * Adds an icon to the header. Expects an `` from `stripes-core`. + * @deprecated use {@link renderHeader} instead + */ + appIcon?: PaneHeaderDefaultProps['appIcon']; + /** + * Wraps the contents in a centered container -- useful in large panes where + * you do not want the content to fill the pane's entire width + */ + centerContent?: boolean; + /** The pane's contents */ + children: ReactNode; + /** + * The percentage of the paneset that should be occupied, + * or `fill` to use all available space + */ + defaultWidth: `${number}%` | 'fill'; + /** + * If a close (x) button should be rendered in the pane's header: + * - A `false` value will not render a button + * - A `true` value will render a button in the firstMenu (left side in ltr languages) + * - A `"last"` value will render a button in the lastMenu (right side in ltr languages) + * @deprecated use {@link renderHeader} instead + */ + dismissible?: PaneHeaderDefaultProps['dismissible']; + /** + * Component (probably a ``) to render at the beginning of the header + * (top left in ltr languages) + * @deprecated use {@link renderHeader} instead + */ + firstMenu?: PaneHeaderDefaultProps['firstMenu']; + /** If true, removes the default min-width applied to the pane's contents */ + fluidContentWidth?: boolean; + /** A node (likely a ) to render at the bottom of the pane */ + footer?: ReactNode; + /** The height of the pane, not to exceed `100vh` (used for the universal FOLIO header) */ + height?: CSSProperties['height']; + /** Specify an ID to use for the Pane */ + id?: string; + /** + * Component (probably a ``) to render at the end of the header + * (top right in ltr languages) + * @deprecated use {@link renderHeader} instead + */ + lastMenu?: PaneHeaderDefaultProps['lastMenu']; + /** + * If the pane is not expected to scroll. If true, scrollbars will be + * hidden, fixing some issues in result panes and the like. + */ + noOverflow?: boolean; + /** + * Callback for when the pane is closed using its close button (see `dismissible` prop) + * @deprecated use {@link renderHeader} instead + */ + onClose?: () => void; + /** Callback for when the pane is mounted */ + onMount?: (args: { + paneRef: RefObject; + paneTitleRef: RefObject; + }) => void; + /** If the pane's contents should be padded */ + padContent?: boolean; + /** + * Add a subtitle to the pane, as a node or string (recommended). + * @deprecated use {@link renderHeader} instead + */ + paneSub?: PaneHeaderDefaultProps['paneSub']; + /** + * Add a title to the pane, as a node or string (recommended). + * This will be enclosed with a `

    ` for accessibility + * @deprecated use {@link renderHeader} instead + */ + paneTitle?: PaneHeaderDefaultProps['paneTitle']; + /** + * A reference to the header of the pane + * @deprecated use {@link renderHeader} instead + */ + paneTitleRef?: PaneHeaderDefaultProps['paneTitleRef']; + /** + * A function to render a ``. This is the preferred method + * over providing props to the `` itself. The parameters are props + * that were passed to this pane but belong to the header, so should + * probably be spread to your custom `` before your props. + * This method will eventually be the only supported method. + */ + renderHeader?: ( + renderProps: Pick< + Optional, + | 'paneTitle' + | 'paneTitleRef' + | 'paneSub' + | 'appIcon' + | 'firstMenu' + | 'lastMenu' + | 'actionMenu' + | 'dismissible' + | 'onClose' + | 'id' + > + ) => ReactNode; + /** Render something immediately beneath the main pane header (likely a ) */ + subheader?: ReactNode; + /** Use a custom element for the root element of the pane */ + tagName?: ElementType; + /** Set the transition of the pane */ + transition?: 'none' | 'slide'; +} + +/** + * A pane, central to FOLIO module layout. + * @example + * + * Pane Content + * + * } + * > + * Pane Content + * + */ +export class Pane extends Component {} +export default Pane; diff --git a/lib/Pane/index.d.ts b/lib/Pane/index.d.ts new file mode 100644 index 000000000..c1f8a909b --- /dev/null +++ b/lib/Pane/index.d.ts @@ -0,0 +1 @@ +export { default, PaneProps } from './Pane'; diff --git a/lib/PaneBackLink/PaneBackLink.d.ts b/lib/PaneBackLink/PaneBackLink.d.ts new file mode 100644 index 000000000..2a2920317 --- /dev/null +++ b/lib/PaneBackLink/PaneBackLink.d.ts @@ -0,0 +1,28 @@ +import { FunctionComponent } from 'react'; +import { Optional } from '../../util/typeUtils'; +import { PaneHeaderIconButtonProps } from '../PaneHeaderIconButton/PaneHeaderIconButton'; + +// The icon is `arrow-left` by default +export type PaneBackLinkProps = Optional; + +/** + * Renders a left arrow used to close panes on smaller screens (hidden above `medium` breakpoint). + * All props are passed to the internal `IconButton`. + * @example + * ( + * + * + * + * } + * /> + * )} + * > + * ... + * + */ +export const PaneBackLink: FunctionComponent; +export default PaneBackLink; diff --git a/lib/PaneBackLink/index.d.ts b/lib/PaneBackLink/index.d.ts new file mode 100644 index 000000000..124ab06d2 --- /dev/null +++ b/lib/PaneBackLink/index.d.ts @@ -0,0 +1 @@ +export { default, PaneBackLinkProps } from './PaneBackLink'; diff --git a/lib/PaneCloseLink/PaneCloseLink.d.ts b/lib/PaneCloseLink/PaneCloseLink.d.ts new file mode 100644 index 000000000..8e032b244 --- /dev/null +++ b/lib/PaneCloseLink/PaneCloseLink.d.ts @@ -0,0 +1,28 @@ +import { FunctionComponent } from 'react'; +import { Optional } from 'utility-types'; +import { PaneHeaderIconButtonProps } from '../PaneHeaderIconButton/PaneHeaderIconButton'; + +// The icon is `arrow-left` or `times` by default +export type PaneCloseLinkProps = Optional; + +/** + * Renders a left arrow used to close panes on smaller screens and a `x` icon + * on larger screens. All props are passed to the internal `IconButton`. + * @example + * ( + * + * + * + * } + * /> + * )} + * > + * ... + * + */ +export const PaneCloseLink: FunctionComponent; +export default PaneCloseLink; diff --git a/lib/PaneCloseLink/index.d.ts b/lib/PaneCloseLink/index.d.ts new file mode 100644 index 000000000..f5b90766e --- /dev/null +++ b/lib/PaneCloseLink/index.d.ts @@ -0,0 +1 @@ +export { default, PaneCloseLinkProps } from './PaneCloseLink'; diff --git a/lib/PaneFooter/DefaultPaneFooter.d.ts b/lib/PaneFooter/DefaultPaneFooter.d.ts new file mode 100644 index 000000000..2fe3f22b0 --- /dev/null +++ b/lib/PaneFooter/DefaultPaneFooter.d.ts @@ -0,0 +1,26 @@ +import { FunctionComponent, ReactNode } from 'react'; + +export interface PaneFooterBaseProps { + /** Sets the class name of the main footer element */ + className?: string; +} + +export interface PaneFooterChildrenContentsProps { + /** The contents of the footer */ + children: ReactNode; +} + +export interface DefaultPaneFooterProps { + /** Adds class name(s) to the footer */ + className?: string; + /** Node(s) to render at the start of the footer */ + renderStart?: ReactNode; + /** Node(s) to render at the end of the footer */ + renderEnd?: ReactNode; +} + +/** + * Renders a pane footer with the given nodes at the start and end + */ +export const DefaultPaneFooter: FunctionComponent; +export default DefaultPaneFooter; diff --git a/lib/PaneFooter/PaneFooter.d.ts b/lib/PaneFooter/PaneFooter.d.ts new file mode 100644 index 000000000..2ed49f5e6 --- /dev/null +++ b/lib/PaneFooter/PaneFooter.d.ts @@ -0,0 +1,72 @@ +import { + Component, + ForwardRefExoticComponent, + PropsWithoutRef, + ReactNode, + RefAttributes, +} from 'react'; +import { RenameByT } from '../../util/typeUtils'; +import { DefaultPaneFooterProps } from './DefaultPaneFooter'; + +export interface PaneFooterBaseProps { + /** Sets the class name of the main footer element */ + className?: string; + /** Overrides the component/tag used for the footer */ + element?: Component; +} + +export interface PaneFooterChildrenContentsProps { + /** The contents of the footer */ + children: ReactNode; +} + +export type PaneFooterBuiltinContentsProps = RenameByT< + DefaultPaneFooterProps, + { + className: 'innerClassName'; + } +> & { + /** Render at the start (left in LTR languages) of the footer */ + renderStart?: ReactNode; + /** Render at the end (right in LTR languages) of the footer */ + renderEnd?: ReactNode; +}; + +export type PaneFooterProps = PaneFooterBaseProps & + (PaneFooterChildrenContentsProps | PaneFooterBuiltinContentsProps); + +/** + * Renders a footer at the bottom of a pane. Props may be used to render + * at the start or end of the footer, or custom children can be passed. + * @example + * const footer = ( + * Cancel} + * renderEnd={} + * className={css.paneFooterClass} + * innerClassName={css.paneFooterContentClass} + * /> + * ); + * + * + * Pane Content + * + * @example + * + *
    + * + * + *
    + *
    + */ +export const PaneFooter: ForwardRefExoticComponent< + PropsWithoutRef & RefAttributes +>; +export default PaneFooter; diff --git a/lib/PaneFooter/index.d.ts b/lib/PaneFooter/index.d.ts new file mode 100644 index 000000000..ee24d0c04 --- /dev/null +++ b/lib/PaneFooter/index.d.ts @@ -0,0 +1 @@ +export { default, PaneFooterProps } from './PaneFooter'; diff --git a/lib/PaneHeader/PaneHeader.d.ts b/lib/PaneHeader/PaneHeader.d.ts new file mode 100644 index 000000000..71c9032f8 --- /dev/null +++ b/lib/PaneHeader/PaneHeader.d.ts @@ -0,0 +1,81 @@ +import { FunctionComponent, ReactNode, RefObject } from 'react'; +import { DropdownMenuFunction } from '../Dropdown/Dropdown'; + +export interface PaneHeaderDefaultProps { + /** + * Activates the action menu dropdown; function must return a node/component + * (probably a ``) + */ + actionMenu?: DropdownMenuFunction; + /** Adds an icon to the header. Expects an `` from `stripes-core`. */ + // TODO: explicitly require an once stripes-core specifies typings + appIcon?: ReactNode; + /** + * If a close (x) button should be rendered in the pane's header: + * - A `false` value will not render a button + * - A `true` value will render a button in the firstMenu (left side in ltr languages) + * - A `"last"` value will render a button in the lastMenu (right side in ltr languages) + */ + dismissible?: boolean | 'last'; + /** + * Component (probably a ``) to render at the beginning of the header + * (top left in ltr languages) + */ + firstMenu?: ReactNode; + /** Specify an ID to use for the PaneHeader */ + id?: string; + /** + * Component (probably a ``) to render at the end of the header + * (top right in ltr languages) + */ + lastMenu?: ReactNode; + /** Callback for when the pane is closed using its close button (see `dismissible` prop) */ + onClose?: () => void; + /** Add a subtitle to the pane, as a node or string (recommended). */ + paneSub?: ReactNode; + /** + * Add a title to the pane, as a node or string (recommended). + * This will be enclosed with a `

    ` for accessibility + */ + paneTitle?: ReactNode; + /** If the title should be auto focused on mount */ + paneTitleAutoFocus?: boolean; + /** A reference to the header of the pane */ + paneTitleRef?: RefObject; +} + +export interface PaneHeaderOverriddenProps { + /** Replace the entire builtin header with the provided node */ + header: ReactNode; +} + +export type PaneHeaderProps = + | PaneHeaderDefaultProps + | PaneHeaderOverriddenProps; + +/** + * A pane's header + * @example + * const renderHeader = renderProps => ( + * } + * lastMenu={} + * actionMenu={({ onToggle }) => { ... }} + * appIcon={} + * /> + * ); + * + * + * ... + * + * + * // Render a with no header + * + * ... + * + */ +export const PaneHeader: FunctionComponent; +export default PaneHeader; diff --git a/lib/PaneHeader/index.d.ts b/lib/PaneHeader/index.d.ts new file mode 100644 index 000000000..551144540 --- /dev/null +++ b/lib/PaneHeader/index.d.ts @@ -0,0 +1 @@ +export { default, PaneHeaderProps } from './PaneHeader'; diff --git a/lib/PaneHeaderIconButton/PaneHeaderIconButton.d.ts b/lib/PaneHeaderIconButton/PaneHeaderIconButton.d.ts new file mode 100644 index 000000000..829bf650f --- /dev/null +++ b/lib/PaneHeaderIconButton/PaneHeaderIconButton.d.ts @@ -0,0 +1,17 @@ +import { + ForwardRefExoticComponent, + PropsWithoutRef, + RefAttributes, +} from 'react'; +import { IconButtonProps } from '../IconButton/IconButton'; + +export type PaneHeaderIconButtonProps = IconButtonProps; + +/** + * `PaneHeaderIconButton` is a variant of `IconButton` and accepts the same props. + */ +export const PaneHeaderIconButton: ForwardRefExoticComponent< + PropsWithoutRef & + RefAttributes +>; +export default PaneHeaderIconButton; diff --git a/lib/PaneHeaderIconButton/index.d.ts b/lib/PaneHeaderIconButton/index.d.ts new file mode 100644 index 000000000..25aafb217 --- /dev/null +++ b/lib/PaneHeaderIconButton/index.d.ts @@ -0,0 +1 @@ +export { default, PaneHeaderIconButtonProps } from './PaneHeaderIconButton'; diff --git a/lib/PaneMenu/PaneMenu.d.ts b/lib/PaneMenu/PaneMenu.d.ts new file mode 100644 index 000000000..161c941a3 --- /dev/null +++ b/lib/PaneMenu/PaneMenu.d.ts @@ -0,0 +1,29 @@ +import { FunctionComponent, ReactNode } from 'react'; + +export interface PaneMenuProps { + /** The contents of the subheader */ + children: ReactNode; +} + +/** + * Wraps contents to prepare them for use as `firstMenu` or `lastMenu` on a `` + * @example + * const firstMenu = ( + * + * + * + * ); + * + * const lastMenu = ( + * + * + * + * ); + * + * ... + */ +export const PaneMenu: FunctionComponent; +export default PaneMenu; diff --git a/lib/PaneMenu/index.d.ts b/lib/PaneMenu/index.d.ts new file mode 100644 index 000000000..392f6c2b5 --- /dev/null +++ b/lib/PaneMenu/index.d.ts @@ -0,0 +1 @@ +export { default, PaneMenuProps } from './PaneMenu'; diff --git a/lib/PaneSubheader/PaneSubheader.d.ts b/lib/PaneSubheader/PaneSubheader.d.ts new file mode 100644 index 000000000..cb6eb383b --- /dev/null +++ b/lib/PaneSubheader/PaneSubheader.d.ts @@ -0,0 +1,23 @@ +import { FunctionComponent, ReactNode } from 'react'; + +export interface PaneSubheaderProps { + /** The contents of the subheader */ + children: ReactNode; +} + +/** + * Renders contents just below a pane's header but outside of the scrollable area + * @example + * const sbh = ( + * + * + * + * + * + * + * + * ); + * ... + */ +export const PaneSubheader: FunctionComponent; +export default PaneSubheader; diff --git a/lib/PaneSubheader/index.d.ts b/lib/PaneSubheader/index.d.ts new file mode 100644 index 000000000..8d0a0f1e4 --- /dev/null +++ b/lib/PaneSubheader/index.d.ts @@ -0,0 +1 @@ +export { default, PaneSubheaderProps } from './PaneSubheader'; diff --git a/lib/Paneset/Paneset.d.ts b/lib/Paneset/Paneset.d.ts new file mode 100644 index 000000000..ce41c7dd0 --- /dev/null +++ b/lib/Paneset/Paneset.d.ts @@ -0,0 +1,98 @@ +import { Component, CSSProperties, ReactNode } from 'react'; + +/** + * Maps a set of IDs (keys) to css widths (or `"fill"`) + */ +export type PanesetWidthSpecification = Record< + string, + CSSProperties['width'] | 'fill' +>; + +export interface PanesetOnLayoutParameters { + /** + * The type of change that occurred. + * - `'added'` when a pane is added to the set + * - `'remove'` when a pane is removed from the set + * - `'paneset-resized'` when the entire paneset is resized + * - `'resize'` when an individual pane is resized + */ + changeType: 'added' | 'removed' | 'paneset-resized' | 'resize'; + /** An object with keys pertaining to the panes being rendered */ + nextLayout: Record; + /** Whether or not there is an existing layout already cached (which would be preferred) */ + layoutCached: boolean; + /** Readonly copy of the paneset's layout cache */ + layoutCache: ReadonlyArray; + /** The contents of the cached layout for this situation */ + widths: PanesetWidthSpecification; +} + +export interface PanesetOnResizeParameters { + /** The current panes/sizes */ + currentLayout: PanesetWidthSpecification; + /** Readonly copy of the paneset's layout cache */ + layoutCache: ReadonlyArray; +} + +export interface PanesetProps { + /** The panes within the paneset */ + children?: ReactNode; + /** + * The initial size of the paneset, or `fill` to use all available space + */ + defaultWidth?: `${number}%` | 'fill'; + /** Specify an ID to use for the paneset */ + id?: string; + initialLayouts?: PanesetWidthSpecification[]; + /** If this paneset should not report to parent panesets, such as in a modal/layer */ + isRoot?: boolean; + /** A custom function to determine pane widths */ + onLayout?: ( + params: PanesetOnLayoutParameters + ) => PanesetWidthSpecification | null; + /** A callback for when pane(s) are resized */ + onResize?: (params: PanesetOnResizeParameters) => void; +} + +/** nested and static cannot both be true */ +export type PanePositionProps = + | { + /** If a paneset is nested within another; applies relative positioning */ + nested?: false; + /** Applies static positioning instead of absolute */ + static: boolean; + } + | { + /** If a paneset is nested within another; applies relative positioning */ + nested: boolean; + /** Applies static positioning instead of absolute */ + static?: false; + } + | { + /** If a paneset is nested within another; applies relative positioning */ + nested?: false; + /** Applies static positioning instead of absolute */ + static?: false; + }; + +/** + * A pane, central to FOLIO module layout. + * @example + * + * Pane Content + * + * } + * > + * Pane Content + * + */ +export class Paneset extends Component {} +export default Paneset; diff --git a/lib/Paneset/index.d.ts b/lib/Paneset/index.d.ts new file mode 100644 index 000000000..8ec12489d --- /dev/null +++ b/lib/Paneset/index.d.ts @@ -0,0 +1 @@ +export { default, PanesetProps } from './Paneset'; diff --git a/lib/Select/Select.d.ts b/lib/Select/Select.d.ts new file mode 100644 index 000000000..0dae48aae --- /dev/null +++ b/lib/Select/Select.d.ts @@ -0,0 +1,95 @@ +import { Component, ReactNode, RefObject } from 'react'; +import { FieldRenderProps } from 'react-final-form'; +import { RequireExactlyOne } from '../../util/typeUtils'; + +/** + * The default option type to be used, contains a label, potentially a value, and an option to disable + */ +export interface OptionType { + label: string; + value: ValueType; + disabled?: boolean; +} + +export interface SelectBaseProps { + /** If the field should auto-focus on mount */ + autoFocus?: boolean; + /** + * Allows passing `