react-stately 3.49.0 → 3.50.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.
- package/dist/exports/useTokenFieldState.cjs.map +1 -1
- package/dist/exports/useTokenFieldState.js.map +1 -1
- package/dist/exports/useTokenFieldState.mjs.map +1 -1
- package/dist/private/calendar/useCalendarState.cjs +2 -1
- package/dist/private/calendar/useCalendarState.cjs.map +1 -1
- package/dist/private/calendar/useCalendarState.js +3 -2
- package/dist/private/calendar/useCalendarState.js.map +1 -1
- package/dist/private/calendar/useCalendarState.mjs +3 -2
- package/dist/private/calendar/useCalendarState.mjs.map +1 -1
- package/dist/private/tokenfield/TokenFieldValue.cjs +45 -15
- package/dist/private/tokenfield/TokenFieldValue.cjs.map +1 -1
- package/dist/private/tokenfield/TokenFieldValue.js +45 -17
- package/dist/private/tokenfield/TokenFieldValue.js.map +1 -1
- package/dist/private/tokenfield/TokenFieldValue.mjs +46 -16
- package/dist/private/tokenfield/TokenFieldValue.mjs.map +1 -1
- package/dist/types/exports/useTokenFieldState.d.ts +1 -1
- package/dist/types/src/collections/Item.d.ts +1 -6
- package/dist/types/src/collections/Section.d.ts +1 -6
- package/dist/types/src/table/Cell.d.ts +0 -5
- package/dist/types/src/table/Column.d.ts +0 -7
- package/dist/types/src/table/Row.d.ts +0 -6
- package/dist/types/src/table/TableBody.d.ts +1 -6
- package/dist/types/src/table/TableHeader.d.ts +1 -7
- package/dist/types/src/tokenfield/TokenFieldValue.d.ts +27 -4
- package/package.json +5 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"mappings":"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","sources":["packages/react-stately/src/tokenfield/TokenFieldValue.ts"],"sourcesContent":["/*\n * Copyright 2026 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nexport type TokenFieldSegment<T = any> = TextSegment | TokenSegment<T>;\n\nexport interface TextSegment {\n type: 'text';\n text: string;\n}\n\nexport interface TokenSegment<T = any> {\n type: 'token';\n text: string;\n /** An arbitrary value associated with the token. */\n value?: T;\n}\n\nexport interface Position {\n /** Index of the segment in the list. */\n index: number;\n /** Text offset within the segment in UTF-16 code units. */\n offset: number;\n}\n\nenum Direction {\n Forward = 1,\n Backward = -1\n}\n\nexport interface TokenFieldValueOptions {\n caretPosition?: Position | null;\n}\n\n/**\n * A list of segments containing editable text and non-editable tokens.\n */\nexport class TokenFieldValue<T = any> {\n static readonly Direction = Direction;\n\n /** The text and token segments in the list. */\n readonly segments: readonly TokenFieldSegment<T>[];\n /** The caret position. */\n caretPosition: Position = {index: 0, offset: 0};\n // Linked list representing the undo/redo history.\n private previous: this | null = null;\n private next: this | null = null;\n private isCoalescing = true;\n\n /** Create a new list with the given segments. */\n constructor(tokens: readonly TokenFieldSegment<T>[], options?: TokenFieldValueOptions) {\n this.segments = tokens;\n this.caretPosition = options?.caretPosition ?? {index: 0, offset: 0};\n }\n\n protected createFieldValue(segments: readonly TokenFieldSegment<T>[]): this {\n const Constructor = this.constructor as new (\n segments: readonly TokenFieldSegment<T>[],\n options?: TokenFieldValueOptions\n ) => this;\n return new Constructor(segments);\n }\n\n /** Create a new list with the caret position set to the given position. */\n withCaretPosition(caretPosition: Position): this {\n if (\n this.caretPosition.index === caretPosition.index &&\n this.caretPosition.offset === caretPosition.offset\n ) {\n return this;\n }\n\n let result = this.createFieldValue(this.segments);\n result.caretPosition = caretPosition;\n result.previous = this.previous;\n result.next = this.next;\n result.isCoalescing = this.isCoalescing;\n return result;\n }\n\n private splitSegment(\n segment: TokenFieldSegment | undefined,\n offset: number\n ): [TokenFieldSegment | null, TokenFieldSegment | null] {\n if (!segment) {\n let empty = this.createTextSegment('');\n return [offset > 0 ? empty : null, offset > 0 ? null : empty];\n }\n\n if (segment.type === 'token') {\n return [offset > 0 ? {...segment} : null, offset > 0 ? null : {...segment}];\n }\n\n return [\n offset > 0 ? {type: 'text', text: segment.text.slice(0, offset)} : null,\n offset < segment.text.length ? this.createTextSegment(segment.text.slice(offset)) : null\n ];\n }\n\n private createTextSegment(text: string): TextSegment {\n return {type: 'text', text};\n }\n\n protected tokenize(text: string): TokenFieldSegment<T>[] {\n return [this.createTextSegment(text)];\n }\n\n private clampPosition(position: Position): Position {\n if (this.segments.length > 0 && position.index >= this.segments.length) {\n return {\n index: this.segments.length - 1,\n offset: this.segments[this.segments.length - 1].text.length\n };\n }\n\n if (position.index < 0) {\n return {index: 0, offset: 0};\n }\n return position;\n }\n\n /** Replace the text between two positions with new text. */\n replaceRange(start: Position, end: Position, text: string, coalesce = true): this {\n return this.replaceRangeWithSegments(\n start,\n end,\n text.length > 0 ? [this.createTextSegment(text)] : [],\n coalesce\n );\n }\n\n /** Replace the text between two positions with new segments. */\n replaceRangeWithSegments(\n start: Position,\n end: Position,\n insert: TokenFieldSegment<T>[],\n coalesce = true\n ): this {\n start = this.clampPosition(start);\n end = this.clampPosition(end);\n let startSegment = this.segments[start.index];\n let endSegment = this.segments[end.index];\n let [startSplit] = this.splitSegment(startSegment, start.offset);\n let [, endSplit] = this.splitSegment(endSegment, end.offset);\n\n let newSegments = this.segments.slice(0, start.index);\n if (startSplit) {\n appendSegments(newSegments, [startSplit]);\n }\n\n if (insert.length) {\n appendSegments(newSegments, insert, text => this.tokenize(text));\n }\n\n let lastSegment = newSegments[newSegments.length - 1];\n let lastIsText = lastSegment && lastSegment.type === 'text';\n let caret = {\n index: lastIsText ? newSegments.length - 1 : newSegments.length,\n offset: lastIsText ? lastSegment.text.length : 0\n };\n\n if (endSplit) {\n appendSegments(newSegments, [endSplit]);\n }\n\n appendSegments(newSegments, this.segments.slice(end.index + 1));\n\n let segments = this.createFieldValue(newSegments);\n segments.caretPosition = caret;\n segments.isCoalescing = coalesce;\n if (this.isCoalescing && coalesce && this.previous) {\n segments.previous = this.previous;\n segments.previous.next = segments;\n } else {\n segments.previous = this;\n this.caretPosition = end;\n this.next = segments;\n }\n return segments;\n }\n\n /** Find the boundary before or after a position using an Intl.Segmenter. */\n findBoundaryWithSegmenter(\n position: Position,\n segmenter: Intl.Segmenter,\n direction: Direction\n ): Position | null {\n position = this.clampPosition(position);\n for (let i = position.index; i >= 0 && i < this.segments.length; i += direction) {\n let segment = this.segments[i];\n switch (segment.type) {\n case 'token':\n if (\n i !== position.index ||\n (direction === Direction.Backward ? position.offset > 0 : position.offset === 0)\n ) {\n let index = i + direction;\n return {\n index: index >= 0 ? index : 0,\n offset:\n direction === Direction.Backward && index >= 0\n ? this.segments[index].text.length\n : 0\n };\n }\n continue;\n case 'text': {\n let offset = direction === Direction.Backward ? segment.text.length : 0;\n if (i === position.index) {\n offset = position.offset;\n }\n if (direction === Direction.Backward) {\n offset--;\n }\n if (offset < 0 || offset >= segment.text.length) {\n continue;\n }\n\n let part = segmenter.segment(segment.text).containing(offset);\n while (part && part.isWordLike === false) {\n offset += direction;\n part = segmenter.segment(segment.text).containing(offset);\n }\n\n if (part) {\n return {\n index: i,\n offset:\n direction === Direction.Backward ? part.index : part.index + part.segment.length\n };\n }\n continue;\n }\n }\n }\n\n return null;\n }\n\n /** Find a line boundary before or after a position. */\n findLineBoundary(position: Position, direction: Direction): Position | null {\n let res = this.findText(position, direction, '\\n');\n if (res) {\n return res;\n }\n return direction === Direction.Backward\n ? {index: 0, offset: 0}\n : {\n index: this.segments.length - 1,\n offset: this.segments[this.segments.length - 1].text.length\n };\n }\n\n /** Find a string or regular expression match before or after a position. */\n findText(position: Position, direction: Direction, search: string | RegExp): Position | null {\n if (this.segments.length === 0) {\n return null;\n }\n\n for (let i = position.index; i >= 0 && i < this.segments.length; i += direction) {\n let segment = this.segments[i];\n if (segment.type !== 'text') {\n continue;\n }\n let offset = findInText(\n segment.text,\n search,\n direction,\n i === position.index ? position.offset : undefined\n );\n if (offset >= 0) {\n return {\n index: i,\n offset: offset\n };\n }\n }\n\n return null;\n }\n\n /** Delete text at a position using a segmenter. */\n delete(\n position: Position,\n segmenter: Intl.Segmenter,\n direction: Direction,\n coalesce = true\n ): this {\n let boundary = this.findBoundaryWithSegmenter(position, segmenter, direction);\n if (boundary) {\n return this.replaceRange(\n direction === Direction.Backward ? boundary : position,\n direction === Direction.Backward ? position : boundary,\n '',\n coalesce\n );\n }\n\n this.caretPosition = position;\n return this;\n }\n\n /** Delete text to the next or previous line break. */\n deleteLine(position: Position, direction: Direction, coalesce = true): this {\n if (this.segments.length === 0) {\n return this;\n }\n\n let boundary = this.findLineBoundary(position, direction);\n if (boundary) {\n return this.replaceRange(\n direction === Direction.Backward ? boundary : position,\n direction === Direction.Backward ? position : boundary,\n '',\n coalesce\n );\n }\n\n return this;\n }\n\n /** Create a new list containing a subset of the segments. */\n slice(start: Position, end: Position): this {\n start = this.clampPosition(start);\n end = this.clampPosition(end);\n if (start.index === end.index && start.offset === end.offset) {\n return this.createFieldValue([]);\n }\n if (start.index === end.index) {\n let segment = this.segments[start.index];\n if (segment.type === 'text') {\n return this.createFieldValue([\n {type: 'text', text: segment.text.slice(start.offset, end.offset)}\n ]);\n }\n return this.createFieldValue([segment]);\n }\n let startSegment = this.segments[start.index];\n let endSegment = this.segments[end.index];\n let [, startSplit] = this.splitSegment(startSegment, start.offset);\n let [endSplit] = this.splitSegment(endSegment, end.offset);\n\n let result: TokenFieldSegment<T>[] = [];\n if (startSplit) {\n result.push(startSplit);\n }\n result.push(...this.segments.slice(start.index + 1, end.index));\n if (endSplit) {\n result.push(endSplit);\n }\n return this.createFieldValue(result);\n }\n\n /** Convert the list to a string. */\n toString(): string {\n return this.segments.map(seg => seg.text).join('');\n }\n\n /** Returns the previous list in the undo history. */\n undo(): this {\n return this.previous ?? this;\n }\n\n /** Returns the next list in the redo history. */\n redo(): this {\n return this.next ?? this;\n }\n\n /** End coalescing undo/redo history. */\n endCoalescing(): void {\n this.isCoalescing = false;\n }\n}\n\nfunction findInText(\n text: string,\n search: string | RegExp,\n direction: Direction,\n fromOffset?: number\n): number {\n if (typeof search === 'string') {\n if (direction === Direction.Backward) {\n return text.lastIndexOf(search, fromOffset !== undefined ? fromOffset - 1 : text.length - 1);\n }\n return text.indexOf(search, fromOffset ?? 0);\n }\n\n if (direction === Direction.Forward) {\n let start = fromOffset ?? 0;\n let index = text.slice(start).search(search);\n return index >= 0 ? start + index : -1;\n }\n\n let limit = fromOffset !== undefined ? fromOffset : text.length;\n if (limit < 0) {\n return -1;\n }\n\n let re = search.flags.includes('g') ? search : new RegExp(search.source, search.flags + 'g');\n let matches = Array.from(text.slice(0, limit).matchAll(re));\n return matches.at(-1)?.index ?? -1;\n}\n\nfunction appendSegments(\n segments: TokenFieldSegment[],\n insert: TokenFieldSegment[],\n tokenize?: (text: string) => TokenFieldSegment[]\n): TokenFieldSegment[] {\n for (let segment of insert) {\n if (segment.type === 'text' && segment.text.length === 0) {\n continue;\n }\n\n let last = segments[segments.length - 1];\n if (last && last.type === 'text' && segment.type === 'text') {\n if (tokenize) {\n let tokenized = tokenize(last.text + segment.text);\n segments.splice(segments.length - 1, 1, ...tokenized);\n } else {\n segments[segments.length - 1] = {type: 'text', text: last.text + segment.text};\n }\n } else if (tokenize && segment.type === 'text') {\n let tokenized = tokenize(segment.text);\n segments.push(...tokenized);\n } else {\n segments.push(segment);\n }\n }\n return segments;\n}\n"],"names":[],"version":3,"file":"TokenFieldValue.cjs.map"}
|
|
1
|
+
{"mappings":"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","sources":["packages/react-stately/src/tokenfield/TokenFieldValue.ts"],"sourcesContent":["/*\n * Copyright 2026 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nexport type TokenFieldSegment<T = any> = TextSegment | TokenSegment<T>;\n\nexport interface TextSegment {\n type: 'text';\n text: string;\n}\n\nexport interface TokenSegment<T = any> {\n type: 'token';\n text: string;\n /** An arbitrary value associated with the token. */\n value?: T;\n}\n\nexport interface Position {\n /** Index of the segment in the list. */\n index: number;\n /** Text offset within the segment in UTF-16 code units. */\n offset: number;\n}\n\n/** Represents a text selection in a TokenField. */\nexport class SelectedRange {\n /** The anchor position. */\n anchor: Position;\n /** The current (i.e. caret) position. */\n current: Position;\n\n /**\n * Creates a new selection range. If only a single position is provided, the selection is\n * collapsed.\n */\n constructor(anchor: Position, current: Position = anchor) {\n this.anchor = anchor;\n this.current = current;\n }\n\n /** Whether the selection is collapsed to a single caret position. */\n get isCollapsed() {\n return this.anchor.index === this.current.index && this.anchor.offset === this.current.offset;\n }\n\n /** The side of the selection closest to the start of the value. */\n get start() {\n return compare(this.anchor, this.current) < 0 ? this.anchor : this.current;\n }\n\n /** The side of the selection closest to the end of the value. */\n get end() {\n return compare(this.anchor, this.current) < 0 ? this.current : this.anchor;\n }\n\n /** Returns whether this selection is equal to another. */\n isEqual(other: SelectedRange) {\n if (this === other) {\n return true;\n }\n return (\n this.anchor.index === other.anchor.index &&\n this.anchor.offset === other.anchor.offset &&\n this.current.index === other.current.index &&\n this.current.offset === other.current.offset\n );\n }\n}\n\nfunction compare(a: Position, b: Position) {\n if (a.index === b.index) {\n return a.offset - b.offset;\n }\n\n return a.index - b.index;\n}\n\nenum Direction {\n Forward = 1,\n Backward = -1\n}\n\nexport interface TokenFieldValueOptions {\n selectedRange?: SelectedRange | null;\n}\n\n/**\n * A list of segments containing editable text and non-editable tokens.\n */\nexport class TokenFieldValue<T = any> {\n static readonly Direction = Direction;\n static readonly SelectedRange = SelectedRange;\n\n /** The text and token segments in the list. */\n readonly segments: readonly TokenFieldSegment<T>[];\n /** The selected range. */\n selectedRange: SelectedRange;\n // Linked list representing the undo/redo history.\n private previous: this | null = null;\n private next: this | null = null;\n private isCoalescing = true;\n\n /** Create a new list with the given segments. */\n constructor(tokens: readonly TokenFieldSegment<T>[], options?: TokenFieldValueOptions) {\n this.segments = tokens;\n this.selectedRange = options?.selectedRange ?? new SelectedRange({index: 0, offset: 0});\n }\n\n protected createFieldValue(segments: readonly TokenFieldSegment<T>[]): this {\n const Constructor = this.constructor as new (\n segments: readonly TokenFieldSegment<T>[],\n options?: TokenFieldValueOptions\n ) => this;\n return new Constructor(segments);\n }\n\n get caretPosition(): Position {\n return this.selectedRange.current;\n }\n\n /** Create a new list with the caret position set to the given position. */\n withSelectedRange(selectedRange: SelectedRange): this {\n if (this.selectedRange.isEqual(selectedRange)) {\n return this;\n }\n\n let result = this.createFieldValue(this.segments);\n result.selectedRange = selectedRange;\n result.previous = this.previous;\n result.next = this.next;\n result.isCoalescing = this.isCoalescing;\n return result;\n }\n\n withCaretPosition(position: Position): this {\n return this.withSelectedRange(new SelectedRange(position));\n }\n\n private splitSegment(\n segment: TokenFieldSegment | undefined,\n offset: number\n ): [TokenFieldSegment | null, TokenFieldSegment | null] {\n if (!segment) {\n let empty = this.createTextSegment('');\n return [offset > 0 ? empty : null, offset > 0 ? null : empty];\n }\n\n if (segment.type === 'token') {\n return [offset > 0 ? {...segment} : null, offset > 0 ? null : {...segment}];\n }\n\n return [\n offset > 0 ? {type: 'text', text: segment.text.slice(0, offset)} : null,\n offset < segment.text.length ? this.createTextSegment(segment.text.slice(offset)) : null\n ];\n }\n\n private createTextSegment(text: string): TextSegment {\n return {type: 'text', text};\n }\n\n protected tokenize(text: string): TokenFieldSegment<T>[] {\n return [this.createTextSegment(text)];\n }\n\n private clampPosition(position: Position): Position {\n if (this.segments.length > 0 && position.index >= this.segments.length) {\n return {\n index: this.segments.length - 1,\n offset: this.segments[this.segments.length - 1].text.length\n };\n }\n\n if (position.index < 0) {\n return {index: 0, offset: 0};\n }\n return position;\n }\n\n /** Replace the text between two positions with new text. */\n replaceRange(start: Position, end: Position, text: string, coalesce = true): this {\n return this.replaceRangeWithSegments(\n start,\n end,\n text.length > 0 ? [this.createTextSegment(text)] : [],\n coalesce\n );\n }\n\n /** Replace the text between two positions with new segments. */\n replaceRangeWithSegments(\n start: Position,\n end: Position,\n insert: TokenFieldSegment<T>[],\n coalesce = true\n ): this {\n start = this.clampPosition(start);\n end = this.clampPosition(end);\n let startSegment = this.segments[start.index];\n let endSegment = this.segments[end.index];\n let [startSplit] = this.splitSegment(startSegment, start.offset);\n let [, endSplit] = this.splitSegment(endSegment, end.offset);\n\n let newSegments = this.segments.slice(0, start.index);\n if (startSplit) {\n appendSegments(newSegments, [startSplit]);\n }\n\n if (insert.length) {\n appendSegments(newSegments, insert, text => this.tokenize(text));\n }\n\n let lastSegment = newSegments[newSegments.length - 1];\n let lastIsText = lastSegment && lastSegment.type === 'text';\n let caret = {\n index: lastIsText ? newSegments.length - 1 : newSegments.length,\n offset: lastIsText ? lastSegment.text.length : 0\n };\n\n if (endSplit) {\n appendSegments(newSegments, [endSplit]);\n }\n\n appendSegments(newSegments, this.segments.slice(end.index + 1));\n\n let segments = this.createFieldValue(newSegments);\n segments.selectedRange = new SelectedRange(caret);\n segments.isCoalescing = coalesce;\n if (this.isCoalescing && coalesce && this.previous) {\n segments.previous = this.previous;\n segments.previous.next = segments;\n } else {\n segments.previous = this;\n this.selectedRange = new SelectedRange(start, end);\n this.next = segments;\n }\n return segments;\n }\n\n /** Find the boundary before or after a position using an Intl.Segmenter. */\n findBoundaryWithSegmenter(\n position: Position,\n segmenter: Intl.Segmenter,\n direction: Direction\n ): Position | null {\n position = this.clampPosition(position);\n for (let i = position.index; i >= 0 && i < this.segments.length; i += direction) {\n let segment = this.segments[i];\n switch (segment.type) {\n case 'token':\n if (\n i !== position.index ||\n (direction === Direction.Backward ? position.offset > 0 : position.offset === 0)\n ) {\n let index = i + direction;\n return {\n index: index >= 0 ? index : 0,\n offset:\n direction === Direction.Backward && index >= 0\n ? this.segments[index].text.length\n : 0\n };\n }\n continue;\n case 'text': {\n let offset = direction === Direction.Backward ? segment.text.length : 0;\n if (i === position.index) {\n offset = position.offset;\n }\n if (direction === Direction.Backward) {\n offset--;\n }\n if (offset < 0 || offset >= segment.text.length) {\n continue;\n }\n\n let part = segmenter.segment(segment.text).containing(offset);\n while (part && part.isWordLike === false) {\n offset += direction;\n part = segmenter.segment(segment.text).containing(offset);\n }\n\n if (part) {\n return {\n index: i,\n offset:\n direction === Direction.Backward ? part.index : part.index + part.segment.length\n };\n }\n continue;\n }\n }\n }\n\n return null;\n }\n\n /** Find a line boundary before or after a position. */\n findLineBoundary(position: Position, direction: Direction): Position | null {\n let res = this.findText(position, direction, '\\n');\n if (res) {\n return res;\n }\n return direction === Direction.Backward\n ? {index: 0, offset: 0}\n : {\n index: this.segments.length - 1,\n offset: this.segments[this.segments.length - 1].text.length\n };\n }\n\n /** Find a string or regular expression match before or after a position. */\n findText(position: Position, direction: Direction, search: string | RegExp): Position | null {\n if (this.segments.length === 0) {\n return null;\n }\n\n for (let i = position.index; i >= 0 && i < this.segments.length; i += direction) {\n let segment = this.segments[i];\n if (segment.type !== 'text') {\n continue;\n }\n let offset = findInText(\n segment.text,\n search,\n direction,\n i === position.index ? position.offset : undefined\n );\n if (offset >= 0) {\n return {\n index: i,\n offset: offset\n };\n }\n }\n\n return null;\n }\n\n /** Delete text at a position using a segmenter. */\n delete(\n position: Position,\n segmenter: Intl.Segmenter,\n direction: Direction,\n coalesce = true\n ): this {\n let boundary = this.findBoundaryWithSegmenter(position, segmenter, direction);\n if (boundary) {\n return this.replaceRange(\n direction === Direction.Backward ? boundary : position,\n direction === Direction.Backward ? position : boundary,\n '',\n coalesce\n );\n }\n\n return this.withSelectedRange(new SelectedRange(position));\n }\n\n /** Delete text to the next or previous line break. */\n deleteLine(position: Position, direction: Direction, coalesce = true): this {\n if (this.segments.length === 0) {\n return this;\n }\n\n let boundary = this.findLineBoundary(position, direction);\n if (boundary) {\n return this.replaceRange(\n direction === Direction.Backward ? boundary : position,\n direction === Direction.Backward ? position : boundary,\n '',\n coalesce\n );\n }\n\n return this.withSelectedRange(new SelectedRange(position));\n }\n\n /** Create a new list containing a subset of the segments. */\n slice(start: Position, end: Position): this {\n start = this.clampPosition(start);\n end = this.clampPosition(end);\n if (start.index === end.index && start.offset === end.offset) {\n return this.createFieldValue([]);\n }\n if (start.index === end.index) {\n let segment = this.segments[start.index];\n if (segment.type === 'text') {\n return this.createFieldValue([\n {type: 'text', text: segment.text.slice(start.offset, end.offset)}\n ]);\n }\n return this.createFieldValue([segment]);\n }\n let startSegment = this.segments[start.index];\n let endSegment = this.segments[end.index];\n let [, startSplit] = this.splitSegment(startSegment, start.offset);\n let [endSplit] = this.splitSegment(endSegment, end.offset);\n\n let result: TokenFieldSegment<T>[] = [];\n if (startSplit) {\n result.push(startSplit);\n }\n result.push(...this.segments.slice(start.index + 1, end.index));\n if (endSplit) {\n result.push(endSplit);\n }\n return this.createFieldValue(result);\n }\n\n /** Convert the list to a string. */\n toString(): string {\n return this.segments.map(seg => seg.text).join('');\n }\n\n /** Returns the previous list in the undo history. */\n undo(): this {\n return this.previous ?? this;\n }\n\n /** Returns the next list in the redo history. */\n redo(): this {\n return this.next ?? this;\n }\n\n /** End coalescing undo/redo history. */\n endCoalescing(): void {\n this.isCoalescing = false;\n }\n}\n\nfunction findInText(\n text: string,\n search: string | RegExp,\n direction: Direction,\n fromOffset?: number\n): number {\n if (typeof search === 'string') {\n if (direction === Direction.Backward) {\n return text.lastIndexOf(search, fromOffset !== undefined ? fromOffset - 1 : text.length - 1);\n }\n return text.indexOf(search, fromOffset ?? 0);\n }\n\n if (direction === Direction.Forward) {\n let start = fromOffset ?? 0;\n let index = text.slice(start).search(search);\n return index >= 0 ? start + index : -1;\n }\n\n let limit = fromOffset !== undefined ? fromOffset : text.length;\n if (limit < 0) {\n return -1;\n }\n\n let re = search.flags.includes('g') ? search : new RegExp(search.source, search.flags + 'g');\n let matches = Array.from(text.slice(0, limit).matchAll(re));\n return matches.at(-1)?.index ?? -1;\n}\n\nfunction appendSegments(\n segments: TokenFieldSegment[],\n insert: TokenFieldSegment[],\n tokenize?: (text: string) => TokenFieldSegment[]\n): TokenFieldSegment[] {\n for (let segment of insert) {\n if (segment.type === 'text' && segment.text.length === 0) {\n continue;\n }\n\n let last = segments[segments.length - 1];\n if (last && last.type === 'text' && segment.type === 'text') {\n if (tokenize) {\n let tokenized = tokenize(last.text + segment.text);\n segments.splice(segments.length - 1, 1, ...tokenized);\n } else {\n segments[segments.length - 1] = {type: 'text', text: last.text + segment.text};\n }\n } else if (tokenize && segment.type === 'text') {\n let tokenized = tokenize(segment.text);\n segments.push(...tokenized);\n } else {\n segments.push(segment);\n }\n }\n return segments;\n}\n"],"names":[],"version":3,"file":"TokenFieldValue.cjs.map"}
|
|
@@ -8,7 +8,33 @@
|
|
|
8
8
|
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
|
|
9
9
|
* OF ANY KIND, either express or implied. See the License for the specific language
|
|
10
10
|
* governing permissions and limitations under the License.
|
|
11
|
-
*/
|
|
11
|
+
*/ class $bb130d0e51bd3001$export$939a711fc6327372 {
|
|
12
|
+
/** Whether the selection is collapsed to a single caret position. */ get isCollapsed() {
|
|
13
|
+
return this.anchor.index === this.current.index && this.anchor.offset === this.current.offset;
|
|
14
|
+
}
|
|
15
|
+
/** The side of the selection closest to the start of the value. */ get start() {
|
|
16
|
+
return $bb130d0e51bd3001$var$compare(this.anchor, this.current) < 0 ? this.anchor : this.current;
|
|
17
|
+
}
|
|
18
|
+
/** The side of the selection closest to the end of the value. */ get end() {
|
|
19
|
+
return $bb130d0e51bd3001$var$compare(this.anchor, this.current) < 0 ? this.current : this.anchor;
|
|
20
|
+
}
|
|
21
|
+
/** Returns whether this selection is equal to another. */ isEqual(other) {
|
|
22
|
+
if (this === other) return true;
|
|
23
|
+
return this.anchor.index === other.anchor.index && this.anchor.offset === other.anchor.offset && this.current.index === other.current.index && this.current.offset === other.current.offset;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Creates a new selection range. If only a single position is provided, the selection is
|
|
27
|
+
* collapsed.
|
|
28
|
+
*/ constructor(anchor, current = anchor){
|
|
29
|
+
this.anchor = anchor;
|
|
30
|
+
this.current = current;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
function $bb130d0e51bd3001$var$compare(a, b) {
|
|
34
|
+
if (a.index === b.index) return a.offset - b.offset;
|
|
35
|
+
return a.index - b.index;
|
|
36
|
+
}
|
|
37
|
+
var $bb130d0e51bd3001$var$Direction = /*#__PURE__*/ function(Direction) {
|
|
12
38
|
Direction[Direction["Forward"] = 1] = "Forward";
|
|
13
39
|
Direction[Direction["Backward"] = -1] = "Backward";
|
|
14
40
|
return Direction;
|
|
@@ -18,15 +44,21 @@ class $bb130d0e51bd3001$export$f3decd0c2cd2fe2e {
|
|
|
18
44
|
const Constructor = this.constructor;
|
|
19
45
|
return new Constructor(segments);
|
|
20
46
|
}
|
|
21
|
-
|
|
22
|
-
|
|
47
|
+
get caretPosition() {
|
|
48
|
+
return this.selectedRange.current;
|
|
49
|
+
}
|
|
50
|
+
/** Create a new list with the caret position set to the given position. */ withSelectedRange(selectedRange) {
|
|
51
|
+
if (this.selectedRange.isEqual(selectedRange)) return this;
|
|
23
52
|
let result = this.createFieldValue(this.segments);
|
|
24
|
-
result.
|
|
53
|
+
result.selectedRange = selectedRange;
|
|
25
54
|
result.previous = this.previous;
|
|
26
55
|
result.next = this.next;
|
|
27
56
|
result.isCoalescing = this.isCoalescing;
|
|
28
57
|
return result;
|
|
29
58
|
}
|
|
59
|
+
withCaretPosition(position) {
|
|
60
|
+
return this.withSelectedRange(new $bb130d0e51bd3001$export$939a711fc6327372(position));
|
|
61
|
+
}
|
|
30
62
|
splitSegment(segment, offset) {
|
|
31
63
|
if (!segment) {
|
|
32
64
|
let empty = this.createTextSegment('');
|
|
@@ -101,14 +133,14 @@ class $bb130d0e51bd3001$export$f3decd0c2cd2fe2e {
|
|
|
101
133
|
]);
|
|
102
134
|
$bb130d0e51bd3001$var$appendSegments(newSegments, this.segments.slice(end.index + 1));
|
|
103
135
|
let segments = this.createFieldValue(newSegments);
|
|
104
|
-
segments.
|
|
136
|
+
segments.selectedRange = new $bb130d0e51bd3001$export$939a711fc6327372(caret);
|
|
105
137
|
segments.isCoalescing = coalesce;
|
|
106
138
|
if (this.isCoalescing && coalesce && this.previous) {
|
|
107
139
|
segments.previous = this.previous;
|
|
108
140
|
segments.previous.next = segments;
|
|
109
141
|
} else {
|
|
110
142
|
segments.previous = this;
|
|
111
|
-
this.
|
|
143
|
+
this.selectedRange = new $bb130d0e51bd3001$export$939a711fc6327372(start, end);
|
|
112
144
|
this.next = segments;
|
|
113
145
|
}
|
|
114
146
|
return segments;
|
|
@@ -175,14 +207,13 @@ class $bb130d0e51bd3001$export$f3decd0c2cd2fe2e {
|
|
|
175
207
|
/** Delete text at a position using a segmenter. */ delete(position, segmenter, direction, coalesce = true) {
|
|
176
208
|
let boundary = this.findBoundaryWithSegmenter(position, segmenter, direction);
|
|
177
209
|
if (boundary) return this.replaceRange(direction === -1 ? boundary : position, direction === -1 ? position : boundary, '', coalesce);
|
|
178
|
-
this.
|
|
179
|
-
return this;
|
|
210
|
+
return this.withSelectedRange(new $bb130d0e51bd3001$export$939a711fc6327372(position));
|
|
180
211
|
}
|
|
181
212
|
/** Delete text to the next or previous line break. */ deleteLine(position, direction, coalesce = true) {
|
|
182
213
|
if (this.segments.length === 0) return this;
|
|
183
214
|
let boundary = this.findLineBoundary(position, direction);
|
|
184
215
|
if (boundary) return this.replaceRange(direction === -1 ? boundary : position, direction === -1 ? position : boundary, '', coalesce);
|
|
185
|
-
return this;
|
|
216
|
+
return this.withSelectedRange(new $bb130d0e51bd3001$export$939a711fc6327372(position));
|
|
186
217
|
}
|
|
187
218
|
/** Create a new list containing a subset of the segments. */ slice(start, end) {
|
|
188
219
|
start = this.clampPosition(start);
|
|
@@ -225,23 +256,20 @@ class $bb130d0e51bd3001$export$f3decd0c2cd2fe2e {
|
|
|
225
256
|
this.isCoalescing = false;
|
|
226
257
|
}
|
|
227
258
|
/** Create a new list with the given segments. */ constructor(tokens, options){
|
|
228
|
-
/** The caret position. */ this.caretPosition = {
|
|
229
|
-
index: 0,
|
|
230
|
-
offset: 0
|
|
231
|
-
};
|
|
232
259
|
// Linked list representing the undo/redo history.
|
|
233
260
|
this.previous = null;
|
|
234
261
|
this.next = null;
|
|
235
262
|
this.isCoalescing = true;
|
|
236
263
|
this.segments = tokens;
|
|
237
|
-
var
|
|
238
|
-
this.
|
|
264
|
+
var _options_selectedRange;
|
|
265
|
+
this.selectedRange = (_options_selectedRange = options === null || options === void 0 ? void 0 : options.selectedRange) !== null && _options_selectedRange !== void 0 ? _options_selectedRange : new $bb130d0e51bd3001$export$939a711fc6327372({
|
|
239
266
|
index: 0,
|
|
240
267
|
offset: 0
|
|
241
|
-
};
|
|
268
|
+
});
|
|
242
269
|
}
|
|
243
270
|
}
|
|
244
271
|
$bb130d0e51bd3001$export$f3decd0c2cd2fe2e.Direction = $bb130d0e51bd3001$var$Direction;
|
|
272
|
+
$bb130d0e51bd3001$export$f3decd0c2cd2fe2e.SelectedRange = $bb130d0e51bd3001$export$939a711fc6327372;
|
|
245
273
|
function $bb130d0e51bd3001$var$findInText(text, search, direction, fromOffset) {
|
|
246
274
|
var _matches_at;
|
|
247
275
|
if (typeof search === 'string') {
|
|
@@ -281,5 +309,5 @@ function $bb130d0e51bd3001$var$appendSegments(segments, insert, tokenize) {
|
|
|
281
309
|
}
|
|
282
310
|
|
|
283
311
|
|
|
284
|
-
export {$bb130d0e51bd3001$export$f3decd0c2cd2fe2e as TokenFieldValue};
|
|
312
|
+
export {$bb130d0e51bd3001$export$939a711fc6327372 as SelectedRange, $bb130d0e51bd3001$export$f3decd0c2cd2fe2e as TokenFieldValue};
|
|
285
313
|
//# sourceMappingURL=TokenFieldValue.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"mappings":"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","sources":["packages/react-stately/src/tokenfield/TokenFieldValue.ts"],"sourcesContent":["/*\n * Copyright 2026 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nexport type TokenFieldSegment<T = any> = TextSegment | TokenSegment<T>;\n\nexport interface TextSegment {\n type: 'text';\n text: string;\n}\n\nexport interface TokenSegment<T = any> {\n type: 'token';\n text: string;\n /** An arbitrary value associated with the token. */\n value?: T;\n}\n\nexport interface Position {\n /** Index of the segment in the list. */\n index: number;\n /** Text offset within the segment in UTF-16 code units. */\n offset: number;\n}\n\nenum Direction {\n Forward = 1,\n Backward = -1\n}\n\nexport interface TokenFieldValueOptions {\n caretPosition?: Position | null;\n}\n\n/**\n * A list of segments containing editable text and non-editable tokens.\n */\nexport class TokenFieldValue<T = any> {\n static readonly Direction = Direction;\n\n /** The text and token segments in the list. */\n readonly segments: readonly TokenFieldSegment<T>[];\n /** The caret position. */\n caretPosition: Position = {index: 0, offset: 0};\n // Linked list representing the undo/redo history.\n private previous: this | null = null;\n private next: this | null = null;\n private isCoalescing = true;\n\n /** Create a new list with the given segments. */\n constructor(tokens: readonly TokenFieldSegment<T>[], options?: TokenFieldValueOptions) {\n this.segments = tokens;\n this.caretPosition = options?.caretPosition ?? {index: 0, offset: 0};\n }\n\n protected createFieldValue(segments: readonly TokenFieldSegment<T>[]): this {\n const Constructor = this.constructor as new (\n segments: readonly TokenFieldSegment<T>[],\n options?: TokenFieldValueOptions\n ) => this;\n return new Constructor(segments);\n }\n\n /** Create a new list with the caret position set to the given position. */\n withCaretPosition(caretPosition: Position): this {\n if (\n this.caretPosition.index === caretPosition.index &&\n this.caretPosition.offset === caretPosition.offset\n ) {\n return this;\n }\n\n let result = this.createFieldValue(this.segments);\n result.caretPosition = caretPosition;\n result.previous = this.previous;\n result.next = this.next;\n result.isCoalescing = this.isCoalescing;\n return result;\n }\n\n private splitSegment(\n segment: TokenFieldSegment | undefined,\n offset: number\n ): [TokenFieldSegment | null, TokenFieldSegment | null] {\n if (!segment) {\n let empty = this.createTextSegment('');\n return [offset > 0 ? empty : null, offset > 0 ? null : empty];\n }\n\n if (segment.type === 'token') {\n return [offset > 0 ? {...segment} : null, offset > 0 ? null : {...segment}];\n }\n\n return [\n offset > 0 ? {type: 'text', text: segment.text.slice(0, offset)} : null,\n offset < segment.text.length ? this.createTextSegment(segment.text.slice(offset)) : null\n ];\n }\n\n private createTextSegment(text: string): TextSegment {\n return {type: 'text', text};\n }\n\n protected tokenize(text: string): TokenFieldSegment<T>[] {\n return [this.createTextSegment(text)];\n }\n\n private clampPosition(position: Position): Position {\n if (this.segments.length > 0 && position.index >= this.segments.length) {\n return {\n index: this.segments.length - 1,\n offset: this.segments[this.segments.length - 1].text.length\n };\n }\n\n if (position.index < 0) {\n return {index: 0, offset: 0};\n }\n return position;\n }\n\n /** Replace the text between two positions with new text. */\n replaceRange(start: Position, end: Position, text: string, coalesce = true): this {\n return this.replaceRangeWithSegments(\n start,\n end,\n text.length > 0 ? [this.createTextSegment(text)] : [],\n coalesce\n );\n }\n\n /** Replace the text between two positions with new segments. */\n replaceRangeWithSegments(\n start: Position,\n end: Position,\n insert: TokenFieldSegment<T>[],\n coalesce = true\n ): this {\n start = this.clampPosition(start);\n end = this.clampPosition(end);\n let startSegment = this.segments[start.index];\n let endSegment = this.segments[end.index];\n let [startSplit] = this.splitSegment(startSegment, start.offset);\n let [, endSplit] = this.splitSegment(endSegment, end.offset);\n\n let newSegments = this.segments.slice(0, start.index);\n if (startSplit) {\n appendSegments(newSegments, [startSplit]);\n }\n\n if (insert.length) {\n appendSegments(newSegments, insert, text => this.tokenize(text));\n }\n\n let lastSegment = newSegments[newSegments.length - 1];\n let lastIsText = lastSegment && lastSegment.type === 'text';\n let caret = {\n index: lastIsText ? newSegments.length - 1 : newSegments.length,\n offset: lastIsText ? lastSegment.text.length : 0\n };\n\n if (endSplit) {\n appendSegments(newSegments, [endSplit]);\n }\n\n appendSegments(newSegments, this.segments.slice(end.index + 1));\n\n let segments = this.createFieldValue(newSegments);\n segments.caretPosition = caret;\n segments.isCoalescing = coalesce;\n if (this.isCoalescing && coalesce && this.previous) {\n segments.previous = this.previous;\n segments.previous.next = segments;\n } else {\n segments.previous = this;\n this.caretPosition = end;\n this.next = segments;\n }\n return segments;\n }\n\n /** Find the boundary before or after a position using an Intl.Segmenter. */\n findBoundaryWithSegmenter(\n position: Position,\n segmenter: Intl.Segmenter,\n direction: Direction\n ): Position | null {\n position = this.clampPosition(position);\n for (let i = position.index; i >= 0 && i < this.segments.length; i += direction) {\n let segment = this.segments[i];\n switch (segment.type) {\n case 'token':\n if (\n i !== position.index ||\n (direction === Direction.Backward ? position.offset > 0 : position.offset === 0)\n ) {\n let index = i + direction;\n return {\n index: index >= 0 ? index : 0,\n offset:\n direction === Direction.Backward && index >= 0\n ? this.segments[index].text.length\n : 0\n };\n }\n continue;\n case 'text': {\n let offset = direction === Direction.Backward ? segment.text.length : 0;\n if (i === position.index) {\n offset = position.offset;\n }\n if (direction === Direction.Backward) {\n offset--;\n }\n if (offset < 0 || offset >= segment.text.length) {\n continue;\n }\n\n let part = segmenter.segment(segment.text).containing(offset);\n while (part && part.isWordLike === false) {\n offset += direction;\n part = segmenter.segment(segment.text).containing(offset);\n }\n\n if (part) {\n return {\n index: i,\n offset:\n direction === Direction.Backward ? part.index : part.index + part.segment.length\n };\n }\n continue;\n }\n }\n }\n\n return null;\n }\n\n /** Find a line boundary before or after a position. */\n findLineBoundary(position: Position, direction: Direction): Position | null {\n let res = this.findText(position, direction, '\\n');\n if (res) {\n return res;\n }\n return direction === Direction.Backward\n ? {index: 0, offset: 0}\n : {\n index: this.segments.length - 1,\n offset: this.segments[this.segments.length - 1].text.length\n };\n }\n\n /** Find a string or regular expression match before or after a position. */\n findText(position: Position, direction: Direction, search: string | RegExp): Position | null {\n if (this.segments.length === 0) {\n return null;\n }\n\n for (let i = position.index; i >= 0 && i < this.segments.length; i += direction) {\n let segment = this.segments[i];\n if (segment.type !== 'text') {\n continue;\n }\n let offset = findInText(\n segment.text,\n search,\n direction,\n i === position.index ? position.offset : undefined\n );\n if (offset >= 0) {\n return {\n index: i,\n offset: offset\n };\n }\n }\n\n return null;\n }\n\n /** Delete text at a position using a segmenter. */\n delete(\n position: Position,\n segmenter: Intl.Segmenter,\n direction: Direction,\n coalesce = true\n ): this {\n let boundary = this.findBoundaryWithSegmenter(position, segmenter, direction);\n if (boundary) {\n return this.replaceRange(\n direction === Direction.Backward ? boundary : position,\n direction === Direction.Backward ? position : boundary,\n '',\n coalesce\n );\n }\n\n this.caretPosition = position;\n return this;\n }\n\n /** Delete text to the next or previous line break. */\n deleteLine(position: Position, direction: Direction, coalesce = true): this {\n if (this.segments.length === 0) {\n return this;\n }\n\n let boundary = this.findLineBoundary(position, direction);\n if (boundary) {\n return this.replaceRange(\n direction === Direction.Backward ? boundary : position,\n direction === Direction.Backward ? position : boundary,\n '',\n coalesce\n );\n }\n\n return this;\n }\n\n /** Create a new list containing a subset of the segments. */\n slice(start: Position, end: Position): this {\n start = this.clampPosition(start);\n end = this.clampPosition(end);\n if (start.index === end.index && start.offset === end.offset) {\n return this.createFieldValue([]);\n }\n if (start.index === end.index) {\n let segment = this.segments[start.index];\n if (segment.type === 'text') {\n return this.createFieldValue([\n {type: 'text', text: segment.text.slice(start.offset, end.offset)}\n ]);\n }\n return this.createFieldValue([segment]);\n }\n let startSegment = this.segments[start.index];\n let endSegment = this.segments[end.index];\n let [, startSplit] = this.splitSegment(startSegment, start.offset);\n let [endSplit] = this.splitSegment(endSegment, end.offset);\n\n let result: TokenFieldSegment<T>[] = [];\n if (startSplit) {\n result.push(startSplit);\n }\n result.push(...this.segments.slice(start.index + 1, end.index));\n if (endSplit) {\n result.push(endSplit);\n }\n return this.createFieldValue(result);\n }\n\n /** Convert the list to a string. */\n toString(): string {\n return this.segments.map(seg => seg.text).join('');\n }\n\n /** Returns the previous list in the undo history. */\n undo(): this {\n return this.previous ?? this;\n }\n\n /** Returns the next list in the redo history. */\n redo(): this {\n return this.next ?? this;\n }\n\n /** End coalescing undo/redo history. */\n endCoalescing(): void {\n this.isCoalescing = false;\n }\n}\n\nfunction findInText(\n text: string,\n search: string | RegExp,\n direction: Direction,\n fromOffset?: number\n): number {\n if (typeof search === 'string') {\n if (direction === Direction.Backward) {\n return text.lastIndexOf(search, fromOffset !== undefined ? fromOffset - 1 : text.length - 1);\n }\n return text.indexOf(search, fromOffset ?? 0);\n }\n\n if (direction === Direction.Forward) {\n let start = fromOffset ?? 0;\n let index = text.slice(start).search(search);\n return index >= 0 ? start + index : -1;\n }\n\n let limit = fromOffset !== undefined ? fromOffset : text.length;\n if (limit < 0) {\n return -1;\n }\n\n let re = search.flags.includes('g') ? search : new RegExp(search.source, search.flags + 'g');\n let matches = Array.from(text.slice(0, limit).matchAll(re));\n return matches.at(-1)?.index ?? -1;\n}\n\nfunction appendSegments(\n segments: TokenFieldSegment[],\n insert: TokenFieldSegment[],\n tokenize?: (text: string) => TokenFieldSegment[]\n): TokenFieldSegment[] {\n for (let segment of insert) {\n if (segment.type === 'text' && segment.text.length === 0) {\n continue;\n }\n\n let last = segments[segments.length - 1];\n if (last && last.type === 'text' && segment.type === 'text') {\n if (tokenize) {\n let tokenized = tokenize(last.text + segment.text);\n segments.splice(segments.length - 1, 1, ...tokenized);\n } else {\n segments[segments.length - 1] = {type: 'text', text: last.text + segment.text};\n }\n } else if (tokenize && segment.type === 'text') {\n let tokenized = tokenize(segment.text);\n segments.push(...tokenized);\n } else {\n segments.push(segment);\n }\n }\n return segments;\n}\n"],"names":[],"version":3,"file":"TokenFieldValue.js.map"}
|
|
1
|
+
{"mappings":"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","sources":["packages/react-stately/src/tokenfield/TokenFieldValue.ts"],"sourcesContent":["/*\n * Copyright 2026 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nexport type TokenFieldSegment<T = any> = TextSegment | TokenSegment<T>;\n\nexport interface TextSegment {\n type: 'text';\n text: string;\n}\n\nexport interface TokenSegment<T = any> {\n type: 'token';\n text: string;\n /** An arbitrary value associated with the token. */\n value?: T;\n}\n\nexport interface Position {\n /** Index of the segment in the list. */\n index: number;\n /** Text offset within the segment in UTF-16 code units. */\n offset: number;\n}\n\n/** Represents a text selection in a TokenField. */\nexport class SelectedRange {\n /** The anchor position. */\n anchor: Position;\n /** The current (i.e. caret) position. */\n current: Position;\n\n /**\n * Creates a new selection range. If only a single position is provided, the selection is\n * collapsed.\n */\n constructor(anchor: Position, current: Position = anchor) {\n this.anchor = anchor;\n this.current = current;\n }\n\n /** Whether the selection is collapsed to a single caret position. */\n get isCollapsed() {\n return this.anchor.index === this.current.index && this.anchor.offset === this.current.offset;\n }\n\n /** The side of the selection closest to the start of the value. */\n get start() {\n return compare(this.anchor, this.current) < 0 ? this.anchor : this.current;\n }\n\n /** The side of the selection closest to the end of the value. */\n get end() {\n return compare(this.anchor, this.current) < 0 ? this.current : this.anchor;\n }\n\n /** Returns whether this selection is equal to another. */\n isEqual(other: SelectedRange) {\n if (this === other) {\n return true;\n }\n return (\n this.anchor.index === other.anchor.index &&\n this.anchor.offset === other.anchor.offset &&\n this.current.index === other.current.index &&\n this.current.offset === other.current.offset\n );\n }\n}\n\nfunction compare(a: Position, b: Position) {\n if (a.index === b.index) {\n return a.offset - b.offset;\n }\n\n return a.index - b.index;\n}\n\nenum Direction {\n Forward = 1,\n Backward = -1\n}\n\nexport interface TokenFieldValueOptions {\n selectedRange?: SelectedRange | null;\n}\n\n/**\n * A list of segments containing editable text and non-editable tokens.\n */\nexport class TokenFieldValue<T = any> {\n static readonly Direction = Direction;\n static readonly SelectedRange = SelectedRange;\n\n /** The text and token segments in the list. */\n readonly segments: readonly TokenFieldSegment<T>[];\n /** The selected range. */\n selectedRange: SelectedRange;\n // Linked list representing the undo/redo history.\n private previous: this | null = null;\n private next: this | null = null;\n private isCoalescing = true;\n\n /** Create a new list with the given segments. */\n constructor(tokens: readonly TokenFieldSegment<T>[], options?: TokenFieldValueOptions) {\n this.segments = tokens;\n this.selectedRange = options?.selectedRange ?? new SelectedRange({index: 0, offset: 0});\n }\n\n protected createFieldValue(segments: readonly TokenFieldSegment<T>[]): this {\n const Constructor = this.constructor as new (\n segments: readonly TokenFieldSegment<T>[],\n options?: TokenFieldValueOptions\n ) => this;\n return new Constructor(segments);\n }\n\n get caretPosition(): Position {\n return this.selectedRange.current;\n }\n\n /** Create a new list with the caret position set to the given position. */\n withSelectedRange(selectedRange: SelectedRange): this {\n if (this.selectedRange.isEqual(selectedRange)) {\n return this;\n }\n\n let result = this.createFieldValue(this.segments);\n result.selectedRange = selectedRange;\n result.previous = this.previous;\n result.next = this.next;\n result.isCoalescing = this.isCoalescing;\n return result;\n }\n\n withCaretPosition(position: Position): this {\n return this.withSelectedRange(new SelectedRange(position));\n }\n\n private splitSegment(\n segment: TokenFieldSegment | undefined,\n offset: number\n ): [TokenFieldSegment | null, TokenFieldSegment | null] {\n if (!segment) {\n let empty = this.createTextSegment('');\n return [offset > 0 ? empty : null, offset > 0 ? null : empty];\n }\n\n if (segment.type === 'token') {\n return [offset > 0 ? {...segment} : null, offset > 0 ? null : {...segment}];\n }\n\n return [\n offset > 0 ? {type: 'text', text: segment.text.slice(0, offset)} : null,\n offset < segment.text.length ? this.createTextSegment(segment.text.slice(offset)) : null\n ];\n }\n\n private createTextSegment(text: string): TextSegment {\n return {type: 'text', text};\n }\n\n protected tokenize(text: string): TokenFieldSegment<T>[] {\n return [this.createTextSegment(text)];\n }\n\n private clampPosition(position: Position): Position {\n if (this.segments.length > 0 && position.index >= this.segments.length) {\n return {\n index: this.segments.length - 1,\n offset: this.segments[this.segments.length - 1].text.length\n };\n }\n\n if (position.index < 0) {\n return {index: 0, offset: 0};\n }\n return position;\n }\n\n /** Replace the text between two positions with new text. */\n replaceRange(start: Position, end: Position, text: string, coalesce = true): this {\n return this.replaceRangeWithSegments(\n start,\n end,\n text.length > 0 ? [this.createTextSegment(text)] : [],\n coalesce\n );\n }\n\n /** Replace the text between two positions with new segments. */\n replaceRangeWithSegments(\n start: Position,\n end: Position,\n insert: TokenFieldSegment<T>[],\n coalesce = true\n ): this {\n start = this.clampPosition(start);\n end = this.clampPosition(end);\n let startSegment = this.segments[start.index];\n let endSegment = this.segments[end.index];\n let [startSplit] = this.splitSegment(startSegment, start.offset);\n let [, endSplit] = this.splitSegment(endSegment, end.offset);\n\n let newSegments = this.segments.slice(0, start.index);\n if (startSplit) {\n appendSegments(newSegments, [startSplit]);\n }\n\n if (insert.length) {\n appendSegments(newSegments, insert, text => this.tokenize(text));\n }\n\n let lastSegment = newSegments[newSegments.length - 1];\n let lastIsText = lastSegment && lastSegment.type === 'text';\n let caret = {\n index: lastIsText ? newSegments.length - 1 : newSegments.length,\n offset: lastIsText ? lastSegment.text.length : 0\n };\n\n if (endSplit) {\n appendSegments(newSegments, [endSplit]);\n }\n\n appendSegments(newSegments, this.segments.slice(end.index + 1));\n\n let segments = this.createFieldValue(newSegments);\n segments.selectedRange = new SelectedRange(caret);\n segments.isCoalescing = coalesce;\n if (this.isCoalescing && coalesce && this.previous) {\n segments.previous = this.previous;\n segments.previous.next = segments;\n } else {\n segments.previous = this;\n this.selectedRange = new SelectedRange(start, end);\n this.next = segments;\n }\n return segments;\n }\n\n /** Find the boundary before or after a position using an Intl.Segmenter. */\n findBoundaryWithSegmenter(\n position: Position,\n segmenter: Intl.Segmenter,\n direction: Direction\n ): Position | null {\n position = this.clampPosition(position);\n for (let i = position.index; i >= 0 && i < this.segments.length; i += direction) {\n let segment = this.segments[i];\n switch (segment.type) {\n case 'token':\n if (\n i !== position.index ||\n (direction === Direction.Backward ? position.offset > 0 : position.offset === 0)\n ) {\n let index = i + direction;\n return {\n index: index >= 0 ? index : 0,\n offset:\n direction === Direction.Backward && index >= 0\n ? this.segments[index].text.length\n : 0\n };\n }\n continue;\n case 'text': {\n let offset = direction === Direction.Backward ? segment.text.length : 0;\n if (i === position.index) {\n offset = position.offset;\n }\n if (direction === Direction.Backward) {\n offset--;\n }\n if (offset < 0 || offset >= segment.text.length) {\n continue;\n }\n\n let part = segmenter.segment(segment.text).containing(offset);\n while (part && part.isWordLike === false) {\n offset += direction;\n part = segmenter.segment(segment.text).containing(offset);\n }\n\n if (part) {\n return {\n index: i,\n offset:\n direction === Direction.Backward ? part.index : part.index + part.segment.length\n };\n }\n continue;\n }\n }\n }\n\n return null;\n }\n\n /** Find a line boundary before or after a position. */\n findLineBoundary(position: Position, direction: Direction): Position | null {\n let res = this.findText(position, direction, '\\n');\n if (res) {\n return res;\n }\n return direction === Direction.Backward\n ? {index: 0, offset: 0}\n : {\n index: this.segments.length - 1,\n offset: this.segments[this.segments.length - 1].text.length\n };\n }\n\n /** Find a string or regular expression match before or after a position. */\n findText(position: Position, direction: Direction, search: string | RegExp): Position | null {\n if (this.segments.length === 0) {\n return null;\n }\n\n for (let i = position.index; i >= 0 && i < this.segments.length; i += direction) {\n let segment = this.segments[i];\n if (segment.type !== 'text') {\n continue;\n }\n let offset = findInText(\n segment.text,\n search,\n direction,\n i === position.index ? position.offset : undefined\n );\n if (offset >= 0) {\n return {\n index: i,\n offset: offset\n };\n }\n }\n\n return null;\n }\n\n /** Delete text at a position using a segmenter. */\n delete(\n position: Position,\n segmenter: Intl.Segmenter,\n direction: Direction,\n coalesce = true\n ): this {\n let boundary = this.findBoundaryWithSegmenter(position, segmenter, direction);\n if (boundary) {\n return this.replaceRange(\n direction === Direction.Backward ? boundary : position,\n direction === Direction.Backward ? position : boundary,\n '',\n coalesce\n );\n }\n\n return this.withSelectedRange(new SelectedRange(position));\n }\n\n /** Delete text to the next or previous line break. */\n deleteLine(position: Position, direction: Direction, coalesce = true): this {\n if (this.segments.length === 0) {\n return this;\n }\n\n let boundary = this.findLineBoundary(position, direction);\n if (boundary) {\n return this.replaceRange(\n direction === Direction.Backward ? boundary : position,\n direction === Direction.Backward ? position : boundary,\n '',\n coalesce\n );\n }\n\n return this.withSelectedRange(new SelectedRange(position));\n }\n\n /** Create a new list containing a subset of the segments. */\n slice(start: Position, end: Position): this {\n start = this.clampPosition(start);\n end = this.clampPosition(end);\n if (start.index === end.index && start.offset === end.offset) {\n return this.createFieldValue([]);\n }\n if (start.index === end.index) {\n let segment = this.segments[start.index];\n if (segment.type === 'text') {\n return this.createFieldValue([\n {type: 'text', text: segment.text.slice(start.offset, end.offset)}\n ]);\n }\n return this.createFieldValue([segment]);\n }\n let startSegment = this.segments[start.index];\n let endSegment = this.segments[end.index];\n let [, startSplit] = this.splitSegment(startSegment, start.offset);\n let [endSplit] = this.splitSegment(endSegment, end.offset);\n\n let result: TokenFieldSegment<T>[] = [];\n if (startSplit) {\n result.push(startSplit);\n }\n result.push(...this.segments.slice(start.index + 1, end.index));\n if (endSplit) {\n result.push(endSplit);\n }\n return this.createFieldValue(result);\n }\n\n /** Convert the list to a string. */\n toString(): string {\n return this.segments.map(seg => seg.text).join('');\n }\n\n /** Returns the previous list in the undo history. */\n undo(): this {\n return this.previous ?? this;\n }\n\n /** Returns the next list in the redo history. */\n redo(): this {\n return this.next ?? this;\n }\n\n /** End coalescing undo/redo history. */\n endCoalescing(): void {\n this.isCoalescing = false;\n }\n}\n\nfunction findInText(\n text: string,\n search: string | RegExp,\n direction: Direction,\n fromOffset?: number\n): number {\n if (typeof search === 'string') {\n if (direction === Direction.Backward) {\n return text.lastIndexOf(search, fromOffset !== undefined ? fromOffset - 1 : text.length - 1);\n }\n return text.indexOf(search, fromOffset ?? 0);\n }\n\n if (direction === Direction.Forward) {\n let start = fromOffset ?? 0;\n let index = text.slice(start).search(search);\n return index >= 0 ? start + index : -1;\n }\n\n let limit = fromOffset !== undefined ? fromOffset : text.length;\n if (limit < 0) {\n return -1;\n }\n\n let re = search.flags.includes('g') ? search : new RegExp(search.source, search.flags + 'g');\n let matches = Array.from(text.slice(0, limit).matchAll(re));\n return matches.at(-1)?.index ?? -1;\n}\n\nfunction appendSegments(\n segments: TokenFieldSegment[],\n insert: TokenFieldSegment[],\n tokenize?: (text: string) => TokenFieldSegment[]\n): TokenFieldSegment[] {\n for (let segment of insert) {\n if (segment.type === 'text' && segment.text.length === 0) {\n continue;\n }\n\n let last = segments[segments.length - 1];\n if (last && last.type === 'text' && segment.type === 'text') {\n if (tokenize) {\n let tokenized = tokenize(last.text + segment.text);\n segments.splice(segments.length - 1, 1, ...tokenized);\n } else {\n segments[segments.length - 1] = {type: 'text', text: last.text + segment.text};\n }\n } else if (tokenize && segment.type === 'text') {\n let tokenized = tokenize(segment.text);\n segments.push(...tokenized);\n } else {\n segments.push(segment);\n }\n }\n return segments;\n}\n"],"names":[],"version":3,"file":"TokenFieldValue.js.map"}
|
|
@@ -8,7 +8,33 @@
|
|
|
8
8
|
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
|
|
9
9
|
* OF ANY KIND, either express or implied. See the License for the specific language
|
|
10
10
|
* governing permissions and limitations under the License.
|
|
11
|
-
*/
|
|
11
|
+
*/ class $4a46f1c4231e5dde$export$939a711fc6327372 {
|
|
12
|
+
/**
|
|
13
|
+
* Creates a new selection range. If only a single position is provided, the selection is
|
|
14
|
+
* collapsed.
|
|
15
|
+
*/ constructor(anchor, current = anchor){
|
|
16
|
+
this.anchor = anchor;
|
|
17
|
+
this.current = current;
|
|
18
|
+
}
|
|
19
|
+
/** Whether the selection is collapsed to a single caret position. */ get isCollapsed() {
|
|
20
|
+
return this.anchor.index === this.current.index && this.anchor.offset === this.current.offset;
|
|
21
|
+
}
|
|
22
|
+
/** The side of the selection closest to the start of the value. */ get start() {
|
|
23
|
+
return $4a46f1c4231e5dde$var$compare(this.anchor, this.current) < 0 ? this.anchor : this.current;
|
|
24
|
+
}
|
|
25
|
+
/** The side of the selection closest to the end of the value. */ get end() {
|
|
26
|
+
return $4a46f1c4231e5dde$var$compare(this.anchor, this.current) < 0 ? this.current : this.anchor;
|
|
27
|
+
}
|
|
28
|
+
/** Returns whether this selection is equal to another. */ isEqual(other) {
|
|
29
|
+
if (this === other) return true;
|
|
30
|
+
return this.anchor.index === other.anchor.index && this.anchor.offset === other.anchor.offset && this.current.index === other.current.index && this.current.offset === other.current.offset;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
function $4a46f1c4231e5dde$var$compare(a, b) {
|
|
34
|
+
if (a.index === b.index) return a.offset - b.offset;
|
|
35
|
+
return a.index - b.index;
|
|
36
|
+
}
|
|
37
|
+
var $4a46f1c4231e5dde$var$Direction = /*#__PURE__*/ function(Direction) {
|
|
12
38
|
Direction[Direction["Forward"] = 1] = "Forward";
|
|
13
39
|
Direction[Direction["Backward"] = -1] = "Backward";
|
|
14
40
|
return Direction;
|
|
@@ -17,34 +43,39 @@ class $4a46f1c4231e5dde$export$f3decd0c2cd2fe2e {
|
|
|
17
43
|
static{
|
|
18
44
|
this.Direction = $4a46f1c4231e5dde$var$Direction;
|
|
19
45
|
}
|
|
46
|
+
static{
|
|
47
|
+
this.SelectedRange = $4a46f1c4231e5dde$export$939a711fc6327372;
|
|
48
|
+
}
|
|
20
49
|
/** Create a new list with the given segments. */ constructor(tokens, options){
|
|
21
|
-
/** The caret position. */ this.caretPosition = {
|
|
22
|
-
index: 0,
|
|
23
|
-
offset: 0
|
|
24
|
-
};
|
|
25
50
|
// Linked list representing the undo/redo history.
|
|
26
51
|
this.previous = null;
|
|
27
52
|
this.next = null;
|
|
28
53
|
this.isCoalescing = true;
|
|
29
54
|
this.segments = tokens;
|
|
30
|
-
this.
|
|
55
|
+
this.selectedRange = options?.selectedRange ?? new $4a46f1c4231e5dde$export$939a711fc6327372({
|
|
31
56
|
index: 0,
|
|
32
57
|
offset: 0
|
|
33
|
-
};
|
|
58
|
+
});
|
|
34
59
|
}
|
|
35
60
|
createFieldValue(segments) {
|
|
36
61
|
const Constructor = this.constructor;
|
|
37
62
|
return new Constructor(segments);
|
|
38
63
|
}
|
|
39
|
-
|
|
40
|
-
|
|
64
|
+
get caretPosition() {
|
|
65
|
+
return this.selectedRange.current;
|
|
66
|
+
}
|
|
67
|
+
/** Create a new list with the caret position set to the given position. */ withSelectedRange(selectedRange) {
|
|
68
|
+
if (this.selectedRange.isEqual(selectedRange)) return this;
|
|
41
69
|
let result = this.createFieldValue(this.segments);
|
|
42
|
-
result.
|
|
70
|
+
result.selectedRange = selectedRange;
|
|
43
71
|
result.previous = this.previous;
|
|
44
72
|
result.next = this.next;
|
|
45
73
|
result.isCoalescing = this.isCoalescing;
|
|
46
74
|
return result;
|
|
47
75
|
}
|
|
76
|
+
withCaretPosition(position) {
|
|
77
|
+
return this.withSelectedRange(new $4a46f1c4231e5dde$export$939a711fc6327372(position));
|
|
78
|
+
}
|
|
48
79
|
splitSegment(segment, offset) {
|
|
49
80
|
if (!segment) {
|
|
50
81
|
let empty = this.createTextSegment('');
|
|
@@ -119,14 +150,14 @@ class $4a46f1c4231e5dde$export$f3decd0c2cd2fe2e {
|
|
|
119
150
|
]);
|
|
120
151
|
$4a46f1c4231e5dde$var$appendSegments(newSegments, this.segments.slice(end.index + 1));
|
|
121
152
|
let segments = this.createFieldValue(newSegments);
|
|
122
|
-
segments.
|
|
153
|
+
segments.selectedRange = new $4a46f1c4231e5dde$export$939a711fc6327372(caret);
|
|
123
154
|
segments.isCoalescing = coalesce;
|
|
124
155
|
if (this.isCoalescing && coalesce && this.previous) {
|
|
125
156
|
segments.previous = this.previous;
|
|
126
157
|
segments.previous.next = segments;
|
|
127
158
|
} else {
|
|
128
159
|
segments.previous = this;
|
|
129
|
-
this.
|
|
160
|
+
this.selectedRange = new $4a46f1c4231e5dde$export$939a711fc6327372(start, end);
|
|
130
161
|
this.next = segments;
|
|
131
162
|
}
|
|
132
163
|
return segments;
|
|
@@ -193,14 +224,13 @@ class $4a46f1c4231e5dde$export$f3decd0c2cd2fe2e {
|
|
|
193
224
|
/** Delete text at a position using a segmenter. */ delete(position, segmenter, direction, coalesce = true) {
|
|
194
225
|
let boundary = this.findBoundaryWithSegmenter(position, segmenter, direction);
|
|
195
226
|
if (boundary) return this.replaceRange(direction === -1 ? boundary : position, direction === -1 ? position : boundary, '', coalesce);
|
|
196
|
-
this.
|
|
197
|
-
return this;
|
|
227
|
+
return this.withSelectedRange(new $4a46f1c4231e5dde$export$939a711fc6327372(position));
|
|
198
228
|
}
|
|
199
229
|
/** Delete text to the next or previous line break. */ deleteLine(position, direction, coalesce = true) {
|
|
200
230
|
if (this.segments.length === 0) return this;
|
|
201
231
|
let boundary = this.findLineBoundary(position, direction);
|
|
202
232
|
if (boundary) return this.replaceRange(direction === -1 ? boundary : position, direction === -1 ? position : boundary, '', coalesce);
|
|
203
|
-
return this;
|
|
233
|
+
return this.withSelectedRange(new $4a46f1c4231e5dde$export$939a711fc6327372(position));
|
|
204
234
|
}
|
|
205
235
|
/** Create a new list containing a subset of the segments. */ slice(start, end) {
|
|
206
236
|
start = this.clampPosition(start);
|
|
@@ -278,5 +308,5 @@ function $4a46f1c4231e5dde$var$appendSegments(segments, insert, tokenize) {
|
|
|
278
308
|
}
|
|
279
309
|
|
|
280
310
|
|
|
281
|
-
export {$4a46f1c4231e5dde$export$f3decd0c2cd2fe2e as TokenFieldValue};
|
|
311
|
+
export {$4a46f1c4231e5dde$export$939a711fc6327372 as SelectedRange, $4a46f1c4231e5dde$export$f3decd0c2cd2fe2e as TokenFieldValue};
|
|
282
312
|
//# sourceMappingURL=TokenFieldValue.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"mappings":"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","sources":["packages/react-stately/src/tokenfield/TokenFieldValue.ts"],"sourcesContent":["/*\n * Copyright 2026 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nexport type TokenFieldSegment<T = any> = TextSegment | TokenSegment<T>;\n\nexport interface TextSegment {\n type: 'text';\n text: string;\n}\n\nexport interface TokenSegment<T = any> {\n type: 'token';\n text: string;\n /** An arbitrary value associated with the token. */\n value?: T;\n}\n\nexport interface Position {\n /** Index of the segment in the list. */\n index: number;\n /** Text offset within the segment in UTF-16 code units. */\n offset: number;\n}\n\nenum Direction {\n Forward = 1,\n Backward = -1\n}\n\nexport interface TokenFieldValueOptions {\n caretPosition?: Position | null;\n}\n\n/**\n * A list of segments containing editable text and non-editable tokens.\n */\nexport class TokenFieldValue<T = any> {\n static readonly Direction = Direction;\n\n /** The text and token segments in the list. */\n readonly segments: readonly TokenFieldSegment<T>[];\n /** The caret position. */\n caretPosition: Position = {index: 0, offset: 0};\n // Linked list representing the undo/redo history.\n private previous: this | null = null;\n private next: this | null = null;\n private isCoalescing = true;\n\n /** Create a new list with the given segments. */\n constructor(tokens: readonly TokenFieldSegment<T>[], options?: TokenFieldValueOptions) {\n this.segments = tokens;\n this.caretPosition = options?.caretPosition ?? {index: 0, offset: 0};\n }\n\n protected createFieldValue(segments: readonly TokenFieldSegment<T>[]): this {\n const Constructor = this.constructor as new (\n segments: readonly TokenFieldSegment<T>[],\n options?: TokenFieldValueOptions\n ) => this;\n return new Constructor(segments);\n }\n\n /** Create a new list with the caret position set to the given position. */\n withCaretPosition(caretPosition: Position): this {\n if (\n this.caretPosition.index === caretPosition.index &&\n this.caretPosition.offset === caretPosition.offset\n ) {\n return this;\n }\n\n let result = this.createFieldValue(this.segments);\n result.caretPosition = caretPosition;\n result.previous = this.previous;\n result.next = this.next;\n result.isCoalescing = this.isCoalescing;\n return result;\n }\n\n private splitSegment(\n segment: TokenFieldSegment | undefined,\n offset: number\n ): [TokenFieldSegment | null, TokenFieldSegment | null] {\n if (!segment) {\n let empty = this.createTextSegment('');\n return [offset > 0 ? empty : null, offset > 0 ? null : empty];\n }\n\n if (segment.type === 'token') {\n return [offset > 0 ? {...segment} : null, offset > 0 ? null : {...segment}];\n }\n\n return [\n offset > 0 ? {type: 'text', text: segment.text.slice(0, offset)} : null,\n offset < segment.text.length ? this.createTextSegment(segment.text.slice(offset)) : null\n ];\n }\n\n private createTextSegment(text: string): TextSegment {\n return {type: 'text', text};\n }\n\n protected tokenize(text: string): TokenFieldSegment<T>[] {\n return [this.createTextSegment(text)];\n }\n\n private clampPosition(position: Position): Position {\n if (this.segments.length > 0 && position.index >= this.segments.length) {\n return {\n index: this.segments.length - 1,\n offset: this.segments[this.segments.length - 1].text.length\n };\n }\n\n if (position.index < 0) {\n return {index: 0, offset: 0};\n }\n return position;\n }\n\n /** Replace the text between two positions with new text. */\n replaceRange(start: Position, end: Position, text: string, coalesce = true): this {\n return this.replaceRangeWithSegments(\n start,\n end,\n text.length > 0 ? [this.createTextSegment(text)] : [],\n coalesce\n );\n }\n\n /** Replace the text between two positions with new segments. */\n replaceRangeWithSegments(\n start: Position,\n end: Position,\n insert: TokenFieldSegment<T>[],\n coalesce = true\n ): this {\n start = this.clampPosition(start);\n end = this.clampPosition(end);\n let startSegment = this.segments[start.index];\n let endSegment = this.segments[end.index];\n let [startSplit] = this.splitSegment(startSegment, start.offset);\n let [, endSplit] = this.splitSegment(endSegment, end.offset);\n\n let newSegments = this.segments.slice(0, start.index);\n if (startSplit) {\n appendSegments(newSegments, [startSplit]);\n }\n\n if (insert.length) {\n appendSegments(newSegments, insert, text => this.tokenize(text));\n }\n\n let lastSegment = newSegments[newSegments.length - 1];\n let lastIsText = lastSegment && lastSegment.type === 'text';\n let caret = {\n index: lastIsText ? newSegments.length - 1 : newSegments.length,\n offset: lastIsText ? lastSegment.text.length : 0\n };\n\n if (endSplit) {\n appendSegments(newSegments, [endSplit]);\n }\n\n appendSegments(newSegments, this.segments.slice(end.index + 1));\n\n let segments = this.createFieldValue(newSegments);\n segments.caretPosition = caret;\n segments.isCoalescing = coalesce;\n if (this.isCoalescing && coalesce && this.previous) {\n segments.previous = this.previous;\n segments.previous.next = segments;\n } else {\n segments.previous = this;\n this.caretPosition = end;\n this.next = segments;\n }\n return segments;\n }\n\n /** Find the boundary before or after a position using an Intl.Segmenter. */\n findBoundaryWithSegmenter(\n position: Position,\n segmenter: Intl.Segmenter,\n direction: Direction\n ): Position | null {\n position = this.clampPosition(position);\n for (let i = position.index; i >= 0 && i < this.segments.length; i += direction) {\n let segment = this.segments[i];\n switch (segment.type) {\n case 'token':\n if (\n i !== position.index ||\n (direction === Direction.Backward ? position.offset > 0 : position.offset === 0)\n ) {\n let index = i + direction;\n return {\n index: index >= 0 ? index : 0,\n offset:\n direction === Direction.Backward && index >= 0\n ? this.segments[index].text.length\n : 0\n };\n }\n continue;\n case 'text': {\n let offset = direction === Direction.Backward ? segment.text.length : 0;\n if (i === position.index) {\n offset = position.offset;\n }\n if (direction === Direction.Backward) {\n offset--;\n }\n if (offset < 0 || offset >= segment.text.length) {\n continue;\n }\n\n let part = segmenter.segment(segment.text).containing(offset);\n while (part && part.isWordLike === false) {\n offset += direction;\n part = segmenter.segment(segment.text).containing(offset);\n }\n\n if (part) {\n return {\n index: i,\n offset:\n direction === Direction.Backward ? part.index : part.index + part.segment.length\n };\n }\n continue;\n }\n }\n }\n\n return null;\n }\n\n /** Find a line boundary before or after a position. */\n findLineBoundary(position: Position, direction: Direction): Position | null {\n let res = this.findText(position, direction, '\\n');\n if (res) {\n return res;\n }\n return direction === Direction.Backward\n ? {index: 0, offset: 0}\n : {\n index: this.segments.length - 1,\n offset: this.segments[this.segments.length - 1].text.length\n };\n }\n\n /** Find a string or regular expression match before or after a position. */\n findText(position: Position, direction: Direction, search: string | RegExp): Position | null {\n if (this.segments.length === 0) {\n return null;\n }\n\n for (let i = position.index; i >= 0 && i < this.segments.length; i += direction) {\n let segment = this.segments[i];\n if (segment.type !== 'text') {\n continue;\n }\n let offset = findInText(\n segment.text,\n search,\n direction,\n i === position.index ? position.offset : undefined\n );\n if (offset >= 0) {\n return {\n index: i,\n offset: offset\n };\n }\n }\n\n return null;\n }\n\n /** Delete text at a position using a segmenter. */\n delete(\n position: Position,\n segmenter: Intl.Segmenter,\n direction: Direction,\n coalesce = true\n ): this {\n let boundary = this.findBoundaryWithSegmenter(position, segmenter, direction);\n if (boundary) {\n return this.replaceRange(\n direction === Direction.Backward ? boundary : position,\n direction === Direction.Backward ? position : boundary,\n '',\n coalesce\n );\n }\n\n this.caretPosition = position;\n return this;\n }\n\n /** Delete text to the next or previous line break. */\n deleteLine(position: Position, direction: Direction, coalesce = true): this {\n if (this.segments.length === 0) {\n return this;\n }\n\n let boundary = this.findLineBoundary(position, direction);\n if (boundary) {\n return this.replaceRange(\n direction === Direction.Backward ? boundary : position,\n direction === Direction.Backward ? position : boundary,\n '',\n coalesce\n );\n }\n\n return this;\n }\n\n /** Create a new list containing a subset of the segments. */\n slice(start: Position, end: Position): this {\n start = this.clampPosition(start);\n end = this.clampPosition(end);\n if (start.index === end.index && start.offset === end.offset) {\n return this.createFieldValue([]);\n }\n if (start.index === end.index) {\n let segment = this.segments[start.index];\n if (segment.type === 'text') {\n return this.createFieldValue([\n {type: 'text', text: segment.text.slice(start.offset, end.offset)}\n ]);\n }\n return this.createFieldValue([segment]);\n }\n let startSegment = this.segments[start.index];\n let endSegment = this.segments[end.index];\n let [, startSplit] = this.splitSegment(startSegment, start.offset);\n let [endSplit] = this.splitSegment(endSegment, end.offset);\n\n let result: TokenFieldSegment<T>[] = [];\n if (startSplit) {\n result.push(startSplit);\n }\n result.push(...this.segments.slice(start.index + 1, end.index));\n if (endSplit) {\n result.push(endSplit);\n }\n return this.createFieldValue(result);\n }\n\n /** Convert the list to a string. */\n toString(): string {\n return this.segments.map(seg => seg.text).join('');\n }\n\n /** Returns the previous list in the undo history. */\n undo(): this {\n return this.previous ?? this;\n }\n\n /** Returns the next list in the redo history. */\n redo(): this {\n return this.next ?? this;\n }\n\n /** End coalescing undo/redo history. */\n endCoalescing(): void {\n this.isCoalescing = false;\n }\n}\n\nfunction findInText(\n text: string,\n search: string | RegExp,\n direction: Direction,\n fromOffset?: number\n): number {\n if (typeof search === 'string') {\n if (direction === Direction.Backward) {\n return text.lastIndexOf(search, fromOffset !== undefined ? fromOffset - 1 : text.length - 1);\n }\n return text.indexOf(search, fromOffset ?? 0);\n }\n\n if (direction === Direction.Forward) {\n let start = fromOffset ?? 0;\n let index = text.slice(start).search(search);\n return index >= 0 ? start + index : -1;\n }\n\n let limit = fromOffset !== undefined ? fromOffset : text.length;\n if (limit < 0) {\n return -1;\n }\n\n let re = search.flags.includes('g') ? search : new RegExp(search.source, search.flags + 'g');\n let matches = Array.from(text.slice(0, limit).matchAll(re));\n return matches.at(-1)?.index ?? -1;\n}\n\nfunction appendSegments(\n segments: TokenFieldSegment[],\n insert: TokenFieldSegment[],\n tokenize?: (text: string) => TokenFieldSegment[]\n): TokenFieldSegment[] {\n for (let segment of insert) {\n if (segment.type === 'text' && segment.text.length === 0) {\n continue;\n }\n\n let last = segments[segments.length - 1];\n if (last && last.type === 'text' && segment.type === 'text') {\n if (tokenize) {\n let tokenized = tokenize(last.text + segment.text);\n segments.splice(segments.length - 1, 1, ...tokenized);\n } else {\n segments[segments.length - 1] = {type: 'text', text: last.text + segment.text};\n }\n } else if (tokenize && segment.type === 'text') {\n let tokenized = tokenize(segment.text);\n segments.push(...tokenized);\n } else {\n segments.push(segment);\n }\n }\n return segments;\n}\n"],"names":[],"version":3,"file":"TokenFieldValue.mjs.map"}
|
|
1
|
+
{"mappings":"AAAA;;;;;;;;;;CAUC,GAwBM,MAAM;IAMX;;;GAGC,GACD,YAAY,MAAgB,EAAE,UAAoB,MAAM,CAAE;QACxD,IAAI,CAAC,MAAM,GAAG;QACd,IAAI,CAAC,OAAO,GAAG;IACjB;IAEA,mEAAmE,GACnE,IAAI,cAAc;QAChB,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,KAAK,IAAI,CAAC,OAAO,CAAC,KAAK,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,KAAK,IAAI,CAAC,OAAO,CAAC,MAAM;IAC/F;IAEA,iEAAiE,GACjE,IAAI,QAAQ;QACV,OAAO,8BAAQ,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,IAAI,IAAI,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,OAAO;IAC5E;IAEA,+DAA+D,GAC/D,IAAI,MAAM;QACR,OAAO,8BAAQ,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,IAAI,IAAI,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,MAAM;IAC5E;IAEA,wDAAwD,GACxD,QAAQ,KAAoB,EAAE;QAC5B,IAAI,IAAI,KAAK,OACX,OAAO;QAET,OACE,IAAI,CAAC,MAAM,CAAC,KAAK,KAAK,MAAM,MAAM,CAAC,KAAK,IACxC,IAAI,CAAC,MAAM,CAAC,MAAM,KAAK,MAAM,MAAM,CAAC,MAAM,IAC1C,IAAI,CAAC,OAAO,CAAC,KAAK,KAAK,MAAM,OAAO,CAAC,KAAK,IAC1C,IAAI,CAAC,OAAO,CAAC,MAAM,KAAK,MAAM,OAAO,CAAC,MAAM;IAEhD;AACF;AAEA,SAAS,8BAAQ,CAAW,EAAE,CAAW;IACvC,IAAI,EAAE,KAAK,KAAK,EAAE,KAAK,EACrB,OAAO,EAAE,MAAM,GAAG,EAAE,MAAM;IAG5B,OAAO,EAAE,KAAK,GAAG,EAAE,KAAK;AAC1B;AAEA,IAAA,AAAK,yDAAA;;;WAAA;EAAA;AAYE,MAAM;;aACK,YAAY;;;aACZ,gBAAgB;;IAWhC,+CAA+C,GAC/C,YAAY,MAAuC,EAAE,OAAgC,CAAE;QANvF,kDAAkD;aAC1C,WAAwB;aACxB,OAAoB;aACpB,eAAe;QAIrB,IAAI,CAAC,QAAQ,GAAG;QAChB,IAAI,CAAC,aAAa,GAAG,SAAS,iBAAiB,IAAI,0CAAc;YAAC,OAAO;YAAG,QAAQ;QAAC;IACvF;IAEU,iBAAiB,QAAyC,EAAQ;QAC1E,MAAM,cAAc,IAAI,CAAC,WAAW;QAIpC,OAAO,IAAI,YAAY;IACzB;IAEA,IAAI,gBAA0B;QAC5B,OAAO,IAAI,CAAC,aAAa,CAAC,OAAO;IACnC;IAEA,yEAAyE,GACzE,kBAAkB,aAA4B,EAAQ;QACpD,IAAI,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,gBAC7B,OAAO,IAAI;QAGb,IAAI,SAAS,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,QAAQ;QAChD,OAAO,aAAa,GAAG;QACvB,OAAO,QAAQ,GAAG,IAAI,CAAC,QAAQ;QAC/B,OAAO,IAAI,GAAG,IAAI,CAAC,IAAI;QACvB,OAAO,YAAY,GAAG,IAAI,CAAC,YAAY;QACvC,OAAO;IACT;IAEA,kBAAkB,QAAkB,EAAQ;QAC1C,OAAO,IAAI,CAAC,iBAAiB,CAAC,IAAI,0CAAc;IAClD;IAEQ,aACN,OAAsC,EACtC,MAAc,EACwC;QACtD,IAAI,CAAC,SAAS;YACZ,IAAI,QAAQ,IAAI,CAAC,iBAAiB,CAAC;YACnC,OAAO;gBAAC,SAAS,IAAI,QAAQ;gBAAM,SAAS,IAAI,OAAO;aAAM;QAC/D;QAEA,IAAI,QAAQ,IAAI,KAAK,SACnB,OAAO;YAAC,SAAS,IAAI;gBAAC,GAAG,OAAO;YAAA,IAAI;YAAM,SAAS,IAAI,OAAO;gBAAC,GAAG,OAAO;YAAA;SAAE;QAG7E,OAAO;YACL,SAAS,IAAI;gBAAC,MAAM;gBAAQ,MAAM,QAAQ,IAAI,CAAC,KAAK,CAAC,GAAG;YAAO,IAAI;YACnE,SAAS,QAAQ,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,iBAAiB,CAAC,QAAQ,IAAI,CAAC,KAAK,CAAC,WAAW;SACrF;IACH;IAEQ,kBAAkB,IAAY,EAAe;QACnD,OAAO;YAAC,MAAM;kBAAQ;QAAI;IAC5B;IAEU,SAAS,IAAY,EAA0B;QACvD,OAAO;YAAC,IAAI,CAAC,iBAAiB,CAAC;SAAM;IACvC;IAEQ,cAAc,QAAkB,EAAY;QAClD,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,KAAK,SAAS,KAAK,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,EACpE,OAAO;YACL,OAAO,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG;YAC9B,QAAQ,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM;QAC7D;QAGF,IAAI,SAAS,KAAK,GAAG,GACnB,OAAO;YAAC,OAAO;YAAG,QAAQ;QAAC;QAE7B,OAAO;IACT;IAEA,0DAA0D,GAC1D,aAAa,KAAe,EAAE,GAAa,EAAE,IAAY,EAAE,WAAW,IAAI,EAAQ;QAChF,OAAO,IAAI,CAAC,wBAAwB,CAClC,OACA,KACA,KAAK,MAAM,GAAG,IAAI;YAAC,IAAI,CAAC,iBAAiB,CAAC;SAAM,GAAG,EAAE,EACrD;IAEJ;IAEA,8DAA8D,GAC9D,yBACE,KAAe,EACf,GAAa,EACb,MAA8B,EAC9B,WAAW,IAAI,EACT;QACN,QAAQ,IAAI,CAAC,aAAa,CAAC;QAC3B,MAAM,IAAI,CAAC,aAAa,CAAC;QACzB,IAAI,eAAe,IAAI,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC;QAC7C,IAAI,aAAa,IAAI,CAAC,QAAQ,CAAC,IAAI,KAAK,CAAC;QACzC,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,YAAY,CAAC,cAAc,MAAM,MAAM;QAC/D,IAAI,GAAG,SAAS,GAAG,IAAI,CAAC,YAAY,CAAC,YAAY,IAAI,MAAM;QAE3D,IAAI,cAAc,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,MAAM,KAAK;QACpD,IAAI,YACF,qCAAe,aAAa;YAAC;SAAW;QAG1C,IAAI,OAAO,MAAM,EACf,qCAAe,aAAa,QAAQ,CAAA,OAAQ,IAAI,CAAC,QAAQ,CAAC;QAG5D,IAAI,cAAc,WAAW,CAAC,YAAY,MAAM,GAAG,EAAE;QACrD,IAAI,aAAa,eAAe,YAAY,IAAI,KAAK;QACrD,IAAI,QAAQ;YACV,OAAO,aAAa,YAAY,MAAM,GAAG,IAAI,YAAY,MAAM;YAC/D,QAAQ,aAAa,YAAY,IAAI,CAAC,MAAM,GAAG;QACjD;QAEA,IAAI,UACF,qCAAe,aAAa;YAAC;SAAS;QAGxC,qCAAe,aAAa,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG;QAE5D,IAAI,WAAW,IAAI,CAAC,gBAAgB,CAAC;QACrC,SAAS,aAAa,GAAG,IAAI,0CAAc;QAC3C,SAAS,YAAY,GAAG;QACxB,IAAI,IAAI,CAAC,YAAY,IAAI,YAAY,IAAI,CAAC,QAAQ,EAAE;YAClD,SAAS,QAAQ,GAAG,IAAI,CAAC,QAAQ;YACjC,SAAS,QAAQ,CAAC,IAAI,GAAG;QAC3B,OAAO;YACL,SAAS,QAAQ,GAAG,IAAI;YACxB,IAAI,CAAC,aAAa,GAAG,IAAI,0CAAc,OAAO;YAC9C,IAAI,CAAC,IAAI,GAAG;QACd;QACA,OAAO;IACT;IAEA,0EAA0E,GAC1E,0BACE,QAAkB,EAClB,SAAyB,EACzB,SAAoB,EACH;QACjB,WAAW,IAAI,CAAC,aAAa,CAAC;QAC9B,IAAK,IAAI,IAAI,SAAS,KAAK,EAAE,KAAK,KAAK,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,KAAK,UAAW;YAC/E,IAAI,UAAU,IAAI,CAAC,QAAQ,CAAC,EAAE;YAC9B,OAAQ,QAAQ,IAAI;gBAClB,KAAK;oBACH,IACE,MAAM,SAAS,KAAK,IACnB,CAAA,mBAAmC,SAAS,MAAM,GAAG,IAAI,SAAS,MAAM,KAAK,CAAA,GAC9E;wBACA,IAAI,QAAQ,IAAI;wBAChB,OAAO;4BACL,OAAO,SAAS,IAAI,QAAQ;4BAC5B,QACE,oBAAoC,SAAS,IACzC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,GAChC;wBACR;oBACF;oBACA;gBACF,KAAK;oBAAQ;wBACX,IAAI,SAAS,mBAAmC,QAAQ,IAAI,CAAC,MAAM,GAAG;wBACtE,IAAI,MAAM,SAAS,KAAK,EACtB,SAAS,SAAS,MAAM;wBAE1B,IAAI,kBACF;wBAEF,IAAI,SAAS,KAAK,UAAU,QAAQ,IAAI,CAAC,MAAM,EAC7C;wBAGF,IAAI,OAAO,UAAU,OAAO,CAAC,QAAQ,IAAI,EAAE,UAAU,CAAC;wBACtD,MAAO,QAAQ,KAAK,UAAU,KAAK,MAAO;4BACxC,UAAU;4BACV,OAAO,UAAU,OAAO,CAAC,QAAQ,IAAI,EAAE,UAAU,CAAC;wBACpD;wBAEA,IAAI,MACF,OAAO;4BACL,OAAO;4BACP,QACE,mBAAmC,KAAK,KAAK,GAAG,KAAK,KAAK,GAAG,KAAK,OAAO,CAAC,MAAM;wBACpF;wBAEF;oBACF;YACF;QACF;QAEA,OAAO;IACT;IAEA,qDAAqD,GACrD,iBAAiB,QAAkB,EAAE,SAAoB,EAAmB;QAC1E,IAAI,MAAM,IAAI,CAAC,QAAQ,CAAC,UAAU,WAAW;QAC7C,IAAI,KACF,OAAO;QAET,OAAO,mBACH;YAAC,OAAO;YAAG,QAAQ;QAAC,IACpB;YACE,OAAO,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG;YAC9B,QAAQ,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM;QAC7D;IACN;IAEA,0EAA0E,GAC1E,SAAS,QAAkB,EAAE,SAAoB,EAAE,MAAuB,EAAmB;QAC3F,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,KAAK,GAC3B,OAAO;QAGT,IAAK,IAAI,IAAI,SAAS,KAAK,EAAE,KAAK,KAAK,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,KAAK,UAAW;YAC/E,IAAI,UAAU,IAAI,CAAC,QAAQ,CAAC,EAAE;YAC9B,IAAI,QAAQ,IAAI,KAAK,QACnB;YAEF,IAAI,SAAS,iCACX,QAAQ,IAAI,EACZ,QACA,WACA,MAAM,SAAS,KAAK,GAAG,SAAS,MAAM,GAAG;YAE3C,IAAI,UAAU,GACZ,OAAO;gBACL,OAAO;gBACP,QAAQ;YACV;QAEJ;QAEA,OAAO;IACT;IAEA,iDAAiD,GACjD,OACE,QAAkB,EAClB,SAAyB,EACzB,SAAoB,EACpB,WAAW,IAAI,EACT;QACN,IAAI,WAAW,IAAI,CAAC,yBAAyB,CAAC,UAAU,WAAW;QACnE,IAAI,UACF,OAAO,IAAI,CAAC,YAAY,CACtB,mBAAmC,WAAW,UAC9C,mBAAmC,WAAW,UAC9C,IACA;QAIJ,OAAO,IAAI,CAAC,iBAAiB,CAAC,IAAI,0CAAc;IAClD;IAEA,oDAAoD,GACpD,WAAW,QAAkB,EAAE,SAAoB,EAAE,WAAW,IAAI,EAAQ;QAC1E,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,KAAK,GAC3B,OAAO,IAAI;QAGb,IAAI,WAAW,IAAI,CAAC,gBAAgB,CAAC,UAAU;QAC/C,IAAI,UACF,OAAO,IAAI,CAAC,YAAY,CACtB,mBAAmC,WAAW,UAC9C,mBAAmC,WAAW,UAC9C,IACA;QAIJ,OAAO,IAAI,CAAC,iBAAiB,CAAC,IAAI,0CAAc;IAClD;IAEA,2DAA2D,GAC3D,MAAM,KAAe,EAAE,GAAa,EAAQ;QAC1C,QAAQ,IAAI,CAAC,aAAa,CAAC;QAC3B,MAAM,IAAI,CAAC,aAAa,CAAC;QACzB,IAAI,MAAM,KAAK,KAAK,IAAI,KAAK,IAAI,MAAM,MAAM,KAAK,IAAI,MAAM,EAC1D,OAAO,IAAI,CAAC,gBAAgB,CAAC,EAAE;QAEjC,IAAI,MAAM,KAAK,KAAK,IAAI,KAAK,EAAE;YAC7B,IAAI,UAAU,IAAI,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC;YACxC,IAAI,QAAQ,IAAI,KAAK,QACnB,OAAO,IAAI,CAAC,gBAAgB,CAAC;gBAC3B;oBAAC,MAAM;oBAAQ,MAAM,QAAQ,IAAI,CAAC,KAAK,CAAC,MAAM,MAAM,EAAE,IAAI,MAAM;gBAAC;aAClE;YAEH,OAAO,IAAI,CAAC,gBAAgB,CAAC;gBAAC;aAAQ;QACxC;QACA,IAAI,eAAe,IAAI,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC;QAC7C,IAAI,aAAa,IAAI,CAAC,QAAQ,CAAC,IAAI,KAAK,CAAC;QACzC,IAAI,GAAG,WAAW,GAAG,IAAI,CAAC,YAAY,CAAC,cAAc,MAAM,MAAM;QACjE,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,YAAY,CAAC,YAAY,IAAI,MAAM;QAEzD,IAAI,SAAiC,EAAE;QACvC,IAAI,YACF,OAAO,IAAI,CAAC;QAEd,OAAO,IAAI,IAAI,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,KAAK,GAAG,GAAG,IAAI,KAAK;QAC7D,IAAI,UACF,OAAO,IAAI,CAAC;QAEd,OAAO,IAAI,CAAC,gBAAgB,CAAC;IAC/B;IAEA,kCAAkC,GAClC,WAAmB;QACjB,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAA,MAAO,IAAI,IAAI,EAAE,IAAI,CAAC;IACjD;IAEA,mDAAmD,GACnD,OAAa;QACX,OAAO,IAAI,CAAC,QAAQ,IAAI,IAAI;IAC9B;IAEA,+CAA+C,GAC/C,OAAa;QACX,OAAO,IAAI,CAAC,IAAI,IAAI,IAAI;IAC1B;IAEA,sCAAsC,GACtC,gBAAsB;QACpB,IAAI,CAAC,YAAY,GAAG;IACtB;AACF;AAEA,SAAS,iCACP,IAAY,EACZ,MAAuB,EACvB,SAAoB,EACpB,UAAmB;IAEnB,IAAI,OAAO,WAAW,UAAU;QAC9B,IAAI,kBACF,OAAO,KAAK,WAAW,CAAC,QAAQ,eAAe,YAAY,aAAa,IAAI,KAAK,MAAM,GAAG;QAE5F,OAAO,KAAK,OAAO,CAAC,QAAQ,cAAc;IAC5C;IAEA,IAAI,iBAAiC;QACnC,IAAI,QAAQ,cAAc;QAC1B,IAAI,QAAQ,KAAK,KAAK,CAAC,OAAO,MAAM,CAAC;QACrC,OAAO,SAAS,IAAI,QAAQ,QAAQ;IACtC;IAEA,IAAI,QAAQ,eAAe,YAAY,aAAa,KAAK,MAAM;IAC/D,IAAI,QAAQ,GACV,OAAO;IAGT,IAAI,KAAK,OAAO,KAAK,CAAC,QAAQ,CAAC,OAAO,SAAS,IAAI,OAAO,OAAO,MAAM,EAAE,OAAO,KAAK,GAAG;IACxF,IAAI,UAAU,MAAM,IAAI,CAAC,KAAK,KAAK,CAAC,GAAG,OAAO,QAAQ,CAAC;IACvD,OAAO,QAAQ,EAAE,CAAC,CAAC,IAAI,SAAS;AAClC;AAEA,SAAS,qCACP,QAA6B,EAC7B,MAA2B,EAC3B,QAAgD;IAEhD,KAAK,IAAI,WAAW,OAAQ;QAC1B,IAAI,QAAQ,IAAI,KAAK,UAAU,QAAQ,IAAI,CAAC,MAAM,KAAK,GACrD;QAGF,IAAI,OAAO,QAAQ,CAAC,SAAS,MAAM,GAAG,EAAE;QACxC,IAAI,QAAQ,KAAK,IAAI,KAAK,UAAU,QAAQ,IAAI,KAAK;YACnD,IAAI,UAAU;gBACZ,IAAI,YAAY,SAAS,KAAK,IAAI,GAAG,QAAQ,IAAI;gBACjD,SAAS,MAAM,CAAC,SAAS,MAAM,GAAG,GAAG,MAAM;YAC7C,OACE,QAAQ,CAAC,SAAS,MAAM,GAAG,EAAE,GAAG;gBAAC,MAAM;gBAAQ,MAAM,KAAK,IAAI,GAAG,QAAQ,IAAI;YAAA;eAE1E,IAAI,YAAY,QAAQ,IAAI,KAAK,QAAQ;YAC9C,IAAI,YAAY,SAAS,QAAQ,IAAI;YACrC,SAAS,IAAI,IAAI;QACnB,OACE,SAAS,IAAI,CAAC;IAElB;IACA,OAAO;AACT","sources":["packages/react-stately/src/tokenfield/TokenFieldValue.ts"],"sourcesContent":["/*\n * Copyright 2026 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nexport type TokenFieldSegment<T = any> = TextSegment | TokenSegment<T>;\n\nexport interface TextSegment {\n type: 'text';\n text: string;\n}\n\nexport interface TokenSegment<T = any> {\n type: 'token';\n text: string;\n /** An arbitrary value associated with the token. */\n value?: T;\n}\n\nexport interface Position {\n /** Index of the segment in the list. */\n index: number;\n /** Text offset within the segment in UTF-16 code units. */\n offset: number;\n}\n\n/** Represents a text selection in a TokenField. */\nexport class SelectedRange {\n /** The anchor position. */\n anchor: Position;\n /** The current (i.e. caret) position. */\n current: Position;\n\n /**\n * Creates a new selection range. If only a single position is provided, the selection is\n * collapsed.\n */\n constructor(anchor: Position, current: Position = anchor) {\n this.anchor = anchor;\n this.current = current;\n }\n\n /** Whether the selection is collapsed to a single caret position. */\n get isCollapsed() {\n return this.anchor.index === this.current.index && this.anchor.offset === this.current.offset;\n }\n\n /** The side of the selection closest to the start of the value. */\n get start() {\n return compare(this.anchor, this.current) < 0 ? this.anchor : this.current;\n }\n\n /** The side of the selection closest to the end of the value. */\n get end() {\n return compare(this.anchor, this.current) < 0 ? this.current : this.anchor;\n }\n\n /** Returns whether this selection is equal to another. */\n isEqual(other: SelectedRange) {\n if (this === other) {\n return true;\n }\n return (\n this.anchor.index === other.anchor.index &&\n this.anchor.offset === other.anchor.offset &&\n this.current.index === other.current.index &&\n this.current.offset === other.current.offset\n );\n }\n}\n\nfunction compare(a: Position, b: Position) {\n if (a.index === b.index) {\n return a.offset - b.offset;\n }\n\n return a.index - b.index;\n}\n\nenum Direction {\n Forward = 1,\n Backward = -1\n}\n\nexport interface TokenFieldValueOptions {\n selectedRange?: SelectedRange | null;\n}\n\n/**\n * A list of segments containing editable text and non-editable tokens.\n */\nexport class TokenFieldValue<T = any> {\n static readonly Direction = Direction;\n static readonly SelectedRange = SelectedRange;\n\n /** The text and token segments in the list. */\n readonly segments: readonly TokenFieldSegment<T>[];\n /** The selected range. */\n selectedRange: SelectedRange;\n // Linked list representing the undo/redo history.\n private previous: this | null = null;\n private next: this | null = null;\n private isCoalescing = true;\n\n /** Create a new list with the given segments. */\n constructor(tokens: readonly TokenFieldSegment<T>[], options?: TokenFieldValueOptions) {\n this.segments = tokens;\n this.selectedRange = options?.selectedRange ?? new SelectedRange({index: 0, offset: 0});\n }\n\n protected createFieldValue(segments: readonly TokenFieldSegment<T>[]): this {\n const Constructor = this.constructor as new (\n segments: readonly TokenFieldSegment<T>[],\n options?: TokenFieldValueOptions\n ) => this;\n return new Constructor(segments);\n }\n\n get caretPosition(): Position {\n return this.selectedRange.current;\n }\n\n /** Create a new list with the caret position set to the given position. */\n withSelectedRange(selectedRange: SelectedRange): this {\n if (this.selectedRange.isEqual(selectedRange)) {\n return this;\n }\n\n let result = this.createFieldValue(this.segments);\n result.selectedRange = selectedRange;\n result.previous = this.previous;\n result.next = this.next;\n result.isCoalescing = this.isCoalescing;\n return result;\n }\n\n withCaretPosition(position: Position): this {\n return this.withSelectedRange(new SelectedRange(position));\n }\n\n private splitSegment(\n segment: TokenFieldSegment | undefined,\n offset: number\n ): [TokenFieldSegment | null, TokenFieldSegment | null] {\n if (!segment) {\n let empty = this.createTextSegment('');\n return [offset > 0 ? empty : null, offset > 0 ? null : empty];\n }\n\n if (segment.type === 'token') {\n return [offset > 0 ? {...segment} : null, offset > 0 ? null : {...segment}];\n }\n\n return [\n offset > 0 ? {type: 'text', text: segment.text.slice(0, offset)} : null,\n offset < segment.text.length ? this.createTextSegment(segment.text.slice(offset)) : null\n ];\n }\n\n private createTextSegment(text: string): TextSegment {\n return {type: 'text', text};\n }\n\n protected tokenize(text: string): TokenFieldSegment<T>[] {\n return [this.createTextSegment(text)];\n }\n\n private clampPosition(position: Position): Position {\n if (this.segments.length > 0 && position.index >= this.segments.length) {\n return {\n index: this.segments.length - 1,\n offset: this.segments[this.segments.length - 1].text.length\n };\n }\n\n if (position.index < 0) {\n return {index: 0, offset: 0};\n }\n return position;\n }\n\n /** Replace the text between two positions with new text. */\n replaceRange(start: Position, end: Position, text: string, coalesce = true): this {\n return this.replaceRangeWithSegments(\n start,\n end,\n text.length > 0 ? [this.createTextSegment(text)] : [],\n coalesce\n );\n }\n\n /** Replace the text between two positions with new segments. */\n replaceRangeWithSegments(\n start: Position,\n end: Position,\n insert: TokenFieldSegment<T>[],\n coalesce = true\n ): this {\n start = this.clampPosition(start);\n end = this.clampPosition(end);\n let startSegment = this.segments[start.index];\n let endSegment = this.segments[end.index];\n let [startSplit] = this.splitSegment(startSegment, start.offset);\n let [, endSplit] = this.splitSegment(endSegment, end.offset);\n\n let newSegments = this.segments.slice(0, start.index);\n if (startSplit) {\n appendSegments(newSegments, [startSplit]);\n }\n\n if (insert.length) {\n appendSegments(newSegments, insert, text => this.tokenize(text));\n }\n\n let lastSegment = newSegments[newSegments.length - 1];\n let lastIsText = lastSegment && lastSegment.type === 'text';\n let caret = {\n index: lastIsText ? newSegments.length - 1 : newSegments.length,\n offset: lastIsText ? lastSegment.text.length : 0\n };\n\n if (endSplit) {\n appendSegments(newSegments, [endSplit]);\n }\n\n appendSegments(newSegments, this.segments.slice(end.index + 1));\n\n let segments = this.createFieldValue(newSegments);\n segments.selectedRange = new SelectedRange(caret);\n segments.isCoalescing = coalesce;\n if (this.isCoalescing && coalesce && this.previous) {\n segments.previous = this.previous;\n segments.previous.next = segments;\n } else {\n segments.previous = this;\n this.selectedRange = new SelectedRange(start, end);\n this.next = segments;\n }\n return segments;\n }\n\n /** Find the boundary before or after a position using an Intl.Segmenter. */\n findBoundaryWithSegmenter(\n position: Position,\n segmenter: Intl.Segmenter,\n direction: Direction\n ): Position | null {\n position = this.clampPosition(position);\n for (let i = position.index; i >= 0 && i < this.segments.length; i += direction) {\n let segment = this.segments[i];\n switch (segment.type) {\n case 'token':\n if (\n i !== position.index ||\n (direction === Direction.Backward ? position.offset > 0 : position.offset === 0)\n ) {\n let index = i + direction;\n return {\n index: index >= 0 ? index : 0,\n offset:\n direction === Direction.Backward && index >= 0\n ? this.segments[index].text.length\n : 0\n };\n }\n continue;\n case 'text': {\n let offset = direction === Direction.Backward ? segment.text.length : 0;\n if (i === position.index) {\n offset = position.offset;\n }\n if (direction === Direction.Backward) {\n offset--;\n }\n if (offset < 0 || offset >= segment.text.length) {\n continue;\n }\n\n let part = segmenter.segment(segment.text).containing(offset);\n while (part && part.isWordLike === false) {\n offset += direction;\n part = segmenter.segment(segment.text).containing(offset);\n }\n\n if (part) {\n return {\n index: i,\n offset:\n direction === Direction.Backward ? part.index : part.index + part.segment.length\n };\n }\n continue;\n }\n }\n }\n\n return null;\n }\n\n /** Find a line boundary before or after a position. */\n findLineBoundary(position: Position, direction: Direction): Position | null {\n let res = this.findText(position, direction, '\\n');\n if (res) {\n return res;\n }\n return direction === Direction.Backward\n ? {index: 0, offset: 0}\n : {\n index: this.segments.length - 1,\n offset: this.segments[this.segments.length - 1].text.length\n };\n }\n\n /** Find a string or regular expression match before or after a position. */\n findText(position: Position, direction: Direction, search: string | RegExp): Position | null {\n if (this.segments.length === 0) {\n return null;\n }\n\n for (let i = position.index; i >= 0 && i < this.segments.length; i += direction) {\n let segment = this.segments[i];\n if (segment.type !== 'text') {\n continue;\n }\n let offset = findInText(\n segment.text,\n search,\n direction,\n i === position.index ? position.offset : undefined\n );\n if (offset >= 0) {\n return {\n index: i,\n offset: offset\n };\n }\n }\n\n return null;\n }\n\n /** Delete text at a position using a segmenter. */\n delete(\n position: Position,\n segmenter: Intl.Segmenter,\n direction: Direction,\n coalesce = true\n ): this {\n let boundary = this.findBoundaryWithSegmenter(position, segmenter, direction);\n if (boundary) {\n return this.replaceRange(\n direction === Direction.Backward ? boundary : position,\n direction === Direction.Backward ? position : boundary,\n '',\n coalesce\n );\n }\n\n return this.withSelectedRange(new SelectedRange(position));\n }\n\n /** Delete text to the next or previous line break. */\n deleteLine(position: Position, direction: Direction, coalesce = true): this {\n if (this.segments.length === 0) {\n return this;\n }\n\n let boundary = this.findLineBoundary(position, direction);\n if (boundary) {\n return this.replaceRange(\n direction === Direction.Backward ? boundary : position,\n direction === Direction.Backward ? position : boundary,\n '',\n coalesce\n );\n }\n\n return this.withSelectedRange(new SelectedRange(position));\n }\n\n /** Create a new list containing a subset of the segments. */\n slice(start: Position, end: Position): this {\n start = this.clampPosition(start);\n end = this.clampPosition(end);\n if (start.index === end.index && start.offset === end.offset) {\n return this.createFieldValue([]);\n }\n if (start.index === end.index) {\n let segment = this.segments[start.index];\n if (segment.type === 'text') {\n return this.createFieldValue([\n {type: 'text', text: segment.text.slice(start.offset, end.offset)}\n ]);\n }\n return this.createFieldValue([segment]);\n }\n let startSegment = this.segments[start.index];\n let endSegment = this.segments[end.index];\n let [, startSplit] = this.splitSegment(startSegment, start.offset);\n let [endSplit] = this.splitSegment(endSegment, end.offset);\n\n let result: TokenFieldSegment<T>[] = [];\n if (startSplit) {\n result.push(startSplit);\n }\n result.push(...this.segments.slice(start.index + 1, end.index));\n if (endSplit) {\n result.push(endSplit);\n }\n return this.createFieldValue(result);\n }\n\n /** Convert the list to a string. */\n toString(): string {\n return this.segments.map(seg => seg.text).join('');\n }\n\n /** Returns the previous list in the undo history. */\n undo(): this {\n return this.previous ?? this;\n }\n\n /** Returns the next list in the redo history. */\n redo(): this {\n return this.next ?? this;\n }\n\n /** End coalescing undo/redo history. */\n endCoalescing(): void {\n this.isCoalescing = false;\n }\n}\n\nfunction findInText(\n text: string,\n search: string | RegExp,\n direction: Direction,\n fromOffset?: number\n): number {\n if (typeof search === 'string') {\n if (direction === Direction.Backward) {\n return text.lastIndexOf(search, fromOffset !== undefined ? fromOffset - 1 : text.length - 1);\n }\n return text.indexOf(search, fromOffset ?? 0);\n }\n\n if (direction === Direction.Forward) {\n let start = fromOffset ?? 0;\n let index = text.slice(start).search(search);\n return index >= 0 ? start + index : -1;\n }\n\n let limit = fromOffset !== undefined ? fromOffset : text.length;\n if (limit < 0) {\n return -1;\n }\n\n let re = search.flags.includes('g') ? search : new RegExp(search.source, search.flags + 'g');\n let matches = Array.from(text.slice(0, limit).matchAll(re));\n return matches.at(-1)?.index ?? -1;\n}\n\nfunction appendSegments(\n segments: TokenFieldSegment[],\n insert: TokenFieldSegment[],\n tokenize?: (text: string) => TokenFieldSegment[]\n): TokenFieldSegment[] {\n for (let segment of insert) {\n if (segment.type === 'text' && segment.text.length === 0) {\n continue;\n }\n\n let last = segments[segments.length - 1];\n if (last && last.type === 'text' && segment.type === 'text') {\n if (tokenize) {\n let tokenized = tokenize(last.text + segment.text);\n segments.splice(segments.length - 1, 1, ...tokenized);\n } else {\n segments[segments.length - 1] = {type: 'text', text: last.text + segment.text};\n }\n } else if (tokenize && segment.type === 'text') {\n let tokenized = tokenize(segment.text);\n segments.push(...tokenized);\n } else {\n segments.push(segment);\n }\n }\n return segments;\n}\n"],"names":[],"version":3,"file":"TokenFieldValue.mjs.map"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { useTokenFieldState } from '../src/tokenfield/useTokenFieldState';
|
|
2
2
|
export { TokenFieldValue } from '../src/tokenfield/TokenFieldValue';
|
|
3
3
|
export type { TokenFieldProps, TokenFieldState } from '../src/tokenfield/useTokenFieldState';
|
|
4
|
-
export type { TokenFieldSegment, TokenSegment, TextSegment, Position, TokenFieldValueOptions } from '../src/tokenfield/TokenFieldValue';
|
|
4
|
+
export type { TokenFieldSegment, TokenSegment, TextSegment, Position, SelectedRange, TokenFieldValueOptions } from '../src/tokenfield/TokenFieldValue';
|
|
@@ -1,9 +1,4 @@
|
|
|
1
1
|
import { ItemProps } from '@react-types/shared';
|
|
2
|
-
import {
|
|
3
|
-
import { JSX, ReactElement } from 'react';
|
|
4
|
-
declare function Item<T>(props: ItemProps<T>): ReactElement | null;
|
|
5
|
-
declare namespace Item {
|
|
6
|
-
var getCollectionNode: <T>(props: ItemProps<T>, context: any) => Generator<PartialNode<T>, any, any>;
|
|
7
|
-
}
|
|
2
|
+
import { JSX } from 'react';
|
|
8
3
|
declare let _Item: <T>(props: ItemProps<T>) => JSX.Element;
|
|
9
4
|
export { _Item as Item };
|