diff --git a/types/bootstrap/bootstrap-tests.ts b/types/bootstrap/bootstrap-tests.ts index 17d6e088cf..21286ad5f4 100755 --- a/types/bootstrap/bootstrap-tests.ts +++ b/types/bootstrap/bootstrap-tests.ts @@ -2,8 +2,10 @@ // Alert // -------------------------------------------------------------------------------------- +// $ExpectType JQuery $("#alert").alert(); +// $ExpectType JQuery $("#alert").alert("close"); $("#alert").on("close.bs.alert", () => {}); @@ -12,20 +14,32 @@ $("#alert").on("close.bs.alert", () => {}); // Button // -------------------------------------------------------------------------------------- -// $("#button").button(); // must fail +// $ExpectError +$("#button").button(); +// $ExpectType JQuery $("#button").button("toggle"); // -------------------------------------------------------------------------------------- // Carousel // -------------------------------------------------------------------------------------- +// $ExpectType JQuery $("#carousel").carousel(); +// $ExpectType JQuery $("#carousel").carousel("pause"); $("#carousel").carousel(100); +$("#carousel").on("slide.bs.carousel", function(ev) { + const that: HTMLElement = this; + const from: number = ev.from; + const to: number = ev.to; + const direction: string = ev.direction; + const data: undefined = ev.data; +}); + $("#carousel").carousel({ interval: 5000, keyboard: true, @@ -37,20 +51,43 @@ $("#carousel").carousel({ pause: false, }); -$("#carousel").on("slide.bs.carousel", function(ev) { - const that: HTMLElement = this; - const from: number = ev.from; - const to: number = ev.to; - const direction: string = ev.direction; - const data: undefined = ev.data; +// -------------------------------------------------------------------------------------- +// Collapse +// -------------------------------------------------------------------------------------- + +// $ExpectType JQuery +$("#collapse").collapse(); + +// $ExpectType JQuery +$("#collapse").collapse("toggle"); + +$("#collapse").on("show.bs.collapse", () => {}); + +$("#collapse").collapse({ + parent: "#parent", + toggle: true, +}); + +$("#collapse").collapse({ + parent: document.body, +}); + +$("#collapse").collapse({ + parent: $("#parent"), +}); + +$("#collapse").collapse({ + toggle: false, }); // -------------------------------------------------------------------------------------- // Dropdown // -------------------------------------------------------------------------------------- +// $ExpectType JQuery $("#dropdown").dropdown(); +// $ExpectType JQuery $("#dropdown").dropdown("update"); $("#dropdown").on("hide.bs.dropdown", () => {}); @@ -66,7 +103,7 @@ $("#dropdown").dropdown({ }); $("#dropdown").dropdown({ - offset(offsets: BootstrapOffsetsExtend) { + offset(offsets: Bootstrap.OffsetsExtend) { if (!this.flip) return { popper: { left: 100 } }; return {}; @@ -81,8 +118,10 @@ $("#dropdown").dropdown({ // Modal // -------------------------------------------------------------------------------------- +// $ExpectType JQuery $("#modal").modal(); +// $ExpectType JQuery $("#modal").modal("show"); $("#modal").on("hide.bs.modal", () => {}); @@ -98,12 +137,90 @@ $("#modal").modal({ backdrop: "static", }); +// -------------------------------------------------------------------------------------- +// Popover +// -------------------------------------------------------------------------------------- + +// $ExpectType JQuery +$("#popover").popover(); + +// $ExpectType JQuery +$("#popover").popover("toggle"); + +$("#popover").on("show.bs.popover", () => {}); + +$("#popover").popover({}); + +$("#popover").popover({ + animation: false, + container: "#container", + delay: {show: 500, hide: 100}, + html: true, + placement: "auto", + selector: "[rel=\"popover\"]", + template: '
', + title: "Hello world", + trigger: "hover focus", + offset: 10, + fallbackPlacement: ["flip", "clockwise"], + boundary: "scrollParent", +}); + +$("#popover").popover({ + placement(this, popover, trigger) { + console.log(this.tip === popover); + console.log(this.element === trigger); + console.log(this.config.content); + return "left"; + }, +}); + +// -------------------------------------------------------------------------------------- +// Scrollspy +// -------------------------------------------------------------------------------------- + +// $ExpectType JQuery +$("#scrollspy").scrollspy(); + +// $ExpectType JQuery +$("#scrollspy").scrollspy("refresh"); + +$("#scrollspy").on("activate.bs.scrollspy", () => {}); + +$("#scrollspy").scrollspy({ + offset: 100, + target: "#navbar-example2", + method: "offset", +}); + +$("#scrollspy").scrollspy({ + target: document.getElementById("navbar-example2") as HTMLElement +}); + +$("#scrollspy").scrollspy({ + method: "position" +}); + +// -------------------------------------------------------------------------------------- +// Tab +// -------------------------------------------------------------------------------------- + +// $ExpectType JQuery +$("#someListItem").tab("show"); + +$("a[data-toggle=\"list\"]").on("shown.bs.tab", (e) => { + e.target; // newly activated tab + e.relatedTarget; // previous active tab +}); + // -------------------------------------------------------------------------------------- // Tooltip // -------------------------------------------------------------------------------------- +// $ExpectType JQuery $("#tooltip").tooltip(); +// $ExpectType JQuery $("#tooltip").tooltip("show"); $("#tooltip").on("hide.bs.tooltip", () => {}); @@ -149,6 +266,14 @@ $("#tooltip").tooltip({ }, }); +$("#tooltip").tooltip({ + placement(this, tooltip, trigger) { + // $ExpectError + console.log(this.config.content); // only for PopoverOption, not TooltipOption + return "left"; + }, +}); + $("#tooltip").tooltip({ selector: "[rel=\"tooltip\"]", }); @@ -176,7 +301,7 @@ $("#tooltip").tooltip({ }); $("#tooltip").tooltip({ - trigger: "focus hover", + trigger: "hover focus", }); $("#tooltip").tooltip({ diff --git a/types/bootstrap/index.d.ts b/types/bootstrap/index.d.ts index c158bbd807..88bcc66af8 100755 --- a/types/bootstrap/index.d.ts +++ b/types/bootstrap/index.d.ts @@ -4,45 +4,43 @@ // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped // TypeScript Version: 2.3 -// TODO: collapse, tab (list-group, navs), popovers, scrollspy +/// -/// +import * as Popper from "popper.js"; + +export as namespace Bootstrap; // -------------------------------------------------------------------------- // Some Types and Interfaces // -------------------------------------------------------------------------- -type BootstrapPlacement = "auto" | "top" | "bottom" | "left" | "right"; -type PopperBehavior = "flip" | "clockwise" | "counterclockwise"; +export type Placement = "auto" | "top" | "bottom" | "left" | "right"; -interface BootstrapDelay { +export type Trigger = "click" | "hover" | "focus" | "manual" | + "click hover" | "click focus" | "hover focus" | + "click hover focus"; + +export interface Delay { show: number; hide: number; } -interface BootstrapTooltipInstance { - config: BootstrapTooltipOption; +export interface TooltipInstance { + config: T; element: Element; tip: HTMLElement; } -interface BootstrapOffsetExtend { - top?: number; - left?: number; - width?: number; - height?: number; -} - -interface BootstrapOffsetsExtend { - popper?: BootstrapOffsetExtend; - reference?: BootstrapOffsetExtend; +export interface OffsetsExtend { + popper?: Partial; + reference?: Partial; } // -------------------------------------------------------------------------------------- // Options Interfaces // -------------------------------------------------------------------------------------- -interface BootstrapCarouselOption { +export interface CarouselOption { /** * The amount of time to delay between automatically cycling an item. If false, carousel will not automatically cycle. * @@ -75,14 +73,32 @@ interface BootstrapCarouselOption { wrap?: boolean; } -interface BootstrapDropdownOption { +export interface CollapseOption { + /** + * If parent is provided, then all collapsible elements under the specified parent will be closed when + * this collapsible item is shown. (similar to traditional accordion behavior - this is dependent on the card class). + * The attribute has to be set on the target collapsible area. + * + * @default "" + */ + parent?: string | JQuery | Element; + + /** + * Toggles the collapsible element on invocation. + * + * @default true + */ + toggle?: boolean; +} + +export interface DropdownOption { /** * Offset of the dropdown relative to its target. * For more information refer to Popper.js's offset docs. * * @default 0 */ - offset?: number | string | ((this: BootstrapDropdownOption, offset: BootstrapOffsetsExtend) => BootstrapOffsetsExtend); + offset?: number | string | ((this: DropdownOption, offset: OffsetsExtend) => OffsetsExtend); /** * Allow Dropdown to flip in case of an overlapping on the reference element. @@ -99,10 +115,10 @@ interface BootstrapDropdownOption { * * @default "scrollParent" */ - boundary?: "viewport" | "window" | "scrollParent" | HTMLElement; + boundary?: Popper.Boundary | HTMLElement; } -interface BootstrapModalOption { +export interface ModalOption { /** * Includes a modal-backdrop element. * Alternatively, specify static for a backdrop which doesn't close the modal on click. @@ -133,36 +149,69 @@ interface BootstrapModalOption { show?: boolean; } -interface BootstrapTooltipOption { +export interface PopoverOption extends TooltipOption { /** - * Apply a CSS fade transition to the tooltip. + * Default content value if data-content attribute isn't present. + * If a function is given, it will be called with its this reference + * set to the element that the popover is attached to. + */ + content?: string | Element | ((this: Element) => string | Element); +} + +export interface ScrollspyOption { + /** + * TODO: https://github.com/twbs/bootstrap/issues/25799 + * + * @default "auto" + */ + method?: "auto" | "offset" | "position"; + + /** + * Pixels to offset from top when calculating position of scroll. + * + * @default 10 + */ + offset?: number; + + /** + * A selector of the parent element or the parent element itself + * of any Bootstrap `.nav` or `.list-group` component. + * + * @default "" + */ + target?: string | Element; +} + +export interface TooltipOption { + /** + * Apply a CSS fade transition to the tooltip or popover. * * @default true */ animation?: boolean; /** - * Appends the tooltip to a specific element. Example: `container: 'body'`. - * This option is particularly useful in that it allows you to position the tooltip + * Appends the tooltip or popover to a specific element. Example: `container: 'body'`. + * This option is particularly useful in that it allows you to position the tooltip or popover * in the flow of the document near the triggering element - which will prevent - * the tooltip from floating away from the triggering element during a window resize. + * it from floating away from the triggering element during a window resize. * * @default false */ container?: string | Element | false; /** - * Delay showing and hiding the tooltip (ms) - does not apply to manual trigger type. + * Delay showing and hiding the tooltip or popover (ms) - does not apply to manual trigger type. * If a number is supplied, delay is applied to both hide/show. * Object structure is: `delay: { "show": 500, "hide": 100 }`. * * @default 0 */ - delay?: number | BootstrapDelay; + delay?: number | Delay; /** - * Allow HTML in the tooltip. - * If true, HTML tags in the tooltip's title will be rendered in the tooltip. + * Allow HTML in the tooltip or popover. + * If true, HTML tags will be rendered in the tooltip or popover. * If false, jQuery's text method will be used to insert content into the DOM. * Use text if you're worried about XSS attacks. * @@ -171,18 +220,18 @@ interface BootstrapTooltipOption { html?: boolean; /** - * How to position the tooltip - auto | top | bottom | left | right. - * When auto is specified, it will dynamically reorient the tooltip. + * How to position the tooltip or popover - auto | top | bottom | left | right. + * When auto is specified, it will dynamically reorient the tooltip or popover. * When a function is used to determine the placement, it is called with - * the tooltip DOM node as its first argument and the triggering element DOM node as its second. - * The this context is set to the tooltip instance. + * the tooltip or popover DOM node as its first argument and the triggering element DOM node as its second. + * The this context is set to the tooltip or popover instance. * * @default "top" */ - placement?: BootstrapPlacement | ((this: BootstrapTooltipInstance, tooltip: HTMLElement, trigger: Element) => BootstrapPlacement); + placement?: Placement | ((this: TooltipInstance, node: HTMLElement, trigger: Element) => Placement); /** - * If a selector is provided, tooltip objects will be delegated to the specified targets. + * If a selector is provided, tooltip or popover objects will be delegated to the specified targets. * In practice, this is used to enable dynamic HTML content to have popovers added. * * @default false @@ -190,41 +239,40 @@ interface BootstrapTooltipOption { selector?: string | false; /** - * Base HTML to use when creating the tooltip. The tooltip's title will be injected into - * the `.tooltip-inner`. The `.arrow` will become the tooltip's arrow. - * The outermost wrapper element should have the `.tooltip` class and `role="tooltip"`. + * Base HTML to use when creating the tooltip or popover. The tooltip's (resp., popover's) title will be injected into + * the `.tooltip-inner` (resp., `.popover-header`). The `.arrow` will become the tooltip's (resp., popover's) arrow. + * The outermost wrapper element should have the `.tooltip` (resp., .popover) class and `role="tooltip"`. * * @default '' + * @default '' */ template?: string; /** * Default title value if title attribute isn't present. * If a function is given, it will be called with its this reference set to the element - * that the tooltip is attached to. + * that the tooltip or popover is attached to. * * @default "" */ - title?: string | Element | ((this: Element) => string); + title?: string | Element | ((this: Element) => string | Element); /** - * How tooltip is triggered - click | hover | focus | manual. You may pass multiple triggers; separate them with a space. - * 'manual' indicates that the tooltip will be triggered programmatically via the .tooltip('show'), .tooltip('hide') and - * .tooltip('toggle') methods; this value cannot be combined with any other trigger. - * 'hover' on its own will result in tooltips that cannot be triggered via the keyboard, and should only be used if - * alternative methods for conveying the same information for keyboard users is present. + * How tooltip or popover is triggered - click | hover | focus | manual. You may pass multiple triggers; separate them with a space. + * 'manual' indicates that the tooltip will be triggered programmatically; this value cannot be combined with any other trigger. + * 'hover' should only be used if alternative methods for conveying the same information for keyboard users is present. * - * @default "hover focus" + * @default tooltip: "hover focus", popover: "click" */ - trigger?: string; + trigger?: Trigger; /** - * Offset of the tooltip relative to its target. + * Offset of the tooltip or popover relative to its target. * For more information refer to Popper.js's offset docs. * * @default 0 */ - offset?: number | string; + offset?: number | string; /** * Allow to specify which position Popper will use on fallback. @@ -232,24 +280,24 @@ interface BootstrapTooltipOption { * * @default "flip" */ - fallbackPlacement?: PopperBehavior | PopperBehavior[]; + fallbackPlacement?: Popper.Behavior | ReadonlyArray; /** - * Overflow constraint boundary of the tooltip. + * Overflow constraint boundary of the tooltip or popover. * Accepts the values of 'viewport', 'window', 'scrollParent', * or an HTMLElement reference (JavaScript only). * For more information refer to Popper.js's preventOverflow docs. * * @default "scrollParent" */ - boundary?: "viewport" | "window" | "scrollParent" | HTMLElement; + boundary?: Popper.Boundary | HTMLElement; } // -------------------------------------------------------------------------------------- // Events // -------------------------------------------------------------------------------------- -interface BootstrapCarouselEventHandler extends JQuery.Event { +export interface CarouselEventHandler extends JQuery.Event { /** * The direction in which the carousel is sliding. */ @@ -266,34 +314,53 @@ interface BootstrapCarouselEventHandler extends JQuery.Event extends Iterable { - alert(action?: "close" | "dispose"): this; +declare global { + interface JQuery extends Iterable { + alert(action?: "close" | "dispose"): this; - button(action: "toggle" | "dispose"): this; + button(action: "toggle" | "dispose"): this; - carousel(action: "cycle" | "pause" | number | "prev" | "next" | "dispose"): this; - carousel(options?: BootstrapCarouselOption): this; + carousel(action: "cycle" | "pause" | number | "prev" | "next" | "dispose"): this; + carousel(options?: CarouselOption): this; - dropdown(action: "toggle" | "update" | "dispose"): this; - dropdown(options?: BootstrapDropdownOption): this; + collapse(action: "toggle" | "show" | "hide" | "dispose"): this; + collapse(options?: CollapseOption): this; - modal(action: "toggle" | "show" | "hide" | "handleUpdate" | "dispose"): this; - modal(options?: BootstrapModalOption): this; + dropdown(action: "toggle" | "update" | "dispose"): this; + dropdown(options?: DropdownOption): this; - tooltip(action: "show" | "hide" | "toggle" | "dispose" | "enable" | "disable" | "toggleEnabled" | "update"): this; - tooltip(options?: BootstrapTooltipOption): this; + modal(action: "toggle" | "show" | "hide" | "handleUpdate" | "dispose"): this; + modal(options?: ModalOption): this; - on(events: BootstrapCarouselEvent, handler: JQuery.EventHandlerBase>): this; - on(events: BootstrapAlertEvent | BootstrapDropdownEvent | BootstrapModalEvent | BootstrapTooltipEvent, - handler: JQuery.EventHandler): this; + popover(action: "show" | "hide" | "toggle" | "dispose" | "enable" | "disable" | "toggleEnabled" | "update"): this; + popover(options?: PopoverOption): this; + + scrollspy(action: "refresh" | "dispose"): this; + scrollspy(options?: ScrollspyOption): this; + + tab(action: "show" | "dispose"): this; + + tooltip(action: "show" | "hide" | "toggle" | "dispose" | "enable" | "disable" | "toggleEnabled" | "update"): this; + tooltip(options?: TooltipOption): this; + + on(events: CarouselEvent, handler: JQuery.EventHandlerBase>): this; + on(events: + AlertEvent | CollapseEvent | DropdownEvent | ModalEvent | + PopoverEvent | ScrollspyEvent | TapEvent | TooltipEvent, + handler: JQuery.EventHandler): this; + } } diff --git a/types/bootstrap/package.json b/types/bootstrap/package.json new file mode 100644 index 0000000000..af84860ef1 --- /dev/null +++ b/types/bootstrap/package.json @@ -0,0 +1,6 @@ +{ + "private": true, + "dependencies": { + "popper.js": "^1.14.1" + } +} \ No newline at end of file