igniteui-webcomponents
Version:
Ignite UI for Web Components is a complete library of UI components, giving you the ability to build modern web applications using encapsulation and the concept of reusable components in a dependency-free approach.
132 lines • 4.35 kB
JavaScript
import { isServer } from 'lit';
import { escapeRegex, iterNodes, nanoid, scrollIntoView, wrap, } from '../common/util.js';
function* matchText(nodes, regexp) {
for (const node of nodes) {
if (node.textContent) {
for (const match of node.textContent.matchAll(regexp)) {
const [start, end] = match.indices[0];
yield { node, indices: [start, end] };
}
}
}
}
class HighlightService {
get size() {
return this._ranges.length;
}
get current() {
return this._current;
}
constructor(host) {
this._ranges = [];
this._current = 0;
this._host = host;
this._host.addController(this);
this._id = `igc-highlight-${nanoid()}`;
this._activeId = `${this._id}-active`;
this._styles = `
::highlight(${this._id}) {
background-color: var(--background, var(--ig-secondary-700));
color: var(--foreground, var(--ig-secondary-700-contrast));
}
::highlight(${this._activeId}) {
background-color: var(--background-active, var(--ig-primary-500));
color: var(--foreground-active, var(--ig-primary-500-contrast));
}`;
if (!isServer) {
this._styleSheet = new CSSStyleSheet();
this._styleSheet.replaceSync(this._styles);
}
}
hostConnected() {
this._createHighlightEntries();
this.find(this._host.searchText);
}
hostDisconnected() {
this._removeHighlightEntries();
this._removeStyleSheet();
}
_removeStyleSheet() {
const root = this._host.renderRoot;
if (this._styleSheet) {
root.adoptedStyleSheets = root.adoptedStyleSheets.filter((sheet) => sheet !== this._styleSheet);
}
}
_createHighlightEntries() {
this._highlight = new Highlight();
this._highlight.priority = 0;
this._activeHighlight = new Highlight();
this._activeHighlight.priority = 1;
CSS.highlights.set(this._id, this._highlight);
CSS.highlights.set(this._activeId, this._activeHighlight);
}
_removeHighlightEntries() {
CSS.highlights.delete(this._id);
CSS.highlights.delete(this._activeId);
this._ranges.length = 0;
}
_createRegex(value) {
return new RegExp(escapeRegex(value), this._host.caseSensitive ? 'dg' : 'dgi');
}
_updateActiveHighlight() {
if (this.size) {
this._activeHighlight.clear();
this._activeHighlight.add(this._ranges[this._current]);
}
}
_goTo(index, options) {
if (!this.size) {
return;
}
this._current = wrap(0, this.size - 1, index);
const range = this._ranges[this._current];
this._activeHighlight.clear();
this._activeHighlight.add(range);
if (!options?.preventScroll) {
scrollIntoView(range.commonAncestorContainer.parentElement, {
block: 'center',
inline: 'center',
});
}
}
attachStylesheet() {
const adoptedSheets = this._host.renderRoot
.adoptedStyleSheets;
if (this._styleSheet && !adoptedSheets.includes(this._styleSheet)) {
adoptedSheets.push(this._styleSheet);
}
}
find(value) {
if (!value?.trim()) {
return;
}
const iterator = matchText(iterNodes(this._host, { show: 'SHOW_TEXT' }), this._createRegex(value));
for (const { node, indices: [start, end], } of iterator) {
const range = new Range();
range.setStart(node, start);
range.setEnd(node, end);
this._ranges.push(range);
this._highlight.add(range);
}
this._updateActiveHighlight();
}
next(options) {
this._goTo(this._current + 1, options);
}
previous(options) {
this._goTo(this._current - 1, options);
}
setActive(index, options) {
this._goTo(index, options);
}
clear() {
this._activeHighlight.clear();
this._highlight.clear();
this._ranges.length = 0;
this._current = 0;
}
}
export function createHighlightController(host) {
return new HighlightService(host);
}
//# sourceMappingURL=service.js.map