Compare commits
No commits in common. "b85089604f581d9a6d1948f0570d0bf1bc9b6f96" and "fc2dbbd14db03ed718bcd526bd08fadf7a66a938" have entirely different histories.
b85089604f
...
fc2dbbd14d
@ -29,32 +29,30 @@ import EqualIcon from '../../Icons/EqualIcon'
|
||||
const operandIconStyle = { fontSize: 8 }
|
||||
|
||||
// Longer symbols first so ".." / "<>" / ">=" match before "." / "<" / ">".
|
||||
// Wildcards (* ?) are highlighted in place; @ stays as plain text — none are operands.
|
||||
const WILDCARDS = new Set(['*', '?'])
|
||||
|
||||
// Wildcards (* ?) and @ stay as plain text — they are not operands.
|
||||
const OPERANDS = [
|
||||
{
|
||||
symbol: '..',
|
||||
label: <ArrowLeftIcon style={operandIconStyle} />,
|
||||
color: 'purple'
|
||||
color: 'cyan'
|
||||
},
|
||||
{
|
||||
symbol: '<>',
|
||||
label: <NotEqualIcon style={operandIconStyle} />,
|
||||
color: 'magenta'
|
||||
color: 'volcano'
|
||||
},
|
||||
{
|
||||
symbol: '>=',
|
||||
label: <GreaterThanOrEqualToIcon style={operandIconStyle} />,
|
||||
color: 'volcano'
|
||||
color: 'orange'
|
||||
},
|
||||
{
|
||||
symbol: '<=',
|
||||
label: <LessThanOrEqualToIcon style={operandIconStyle} />,
|
||||
color: 'volcano'
|
||||
color: 'orange'
|
||||
},
|
||||
{ symbol: '|', label: 'OR', color: 'cyan' },
|
||||
{ symbol: '&', label: 'AND', color: 'cyan' },
|
||||
{ symbol: '|', label: 'OR', color: 'purple' },
|
||||
{ symbol: '&', label: 'AND', color: 'purple' },
|
||||
{
|
||||
symbol: '>',
|
||||
label: (
|
||||
@ -70,7 +68,7 @@ const OPERANDS = [
|
||||
{
|
||||
symbol: '=',
|
||||
label: <EqualIcon style={operandIconStyle} />,
|
||||
color: 'green'
|
||||
color: 'blue'
|
||||
}
|
||||
]
|
||||
|
||||
@ -95,13 +93,6 @@ const tokenize = (raw = '') => {
|
||||
}
|
||||
tokens.push({ type: 'operand', value: match.symbol })
|
||||
i += match.symbol.length
|
||||
} else if (WILDCARDS.has(value[i])) {
|
||||
if (text) {
|
||||
tokens.push({ type: 'text', value: text })
|
||||
text = ''
|
||||
}
|
||||
tokens.push({ type: 'wildcard', value: value[i] })
|
||||
i += 1
|
||||
} else {
|
||||
text += value[i]
|
||||
i += 1
|
||||
@ -112,14 +103,6 @@ const tokenize = (raw = '') => {
|
||||
return tokens
|
||||
}
|
||||
|
||||
const renderWildcardNode = (char) => {
|
||||
const span = document.createElement('span')
|
||||
span.setAttribute('data-wildcard', char)
|
||||
span.style.color = 'var(--color-primary)'
|
||||
span.textContent = char
|
||||
return span
|
||||
}
|
||||
|
||||
const normalize = (raw = '') =>
|
||||
tokenize(raw)
|
||||
.map((token) => token.value)
|
||||
@ -319,40 +302,31 @@ const setCaretOffset = (root, targetOffset) => {
|
||||
scrollSelectionIntoView(root)
|
||||
}
|
||||
|
||||
const walk = (container) => {
|
||||
for (let i = 0; i < container.childNodes.length; i += 1) {
|
||||
const child = container.childNodes[i]
|
||||
const length = nodeLength(child)
|
||||
for (let i = 0; i < root.childNodes.length; i += 1) {
|
||||
const child = root.childNodes[i]
|
||||
const length = nodeLength(child)
|
||||
|
||||
if (child.nodeType === Node.TEXT_NODE) {
|
||||
if (remaining <= length) {
|
||||
place(child, remaining)
|
||||
return true
|
||||
}
|
||||
remaining -= length
|
||||
continue
|
||||
if (child.nodeType === Node.TEXT_NODE) {
|
||||
if (remaining <= length) {
|
||||
place(child, remaining)
|
||||
return
|
||||
}
|
||||
|
||||
if (child.getAttribute?.('data-operand') != null) {
|
||||
if (remaining === 0) {
|
||||
place(container, i)
|
||||
return true
|
||||
}
|
||||
if (remaining <= length) {
|
||||
place(container, i + 1)
|
||||
return true
|
||||
}
|
||||
remaining -= length
|
||||
continue
|
||||
}
|
||||
|
||||
// Element wrappers (e.g. wildcard spans): recurse into children.
|
||||
if (walk(child)) return true
|
||||
remaining -= length
|
||||
continue
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
if (walk(root)) return
|
||||
if (child.getAttribute?.('data-operand') != null) {
|
||||
if (remaining === 0) {
|
||||
place(root, i)
|
||||
return
|
||||
}
|
||||
if (remaining <= length) {
|
||||
place(root, i + 1)
|
||||
return
|
||||
}
|
||||
remaining -= length
|
||||
}
|
||||
}
|
||||
|
||||
const range = document.createRange()
|
||||
range.selectNodeContents(root)
|
||||
@ -367,10 +341,7 @@ const domMatchesTokens = (root, raw) => {
|
||||
const tokens = tokenize(raw)
|
||||
const children = Array.from(root.childNodes).filter((node) => {
|
||||
if (node.nodeType === Node.TEXT_NODE) return (node.textContent ?? '') !== ''
|
||||
return (
|
||||
node.getAttribute?.('data-operand') != null ||
|
||||
node.getAttribute?.('data-wildcard') != null
|
||||
)
|
||||
return node.getAttribute?.('data-operand') != null
|
||||
})
|
||||
|
||||
// Empty editor may keep a single empty text node.
|
||||
@ -392,12 +363,6 @@ const domMatchesTokens = (root, raw) => {
|
||||
child.nodeType === Node.TEXT_NODE && child.textContent === token.value
|
||||
)
|
||||
}
|
||||
if (token.type === 'wildcard') {
|
||||
return (
|
||||
child.getAttribute?.('data-wildcard') === token.value &&
|
||||
(child.textContent ?? '') === token.value
|
||||
)
|
||||
}
|
||||
return child.getAttribute?.('data-operand') === token.value
|
||||
})
|
||||
}
|
||||
@ -604,8 +569,6 @@ const FilterInput = ({
|
||||
for (const item of tokens) {
|
||||
if (item.type === 'text') {
|
||||
nextChildren.push(document.createTextNode(item.value))
|
||||
} else if (item.type === 'wildcard') {
|
||||
nextChildren.push(renderWildcardNode(item.value))
|
||||
} else {
|
||||
nextChildren.push(takeChip(item.value))
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user