@singapore-editor/find 0.1.1

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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"findController.js","names":[],"sources":["../src/findController.ts"],"sourcesContent":["import {\n wordRangeAtOffset,\n type TextEdit,\n type TextReadSnapshot,\n} from '@singapore-editor/core/document'\nimport type { EditorSetSelectionOptions } from '@singapore-editor/core/editor'\nimport type {\n EditorContributionChange,\n EditorDisposable,\n EditorResolvedSelection,\n EditorSelectionRange,\n EditorViewContributionUpdateKind,\n} from '@singapore-editor/core/extensions'\nimport type { VirtualizedTextHighlightStyle } from '@singapore-editor/core/rendering'\nimport { EditorSecondaryViewScheduler } from '@singapore-editor/core/secondary-views'\nimport {\n countMatches,\n escapeRegExpCharacters,\n FIND_MATCHES_LIMIT,\n FIND_REPLACE_ALL_LIMIT,\n findLineRange,\n findMatchIndex,\n findMatches,\n findNextMatchFrom,\n findPreviousMatchFrom,\n findTextSourceFromSnapshot,\n type FindMatch,\n type FindMatchFromOptions,\n type FindMatchFromSearcher,\n type FindQuery,\n type FindRange,\n type FindTextSource,\n} from './search'\nimport { parseReplaceString, ReplacePattern } from './replacePattern'\nimport type { EditorFindOptions } from './types'\n\n// These three overlap by construction — the current match is always also a\n// match, and both sit inside the scope — so their stacking is declared rather\n// than left to the order the groups happen to reach the highlight registry in.\n//\n// The numbers are exported because they are half of a cross-package agreement: the highlight\n// priority space is one namespace that several subsystems write into, and priority is what settles\n// a contest between two of them that declare the same property. A regression test elsewhere asserts\n// the resulting order, and it can only do that by reading these rather than by restating them.\n//\n// They sit above the error diagnostic, which declares a background of its own at 2. `current` is the\n// only find style that declares a `color`, so it is the only one contending on that axis — but all\n// three declare a background, and so does the error, which is why none of them may share its number.\n// A tie there would put the background contest back where the numbers exist to take it out of:\n// registration order in the document's shared registry.\nexport const FIND_HIGHLIGHT_Z_INDEX = {\n scope: 4,\n match: 5,\n current: 6,\n} as const\n\nconst FIND_MATCH_STYLE = {\n dimmable: false,\n backgroundColor: 'rgba(234, 179, 8, 0.34)',\n zIndex: FIND_HIGHLIGHT_Z_INDEX.match,\n}\nconst FIND_CURRENT_STYLE = {\n dimmable: false,\n backgroundColor: 'rgba(245, 158, 11, 0.72)',\n color: '#111827',\n zIndex: FIND_HIGHLIGHT_Z_INDEX.current,\n}\nconst FIND_SCOPE_STYLE = {\n dimmable: false,\n backgroundColor: 'rgba(59, 130, 246, 0.22)',\n zIndex: FIND_HIGHLIGHT_Z_INDEX.scope,\n}\n\n// A match on screen stays where the reader is looking at it; one that is not lands\n// in the middle, with context on both sides rather than on the viewport's edge.\nfunction findReveal(match: FindRange, committed = true): EditorSetSelectionOptions {\n return {\n ...(committed ? { jumpCause: 'find' as const } : {}),\n revealOffset: match.end,\n revealBlock: 'center-if-outside',\n }\n}\n\n// Seeding stops here rather than pushing a multi-megabyte selection through the\n// find input and searching for it.\nconst SEARCH_STRING_MAX_LENGTH = 524_288\n\n// A re-search reads the whole document, which is not a bill a keystroke can be\n// handed. The ceiling is the load-bearing half: a sustained typing run never\n// leaves the quiet gap, so waiting only for quiet would mean never re-searching\n// at all for as long as the user keeps going.\nconst FIND_RESEARCH_KEY = 'find.research'\nconst FIND_RESEARCH_DELAY_MS = 100\nconst FIND_RESEARCH_MAX_DELAY_MS = 400\n\ntype EditorFindSelectionRange = EditorSelectionRange\n\nexport type EditorFindResolvedSelection = EditorResolvedSelection & {\n readonly collapsed: boolean\n}\n\n/**\n * Ranges the host follows through edits on find's behalf.\n *\n * A scope outlives the selection it was taken from: the first replace inside it moves the caret off\n * that selection, so a scope re-derived from what is selected now would be re-derived from\n * something else — or from nothing, and a scope of nothing is indistinguishable from no scope at\n * all. Handed over once, it answers from wherever its text went, however many edits later.\n */\nexport type FindTrackedRanges = {\n resolve(): readonly FindRange[]\n}\n\nexport type EditorFindHost = {\n hasDocument(): boolean\n // Ranges rather than a string, so nothing find does can cost a copy of the\n // document — the reason there is no full-text accessor here to reach for.\n textSource(): FindTextSource\n hasTextSnapshot(snapshot: TextReadSnapshot): boolean\n // Followed wherever they end up, however far off screen: a scope decides where\n // Replace All rewrites, and one that stopped being followed would rewrite text\n // the user never marked.\n trackRanges(ranges: readonly FindRange[]): FindTrackedRanges\n // Followed only as far as the host paints them, the rest answered with the\n // offsets they were handed; see adoptMatches.\n trackPaintedRanges(ranges: readonly FindRange[]): FindTrackedRanges\n getSelections(): readonly EditorFindResolvedSelection[]\n focusEditor(): void\n announce(message: string): void\n setSelection(\n anchor: number,\n head: number,\n timingName: string,\n options?: EditorSetSelectionOptions,\n ): void\n setSelections(\n selections: readonly EditorFindSelectionRange[],\n timingName: string,\n revealOffset?: number,\n ): void\n setRangeHighlight(\n name: string,\n ranges: readonly FindRange[],\n style: VirtualizedTextHighlightStyle,\n ): void\n clearRangeHighlight(name: string): void\n}\n\nexport type EditorFindEditHost = {\n textSnapshot(): TextReadSnapshot | null\n getSelections(): readonly EditorFindResolvedSelection[]\n applyEdits(\n edits: readonly TextEdit[],\n timingName: string,\n selection?: EditorFindSelectionRange,\n ): void\n}\n\nexport type EditorFindStartOptions = {\n readonly replace: boolean\n readonly focus: 'find' | 'replace' | 'none'\n}\n\nexport type EditorFindState = FindQuery & {\n readonly replaceString: string\n readonly preserveCase: boolean\n readonly revealed: boolean\n readonly replaceRevealed: boolean\n readonly inSelection: boolean\n}\n\nexport type EditorFindWidgetState = EditorFindState & {\n // Every match in the searched text, however many of them are painted.\n readonly matchesCount: number\n readonly matchesPosition: number\n // Painting stopped at FIND_MATCHES_LIMIT. The count and navigation did not.\n readonly highlightsTruncated: boolean\n}\n\nexport type EditorFindUiEvent =\n | { readonly type: 'show'; readonly replaceVisible: boolean }\n | { readonly type: 'hide' }\n | { readonly type: 'focus'; readonly target: 'find' | 'replace' }\n | { readonly type: 'update'; readonly state: EditorFindWidgetState }\n\ntype ResolvedFindOptions = Required<EditorFindOptions>\ntype EditorFindUiListener = (event: EditorFindUiEvent) => void\n\n// What every search resolves to before it runs: the text, and the ranges of it\n// the query is allowed to answer from. Null scopes are the whole document; an\n// empty scope refuses the search outright, so it is never one of these.\ntype FindSearchTarget = {\n readonly source: FindTextSource\n readonly scopes: readonly FindRange[] | null\n}\n\nexport class EditorFindController {\n private readonly options: ResolvedFindOptions\n private readonly listeners = new Set<EditorFindUiListener>()\n private host: EditorFindHost | null = null\n private editHost: EditorFindEditHost | null = null\n private matchHighlightName = ''\n private currentHighlightName = ''\n private scopeHighlightName = ''\n private state: EditorFindState = {\n searchString: '',\n replaceString: '',\n isRegex: false,\n matchCase: false,\n wholeWord: false,\n preserveCase: false,\n revealed: false,\n replaceRevealed: false,\n inSelection: false,\n }\n private readonly scheduler = new EditorSecondaryViewScheduler()\n private matches: readonly FindMatch[] = []\n private highlightsTruncated = false\n // Counted rather than listed, so it is exact past the paint cap.\n private totalMatches = 0\n private scope: FindTrackedRanges | null = null\n // What the host follows the painted matches by, so a deferred re-search cannot\n // leave a highlight standing on text that moved out from under it.\n private trackedMatches: FindTrackedRanges | null = null\n private currentMatch: FindMatch | null = null\n private replacing = false\n private pendingResearch = false\n\n public constructor(options: EditorFindOptions = {}) {\n this.options = resolveFindOptions(options)\n }\n\n public attachHost(host: EditorFindHost, highlightPrefix: string): EditorDisposable {\n if (this.host && this.host !== host) this.clearHighlights()\n\n this.host = host\n this.matchHighlightName = `${highlightPrefix}-find-match`\n this.currentHighlightName = `${highlightPrefix}-find-current`\n this.scopeHighlightName = `${highlightPrefix}-find-scope`\n return { dispose: () => this.detachHost(host) }\n }\n\n public attachEditHost(host: EditorFindEditHost): EditorDisposable {\n this.editHost = host\n return { dispose: () => this.detachEditHost(host) }\n }\n\n public subscribe(listener: EditorFindUiListener): EditorDisposable {\n this.listeners.add(listener)\n return { dispose: () => this.listeners.delete(listener) }\n }\n\n public dispose(): void {\n this.pendingResearch = false\n this.scheduler.dispose()\n this.clearHighlights()\n this.listeners.clear()\n this.host = null\n this.editHost = null\n }\n\n public isVisible(): boolean {\n return this.state.revealed\n }\n\n public openFind(): boolean {\n return this.open({ replace: false, focus: 'find' })\n }\n\n public toggleFind(): boolean {\n if (this.state.revealed) return this.close()\n return this.openFind()\n }\n\n public openFindReplace(): boolean {\n return this.open({ replace: true, focus: 'replace' })\n }\n\n public close(): boolean {\n const host = this.host\n if (!this.state.revealed || !host) return false\n\n this.pendingResearch = false\n this.state = { ...this.state, revealed: false, inSelection: false }\n this.scope = null\n this.trackedMatches = null\n this.currentMatch = null\n this.scheduler.cancel(FIND_RESEARCH_KEY)\n this.clearHighlights()\n this.emit({ type: 'hide' })\n host.focusEditor()\n return true\n }\n\n public findNext(): boolean {\n if (!this.ensureFindReady('none')) return false\n\n const startOffset = this.primarySelection()?.endOffset ?? 0\n const match = this.nextMatchAt(startOffset, true)\n // Landing behind where the search started is the search having run out and begun again. Nothing\n // on screen says so to a reader who cannot see the caret jump back up the file.\n if (match && match.start < startOffset) this.host?.announce('Wrapped to the first match')\n\n return this.selectMatch(match)\n }\n\n public findPrevious(): boolean {\n if (!this.ensureFindReady('none')) return false\n\n const startOffset = this.primarySelection()?.startOffset ?? 0\n const match = this.searchFrom(findPreviousMatchFrom, startOffset, {\n escapeEmptyMatchAtOffset: true,\n })\n if (match && match.start > startOffset) this.host?.announce('Wrapped to the last match')\n\n return this.selectMatch(match)\n }\n\n public replaceOne(): boolean {\n if (!this.ensureFindReady('replace')) return false\n const editHost = this.editHost\n if (!editHost) return false\n\n const selection = this.primarySelection()\n if (!selection) return false\n const search = this.commandSearchTarget()\n if (!search) return false\n\n // One scan, from the cursor, with the capture groups of the one match that\n // may be about to be rewritten: enumerating the document for them allocates\n // a capture array per match in it to use exactly one.\n const match = findNextMatchFrom(\n search.source,\n this.state,\n selection.startOffset,\n search.scopes,\n { captureMatches: true, loop: this.options.loop },\n )\n if (!match) return false\n // Not on it yet, so this press is the one that selects it and the next one\n // replaces it.\n if (match.start !== selection.startOffset || match.end !== selection.endOffset)\n return this.selectMatch(match)\n\n const replaceText = this.replacePattern().buildReplaceString(\n match.matches,\n this.state.preserveCase,\n )\n this.applyReplacement(\n [{ from: match.start, to: match.end, text: replaceText }],\n 'input.findReplaceOne',\n { anchor: match.start + replaceText.length, head: match.start + replaceText.length },\n )\n this.selectNextReplacementMatch()\n this.research(false)\n return true\n }\n\n public replaceAll(): boolean {\n if (!this.ensureFindReady('replace')) return false\n const editHost = this.editHost\n if (!editHost) return false\n const search = this.commandSearchTarget()\n if (!search) return false\n\n const pattern = this.replacePattern()\n // Deliberately not FIND_MATCHES_LIMIT: that cap exists to bound painting,\n // and applying it here would rewrite the first 19,999 matches and leave the\n // rest, silently.\n const matches = findMatches(\n search.source,\n this.state,\n search.scopes,\n pattern.hasReplacementPatterns || this.state.preserveCase,\n FIND_REPLACE_ALL_LIMIT,\n )\n if (matches.length === 0) return false\n\n const edits = mergeAdjacentReplaceEdits(\n matches.map((match) => ({\n from: match.start,\n to: match.end,\n text: pattern.buildReplaceString(match.matches, this.state.preserveCase),\n })),\n )\n this.applyReplacement(edits, 'input.findReplaceAll')\n this.research(false)\n return true\n }\n\n public selectAllMatches(): boolean {\n const host = this.host\n if (!host) return false\n if (!this.ensureFindReady('none')) return false\n\n // Re-queried uncapped for the same reason Replace All is: FIND_MATCHES_LIMIT\n // bounds painting, and a cursor set that silently stopped at the paint cap\n // would let the next keystroke edit only part of what the user selected.\n const search = this.commandSearchTarget()\n if (!search) return false\n const matches = findMatches(\n search.source,\n this.state,\n search.scopes,\n false,\n FIND_REPLACE_ALL_LIMIT,\n )\n if (matches.length === 0) return false\n\n const selections = orderedMatchSelections(matches, this.primarySelection())\n host.setSelections(selections, 'input.findSelectAll', selections[0]?.head)\n return true\n }\n\n public toggleMatchCase(): boolean {\n this.state = { ...this.state, matchCase: !this.state.matchCase }\n this.research(this.options.cursorMoveOnType)\n return true\n }\n\n public toggleWholeWord(): boolean {\n this.state = { ...this.state, wholeWord: !this.state.wholeWord }\n this.research(this.options.cursorMoveOnType)\n return true\n }\n\n public toggleRegex(): boolean {\n this.state = { ...this.state, isRegex: !this.state.isRegex }\n this.research(this.options.cursorMoveOnType)\n return true\n }\n\n public togglePreserveCase(): boolean {\n this.state = { ...this.state, preserveCase: !this.state.preserveCase }\n this.updateWidget()\n return true\n }\n\n public toggleReplace(): boolean {\n this.state = { ...this.state, replaceRevealed: !this.state.replaceRevealed }\n this.updateWidget()\n return true\n }\n\n public toggleFindInSelection(): boolean {\n if (this.state.inSelection) {\n this.state = { ...this.state, inSelection: false }\n this.scope = null\n this.research(this.options.cursorMoveOnType)\n return true\n }\n\n const host = this.host\n if (!host) return false\n\n const scopes = nonEmptySelectionRanges(this.commandSelections())\n if (scopes.length === 0) return false\n\n this.state = { ...this.state, inSelection: true }\n this.scope = host.trackRanges(scopes)\n this.research(this.options.cursorMoveOnType)\n return true\n }\n\n public setSearchString(value: string): void {\n this.state = { ...this.state, searchString: value }\n if (this.options.findOnType) this.research(this.options.cursorMoveOnType)\n }\n\n public setReplaceString(value: string): void {\n this.state = { ...this.state, replaceString: value }\n this.updateWidget()\n }\n\n public handleViewUpdate(\n kind: EditorViewContributionUpdateKind,\n change: EditorContributionChange | null,\n ): void {\n if (!this.state.revealed) return\n if (!isFindDocumentUpdate(kind)) return\n if (change?.kind === 'selection' || change?.kind === 'none') return\n\n if (kind === 'clear') {\n this.close()\n return\n }\n\n // Find's own replace re-searches once the edit it is applying has landed,\n // rather than from inside it, so the matches it is about to discard are not\n // followed through the edit first.\n if (this.replacing) return\n // Nothing to follow across a document swap: the ranges being tracked belong\n // to the buffer that was just replaced. A scope among them is the one that\n // cannot simply be dropped on the floor — resolved against the new buffer it\n // answers with offsets of text the user never marked, and a search confined\n // to those is a Replace All rewriting inside a region nobody drew.\n if (kind === 'document') {\n this.pendingResearch = false\n this.scope = null\n this.state = { ...this.state, inSelection: false }\n this.research(false)\n return\n }\n\n if (this.pendingResearch) {\n this.research(false)\n return\n }\n this.scheduleResearch()\n }\n\n private detachHost(host: EditorFindHost): void {\n if (this.host !== host) return\n\n this.pendingResearch = false\n this.clearHighlights()\n this.host = null\n this.matchHighlightName = ''\n this.currentHighlightName = ''\n this.scopeHighlightName = ''\n this.state = { ...this.state, revealed: false, inSelection: false }\n this.matches = []\n this.highlightsTruncated = false\n this.totalMatches = 0\n this.scope = null\n this.trackedMatches = null\n this.currentMatch = null\n this.scheduler.cancel(FIND_RESEARCH_KEY)\n }\n\n private detachEditHost(host: EditorFindEditHost): void {\n if (this.editHost !== host) return\n\n this.pendingResearch = false\n this.editHost = null\n }\n\n private open(options: EditorFindStartOptions): boolean {\n const host = this.host\n if (!host || !host.hasDocument()) return false\n\n const searchString = this.seedSearchString()\n this.state = {\n ...this.state,\n searchString: searchString || this.state.searchString,\n revealed: true,\n replaceRevealed: options.replace || this.state.replaceRevealed,\n }\n this.applyAutoFindInSelection(host)\n this.emit({ type: 'show', replaceVisible: this.state.replaceRevealed })\n this.research(false)\n this.focusWidget(options.focus)\n return true\n }\n\n private ensureFindReady(focus: 'find' | 'replace' | 'none'): boolean {\n if (!this.state.revealed) return this.open({ replace: focus === 'replace', focus })\n if (this.matches.length === 0) this.research(false)\n return this.state.searchString.length > 0\n }\n\n private research(moveCursor: boolean): void {\n if (!this.host) return\n if (!this.canPaintCurrentDocument()) {\n this.pendingResearch = true\n if (moveCursor) this.selectFirstMatchFromSelection()\n return\n }\n this.pendingResearch = false\n\n // Whatever a deferred run was going to answer, this run answers now.\n this.scheduler.cancel(FIND_RESEARCH_KEY)\n // One past the cap, so a document holding exactly FIND_MATCHES_LIMIT\n // matches is reported as a complete count rather than an overflow.\n const found = this.findAll(false, FIND_MATCHES_LIMIT + 1)\n this.highlightsTruncated = found.length > FIND_MATCHES_LIMIT\n this.totalMatches = this.highlightsTruncated ? this.countAll() : found.length\n this.adoptMatches(this.highlightsTruncated ? found.slice(0, FIND_MATCHES_LIMIT) : found)\n this.currentMatch = matchAtSelection(this.matches, this.primarySelection())\n this.updateHighlights()\n this.updateWidget()\n // Nothing listed is nothing to land on, and asking anyway is two more passes\n // over the document for every keystroke of a query that matches nothing.\n if (moveCursor && found.length > 0) this.selectFirstMatchFromSelection()\n }\n\n private scheduleResearch(): void {\n this.followPendingMatches()\n this.scheduler.schedule({\n key: FIND_RESEARCH_KEY,\n taskClass: 'background-derived',\n delayMs: FIND_RESEARCH_DELAY_MS,\n maxDelayMs: FIND_RESEARCH_MAX_DELAY_MS,\n run: () => this.research(false),\n })\n }\n\n /**\n * Adopts a match set and hands it to the host to follow as far as it is painted.\n *\n * Handed over now rather than when an edit arrives: find is told about an edit\n * once the text has already moved, and a range recorded against the document\n * as it is by then is a range that will never shift.\n *\n * What the reader can see is the bound. A set stopping at the paint cap holds\n * twenty thousand matches, and asking the host to carry all of them costs more\n * per keystroke than the search this deferral exists to keep off it.\n */\n private adoptMatches(matches: readonly FindMatch[]): void {\n this.matches = matches\n this.trackedMatches = this.host?.trackPaintedRanges(matches) ?? null\n }\n\n /**\n * Carries the painted matches through the edit that deferred their re-search.\n *\n * Until it lands they are what the reader sees, and the offsets they were found\n * at address text that has since moved — so they are read back from where that\n * text went. A match whose text is gone resolves to nothing and stops being\n * painted.\n */\n /** Takes the offsets again from what the host is following, after the line it follows to moved. */\n public refreshTrackedMatches(): void {\n this.followPendingMatches()\n }\n\n private followPendingMatches(): void {\n if (!this.canPaintCurrentDocument()) return\n const tracked = this.trackedMatches\n if (!tracked || this.matches.length === 0) return\n\n // The capture groups belonged to the text that was there; only the ranges\n // survive the edit, and the re-search is what recovers the rest.\n this.matches = tracked.resolve().map((range) => ({ ...range, matches: null }))\n this.currentMatch = matchAtSelection(this.matches, this.primarySelection())\n this.updateHighlights()\n this.updateWidget()\n }\n\n private applyReplacement(\n edits: readonly TextEdit[],\n timingName: string,\n selection?: EditorFindSelectionRange,\n ): void {\n const editHost = this.editHost\n if (!editHost) return\n\n this.replacing = true\n try {\n editHost.applyEdits(edits, timingName, selection)\n } finally {\n this.replacing = false\n }\n }\n\n private selectNextReplacementMatch(): void {\n const offset = this.primarySelection()?.endOffset ?? 0\n const match = this.searchFrom(findNextMatchFrom, offset, {})\n if (!match) return\n this.host?.setSelection(match.start, match.end, 'input.findNavigate', findReveal(match))\n }\n\n private canPaintCurrentDocument(): boolean {\n if (!this.editHost) return true\n const snapshot = this.editHost.textSnapshot()\n return snapshot !== null && this.host?.hasTextSnapshot(snapshot) === true\n }\n\n private commandTextSource(): FindTextSource | undefined {\n if (!this.editHost) return this.host?.textSource()\n const snapshot = this.editHost.textSnapshot()\n return snapshot ? findTextSourceFromSnapshot(snapshot) : undefined\n }\n\n private commandSelections(): readonly EditorFindResolvedSelection[] {\n return this.editHost?.getSelections() ?? this.host?.getSelections() ?? []\n }\n\n private commandSearchTarget(): FindSearchTarget | null {\n const source = this.commandTextSource()\n return source ? this.searchTarget(source) : null\n }\n\n private findAll(captureMatches: boolean, limit = FIND_MATCHES_LIMIT): readonly FindMatch[] {\n const search = this.searchTarget()\n if (!search) return []\n\n return findMatches(search.source, this.state, search.scopes, captureMatches, limit)\n }\n\n private countAll(before?: number): number {\n const search = this.searchTarget()\n return search ? countMatches(search.source, this.state, search.scopes, before) : 0\n }\n\n private searchFrom(\n find: FindMatchFromSearcher,\n offset: number,\n options: FindMatchFromOptions,\n ): FindMatch | null {\n const search = this.commandSearchTarget()\n if (!search) return null\n\n return find(search.source, this.state, offset, search.scopes, {\n loop: this.options.loop,\n ...options,\n })\n }\n\n private searchTarget(source = this.host?.textSource()): FindSearchTarget | null {\n if (!source) return null\n\n const scopes = this.scopeRanges()\n // A scope that has run out of ranges is not the absence of a scope: every\n // range the user marked was edited away, and widening the search to the\n // document would let the next Replace All rewrite text they never marked.\n if (scopes && scopes.length === 0) return null\n\n return { source, scopes }\n }\n\n private scopeRanges(): readonly FindRange[] | null {\n return this.scope?.resolve() ?? null\n }\n\n private selectFirstMatchFromSelection(): void {\n const offset = this.primarySelection()?.endOffset ?? 0\n // Deliberately not escaping an empty match here: re-searching should land\n // on the match at the cursor, empty or not. Only an explicit Find\n // Next/Previous is asking to move off it.\n this.selectMatch(this.nextMatchAt(offset, false), false)\n }\n\n private nextMatchAt(offset: number, escapeEmptyMatchAtOffset: boolean): FindMatch | null {\n return this.searchFrom(findNextMatchFrom, offset, { escapeEmptyMatchAtOffset })\n }\n\n private selectMatch(match: FindMatch | null, committed = true): boolean {\n const host = this.host\n if (!match || !host) return false\n\n if (this.canPaintCurrentDocument()) this.currentMatch = match\n host.setSelection(match.start, match.end, 'input.findNavigate', findReveal(match, committed))\n if (!this.canPaintCurrentDocument()) return true\n this.updateHighlights()\n this.updateWidget()\n return true\n }\n\n private updateHighlights(): void {\n if (!this.canPaintCurrentDocument()) return\n const host = this.host\n if (!host) return\n\n host.setRangeHighlight(this.matchHighlightName, this.matches, FIND_MATCH_STYLE)\n host.setRangeHighlight(this.currentHighlightName, this.currentMatchRanges(), FIND_CURRENT_STYLE)\n const scopes = this.scopeRanges()\n if (scopes) {\n host.setRangeHighlight(this.scopeHighlightName, scopes, FIND_SCOPE_STYLE)\n return\n }\n\n host.clearRangeHighlight(this.scopeHighlightName)\n }\n\n private currentMatchRanges(): readonly FindRange[] {\n return this.currentMatch ? [this.currentMatch] : []\n }\n\n private clearHighlights(): void {\n const host = this.host\n if (!host || !this.matchHighlightName) return\n\n host.clearRangeHighlight(this.matchHighlightName)\n host.clearRangeHighlight(this.currentHighlightName)\n host.clearRangeHighlight(this.scopeHighlightName)\n }\n\n private updateWidget(): void {\n this.emit({ type: 'update', state: this.widgetState() })\n }\n\n private widgetState(): EditorFindWidgetState {\n return {\n ...this.state,\n // Between an edit and its re-search the painted matches are what is known.\n matchesCount: this.highlightsTruncated ? this.totalMatches : this.matches.length,\n matchesPosition: this.currentMatchPosition(),\n highlightsTruncated: this.highlightsTruncated,\n }\n }\n\n // Past the paint cap the match is in no list to look it up in, so its place is\n // the number of matches in front of it.\n private currentMatchPosition(): number {\n if (!this.currentMatch) return 0\n\n const painted = findMatchIndex(this.matches, this.currentMatch)\n if (painted >= 0 || !this.highlightsTruncated) return painted + 1\n return this.countAll(this.currentMatch.start) + 1\n }\n\n private focusWidget(focus: 'find' | 'replace' | 'none'): void {\n if (focus === 'find') this.emit({ type: 'focus', target: 'find' })\n if (focus === 'replace') this.emit({ type: 'focus', target: 'replace' })\n }\n\n private seedSearchString(): string {\n if (this.options.seedSearchStringFromSelection === 'never') return ''\n\n const selection = this.primarySelection()\n if (!selection) return ''\n\n const source = this.commandTextSource()\n if (!source) return ''\n if (!selection.collapsed)\n return this.seedFromLiteralText(selectedSingleLineText(source, selection))\n if (this.options.seedSearchStringFromSelection === 'selection') return ''\n\n return this.seedFromLiteralText(wordTextAtOffset(source, selection.headOffset))\n }\n\n // The seed is document text, never a pattern: unescaped, `foo(bar)` seeded\n // into a regex search becomes a capture group and finds nothing, with no hint\n // to the user why.\n private seedFromLiteralText(value: string): string {\n return this.state.isRegex ? escapeRegExpCharacters(value) : value\n }\n\n private applyAutoFindInSelection(host: EditorFindHost): void {\n const scopes = nonEmptySelectionRanges(this.commandSelections())\n if (scopes.length === 0) return\n if (this.options.autoFindInSelection === 'never') return\n if (this.options.autoFindInSelection === 'always') {\n this.state = { ...this.state, inSelection: true }\n this.scope = host.trackRanges(scopes)\n return\n }\n\n const source = this.commandTextSource()\n if (!source || !hasMultilineScope(source, scopes)) return\n\n this.state = { ...this.state, inSelection: true }\n this.scope = host.trackRanges(scopes)\n }\n\n private replacePattern(): ReplacePattern {\n if (this.state.isRegex) return parseReplaceString(this.state.replaceString)\n return ReplacePattern.fromStaticValue(this.state.replaceString)\n }\n\n private primarySelection(): EditorFindResolvedSelection | null {\n return this.commandSelections()[0] ?? null\n }\n\n private emit(event: EditorFindUiEvent): void {\n for (const listener of this.listeners) listener(event)\n }\n}\n\nfunction resolveFindOptions(options: EditorFindOptions): ResolvedFindOptions {\n return {\n loop: options.loop ?? true,\n seedSearchStringFromSelection: options.seedSearchStringFromSelection ?? 'always',\n findOnType: options.findOnType ?? true,\n cursorMoveOnType: options.cursorMoveOnType ?? true,\n autoFindInSelection: options.autoFindInSelection ?? 'never',\n }\n}\n\nfunction isFindDocumentUpdate(kind: EditorViewContributionUpdateKind): boolean {\n return kind === 'document' || kind === 'content' || kind === 'clear'\n}\n\nfunction selectedSingleLineText(\n source: FindTextSource,\n selection: EditorFindResolvedSelection,\n): string {\n // Both bounds are checked before the read, so an oversized or multi-line\n // selection is never copied at all.\n if (selection.endOffset - selection.startOffset >= SEARCH_STRING_MAX_LENGTH) return ''\n if (spansLines(source, selection.startOffset, selection.endOffset)) return ''\n\n return source.readRange(selection.startOffset, selection.endOffset)\n}\n\n// A word ends at a line break, so the line holding the caret is the whole\n// haystack the scan can need.\nfunction wordTextAtOffset(source: FindTextSource, offset: number): string {\n const line = findLineRange(source, offset)\n const text = source.readRange(line.start, line.end)\n const word = wordRangeAtOffset(text, offset - line.start)\n return text.slice(word.start, word.end)\n}\n\nfunction nonEmptySelectionRanges(\n selections: readonly EditorFindResolvedSelection[],\n): readonly FindRange[] {\n return selections\n .filter((selection) => !selection.collapsed)\n .map((selection) => ({ start: selection.startOffset, end: selection.endOffset }))\n}\n\nfunction hasMultilineScope(source: FindTextSource, scopes: readonly FindRange[]): boolean {\n return scopes.some((scope) => spansLines(source, scope.start, scope.end))\n}\n\n// Asked of the line index instead of the text: whether two offsets sit on one\n// line is already known there, and reading the span out to look for a break\n// would copy a selection that can be the whole document.\nfunction spansLines(source: FindTextSource, start: number, end: number): boolean {\n const lineStartsView = source.lineStartsView\n return lineStartsView.indexForOffset(start) !== lineStartsView.indexForOffset(end)\n}\n\nfunction matchAtSelection(\n matches: readonly FindMatch[],\n selection: EditorFindResolvedSelection | null,\n): FindMatch | null {\n if (!selection) return null\n return (\n matches.find(\n (match) => match.start === selection.startOffset && match.end === selection.endOffset,\n ) ?? null\n )\n}\n\nfunction orderedMatchSelections(\n matches: readonly FindMatch[],\n currentSelection: EditorFindResolvedSelection | null,\n): readonly EditorFindSelectionRange[] {\n const selections = matches.map(selectionForMatch)\n const currentMatch = matchAtSelection(matches, currentSelection)\n const currentIndex = currentMatch ? findMatchIndex(matches, currentMatch) : -1\n if (!currentSelection || currentIndex < 0) return selections\n\n const current = {\n anchor: currentSelection.anchorOffset,\n head: currentSelection.headOffset,\n affinity: currentSelection.affinity,\n }\n if (currentIndex === 0) return [current, ...selections.slice(1)]\n return [current, ...selections.slice(0, currentIndex), ...selections.slice(currentIndex + 1)]\n}\n\nfunction selectionForMatch(match: FindMatch): EditorFindSelectionRange {\n return { anchor: match.start, head: match.end, affinity: 'after' }\n}\n\nfunction mergeAdjacentReplaceEdits(edits: readonly TextEdit[]): readonly TextEdit[] {\n const sorted = edits.toSorted((left, right) => left.from - right.from || left.to - right.to)\n const merged: TextEdit[] = []\n for (const edit of sorted) mergeReplaceEdit(merged, edit)\n return merged\n}\n\nfunction mergeReplaceEdit(merged: TextEdit[], edit: TextEdit): void {\n const previous = merged.at(-1)\n if (!previous || previous.to !== edit.from) {\n merged.push({ ...edit })\n return\n }\n\n merged[merged.length - 1] = {\n from: previous.from,\n to: edit.to,\n text: previous.text + edit.text,\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,49 @@
1
+ export declare const FIND_ICONS: {
2
+ readonly caseSensitive: {
3
+ readonly name: "text-a-underline";
4
+ readonly path: "M60.59,175.24a8,8,0,0,0,10.65-3.83L87.9,136h80.2l16.66,35.41a8,8,0,1,0,14.48-6.82l-64-136a8,8,0,0,0-14.48,0l-64,136A8,8,0,0,0,60.59,175.24ZM128,50.79,160.57,120H95.43ZM224,216a8,8,0,0,1-8,8H40a8,8,0,0,1,0-16H216A8,8,0,0,1,224,216Z";
5
+ };
6
+ readonly close: {
7
+ readonly name: "x";
8
+ readonly path: "M205.66,194.34a8,8,0,0,1-11.32,11.32L128,139.31,61.66,205.66a8,8,0,0,1-11.32-11.32L116.69,128,50.34,61.66A8,8,0,0,1,61.66,50.34L128,116.69l66.34-66.35a8,8,0,0,1,11.32,11.32L139.31,128Z";
9
+ };
10
+ readonly next: {
11
+ readonly name: "caret-down";
12
+ readonly path: "M213.66,101.66l-80,80a8,8,0,0,1-11.32,0l-80-80A8,8,0,0,1,53.66,90.34L128,164.69l74.34-74.35a8,8,0,0,1,11.32,11.32Z";
13
+ };
14
+ readonly preserveCase: {
15
+ readonly name: "text-aa";
16
+ readonly path: "M87.24,52.59a8,8,0,0,0-14.48,0l-64,136a8,8,0,1,0,14.48,6.81L39.9,160h80.2l16.66,35.4a8,8,0,1,0,14.48-6.81ZM47.43,144,80,74.79,112.57,144ZM200,96c-12.76,0-22.73,3.47-29.63,10.32a8,8,0,0,0,11.26,11.36c3.8-3.77,10-5.68,18.37-5.68,13.23,0,24,9,24,20v3.22A42.76,42.76,0,0,0,200,128c-22.06,0-40,16.15-40,36s17.94,36,40,36a42.73,42.73,0,0,0,24-7.25,8,8,0,0,0,16-.75V132C240,112.15,222.06,96,200,96Zm0,88c-13.23,0-24-9-24-20s10.77-20,24-20,24,9,24,20S213.23,184,200,184Z";
17
+ };
18
+ readonly previous: {
19
+ readonly name: "caret-up";
20
+ readonly path: "M213.66,165.66a8,8,0,0,1-11.32,0L128,91.31,53.66,165.66a8,8,0,0,1-11.32-11.32l80-80a8,8,0,0,1,11.32,0l80,80A8,8,0,0,1,213.66,165.66Z";
21
+ };
22
+ readonly regex: {
23
+ readonly name: "asterisk";
24
+ readonly path: "M214.86,180.12a8,8,0,0,1-11,2.74L136,142.13V216a8,8,0,0,1-16,0V142.13L52.12,182.86a8,8,0,1,1-8.23-13.72L112.45,128,43.89,86.86a8,8,0,1,1,8.23-13.72L120,113.87V40a8,8,0,0,1,16,0v73.87l67.88-40.73a8,8,0,1,1,8.23,13.72L143.55,128l68.56,41.14A8,8,0,0,1,214.86,180.12Z";
25
+ };
26
+ readonly replace: {
27
+ readonly name: "swap";
28
+ readonly path: "M224,48V152a16,16,0,0,1-16,16H99.31l10.35,10.34a8,8,0,0,1-11.32,11.32l-24-24a8,8,0,0,1,0-11.32l24-24a8,8,0,0,1,11.32,11.32L99.31,152H208V48H96v8a8,8,0,0,1-16,0V48A16,16,0,0,1,96,32H208A16,16,0,0,1,224,48ZM168,192a8,8,0,0,0-8,8v8H48V104H156.69l-10.35,10.34a8,8,0,0,0,11.32,11.32l24-24a8,8,0,0,0,0-11.32l-24-24a8,8,0,0,0-11.32,11.32L156.69,88H48a16,16,0,0,0-16,16V208a16,16,0,0,0,16,16H160a16,16,0,0,0,16-16v-8A8,8,0,0,0,168,192Z";
29
+ };
30
+ readonly replaceAll: {
31
+ readonly name: "arrows-clockwise";
32
+ readonly path: "M224,48V96a8,8,0,0,1-8,8H168a8,8,0,0,1,0-16h28.69L182.06,73.37a79.56,79.56,0,0,0-56.13-23.43h-.45A79.52,79.52,0,0,0,69.59,72.71,8,8,0,0,1,58.41,61.27a96,96,0,0,1,135,.79L208,76.69V48a8,8,0,0,1,16,0ZM186.41,183.29a80,80,0,0,1-112.47-.66L59.31,168H88a8,8,0,0,0,0-16H40a8,8,0,0,0-8,8v48a8,8,0,0,0,16,0V179.31l14.63,14.63A95.43,95.43,0,0,0,130,222.06h.53a95.36,95.36,0,0,0,67.07-27.33,8,8,0,0,0-11.18-11.44Z";
33
+ };
34
+ readonly replaceToggle: {
35
+ readonly name: "caret-right";
36
+ readonly path: "M181.66,133.66l-80,80a8,8,0,0,1-11.32-11.32L164.69,128,90.34,53.66a8,8,0,0,1,11.32-11.32l80,80A8,8,0,0,1,181.66,133.66Z";
37
+ };
38
+ readonly scope: {
39
+ readonly name: "selection";
40
+ readonly path: "M152,40a8,8,0,0,1-8,8H112a8,8,0,0,1,0-16h32A8,8,0,0,1,152,40Zm-8,168H112a8,8,0,0,0,0,16h32a8,8,0,0,0,0-16ZM208,32H184a8,8,0,0,0,0,16h24V72a8,8,0,0,0,16,0V48A16,16,0,0,0,208,32Zm8,72a8,8,0,0,0-8,8v32a8,8,0,0,0,16,0V112A8,8,0,0,0,216,104Zm0,72a8,8,0,0,0-8,8v24H184a8,8,0,0,0,0,16h24a16,16,0,0,0,16-16V184A8,8,0,0,0,216,176ZM40,152a8,8,0,0,0,8-8V112a8,8,0,0,0-16,0v32A8,8,0,0,0,40,152Zm32,56H48V184a8,8,0,0,0-16,0v24a16,16,0,0,0,16,16H72a8,8,0,0,0,0-16ZM72,32H48A16,16,0,0,0,32,48V72a8,8,0,0,0,16,0V48H72a8,8,0,0,0,0-16Z";
41
+ };
42
+ readonly wholeWord: {
43
+ readonly name: "textbox";
44
+ readonly path: "M112,40a8,8,0,0,0-8,8V64H24A16,16,0,0,0,8,80v96a16,16,0,0,0,16,16h80v16a8,8,0,0,0,16,0V48A8,8,0,0,0,112,40ZM24,176V80h80v96ZM248,80v96a16,16,0,0,1-16,16H144a8,8,0,0,1,0-16h88V80H144a8,8,0,0,1,0-16h88A16,16,0,0,1,248,80ZM88,112a8,8,0,0,1-8,8H72v24a8,8,0,0,1-16,0V120H48a8,8,0,0,1,0-16H80A8,8,0,0,1,88,112Z";
45
+ };
46
+ };
47
+ export type FindIcon = (typeof FIND_ICONS)[keyof typeof FIND_ICONS];
48
+ export declare function createFindIcon(document: Document, icon: FindIcon): SVGSVGElement;
49
+ //# sourceMappingURL=findIcons.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"findIcons.d.ts","sourceRoot":"","sources":["../src/findIcons.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6Cb,CAAA;AAEV,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,OAAO,UAAU,CAAC,CAAA;AAInE,wBAAgB,cAAc,CAAC,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,GAAG,aAAa,CAWhF"}
@@ -0,0 +1,65 @@
1
+ //#region src/findIcons.ts
2
+ var FIND_ICON_VIEW_BOX = "0 0 256 256";
3
+ var FIND_ICONS = {
4
+ caseSensitive: {
5
+ name: "text-a-underline",
6
+ path: "M60.59,175.24a8,8,0,0,0,10.65-3.83L87.9,136h80.2l16.66,35.41a8,8,0,1,0,14.48-6.82l-64-136a8,8,0,0,0-14.48,0l-64,136A8,8,0,0,0,60.59,175.24ZM128,50.79,160.57,120H95.43ZM224,216a8,8,0,0,1-8,8H40a8,8,0,0,1,0-16H216A8,8,0,0,1,224,216Z"
7
+ },
8
+ close: {
9
+ name: "x",
10
+ path: "M205.66,194.34a8,8,0,0,1-11.32,11.32L128,139.31,61.66,205.66a8,8,0,0,1-11.32-11.32L116.69,128,50.34,61.66A8,8,0,0,1,61.66,50.34L128,116.69l66.34-66.35a8,8,0,0,1,11.32,11.32L139.31,128Z"
11
+ },
12
+ next: {
13
+ name: "caret-down",
14
+ path: "M213.66,101.66l-80,80a8,8,0,0,1-11.32,0l-80-80A8,8,0,0,1,53.66,90.34L128,164.69l74.34-74.35a8,8,0,0,1,11.32,11.32Z"
15
+ },
16
+ preserveCase: {
17
+ name: "text-aa",
18
+ path: "M87.24,52.59a8,8,0,0,0-14.48,0l-64,136a8,8,0,1,0,14.48,6.81L39.9,160h80.2l16.66,35.4a8,8,0,1,0,14.48-6.81ZM47.43,144,80,74.79,112.57,144ZM200,96c-12.76,0-22.73,3.47-29.63,10.32a8,8,0,0,0,11.26,11.36c3.8-3.77,10-5.68,18.37-5.68,13.23,0,24,9,24,20v3.22A42.76,42.76,0,0,0,200,128c-22.06,0-40,16.15-40,36s17.94,36,40,36a42.73,42.73,0,0,0,24-7.25,8,8,0,0,0,16-.75V132C240,112.15,222.06,96,200,96Zm0,88c-13.23,0-24-9-24-20s10.77-20,24-20,24,9,24,20S213.23,184,200,184Z"
19
+ },
20
+ previous: {
21
+ name: "caret-up",
22
+ path: "M213.66,165.66a8,8,0,0,1-11.32,0L128,91.31,53.66,165.66a8,8,0,0,1-11.32-11.32l80-80a8,8,0,0,1,11.32,0l80,80A8,8,0,0,1,213.66,165.66Z"
23
+ },
24
+ regex: {
25
+ name: "asterisk",
26
+ path: "M214.86,180.12a8,8,0,0,1-11,2.74L136,142.13V216a8,8,0,0,1-16,0V142.13L52.12,182.86a8,8,0,1,1-8.23-13.72L112.45,128,43.89,86.86a8,8,0,1,1,8.23-13.72L120,113.87V40a8,8,0,0,1,16,0v73.87l67.88-40.73a8,8,0,1,1,8.23,13.72L143.55,128l68.56,41.14A8,8,0,0,1,214.86,180.12Z"
27
+ },
28
+ replace: {
29
+ name: "swap",
30
+ path: "M224,48V152a16,16,0,0,1-16,16H99.31l10.35,10.34a8,8,0,0,1-11.32,11.32l-24-24a8,8,0,0,1,0-11.32l24-24a8,8,0,0,1,11.32,11.32L99.31,152H208V48H96v8a8,8,0,0,1-16,0V48A16,16,0,0,1,96,32H208A16,16,0,0,1,224,48ZM168,192a8,8,0,0,0-8,8v8H48V104H156.69l-10.35,10.34a8,8,0,0,0,11.32,11.32l24-24a8,8,0,0,0,0-11.32l-24-24a8,8,0,0,0-11.32,11.32L156.69,88H48a16,16,0,0,0-16,16V208a16,16,0,0,0,16,16H160a16,16,0,0,0,16-16v-8A8,8,0,0,0,168,192Z"
31
+ },
32
+ replaceAll: {
33
+ name: "arrows-clockwise",
34
+ path: "M224,48V96a8,8,0,0,1-8,8H168a8,8,0,0,1,0-16h28.69L182.06,73.37a79.56,79.56,0,0,0-56.13-23.43h-.45A79.52,79.52,0,0,0,69.59,72.71,8,8,0,0,1,58.41,61.27a96,96,0,0,1,135,.79L208,76.69V48a8,8,0,0,1,16,0ZM186.41,183.29a80,80,0,0,1-112.47-.66L59.31,168H88a8,8,0,0,0,0-16H40a8,8,0,0,0-8,8v48a8,8,0,0,0,16,0V179.31l14.63,14.63A95.43,95.43,0,0,0,130,222.06h.53a95.36,95.36,0,0,0,67.07-27.33,8,8,0,0,0-11.18-11.44Z"
35
+ },
36
+ replaceToggle: {
37
+ name: "caret-right",
38
+ path: "M181.66,133.66l-80,80a8,8,0,0,1-11.32-11.32L164.69,128,90.34,53.66a8,8,0,0,1,11.32-11.32l80,80A8,8,0,0,1,181.66,133.66Z"
39
+ },
40
+ scope: {
41
+ name: "selection",
42
+ path: "M152,40a8,8,0,0,1-8,8H112a8,8,0,0,1,0-16h32A8,8,0,0,1,152,40Zm-8,168H112a8,8,0,0,0,0,16h32a8,8,0,0,0,0-16ZM208,32H184a8,8,0,0,0,0,16h24V72a8,8,0,0,0,16,0V48A16,16,0,0,0,208,32Zm8,72a8,8,0,0,0-8,8v32a8,8,0,0,0,16,0V112A8,8,0,0,0,216,104Zm0,72a8,8,0,0,0-8,8v24H184a8,8,0,0,0,0,16h24a16,16,0,0,0,16-16V184A8,8,0,0,0,216,176ZM40,152a8,8,0,0,0,8-8V112a8,8,0,0,0-16,0v32A8,8,0,0,0,40,152Zm32,56H48V184a8,8,0,0,0-16,0v24a16,16,0,0,0,16,16H72a8,8,0,0,0,0-16ZM72,32H48A16,16,0,0,0,32,48V72a8,8,0,0,0,16,0V48H72a8,8,0,0,0,0-16Z"
43
+ },
44
+ wholeWord: {
45
+ name: "textbox",
46
+ path: "M112,40a8,8,0,0,0-8,8V64H24A16,16,0,0,0,8,80v96a16,16,0,0,0,16,16h80v16a8,8,0,0,0,16,0V48A8,8,0,0,0,112,40ZM24,176V80h80v96ZM248,80v96a16,16,0,0,1-16,16H144a8,8,0,0,1,0-16h88V80H144a8,8,0,0,1,0-16h88A16,16,0,0,1,248,80ZM88,112a8,8,0,0,1-8,8H72v24a8,8,0,0,1-16,0V120H48a8,8,0,0,1,0-16H80A8,8,0,0,1,88,112Z"
47
+ }
48
+ };
49
+ var SVG_NAMESPACE = "http://www.w3.org/2000/svg";
50
+ function createFindIcon(document, icon) {
51
+ const svg = document.createElementNS(SVG_NAMESPACE, "svg");
52
+ svg.setAttribute("class", "editor-find-icon");
53
+ svg.setAttribute("viewBox", FIND_ICON_VIEW_BOX);
54
+ svg.setAttribute("fill", "currentColor");
55
+ svg.setAttribute("aria-hidden", "true");
56
+ svg.dataset.icon = icon.name;
57
+ const path = document.createElementNS(SVG_NAMESPACE, "path");
58
+ path.setAttribute("d", icon.path);
59
+ svg.appendChild(path);
60
+ return svg;
61
+ }
62
+ //#endregion
63
+ export { FIND_ICONS, createFindIcon };
64
+
65
+ //# sourceMappingURL=findIcons.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"findIcons.js","names":[],"sources":["../src/findIcons.ts"],"sourcesContent":["// Phosphor regular-weight glyphs as path data. Inline paths keep the icon font\n// (and its 4 MB of unused formats) out of every host's boot path.\nconst FIND_ICON_VIEW_BOX = '0 0 256 256'\n\nexport const FIND_ICONS = {\n caseSensitive: {\n name: 'text-a-underline',\n path: 'M60.59,175.24a8,8,0,0,0,10.65-3.83L87.9,136h80.2l16.66,35.41a8,8,0,1,0,14.48-6.82l-64-136a8,8,0,0,0-14.48,0l-64,136A8,8,0,0,0,60.59,175.24ZM128,50.79,160.57,120H95.43ZM224,216a8,8,0,0,1-8,8H40a8,8,0,0,1,0-16H216A8,8,0,0,1,224,216Z',\n },\n close: {\n name: 'x',\n path: 'M205.66,194.34a8,8,0,0,1-11.32,11.32L128,139.31,61.66,205.66a8,8,0,0,1-11.32-11.32L116.69,128,50.34,61.66A8,8,0,0,1,61.66,50.34L128,116.69l66.34-66.35a8,8,0,0,1,11.32,11.32L139.31,128Z',\n },\n next: {\n name: 'caret-down',\n path: 'M213.66,101.66l-80,80a8,8,0,0,1-11.32,0l-80-80A8,8,0,0,1,53.66,90.34L128,164.69l74.34-74.35a8,8,0,0,1,11.32,11.32Z',\n },\n preserveCase: {\n name: 'text-aa',\n path: 'M87.24,52.59a8,8,0,0,0-14.48,0l-64,136a8,8,0,1,0,14.48,6.81L39.9,160h80.2l16.66,35.4a8,8,0,1,0,14.48-6.81ZM47.43,144,80,74.79,112.57,144ZM200,96c-12.76,0-22.73,3.47-29.63,10.32a8,8,0,0,0,11.26,11.36c3.8-3.77,10-5.68,18.37-5.68,13.23,0,24,9,24,20v3.22A42.76,42.76,0,0,0,200,128c-22.06,0-40,16.15-40,36s17.94,36,40,36a42.73,42.73,0,0,0,24-7.25,8,8,0,0,0,16-.75V132C240,112.15,222.06,96,200,96Zm0,88c-13.23,0-24-9-24-20s10.77-20,24-20,24,9,24,20S213.23,184,200,184Z',\n },\n previous: {\n name: 'caret-up',\n path: 'M213.66,165.66a8,8,0,0,1-11.32,0L128,91.31,53.66,165.66a8,8,0,0,1-11.32-11.32l80-80a8,8,0,0,1,11.32,0l80,80A8,8,0,0,1,213.66,165.66Z',\n },\n regex: {\n name: 'asterisk',\n path: 'M214.86,180.12a8,8,0,0,1-11,2.74L136,142.13V216a8,8,0,0,1-16,0V142.13L52.12,182.86a8,8,0,1,1-8.23-13.72L112.45,128,43.89,86.86a8,8,0,1,1,8.23-13.72L120,113.87V40a8,8,0,0,1,16,0v73.87l67.88-40.73a8,8,0,1,1,8.23,13.72L143.55,128l68.56,41.14A8,8,0,0,1,214.86,180.12Z',\n },\n replace: {\n name: 'swap',\n path: 'M224,48V152a16,16,0,0,1-16,16H99.31l10.35,10.34a8,8,0,0,1-11.32,11.32l-24-24a8,8,0,0,1,0-11.32l24-24a8,8,0,0,1,11.32,11.32L99.31,152H208V48H96v8a8,8,0,0,1-16,0V48A16,16,0,0,1,96,32H208A16,16,0,0,1,224,48ZM168,192a8,8,0,0,0-8,8v8H48V104H156.69l-10.35,10.34a8,8,0,0,0,11.32,11.32l24-24a8,8,0,0,0,0-11.32l-24-24a8,8,0,0,0-11.32,11.32L156.69,88H48a16,16,0,0,0-16,16V208a16,16,0,0,0,16,16H160a16,16,0,0,0,16-16v-8A8,8,0,0,0,168,192Z',\n },\n replaceAll: {\n name: 'arrows-clockwise',\n path: 'M224,48V96a8,8,0,0,1-8,8H168a8,8,0,0,1,0-16h28.69L182.06,73.37a79.56,79.56,0,0,0-56.13-23.43h-.45A79.52,79.52,0,0,0,69.59,72.71,8,8,0,0,1,58.41,61.27a96,96,0,0,1,135,.79L208,76.69V48a8,8,0,0,1,16,0ZM186.41,183.29a80,80,0,0,1-112.47-.66L59.31,168H88a8,8,0,0,0,0-16H40a8,8,0,0,0-8,8v48a8,8,0,0,0,16,0V179.31l14.63,14.63A95.43,95.43,0,0,0,130,222.06h.53a95.36,95.36,0,0,0,67.07-27.33,8,8,0,0,0-11.18-11.44Z',\n },\n replaceToggle: {\n name: 'caret-right',\n path: 'M181.66,133.66l-80,80a8,8,0,0,1-11.32-11.32L164.69,128,90.34,53.66a8,8,0,0,1,11.32-11.32l80,80A8,8,0,0,1,181.66,133.66Z',\n },\n scope: {\n name: 'selection',\n path: 'M152,40a8,8,0,0,1-8,8H112a8,8,0,0,1,0-16h32A8,8,0,0,1,152,40Zm-8,168H112a8,8,0,0,0,0,16h32a8,8,0,0,0,0-16ZM208,32H184a8,8,0,0,0,0,16h24V72a8,8,0,0,0,16,0V48A16,16,0,0,0,208,32Zm8,72a8,8,0,0,0-8,8v32a8,8,0,0,0,16,0V112A8,8,0,0,0,216,104Zm0,72a8,8,0,0,0-8,8v24H184a8,8,0,0,0,0,16h24a16,16,0,0,0,16-16V184A8,8,0,0,0,216,176ZM40,152a8,8,0,0,0,8-8V112a8,8,0,0,0-16,0v32A8,8,0,0,0,40,152Zm32,56H48V184a8,8,0,0,0-16,0v24a16,16,0,0,0,16,16H72a8,8,0,0,0,0-16ZM72,32H48A16,16,0,0,0,32,48V72a8,8,0,0,0,16,0V48H72a8,8,0,0,0,0-16Z',\n },\n wholeWord: {\n name: 'textbox',\n path: 'M112,40a8,8,0,0,0-8,8V64H24A16,16,0,0,0,8,80v96a16,16,0,0,0,16,16h80v16a8,8,0,0,0,16,0V48A8,8,0,0,0,112,40ZM24,176V80h80v96ZM248,80v96a16,16,0,0,1-16,16H144a8,8,0,0,1,0-16h88V80H144a8,8,0,0,1,0-16h88A16,16,0,0,1,248,80ZM88,112a8,8,0,0,1-8,8H72v24a8,8,0,0,1-16,0V120H48a8,8,0,0,1,0-16H80A8,8,0,0,1,88,112Z',\n },\n} as const\n\nexport type FindIcon = (typeof FIND_ICONS)[keyof typeof FIND_ICONS]\n\nconst SVG_NAMESPACE = 'http://www.w3.org/2000/svg'\n\nexport function createFindIcon(document: Document, icon: FindIcon): SVGSVGElement {\n const svg = document.createElementNS(SVG_NAMESPACE, 'svg')\n svg.setAttribute('class', 'editor-find-icon')\n svg.setAttribute('viewBox', FIND_ICON_VIEW_BOX)\n svg.setAttribute('fill', 'currentColor')\n svg.setAttribute('aria-hidden', 'true')\n svg.dataset.icon = icon.name\n const path = document.createElementNS(SVG_NAMESPACE, 'path')\n path.setAttribute('d', icon.path)\n svg.appendChild(path)\n return svg\n}\n"],"mappings":";AAEA,IAAM,qBAAqB;AAE3B,IAAa,aAAa;CACxB,eAAe;EACb,MAAM;EACN,MAAM;CACR;CACA,OAAO;EACL,MAAM;EACN,MAAM;CACR;CACA,MAAM;EACJ,MAAM;EACN,MAAM;CACR;CACA,cAAc;EACZ,MAAM;EACN,MAAM;CACR;CACA,UAAU;EACR,MAAM;EACN,MAAM;CACR;CACA,OAAO;EACL,MAAM;EACN,MAAM;CACR;CACA,SAAS;EACP,MAAM;EACN,MAAM;CACR;CACA,YAAY;EACV,MAAM;EACN,MAAM;CACR;CACA,eAAe;EACb,MAAM;EACN,MAAM;CACR;CACA,OAAO;EACL,MAAM;EACN,MAAM;CACR;CACA,WAAW;EACT,MAAM;EACN,MAAM;CACR;AACF;AAIA,IAAM,gBAAgB;AAEtB,SAAgB,eAAe,UAAoB,MAA+B;CAChF,MAAM,MAAM,SAAS,gBAAgB,eAAe,KAAK;CACzD,IAAI,aAAa,SAAS,kBAAkB;CAC5C,IAAI,aAAa,WAAW,kBAAkB;CAC9C,IAAI,aAAa,QAAQ,cAAc;CACvC,IAAI,aAAa,eAAe,MAAM;CACtC,IAAI,QAAQ,OAAO,KAAK;CACxB,MAAM,OAAO,SAAS,gBAAgB,eAAe,MAAM;CAC3D,KAAK,aAAa,KAAK,KAAK,IAAI;CAChC,IAAI,YAAY,IAAI;CACpB,OAAO;AACT"}
@@ -0,0 +1,45 @@
1
+ import type { EditorFindWidgetState } from './findController';
2
+ export type EditorFindWidgetOptions = {
3
+ readonly onSearchInput: (value: string) => void;
4
+ readonly onReplaceInput: (value: string) => void;
5
+ readonly onToggleReplace: () => void;
6
+ readonly onPrevious: () => void;
7
+ readonly onNext: () => void;
8
+ readonly onClose: () => void;
9
+ readonly onToggleCase: () => void;
10
+ readonly onToggleWholeWord: () => void;
11
+ readonly onToggleRegex: () => void;
12
+ readonly onToggleScope: () => void;
13
+ readonly onTogglePreserveCase: () => void;
14
+ readonly onReplaceOne: () => void;
15
+ readonly onReplaceAll: () => void;
16
+ };
17
+ export declare class EditorFindWidget {
18
+ private readonly themeSource;
19
+ private readonly options;
20
+ private readonly root;
21
+ private readonly findInput;
22
+ private readonly replaceInput;
23
+ private readonly replaceRow;
24
+ private readonly count;
25
+ private readonly replaceToggleButton;
26
+ private readonly caseButton;
27
+ private readonly wordButton;
28
+ private readonly regexButton;
29
+ private readonly scopeButton;
30
+ private readonly preserveButton;
31
+ constructor(container: HTMLElement, themeSource: HTMLElement, options: EditorFindWidgetOptions);
32
+ show(replaceVisible: boolean): void;
33
+ hide(): void;
34
+ setTrailingInset(width: number): void;
35
+ update(state: EditorFindWidgetState): void;
36
+ focusFindInput(): void;
37
+ focusReplaceInput(): void;
38
+ dispose(): void;
39
+ private build;
40
+ private findRow;
41
+ private findInputFrame;
42
+ private installHandlers;
43
+ private handleKeyDown;
44
+ }
45
+ //# sourceMappingURL=findWidget.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"findWidget.d.ts","sourceRoot":"","sources":["../src/findWidget.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAA;AAU7D,MAAM,MAAM,uBAAuB,GAAG;IACpC,QAAQ,CAAC,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IAC/C,QAAQ,CAAC,cAAc,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IAChD,QAAQ,CAAC,eAAe,EAAE,MAAM,IAAI,CAAA;IACpC,QAAQ,CAAC,UAAU,EAAE,MAAM,IAAI,CAAA;IAC/B,QAAQ,CAAC,MAAM,EAAE,MAAM,IAAI,CAAA;IAC3B,QAAQ,CAAC,OAAO,EAAE,MAAM,IAAI,CAAA;IAC5B,QAAQ,CAAC,YAAY,EAAE,MAAM,IAAI,CAAA;IACjC,QAAQ,CAAC,iBAAiB,EAAE,MAAM,IAAI,CAAA;IACtC,QAAQ,CAAC,aAAa,EAAE,MAAM,IAAI,CAAA;IAClC,QAAQ,CAAC,aAAa,EAAE,MAAM,IAAI,CAAA;IAClC,QAAQ,CAAC,oBAAoB,EAAE,MAAM,IAAI,CAAA;IACzC,QAAQ,CAAC,YAAY,EAAE,MAAM,IAAI,CAAA;IACjC,QAAQ,CAAC,YAAY,EAAE,MAAM,IAAI,CAAA;CAClC,CAAA;AAED,qBAAa,gBAAgB;IAezB,OAAO,CAAC,QAAQ,CAAC,WAAW;IAC5B,OAAO,CAAC,QAAQ,CAAC,OAAO;IAf1B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAgB;IACrC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAkB;IAC5C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAkB;IAC/C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAgB;IAC3C,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAiB;IACvC,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAmB;IACvD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAmB;IAC9C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAmB;IAC9C,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAmB;IAC/C,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAmB;IAC/C,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAmB;gBAGhD,SAAS,EAAE,WAAW,EACL,WAAW,EAAE,WAAW,EACxB,OAAO,EAAE,uBAAuB;IAyB5C,IAAI,CAAC,cAAc,EAAE,OAAO,GAAG,IAAI;IAMnC,IAAI,IAAI,IAAI;IAOZ,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAIrC,MAAM,CAAC,KAAK,EAAE,qBAAqB,GAAG,IAAI;IAkB1C,cAAc,IAAI,IAAI;IAKtB,iBAAiB,IAAI,IAAI;IAKzB,OAAO,IAAI,IAAI;IAItB,OAAO,CAAC,KAAK;IA4Bb,OAAO,CAAC,OAAO;IAqBf,OAAO,CAAC,cAAc;IAUtB,OAAO,CAAC,eAAe;IAcvB,OAAO,CAAC,aAAa;CAkBtB"}
@@ -0,0 +1,194 @@
1
+ import { FIND_MATCHES_LIMIT } from "./search.js";
2
+ import { FIND_ICONS, createFindIcon } from "./findIcons.js";
3
+ //#region src/findWidget.ts
4
+ var EDITOR_THEME_VARIABLES = [
5
+ "--editor-background",
6
+ "--editor-foreground",
7
+ "--editor-caret-color"
8
+ ];
9
+ var EditorFindWidget = class {
10
+ themeSource;
11
+ options;
12
+ root;
13
+ findInput;
14
+ replaceInput;
15
+ replaceRow;
16
+ count;
17
+ replaceToggleButton;
18
+ caseButton;
19
+ wordButton;
20
+ regexButton;
21
+ scopeButton;
22
+ preserveButton;
23
+ constructor(container, themeSource, options) {
24
+ this.themeSource = themeSource;
25
+ this.options = options;
26
+ const document = container.ownerDocument;
27
+ const position = container.ownerDocument.defaultView?.getComputedStyle(container).position;
28
+ if (!position || position === "static") container.style.position = "relative";
29
+ this.root = document.createElement("div");
30
+ this.findInput = document.createElement("input");
31
+ this.replaceInput = document.createElement("input");
32
+ this.replaceRow = document.createElement("div");
33
+ this.count = document.createElement("span");
34
+ this.replaceToggleButton = createFindButton(document, FIND_ICONS.replaceToggle, "Toggle Replace");
35
+ this.replaceToggleButton.classList.add("editor-find-replace-toggle");
36
+ this.caseButton = createFindButton(document, FIND_ICONS.caseSensitive, "Match Case");
37
+ this.wordButton = createFindButton(document, FIND_ICONS.wholeWord, "Whole Word");
38
+ this.regexButton = createFindButton(document, FIND_ICONS.regex, "Use Regular Expression");
39
+ this.scopeButton = createFindButton(document, FIND_ICONS.scope, "Find in Selection");
40
+ this.preserveButton = createFindButton(document, FIND_ICONS.preserveCase, "Preserve Case");
41
+ this.build(document);
42
+ container.appendChild(this.root);
43
+ }
44
+ show(replaceVisible) {
45
+ syncEditorThemeVariables(this.root, this.themeSource);
46
+ this.root.hidden = false;
47
+ this.replaceRow.hidden = !replaceVisible;
48
+ }
49
+ hide() {
50
+ this.root.hidden = true;
51
+ }
52
+ setTrailingInset(width) {
53
+ this.root.style.marginRight = width > 0 ? `${Math.ceil(width)}px` : "";
54
+ }
55
+ update(state) {
56
+ syncEditorThemeVariables(this.root, this.themeSource);
57
+ if (this.findInput.value !== state.searchString) this.findInput.value = state.searchString;
58
+ if (this.replaceInput.value !== state.replaceString) this.replaceInput.value = state.replaceString;
59
+ this.replaceRow.hidden = !state.replaceRevealed;
60
+ setToggleExpanded(this.replaceToggleButton, state.replaceRevealed, "Replace");
61
+ this.count.textContent = resultCountText(state.matchesPosition, state.matchesCount);
62
+ this.count.title = state.highlightsTruncated ? TRUNCATED_HIGHLIGHTS_TITLE : this.count.textContent;
63
+ setTogglePressed(this.caseButton, state.matchCase, "Match Case");
64
+ setTogglePressed(this.wordButton, state.wholeWord, "Match Whole Word");
65
+ setTogglePressed(this.regexButton, state.isRegex, "Use Regular Expression");
66
+ setTogglePressed(this.scopeButton, state.inSelection, "Find in Selection");
67
+ setTogglePressed(this.preserveButton, state.preserveCase, "Preserve Case");
68
+ }
69
+ focusFindInput() {
70
+ this.findInput.focus();
71
+ this.findInput.select();
72
+ }
73
+ focusReplaceInput() {
74
+ this.replaceInput.focus();
75
+ this.replaceInput.select();
76
+ }
77
+ dispose() {
78
+ this.root.remove();
79
+ }
80
+ build(document) {
81
+ this.root.className = "editor-find-widget";
82
+ this.root.hidden = true;
83
+ this.root.style.zIndex = "var(--editor-z-overlay-widget, 20)";
84
+ this.findInput.className = "editor-find-input";
85
+ this.findInput.type = "text";
86
+ this.findInput.placeholder = "Find";
87
+ this.findInput.title = "Find";
88
+ this.findInput.spellcheck = false;
89
+ this.findInput.autocomplete = "off";
90
+ this.findInput.setAttribute("aria-label", "Find");
91
+ this.replaceInput.className = "editor-find-input editor-find-input-standalone";
92
+ this.replaceInput.type = "text";
93
+ this.replaceInput.placeholder = "Replace";
94
+ this.replaceInput.title = "Replace";
95
+ this.replaceInput.spellcheck = false;
96
+ this.replaceInput.autocomplete = "off";
97
+ this.replaceInput.setAttribute("aria-label", "Replace");
98
+ this.replaceRow.className = "editor-find-row editor-find-replace-row";
99
+ this.count.className = "editor-find-count";
100
+ this.root.append(this.findRow(document), this.replaceRow);
101
+ this.installHandlers();
102
+ }
103
+ findRow(document) {
104
+ const row = document.createElement("div");
105
+ row.className = "editor-find-row";
106
+ row.append(this.replaceToggleButton, this.findInputFrame(document), this.count, this.scopeButton, createFindButton(document, FIND_ICONS.previous, "Previous Match", this.options.onPrevious), createFindButton(document, FIND_ICONS.next, "Next Match", this.options.onNext), createFindButton(document, FIND_ICONS.close, "Close", this.options.onClose));
107
+ this.replaceRow.append(this.replaceInput, this.preserveButton, createFindButton(document, FIND_ICONS.replace, "Replace", this.options.onReplaceOne), createFindButton(document, FIND_ICONS.replaceAll, "Replace All", this.options.onReplaceAll));
108
+ return row;
109
+ }
110
+ findInputFrame(document) {
111
+ const frame = document.createElement("div");
112
+ const controls = document.createElement("div");
113
+ frame.className = "editor-find-input-frame";
114
+ controls.className = "editor-find-input-controls";
115
+ controls.append(this.caseButton, this.wordButton, this.regexButton);
116
+ frame.append(this.findInput, controls);
117
+ return frame;
118
+ }
119
+ installHandlers() {
120
+ this.root.addEventListener("keydown", (event) => this.handleKeyDown(event));
121
+ this.findInput.addEventListener("input", () => this.options.onSearchInput(this.findInput.value));
122
+ this.replaceInput.addEventListener("input", () => this.options.onReplaceInput(this.replaceInput.value));
123
+ this.caseButton.addEventListener("click", this.options.onToggleCase);
124
+ this.wordButton.addEventListener("click", this.options.onToggleWholeWord);
125
+ this.regexButton.addEventListener("click", this.options.onToggleRegex);
126
+ this.replaceToggleButton.addEventListener("click", this.options.onToggleReplace);
127
+ this.scopeButton.addEventListener("click", this.options.onToggleScope);
128
+ this.preserveButton.addEventListener("click", this.options.onTogglePreserveCase);
129
+ }
130
+ handleKeyDown(event) {
131
+ event.stopPropagation();
132
+ if ([isFindToggleKey(event), event.key === "Escape"].some(Boolean)) {
133
+ event.preventDefault();
134
+ this.options.onClose();
135
+ return;
136
+ }
137
+ if (event.key !== "Enter") return;
138
+ event.preventDefault();
139
+ if (event.target === this.replaceInput && !event.shiftKey) {
140
+ this.options.onReplaceOne();
141
+ return;
142
+ }
143
+ if (event.shiftKey) this.options.onPrevious();
144
+ else this.options.onNext();
145
+ }
146
+ };
147
+ function createFindButton(document, icon, title, onClick) {
148
+ const button = document.createElement("button");
149
+ button.type = "button";
150
+ button.className = "editor-find-button";
151
+ button.appendChild(createFindIcon(document, icon));
152
+ setNativeTooltip(button, title);
153
+ if (onClick) button.addEventListener("click", onClick);
154
+ return button;
155
+ }
156
+ function syncEditorThemeVariables(target, source) {
157
+ const style = source.ownerDocument.defaultView?.getComputedStyle(source);
158
+ if (!style) return;
159
+ for (const variable of EDITOR_THEME_VARIABLES) {
160
+ const value = source.style.getPropertyValue(variable).trim() || style.getPropertyValue(variable).trim();
161
+ if (value) target.style.setProperty(variable, value);
162
+ }
163
+ }
164
+ function setTogglePressed(button, pressed, label) {
165
+ button.classList.toggle("active", pressed);
166
+ button.setAttribute("aria-pressed", pressed ? "true" : "false");
167
+ setNativeTooltip(button, toggleTooltip(label, pressed));
168
+ }
169
+ function setToggleExpanded(button, expanded, label) {
170
+ button.classList.toggle("active", expanded);
171
+ button.setAttribute("aria-expanded", expanded ? "true" : "false");
172
+ setNativeTooltip(button, expanded ? `Hide ${label}` : `Show ${label}`);
173
+ }
174
+ function setNativeTooltip(element, value) {
175
+ element.title = value;
176
+ element.setAttribute("aria-label", value);
177
+ }
178
+ function isFindToggleKey(event) {
179
+ if (event.key.toLowerCase() !== "f") return false;
180
+ if (event.altKey || event.shiftKey) return false;
181
+ return event.metaKey || event.ctrlKey;
182
+ }
183
+ function toggleTooltip(label, active) {
184
+ return active ? `${label} (On)` : `${label} (Off)`;
185
+ }
186
+ function resultCountText(position, count) {
187
+ if (count === 0) return "No results";
188
+ return `${position || "?"} of ${count}`;
189
+ }
190
+ var TRUNCATED_HIGHLIGHTS_TITLE = `Only the first ${FIND_MATCHES_LIMIT} results are highlighted. Every result is counted, and Find Next, Replace All and Select All Matches cover the entire text.`;
191
+ //#endregion
192
+ export { EditorFindWidget };
193
+
194
+ //# sourceMappingURL=findWidget.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"findWidget.js","names":[],"sources":["../src/findWidget.ts"],"sourcesContent":["import type { EditorFindWidgetState } from './findController'\nimport { createFindIcon, FIND_ICONS, type FindIcon } from './findIcons'\nimport { FIND_MATCHES_LIMIT } from './search'\n\nconst EDITOR_THEME_VARIABLES = [\n '--editor-background',\n '--editor-foreground',\n '--editor-caret-color',\n] as const\n\nexport type EditorFindWidgetOptions = {\n readonly onSearchInput: (value: string) => void\n readonly onReplaceInput: (value: string) => void\n readonly onToggleReplace: () => void\n readonly onPrevious: () => void\n readonly onNext: () => void\n readonly onClose: () => void\n readonly onToggleCase: () => void\n readonly onToggleWholeWord: () => void\n readonly onToggleRegex: () => void\n readonly onToggleScope: () => void\n readonly onTogglePreserveCase: () => void\n readonly onReplaceOne: () => void\n readonly onReplaceAll: () => void\n}\n\nexport class EditorFindWidget {\n private readonly root: HTMLDivElement\n private readonly findInput: HTMLInputElement\n private readonly replaceInput: HTMLInputElement\n private readonly replaceRow: HTMLDivElement\n private readonly count: HTMLSpanElement\n private readonly replaceToggleButton: HTMLButtonElement\n private readonly caseButton: HTMLButtonElement\n private readonly wordButton: HTMLButtonElement\n private readonly regexButton: HTMLButtonElement\n private readonly scopeButton: HTMLButtonElement\n private readonly preserveButton: HTMLButtonElement\n\n public constructor(\n container: HTMLElement,\n private readonly themeSource: HTMLElement,\n private readonly options: EditorFindWidgetOptions,\n ) {\n const document = container.ownerDocument\n const position = container.ownerDocument.defaultView?.getComputedStyle(container).position\n if (!position || position === 'static') container.style.position = 'relative'\n this.root = document.createElement('div')\n this.findInput = document.createElement('input')\n this.replaceInput = document.createElement('input')\n this.replaceRow = document.createElement('div')\n this.count = document.createElement('span')\n this.replaceToggleButton = createFindButton(\n document,\n FIND_ICONS.replaceToggle,\n 'Toggle Replace',\n )\n this.replaceToggleButton.classList.add('editor-find-replace-toggle')\n this.caseButton = createFindButton(document, FIND_ICONS.caseSensitive, 'Match Case')\n this.wordButton = createFindButton(document, FIND_ICONS.wholeWord, 'Whole Word')\n this.regexButton = createFindButton(document, FIND_ICONS.regex, 'Use Regular Expression')\n this.scopeButton = createFindButton(document, FIND_ICONS.scope, 'Find in Selection')\n this.preserveButton = createFindButton(document, FIND_ICONS.preserveCase, 'Preserve Case')\n this.build(document)\n container.appendChild(this.root)\n }\n\n public show(replaceVisible: boolean): void {\n syncEditorThemeVariables(this.root, this.themeSource)\n this.root.hidden = false\n this.replaceRow.hidden = !replaceVisible\n }\n\n public hide(): void {\n this.root.hidden = true\n }\n\n // The stylesheet anchors the widget a fixed inset from the container's\n // trailing edge, which is also where a minimap parks. Margin keeps that inset\n // authoritative and shifts the whole widget inboard of the claimed strip.\n public setTrailingInset(width: number): void {\n this.root.style.marginRight = width > 0 ? `${Math.ceil(width)}px` : ''\n }\n\n public update(state: EditorFindWidgetState): void {\n syncEditorThemeVariables(this.root, this.themeSource)\n if (this.findInput.value !== state.searchString) this.findInput.value = state.searchString\n if (this.replaceInput.value !== state.replaceString)\n this.replaceInput.value = state.replaceString\n this.replaceRow.hidden = !state.replaceRevealed\n setToggleExpanded(this.replaceToggleButton, state.replaceRevealed, 'Replace')\n this.count.textContent = resultCountText(state.matchesPosition, state.matchesCount)\n this.count.title = state.highlightsTruncated\n ? TRUNCATED_HIGHLIGHTS_TITLE\n : this.count.textContent\n setTogglePressed(this.caseButton, state.matchCase, 'Match Case')\n setTogglePressed(this.wordButton, state.wholeWord, 'Match Whole Word')\n setTogglePressed(this.regexButton, state.isRegex, 'Use Regular Expression')\n setTogglePressed(this.scopeButton, state.inSelection, 'Find in Selection')\n setTogglePressed(this.preserveButton, state.preserveCase, 'Preserve Case')\n }\n\n public focusFindInput(): void {\n this.findInput.focus()\n this.findInput.select()\n }\n\n public focusReplaceInput(): void {\n this.replaceInput.focus()\n this.replaceInput.select()\n }\n\n public dispose(): void {\n this.root.remove()\n }\n\n private build(document: Document): void {\n this.root.className = 'editor-find-widget'\n this.root.hidden = true\n // Layer from the editor's shared stacking scale so the widget keeps its\n // place as other surfaces claim tiers; the literal is the standalone\n // fallback for hosts that ship this stylesheet without the editor's.\n this.root.style.zIndex = 'var(--editor-z-overlay-widget, 20)'\n this.findInput.className = 'editor-find-input'\n this.findInput.type = 'text'\n this.findInput.placeholder = 'Find'\n this.findInput.title = 'Find'\n this.findInput.spellcheck = false\n this.findInput.autocomplete = 'off'\n this.findInput.setAttribute('aria-label', 'Find')\n this.replaceInput.className = 'editor-find-input editor-find-input-standalone'\n this.replaceInput.type = 'text'\n this.replaceInput.placeholder = 'Replace'\n this.replaceInput.title = 'Replace'\n this.replaceInput.spellcheck = false\n this.replaceInput.autocomplete = 'off'\n this.replaceInput.setAttribute('aria-label', 'Replace')\n this.replaceRow.className = 'editor-find-row editor-find-replace-row'\n this.count.className = 'editor-find-count'\n\n this.root.append(this.findRow(document), this.replaceRow)\n this.installHandlers()\n }\n\n private findRow(document: Document): HTMLDivElement {\n const row = document.createElement('div')\n row.className = 'editor-find-row'\n row.append(\n this.replaceToggleButton,\n this.findInputFrame(document),\n this.count,\n this.scopeButton,\n createFindButton(document, FIND_ICONS.previous, 'Previous Match', this.options.onPrevious),\n createFindButton(document, FIND_ICONS.next, 'Next Match', this.options.onNext),\n createFindButton(document, FIND_ICONS.close, 'Close', this.options.onClose),\n )\n this.replaceRow.append(\n this.replaceInput,\n this.preserveButton,\n createFindButton(document, FIND_ICONS.replace, 'Replace', this.options.onReplaceOne),\n createFindButton(document, FIND_ICONS.replaceAll, 'Replace All', this.options.onReplaceAll),\n )\n return row\n }\n\n private findInputFrame(document: Document): HTMLDivElement {\n const frame = document.createElement('div')\n const controls = document.createElement('div')\n frame.className = 'editor-find-input-frame'\n controls.className = 'editor-find-input-controls'\n controls.append(this.caseButton, this.wordButton, this.regexButton)\n frame.append(this.findInput, controls)\n return frame\n }\n\n private installHandlers(): void {\n this.root.addEventListener('keydown', (event) => this.handleKeyDown(event))\n this.findInput.addEventListener('input', () => this.options.onSearchInput(this.findInput.value))\n this.replaceInput.addEventListener('input', () =>\n this.options.onReplaceInput(this.replaceInput.value),\n )\n this.caseButton.addEventListener('click', this.options.onToggleCase)\n this.wordButton.addEventListener('click', this.options.onToggleWholeWord)\n this.regexButton.addEventListener('click', this.options.onToggleRegex)\n this.replaceToggleButton.addEventListener('click', this.options.onToggleReplace)\n this.scopeButton.addEventListener('click', this.options.onToggleScope)\n this.preserveButton.addEventListener('click', this.options.onTogglePreserveCase)\n }\n\n private handleKeyDown(event: KeyboardEvent): void {\n event.stopPropagation()\n const shouldClose = [isFindToggleKey(event), event.key === 'Escape'].some(Boolean)\n if (shouldClose) {\n event.preventDefault()\n this.options.onClose()\n return\n }\n\n if (event.key !== 'Enter') return\n event.preventDefault()\n if (event.target === this.replaceInput && !event.shiftKey) {\n this.options.onReplaceOne()\n return\n }\n if (event.shiftKey) this.options.onPrevious()\n else this.options.onNext()\n }\n}\n\nfunction createFindButton(\n document: Document,\n icon: FindIcon,\n title: string,\n onClick?: () => void,\n): HTMLButtonElement {\n const button = document.createElement('button')\n button.type = 'button'\n button.className = 'editor-find-button'\n button.appendChild(createFindIcon(document, icon))\n setNativeTooltip(button, title)\n if (onClick) button.addEventListener('click', onClick)\n return button\n}\n\nfunction syncEditorThemeVariables(target: HTMLElement, source: HTMLElement): void {\n const style = source.ownerDocument.defaultView?.getComputedStyle(source)\n if (!style) return\n\n for (const variable of EDITOR_THEME_VARIABLES) {\n const value =\n source.style.getPropertyValue(variable).trim() || style.getPropertyValue(variable).trim()\n if (value) target.style.setProperty(variable, value)\n }\n}\n\nfunction setTogglePressed(button: HTMLButtonElement, pressed: boolean, label: string): void {\n button.classList.toggle('active', pressed)\n button.setAttribute('aria-pressed', pressed ? 'true' : 'false')\n setNativeTooltip(button, toggleTooltip(label, pressed))\n}\n\nfunction setToggleExpanded(button: HTMLButtonElement, expanded: boolean, label: string): void {\n button.classList.toggle('active', expanded)\n button.setAttribute('aria-expanded', expanded ? 'true' : 'false')\n setNativeTooltip(button, expanded ? `Hide ${label}` : `Show ${label}`)\n}\n\nfunction setNativeTooltip(element: HTMLElement, value: string): void {\n element.title = value\n element.setAttribute('aria-label', value)\n}\n\nfunction isFindToggleKey(event: KeyboardEvent): boolean {\n if (event.key.toLowerCase() !== 'f') return false\n if (event.altKey || event.shiftKey) return false\n return event.metaKey || event.ctrlKey\n}\n\nfunction toggleTooltip(label: string, active: boolean): string {\n return active ? `${label} (On)` : `${label} (Off)`\n}\n\nfunction resultCountText(position: number, count: number): string {\n if (count === 0) return 'No results'\n return `${position || '?'} of ${count}`\n}\n\n// The count is exact; what stops at the cap is the painting, and saying so is the\n// only sign a reader gets that an unpainted match further down is still a match.\nconst TRUNCATED_HIGHLIGHTS_TITLE = `Only the first ${FIND_MATCHES_LIMIT} results are highlighted. Every result is counted, and Find Next, Replace All and Select All Matches cover the entire text.`\n"],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import './style.css';
2
+ export { createEditorFindContributionProviders, createEditorFindPlugin, EDITOR_FIND_FEATURE, EDITOR_FIND_FEATURE_ID, type EditorFindContributionProviders, type EditorFindFeature, } from './plugin';
3
+ export { FIND_HIGHLIGHT_Z_INDEX } from './findController';
4
+ export type { EditorFindOptions } from './types';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,aAAa,CAAA;AAEpB,OAAO,EACL,qCAAqC,EACrC,sBAAsB,EACtB,mBAAmB,EACnB,sBAAsB,EACtB,KAAK,+BAA+B,EACpC,KAAK,iBAAiB,GACvB,MAAM,UAAU,CAAA;AACjB,OAAO,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAA;AACzD,YAAY,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,4 @@
1
+ import { FIND_HIGHLIGHT_Z_INDEX } from "./findController.js";
2
+ import { EDITOR_FIND_FEATURE, EDITOR_FIND_FEATURE_ID, createEditorFindContributionProviders, createEditorFindPlugin } from "./plugin.js";
3
+ import "./style.css";
4
+ export { EDITOR_FIND_FEATURE, EDITOR_FIND_FEATURE_ID, FIND_HIGHLIGHT_Z_INDEX, createEditorFindContributionProviders, createEditorFindPlugin };
@@ -0,0 +1,14 @@
1
+ import type { EditorCapabilityContributionProvider, EditorCommandContributionProvider, EditorEditContributionProvider, EditorFindFeature, EditorPlugin, EditorViewContributionProvider } from '@singapore-editor/core/extensions';
2
+ import { EDITOR_FIND_FEATURE, EDITOR_FIND_FEATURE_ID } from '@singapore-editor/core/extensions';
3
+ import type { EditorFindOptions } from './types';
4
+ export { EDITOR_FIND_FEATURE, EDITOR_FIND_FEATURE_ID };
5
+ export type EditorFindContributionProviders = {
6
+ readonly view: EditorViewContributionProvider;
7
+ readonly command: EditorCommandContributionProvider;
8
+ readonly capability: EditorCapabilityContributionProvider;
9
+ readonly edit: EditorEditContributionProvider;
10
+ };
11
+ export declare function createEditorFindPlugin(options?: EditorFindOptions): EditorPlugin;
12
+ export declare function createEditorFindContributionProviders(options?: EditorFindOptions): EditorFindContributionProviders;
13
+ export type { EditorFindFeature, EditorFindOptions };
14
+ //# sourceMappingURL=plugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAGV,oCAAoC,EAGpC,iCAAiC,EAIjC,8BAA8B,EAC9B,iBAAiB,EAGjB,YAAY,EAIZ,8BAA8B,EAG/B,MAAM,mCAAmC,CAAA;AAC1C,OAAO,EACL,mBAAmB,EACnB,sBAAsB,EAEvB,MAAM,mCAAmC,CAAA;AAW1C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAA;AAEhD,OAAO,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,CAAA;AAEtD,MAAM,MAAM,+BAA+B,GAAG;IAC5C,QAAQ,CAAC,IAAI,EAAE,8BAA8B,CAAA;IAC7C,QAAQ,CAAC,OAAO,EAAE,iCAAiC,CAAA;IACnD,QAAQ,CAAC,UAAU,EAAE,oCAAoC,CAAA;IACzD,QAAQ,CAAC,IAAI,EAAE,8BAA8B,CAAA;CAC9C,CAAA;AAED,wBAAgB,sBAAsB,CAAC,OAAO,GAAE,iBAAsB,GAAG,YAAY,CAapF;AAED,wBAAgB,qCAAqC,CACnD,OAAO,GAAE,iBAAsB,GAC9B,+BAA+B,CAgBjC;AAqeD,YAAY,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,CAAA"}