/* * aussom-bs: Bootstrap 5 Library for Aussom-Script */ /* --- Enums --- */ /** * Bootstrap responsive size breakpoints. * (sm, md, lg, xl, xxl) */ enum bsSize { sm; md; lg; xl; xxl; } /** * Bootstrap container size breakpoints including fluid. * (sm, md, lg, xl, xxl, fluid) */ enum bsContainerSize { sm; md; lg; xl; xxl; fluid; } /** * Bootstrap color variant names. * (primary, secondary, success, danger, warning, info, light, dark) */ enum bsVariant { primary; secondary; success; danger; warning; info; light; dark; } /** * Bootstrap spinner types. * (border, grow) */ enum bsSpinnerType { border; grow; } /** * Bootstrap nav styles. * (tabs, pills) */ enum bsNavStyle { tabs; pills; } /** * Bootstrap card image positions. * (top, bottom, overlay) */ enum bsCardImgPos { top; bottom; overlay; } /** * Bootstrap dropdown direction variants. * (dropdown, dropup, dropend, dropstart) */ enum bsDropDirection { dropdown; dropup; dropend; dropstart; } /** * Bootstrap navbar color scheme themes. * (light, dark) */ enum bsNavbarTheme { light; dark; } /** * Bootstrap navbar expand breakpoints. * (sm, md, lg, xl, xxl) */ enum bsNavbarExpand { sm; md; lg; xl; xxl; } /** * Bootstrap toast container position values. * (topStart, topCenter, topEnd, middleStart, middleCenter, * middleEnd, bottomStart, bottomCenter, bottomEnd) */ enum bsToastPos { topStart; topCenter; topEnd; middleStart; middleCenter; middleEnd; bottomStart; bottomCenter; bottomEnd; } /** * Bootstrap button type attribute values. * (button, submit, reset) */ enum bsButtonType { button; submit; reset; } /* --- Layout --- */ /** * Bootstrap container div. Wraps page content with a centered, * fixed-width (or fluid) layout. Extends Div. */ class BsContainer : Div { /** * Creates a Bootstrap container. * @p Size is an optional bsContainerSize enum value for the * container width. (sm, md, lg, xl, xxl, fluid) Omit for * a default fixed-width container. * @r This object. */ public BsContainer(string Size = null) { this.Div(); if (Size != null) { this.setAttr('class', 'container-' + Size); } else { this.setAttr('class', 'container'); } } } /** * Bootstrap grid row. Must contain BsCol children. Extends Div. */ class BsRow : Div { /** * Creates a Bootstrap grid row. * @p Children is an optional list of child objects to add. * @r This object. */ public BsRow(list Children = null) { this.Div(); this.setAttr('class', 'row'); if (Children != null) { for (child : Children) { this.add(child); } } } } /** * Bootstrap grid column. Place inside a BsRow. Extends Div. */ class BsCol : Div { /** * Creates a Bootstrap grid column. * @p NumberOfCols is an optional string with the column span * width (1-12). Omit for an auto-width column. * @p Size is an optional bsSize enum breakpoint. (sm, md, lg, * xl, xxl) Omit to apply at all sizes. * @r This object. */ public BsCol(string NumberOfCols = null, string Size = null) { this.Div(); className = 'col'; if (Size != null) { className += '-' + Size; } if (NumberOfCols != null) { className += '-' + NumberOfCols; } this.setAttr('class', className); } } /* --- Typography & Content --- */ /** * Bootstrap display heading. Renders larger, decorative headings. * Extends Div. */ class BsDisplay : Div { /** * Creates a Bootstrap display heading. * @p Level is a string with the display level (1-6). * @p Text is an optional string with the heading text. * @r This object. */ public BsDisplay(string Level, string Text = null) { this.Div(); this.setAttr('class', 'display-' + Level); if (Text != null) { this.add(new Text(Text)); } } } /** * Bootstrap lead paragraph. Renders text slightly larger and * lighter than body copy. Extends P. */ class BsLead : P { /** * Creates a Bootstrap lead paragraph. * @p Text is an optional string with the paragraph text. * @r This object. */ public BsLead(string Text = null) { this.P(Text); this.addClass('lead'); } } /** * Bootstrap blockquote. Displays quoted text with an optional * footer attribution. Extends Div. */ class BsBlockquote : Div { /** * Creates a Bootstrap blockquote. * @p Text is the string with the quoted text. * @p Footer is an optional string with the attribution text. * @r This object. */ public BsBlockquote(string Text, string Footer = null) { this.Div(); quote = new Div(); quote.setAttr('class', 'blockquote'); quote.add(new P(Text)); if (Footer != null) { foot = new Div(); foot.setAttr('class', 'blockquote-footer'); foot.add(new Text(Footer)); quote.add(foot); } this.add(quote); } } /** * Bootstrap muted text span. Renders text in a subdued gray color. * Extends Span. */ class BsMuted : Span { /** * Creates a Bootstrap muted text span. * @p Text is an optional string with the text content. * @r This object. */ public BsMuted(string Text = null) { this.Span(Text); this.addClass('text-muted'); } } /* --- Images --- */ /** * Bootstrap image. Supports responsive, thumbnail, and rounded * styles. Extends Img. */ class BsImage : Img { /** * Creates a Bootstrap image. * @p Src is a string with the image source URL. * @p Alt is an optional string with the alternative text. * @p Style is an optional string with the visual style. * (fluid, thumbnail, rounded) Defaults to fluid. * @r This object. */ public BsImage(string Src, string Alt = null, string Style = 'fluid') { this.Img(Src, Alt); this.addClass('img-' + Style); } } /** * Bootstrap figure. Groups an image with a caption. Extends Div. */ class BsFigure : Div { /** * Creates a Bootstrap figure with image and optional caption. * @p Src is a string with the image source URL. * @p Alt is an optional string with the alternative text. * @p Caption is an optional string with the caption text. * @r This object. */ public BsFigure(string Src, string Alt = null, string Caption = null) { this.Div(); this.setAttr('class', 'figure'); img = new BsImage(Src, Alt, 'fluid'); img.addClass('figure-img rounded'); this.add(img); if (Caption != null) { cap = new Div(); cap.setAttr('class', 'figure-caption'); cap.add(new Text(Caption)); this.add(cap); } } } /* --- Tables --- */ /** * Bootstrap table. Applies Bootstrap table styles to a standard * HTML table element. Extends Table. */ class BsTable : Table { /** * Creates a Bootstrap table. * @p Variant is an optional bsVariant enum for the table color. * (primary, secondary, success, danger, warning, info, light, dark) * @p Striped is an optional bool; true adds alternating row shading. * @p Hover is an optional bool; true highlights rows on hover. * @p Bordered is an optional bool; true adds borders to all cells. * @p Small is an optional bool; true reduces cell padding. * @r This object. */ public BsTable(string Variant = null, bool Striped = false, bool Hover = false, bool Bordered = false, bool Small = false) { this.Table(); this.setAttr('class', 'table'); if (Variant != null) { this.addClass('table-' + Variant); } if (Striped) { this.addClass('table-striped'); } if (Hover) { this.addClass('table-hover'); } if (Bordered) { this.addClass('table-bordered'); } if (Small) { this.addClass('table-sm'); } } } /** * Bootstrap table header section. Extends Thead. */ class BsTableHead : Thead { /** * Creates a Bootstrap table head. * @p Variant is an optional bsVariant enum for the header color. * (primary, secondary, success, danger, warning, info, light, dark) * @r This object. */ public BsTableHead(string Variant = null) { this.Thead(); if (Variant != null) { this.setAttr('class', 'table-' + Variant); } } } /** * Bootstrap table body section. Extends Tbody. */ class BsTableBody : Tbody { /** * Creates a Bootstrap table body. * @r This object. */ public BsTableBody() { this.Tbody(); } } /** * Bootstrap table row. Extends Tr. */ class BsTableRow : Tr { /** * Creates a Bootstrap table row. * @p Variant is an optional bsVariant enum for the row color. * (primary, secondary, success, danger, warning, info, light, dark) * @r This object. */ public BsTableRow(string Variant = null) { this.Tr(); if (Variant != null) { this.setAttr('class', 'table-' + Variant); } } } /** * Bootstrap table data cell. Extends Td. */ class BsTableCell : Td { /** * Creates a Bootstrap table data cell. * @p Text is an optional string with the cell content. * @p Variant is an optional bsVariant enum for the cell color. * (primary, secondary, success, danger, warning, info, light, dark) * @r This object. */ public BsTableCell(string Text = null, string Variant = null) { this.Td(); if (Text != null) { this.add(new Text(Text)); } if (Variant != null) { this.setAttr('class', 'table-' + Variant); } } } /** * Bootstrap table header cell. Extends Th. */ class BsTableHeadCell : Th { /** * Creates a Bootstrap table header cell. * @p Text is an optional string with the header cell content. * @r This object. */ public BsTableHeadCell(string Text = null) { this.Th(); if (Text != null) { this.add(new Text(Text)); } } } /* --- Alerts --- */ /** * Bootstrap alert message box. Supports all color variants and * an optional dismiss button. Extends Div. */ class BsAlert : Div { /** * Creates a Bootstrap alert. * @p Variant is a bsVariant enum for the alert color. * (primary, secondary, success, danger, warning, info, light, dark) * @p Message is an optional string with the alert message. * @p Dismissible is an optional bool; true adds a close button. * @r This object. */ public BsAlert(string Variant = 'primary', string Message = null, bool Dismissible = false) { this.Div(); cls = 'alert alert-' + Variant; if (Dismissible) { cls += ' alert-dismissible fade show'; } this.setAttr('class', cls); this.setAttr('role', 'alert'); if (Message != null) { this.add(new Text(Message)); } if (Dismissible) { btn = new BsCloseButton(); btn.setAttr('data-bs-dismiss', 'alert'); this.add(btn); } } } /* --- Badges --- */ /** * Bootstrap badge. A small label component for counts or status * indicators. Extends Span. */ class BsBadge : Span { /** * Creates a Bootstrap badge. * @p Variant is a bsVariant enum for the badge background color. * (primary, secondary, success, danger, warning, info, light, dark) * @p Text is an optional string with the badge label. * @p Pill is an optional bool; true renders a pill-shaped badge. * @r This object. */ public BsBadge(string Variant = 'primary', string Text = null, bool Pill = false) { this.Span(Text); cls = 'badge bg-' + Variant; if (Pill) { cls += ' rounded-pill'; } this.setAttr('class', cls); } } /* --- Breadcrumbs --- */ /** * Bootstrap breadcrumb navigation container. Extends Nav. */ class BsBreadcrumb : Nav { public items = null; /** * Creates a Bootstrap breadcrumb nav. * @r This object. */ public BsBreadcrumb() { this.Nav(); this.setAttr('aria-label', 'breadcrumb'); ol = new Div(); ol.setAttr('class', 'breadcrumb'); this.add(ol); // Store reference for adding items this.items = ol; } /** * Adds a breadcrumb item to the nav. * @p Item is a BsBreadcrumbItem to add. * @r This object. */ public addItem(object Item) { this.items.add(Item); return this; } } /** * Bootstrap breadcrumb item. Represents a single step in the * breadcrumb trail. Extends Span. */ class BsBreadcrumbItem : Span { /** * Creates a Bootstrap breadcrumb item. * @p Text is the string label for this breadcrumb step. * @p Href is an optional string URL. Omit for the active item. * @p Active is an optional bool; true marks this as the current page. * @r This object. */ public BsBreadcrumbItem(string Text, string Href = null, bool Active = false) { this.Span(); cls = 'breadcrumb-item'; if (Active) { cls += ' active'; this.setAttr('aria-current', 'page'); this.add(new Text(Text)); } else { link = new A(Text, Href); this.add(link); } this.setAttr('class', cls); } } /* --- Buttons --- */ /** * Bootstrap close button. A styled X button used to dismiss * components such as alerts and modals. Extends Button. */ class BsCloseButton : Button { /** * Creates a Bootstrap close button. * @p AriaLabel is an optional accessible label string. * Defaults to 'Close'. * @r This object. */ public BsCloseButton(string AriaLabel = 'Close') { this.Button(); this.setAttr('class', 'btn-close'); this.setAttr('type', 'button'); this.setAttr('aria-label', AriaLabel); } } /** * Bootstrap button. Supports all color variants, outline style, * sizes, and disabled state. Extends Button. */ class BsButton : Button { /** * Creates a Bootstrap button. * @p Variant is a bsVariant enum for the button color. * (primary, secondary, success, danger, warning, info, light, dark) * @p Text is an optional string with the button label. * @p Outline is an optional bool; true renders an outline-style button. * @p Size is an optional bsSize enum for the button size. (sm, lg) * @p Disabled is an optional bool; true disables the button. * @p Type is an optional bsButtonType enum for the button type attribute. * (button, submit, reset) Defaults to button. * @r This object. */ public BsButton(string Variant = 'primary', string Text = null, bool Outline = false, string Size = null, bool Disabled = false, string Type = 'button') { this.Button(); if (Outline) { base = 'btn btn-outline-' + Variant; } else { base = 'btn btn-' + Variant; } this.setAttr('class', base); this.setAttr('type', '' + Type); if (Size != null) { this.addClass('btn-' + Size); } if (Disabled) { this.setAttr('disabled', 'disabled'); } if (Text != null) { this.add(new Text(Text)); } } } /** * Bootstrap button group. Groups multiple buttons on a single line. * Extends Div. */ class BsButtonGroup : Div { /** * Creates a Bootstrap button group. * @p Vertical is an optional bool; true stacks buttons vertically. * @p Size is an optional bsSize enum for the group size. (sm, lg) * @r This object. */ public BsButtonGroup(bool Vertical = false, string Size = null) { this.Div(); if (Vertical) { cls = 'btn-group-vertical'; } else { cls = 'btn-group'; } if (Size != null) { cls += ' btn-group-' + Size; } this.setAttr('class', cls); this.setAttr('role', 'group'); } } /** * Bootstrap button toolbar. Groups multiple button groups together. * Extends Div. */ class BsButtonToolbar : Div { /** * Creates a Bootstrap button toolbar. * @r This object. */ public BsButtonToolbar() { this.Div(); this.setAttr('class', 'btn-toolbar'); this.setAttr('role', 'toolbar'); } } /* --- Cards --- */ /** * Bootstrap card. A flexible content container with optional * header, body, footer, and image sections. Extends Div. */ class BsCard : Div { /** * Creates a Bootstrap card. * @r This object. */ public BsCard() { this.Div(); this.setAttr('class', 'card'); } } /** * Bootstrap card header section. Extends Div. */ class BsCardHeader : Div { /** * Creates a Bootstrap card header. * @p Text is an optional string with the header text. * @r This object. */ public BsCardHeader(string Text = null) { this.Div(); this.setAttr('class', 'card-header'); if (Text != null) { this.add(new Text(Text)); } } } /** * Bootstrap card body section. Extends Div. */ class BsCardBody : Div { /** * Creates a Bootstrap card body. * @r This object. */ public BsCardBody() { this.Div(); this.setAttr('class', 'card-body'); } } /** * Bootstrap card footer section. Extends Div. */ class BsCardFooter : Div { /** * Creates a Bootstrap card footer. * @p Text is an optional string with the footer text. * @r This object. */ public BsCardFooter(string Text = null) { this.Div(); this.setAttr('class', 'card-footer'); if (Text != null) { this.add(new Text(Text)); } } } /** * Bootstrap card title heading. Extends H5. */ class BsCardTitle : H5 { /** * Creates a Bootstrap card title. * @p Text is an optional string with the title text. * @r This object. */ public BsCardTitle(string Text = null) { this.H5(Text); this.addClass('card-title'); } } /** * Bootstrap card subtitle heading. Extends H6. */ class BsCardSubtitle : H6 { /** * Creates a Bootstrap card subtitle. * @p Text is an optional string with the subtitle text. * @r This object. */ public BsCardSubtitle(string Text = null) { this.H6(Text); this.addClass('card-subtitle mb-2 text-muted'); } } /** * Bootstrap card text paragraph. Extends P. */ class BsCardText : P { /** * Creates a Bootstrap card text paragraph. * @p Text is an optional string with the paragraph text. * @r This object. */ public BsCardText(string Text = null) { this.P(Text); this.addClass('card-text'); } } /** * Bootstrap card image. Positions an image at the top, bottom, * or as an overlay inside a card. Extends Img. */ class BsCardImg : Img { /** * Creates a Bootstrap card image. * @p Src is a string with the image source URL. * @p Alt is an optional string with the alternative text. * @p Position is an optional bsCardImgPos enum. * (top, bottom, overlay) Defaults to top. * @r This object. */ public BsCardImg(string Src, string Alt = null, string Position = 'top') { this.Img(Src, Alt); if (Position == bsCardImgPos.overlay) { this.addClass('card-img'); } else { this.addClass('card-img-' + Position); } } } /** * Bootstrap card group. Lays multiple cards side by side with * equal width and height. Extends Div. */ class BsCardGroup : Div { /** * Creates a Bootstrap card group. * @r This object. */ public BsCardGroup() { this.Div(); this.setAttr('class', 'card-group'); } } /* --- List Groups --- */ /** * Bootstrap list group. A series of styled list items. Extends Ul. */ class BsListGroup : Ul { /** * Creates a Bootstrap list group. * @p Flush is an optional bool; true removes the border and rounded * corners for a flush appearance inside another element. * @p Horizontal is an optional bool; true lays items side by side. * @r This object. */ public BsListGroup(bool Flush = false, bool Horizontal = false) { this.Ul(); cls = 'list-group'; if (Flush) { cls += ' list-group-flush'; } if (Horizontal) { cls += ' list-group-horizontal'; } this.setAttr('class', cls); } } /** * Bootstrap list group item. A single item within a BsListGroup. * Extends Span. */ class BsListGroupItem : Span { /** * Creates a Bootstrap list group item. * @p Text is an optional string with the item text. * @p Variant is an optional bsVariant enum for the item color. * (primary, secondary, success, danger, warning, info, light, dark) * @p Active is an optional bool; true highlights this item as selected. * @p Disabled is an optional bool; true grays out the item. * @r This object. */ public BsListGroupItem(string Text = null, string Variant = null, bool Active = false, bool Disabled = false) { this.Span(); cls = 'list-group-item'; if (Variant != null) { cls += ' list-group-item-' + Variant; } if (Active) { cls += ' active'; } if (Disabled) { cls += ' disabled'; } this.setAttr('class', cls); if (Text != null) { this.add(new Text(Text)); } } } /* --- Navs & Tabs --- */ /** * Bootstrap nav list. Base navigation component supporting tabs * and pills styles. Extends Ul. */ class BsNav : Ul { /** * Creates a Bootstrap nav. * @p Style is an optional bsNavStyle enum. (tabs, pills) * Omit for a basic nav. * @p Fill is an optional bool; true expands items to fill * all available width. * @p Justified is an optional bool; true makes all items * equal width. * @r This object. */ public BsNav(string Style = null, bool Fill = false, bool Justified = false) { this.Ul(); cls = 'nav'; if (Style != null) { cls += ' nav-' + Style; } if (Fill) { cls += ' nav-fill'; } if (Justified) { cls += ' nav-justified'; } this.setAttr('class', cls); } } /** * Bootstrap nav item. A list item wrapper inside a BsNav. Extends Span. */ class BsNavItem : Span { /** * Creates a Bootstrap nav item. * @r This object. */ public BsNavItem() { this.Span(); this.setAttr('class', 'nav-item'); } } /** * Bootstrap nav link. The clickable anchor element inside a BsNavItem. * Extends A. */ class BsNavLink : A { /** * Creates a Bootstrap nav link. * @p Text is a string with the link label. * @p Href is an optional string with the link URL. * @p Active is an optional bool; true marks the link as the current page. * @p Disabled is an optional bool; true grays out the link. * @r This object. */ public BsNavLink(string Text, string Href = '#', bool Active = false, bool Disabled = false) { this.A(Text, Href); cls = 'nav-link'; if (Active) { cls += ' active'; } if (Disabled) { cls += ' disabled'; } this.setAttr('class', cls); if (Active) { this.setAttr('aria-current', 'page'); } } } /** * Bootstrap tab content wrapper. Contains BsTabPane children. * Extends Div. */ class BsTabContent : Div { /** * Creates a Bootstrap tab content wrapper. * @r This object. */ public BsTabContent() { this.Div(); this.setAttr('class', 'tab-content'); } } /** * Bootstrap tab pane. A single panel shown when its matching * nav tab is active. Extends Div. */ class BsTabPane : Div { /** * Creates a Bootstrap tab pane. * @p Id is a string with the pane element ID. * @p Active is an optional bool; true shows this pane initially. * @r This object. */ public BsTabPane(string Id, bool Active = false) { this.Div(); cls = 'tab-pane fade'; if (Active) { cls += ' show active'; } this.setAttr('class', cls); this.setId(Id); } } /* --- Navbar --- */ /** * Bootstrap navbar. A responsive navigation header. Extends Nav. */ class BsNavbar : Nav { /** * Creates a Bootstrap navbar. * @p Theme is an optional bsNavbarTheme enum. (light, dark) * Defaults to light. * @p BgVariant is an optional bsVariant enum for the background * color. (primary, secondary, success, danger, warning, info, * light, dark) * @p Expand is an optional bsNavbarExpand enum for the breakpoint * at which the navbar expands. (sm, md, lg, xl, xxl) * Defaults to lg. * @r This object. */ public BsNavbar(string Theme = 'light', string BgVariant = 'light', string Expand = 'lg') { this.Nav(); cls = 'navbar navbar-expand-' + Expand; cls += ' navbar-' + Theme; cls += ' bg-' + BgVariant; this.setAttr('class', cls); } } /** * Bootstrap navbar brand. The logo or site name link. Extends A. */ class BsNavbarBrand : A { /** * Creates a Bootstrap navbar brand link. * @p Text is a string with the brand label. * @p Href is an optional string with the brand URL. Defaults to '#'. * @r This object. */ public BsNavbarBrand(string Text, string Href = '#') { this.A(Text, Href); this.addClass('navbar-brand'); } } /** * Bootstrap navbar toggler button. Reveals collapsed nav content * on smaller screens. Extends Button. */ class BsNavbarToggler : Button { /** * Creates a Bootstrap navbar toggler button. * @p Target is a string with the ID of the collapse target. * @r This object. */ public BsNavbarToggler(string Target) { this.Button(); this.setAttr('class', 'navbar-toggler'); this.setAttr('type', 'button'); this.setAttr('data-bs-toggle', 'collapse'); this.setAttr('data-bs-target', '#' + Target); this.setAttr('aria-controls', Target); this.setAttr('aria-expanded', 'false'); this.setAttr('aria-label', 'Toggle navigation'); icon = new Span(); icon.setAttr('class', 'navbar-toggler-icon'); this.add(icon); } } /** * Bootstrap navbar collapse wrapper. Contains nav items that * collapse on small screens. Extends Div. */ class BsNavbarCollapse : Div { /** * Creates a Bootstrap navbar collapse div. * @p Id is a string with the element ID referenced by BsNavbarToggler. * @r This object. */ public BsNavbarCollapse(string Id) { this.Div(); this.setAttr('class', 'collapse navbar-collapse'); this.setId(Id); } } /** * Bootstrap navbar nav list. A Ul that holds nav items inside * a navbar. Extends Ul. */ class BsNavbarNav : Ul { /** * Creates a Bootstrap navbar nav list. * @r This object. */ public BsNavbarNav() { this.Ul(); this.setAttr('class', 'navbar-nav'); } } /* --- Pagination --- */ /** * Bootstrap pagination nav. Wraps a list of page link items. * Extends Nav. */ class BsPagination : Nav { public items = null; /** * Creates a Bootstrap pagination nav. * @p Size is an optional bsSize enum for the pagination size. * (sm, lg) * @r This object. */ public BsPagination(string Size = null) { this.Nav(); this.setAttr('aria-label', 'Page navigation'); ul = new Ul(); cls = 'pagination'; if (Size != null) { cls += ' pagination-' + Size; } ul.setAttr('class', cls); this.add(ul); this.items = ul; } /** * Adds a BsPageItem to the pagination list. * @p Item is a BsPageItem to add. * @r This object. */ public addItem(object Item) { this.items.add(Item); return this; } } /** * Bootstrap page item. A list item wrapping a BsPageLink. * Extends Span. */ class BsPageItem : Span { /** * Creates a Bootstrap page item. * @p Active is an optional bool; true highlights as the current page. * @p Disabled is an optional bool; true disables the item. * @r This object. */ public BsPageItem(bool Active = false, bool Disabled = false) { this.Span(); cls = 'page-item'; if (Active) { cls += ' active'; } if (Disabled) { cls += ' disabled'; } this.setAttr('class', cls); } } /** * Bootstrap page link. The anchor element inside a BsPageItem. * Extends A. */ class BsPageLink : A { /** * Creates a Bootstrap page link. * @p Text is a string with the link label. * @p Href is an optional string with the page URL. Defaults to '#'. * @r This object. */ public BsPageLink(string Text, string Href = '#') { this.A(Text, Href); this.addClass('page-link'); } } /* --- Progress --- */ /** * Bootstrap progress bar wrapper. Contains one or more * BsProgressBar components. Extends Div. */ class BsProgress : Div { /** * Creates a Bootstrap progress bar wrapper. * @r This object. */ public BsProgress() { this.Div(); this.setAttr('class', 'progress'); } } /** * Bootstrap progress bar fill. Must be placed inside a BsProgress. * Extends Div. */ class BsProgressBar : Div { /** * Creates a Bootstrap progress bar fill. * @p Value is an int with the current progress value. * @p Min is an optional int with the minimum value. Defaults to 0. * @p Max is an optional int with the maximum value. Defaults to 100. * @p Label is an optional string with an accessible or visible label. * @p Variant is an optional bsVariant enum for the bar color. * (primary, secondary, success, danger, warning, info, light, dark) * @p Striped is an optional bool; true adds a striped pattern. * @p Animated is an optional bool; true animates the stripes. * @r This object. */ public BsProgressBar(int Value = 0, int Min = 0, int Max = 100, string Label = null, string Variant = null, bool Striped = false, bool Animated = false) { this.Div(); cls = 'progress-bar'; if (Variant != null) { cls += ' bg-' + Variant; } if (Striped) { cls += ' progress-bar-striped'; } if (Animated) { cls += ' progress-bar-animated'; } this.setAttr('class', cls); this.setAttr('role', 'progressbar'); this.setAttr('style', 'width: ' + Value + '%;'); this.setAttr('aria-valuenow', '' + Value); this.setAttr('aria-valuemin', '' + Min); this.setAttr('aria-valuemax', '' + Max); if (Label != null) { this.add(new Text(Label)); } } } /* --- Spinners --- */ /** * Bootstrap loading spinner. Displays an animated indicator * while content is loading. Extends Div. */ class BsSpinner : Div { /** * Creates a Bootstrap spinner. * @p Type is an optional bsSpinnerType enum. (border, grow) * Defaults to border. * @p Variant is an optional bsVariant enum for the spinner color. * (primary, secondary, success, danger, warning, info, light, dark) * @p Size is an optional bsSize enum for a smaller spinner. (sm) * @p Label is an optional string with the accessible label. * Defaults to 'Loading...'. * @r This object. */ public BsSpinner(string Type = 'border', string Variant = null, string Size = null, string Label = 'Loading...') { this.Div(); cls = 'spinner-' + Type; if (Variant != null) { cls += ' text-' + Variant; } if (Size != null) { cls += ' spinner-' + Type + '-' + Size; } this.setAttr('class', cls); this.setAttr('role', 'status'); srSpan = new Span(Label); srSpan.setAttr('class', 'visually-hidden'); this.add(srSpan); } } /* --- Accordion --- */ /** * Bootstrap accordion. A vertically collapsing list of items. * Extends Div. */ class BsAccordion : Div { public accordionId = null; public alwaysOpen = false; /** * Creates a Bootstrap accordion. * @p Id is a string with the accordion element ID. * @p AlwaysOpen is an optional bool; true allows multiple items * to stay open at the same time. * @r This object. */ public BsAccordion(string Id, bool AlwaysOpen = false) { this.Div(); this.setAttr('class', 'accordion'); this.setId(Id); this.accordionId = Id; this.alwaysOpen = AlwaysOpen; } /** * Adds a BsAccordionItem to this accordion. * @p Title is a string with the item header text. * @p Body is a string with the item body text. * @p Open is an optional bool; true expands this item initially. * @r This object. */ public addItem(string Title, string Body, bool Open = false) { itemId = this.accordionId + '-item-' + this.getChildren().size(); parentId = null; if (!this.alwaysOpen) { parentId = this.accordionId; } item = new BsAccordionItem(parentId, itemId, Title, Body, Open); this.add(item); return this; } } /** * Bootstrap accordion item. A single collapsible section inside * a BsAccordion. Extends Div. */ class BsAccordionItem : Div { /** * Creates a Bootstrap accordion item. * @p ParentId is a string with the parent accordion ID, or null * for always-open behavior. * @p ItemId is a string with a unique ID for this item. * @p Title is a string with the header button text. * @p Body is a string with the collapsible body content. * @p Open is an optional bool; true expands the item by default. * @r This object. */ public BsAccordionItem(string ParentId, string ItemId, string Title, string Body, bool Open = false) { this.Div(); this.setAttr('class', 'accordion-item'); headerId = ItemId + '-header'; collapseId = ItemId + '-collapse'; // Build header header = new H2(); header.setAttr('class', 'accordion-header'); header.setId(headerId); btnCls = 'accordion-button'; if (!Open) { btnCls += ' collapsed'; } btn = new Button(Title); btn.setAttr('class', btnCls); btn.setAttr('type', 'button'); btn.setAttr('data-bs-toggle', 'collapse'); btn.setAttr('data-bs-target', '#' + collapseId); btn.setAttr('aria-expanded', '' + Open); btn.setAttr('aria-controls', collapseId); header.add(btn); this.add(header); // Build collapse body collapseCls = 'accordion-collapse collapse'; if (Open) { collapseCls += ' show'; } collapse = new Div(); collapse.setAttr('class', collapseCls); collapse.setId(collapseId); collapse.setAttr('aria-labelledby', headerId); if (ParentId != null) { collapse.setAttr('data-bs-parent', '#' + ParentId); } bodyDiv = new Div(); bodyDiv.setAttr('class', 'accordion-body'); bodyDiv.add(new Text(Body)); collapse.add(bodyDiv); this.add(collapse); } } /* --- Dropdowns --- */ /** * Bootstrap dropdown. A toggleable contextual overlay. Extends Div. */ class BsDropdown : Div { /** * Creates a Bootstrap dropdown container. * @p Direction is an optional bsDropDirection enum. * (dropdown, dropup, dropend, dropstart) Defaults to dropdown. * @r This object. */ public BsDropdown(string Direction = 'dropdown') { this.Div(); this.setAttr('class', '' + Direction); } } /** * Bootstrap dropdown toggle button. Opens and closes the dropdown * menu when clicked. Extends Button. */ class BsDropdownToggle : Button { /** * Creates a Bootstrap dropdown toggle button. * @p Text is a string with the button label. * @p Variant is a bsVariant enum for the button color. * (primary, secondary, success, danger, warning, info, light, dark) * Defaults to primary. * @r This object. */ public BsDropdownToggle(string Text, string Variant = 'primary') { this.Button(Text); this.setAttr('class', 'btn btn-' + Variant + ' dropdown-toggle'); this.setAttr('type', 'button'); this.setAttr('data-bs-toggle', 'dropdown'); this.setAttr('aria-expanded', 'false'); } } /** * Bootstrap dropdown menu. The list of items revealed on toggle. * Extends Ul. */ class BsDropdownMenu : Ul { /** * Creates a Bootstrap dropdown menu. * @p AlignEnd is an optional bool; true right-aligns the menu. * @r This object. */ public BsDropdownMenu(bool AlignEnd = false) { this.Ul(); cls = 'dropdown-menu'; if (AlignEnd) { cls += ' dropdown-menu-end'; } this.setAttr('class', cls); } } /** * Bootstrap dropdown item. A single option inside a BsDropdownMenu. * Extends Span. */ class BsDropdownItem : Span { /** * Creates a Bootstrap dropdown item. * @p Text is a string with the item label. * @p Href is an optional string URL. Defaults to '#'. * @p Active is an optional bool; true highlights this item. * @p Disabled is an optional bool; true disables the item. * @r This object. */ public BsDropdownItem(string Text, string Href = '#', bool Active = false, bool Disabled = false) { this.Span(); this.setAttr('class', 'dropdown-item-wrapper'); link = new A(Text, Href); cls = 'dropdown-item'; if (Active) { cls += ' active'; } if (Disabled) { cls += ' disabled'; } link.setAttr('class', cls); this.add(link); } } /** * Bootstrap dropdown divider. A horizontal rule separating groups * of dropdown items. Extends Span. */ class BsDropdownDivider : Span { /** * Creates a Bootstrap dropdown divider. * @r This object. */ public BsDropdownDivider() { this.Span(); hr = new Hr(); hr.setAttr('class', 'dropdown-divider'); this.add(hr); } } /** * Bootstrap dropdown header. A non-interactive label for a group * of dropdown items. Extends Span. */ class BsDropdownHeader : Span { /** * Creates a Bootstrap dropdown header label. * @p Text is a string with the header text. * @r This object. */ public BsDropdownHeader(string Text) { this.Span(); this.setAttr('class', 'dropdown-header'); this.add(new Text(Text)); } } /* --- Modal --- */ /** * Bootstrap modal dialog. A layered dialog box displayed above * the page content. Extends Div. */ class BsModal : Div { public modalSize = null; /** * Creates a Bootstrap modal. * @p Id is a string with the modal element ID. * @p Static is an optional bool; true prevents closing the modal * by clicking the backdrop. * @p Size is an optional bsSize enum for the modal size. (sm, lg, xl) * @r This object. */ public BsModal(string Id, bool Static = false, string Size = null) { this.Div(); this.setAttr('class', 'modal fade'); this.setId(Id); this.setAttr('tabindex', '-1'); this.setAttr('aria-hidden', 'true'); if (Static) { this.setAttr('data-bs-backdrop', 'static'); this.setAttr('data-bs-keyboard', 'false'); } this.modalSize = Size; } /** * Returns the size enum value stored for use by BsModalDialog. * @r The bsSize enum value or null. */ public getModalSize() { return this.modalSize; } } /** * Bootstrap modal dialog container. The inner sizing wrapper * for a BsModal. Extends Div. */ class BsModalDialog : Div { /** * Creates a Bootstrap modal dialog container. * @p Scrollable is an optional bool; true allows scrolling the * modal body independently. * @p Centered is an optional bool; true vertically centers the modal. * @p Size is an optional bsSize enum for the modal size. (sm, lg, xl) * @r This object. */ public BsModalDialog(bool Scrollable = false, bool Centered = false, string Size = null) { this.Div(); cls = 'modal-dialog'; if (Scrollable) { cls += ' modal-dialog-scrollable'; } if (Centered) { cls += ' modal-dialog-centered'; } if (Size != null) { cls += ' modal-' + Size; } this.setAttr('class', cls); } } /** * Bootstrap modal content wrapper. Contains the header, body, * and footer sections. Extends Div. */ class BsModalContent : Div { /** * Creates a Bootstrap modal content div. * @r This object. */ public BsModalContent() { this.Div(); this.setAttr('class', 'modal-content'); } } /** * Bootstrap modal header. Contains the modal title and optional * close button. Extends Div. */ class BsModalHeader : Div { /** * Creates a Bootstrap modal header. * @p Title is an optional string with the modal title text. * @p Dismissible is an optional bool; true adds a close button. * Defaults to true. * @r This object. */ public BsModalHeader(string Title = null, bool Dismissible = true) { this.Div(); this.setAttr('class', 'modal-header'); if (Title != null) { h5 = new H5(Title); h5.setAttr('class', 'modal-title'); this.add(h5); } if (Dismissible) { btn = new BsCloseButton(); btn.setAttr('data-bs-dismiss', 'modal'); this.add(btn); } } } /** * Bootstrap modal body. The main content area of a modal. * Extends Div. */ class BsModalBody : Div { /** * Creates a Bootstrap modal body. * @r This object. */ public BsModalBody() { this.Div(); this.setAttr('class', 'modal-body'); } } /** * Bootstrap modal footer. The action button area at the bottom * of a modal. Extends Div. */ class BsModalFooter : Div { /** * Creates a Bootstrap modal footer. * @r This object. */ public BsModalFooter() { this.Div(); this.setAttr('class', 'modal-footer'); } } /* --- Toast --- */ /** * Bootstrap toast container. Positions toast notifications on * the screen. Extends Div. */ class BsToastContainer : Div { /** * Creates a Bootstrap toast container. * @p Position is an optional bsToastPos enum for screen placement. * (topStart, topCenter, topEnd, middleStart, middleCenter, * middleEnd, bottomStart, bottomCenter, bottomEnd) * Defaults to bottomEnd. * @r This object. */ public BsToastContainer(string Position = 'bottomEnd') { this.Div(); this.setAttr('class', 'toast-container position-fixed p-3'); posClass = 'bottom-0 end-0'; if (Position == bsToastPos.topStart) { posClass = 'top-0 start-0'; } else if (Position == bsToastPos.topCenter) { posClass = 'top-0 start-50 translate-middle-x'; } else if (Position == bsToastPos.topEnd) { posClass = 'top-0 end-0'; } else if (Position == bsToastPos.middleStart) { posClass = 'top-50 start-0 translate-middle-y'; } else if (Position == bsToastPos.middleCenter) { posClass = 'top-50 start-50 translate-middle'; } else if (Position == bsToastPos.middleEnd) { posClass = 'top-50 end-0 translate-middle-y'; } else if (Position == bsToastPos.bottomStart) { posClass = 'bottom-0 start-0'; } else if (Position == bsToastPos.bottomCenter) { posClass = 'bottom-0 start-50 translate-middle-x'; } this.addClass(posClass); } } /** * Bootstrap toast notification. A lightweight, auto-dismissing * alert. Extends Div. */ class BsToast : Div { /** * Creates a Bootstrap toast. * @p Id is a string with the toast element ID. * @p AutoHide is an optional bool; false keeps the toast visible * until dismissed. Defaults to true. * @p Delay is an optional int with the auto-hide delay in * milliseconds. Defaults to 5000. * @r This object. */ public BsToast(string Id, bool AutoHide = true, int Delay = 5000) { this.Div(); this.setAttr('class', 'toast'); this.setId(Id); this.setAttr('role', 'alert'); this.setAttr('aria-live', 'assertive'); this.setAttr('aria-atomic', 'true'); if (!AutoHide) { this.setAttr('data-bs-autohide', 'false'); } else { this.setAttr('data-bs-delay', '' + Delay); } } } /** * Bootstrap toast header. Contains the title and optional dismiss * button for a BsToast. Extends Div. */ class BsToastHeader : Div { /** * Creates a Bootstrap toast header. * @p Title is an optional string with the toast title. * @p Subtitle is an optional string with secondary text * (e.g., a timestamp). * @p Dismissible is an optional bool; true adds a close button. * Defaults to true. * @r This object. */ public BsToastHeader(string Title = null, string Subtitle = null, bool Dismissible = true) { this.Div(); this.setAttr('class', 'toast-header'); if (Title != null) { strong = new Strong(Title); strong.addClass('me-auto'); this.add(strong); } if (Subtitle != null) { small = new Span(Subtitle); small.addClass('text-muted'); this.add(small); } if (Dismissible) { btn = new BsCloseButton(); btn.setAttr('data-bs-dismiss', 'toast'); this.add(btn); } } } /** * Bootstrap toast body. The main content area of a BsToast. * Extends Div. */ class BsToastBody : Div { /** * Creates a Bootstrap toast body. * @p Text is an optional string with the toast message. * @r This object. */ public BsToastBody(string Text = null) { this.Div(); this.setAttr('class', 'toast-body'); if (Text != null) { this.add(new Text(Text)); } } } /* --- Forms --- */ /** * Bootstrap form wrapper. Manages form submission and field layout. * Extends Form. */ class BsForm : Form { /** * Creates a Bootstrap form. * @p Action is an optional string with the form submission URL. * @p Method is an optional string with the HTTP method. * (get, post) Defaults to post. * @r This object. */ public BsForm(string Action = null, string Method = 'post') { this.Form(Action, Method); } /** * Adds a labeled form field row to the form. * @p DisplayName is a string with the field label text. * @p FormField is the input object to add. * @p HelpText is an optional string with hint text shown below the field. * @r This object. */ public addField(string DisplayName, object FormField, string HelpText = null) { lbl = new BsFormLabel(FormField.getId(), DisplayName); farr = [lbl, FormField]; if (HelpText != null) { farr.add(new BsFormHelp(FormField.getId() + 'Help', HelpText)); } frow = new BsFormRow(farr); this.add(frow); return this; } } /** * Bootstrap form label. Associates visible text with a form * input control. Extends Label. */ class BsFormLabel : Label { /** * Creates a Bootstrap form label. * @p Id is a string with the ID of the associated input element. * @p TextData is a string with the label text. * @r This object. */ public BsFormLabel(string Id, string TextData) { this.Label(TextData); this.addClass('form-label'); this.setAttr('for', Id); } } /** * Bootstrap form help text. Displays a hint below a form field. * Extends Div. */ class BsFormHelp : Div { /** * Creates Bootstrap form help text. * @p Id is a string with the element ID. * @p TextData is a string with the help text. * @r This object. */ public BsFormHelp(string Id, string TextData) { this.Div(); this.setId(Id); this.addClass('form-text'); this.add(new Text(TextData)); } } /** * Bootstrap form row helper. Wraps form elements with bottom * margin spacing. Extends Div. */ class BsFormRow : Div { /** * Creates a Bootstrap form row. * @p Items is an optional object or list of objects to add. * @r This object. */ public BsFormRow(Items = null) { this.Div(); this.addClass('mb-3'); if (Items instanceof 'list') { for (item : Items) { this.add(item); } } else if (Items != null) { this.add(Items); } } } /** * Bootstrap text field input. A single-line plain text input. * Extends Input. */ class BsTextField : Input { /** * Creates a Bootstrap text input. * @p Id is a string with the input name and element ID. * @p Value is an optional string with the initial value. * @p Placeholder is an optional string shown when the field is empty. * @r This object. */ public BsTextField(string Id, string Value = null, string Placeholder = null) { this.Input('text', Id, Value); this.addClass('form-control'); this.setId(Id); if (Placeholder != null) { this.setPlaceholder(Placeholder); } } } /** * Bootstrap email input field. Extends Email. */ class BsEmailField : Email { /** * Creates a Bootstrap email input. * @p Id is a string with the input name and element ID. * @p Value is an optional string with the initial value. * @p Placeholder is an optional string shown when the field is empty. * @r This object. */ public BsEmailField(string Id, string Value = null, string Placeholder = null) { this.Email(Id, Value); this.addClass('form-control'); this.setId(Id); if (Placeholder != null) { this.setPlaceholder(Placeholder); } } } /** * Bootstrap password input field. Extends Password. */ class BsPasswordField : Password { /** * Creates a Bootstrap password input. * @p Id is a string with the input name and element ID. * @p Value is an optional string with the initial value. * @p Placeholder is an optional string shown when the field is empty. * @r This object. */ public BsPasswordField(string Id, string Value = null, string Placeholder = null) { this.Password(Id, Value); this.addClass('form-control'); this.setId(Id); if (Placeholder != null) { this.setPlaceholder(Placeholder); } } } /** * Bootstrap number input field. Extends Number. */ class BsNumberField : Number { /** * Creates a Bootstrap number input. * @p Id is a string with the input name and element ID. * @p Value is an optional string with the initial value. * @p Min is an optional number for the minimum allowed value. * @p Max is an optional number for the maximum allowed value. * @p Step is an optional number for the increment step. * @r This object. */ public BsNumberField(string Id, string Value = null, Min = null, Max = null, Step = null) { this.Number(Id, Value); this.addClass('form-control'); this.setId(Id); if (Min != null) { this.setMin(Min); } if (Max != null) { this.setMax(Max); } if (Step != null) { this.setAttr('step', '' + Step); } } } /** * Bootstrap textarea input. A multi-line text input. Extends Textarea. */ class BsTextarea : Textarea { /** * Creates a Bootstrap textarea. * @p Id is a string with the textarea name and element ID. * @p Rows is an optional int with the visible row count. Defaults to 3. * @p Value is an optional string with the initial text content. * @r This object. */ public BsTextarea(string Id, int Rows = 3, string Value = null) { this.Textarea(Id, Value); this.addClass('form-control'); this.setId(Id); this.setRows(Rows); } } /** * Bootstrap select dropdown. A styled HTML select element. Extends Select. */ class BsSelect : Select { /** * Creates a Bootstrap select dropdown. * @p Id is a string with the select name and element ID. * @p Size is an optional bsSize enum for the select height. (sm, lg) * @p Multiple is an optional bool; true allows multiple selections. * @r This object. */ public BsSelect(string Id, string Size = null, bool Multiple = false) { this.Select(Id); cls = 'form-select'; if (Size != null) { cls += ' form-select-' + Size; } this.setAttr('class', cls); this.setId(Id); if (Multiple) { this.setAttr('multiple', 'multiple'); } } } /** * Bootstrap checkbox. A self-contained form-check component with * a labeled checkbox input. Extends Div. */ class BsCheckbox : Div { public input = null; /** * Creates a Bootstrap checkbox with a wrapper div and label. * @p Id is a string with the input element ID. * @p LabelText is a string with the checkbox label. * @p Checked is an optional bool; true checks the box by default. * @p Disabled is an optional bool; true disables the checkbox. * @r This object. */ public BsCheckbox(string Id, string LabelText, bool Checked = false, bool Disabled = false) { this.Div(); this.setAttr('class', 'form-check'); input = new Checkbox(Id); input.addClass('form-check-input'); input.setId(Id); if (Checked) { input.setAttr('checked', 'checked'); } if (Disabled) { input.setAttr('disabled', 'disabled'); } lbl = new Label(LabelText); lbl.addClass('form-check-label'); lbl.setAttr('for', Id); this.add(input); this.add(lbl); this.input = input; } /** * Gets the checked state of the checkbox. * @r A bool with true if checked, false otherwise. */ public getChecked() { return this.input.getChecked(); } /** * Sets the checked state of the checkbox. * @p Checked is a bool with true to check, false to uncheck. * @r This object. */ public setChecked(bool Checked) { this.input.setChecked(Checked); return this; } } /** * Bootstrap radio button. A self-contained form-check component * with a labeled radio input. Extends Div. */ class BsRadio : Div { public input = null; /** * Creates a Bootstrap radio button with a wrapper div and label. * @p Id is a string with the input element ID. * @p Name is a string with the radio group name. * @p LabelText is a string with the radio button label. * @p Checked is an optional bool; true selects this option by default. * @p Disabled is an optional bool; true disables the radio button. * @r This object. */ public BsRadio(string Id, string Name, string LabelText, bool Checked = false, bool Disabled = false) { this.Div(); this.setAttr('class', 'form-check'); input = new Radio(Id, Name); input.addClass('form-check-input'); if (Checked) { input.setAttr('checked', 'checked'); } if (Disabled) { input.setAttr('disabled', 'disabled'); } lbl = new Label(LabelText); lbl.addClass('form-check-label'); lbl.setAttr('for', Id); this.add(input); this.add(lbl); this.input = input; } /** * Gets the checked state of the radio button. * @r A bool with true if checked, false otherwise. */ public getChecked() { return this.input.getChecked(); } } /** * Bootstrap switch. A toggle switch styled as a form-check with * the switch role. Extends Div. */ class BsSwitch : Div { public input = null; /** * Creates a Bootstrap switch toggle. * @p Id is a string with the input element ID. * @p LabelText is a string with the switch label. * @p Checked is an optional bool; true turns the switch on by default. * @r This object. */ public BsSwitch(string Id, string LabelText, bool Checked = false) { this.Div(); this.setAttr('class', 'form-check form-switch'); input = new Checkbox(Id); input.addClass('form-check-input'); input.setId(Id); input.setAttr('role', 'switch'); if (Checked) { input.setAttr('checked', 'checked'); } lbl = new Label(LabelText); lbl.addClass('form-check-label'); lbl.setAttr('for', Id); this.add(input); this.add(lbl); this.input = input; } /** * Gets the checked state of the switch. * @r A bool with true if on, false if off. */ public getChecked() { return this.input.getChecked(); } /** * Sets the checked state of the switch. * @p Checked is a bool with true to turn on, false to turn off. * @r This object. */ public setChecked(bool Checked) { this.input.setChecked(Checked); return this; } } /** * Bootstrap range slider input. Extends Range. */ class BsRange : Range { /** * Creates a Bootstrap range slider. * @p Id is a string with the input name and element ID. * @p Min is an optional number for the minimum value. Defaults to 0. * @p Max is an optional number for the maximum value. Defaults to 100. * @p Step is an optional number for the increment step. * @p Value is an optional string with the initial value. * @r This object. */ public BsRange(string Id, Min = 0, Max = 100, Step = null, string Value = null) { this.Range(Id, Value); this.addClass('form-range'); this.setId(Id); this.setMin(Min); this.setMax(Max); if (Step != null) { this.setAttr('step', '' + Step); } } } /** * Bootstrap file input field. Extends FileInput. */ class BsFileInput : FileInput { /** * Creates a Bootstrap file input. * @p Id is a string with the input name and element ID. * @p Multiple is an optional bool; true allows selecting multiple files. * @p Accept is an optional list of accepted MIME types or extensions. * @r This object. */ public BsFileInput(string Id, bool Multiple = false, list Accept = null) { acceptList = []; if (Accept != null) { acceptList = Accept; } this.FileInput(Id, acceptList); this.addClass('form-control'); this.setId(Id); if (Multiple) { this.setAttr('multiple', 'multiple'); } } } /* --- Input Groups --- */ /** * Bootstrap input group. Attaches addons (text, buttons) to the * sides of an input field. Extends Div. */ class BsInputGroup : Div { /** * Creates a Bootstrap input group. * @p Size is an optional bsSize enum for the input group size. * (sm, lg) * @r This object. */ public BsInputGroup(string Size = null) { this.Div(); cls = 'input-group'; if (Size != null) { cls += ' input-group-' + Size; } this.setAttr('class', cls); } } /** * Bootstrap input group text addon. A styled text label attached * to an input inside a BsInputGroup. Extends Span. */ class BsInputGroupText : Span { /** * Creates a Bootstrap input group text addon. * @p Text is a string with the addon label. * @r This object. */ public BsInputGroupText(string Text) { this.Span(Text); this.setAttr('class', 'input-group-text'); } } /* --- Floating Labels --- */ /** * Bootstrap floating label wrapper. Wraps an input and its label * so the label floats above the input when focused or filled. * Extends Div. */ class BsFloatingLabel : Div { /** * Creates a Bootstrap floating label wrapper. * @p LabelText is a string with the floating label text. * @p InputField is the input object to wrap. The input must * have an element ID set and a placeholder attribute. * @r This object. */ public BsFloatingLabel(string LabelText, object InputField) { this.Div(); this.setAttr('class', 'form-floating'); this.add(InputField); lbl = new Label(LabelText); lbl.setAttr('for', InputField.getId()); this.add(lbl); } }