@table-bro/native 0.0.0-stage → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +100 -2
  3. package/THIRD_PARTY_NOTICES.md +69 -0
  4. package/dist/table-bro.native.d.ts +213 -0
  5. package/dist/table-bro.native.esm.js +114 -0
  6. package/dist/table-bro.native.esm.js.map +1 -0
  7. package/dist/table-bro.native.min.css +1 -0
  8. package/dist/table-bro.native.umd.js +114 -0
  9. package/dist/table-bro.native.umd.js.map +1 -0
  10. package/package.json +75 -4
  11. package/styles/_table-bro.api.scss +3 -0
  12. package/styles/_table-bro.native.api.scss +5 -0
  13. package/styles/mixins/_text-ellipsis.scss +5 -0
  14. package/styles/mixins/_visually-hidden.scss +14 -0
  15. package/styles/skin/shared/_variables.scss +94 -0
  16. package/styles/skin/shared/mixins/_custom-properties.scss +39 -0
  17. package/styles/skin/shared/mixins/_progress-bar.scss +27 -0
  18. package/styles/skin/shared/mixins/_shared.scss +79 -0
  19. package/styles/skin/shared/mixins/_skin-colors.scss +64 -0
  20. package/styles/skin/shared/mixins/_slide-toggle.scss +5 -0
  21. package/styles/skin/shared/mixins/_sort-header.scss +11 -0
  22. package/styles/skin/shared/mixins/_toolbar.scss +61 -0
  23. package/styles/skin/shared/table-bro/_details.scss +11 -0
  24. package/styles/skin/shared/table-bro/_filter-drawer.scss +62 -0
  25. package/styles/skin/shared/table-bro/_shadows.scss +19 -0
  26. package/styles/skin/shared/table-bro/_state.scss +38 -0
  27. package/styles/skin/shared/table-bro/_table.scss +70 -0
  28. package/styles/skin/shared/table-bro/_text-ellipsis.scss +14 -0
  29. package/styles/skin/vanilla-js/native/_themes.scss +45 -0
  30. package/styles/skin/vanilla-js/native/_variables.scss +54 -0
  31. package/styles/skin/vanilla-js/native/components/bootstrap-based/_paginator.scss +50 -0
  32. package/styles/skin/vanilla-js/native/components/bootstrap-based/_toolbar.scss +107 -0
  33. package/styles/skin/vanilla-js/native/table-bro/_button.scss +36 -0
  34. package/styles/skin/vanilla-js/native/table-bro/_filter-drawer.scss +10 -0
  35. package/styles/skin/vanilla-js/native/table-bro/_progress-bar.scss +45 -0
  36. package/styles/skin/vanilla-js/native/table-bro/_table.scss +16 -0
  37. package/styles/skin/vanilla-js/native/table-bro/_toolbar-search.scss +17 -0
  38. package/styles/skin/vanilla-js/native/table-bro/_toolbar.scss +31 -0
  39. package/styles/skin/vanilla-js/shared/_bootstrap-adapter.scss +9 -0
  40. package/styles/skin/vanilla-js/shared/_skin.scss +76 -0
  41. package/styles/skin/vanilla-js/shared/components/bootstrap-based/_button.scss +9 -0
  42. package/styles/skin/vanilla-js/shared/components/material-based/_paginator.scss +62 -0
  43. package/styles/skin/vanilla-js/shared/components/material-based/_sort-header.scss +149 -0
  44. package/styles/skin/vanilla-js/shared/components/material-based/_table.scss +11 -0
  45. package/styles/skin/vanilla-js/shared/table-bro/_filter-drawer.scss +13 -0
  46. package/styles/skin/vanilla-js/shared/table-bro/_paginator.scss +5 -0
  47. package/styles/skin/vanilla-js/shared/table-bro/_toolbar-search.scss +31 -0
  48. package/styles/skin/vanilla-js/shared/table-bro/_toolbar.scss +39 -0
  49. package/styles/skin/vanilla-js/shared/vendor-extensions/material-based/_paginator.scss +12 -0
  50. package/styles/table-bro.native.scss +43 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"table-bro.native.umd.js","names":["BroHTMLElement","BroHTML","BroHTMLElement","escape","BroHTML","BroHTMLElement","escape","BroHTML","BroHTMLElement","escape","events","isPrerendered","BroDom","broVisuallyHidden","BroHTML","BroHTMLElement","escape","BroHTML","BroHTMLElement","broCellSelectors","escape","BroHTML","BroHTMLElement","escape","events","isPrerendered","BroHTML","BroHTMLElement","escape","isPrerendered","BroDom","BroHTML","BroHTMLElement","escape","isPrerendered","BroHTML","BroHTMLElement","isPrerendered","factory","global","exports","tagsTexts","connectedTags","setTagsTexts","texts","tags","BroTagsComponent","_table_bro_core","name","items","tagEl","i","item","escape$8","BroSwitchComponent","checked","input","escape$7","BroToolbarComponent","divClass","nodes","escape$6","BroToolbarMainComponent","ulClass","event","link","broToolbar","wrapper","broDropdown","hidden","word","wordHTML","buttonTitle","className","iconHTML","broButton","button","buttonEl","escape$5","BroButtonComponent","ariaLabel","content","escape$4","BroTextEllipsisComponent","valueEl","text","tooltipEl","escape$3","BroSortHeaderComponent","classList","control","headerContainerEl","sort","container","oldValue","value","escape$2","sharedElements","ul","liClass","aClass","currentValue","maxPageIndex","err","dropdown","pageSizeValueEl","disable","noPrevious","noNext","previousIndex","index","startIndex","pageSize","withSwitch","defineElement","registry","element","defineSharedElements","definedElsewhere","defined","skinPackage","BroNativeTagsComponent","escape$1","BroNativeDropdownComponent","label","select","menu","keyboard","pending","send","options","option","BroNativeProgressBarComponent","indeterminate","escape","nativeSkinConfig","closeButton","searchButton","backButton","clearButton","withTags"],"sources":["../../shared/js/bro-tags.ts","../../shared/js/bootstrap-based/bro-switch.ts","../../shared/js/bootstrap-based/toolbar/bro-toolbar.ts","../../shared/js/bootstrap-based/toolbar/bro-toolbar-main.ts","../../shared/js/bro-button.ts","../../shared/js/bro-text-ellipsis.ts","../../shared/js/material-based/bro-sort-header.ts","../../shared/js/material-based/paginator/bro-paginator.ts","../../shared/js/define-shared-elements.ts","../js/bro-tags.native.ts","../js/bro-dropdown.native.ts","../js/bro-progress-bar.native.ts","../js/table-bro.native.config.ts","../js/table-bro.native.ts"],"sourcesContent":["import {type BroCellElement, type BroCol, type BroConfiguredElement, BroHTMLElement, type BroResolvedConfig, type BroRow, type BroView, fitCellItems} from '@table-bro/core';\n\n/** The texts of the tags of a skin. */\nexport interface BroTagsTexts {\n /** The text of a cell of tags without items, No data by default. */\n empty: string;\n}\n\n/** The texts that the application gives the tags by withTags() and setTagsTexts() of the skin. */\nlet tagsTexts: Partial<BroTagsTexts> = {};\n/** The tags in the DOM, which a new text of a cell without items renders again. */\nconst connectedTags = new Set<BroTagsComponent>();\n\n/**\n * Sets the texts of the tags of the skin, as when the language of the page changes: the tags in the DOM take them at\n * once. They take the place of texts.noItems of the config of a table.\n * @param texts - the texts that change\n */\nexport function setTagsTexts(texts: Partial<BroTagsTexts>): void {\n tagsTexts = {...tagsTexts, ...texts};\n connectedTags.forEach(tags => tags.renderEmpty());\n}\n\n/**\n * The tags of a cell of the vanilla skins: the items of the field of the column in the row, each in the markup of a tag\n * of the skin.\n */\nexport abstract class BroTagsComponent extends BroHTMLElement implements BroView, BroCellElement, BroConfiguredElement {\n template(): string {\n const name = this.col?.name;\n const items = name && this.row?.[name];\n\n this.empty = !(Array.isArray(items) && items.length);\n this.items = this.empty ? [this.emptyText()] : <string[]>items;\n\n return this.items.map(() => this.tagHTML).join('');\n }\n\n row?: BroRow;\n col?: BroCol;\n config?: BroResolvedConfig;\n\n items: string[] = [];\n /** Whether the cell has no items and shows the text of an empty cell. */\n private empty: boolean = false;\n\n /** Stops fitting the tags into the line when the element leaves the DOM. */\n private fitting?: AbortController;\n /** A move in the DOM connects the element again; it keeps its markup and listeners. */\n private rendered: boolean = false;\n\n render(): void {\n this.insertAdjacentHTML('afterbegin', this.template());\n Array.from(this.children).forEach((tagEl: Element, i: number) => this.renderTag(tagEl, this.items[i]));\n }\n\n /** Renders the text of an empty cell again, as setTagsTexts() changes it. */\n renderEmpty(): void {\n if (this.empty && this.firstElementChild) {\n this.items = [this.emptyText()];\n this.renderTag(this.firstElementChild, this.items[0]);\n }\n }\n\n /**\n * Puts an item into its tag: a tag is markup only for a column with html: true.\n * @param tagEl - the tag\n * @param item - the item\n */\n private renderTag(tagEl: Element, item: string): void {\n if (this.col?.html) {\n tagEl.innerHTML = item;\n } else {\n tagEl.textContent = item;\n }\n }\n\n /** The text of an empty cell: the one of the skin, the deprecated texts.noItems of the table, or No data. */\n private emptyText(): string {\n return tagsTexts.empty ?? this.config?.texts.noItems ?? 'No data';\n }\n\n /** The empty markup of one tag of the skin, which takes the text of an item. */\n protected abstract readonly tagHTML: string;\n\n connectedCallback(): void {\n connectedTags.add(this);\n\n if (!this.rendered) {\n this.rendered = true;\n\n this.render();\n } else {\n // The texts may have changed while the element was out of the DOM\n this.renderEmpty();\n }\n\n // The tags that do not fit the line give way to an ellipsis\n this.fitting = new AbortController();\n fitCellItems(this, this.fitting.signal);\n }\n\n disconnectedCallback(): void {\n connectedTags.delete(this);\n this.fitting?.abort();\n }\n}\n","import {type BroCol, type BroConfiguredElement, BroHTML, BroHTMLElement, type BroResolvedConfig, type BroSkinComponents, type BroView} from '@table-bro/core';\n\nconst {escape} = BroHTML;\n\n/**\n * A switch of a boolean of a cell. A change sends the action of the attribute name, as the event action that the table\n * turns into bro-action with the column and the row (event: 'action' of the column); the title of the column names\n * the switch for screen readers.\n */\nexport class BroSwitchComponent extends BroHTMLElement implements BroView, BroConfiguredElement {\n template(): string {\n this.css = this.config.components.switch?.css;\n\n this.checked = this.getAttribute('checked');\n\n const checked = (this.checked === 'true');\n\n return `\n <div ${this.css ? `class=\"${escape(this.css.div.className)}\"` : ''}>\n <input type=\"checkbox\"\n ${this.css ? `class=\"${escape(this.css.div.input.className)}\"` : ''}\n role=\"switch\"\n ${checked ? ' checked' : ''}>\n </div>`;\n }\n\n config!: BroResolvedConfig;\n /** The column of the cell, which the table sets. */\n col?: BroCol;\n\n checked!: string | null;\n\n private css: NonNullable<BroSkinComponents['switch']>['css'];\n /** A move in the DOM connects the element again; it keeps its markup and listeners. */\n private rendered: boolean = false;\n\n events() {\n const input = <HTMLInputElement>this.querySelector('input');\n const name = this.getAttribute('name');\n\n input.setAttribute('aria-label', this.col?.title ?? '');\n\n input.addEventListener('change', () => {\n if (name) {\n this.dispatchEvent(new CustomEvent('action', {detail: name}));\n }\n });\n }\n\n render(): void {\n this.insertAdjacentHTML('afterbegin', this.template());\n\n this.events();\n }\n\n connectedCallback(): void {\n if (this.rendered) {\n return;\n }\n\n this.rendered = true;\n\n this.render();\n }\n}\n","import {type BroConfiguredElement, BroHTML, BroHTMLElement, type BroResolvedConfig, type BroSkinComponents, type BroToolbarElement, type BroView} from '@table-bro/core';\n\nconst {escape} = BroHTML;\n\nexport class BroToolbarComponent extends BroHTMLElement implements BroView, BroConfiguredElement, BroToolbarElement {\n template(): string {\n this.css = <NonNullable<BroSkinComponents['toolbar']['css']>>this.config.components.toolbar.css;\n\n const divClass = this.css.nav.div?.className ? `${this.css.nav.div.className} ${this.contentClassName}` : this.contentClassName;\n\n return `\n <nav class=\"${escape(this.css.nav.className)}\">\n <div class=\"${escape(divClass)}\">\n <!-- toolbar content -->\n </div>\n </nav>`;\n }\n\n config!: BroResolvedConfig;\n contentClassName: string = 'bro-toolbar-content';\n\n // The vanilla skins give the classes of their toolbar\n private css!: NonNullable<BroSkinComponents['toolbar']['css']>;\n\n render(): void {\n this.insertAdjacentHTML('afterbegin', this.template());\n }\n\n appendToolbarContent(...nodes: (Node | string)[]): void {\n if (!this.firstChild) {\n this.render();\n }\n\n this.querySelector(`.${this.contentClassName}`)\n ?.append(...nodes);\n }\n}\n","import {type BroButton, type BroConfiguredElement, BroDom, type BroDropdown, BroHTML, BroHTMLElement, type BroResolvedConfig, type BroSkinComponents, type BroToolbarMain, type BroView, broVisuallyHidden, events, isPrerendered} from '@table-bro/core';\n\nimport type {BroToolbarComponent} from './bro-toolbar';\n\nconst {escape} = BroHTML;\n\nexport class BroToolbarMainComponent extends BroHTMLElement implements BroView, BroConfiguredElement, BroToolbarMain {\n template(): string {\n this.css = <NonNullable<BroSkinComponents['toolbarMain']['css']>>this.config.components.toolbarMain.css;\n\n this.toolbarTitle = this.config.toolbarTitle;\n\n const ulClass = this.css.navbarCollapse.ul.className ? `${this.css.navbarCollapse.ul.className} ${this.contentClassName}` : this.contentClassName;\n\n return `\n <!--bro-toolbar-->\n <span class=\"bro-toolbar-title-space\"></span>\n <span class=\"${escape(this.css.toolbarTitle.className)}\">${escape(this.toolbarTitle)}</span>\n\n <span class=\"bro-toolbar-space\"></span>\n\n <div class=\"${escape(this.css.navbarCollapse.className)} bro-toolbar-buttons\">\n <ul class=\"${escape(ulClass)}\">\n <!-- search-button -->\n <!-- buttons -->\n </ul>\n </div>\n <!--/bro-toolbar-->`;\n }\n\n config!: BroResolvedConfig;\n\n contentClassName: string = 'bro-navbar-nav';\n toolbarTitle!: string;\n\n // The vanilla skins give the classes of their toolbar\n private css!: NonNullable<BroSkinComponents['toolbarMain']['css']>;\n private navContentEl!: HTMLElement;\n /** A move in the DOM connects the element again; it keeps its markup and listeners. */\n private rendered: boolean = false;\n\n events() {\n this.addEventListener('click', (event: Event) => {\n event.preventDefault();\n });\n\n // A link in the role of a button takes Space as a button does, instead of scrolling the page; Enter clicks a link anyway.\n // A button of the skin in the toolbar, as Back of the search, takes Space itself\n this.addEventListener('keydown', (event: KeyboardEvent) => {\n const link = (<HTMLElement>event.target).closest?.('a[role=\"button\"]');\n\n if (event.key === ' ' && !event.repeat && !event.defaultPrevented && link) {\n event.preventDefault();\n\n (<HTMLElement>link).click();\n }\n });\n\n const searchLink = this.navContentEl.children[0];\n\n searchLink.addEventListener('click', () => {\n this.dispatchEvent(\n new CustomEvent(events.toolbarEvent, {\n bubbles: true,\n composed: true,\n detail: events.toolbarSearchOpenEvent\n })\n );\n });\n }\n\n render(): void {\n // The toolbar element\n const broToolbar = this.dom.createElement<BroToolbarComponent>(this.config.components.toolbar.selector);\n\n broToolbar.setAttribute('class', 'bro-toolbar');\n\n broToolbar.config = this.config;\n\n this.appendChild(broToolbar);\n\n // The template in the toolbar element\n const wrapper: HTMLElement = this.dom.createElement('div');\n\n wrapper.insertAdjacentHTML('afterbegin', this.template());\n\n broToolbar.appendToolbarContent(\n ...Array.from(wrapper.children)\n );\n\n // The buttons\n this.appendToolbarContent(\n this.renderSearchButton(),\n\n ...this.renderButtons()\n );\n\n this.querySelectorAll(<string>this.config.components.dropdown?.selector).forEach(broDropdown => {\n broDropdown.replaceWith(broDropdown.children[0]);\n });\n\n this.events();\n }\n\n connectedCallback(): void {\n // An element of a prerendered table keeps its markup until the table renders its own elements in its place\n if (isPrerendered(this)) {\n return;\n }\n\n if (this.rendered) {\n return;\n }\n\n this.rendered = true;\n\n this.render();\n }\n\n appendToolbarContent(...nodes: (Node | string)[]): void {\n if (!this.navContentEl) {\n this.navContentEl = <HTMLElement>this.querySelector(`.${this.contentClassName}`);\n }\n\n this.navContentEl\n .append(...nodes);\n }\n\n /** The nodes of the toolbar in the document of its element, as of a server DOM in a prerender. */\n private get dom(): BroDom {\n return new BroDom(this.ownerDocument);\n }\n\n /**\n * A link of the toolbar.\n * @param buttonTitle - the title of the link\n * @param word - the words after the title, as visually hidden text, as for Orders; none without a title\n * @param iconHTML - the icon before the title\n * @param className - a class of the link\n */\n private templateToolbarButton(buttonTitle: string, word: string, iconHTML?: string, className?: string): HTMLElement {\n // A link says what it is with visually hidden text: Lighthouse reads the text of a link, not its label. The word of\n // the role button repeats the role of the link to a screen reader, so only the text of the link keeps it\n const hidden = (word === this.config.texts.buttonRole) ? ' aria-hidden=\"true\"' : '';\n const wordHTML = (buttonTitle && word) ? `<span class=\"${escape(broVisuallyHidden)}\"${hidden}> ${escape(word)}</span>` : '';\n\n // The link acts on the table and goes nowhere: a button, as Bootstrap has a link with the classes of a button\n return this.dom.createFromHTML(`\n <li class=\"${escape(this.css.navbarCollapse.ul.li.className)}\">\n <a class=\"${escape(this.css.navbarCollapse.ul.li.a.className)}${className ? ` ${escape(className)}` : ''}\" href=\"\"\n role=\"button\">\n ${iconHTML || ''}${escape(buttonTitle)}${wordHTML}\n </a>\n </li>`);\n }\n\n private renderSearchButton(): HTMLElement {\n const broButton = this.dom.createElement<BroButton>(this.config.components.button.selector);\n\n this.config.components.toolbarMain.beforeRender?.(broButton, this.config.texts.search);\n\n const buttonTitle = broButton.getAttribute('button-title') ?? '';\n\n // The search says what it searches: the rows of the table that the toolbar names\n return this.templateToolbarButton(buttonTitle, this.config.texts.searchRole(this.config.toolbarTitle), broButton.iconHTML, 'bro-toolbar-button-search');\n }\n\n private renderButtons(): HTMLElement[] {\n return (this.config.components.toolbarMain.buttons ?? []).map((button: BroButton | BroDropdown) => {\n if (button.mode === 'navbar-dropdown') {\n const broDropdown: HTMLElement = this.dom.createElement(<string>this.config.components.dropdown?.selector);\n\n (<BroConfiguredElement>broDropdown).config = this.config;\n\n broDropdown.setAttribute('mode', 'navbar-dropdown');\n broDropdown.setAttribute('button-title', button.buttonTitle);\n broDropdown.setAttribute('options', JSON.stringify(button.options));\n\n // The menu sends the value of its option as a toolbar action. The toolbar puts the markup of the menu in place\n // of its element (render), so the element sends its value out of the DOM, and only its own listener hears it\n broDropdown.addEventListener('value', (event: Event) => {\n this.dispatchEvent(\n new CustomEvent(events.toolbarEvent, {\n bubbles: true,\n composed: true,\n detail: (<CustomEvent>event).detail\n })\n );\n });\n\n return broDropdown;\n } else {\n const buttonEl = this.templateToolbarButton(button.buttonTitle, this.config.texts.buttonRole, button.iconHTML);\n\n // A config button sends its eventType as a toolbar action, as the Material toolbar does\n buttonEl.querySelector('a')?.addEventListener('click', () => {\n this.dispatchEvent(\n new CustomEvent(events.toolbarEvent, {\n bubbles: true,\n composed: true,\n detail: (<BroButton>button).eventType\n })\n );\n });\n\n return buttonEl;\n }\n });\n }\n}\n","import {type BroButton, BroHTML, BroHTMLElement, type BroView, dispatchAction} from '@table-bro/core';\n\nconst {escape} = BroHTML;\n\nexport class BroButtonComponent extends BroHTMLElement implements BroView, BroButton {\n template(): string {\n this.label = this.getAttribute('label') || '';\n\n this.buttonClassName = this.getAttribute('button-class');\n\n this.buttonTitle = this.getAttribute('button-title') || '';\n this.iconHTML = this.getAttribute('icon-html') || this.iconHTML;\n this.mode = <BroButton['mode']>this.getAttribute('mode') || 'button';\n\n this.eventType = this.getAttribute('event-type') || 'action';\n\n // A button with a title takes its name from the title; a button with an icon only takes the label.\n // The title and the name are text; the icon is the markup of the skin\n const className = this.buttonClassName ? ` class=\"${escape(this.buttonClassName)}\"` : '';\n const ariaLabel = (!this.buttonTitle && this.label) ? ` aria-label=\"${escape(this.label)}\"` : '';\n const content = `${escape(this.buttonTitle)}${this.iconHTML ? `${this.buttonTitle ? '&nbsp;' : ''}${this.iconHTML}` : ''}`;\n\n if (this.mode !== 'link') {\n return `\n <button${className}\n type=\"button\"${ariaLabel}>\n ${content}\n </button>`;\n } else {\n return `\n <a${className} href=\"\"\n role=\"button\"${ariaLabel}>\n ${content}\n </a>`;\n }\n }\n\n label!: string;\n buttonClassName!: string | null;\n buttonTitle!: string;\n iconHTML!: string;\n mode: BroButton['mode'];\n\n eventType!: string;\n\n events() {\n const buttonEl = this.children[0];\n\n buttonEl.addEventListener('click', (event: Event) => {\n dispatchAction(buttonEl, this.eventType);\n\n event.preventDefault();\n });\n\n // A link in the role of a button takes Space as a button does, instead of scrolling the page; Enter clicks a link anyway\n if (this.mode === 'link') {\n buttonEl.addEventListener('keydown', (event: Event) => {\n if ((<KeyboardEvent>event).key === ' ' && !(<KeyboardEvent>event).repeat) {\n event.preventDefault();\n\n (<HTMLElement>buttonEl).click();\n }\n });\n }\n }\n\n render(): void {\n this.insertAdjacentHTML('afterbegin', this.template());\n\n this.events();\n }\n\n connectedCallback(): void {\n if (!this.firstChild) {\n this.render();\n }\n }\n}\n","import {type BroCellElement, broCellSelectors, type BroCol, type BroConfiguredElement, BroHTML, BroHTMLElement, type BroResolvedConfig, type BroRow, type BroTextEllipsis, type BroView} from '@table-bro/core';\n\nconst {escape, text} = BroHTML;\n\nexport class BroTextEllipsisComponent extends BroHTMLElement implements BroView, BroCellElement, BroConfiguredElement, BroTextEllipsis {\n template(): string {\n this.containerClassName = this.getAttribute('container-class');\n this.value = this.getAttribute('value') || '';\n\n return `\n <span class=\"${broCellSelectors.ellipsisContainer}${this.containerClassName ? ` ${escape(this.containerClassName)}` : ''}\">\n <span class=\"${broCellSelectors.ellipsis}\"></span>\n </span>`;\n }\n\n row?: BroRow;\n col?: BroCol;\n // The table sets the config before the element connects\n config!: BroResolvedConfig;\n\n containerClassName!: string | null;\n tooltip!: string;\n value!: string;\n\n /** Cleanup returned by afterRender of the skin, for example the removal of a tooltip. */\n private release?: void | (() => void);\n private released: boolean = false;\n /** A move in the DOM connects the element again; it keeps its markup and listeners. */\n private rendered: boolean = false;\n\n render(): void {\n this.insertAdjacentHTML('afterbegin', this.template());\n\n const valueEl = <Element>this.querySelector(`.${broCellSelectors.ellipsis}`);\n\n // The value is markup only for a column with html: true\n if (this.col?.html) {\n valueEl.innerHTML = this.value;\n this.tooltip = text(this.value);\n } else {\n valueEl.textContent = this.value;\n this.tooltip = this.value;\n }\n\n this.afterRender();\n }\n\n connectedCallback(): void {\n if (this.rendered) {\n if (this.released) {\n this.released = false;\n\n this.afterRender();\n }\n\n return;\n }\n\n this.rendered = true;\n\n this.render();\n }\n\n disconnectedCallback(): void {\n // A move connects the element again in the same task; only a removed element releases the skin callback\n queueMicrotask(() => {\n if (!this.isConnected) {\n if (typeof this.release === 'function') {\n this.release();\n }\n\n this.release = undefined;\n this.released = true;\n }\n });\n }\n\n private afterRender(): void {\n const tooltipEl = this.children[0];\n\n if (this.config.components.textEllipsis.afterRender) {\n this.release = this.config.components.textEllipsis.afterRender(tooltipEl, this.tooltip);\n }\n }\n}\n","import {type BroColSort, type BroConfiguredElement, BroHTML, BroHTMLElement, type BroResolvedConfig, type BroSortDirection, type BroSortHeader, type BroView, dispatchAction, events, isPrerendered} from '@table-bro/core';\n\nconst {escape} = BroHTML;\n\nexport class BroSortHeaderComponent extends BroHTMLElement implements BroView, BroConfiguredElement, BroSortHeader {\n template(): string {\n this.arrowPosition = <BroSortHeader['arrowPosition']>this.getAttribute('arrow-position') || 'after';\n this.sortId = this.getAttribute('sort-id') || '';\n this.dataType = this.getAttribute('data-type') || '';\n this.headerTitle = this.getAttribute('header-title') || '';\n this.iconHTML = this.getAttribute('icon-html') || '';\n this.tooltip = this.getAttribute('tooltip') || '';\n\n let classList: string = '';\n\n if (this.arrowPosition === 'before') {\n classList += ' bro-sort-header-position-before';\n }\n\n // The direction is descending by default\n classList += ' bro-sort-header-descending';\n\n // A control of the column header: Enter and Space sort, as a click does. A header without a title, as of a column\n // of buttons, sorts nothing and is no control, as in the mat skin\n const control = this.headerTitle ? ' role=\"button\" tabindex=\"0\"' : '';\n\n return `\n <div class=\"bro-sort-header-container${classList}\"${control}>\n <div class=\"bro-sort-header-content\">${escape(this.headerTitle)}</div>\n <div class=\"bro-sort-header-arrow\" aria-hidden=\"true\">${this.iconHTML}</div>\n </div>`;\n }\n\n static get observedAttributes(): string[] {\n return ['tooltip'];\n }\n\n config!: BroResolvedConfig;\n\n arrowPosition!: BroSortHeader['arrowPosition'];\n headerTitle!: string;\n dataType!: string;\n iconHTML!: string;\n sortId!: string;\n tooltip!: string;\n\n private _activeSort?: BroColSort;\n private direction: BroSortDirection | '' = '';\n /** Cleanup returned by afterRender of the skin, for example the removal of a tooltip. */\n private release?: void | (() => void);\n private released: boolean = false;\n /** A move in the DOM connects the element again; it keeps its markup and listeners. */\n private rendered: boolean = false;\n\n events() {\n const headerContainerEl = <HTMLElement>this.children[0];\n\n if (!this.headerTitle) {\n return;\n }\n\n headerContainerEl.addEventListener('blur', () => {\n headerContainerEl.classList.remove('bro-sort-header-recently-cleared-ascending');\n });\n\n // The header is a button for the keyboard too: Enter and Space sort it as a click does\n headerContainerEl.addEventListener('keydown', (event: KeyboardEvent) => {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n\n headerContainerEl.click();\n }\n });\n\n headerContainerEl.addEventListener('click', () => {\n if (this.direction === '') {\n this.direction = 'desc';\n\n headerContainerEl.classList.add('bro-sort-header-sorted');\n\n headerContainerEl.classList.remove('bro-sort-header-recently-cleared-ascending');\n } else if (this.direction === 'desc') {\n this.direction = 'asc';\n\n headerContainerEl.classList.remove('bro-sort-header-descending');\n } else if (this.direction === 'asc') {\n this.direction = '';\n\n headerContainerEl.classList.remove('bro-sort-header-sorted');\n headerContainerEl.classList.add('bro-sort-header-descending');\n\n headerContainerEl.classList.add('bro-sort-header-recently-cleared-ascending');\n }\n\n // The third click clears the sort, as in the mat skin: sortDirection is undefined then\n dispatchAction(this, events.filtersSortEvent, {\n sortKey: this.sortId,\n sortDirection: this.direction || undefined\n });\n });\n }\n\n render(): void {\n this.insertAdjacentHTML('afterbegin', this.template());\n\n this.afterRender();\n\n this.events();\n }\n\n get activeSort(): BroColSort | undefined {\n return this._activeSort;\n }\n\n /** A sort of another column resets the arrow of this header. */\n set activeSort(sort: BroColSort) {\n this._activeSort = sort;\n\n const container = this.children[0];\n\n if (this.direction !== '' && sort?.sortKey !== this.sortId && container) {\n this.direction = '';\n\n container.classList.remove('bro-sort-header-sorted');\n container.classList.add('bro-sort-header-descending');\n }\n }\n\n connectedCallback(): void {\n // An element of a prerendered table keeps its markup until the table renders its own elements in its place\n if (isPrerendered(this)) {\n return;\n }\n\n if (this.rendered) {\n if (this.released) {\n this.released = false;\n\n this.afterRender();\n }\n\n return;\n }\n\n this.rendered = true;\n\n this.render();\n }\n\n disconnectedCallback(): void {\n // A move connects the element again in the same task; only a removed element releases the skin callback\n queueMicrotask(() => {\n if (!this.isConnected) {\n if (typeof this.release === 'function') {\n this.release();\n }\n\n this.release = undefined;\n this.released = true;\n }\n });\n }\n\n /** The table gives a new tooltip when the width of the column changes: the skin callback runs again with it. */\n attributeChangedCallback(name: string, oldValue: string | null, value: string | null): void {\n if (!this.rendered || oldValue === value) {\n return;\n }\n\n this.tooltip = value || '';\n\n if (typeof this.release === 'function') {\n this.release();\n }\n\n this.release = undefined;\n\n // A header out of the document gets the callback again when it is connected\n if (this.isConnected) {\n this.afterRender();\n } else {\n this.released = true;\n }\n }\n\n private afterRender(): void {\n const container = this.children[0];\n\n // A prerender runs no scripts of the browser, as the tooltips of a skin\n if (this.config.prerender) {\n return;\n }\n\n this.release = this.config.components.sortHeader.afterRender?.(container, this.tooltip);\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.dev/license\n */\n\nimport type {BroConfiguredElement, BroDropdownOption, BroPaginatorElement, BroPaginatorPageEvent, BroResolvedConfig, BroTexts, BroView} from '@table-bro/core';\nimport {BroDom, BroHTML, BroHTMLElement, isPrerendered} from '@table-bro/core';\n\nconst {escape} = BroHTML;\n\nexport class BroPaginatorComponent extends BroHTMLElement implements BroView, BroConfiguredElement, BroPaginatorElement {\n template(): string {\n this.disabled = this.getAttribute('disabled') === 'true' || false;\n this.length = Number(this.getAttribute('length')) || 0;\n this.pageIndex = Math.max(Number(this.getAttribute('page-index')) || 0, 0);\n this.pageSize = Number(this.getAttribute('page-size'));\n // The table writes 'true' or 'false'; without the attribute the buttons are shown\n this.showFirstLastButtons = this.getAttribute('show-first-last-buttons') !== 'false';\n\n this.parsePageSizeOptions();\n\n const texts = this.texts = this.config.texts;\n\n // The vanilla skins, which have this paginator, give the classes of its list and their dropdown\n const ul = this.config.components.paginator.css?.ul;\n // No class attribute for a class the skin does not give\n const ulClass = ul?.className ? ` class=\"${escape(ul.className)}\"` : '';\n const liClass = ul?.li?.className ? ` class=\"${escape(ul.li.className)}\"` : '';\n const aClass = ul?.li?.a?.className ? `${escape(ul.li.a.className)} ` : '';\n\n this.dropdownSelector = <string>this.config.components.dropdown?.selector;\n\n return `\n <div class=\"bro-paginator-outer-container\">\n <div class=\"bro-paginator-inner-container\">\n <div class=\"bro-paginator-page-size\">\n <div class=\"bro-paginator-page-size-label\">\n ${escape(texts.itemsPerPage)}\n </div>\n\n ${this.pageSizeDropdown?.length ? '' : this.templatePageSizeValue()}\n </div>\n\n <div class=\"bro-paginator-range-actions\">\n <div class=\"bro-paginator-range-label\" aria-live=\"polite\">\n ${escape(texts.rangeLabel(this.pageIndex, this.pageSize, this.length))}\n </div>\n\n <nav aria-label=\"${escape(texts.pageNavigation)}\">\n <ul${ulClass}>\n ${this.showFirstLastButtons\n ? `\n <li${liClass}>\n <a class=\"${aClass}bro-paginator-navigation-first\" href=\"\"\n aria-label=\"${escape(texts.firstPage)}\">${escape(texts.first)}</a>\n </li>`\n : ''\n }\n\n <li${liClass}>\n <a class=\"${aClass}bro-paginator-navigation-previous\" href=\"\"\n aria-label=\"${escape(texts.previousPage)}\">${escape(texts.previous)}</a>\n </li>\n\n <li${liClass}>\n <a class=\"${aClass}bro-paginator-navigation-next\" href=\"\"\n aria-label=\"${escape(texts.nextPage)}\">${escape(texts.next)}</a>\n </li>\n\n ${this.showFirstLastButtons\n ? `\n <li${liClass}>\n <a class=\"${aClass}bro-paginator-navigation-last\" href=\"\"\n aria-label=\"${escape(texts.lastPage)}\">${escape(texts.last)}</a>\n </li>`\n : ''\n }\n </ul>\n </nav>\n </div>\n </div>\n </div>`;\n }\n\n static get observedAttributes() {\n return [\n 'page-index', 'page-size', 'length',\n 'page-size-options', 'disabled'\n ];\n }\n\n // The table sets the config, and the template reads the other values from the attributes, before the element renders\n config!: BroResolvedConfig;\n\n disabled!: boolean;\n length!: number;\n pageIndex!: number;\n pageSize!: number;\n pageSizeOptions!: number[];\n showFirstLastButtons!: boolean;\n\n private page!: BroPaginatorPageEvent;\n private eventName = 'page';\n\n // The elements of the template of the paginator, found when it renders\n private firstEl!: HTMLElement;\n private previousEl!: HTMLElement;\n private nextEl!: HTMLElement;\n private lastEl!: HTMLElement;\n\n private pageSizeEl!: HTMLElement;\n private pageSizeValueEl!: HTMLElement;\n private rangeLabelEl!: HTMLElement;\n\n private dropdownSelector!: string;\n /** The texts of the table, taken at the render: before it the attributes change nothing. */\n private texts?: BroTexts;\n private pageSizeDropdown?: BroDropdownOption[];\n /** A move in the DOM connects the element again; it keeps its markup and listeners. */\n private rendered: boolean = false;\n\n events() {\n this.previousEl = <HTMLElement>this.querySelector('.bro-paginator-navigation-previous');\n this.nextEl = <HTMLElement>this.querySelector('.bro-paginator-navigation-next');\n\n this.previousEl.addEventListener('click', (event: Event) => {\n event.preventDefault();\n\n if (!this.hasPreviousPage()) {\n return;\n }\n\n this.navigate(this.pageIndex - 1);\n });\n\n this.nextEl.addEventListener('click', (event: Event) => {\n event.preventDefault();\n\n if (!this.hasNextPage()) {\n return;\n }\n\n this.navigate(this.pageIndex + 1);\n });\n\n if (this.showFirstLastButtons) {\n this.firstEl = <HTMLElement>this.querySelector('.bro-paginator-navigation-first');\n this.lastEl = <HTMLElement>this.querySelector('.bro-paginator-navigation-last');\n\n this.firstEl.addEventListener('click', (event: Event) => {\n event.preventDefault();\n\n if (!this.hasPreviousPage()) {\n return;\n }\n\n this.navigate(0);\n });\n\n this.lastEl.addEventListener('click', (event: Event) => {\n event.preventDefault();\n\n if (!this.hasNextPage()) {\n return;\n }\n\n this.navigate(this.getNumberOfPages() - 1);\n });\n }\n }\n\n render(): void {\n this.insertAdjacentHTML('afterbegin', this.template());\n\n // The list gets the config of the table before it connects\n if (this.pageSizeDropdown?.length) {\n this.pageSizeEl = <HTMLElement>this.querySelector('.bro-paginator-page-size');\n\n this.renderPageSizeDropdown();\n }\n\n this.events();\n\n this.renderNavigationState();\n }\n\n connectedCallback(): void {\n // An element of a prerendered table keeps its markup until the table renders its own elements in its place\n if (isPrerendered(this)) {\n return;\n }\n\n if (this.rendered) {\n return;\n }\n\n this.rendered = true;\n\n this.render();\n }\n\n attributeChangedCallback(name: string, previousValue: string, currentValue: string) {\n if (!this.texts) {\n return;\n }\n\n if (name === 'page-index' || name === 'page-size' || name === 'length') {\n if (!this.rangeLabelEl) {\n this.rangeLabelEl = <HTMLElement>this.querySelector('.bro-paginator-range-label');\n }\n\n if (!this.pageSizeValueEl) {\n this.pageSizeValueEl = <HTMLElement>this.querySelector('.bro-paginator-page-size-value');\n }\n\n if (name === 'page-index') {\n this.pageIndex = +currentValue;\n }\n\n if (name === 'page-size') {\n this.pageSize = +currentValue;\n\n if (!this.pageSizeOptions.length) {\n this.pageSizeValueEl.innerText = currentValue;\n }\n }\n\n if (name === 'length') {\n this.length = +currentValue;\n }\n\n this.rangeLabelEl.textContent = this.texts.rangeLabel(this.pageIndex, this.pageSize, this.length);\n\n this.renderNavigationState();\n }\n\n if (name === 'page-size-options') {\n this.parsePageSizeOptions();\n\n this.unrenderPageSizeControls();\n\n if (!this.pageSizeEl) {\n this.pageSizeEl = <HTMLElement>this.querySelector('.bro-paginator-page-size');\n }\n\n if (this.pageSizeDropdown?.length) {\n this.renderPageSizeDropdown();\n } else {\n this.renderPageSizeValue();\n\n this.setAttribute('disabled', true.toString());\n }\n }\n\n if (name === 'disabled') {\n this.setDisabledState(currentValue === true.toString());\n }\n }\n\n /** Whether there is a previous page. */\n hasPreviousPage(): boolean {\n return this.pageIndex >= 1 && this.pageSize != 0;\n }\n\n /** Whether there is a next page. */\n hasNextPage(): boolean {\n const maxPageIndex = this.getNumberOfPages() - 1;\n\n return this.pageIndex < maxPageIndex && this.pageSize != 0;\n }\n\n /** Calculate the number of pages */\n getNumberOfPages(): number {\n if (!this.pageSize) {\n return 0;\n }\n\n return Math.ceil(this.length / this.pageSize);\n }\n\n private parsePageSizeOptions() {\n if (!this.getAttribute('page-size-options')) {\n return;\n }\n\n try {\n this.pageSizeOptions = JSON.parse(<string>this.getAttribute('page-size-options'))\n .map((item: string) => +item);\n\n this.pageSizeDropdown = this.pageSizeOptions.map(item => {\n return {\n value: item.toString(),\n title: item.toString()\n };\n });\n } catch (err) {\n this.pageSizeOptions = [];\n\n if (this.config.debug) {\n console.log(err);\n }\n }\n }\n\n private templatePageSizeValue(): string {\n return `<div class=\"bro-paginator-page-size-value\">${this.pageSize}</div>`;\n }\n\n private unrenderPageSizeControls(): void {\n const dropdown = <HTMLElement>this.querySelector(this.dropdownSelector);\n\n if (dropdown) {\n dropdown.remove();\n }\n\n const pageSizeValueEl = <HTMLElement>this.querySelector('.bro-paginator-page-size-value');\n\n if (pageSizeValueEl) {\n pageSizeValueEl.remove();\n }\n }\n\n private renderPageSizeDropdown(): void {\n const broDropdown: HTMLElement = new BroDom(this.ownerDocument).createElement(this.dropdownSelector);\n\n (<BroConfiguredElement>broDropdown).config = this.config;\n broDropdown.setAttribute('mode', 'select');\n broDropdown.setAttribute('button-title', this.pageSize.toString());\n broDropdown.setAttribute('options', JSON.stringify(this.pageSizeDropdown));\n broDropdown.setAttribute('label', this.texts!.itemsPerPage);\n // The list takes the state of the paginator at its render, as the select of MatPaginator does\n broDropdown.setAttribute('disabled', this.disabled.toString());\n\n this.eventsPageSize(broDropdown);\n\n this.pageSizeEl.append(\n broDropdown\n );\n }\n\n private eventsPageSize(broDropdown: Element) {\n broDropdown.addEventListener('value', (event: Event) => {\n const value: string = (<CustomEvent>event).detail;\n\n this.changePageSize(+value);\n\n this.setAttribute('page-size', value);\n });\n }\n\n private renderPageSizeValue(): void {\n this.pageSizeEl.insertAdjacentHTML('beforeend', this.templatePageSizeValue());\n }\n\n private setDisabledState(disable: boolean) {\n this.disabled = disable;\n\n const dropdown = <HTMLElement>this.querySelector(this.dropdownSelector);\n\n if (dropdown) {\n dropdown.setAttribute('disabled', disable.toString());\n }\n\n this.renderNavigationState();\n }\n\n /**\n * Disables the buttons of a disabled paginator, First and Previous on the first page, and Next and Last on the last\n * one, as MatPaginator does.\n */\n private renderNavigationState(): void {\n const noPrevious = this.disabled || !this.hasPreviousPage();\n const noNext = this.disabled || !this.hasNextPage();\n const buttons: [HTMLElement | undefined, boolean][] = [[this.firstEl, noPrevious], [this.previousEl, noPrevious], [this.nextEl, noNext], [this.lastEl, noNext]];\n\n buttons.forEach(([button, disable]) => {\n // The class shows the state, and aria-disabled tells it to screen readers\n if (disable) {\n button?.parentElement?.classList.add('disabled');\n button?.setAttribute('aria-disabled', 'true');\n } else {\n button?.parentElement?.classList.remove('disabled');\n button?.removeAttribute('aria-disabled');\n }\n });\n }\n\n /** Navigates to a specific page index. */\n private navigate(index: number) {\n const previousIndex = this.pageIndex;\n\n if (index !== previousIndex) {\n this.pageIndex = index;\n this.setAttribute('page-index', this.pageIndex.toString());\n this.emitPageEvent(previousIndex);\n }\n }\n\n /**\n * Changes the page size so that the first item displayed on the page will still be\n * displayed using the new page size.\n *\n * For example, if the page size is 10 and on the second page (items indexed 10-19) then\n * switching so that the page size is 5 will set the third page as the current page so\n * that the 10th item will still be displayed.\n */\n changePageSize(pageSize: number) {\n // Current page needs to be updated to reflect the new page size. Navigate to the page\n // containing the previous page's first item.\n const startIndex = this.pageIndex * this.pageSize;\n const previousIndex = this.pageIndex;\n\n this.pageIndex = Math.floor(startIndex / pageSize) || 0;\n this.pageSize = pageSize;\n this.emitPageEvent(previousIndex);\n }\n\n /** Emits an event notifying that a change of the paginator's properties has been triggered. */\n private emitPageEvent(previousPageIndex: number) {\n this.page = {\n previousPageIndex,\n pageIndex: this.pageIndex,\n pageSize: this.pageSize,\n length: this.length\n };\n\n this.dispatchEvent(\n new CustomEvent(this.eventName, {\n bubbles: true,\n composed: true,\n detail: this.page\n })\n );\n }\n}\n","import {BroSwitchComponent} from './bootstrap-based/bro-switch';\nimport {BroToolbarComponent} from './bootstrap-based/toolbar/bro-toolbar';\nimport {BroToolbarMainComponent} from './bootstrap-based/toolbar/bro-toolbar-main';\nimport {BroButtonComponent} from './bro-button';\nimport {BroTextEllipsisComponent} from './bro-text-ellipsis';\nimport {BroSortHeaderComponent} from './material-based/bro-sort-header';\nimport {BroPaginatorComponent} from './material-based/paginator/bro-paginator';\n\n/** The elements that the bs and nv skins share. */\nconst sharedElements: Record<string, CustomElementConstructor> = {\n 'bro-button': BroButtonComponent,\n 'bro-paginator': BroPaginatorComponent,\n 'bro-sort-header': BroSortHeaderComponent,\n 'bro-text-ellipsis': BroTextEllipsisComponent,\n 'bro-toolbar': BroToolbarComponent,\n 'bro-toolbar-main': BroToolbarMainComponent\n};\n\n/**\n * Defines the optional element bro-switch, a boolean of a column as a switch, unless it is defined; without a DOM, as\n * in the server render, it does nothing.\n */\nexport function withSwitch(): void {\n defineElement('bro-switch', BroSwitchComponent);\n}\n\n/**\n * Defines an element of a skin unless it is defined: a second load of the bundle of the skin finds it defined.\n * @param name - the tag of the element\n * @param element - the class of the element\n * @param registry - the registry of the custom elements: the one of the page by default, none without a DOM\n */\nexport function defineElement(name: string, element: CustomElementConstructor, registry: CustomElementRegistry | undefined = (typeof customElements !== 'undefined') ? customElements : undefined): void {\n if (registry && !registry.get(name)) {\n registry.define(name, element);\n }\n}\n\n/**\n * Defines the shared elements of a vanilla skin. Each skin bundle carries its own copy of them, so with two bundles\n * on one page the bundle loaded first defines them and the other skin works with its classes. Two vanilla skin\n * bundles on one page are not supported, so the skin loaded second warns about it.\n * @param skinPackage - the package of the skin, for the warning\n * @param registry - the registry of the custom elements\n */\nexport function defineSharedElements(skinPackage: string, registry: CustomElementRegistry): void {\n const definedElsewhere: string[] = [];\n\n Object.entries(sharedElements).forEach(([name, element]) => {\n const defined = registry.get(name);\n\n if (!defined) {\n registry.define(name, element);\n } else if (defined !== element) {\n definedElsewhere.push(name);\n }\n });\n\n if (definedElsewhere.length) {\n console.warn(`${skinPackage}: ${definedElsewhere.join(', ')} are already defined by another vanilla skin bundle, `\n + 'so this skin uses its elements. Load one vanilla skin bundle per page.');\n }\n}\n","import {BroTagsComponent} from '../../shared/js/bro-tags';\n\n/** The tags of the native skin: marks. */\nexport class BroNativeTagsComponent extends BroTagsComponent {\n protected readonly tagHTML: string = '<mark></mark>';\n}\n","import {type BroConfiguredElement, type BroDropdown, type BroDropdownOption, BroHTML, BroHTMLElement, type BroResolvedConfig, type BroView, isPrerendered} from '@table-bro/core';\n\nconst {escape} = BroHTML;\n\nexport class BroNativeDropdownComponent extends BroHTMLElement implements BroView, BroConfiguredElement, BroDropdown {\n template(): string {\n this.buttonTitle = this.getAttribute('button-title') || '';\n this.name = this.getAttribute('name') || 'action';\n this.mode = <BroDropdown['mode']>this.getAttribute('mode') || 'dropdown';\n\n try {\n this.options = JSON.parse(<string>this.getAttribute('options'));\n } catch (err) {\n this.options = [];\n\n if (this.config.debug) {\n console.log(err);\n }\n }\n\n // The select takes the name that the element gets, such as the label of the page size, else its title, as More\n const label = this.getAttribute('label') || this.buttonTitle;\n // The titles, the values and the names of the config are text in the markup\n const ariaLabel = label ? ` aria-label=\"${escape(label)}\"` : '';\n\n if (this.mode === 'select' || this.mode === 'dropdown') {\n return `\n <select name=\"${escape(this.name)}\"${ariaLabel}>\n <option value=\"\" hidden>${escape(this.buttonTitle)}</option>\n ${this.templateDropdown(this.options)}\n </select>`;\n } else {\n // navbar-dropdown\n return `\n <li class=\"bro-nav-item bro-dropdown\">\n <select name=\"${escape(this.name)}\"${ariaLabel}>\n <option value=\"\" hidden>${escape(this.buttonTitle)}</option>\n ${this.templateDropdown(this.options)}\n </select>\n </li>`;\n }\n }\n\n static get observedAttributes() {\n return [\n 'disabled'\n ];\n }\n\n config!: BroResolvedConfig;\n\n buttonTitle!: string;\n name!: string;\n\n mode!: BroDropdown['mode'];\n options!: BroDropdownOption[];\n\n private eventName = 'value';\n\n private dropdownToggleEl!: HTMLElement;\n /** A move in the DOM connects the element again; it keeps its markup and listeners. */\n private rendered: boolean = false;\n\n /**\n * The select sends its value. A menu (navbar-dropdown) shows its title again after a choice, and acts only on a choice:\n * the keys of a closed select change its value on Windows, so a value that came from the keyboard waits for Enter.\n */\n events() {\n const select = <HTMLSelectElement>this.querySelector('select');\n const menu = (this.mode === 'navbar-dropdown');\n\n let keyboard = false;\n let pending: string | null = null;\n\n this.dropdownToggleEl = select;\n this.renderDisabled();\n\n const send = (value: string) => {\n pending = null;\n\n if (menu) {\n select.selectedIndex = 0;\n }\n\n this.dispatchEvent(\n new CustomEvent(this.eventName, {\n bubbles: true,\n composed: true,\n detail: value\n })\n );\n };\n\n if (menu) {\n select.addEventListener('pointerdown', () => {\n keyboard = false;\n });\n\n select.addEventListener('keydown', (event: KeyboardEvent) => {\n keyboard = (event.key !== 'Enter');\n\n if (event.key === 'Enter' && pending !== null) {\n send(pending);\n }\n });\n\n // A value that the keyboard chose and did not confirm leaves with the focus\n select.addEventListener('blur', () => {\n if (pending !== null) {\n pending = null;\n select.selectedIndex = 0;\n }\n });\n }\n\n select.addEventListener('change', () => {\n if (menu && keyboard) {\n pending = select.value;\n } else {\n send(select.value);\n }\n });\n }\n\n render(): void {\n this.insertAdjacentHTML('afterbegin', this.template());\n\n this.events();\n }\n\n connectedCallback(): void {\n // An element of a prerendered table keeps its markup until the table renders its own elements in its place\n if (isPrerendered(this)) {\n return;\n }\n\n if (this.rendered) {\n return;\n }\n\n this.rendered = true;\n\n this.render();\n }\n\n attributeChangedCallback(name: string) {\n // Before its render the element has no select: the render takes the attribute\n if (name === 'disabled' && this.dropdownToggleEl) {\n this.renderDisabled();\n }\n }\n\n private templateDropdown(options: BroDropdownOption[]): string {\n return `\n ${options.map((option: BroDropdownOption) => {\n if ('value' in option && 'title' in option) {\n return `\n <option value=\"${escape(option.value)}\">${escape(option.title)}</option>`;\n } else if ('divider' in option) {\n return `\n <hr>`;\n } else if ('header' in option) {\n return `\n <optgroup label=\"${escape(option.header)}\"></optgroup>`;\n }\n }).join('')}`;\n }\n\n /** The select is disabled by the attribute disabled=\"true\". */\n private renderDisabled(): void {\n this.dropdownToggleEl.toggleAttribute('disabled', this.getAttribute('disabled') === 'true');\n }\n}\n","import {type BroConfiguredElement, BroHTML, BroHTMLElement, type BroProgressBar, type BroProgressMode, type BroResolvedConfig, type BroView, isPrerendered} from '@table-bro/core';\n\nconst {escape} = BroHTML;\n\nexport class BroNativeProgressBarComponent extends BroHTMLElement implements BroView, BroConfiguredElement, BroProgressBar {\n template(): string {\n // The skin has no colors of the bar; the contract keeps the attribute of the table\n this.color = this.getAttribute('color') || '';\n\n this.mode = <BroProgressMode>this.getAttribute('mode') || 'indeterminate';\n\n const indeterminate = (this.mode === 'indeterminate');\n\n this.value = (indeterminate ? 100 : (this.getAttribute('value') || 0))\n .toString();\n\n return `\n <progress ${indeterminate ? '' : `value=\"${this.value}\"`}\n max=\"${indeterminate ? '' : 100}\" aria-label=\"${escape(this.config.texts.loadingProgress)}\"></progress>`;\n }\n\n static get observedAttributes() {\n return [\n 'value'\n ];\n }\n\n config!: BroResolvedConfig;\n\n color!: string;\n mode!: BroProgressMode;\n value!: string;\n\n /** A move in the DOM connects the element again; it keeps its markup and listeners. */\n private rendered: boolean = false;\n private valueEl!: HTMLProgressElement;\n\n render(): void {\n this.insertAdjacentHTML('afterbegin', this.template());\n }\n\n connectedCallback(): void {\n // An element of a prerendered table keeps its markup until the table renders its own elements in its place\n if (isPrerendered(this)) {\n return;\n }\n\n if (this.rendered) {\n return;\n }\n\n this.rendered = true;\n\n this.render();\n }\n\n attributeChangedCallback(name: string, previousValue: string, currentValue: string) {\n if (this.mode === 'determinate' && name === 'value') {\n if (!this.valueEl) {\n this.valueEl = <HTMLProgressElement>this.querySelector('progress');\n }\n\n this.valueEl.value = +currentValue;\n }\n }\n}\n","import type {BroButton, BroSkinConfig} from '@table-bro/core';\n\nimport {defineElement, defineSharedElements} from '../../shared/js/define-shared-elements';\nimport {BroNativeDropdownComponent} from './bro-dropdown.native';\nimport {BroNativeProgressBarComponent} from './bro-progress-bar.native';\n\n// The constant keeps the type of its value: an application reads its buttons and its states without checks of undefined\nexport const nativeSkinConfig = {\n css: {\n table: {\n thead: {\n tr: {\n className: 'bro-header-row',\n\n th: {\n className: 'bro-header-cell'\n }\n }\n },\n\n tbody: {\n tr: {\n className: 'bro-row',\n\n td: {\n className: 'bro-cell'\n }\n }\n }\n },\n\n shadow: {\n className: 'shadow-lg'\n }\n },\n\n components: {\n button: {\n selector: 'bro-button',\n\n iconSelector: '.bro-button-toggle',\n\n beforeRender: (element: Element, value: string) => {\n element.setAttribute('mode', 'link');\n element.setAttribute('button-title', value);\n element.setAttribute('icon-html', '<span class=\"bro-button-toggle\"></span>');\n }\n },\n dropdown: {\n selector: 'bro-nv-dropdown'\n },\n filterDrawer: {\n beforeRender: (closeButton: Element) => {\n (<Element & BroButton>closeButton).iconHTML = '&times;';\n closeButton.setAttribute('button-class', 'bro-nav-link');\n closeButton.setAttribute('mode', 'link');\n }\n },\n paginator: {\n selector: 'bro-paginator',\n\n css: {\n ul: {\n className: 'bro-pagination',\n\n li: {\n className: 'bro-page-item',\n\n a: {\n className: 'bro-page-link'\n }\n }\n }\n }\n },\n progressBar: {\n selector: 'bro-nv-progress-bar'\n },\n sortHeader: {\n selector: 'bro-sort-header',\n contentSelector: '.bro-sort-header-content',\n\n beforeRender: <(element: Element, value: string) => void>((element: Element) => {\n element.setAttribute('icon-html', '<span class=\"bro-button-icon\">&#9660;</span>');\n }),\n afterRender: (element: Element, value: string) => {\n element.setAttribute('title', value);\n }\n },\n state: {\n states: {\n loading: ['🚀', 'Loading'],\n 'no-data': ['💔', 'No data'],\n 'not-found': ['🔦', 'No records found'],\n fail: ['😕', 'Failed']\n }\n },\n switch: {\n selector: 'bro-switch',\n\n css: {\n div: {\n className: 'bro-form-check bro-form-switch',\n\n input: {\n className: 'bro-form-check-input'\n }\n }\n }\n },\n textEllipsis: {\n selector: 'bro-text-ellipsis',\n\n afterRender: (element: Element, value: string) => {\n element.setAttribute('title', value);\n }\n },\n toolbar: {\n selector: 'bro-toolbar',\n\n css: {\n nav: {\n className: 'bro-navbar bro-navbar-expand'\n }\n }\n },\n toolbarMain: {\n selector: 'bro-toolbar-main',\n\n css: {\n toolbarTitle: {\n className: 'bro-navbar-brand'\n },\n navbarCollapse: {\n className: 'bro-navbar-collapse',\n\n ul: {\n li: {\n className: 'bro-nav-item',\n\n a: {\n className: 'bro-nav-link'\n }\n }\n }\n }\n },\n\n // The value is the word of the search button, texts.search of the config\n beforeRender: (searchButton: Element, value: string) => {\n searchButton.setAttribute('button-title', value);\n }\n },\n toolbarSearch: {\n beforeRender: (backButton: Element, clearButton: Element) => {\n (<Element & BroButton>backButton).iconHTML = '&larr;';\n backButton.setAttribute('button-class', 'bro-nav-link');\n backButton.setAttribute('mode', 'link');\n\n (<Element & BroButton>clearButton).iconHTML = '&times;';\n clearButton.setAttribute('button-class', 'bro-nav-link');\n clearButton.setAttribute('mode', 'link');\n }\n }\n },\n\n // The optional elements: a table that uses one undefined names its function in the console\n elements: {\n 'bro-nv-tags': 'withTags',\n 'bro-switch': 'withSwitch'\n },\n\n // The optional elements, tags and switch, come with withTags() and withSwitch()\n defineElements: (registry: CustomElementRegistry): void => {\n defineSharedElements('@table-bro/native', registry);\n\n defineElement('bro-nv-dropdown', BroNativeDropdownComponent, registry);\n defineElement('bro-nv-progress-bar', BroNativeProgressBarComponent, registry);\n }\n} satisfies BroSkinConfig;\n","import {registerSkin} from '@table-bro/core';\n\nimport {type BroTagsTexts, setTagsTexts} from '../../shared/js/bro-tags';\nimport {defineElement} from '../../shared/js/define-shared-elements';\nimport {BroNativeTagsComponent} from './bro-tags.native';\nimport {nativeSkinConfig} from './table-bro.native.config';\n\n// The elements are defined only in the browser: imported without a DOM, as in the server render, the skin only\n// registers its config, and a prerender defines them in its server DOM (defineElements). The optional elements, tags\n// and switch, come with withTags() and withSwitch()\nif (typeof customElements !== 'undefined') {\n nativeSkinConfig.defineElements(customElements);\n}\n\nregisterSkin('nv', nativeSkinConfig);\n\n/**\n * Defines the optional element bro-nv-tags, the items of a column as tags, unless it is defined; without a DOM, as in\n * the server render, it does nothing. A page without the call does not carry the code of the tags.\n * @param options - the texts of the tags, as {texts: {empty: 'No tags'}}; setTagsTexts() changes them later\n * @param options.texts - the texts of the tags\n */\nexport function withTags(options: {texts?: Partial<BroTagsTexts>} = {}): void {\n setTagsTexts(options.texts ?? {});\n defineElement('bro-nv-tags', BroNativeTagsComponent);\n}\n\nexport * from './table-bro.native.config';\nexport {BroNativeTagsComponent} from './bro-tags.native';\nexport {BroSwitchComponent} from '../../shared/js/bootstrap-based/bro-switch';\nexport {setTagsTexts} from '../../shared/js/bro-tags';\nexport type {BroTagsTexts} from '../../shared/js/bro-tags';\nexport {withSwitch} from '../../shared/js/define-shared-elements';\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,77 @@
1
1
  {
2
2
  "name": "@table-bro/native",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "1.2.0",
4
+ "description": "Pixel-perfect Material data tables for Angular, and more. A Web Components table engine on top of existing UI components.",
5
+ "keywords": [
6
+ "table",
7
+ "data-table",
8
+ "datatable",
9
+ "data-grid",
10
+ "web-components",
11
+ "native",
12
+ "mcp",
13
+ "ai-coding-agents",
14
+ "vibe-coding",
15
+ "claude-code",
16
+ "cursor",
17
+ "codex",
18
+ "github-copilot",
19
+ "windsurf",
20
+ "gemini-cli",
21
+ "grok",
22
+ "cline",
23
+ "zed",
24
+ "jetbrains-ai"
25
+ ],
26
+ "author": "table-bro",
27
+ "homepage": "https://table-bro.com",
28
+ "repository": {
29
+ "type": "git",
30
+ "url": "git+https://github.com/table-bro/table-bro.git",
31
+ "directory": "packages/skins/native"
32
+ },
33
+ "bugs": {
34
+ "url": "https://github.com/table-bro/table-bro/issues"
35
+ },
36
+ "license": "MIT",
37
+ "type": "module",
38
+ "main": "dist/table-bro.native.esm.js",
39
+ "module": "dist/table-bro.native.esm.js",
40
+ "types": "dist/table-bro.native.d.ts",
41
+ "exports": {
42
+ ".": {
43
+ "types": "./dist/table-bro.native.d.ts",
44
+ "import": "./dist/table-bro.native.esm.js",
45
+ "default": "./dist/table-bro.native.esm.js"
46
+ },
47
+ "./dist/*.css": "./dist/*.css",
48
+ "./styles/*": "./styles/*"
49
+ },
50
+ "unpkg": "dist/table-bro.native.umd.js",
51
+ "jsdelivr": "dist/table-bro.native.umd.js",
52
+ "sideEffects": [
53
+ "./js/index.ts",
54
+ "./js/table-bro.native.ts",
55
+ "./dist/table-bro.native.esm.js",
56
+ "./dist/table-bro.native.umd.js",
57
+ "./dist/*.css"
58
+ ],
59
+ "files": [
60
+ "dist/",
61
+ "styles/",
62
+ "THIRD_PARTY_NOTICES.md"
63
+ ],
64
+ "scripts": {
65
+ "build": "tsdown && node ../../../scripts/build-css.mjs . table-bro.native",
66
+ "build:js": "tsdown",
67
+ "build:css": "node ../../../scripts/build-css.mjs . table-bro.native",
68
+ "watch": "tsdown --watch"
69
+ },
70
+ "peerDependencies": {
71
+ "@table-bro/core": "^1.2.0"
72
+ },
73
+ "devDependencies": {
74
+ "tsdown": "^0.23.0",
75
+ "typescript": "^5.8.3"
76
+ }
77
+ }
@@ -0,0 +1,3 @@
1
+ // The SCSS API of the core without its CSS: the mixins for custom table styles, the same for every skin.
2
+ // A stylesheet that needs only them, such as the styles of a page or of a component, uses this module: @use "table-bro.api" as *.
3
+ @forward "./mixins/text-ellipsis" show bro-text-ellipsis-width;
@@ -0,0 +1,5 @@
1
+ // The SCSS API of the native skin without its CSS: the variables of the skin and the mixins of table-bro.api.
2
+ // A stylesheet that needs only them, such as the styles of a component, uses this module instead of table-bro.native,
3
+ // whose @use prints the CSS of the skin. It takes the same configuration: @use "table-bro.native.api" with (...).
4
+ @forward "./skin/vanilla-js/native/variables";
5
+ @forward "./table-bro.api";
@@ -0,0 +1,5 @@
1
+ @mixin bro-text-ellipsis-width($column-classname, $width) {
2
+ #{$column-classname} .bro-cell_component {
3
+ width: $width;
4
+ }
5
+ }
@@ -0,0 +1,14 @@
1
+ // Hides an element from the eye, not from screen readers. The one rule of the core and the skins: the class
2
+ // bro-visually-hidden of the core and the hidden items of a component cell of the skins (mixin bro-cell-items) take it
3
+ @mixin bro-visually-hidden() {
4
+ position: absolute;
5
+
6
+ overflow: hidden;
7
+
8
+ width: 1px;
9
+ height: 1px;
10
+
11
+ white-space: nowrap;
12
+
13
+ clip-path: inset(50%);
14
+ }
@@ -0,0 +1,94 @@
1
+ // The variables every skin has. Each skin forwards this file with its own values (skin/<skin>/_variables.scss),
2
+ // and users change them with @use "table-bro.<skin>" with (...). A variable of one skin lives in the file of that skin.
3
+ // The sizes and timings that the table script reads too go to the host as custom properties
4
+ // (skin/shared/mixins/_custom-properties.scss).
5
+ $bro-skin: null !default;
6
+
7
+
8
+ // Table
9
+ $bro-table-width: null !default; // or px-value, or 100%;
10
+ $bro-table-header-height: null !default;
11
+ $bro-table-row-height: null !default;
12
+ $bro-row-horizontal-padding: null !default;
13
+ $bro-table-shadow-size: null !default;
14
+
15
+ // The space between the islands of the table, as between the table and its filter drawer
16
+ $bro-island-space-size: null !default;
17
+
18
+ // The radius of the corners of the table; 0 keeps them square
19
+ $bro-corner-radius: null !default;
20
+
21
+
22
+ // Toolbar and paginator
23
+ $bro-toolbar-height: null !default;
24
+ $bro-paginator-height: null !default;
25
+
26
+ // The narrowest table, as wide as its paginator in one line, and the filter drawer lies over a table that would be narrower
27
+ // next to it. The range of the paginator writes the number of rows, so 1000 rows, as 996 – 1,000 of 1,000 on their
28
+ // last page, need a wider table than fewer rows: the skins take this width, and a page with fewer rows may set a smaller one
29
+ $bro-table-min-width: null !default;
30
+
31
+
32
+ // Table cells
33
+ $bro-cell-number-width: null !default;
34
+
35
+
36
+ // Filter drawer
37
+ $bro-filter-drawer-width: null !default;
38
+ $bro-filter-drawer-corner-radius: null !default;
39
+
40
+ // The scrim over the table of the modal filter drawer
41
+ $bro-scrim-color: null !default;
42
+
43
+
44
+ // Progress
45
+ $bro-global-progress: null !default;
46
+ $bro-details-progress: null !default;
47
+
48
+ // How much the body fades during a refresh, from 0 to 1, in the light and the dark theme
49
+ $bro-refresh-overlay-opacity: null !default;
50
+ $bro-refresh-overlay-opacity-dark: null !default;
51
+
52
+
53
+ // State
54
+ $bro-state-icon-size: null !default;
55
+ $bro-state-icon-margin-right: null !default;
56
+ $bro-state-line-height: null !default;
57
+ $bro-state-message-font-size: null !default;
58
+
59
+
60
+ // Motion
61
+ $bro-column-width-duration: null !default; // the motion of the columns to their new widths
62
+ $bro-details-duration: null !default;
63
+ $bro-details-easing: null !default; // the curve of the eased row details and of the turn of their button
64
+ $bro-filter-drawer-duration: null !default;
65
+ $bro-kinetic-time-constant: null !default; // the time constant of the exponential decay, not its duration
66
+ $bro-state-icon-duration: null !default;
67
+ $bro-state-message-duration: null !default;
68
+
69
+
70
+ // Layers: the containers of the table and the shadows under them
71
+ $bro-table-container-z-index: null !default;
72
+ $bro-shadow-z-index: null !default;
73
+
74
+ // The layers above the containers of the table, from the bottom up: the header and the paginator over the rows,
75
+ // the filter drawer next to the table, the toolbar with its menus over that drawer, and the modal filter drawer
76
+ // over the whole table, its toolbar too
77
+ $bro-header-paginator-z-index: $bro-table-container-z-index + 1;
78
+ $bro-filter-drawer-scrim-z-index: $bro-table-container-z-index + 2;
79
+ $bro-filter-drawer-card-z-index: $bro-table-container-z-index + 3;
80
+ $bro-filter-drawer-content-z-index: $bro-table-container-z-index + 4;
81
+ $bro-toolbar-z-index: $bro-table-container-z-index + 5;
82
+ $bro-modal-filter-drawer-scrim-z-index: $bro-table-container-z-index + 6;
83
+ $bro-modal-filter-drawer-card-z-index: $bro-table-container-z-index + 7;
84
+ $bro-modal-filter-drawer-content-z-index: $bro-table-container-z-index + 8;
85
+
86
+
87
+ // Derived values: a skin or a user may set them, otherwise they follow the values above
88
+ @if not $bro-island-space-size {
89
+ $bro-island-space-size: $bro-table-shadow-size * .5;
90
+ }
91
+
92
+ @if not $bro-state-line-height {
93
+ $bro-state-line-height: $bro-state-icon-size;
94
+ }
@@ -0,0 +1,39 @@
1
+ @use "../variables" as *;
2
+
3
+ // The sizes and timings of the skin as custom properties on the host. The rules of the skin size the table with them,
4
+ // and the table script reads them at render (packages/core/shared/styles.ts) as numbers for the geometry
5
+ // of the rows, the kinetic scroll, the shadows and the animations; only the header height, the corner radii and
6
+ // the duration of the motion of the column widths are for the CSS alone.
7
+ // A value set on the table changes the CSS and the script together, without a new build of the skin.
8
+ // The core CSS registers the properties (_custom-properties.scss).
9
+ @mixin bro-skin-custom-properties() {
10
+ --bro-row-height: #{$bro-table-row-height};
11
+ --bro-header-height: #{$bro-table-header-height};
12
+ --bro-shadow-size: #{$bro-table-shadow-size};
13
+ --bro-corner-radius: #{$bro-corner-radius};
14
+ --bro-island-space-size: #{$bro-island-space-size};
15
+ --bro-table-min-width: #{$bro-table-min-width};
16
+ --bro-filter-drawer-width: #{$bro-filter-drawer-width};
17
+ --bro-filter-drawer-corner-radius: #{$bro-filter-drawer-corner-radius};
18
+
19
+ --bro-table-body-container-z-index: #{$bro-table-container-z-index};
20
+ --bro-refresh-overlay-opacity: #{$bro-refresh-overlay-opacity};
21
+ --bro-refresh-overlay-opacity-dark: #{$bro-refresh-overlay-opacity-dark};
22
+
23
+ --bro-column-width-duration: #{$bro-column-width-duration};
24
+ --bro-details-duration: #{$bro-details-duration};
25
+ --bro-details-easing: #{$bro-details-easing};
26
+ --bro-filter-drawer-duration: #{$bro-filter-drawer-duration};
27
+ --bro-kinetic-time-constant: #{$bro-kinetic-time-constant};
28
+ --bro-state-icon-duration: #{$bro-state-icon-duration};
29
+ --bro-state-message-duration: #{$bro-state-message-duration};
30
+
31
+ // The factor of every animation of the table; without motion each one draws its end at once
32
+ --bro-duration-scale: 1;
33
+
34
+ @media (prefers-reduced-motion: reduce) {
35
+ @at-root #{&} {
36
+ --bro-duration-scale: 0;
37
+ }
38
+ }
39
+ }
@@ -0,0 +1,27 @@
1
+ @use "../variables" as *;
2
+ @use "shared-selector-map" as *;
3
+
4
+ @mixin table-header-progress-bar($progress-bar-selector) {
5
+ #{$bro-table-header} {
6
+ #{$progress-bar-selector} {
7
+ position: absolute;
8
+ top: calc(var(--bro-header-height) - #{$bro-global-progress});
9
+
10
+ width: 100%;
11
+ height: $bro-global-progress;
12
+ }
13
+ }
14
+ }
15
+
16
+ @mixin table-aux-progress-bar($progress-bar-selector) {
17
+ #{$bro-table-aux} {
18
+ #{$progress-bar-selector} {
19
+ position: absolute;
20
+ z-index: $bro-table-container-z-index;
21
+ top: calc(var(--bro-row-height) - #{$bro-details-progress});
22
+
23
+ width: 100%;
24
+ height: $bro-details-progress;
25
+ }
26
+ }
27
+ }
@@ -0,0 +1,79 @@
1
+ @use "../variables" as *;
2
+ @use "../../../mixins/visually-hidden" as *;
3
+
4
+ // The same mixin is in components/material-based/_table.scss of the core: the core and the skins are separate packages,
5
+ // which share no Sass module but the maps of the selectors
6
+ @mixin table-width-transition() {
7
+ // --bro-duration-scale is 0 under prefers-reduced-motion: reduce
8
+ transition: width calc(var(--bro-column-width-duration) * var(--bro-duration-scale)) ease;
9
+ }
10
+
11
+ // The items of a component cell, such as tags, keep to one line, so the row keeps its height. The component calls
12
+ // fitCellItems() of the core: the items that do not fit whole give way to an ellipsis after the items that show.
13
+ // The first item always shows and shrinks with its own ellipsis in a narrow cell.
14
+ // @param $row - the element that holds the items in its line
15
+ // @param $item - an item
16
+ // @param $text - the text inside an item; without it the item holds its text itself
17
+ @mixin bro-cell-items($row, $item, $text: null) {
18
+ #{$row} {
19
+ display: flex;
20
+ overflow: hidden;
21
+
22
+ box-sizing: border-box;
23
+ width: 100%;
24
+ min-width: 0;
25
+
26
+ flex-wrap: nowrap;
27
+ align-items: center;
28
+
29
+ > #{$item} {
30
+ flex: none;
31
+ }
32
+
33
+ > #{$item}:first-child {
34
+ min-width: 0;
35
+
36
+ flex-shrink: 1;
37
+
38
+ // The boxes inside the item shrink with it down to its text
39
+ * {
40
+ min-width: 0;
41
+ }
42
+
43
+ @if $text {
44
+ #{$text} {
45
+ overflow: hidden;
46
+
47
+ text-overflow: ellipsis;
48
+ }
49
+ } @else {
50
+ overflow: hidden;
51
+
52
+ text-overflow: ellipsis;
53
+ }
54
+ }
55
+
56
+ > .bro-cell-items-ellipsis {
57
+ flex: none;
58
+ }
59
+
60
+ // An item that does not fit the line: hidden from the eye, not from screen readers (fitCellItems)
61
+ > .bro-cell-item-hidden {
62
+ @include bro-visually-hidden;
63
+ }
64
+ }
65
+ }
66
+
67
+ // A container of the table on the page lines the table up with its content: the table moves left by its shadow size,
68
+ // so its visible part starts at the content and its shadows fall into the margins around it. The table knows its skin,
69
+ // so the rule needs no skin class around the container. A full width table takes the full width of the container,
70
+ // its shadows falling into the margins.
71
+ @mixin bro-table-shadow-container() {
72
+ @at-root .bro-table-shadow-container > table-bro#{&} {
73
+ margin-left: calc(var(--bro-shadow-size) * -1);
74
+
75
+ @if $bro-table-width == 100% {
76
+ width: 100%;
77
+ }
78
+ }
79
+ }
@@ -0,0 +1,64 @@
1
+ @use "sass:selector";
2
+ @use "shared-selector-map" as *;
3
+
4
+ @mixin bro-table-theme($table-selector, $toolbar-selector, $bro-bg, $bro-border-color, $bro-text-color, $bro-text-secondary-color) {
5
+ #{$table-selector} {
6
+ background: transparent;
7
+ }
8
+
9
+ #{$bro-table-header_container} {
10
+ > table {
11
+ background: $bro-bg;
12
+ }
13
+ }
14
+
15
+ #{$bro-table-toolbar_container} #{$toolbar-selector},
16
+ .bro-filter-drawer-header #{$toolbar-selector} {
17
+ border-bottom-color: $bro-border-color;
18
+
19
+ background: $bro-bg;
20
+ }
21
+
22
+ // The table with the filter drawer carries the class of the skin itself, so do the drawer of the mat skin and
23
+ // the card in it. Unify keeps the dark theme class where it is: on an ancestor
24
+ // (.bro-dark-theme table-bro-filter-drawer-container.bs) or on this element (table-bro-filter-drawer-container.bro-dark-theme.bs)
25
+ @at-root #{selector.unify(&, 'table-bro-filter-drawer-container')} {
26
+ > .bro-filter-drawer-header,
27
+ > [slot="filters"] {
28
+ color: $bro-text-color;
29
+ }
30
+ }
31
+
32
+ // The ellipsis after the items of a component cell that show (fitCellItems)
33
+ .bro-cell-items-ellipsis {
34
+ color: $bro-text-color;
35
+ }
36
+
37
+ // The card of the drawer under its header and its filters
38
+ .bro-filter-drawer-card {
39
+ background: $bro-bg;
40
+ color: $bro-text-color;
41
+ }
42
+
43
+ // The rows of the table of the body: the aux table measures the same rows, and its rows stay transparent
44
+ .bro-table tr.bro-row {
45
+ background: $bro-bg;
46
+ }
47
+
48
+ .bro-table #{$bro-details_tr} {
49
+ background-color: $bro-bg;
50
+ }
51
+
52
+ #{$bro-toolbar_content-search} input {
53
+ background: $bro-bg;
54
+ color: $bro-text-color;
55
+
56
+ &::placeholder {
57
+ color: $bro-text-secondary-color;
58
+ }
59
+ }
60
+
61
+ .bro-paginator-outer-container {
62
+ background-color: $bro-bg;
63
+ }
64
+ }
@@ -0,0 +1,5 @@
1
+ @mixin slide-toggle($slide-toggle-selector: 'bro-mat-slide-toggle') {
2
+ #{$slide-toggle-selector} {
3
+ overflow: visible;
4
+ }
5
+ }
@@ -0,0 +1,11 @@
1
+ @mixin sort-header-content() {
2
+ // A block, not a flex container: text-overflow does not apply to the anonymous flex item of the title. The container of
3
+ // the sort header centers the content as its flex item
4
+ display: block;
5
+
6
+ overflow: hidden;
7
+
8
+ text-overflow: ellipsis;
9
+
10
+ white-space: nowrap;
11
+ }