@vuu-ui/vuu-filters 0.8.4-debug → 0.8.5-debug

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/cjs/index.js CHANGED
@@ -103,7 +103,6 @@ var require_classnames = __commonJS({
103
103
  var src_exports = {};
104
104
  __export(src_exports, {
105
105
  AND: () => AND,
106
- ColumnFilter: () => ColumnFilter,
107
106
  ENDS_WITH: () => ENDS_WITH,
108
107
  EQUALS: () => EQUALS,
109
108
  FilterInput: () => FilterInput,
@@ -117,6 +116,8 @@ __export(src_exports, {
117
116
  filterClauses: () => filterClauses,
118
117
  filterEquals: () => filterEquals,
119
118
  filterIncludesColumn: () => filterIncludesColumn,
119
+ getNumericFilter: () => getNumericFilter,
120
+ getTypeaheadFilter: () => getTypeaheadFilter,
120
121
  overrideColName: () => overrideColName,
121
122
  removeFilter: () => removeFilter,
122
123
  splitFilterOnColumn: () => splitFilterOnColumn,
@@ -126,1288 +127,752 @@ __export(src_exports, {
126
127
  });
127
128
  module.exports = __toCommonJS(src_exports);
128
129
 
129
- // src/column-filter/ColumnFilter.tsx
130
- var import_salt_lab4 = require("@heswell/salt-lab");
130
+ // src/filter-input/FilterInput.tsx
131
131
  var import_core = require("@salt-ds/core");
132
132
 
133
- // ../../node_modules/@salt-ds/icons/dist-es/packages/icons/src/icon/Icon.js
134
- var import_jsx_runtime = require("react/jsx-runtime");
135
- var import_react = require("react");
136
-
137
- // ../../node_modules/clsx/dist/clsx.m.js
138
- function r(e) {
139
- var t, f, n = "";
140
- if ("string" == typeof e || "number" == typeof e)
141
- n += e;
142
- else if ("object" == typeof e)
143
- if (Array.isArray(e))
144
- for (t = 0; t < e.length; t++)
145
- e[t] && (f = r(e[t])) && (n && (n += " "), n += f);
146
- else
147
- for (t in e)
148
- e[t] && (n && (n += " "), n += t);
149
- return n;
150
- }
151
- function clsx() {
152
- for (var e, t, f = 0, n = ""; f < arguments.length; )
153
- (e = arguments[f++]) && (t = r(e)) && (n && (n += " "), n += t);
154
- return n;
155
- }
133
+ // src/filter-input/useCodeMirrorEditor.ts
134
+ var import_vuu_codemirror5 = require("@vuu-ui/vuu-codemirror");
156
135
 
157
- // ../../node_modules/@salt-ds/icons/dist-es/node_modules/style-inject/dist/style-inject.es.js
158
- function styleInject(css, ref) {
159
- if (ref === void 0)
160
- ref = {};
161
- var insertAt = ref.insertAt;
162
- if (!css || typeof document === "undefined") {
163
- return;
164
- }
165
- var head = document.head || document.getElementsByTagName("head")[0];
166
- var style = document.createElement("style");
167
- style.type = "text/css";
168
- if (insertAt === "top") {
169
- if (head.firstChild) {
170
- head.insertBefore(style, head.firstChild);
171
- } else {
172
- head.appendChild(style);
173
- }
174
- } else {
175
- head.appendChild(style);
176
- }
177
- if (style.styleSheet) {
178
- style.styleSheet.cssText = css;
179
- } else {
180
- style.appendChild(document.createTextNode(css));
136
+ // ../../node_modules/@lezer/common/dist/index.js
137
+ var DefaultBufferLength = 1024;
138
+ var nextPropID = 0;
139
+ var Range = class {
140
+ constructor(from, to) {
141
+ this.from = from;
142
+ this.to = to;
181
143
  }
182
- }
183
-
184
- // ../../node_modules/@salt-ds/icons/dist-es/packages/icons/src/icon/Icon.css.js
185
- var css_248z = "/* Style applied to the root element */\n.saltIcon {\n --icon-color: var(--saltIcon-color, var(--salt-text-secondary-foreground));\n --icon-size-multiplier: var(--saltIcon-size-multiplier, 1);\n --icon-base-size: var(--salt-size-icon-base, 12px);\n /**\n * Icon size will be the multiplier (an integer from the size prop) * the base size (set by the theme per density)\n * Icons should never be smaller than 12px for readability so we've added a max() to enforce this\n */\n --icon-size: max(calc(var(--icon-base-size) * var(--icon-size-multiplier)), 12px);\n}\n\n.saltIcon {\n fill: var(--saltIcon-color, var(--icon-color));\n display: inline-block;\n margin: var(--saltIcon-margin, 0);\n position: relative;\n width: var(--icon-size);\n height: var(--icon-size);\n min-width: var(--icon-size);\n min-height: var(--icon-size);\n}\n\n.saltIcon:hover {\n --icon-color: var(--saltIcon-color-hover, var(--salt-text-secondary-foreground));\n}\n\n.saltIcon:active {\n --icon-color: var(--saltIcon-color-active, var(--salt-text-secondary-foreground));\n}\n";
186
- styleInject(css_248z);
187
-
188
- // ../../node_modules/@salt-ds/icons/dist-es/packages/icons/src/icon/Icon.js
189
- var makePrefixer = (prefix) => (...names) => [prefix, ...names].join("-");
190
- var withBaseName = makePrefixer("saltIcon");
191
- var DEFAULT_ICON_SIZE = 1;
192
- var Icon = (0, import_react.forwardRef)(function Icon2({ children, className, size = DEFAULT_ICON_SIZE, style: styleProp, ...rest }, ref) {
193
- const style = {
194
- ...styleProp,
195
- "--saltIcon-size-multiplier": `${size}`
196
- };
197
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", {
198
- className: clsx(withBaseName(), className),
199
- style,
200
- role: "img",
201
- ...rest,
202
- ref,
203
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("g", {
204
- "aria-hidden": true,
205
- children
206
- })
207
- });
208
- });
209
-
210
- // ../../node_modules/@salt-ds/icons/dist-es/packages/icons/src/components/Delete.js
211
- var import_jsx_runtime2 = require("react/jsx-runtime");
212
- var import_react2 = require("react");
213
- var DeleteIcon = (0, import_react2.forwardRef)(
214
- function DeleteIcon2(props, ref) {
215
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Icon, {
216
- "data-testid": "DeleteIcon",
217
- "aria-label": "delete",
218
- viewBox: "0 0 12 12",
219
- ref,
220
- ...props,
221
- children: [
222
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", {
223
- d: "M5 4v6H4V4h1Zm2 0v6H6V4h1Z"
224
- }),
225
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", {
226
- fillRule: "evenodd",
227
- d: "M4 0a1 1 0 0 0-1 1v1H0v1h1v7a2 2 0 0 0 2 2h5.25A1.75 1.75 0 0 0 10 10.25V3h1V2H8V1a1 1 0 0 0-1-1H4Zm5 3H2v7a1 1 0 0 0 1 1h5.25a.75.75 0 0 0 .75-.75V3ZM7 2H4v-.5a.5.5 0 0 1 .5-.5h2a.5.5 0 0 1 .5.5V2Z",
228
- clipRule: "evenodd"
229
- })
230
- ]
144
+ };
145
+ var NodeProp = class {
146
+ /// Create a new node prop type.
147
+ constructor(config = {}) {
148
+ this.id = nextPropID++;
149
+ this.perNode = !!config.perNode;
150
+ this.deserialize = config.deserialize || (() => {
151
+ throw new Error("This node type doesn't define a deserialize function");
231
152
  });
232
153
  }
233
- );
234
-
235
- // src/column-filter/RangeFilter.tsx
236
- var import_salt_lab = require("@heswell/salt-lab");
237
-
238
- // src/filter-utils.ts
239
- var import_vuu_utils = require("@vuu-ui/vuu-utils");
240
- var AND = "and";
241
- var EQUALS = "=";
242
- var GREATER_THAN = ">";
243
- var LESS_THAN = "<";
244
- var OR = "or";
245
- var STARTS_WITH = "starts";
246
- var ENDS_WITH = "ends";
247
- var IN = "in";
248
- var filterClauses = (filter, clauses = []) => {
249
- if (filter) {
250
- if ((0, import_vuu_utils.isMultiClauseFilter)(filter)) {
251
- filter.filters.forEach((f) => clauses.push(...filterClauses(f)));
252
- } else {
253
- clauses.push(filter);
254
- }
154
+ /// This is meant to be used with
155
+ /// [`NodeSet.extend`](#common.NodeSet.extend) or
156
+ /// [`LRParser.configure`](#lr.ParserConfig.props) to compute
157
+ /// prop values for each node type in the set. Takes a [match
158
+ /// object](#common.NodeType^match) or function that returns undefined
159
+ /// if the node type doesn't get this prop, and the prop's value if
160
+ /// it does.
161
+ add(match) {
162
+ if (this.perNode)
163
+ throw new RangeError("Can't add per-node props to node types");
164
+ if (typeof match != "function")
165
+ match = NodeType.match(match);
166
+ return (type) => {
167
+ let result = match(type);
168
+ return result === void 0 ? null : [this, result];
169
+ };
255
170
  }
256
- return clauses;
257
- };
258
- var DEFAULT_ADD_FILTER_OPTS = {
259
- combineWith: "and"
260
171
  };
261
- var addFilter = (existingFilter, filter, { combineWith = AND } = DEFAULT_ADD_FILTER_OPTS) => {
262
- var _a;
263
- if (includesNoValues(filter)) {
264
- if ((0, import_vuu_utils.isMultiClauseFilter)(filter)) {
265
- } else {
266
- existingFilter = removeFilterForColumn(existingFilter, {
267
- name: filter.column
268
- });
269
- }
270
- } else if (includesAllValues(filter)) {
271
- if ((0, import_vuu_utils.isMultiClauseFilter)(filter)) {
272
- }
273
- return removeFilterForColumn(existingFilter, { name: (_a = filter.column) != null ? _a : "" });
274
- }
275
- if (!existingFilter) {
276
- return filter;
172
+ NodeProp.closedBy = new NodeProp({ deserialize: (str) => str.split(" ") });
173
+ NodeProp.openedBy = new NodeProp({ deserialize: (str) => str.split(" ") });
174
+ NodeProp.group = new NodeProp({ deserialize: (str) => str.split(" ") });
175
+ NodeProp.contextHash = new NodeProp({ perNode: true });
176
+ NodeProp.lookAhead = new NodeProp({ perNode: true });
177
+ NodeProp.mounted = new NodeProp({ perNode: true });
178
+ var noProps = /* @__PURE__ */ Object.create(null);
179
+ var NodeType = class {
180
+ /// @internal
181
+ constructor(name, props, id, flags = 0) {
182
+ this.name = name;
183
+ this.props = props;
184
+ this.id = id;
185
+ this.flags = flags;
277
186
  }
278
- if (!filter) {
279
- return existingFilter;
187
+ /// Define a node type.
188
+ static define(spec) {
189
+ let props = spec.props && spec.props.length ? /* @__PURE__ */ Object.create(null) : noProps;
190
+ let flags = (spec.top ? 1 : 0) | (spec.skipped ? 2 : 0) | (spec.error ? 4 : 0) | (spec.name == null ? 8 : 0);
191
+ let type = new NodeType(spec.name || "", props, spec.id, flags);
192
+ if (spec.props)
193
+ for (let src of spec.props) {
194
+ if (!Array.isArray(src))
195
+ src = src(type);
196
+ if (src) {
197
+ if (src[0].perNode)
198
+ throw new RangeError("Can't store a per-node prop on a node type");
199
+ props[src[0].id] = src[1];
200
+ }
201
+ }
202
+ return type;
280
203
  }
281
- if (existingFilter.op === AND && filter.op === AND) {
282
- return {
283
- op: AND,
284
- filters: combine(existingFilter.filters, filter.filters)
285
- };
204
+ /// Retrieves a node prop for this type. Will return `undefined` if
205
+ /// the prop isn't present on this node.
206
+ prop(prop) {
207
+ return this.props[prop.id];
286
208
  }
287
- if (existingFilter.op === AND) {
288
- const filters = replaceOrInsert(existingFilter.filters, filter);
289
- return filters.length > 1 ? { op: AND, filters } : filters[0];
209
+ /// True when this is the top node of a grammar.
210
+ get isTop() {
211
+ return (this.flags & 1) > 0;
290
212
  }
291
- if (filter.op === AND) {
292
- return { op: AND, filters: filter.filters.concat(existingFilter) };
213
+ /// True when this node is produced by a skip rule.
214
+ get isSkipped() {
215
+ return (this.flags & 2) > 0;
293
216
  }
294
- if (filterEquals(existingFilter, filter, true)) {
295
- return filter;
217
+ /// Indicates whether this is an error node.
218
+ get isError() {
219
+ return (this.flags & 4) > 0;
296
220
  }
297
- if (canMerge(existingFilter, filter)) {
298
- return merge(existingFilter, filter);
221
+ /// When true, this node type doesn't correspond to a user-declared
222
+ /// named node, for example because it is used to cache repetition.
223
+ get isAnonymous() {
224
+ return (this.flags & 8) > 0;
299
225
  }
300
- return { op: combineWith, filters: [existingFilter, filter] };
301
- };
302
- var includesNoValues = (filter) => {
303
- if (!filter) {
304
- return false;
226
+ /// Returns true when this node's name or one of its
227
+ /// [groups](#common.NodeProp^group) matches the given string.
228
+ is(name) {
229
+ if (typeof name == "string") {
230
+ if (this.name == name)
231
+ return true;
232
+ let group = this.prop(NodeProp.group);
233
+ return group ? group.indexOf(name) > -1 : false;
234
+ }
235
+ return this.id == name;
305
236
  }
306
- if ((0, import_vuu_utils.isInFilter)(filter) && filter.values.length === 0) {
307
- return true;
237
+ /// Create a function from node types to arbitrary values by
238
+ /// specifying an object whose property names are node or
239
+ /// [group](#common.NodeProp^group) names. Often useful with
240
+ /// [`NodeProp.add`](#common.NodeProp.add). You can put multiple
241
+ /// names, separated by spaces, in a single property name to map
242
+ /// multiple node names to a single value.
243
+ static match(map) {
244
+ let direct = /* @__PURE__ */ Object.create(null);
245
+ for (let prop in map)
246
+ for (let name of prop.split(" "))
247
+ direct[name] = map[prop];
248
+ return (node) => {
249
+ for (let groups = node.prop(NodeProp.group), i = -1; i < (groups ? groups.length : 0); i++) {
250
+ let found = direct[i < 0 ? node.name : groups[i]];
251
+ if (found)
252
+ return found;
253
+ }
254
+ };
308
255
  }
309
- return (0, import_vuu_utils.isAndFilter)(filter) && filter.filters.some((f) => includesNoValues(f));
310
256
  };
311
- var includesAllValues = (filter) => {
312
- if (!filter) {
313
- return false;
257
+ NodeType.none = new NodeType(
258
+ "",
259
+ /* @__PURE__ */ Object.create(null),
260
+ 0,
261
+ 8
262
+ /* NodeFlag.Anonymous */
263
+ );
264
+ var NodeSet = class {
265
+ /// Create a set with the given types. The `id` property of each
266
+ /// type should correspond to its position within the array.
267
+ constructor(types) {
268
+ this.types = types;
269
+ for (let i = 0; i < types.length; i++)
270
+ if (types[i].id != i)
271
+ throw new RangeError("Node type ids should correspond to array positions when creating a node set");
314
272
  }
315
- if (filter.op === STARTS_WITH && filter.value === "") {
316
- return true;
273
+ /// Create a copy of this set with some node properties added. The
274
+ /// arguments to this method can be created with
275
+ /// [`NodeProp.add`](#common.NodeProp.add).
276
+ extend(...props) {
277
+ let newTypes = [];
278
+ for (let type of this.types) {
279
+ let newProps = null;
280
+ for (let source of props) {
281
+ let add = source(type);
282
+ if (add) {
283
+ if (!newProps)
284
+ newProps = Object.assign({}, type.props);
285
+ newProps[add[0].id] = add[1];
286
+ }
287
+ }
288
+ newTypes.push(newProps ? new NodeType(type.name, newProps, type.id, type.flags) : type);
289
+ }
290
+ return new NodeSet(newTypes);
317
291
  }
318
- return filter.op === STARTS_WITH && filter.value === "";
319
- };
320
- var replaceOrInsert = (filters, filter) => {
321
- return filters.concat(filter);
322
292
  };
323
- var merge = (f1, f2) => {
324
- if (includesNoValues(f2)) {
325
- return f2;
326
- }
327
- if ((0, import_vuu_utils.isInFilter)(f1) && (0, import_vuu_utils.isInFilter)(f2)) {
328
- return {
329
- ...f1,
330
- values: [
331
- ...f1.values,
332
- ...f2.values.filter(
333
- (v) => !f1.values.includes(v)
334
- )
335
- ]
336
- };
337
- } else if ((0, import_vuu_utils.isInFilter)(f1) && f2.op === EQUALS) {
338
- return {
339
- ...f1,
340
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
341
- // @ts-ignore
342
- values: f1.values.concat([f2.value])
343
- };
344
- } else if (f1.op === EQUALS && f2.op === EQUALS) {
345
- return {
346
- column: f1.column,
347
- op: IN,
348
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
349
- // @ts-ignore
350
- values: [f1.value, f2.value]
351
- };
293
+ var CachedNode = /* @__PURE__ */ new WeakMap();
294
+ var CachedInnerNode = /* @__PURE__ */ new WeakMap();
295
+ var IterMode;
296
+ (function(IterMode2) {
297
+ IterMode2[IterMode2["ExcludeBuffers"] = 1] = "ExcludeBuffers";
298
+ IterMode2[IterMode2["IncludeAnonymous"] = 2] = "IncludeAnonymous";
299
+ IterMode2[IterMode2["IgnoreMounts"] = 4] = "IgnoreMounts";
300
+ IterMode2[IterMode2["IgnoreOverlays"] = 8] = "IgnoreOverlays";
301
+ })(IterMode || (IterMode = {}));
302
+ var Tree = class {
303
+ /// Construct a new tree. See also [`Tree.build`](#common.Tree^build).
304
+ constructor(type, children, positions, length, props) {
305
+ this.type = type;
306
+ this.children = children;
307
+ this.positions = positions;
308
+ this.length = length;
309
+ this.props = null;
310
+ if (props && props.length) {
311
+ this.props = /* @__PURE__ */ Object.create(null);
312
+ for (let [prop, value] of props)
313
+ this.props[typeof prop == "number" ? prop : prop.id] = value;
314
+ }
352
315
  }
353
- return f2;
354
- };
355
- var combine = (existingFilters, replacementFilters) => {
356
- const equivalentType = ({ op: t1 }, { op: t2 }) => {
357
- return t1 === t2 || t1[0] === t2[0];
358
- };
359
- const replaces = (existingFilter, replacementFilter) => {
360
- return existingFilter.column === replacementFilter.column && equivalentType(existingFilter, replacementFilter);
361
- };
362
- const stillApplicable = (existingFilter) => replacementFilters.some(
363
- (replacementFilter) => replaces(existingFilter, replacementFilter)
364
- ) === false;
365
- return existingFilters.filter(stillApplicable).concat(replacementFilters);
366
- };
367
- var removeFilter = (sourceFilter, filterToRemove) => {
368
- if (filterEquals(sourceFilter, filterToRemove, true)) {
369
- return null;
316
+ /// @internal
317
+ toString() {
318
+ let mounted = this.prop(NodeProp.mounted);
319
+ if (mounted && !mounted.overlay)
320
+ return mounted.tree.toString();
321
+ let children = "";
322
+ for (let ch of this.children) {
323
+ let str = ch.toString();
324
+ if (str) {
325
+ if (children)
326
+ children += ",";
327
+ children += str;
328
+ }
329
+ }
330
+ return !this.type.name ? children : (/\W/.test(this.type.name) && !this.type.isError ? JSON.stringify(this.type.name) : this.type.name) + (children.length ? "(" + children + ")" : "");
370
331
  }
371
- if (sourceFilter.op !== AND) {
372
- throw Error(
373
- `removeFilter cannot remove ${JSON.stringify(
374
- filterToRemove
375
- )} from ${JSON.stringify(sourceFilter)}`
376
- );
332
+ /// Get a [tree cursor](#common.TreeCursor) positioned at the top of
333
+ /// the tree. Mode can be used to [control](#common.IterMode) which
334
+ /// nodes the cursor visits.
335
+ cursor(mode = 0) {
336
+ return new TreeCursor(this.topNode, mode);
377
337
  }
378
- const filters = sourceFilter.filters.filter(
379
- (f) => !filterEquals(f, filterToRemove)
380
- );
381
- return filters.length > 0 ? { type: AND, filters } : null;
382
- };
383
- var splitFilterOnColumn = (columnName, filter) => {
384
- if (!filter) {
385
- return [void 0, void 0];
338
+ /// Get a [tree cursor](#common.TreeCursor) pointing into this tree
339
+ /// at the given position and side (see
340
+ /// [`moveTo`](#common.TreeCursor.moveTo).
341
+ cursorAt(pos, side = 0, mode = 0) {
342
+ let scope = CachedNode.get(this) || this.topNode;
343
+ let cursor = new TreeCursor(scope);
344
+ cursor.moveTo(pos, side);
345
+ CachedNode.set(this, cursor._tree);
346
+ return cursor;
386
347
  }
387
- if (filter.column === columnName) {
388
- return [filter, void 0];
348
+ /// Get a [syntax node](#common.SyntaxNode) object for the top of the
349
+ /// tree.
350
+ get topNode() {
351
+ return new TreeNode(this, 0, 0, null);
389
352
  }
390
- if (filter.op !== AND) {
391
- return [void 0, filter];
353
+ /// Get the [syntax node](#common.SyntaxNode) at the given position.
354
+ /// If `side` is -1, this will move into nodes that end at the
355
+ /// position. If 1, it'll move into nodes that start at the
356
+ /// position. With 0, it'll only enter nodes that cover the position
357
+ /// from both sides.
358
+ ///
359
+ /// Note that this will not enter
360
+ /// [overlays](#common.MountedTree.overlay), and you often want
361
+ /// [`resolveInner`](#common.Tree.resolveInner) instead.
362
+ resolve(pos, side = 0) {
363
+ let node = resolveNode(CachedNode.get(this) || this.topNode, pos, side, false);
364
+ CachedNode.set(this, node);
365
+ return node;
392
366
  }
393
- const [[columnFilter = void 0], filters] = (0, import_vuu_utils.partition)(
394
- filter.filters,
395
- (f) => f.column === columnName
396
- );
397
- return filters.length === 1 ? [columnFilter, filters[0]] : [columnFilter, { op: AND, filters }];
398
- };
399
- var overrideColName = (filter, column) => {
400
- if ((0, import_vuu_utils.isMultiClauseFilter)(filter)) {
401
- return {
402
- op: filter.op,
403
- filters: filter.filters.map((f) => overrideColName(f, column))
404
- };
367
+ /// Like [`resolve`](#common.Tree.resolve), but will enter
368
+ /// [overlaid](#common.MountedTree.overlay) nodes, producing a syntax node
369
+ /// pointing into the innermost overlaid tree at the given position
370
+ /// (with parent links going through all parent structure, including
371
+ /// the host trees).
372
+ resolveInner(pos, side = 0) {
373
+ let node = resolveNode(CachedInnerNode.get(this) || this.topNode, pos, side, true);
374
+ CachedInnerNode.set(this, node);
375
+ return node;
405
376
  }
406
- return { ...filter, column };
407
- };
408
- var filterIncludesColumn = (filter, column) => {
409
- if (!filter) {
410
- return false;
377
+ /// Iterate over the tree and its children, calling `enter` for any
378
+ /// node that touches the `from`/`to` region (if given) before
379
+ /// running over such a node's children, and `leave` (if given) when
380
+ /// leaving the node. When `enter` returns `false`, that node will
381
+ /// not have its children iterated over (or `leave` called).
382
+ iterate(spec) {
383
+ let { enter, leave, from = 0, to = this.length } = spec;
384
+ let mode = spec.mode || 0, anon = (mode & IterMode.IncludeAnonymous) > 0;
385
+ for (let c = this.cursor(mode | IterMode.IncludeAnonymous); ; ) {
386
+ let entered = false;
387
+ if (c.from <= to && c.to >= from && (!anon && c.type.isAnonymous || enter(c) !== false)) {
388
+ if (c.firstChild())
389
+ continue;
390
+ entered = true;
391
+ }
392
+ for (; ; ) {
393
+ if (entered && leave && (anon || !c.type.isAnonymous))
394
+ leave(c);
395
+ if (c.nextSibling())
396
+ break;
397
+ if (!c.parent())
398
+ return;
399
+ entered = true;
400
+ }
401
+ }
411
402
  }
412
- const { op, column: filterColName } = filter;
413
- switch (op) {
414
- case AND:
415
- case OR:
416
- return filter.filters != null && filter.filters.some((f) => filterIncludesColumn(f, column));
417
- default:
418
- return filterColName === column.name;
403
+ /// Get the value of the given [node prop](#common.NodeProp) for this
404
+ /// node. Works with both per-node and per-type props.
405
+ prop(prop) {
406
+ return !prop.perNode ? this.type.prop(prop) : this.props ? this.props[prop.id] : void 0;
419
407
  }
420
- };
421
- var removeFilterForColumn = (sourceFilter, column) => {
422
- const colName = column.name;
423
- if (!sourceFilter) {
424
- return void 0;
408
+ /// Returns the node's [per-node props](#common.NodeProp.perNode) in a
409
+ /// format that can be passed to the [`Tree`](#common.Tree)
410
+ /// constructor.
411
+ get propValues() {
412
+ let result = [];
413
+ if (this.props)
414
+ for (let id in this.props)
415
+ result.push([+id, this.props[id]]);
416
+ return result;
425
417
  }
426
- if (sourceFilter.column === colName) {
427
- return void 0;
418
+ /// Balance the direct children of this tree, producing a copy of
419
+ /// which may have children grouped into subtrees with type
420
+ /// [`NodeType.none`](#common.NodeType^none).
421
+ balance(config = {}) {
422
+ return this.children.length <= 8 ? this : balanceRange(NodeType.none, this.children, this.positions, 0, this.children.length, 0, this.length, (children, positions, length) => new Tree(this.type, children, positions, length, this.propValues), config.makeTree || ((children, positions, length) => new Tree(NodeType.none, children, positions, length)));
428
423
  }
429
- if ((0, import_vuu_utils.isAndFilter)(sourceFilter) || (0, import_vuu_utils.isOrFilter)(sourceFilter)) {
430
- const { op } = sourceFilter;
431
- const filters = sourceFilter.filters;
432
- const otherColFilters = filters.filter((f) => f.column !== colName);
433
- switch (otherColFilters.length) {
434
- case 0:
435
- return void 0;
436
- case 1:
437
- return otherColFilters[0];
438
- default:
439
- return { op, filters: otherColFilters };
440
- }
424
+ /// Build a tree from a postfix-ordered buffer of node information,
425
+ /// or a cursor over such a buffer.
426
+ static build(data) {
427
+ return buildTree(data);
441
428
  }
442
- return sourceFilter;
443
429
  };
444
- var canMerge = (f1, f2) => f1.column === f2.column && (f1.op === "=" || f1.op === "in") && (f2.op === "=" || f2.op === "in");
445
- var sameValues = (arr1, arr2) => {
446
- if (arr1 === arr2) {
447
- return true;
430
+ Tree.empty = new Tree(NodeType.none, [], [], 0);
431
+ var FlatBufferCursor = class {
432
+ constructor(buffer, index) {
433
+ this.buffer = buffer;
434
+ this.index = index;
448
435
  }
449
- if (arr1.length === arr2.length) {
450
- const a = arr1.slice().sort();
451
- const b = arr2.slice().sort();
452
- return a.join("|") === b.join("|");
436
+ get id() {
437
+ return this.buffer[this.index - 4];
453
438
  }
454
- return false;
455
- };
456
- var filterEquals = (f1, f2, strict = false) => {
457
- if (!strict) {
458
- return true;
439
+ get start() {
440
+ return this.buffer[this.index - 3];
459
441
  }
460
- if (f1 && f2 && canMerge(f1, f2)) {
461
- return f1.op === f2.op && ((0, import_vuu_utils.isSingleValueFilter)(f1) && (0, import_vuu_utils.isSingleValueFilter)(f2) && f1.value === f2.value || (0, import_vuu_utils.isMultiValueFilter)(f1) && (0, import_vuu_utils.isMultiValueFilter)(f2) && sameValues(f1.values, f2.values));
442
+ get end() {
443
+ return this.buffer[this.index - 2];
444
+ }
445
+ get size() {
446
+ return this.buffer[this.index - 1];
447
+ }
448
+ get pos() {
449
+ return this.index;
450
+ }
451
+ next() {
452
+ this.index -= 4;
453
+ }
454
+ fork() {
455
+ return new FlatBufferCursor(this.buffer, this.index);
462
456
  }
463
- return false;
464
457
  };
465
- var updateFilter = (filter, newFilter, mode) => {
466
- if (filter && newFilter) {
467
- if (mode === "replace") {
468
- return newFilter;
469
- }
470
- if (filter.op === "and") {
471
- return {
472
- ...filter,
473
- filters: filter.filters.concat(newFilter)
474
- };
475
- }
476
- const { column: columnName } = newFilter;
477
- if (columnName) {
478
- const existingClause = newFilter.column ? (0, import_vuu_utils.extractFilterForColumn)(filter, columnName) : void 0;
479
- if (existingClause && columnName) {
480
- const result = removeFilterForColumn(filter, { name: columnName });
481
- return updateFilter(result, newFilter, "add");
482
- }
483
- }
484
- return {
485
- op: "and",
486
- filters: [filter, newFilter]
487
- };
458
+ var TreeBuffer = class {
459
+ /// Create a tree buffer.
460
+ constructor(buffer, length, set) {
461
+ this.buffer = buffer;
462
+ this.length = length;
463
+ this.set = set;
488
464
  }
489
- if (newFilter) {
490
- return newFilter;
465
+ /// @internal
466
+ get type() {
467
+ return NodeType.none;
491
468
  }
492
- return filter;
493
- };
494
-
495
- // src/column-filter/utils.ts
496
- var isStartsWithValue = (value) => /\.\.\.$/.test(value);
497
- var getTypeaheadFilter = (column, filterValues, isStartsWithFilter) => {
498
- if (filterValues.length === 0) {
499
- return void 0;
469
+ /// @internal
470
+ toString() {
471
+ let result = [];
472
+ for (let index = 0; index < this.buffer.length; ) {
473
+ result.push(this.childString(index));
474
+ index = this.buffer[index + 3];
475
+ }
476
+ return result.join(",");
500
477
  }
501
- if (isStartsWithFilter) {
502
- const startsWith = filterValues[0].substring(0, filterValues[0].length - 3);
503
- return {
504
- column,
505
- op: "starts",
506
- value: `"${startsWith}"`
507
- };
478
+ /// @internal
479
+ childString(index) {
480
+ let id = this.buffer[index], endIndex = this.buffer[index + 3];
481
+ let type = this.set.types[id], result = type.name;
482
+ if (/\W/.test(result) && !type.isError)
483
+ result = JSON.stringify(result);
484
+ index += 4;
485
+ if (endIndex == index)
486
+ return result;
487
+ let children = [];
488
+ while (index < endIndex) {
489
+ children.push(this.childString(index));
490
+ index = this.buffer[index + 3];
491
+ }
492
+ return result + "(" + children.join(",") + ")";
508
493
  }
509
- return {
510
- column,
511
- op: "in",
512
- values: filterValues.map((value) => `"${value}"`)
513
- };
514
- };
515
- var getRangeFilter = (column, startValue, endValue) => {
516
- const startFilter = startValue === void 0 ? void 0 : { column, op: ">", value: startValue - 1 };
517
- const endFilter = endValue === void 0 ? void 0 : { column, op: "<", value: endValue + 1 };
518
- if (endFilter === void 0)
519
- return startFilter;
520
- return addFilter(startFilter, endFilter, { combineWith: "and" });
521
- };
522
-
523
- // src/column-filter/RangeFilter.tsx
524
- var import_jsx_runtime3 = require("react/jsx-runtime");
525
- var RangeFilter = ({
526
- defaultTypeaheadParams,
527
- filterValues,
528
- onChange
529
- }) => {
530
- var _a, _b;
531
- const columnName = defaultTypeaheadParams[1];
532
- const startChangeHandler = (e) => {
533
- const value = parseFloat(e.target.value);
534
- const newRange = {
535
- start: isNaN(value) ? void 0 : value,
536
- end: filterValues == null ? void 0 : filterValues.end
537
- };
538
- const filter = getRangeFilter(columnName, newRange.start, newRange.end);
539
- onChange(newRange, filter);
540
- };
541
- const endChangeHandler = (e) => {
542
- const value = parseFloat(e.target.value);
543
- const newRange = {
544
- start: filterValues == null ? void 0 : filterValues.start,
545
- end: isNaN(value) ? void 0 : value
546
- };
547
- const filter = getRangeFilter(columnName, newRange.start, newRange.end);
548
- onChange(newRange, filter);
549
- };
550
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", flexDirection: "row" }, children: [
551
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_salt_lab.ToolbarField, { label: "From", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
552
- import_salt_lab.Input,
553
- {
554
- onChange: startChangeHandler,
555
- value: ((_a = filterValues == null ? void 0 : filterValues.start) == null ? void 0 : _a.toString()) || "",
556
- type: "number"
557
- }
558
- ) }),
559
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_salt_lab.ToolbarField, { label: "To", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
560
- import_salt_lab.Input,
561
- {
562
- onChange: endChangeHandler,
563
- value: ((_b = filterValues == null ? void 0 : filterValues.end) == null ? void 0 : _b.toString()) || "",
564
- type: "number"
565
- }
566
- ) })
567
- ] });
568
- };
569
-
570
- // src/column-filter/TypeaheadFilter.tsx
571
- var import_vuu_data_react = require("@vuu-ui/vuu-data-react");
572
- var import_salt_lab2 = require("@heswell/salt-lab");
573
- var import_react3 = require("react");
574
- var import_jsx_runtime4 = require("react/jsx-runtime");
575
- var TypeaheadFilter = ({
576
- defaultTypeaheadParams,
577
- filterValues = [],
578
- onChange: onFilterChange
579
- }) => {
580
- const [tableName, columnName] = defaultTypeaheadParams;
581
- const [searchValue, setSearchValue] = (0, import_react3.useState)("");
582
- const [typeaheadValues, setTypeaheadValues] = (0, import_react3.useState)([]);
583
- const getSuggestions = (0, import_vuu_data_react.useTypeaheadSuggestions)();
584
- (0, import_react3.useEffect)(() => {
585
- const params = searchValue ? [tableName, columnName, searchValue] : defaultTypeaheadParams;
586
- let isSubscribed = true;
587
- getSuggestions(params).then((options) => {
588
- if (!isSubscribed) {
589
- return;
590
- }
591
- if (isStartsWithValue(filterValues[0])) {
592
- options.unshift(filterValues[0]);
593
- }
594
- if (searchValue) {
595
- options.unshift(`${searchValue}...`);
596
- }
597
- options.concat(filterValues);
598
- setTypeaheadValues(options);
599
- });
600
- return () => {
601
- isSubscribed = false;
602
- };
603
- }, [
604
- filterValues,
605
- searchValue,
606
- columnName,
607
- tableName,
608
- getSuggestions,
609
- defaultTypeaheadParams
610
- ]);
611
- const onInputChange = (0, import_react3.useCallback)(
612
- (evt) => {
613
- const value = evt.target.value;
614
- setSearchValue(value);
615
- },
616
- []
617
- );
618
- const onSelectionChange = (0, import_react3.useCallback)(
619
- (_evt, selected) => {
620
- setSearchValue("");
621
- if (selected === null)
622
- return;
623
- if (selected.some(isStartsWithValue)) {
624
- selected = selected.filter(isStartsWithValue).slice(-1);
494
+ /// @internal
495
+ findChild(startIndex, endIndex, dir, pos, side) {
496
+ let { buffer } = this, pick = -1;
497
+ for (let i = startIndex; i != endIndex; i = buffer[i + 3]) {
498
+ if (checkSide(side, pos, buffer[i + 1], buffer[i + 2])) {
499
+ pick = i;
500
+ if (dir > 0)
501
+ break;
625
502
  }
626
- const filter = getTypeaheadFilter(
627
- columnName,
628
- selected,
629
- isStartsWithValue(selected[0])
630
- );
631
- onFilterChange(selected, filter);
632
- },
633
- [columnName, onFilterChange]
634
- );
635
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
636
- import_salt_lab2.ComboBoxDeprecated,
637
- {
638
- multiSelect: true,
639
- onInputChange,
640
- onChange: onSelectionChange,
641
- source: typeaheadValues,
642
- style: { minWidth: 200 },
643
- inputValue: searchValue,
644
- selectedItem: filterValues
645
- },
646
- columnName
647
- );
648
- };
649
-
650
- // src/column-filter/ColumnListItem.tsx
651
- var import_react4 = require("react");
652
- var import_salt_lab3 = require("@heswell/salt-lab");
653
- var import_jsx_runtime5 = require("react/jsx-runtime");
654
- var ColumnListItem = (props) => {
655
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(MemoColumnItem, { ...props });
656
- };
657
- var MemoColumnItem = (0, import_react4.memo)(function MemoizedItem({
658
- item,
659
- itemTextHighlightPattern,
660
- ...restProps
661
- }) {
662
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_salt_lab3.ListItem, { ...restProps, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { style: { marginLeft: 10 }, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
663
- import_salt_lab3.Highlighter,
664
- {
665
- matchPattern: itemTextHighlightPattern,
666
- text: item == null ? void 0 : item.name
667
503
  }
668
- ) }) });
669
- });
670
-
671
- // src/column-filter/useColumnFilterStore.ts
672
- var import_vuu_utils2 = require("@vuu-ui/vuu-utils");
673
- var import_react5 = require("react");
674
- var addOrReplace = (array, newValue, key) => array.filter((oldValue) => oldValue[key] !== newValue[key]).concat(newValue);
675
- var useColumnFilterStore = (onFilterSubmit) => {
676
- var _a, _b;
677
- const [selectedColumnName, setSelectedColumnName] = (0, import_react5.useState)("");
678
- const [savedFilters, setSavedFilters] = (0, import_react5.useState)([]);
679
- const [rangeValues, setRangeValues] = (0, import_react5.useState)([]);
680
- const [typeaheadValues, setTypeaheadValues] = (0, import_react5.useState)([]);
681
- const clear = () => {
682
- setSelectedColumnName("");
683
- setRangeValues([]);
684
- setTypeaheadValues([]);
685
- setSavedFilters([]);
686
- onFilterSubmit({ filter: "" });
687
- };
688
- const updateFilters = (0, import_react5.useCallback)(
689
- (newFilter) => {
690
- const newSavedFilters = addOrReplace(
691
- savedFilters,
692
- { column: selectedColumnName, filter: newFilter },
693
- "column"
694
- );
695
- setSavedFilters(newSavedFilters);
696
- const combinedFilter = newSavedFilters.map((x) => x.filter).reduce((prev, filter) => {
697
- if (filter === void 0)
698
- return prev;
699
- return addFilter(prev, filter, { combineWith: AND });
700
- }, void 0);
701
- const query = combinedFilter === void 0 ? "" : (0, import_vuu_utils2.filterAsQuery)(combinedFilter);
702
- onFilterSubmit({ filter: query, filterStruct: combinedFilter });
703
- },
704
- [selectedColumnName, onFilterSubmit, savedFilters]
705
- );
706
- const onTypeaheadChange = (0, import_react5.useCallback)(
707
- (newValues, newFilter) => {
708
- setTypeaheadValues(
709
- addOrReplace(
710
- typeaheadValues,
711
- { column: selectedColumnName, value: newValues },
712
- "column"
713
- )
714
- );
715
- updateFilters(newFilter);
716
- },
717
- [selectedColumnName, typeaheadValues, updateFilters]
718
- );
719
- const onRangeChange = (0, import_react5.useCallback)(
720
- (newValues, newFilter) => {
721
- setRangeValues(
722
- addOrReplace(
723
- rangeValues,
724
- { column: selectedColumnName, value: newValues },
725
- "column"
726
- )
727
- );
728
- updateFilters(newFilter);
729
- },
730
- [selectedColumnName, rangeValues, updateFilters]
731
- );
732
- const onSelectedColumnChange = (0, import_react5.useCallback)(
733
- (column) => setSelectedColumnName((column == null ? void 0 : column.name) || ""),
734
- []
735
- );
736
- const rangeValue = (_a = rangeValues.filter(
737
- (v) => v.column === selectedColumnName
738
- )[0]) == null ? void 0 : _a.value;
739
- const typeaheadValue = (_b = typeaheadValues.filter(
740
- (v) => v.column === selectedColumnName
741
- )[0]) == null ? void 0 : _b.value;
742
- return {
743
- clear,
744
- selectedColumnName,
745
- rangeValue,
746
- typeaheadValue,
747
- onSelectedColumnChange,
748
- onRangeChange,
749
- onTypeaheadChange
750
- };
504
+ return pick;
505
+ }
506
+ /// @internal
507
+ slice(startI, endI, from) {
508
+ let b = this.buffer;
509
+ let copy = new Uint16Array(endI - startI), len = 0;
510
+ for (let i = startI, j = 0; i < endI; ) {
511
+ copy[j++] = b[i++];
512
+ copy[j++] = b[i++] - from;
513
+ let to = copy[j++] = b[i++] - from;
514
+ copy[j++] = b[i++] - startI;
515
+ len = Math.max(len, to);
516
+ }
517
+ return new TreeBuffer(copy, len, this.set);
518
+ }
751
519
  };
752
-
753
- // src/column-filter/ColumnFilter.tsx
754
- var import_jsx_runtime6 = require("react/jsx-runtime");
755
- var ColumnFilter = ({
756
- className,
757
- table,
758
- columns,
759
- onFilterSubmit,
760
- ...htmlAttributes
761
- }) => {
762
- const {
763
- clear,
764
- onTypeaheadChange,
765
- onRangeChange,
766
- onSelectedColumnChange,
767
- selectedColumnName,
768
- rangeValue,
769
- typeaheadValue
770
- } = useColumnFilterStore(onFilterSubmit);
771
- const getFilterComponent = () => {
772
- var _a;
773
- const defaultTypeaheadParams = [table, selectedColumnName];
774
- const selectedColumnType = (_a = columns.find(
775
- (column) => column.name === selectedColumnName
776
- )) == null ? void 0 : _a.serverDataType;
777
- switch (selectedColumnType) {
778
- case "string":
779
- case "char":
780
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
781
- import_salt_lab4.ToolbarField,
782
- {
783
- label: "Start typing to select a filter",
784
- labelPlacement: "top",
785
- children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
786
- TypeaheadFilter,
787
- {
788
- defaultTypeaheadParams,
789
- filterValues: typeaheadValue,
790
- onChange: onTypeaheadChange
791
- }
792
- )
793
- }
794
- );
795
- case "int":
796
- case "long":
797
- case "double":
798
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_salt_lab4.ToolbarField, { label: "Select a range", labelPlacement: "top", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
799
- RangeFilter,
800
- {
801
- defaultTypeaheadParams,
802
- filterValues: rangeValue,
803
- onChange: onRangeChange
804
- }
805
- ) });
806
- default:
807
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_salt_lab4.ToolbarField, { children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_core.Text, { children: "Data type unsupported" }) });
520
+ function checkSide(side, pos, from, to) {
521
+ switch (side) {
522
+ case -2:
523
+ return from < pos;
524
+ case -1:
525
+ return to >= pos && from < pos;
526
+ case 0:
527
+ return from < pos && to > pos;
528
+ case 1:
529
+ return from <= pos && to > pos;
530
+ case 2:
531
+ return to > pos;
532
+ case 4:
533
+ return true;
534
+ }
535
+ }
536
+ function enterUnfinishedNodesBefore(node, pos) {
537
+ let scan = node.childBefore(pos);
538
+ while (scan) {
539
+ let last = scan.lastChild;
540
+ if (!last || last.to != scan.to)
541
+ break;
542
+ if (last.type.isError && last.from == last.to) {
543
+ node = scan;
544
+ scan = last.prevSibling;
545
+ } else {
546
+ scan = last;
808
547
  }
809
- };
810
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
811
- import_salt_lab4.Toolbar,
812
- {
813
- ...htmlAttributes,
814
- style: { alignItems: "center", height: "36px" },
815
- children: [
816
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
817
- import_salt_lab4.ToolbarField,
818
- {
819
- label: "Select a column to filter",
820
- labelPlacement: "top",
821
- style: { width: 180 },
822
- children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
823
- import_salt_lab4.Dropdown,
824
- {
825
- source: columns,
826
- ListItem: ColumnListItem,
827
- itemToString: (column) => column.name,
828
- onSelectionChange: (_evt, column) => onSelectedColumnChange(column)
829
- }
830
- )
831
- }
832
- ),
833
- selectedColumnName && getFilterComponent(),
834
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_salt_lab4.ToolbarButton, { onClick: clear, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(DeleteIcon, {}) })
835
- ]
548
+ }
549
+ return node;
550
+ }
551
+ function resolveNode(node, pos, side, overlays) {
552
+ var _a;
553
+ while (node.from == node.to || (side < 1 ? node.from >= pos : node.from > pos) || (side > -1 ? node.to <= pos : node.to < pos)) {
554
+ let parent = !overlays && node instanceof TreeNode && node.index < 0 ? null : node.parent;
555
+ if (!parent)
556
+ return node;
557
+ node = parent;
558
+ }
559
+ let mode = overlays ? 0 : IterMode.IgnoreOverlays;
560
+ if (overlays)
561
+ for (let scan = node, parent = scan.parent; parent; scan = parent, parent = scan.parent) {
562
+ if (scan instanceof TreeNode && scan.index < 0 && ((_a = parent.enter(pos, side, mode)) === null || _a === void 0 ? void 0 : _a.from) != scan.from)
563
+ node = parent;
836
564
  }
837
- );
838
- };
839
-
840
- // src/filter-input/FilterInput.tsx
841
- var import_core2 = require("@salt-ds/core");
842
-
843
- // src/filter-input/useCodeMirrorEditor.ts
844
- var import_vuu_codemirror5 = require("@vuu-ui/vuu-codemirror");
845
-
846
- // ../../node_modules/@lezer/common/dist/index.js
847
- var DefaultBufferLength = 1024;
848
- var nextPropID = 0;
849
- var Range = class {
850
- constructor(from, to) {
565
+ for (; ; ) {
566
+ let inner = node.enter(pos, side, mode);
567
+ if (!inner)
568
+ return node;
569
+ node = inner;
570
+ }
571
+ }
572
+ var TreeNode = class {
573
+ constructor(_tree, from, index, _parent) {
574
+ this._tree = _tree;
851
575
  this.from = from;
852
- this.to = to;
576
+ this.index = index;
577
+ this._parent = _parent;
853
578
  }
854
- };
855
- var NodeProp = class {
856
- /// Create a new node prop type.
857
- constructor(config = {}) {
858
- this.id = nextPropID++;
859
- this.perNode = !!config.perNode;
860
- this.deserialize = config.deserialize || (() => {
861
- throw new Error("This node type doesn't define a deserialize function");
862
- });
579
+ get type() {
580
+ return this._tree.type;
863
581
  }
864
- /// This is meant to be used with
865
- /// [`NodeSet.extend`](#common.NodeSet.extend) or
866
- /// [`LRParser.configure`](#lr.ParserConfig.props) to compute
867
- /// prop values for each node type in the set. Takes a [match
868
- /// object](#common.NodeType^match) or function that returns undefined
869
- /// if the node type doesn't get this prop, and the prop's value if
870
- /// it does.
871
- add(match) {
872
- if (this.perNode)
873
- throw new RangeError("Can't add per-node props to node types");
874
- if (typeof match != "function")
875
- match = NodeType.match(match);
876
- return (type) => {
877
- let result = match(type);
878
- return result === void 0 ? null : [this, result];
879
- };
582
+ get name() {
583
+ return this._tree.type.name;
880
584
  }
881
- };
882
- NodeProp.closedBy = new NodeProp({ deserialize: (str) => str.split(" ") });
883
- NodeProp.openedBy = new NodeProp({ deserialize: (str) => str.split(" ") });
884
- NodeProp.group = new NodeProp({ deserialize: (str) => str.split(" ") });
885
- NodeProp.contextHash = new NodeProp({ perNode: true });
886
- NodeProp.lookAhead = new NodeProp({ perNode: true });
887
- NodeProp.mounted = new NodeProp({ perNode: true });
888
- var noProps = /* @__PURE__ */ Object.create(null);
889
- var NodeType = class {
890
- /// @internal
891
- constructor(name, props, id, flags = 0) {
892
- this.name = name;
893
- this.props = props;
894
- this.id = id;
895
- this.flags = flags;
585
+ get to() {
586
+ return this.from + this._tree.length;
896
587
  }
897
- /// Define a node type.
898
- static define(spec) {
899
- let props = spec.props && spec.props.length ? /* @__PURE__ */ Object.create(null) : noProps;
900
- let flags = (spec.top ? 1 : 0) | (spec.skipped ? 2 : 0) | (spec.error ? 4 : 0) | (spec.name == null ? 8 : 0);
901
- let type = new NodeType(spec.name || "", props, spec.id, flags);
902
- if (spec.props)
903
- for (let src of spec.props) {
904
- if (!Array.isArray(src))
905
- src = src(type);
906
- if (src) {
907
- if (src[0].perNode)
908
- throw new RangeError("Can't store a per-node prop on a node type");
909
- props[src[0].id] = src[1];
588
+ nextChild(i, dir, pos, side, mode = 0) {
589
+ for (let parent = this; ; ) {
590
+ for (let { children, positions } = parent._tree, e = dir > 0 ? children.length : -1; i != e; i += dir) {
591
+ let next = children[i], start = positions[i] + parent.from;
592
+ if (!checkSide(side, pos, start, start + next.length))
593
+ continue;
594
+ if (next instanceof TreeBuffer) {
595
+ if (mode & IterMode.ExcludeBuffers)
596
+ continue;
597
+ let index = next.findChild(0, next.buffer.length, dir, pos - start, side);
598
+ if (index > -1)
599
+ return new BufferNode(new BufferContext(parent, next, i, start), null, index);
600
+ } else if (mode & IterMode.IncludeAnonymous || (!next.type.isAnonymous || hasChild(next))) {
601
+ let mounted;
602
+ if (!(mode & IterMode.IgnoreMounts) && next.props && (mounted = next.prop(NodeProp.mounted)) && !mounted.overlay)
603
+ return new TreeNode(mounted.tree, start, i, parent);
604
+ let inner = new TreeNode(next, start, i, parent);
605
+ return mode & IterMode.IncludeAnonymous || !inner.type.isAnonymous ? inner : inner.nextChild(dir < 0 ? next.children.length - 1 : 0, dir, pos, side);
910
606
  }
911
607
  }
912
- return type;
913
- }
914
- /// Retrieves a node prop for this type. Will return `undefined` if
915
- /// the prop isn't present on this node.
916
- prop(prop) {
917
- return this.props[prop.id];
918
- }
919
- /// True when this is the top node of a grammar.
920
- get isTop() {
921
- return (this.flags & 1) > 0;
922
- }
923
- /// True when this node is produced by a skip rule.
924
- get isSkipped() {
925
- return (this.flags & 2) > 0;
926
- }
927
- /// Indicates whether this is an error node.
928
- get isError() {
929
- return (this.flags & 4) > 0;
930
- }
931
- /// When true, this node type doesn't correspond to a user-declared
932
- /// named node, for example because it is used to cache repetition.
933
- get isAnonymous() {
934
- return (this.flags & 8) > 0;
935
- }
936
- /// Returns true when this node's name or one of its
937
- /// [groups](#common.NodeProp^group) matches the given string.
938
- is(name) {
939
- if (typeof name == "string") {
940
- if (this.name == name)
941
- return true;
942
- let group = this.prop(NodeProp.group);
943
- return group ? group.indexOf(name) > -1 : false;
608
+ if (mode & IterMode.IncludeAnonymous || !parent.type.isAnonymous)
609
+ return null;
610
+ if (parent.index >= 0)
611
+ i = parent.index + dir;
612
+ else
613
+ i = dir < 0 ? -1 : parent._parent._tree.children.length;
614
+ parent = parent._parent;
615
+ if (!parent)
616
+ return null;
944
617
  }
945
- return this.id == name;
946
618
  }
947
- /// Create a function from node types to arbitrary values by
948
- /// specifying an object whose property names are node or
949
- /// [group](#common.NodeProp^group) names. Often useful with
950
- /// [`NodeProp.add`](#common.NodeProp.add). You can put multiple
951
- /// names, separated by spaces, in a single property name to map
952
- /// multiple node names to a single value.
953
- static match(map) {
954
- let direct = /* @__PURE__ */ Object.create(null);
955
- for (let prop in map)
956
- for (let name of prop.split(" "))
957
- direct[name] = map[prop];
958
- return (node) => {
959
- for (let groups = node.prop(NodeProp.group), i = -1; i < (groups ? groups.length : 0); i++) {
960
- let found = direct[i < 0 ? node.name : groups[i]];
961
- if (found)
962
- return found;
963
- }
964
- };
619
+ get firstChild() {
620
+ return this.nextChild(
621
+ 0,
622
+ 1,
623
+ 0,
624
+ 4
625
+ /* Side.DontCare */
626
+ );
965
627
  }
966
- };
967
- NodeType.none = new NodeType(
968
- "",
969
- /* @__PURE__ */ Object.create(null),
970
- 0,
971
- 8
972
- /* NodeFlag.Anonymous */
973
- );
974
- var NodeSet = class {
975
- /// Create a set with the given types. The `id` property of each
976
- /// type should correspond to its position within the array.
977
- constructor(types) {
978
- this.types = types;
979
- for (let i = 0; i < types.length; i++)
980
- if (types[i].id != i)
981
- throw new RangeError("Node type ids should correspond to array positions when creating a node set");
628
+ get lastChild() {
629
+ return this.nextChild(
630
+ this._tree.children.length - 1,
631
+ -1,
632
+ 0,
633
+ 4
634
+ /* Side.DontCare */
635
+ );
982
636
  }
983
- /// Create a copy of this set with some node properties added. The
984
- /// arguments to this method can be created with
985
- /// [`NodeProp.add`](#common.NodeProp.add).
986
- extend(...props) {
987
- let newTypes = [];
988
- for (let type of this.types) {
989
- let newProps = null;
990
- for (let source of props) {
991
- let add = source(type);
992
- if (add) {
993
- if (!newProps)
994
- newProps = Object.assign({}, type.props);
995
- newProps[add[0].id] = add[1];
996
- }
997
- }
998
- newTypes.push(newProps ? new NodeType(type.name, newProps, type.id, type.flags) : type);
999
- }
1000
- return new NodeSet(newTypes);
637
+ childAfter(pos) {
638
+ return this.nextChild(
639
+ 0,
640
+ 1,
641
+ pos,
642
+ 2
643
+ /* Side.After */
644
+ );
1001
645
  }
1002
- };
1003
- var CachedNode = /* @__PURE__ */ new WeakMap();
1004
- var CachedInnerNode = /* @__PURE__ */ new WeakMap();
1005
- var IterMode;
1006
- (function(IterMode2) {
1007
- IterMode2[IterMode2["ExcludeBuffers"] = 1] = "ExcludeBuffers";
1008
- IterMode2[IterMode2["IncludeAnonymous"] = 2] = "IncludeAnonymous";
1009
- IterMode2[IterMode2["IgnoreMounts"] = 4] = "IgnoreMounts";
1010
- IterMode2[IterMode2["IgnoreOverlays"] = 8] = "IgnoreOverlays";
1011
- })(IterMode || (IterMode = {}));
1012
- var Tree = class {
1013
- /// Construct a new tree. See also [`Tree.build`](#common.Tree^build).
1014
- constructor(type, children, positions, length, props) {
1015
- this.type = type;
1016
- this.children = children;
1017
- this.positions = positions;
1018
- this.length = length;
1019
- this.props = null;
1020
- if (props && props.length) {
1021
- this.props = /* @__PURE__ */ Object.create(null);
1022
- for (let [prop, value] of props)
1023
- this.props[typeof prop == "number" ? prop : prop.id] = value;
1024
- }
646
+ childBefore(pos) {
647
+ return this.nextChild(
648
+ this._tree.children.length - 1,
649
+ -1,
650
+ pos,
651
+ -2
652
+ /* Side.Before */
653
+ );
1025
654
  }
1026
- /// @internal
1027
- toString() {
1028
- let mounted = this.prop(NodeProp.mounted);
1029
- if (mounted && !mounted.overlay)
1030
- return mounted.tree.toString();
1031
- let children = "";
1032
- for (let ch of this.children) {
1033
- let str = ch.toString();
1034
- if (str) {
1035
- if (children)
1036
- children += ",";
1037
- children += str;
655
+ enter(pos, side, mode = 0) {
656
+ let mounted;
657
+ if (!(mode & IterMode.IgnoreOverlays) && (mounted = this._tree.prop(NodeProp.mounted)) && mounted.overlay) {
658
+ let rPos = pos - this.from;
659
+ for (let { from, to } of mounted.overlay) {
660
+ if ((side > 0 ? from <= rPos : from < rPos) && (side < 0 ? to >= rPos : to > rPos))
661
+ return new TreeNode(mounted.tree, mounted.overlay[0].from + this.from, -1, this);
1038
662
  }
1039
663
  }
1040
- return !this.type.name ? children : (/\W/.test(this.type.name) && !this.type.isError ? JSON.stringify(this.type.name) : this.type.name) + (children.length ? "(" + children + ")" : "");
664
+ return this.nextChild(0, 1, pos, side, mode);
1041
665
  }
1042
- /// Get a [tree cursor](#common.TreeCursor) positioned at the top of
1043
- /// the tree. Mode can be used to [control](#common.IterMode) which
1044
- /// nodes the cursor visits.
1045
- cursor(mode = 0) {
1046
- return new TreeCursor(this.topNode, mode);
666
+ nextSignificantParent() {
667
+ let val = this;
668
+ while (val.type.isAnonymous && val._parent)
669
+ val = val._parent;
670
+ return val;
1047
671
  }
1048
- /// Get a [tree cursor](#common.TreeCursor) pointing into this tree
1049
- /// at the given position and side (see
1050
- /// [`moveTo`](#common.TreeCursor.moveTo).
1051
- cursorAt(pos, side = 0, mode = 0) {
1052
- let scope = CachedNode.get(this) || this.topNode;
1053
- let cursor = new TreeCursor(scope);
1054
- cursor.moveTo(pos, side);
1055
- CachedNode.set(this, cursor._tree);
1056
- return cursor;
672
+ get parent() {
673
+ return this._parent ? this._parent.nextSignificantParent() : null;
1057
674
  }
1058
- /// Get a [syntax node](#common.SyntaxNode) object for the top of the
1059
- /// tree.
1060
- get topNode() {
1061
- return new TreeNode(this, 0, 0, null);
675
+ get nextSibling() {
676
+ return this._parent && this.index >= 0 ? this._parent.nextChild(
677
+ this.index + 1,
678
+ 1,
679
+ 0,
680
+ 4
681
+ /* Side.DontCare */
682
+ ) : null;
683
+ }
684
+ get prevSibling() {
685
+ return this._parent && this.index >= 0 ? this._parent.nextChild(
686
+ this.index - 1,
687
+ -1,
688
+ 0,
689
+ 4
690
+ /* Side.DontCare */
691
+ ) : null;
692
+ }
693
+ cursor(mode = 0) {
694
+ return new TreeCursor(this, mode);
695
+ }
696
+ get tree() {
697
+ return this._tree;
698
+ }
699
+ toTree() {
700
+ return this._tree;
1062
701
  }
1063
- /// Get the [syntax node](#common.SyntaxNode) at the given position.
1064
- /// If `side` is -1, this will move into nodes that end at the
1065
- /// position. If 1, it'll move into nodes that start at the
1066
- /// position. With 0, it'll only enter nodes that cover the position
1067
- /// from both sides.
1068
- ///
1069
- /// Note that this will not enter
1070
- /// [overlays](#common.MountedTree.overlay), and you often want
1071
- /// [`resolveInner`](#common.Tree.resolveInner) instead.
1072
702
  resolve(pos, side = 0) {
1073
- let node = resolveNode(CachedNode.get(this) || this.topNode, pos, side, false);
1074
- CachedNode.set(this, node);
1075
- return node;
703
+ return resolveNode(this, pos, side, false);
1076
704
  }
1077
- /// Like [`resolve`](#common.Tree.resolve), but will enter
1078
- /// [overlaid](#common.MountedTree.overlay) nodes, producing a syntax node
1079
- /// pointing into the innermost overlaid tree at the given position
1080
- /// (with parent links going through all parent structure, including
1081
- /// the host trees).
1082
705
  resolveInner(pos, side = 0) {
1083
- let node = resolveNode(CachedInnerNode.get(this) || this.topNode, pos, side, true);
1084
- CachedInnerNode.set(this, node);
1085
- return node;
706
+ return resolveNode(this, pos, side, true);
1086
707
  }
1087
- /// Iterate over the tree and its children, calling `enter` for any
1088
- /// node that touches the `from`/`to` region (if given) before
1089
- /// running over such a node's children, and `leave` (if given) when
1090
- /// leaving the node. When `enter` returns `false`, that node will
1091
- /// not have its children iterated over (or `leave` called).
1092
- iterate(spec) {
1093
- let { enter, leave, from = 0, to = this.length } = spec;
1094
- let mode = spec.mode || 0, anon = (mode & IterMode.IncludeAnonymous) > 0;
1095
- for (let c = this.cursor(mode | IterMode.IncludeAnonymous); ; ) {
1096
- let entered = false;
1097
- if (c.from <= to && c.to >= from && (!anon && c.type.isAnonymous || enter(c) !== false)) {
1098
- if (c.firstChild())
1099
- continue;
1100
- entered = true;
1101
- }
1102
- for (; ; ) {
1103
- if (entered && leave && (anon || !c.type.isAnonymous))
1104
- leave(c);
1105
- if (c.nextSibling())
1106
- break;
1107
- if (!c.parent())
1108
- return;
1109
- entered = true;
1110
- }
1111
- }
708
+ enterUnfinishedNodesBefore(pos) {
709
+ return enterUnfinishedNodesBefore(this, pos);
1112
710
  }
1113
- /// Get the value of the given [node prop](#common.NodeProp) for this
1114
- /// node. Works with both per-node and per-type props.
1115
- prop(prop) {
1116
- return !prop.perNode ? this.type.prop(prop) : this.props ? this.props[prop.id] : void 0;
711
+ getChild(type, before = null, after = null) {
712
+ let r = getChildren(this, type, before, after);
713
+ return r.length ? r[0] : null;
1117
714
  }
1118
- /// Returns the node's [per-node props](#common.NodeProp.perNode) in a
1119
- /// format that can be passed to the [`Tree`](#common.Tree)
1120
- /// constructor.
1121
- get propValues() {
1122
- let result = [];
1123
- if (this.props)
1124
- for (let id in this.props)
1125
- result.push([+id, this.props[id]]);
1126
- return result;
715
+ getChildren(type, before = null, after = null) {
716
+ return getChildren(this, type, before, after);
1127
717
  }
1128
- /// Balance the direct children of this tree, producing a copy of
1129
- /// which may have children grouped into subtrees with type
1130
- /// [`NodeType.none`](#common.NodeType^none).
1131
- balance(config = {}) {
1132
- return this.children.length <= 8 ? this : balanceRange(NodeType.none, this.children, this.positions, 0, this.children.length, 0, this.length, (children, positions, length) => new Tree(this.type, children, positions, length, this.propValues), config.makeTree || ((children, positions, length) => new Tree(NodeType.none, children, positions, length)));
718
+ /// @internal
719
+ toString() {
720
+ return this._tree.toString();
1133
721
  }
1134
- /// Build a tree from a postfix-ordered buffer of node information,
1135
- /// or a cursor over such a buffer.
1136
- static build(data) {
1137
- return buildTree(data);
722
+ get node() {
723
+ return this;
724
+ }
725
+ matchContext(context) {
726
+ return matchNodeContext(this, context);
1138
727
  }
1139
728
  };
1140
- Tree.empty = new Tree(NodeType.none, [], [], 0);
1141
- var FlatBufferCursor = class {
1142
- constructor(buffer, index) {
729
+ function getChildren(node, type, before, after) {
730
+ let cur = node.cursor(), result = [];
731
+ if (!cur.firstChild())
732
+ return result;
733
+ if (before != null) {
734
+ while (!cur.type.is(before))
735
+ if (!cur.nextSibling())
736
+ return result;
737
+ }
738
+ for (; ; ) {
739
+ if (after != null && cur.type.is(after))
740
+ return result;
741
+ if (cur.type.is(type))
742
+ result.push(cur.node);
743
+ if (!cur.nextSibling())
744
+ return after == null ? result : [];
745
+ }
746
+ }
747
+ function matchNodeContext(node, context, i = context.length - 1) {
748
+ for (let p = node.parent; i >= 0; p = p.parent) {
749
+ if (!p)
750
+ return false;
751
+ if (!p.type.isAnonymous) {
752
+ if (context[i] && context[i] != p.name)
753
+ return false;
754
+ i--;
755
+ }
756
+ }
757
+ return true;
758
+ }
759
+ var BufferContext = class {
760
+ constructor(parent, buffer, index, start) {
761
+ this.parent = parent;
1143
762
  this.buffer = buffer;
1144
763
  this.index = index;
764
+ this.start = start;
1145
765
  }
1146
- get id() {
1147
- return this.buffer[this.index - 4];
766
+ };
767
+ var BufferNode = class {
768
+ get name() {
769
+ return this.type.name;
1148
770
  }
1149
- get start() {
1150
- return this.buffer[this.index - 3];
771
+ get from() {
772
+ return this.context.start + this.context.buffer.buffer[this.index + 1];
1151
773
  }
1152
- get end() {
1153
- return this.buffer[this.index - 2];
774
+ get to() {
775
+ return this.context.start + this.context.buffer.buffer[this.index + 2];
1154
776
  }
1155
- get size() {
1156
- return this.buffer[this.index - 1];
777
+ constructor(context, _parent, index) {
778
+ this.context = context;
779
+ this._parent = _parent;
780
+ this.index = index;
781
+ this.type = context.buffer.set.types[context.buffer.buffer[index]];
1157
782
  }
1158
- get pos() {
1159
- return this.index;
783
+ child(dir, pos, side) {
784
+ let { buffer } = this.context;
785
+ let index = buffer.findChild(this.index + 4, buffer.buffer[this.index + 3], dir, pos - this.context.start, side);
786
+ return index < 0 ? null : new BufferNode(this.context, this, index);
1160
787
  }
1161
- next() {
1162
- this.index -= 4;
788
+ get firstChild() {
789
+ return this.child(
790
+ 1,
791
+ 0,
792
+ 4
793
+ /* Side.DontCare */
794
+ );
1163
795
  }
1164
- fork() {
1165
- return new FlatBufferCursor(this.buffer, this.index);
796
+ get lastChild() {
797
+ return this.child(
798
+ -1,
799
+ 0,
800
+ 4
801
+ /* Side.DontCare */
802
+ );
1166
803
  }
1167
- };
1168
- var TreeBuffer = class {
1169
- /// Create a tree buffer.
1170
- constructor(buffer, length, set) {
1171
- this.buffer = buffer;
1172
- this.length = length;
1173
- this.set = set;
804
+ childAfter(pos) {
805
+ return this.child(
806
+ 1,
807
+ pos,
808
+ 2
809
+ /* Side.After */
810
+ );
1174
811
  }
1175
- /// @internal
1176
- get type() {
1177
- return NodeType.none;
812
+ childBefore(pos) {
813
+ return this.child(
814
+ -1,
815
+ pos,
816
+ -2
817
+ /* Side.Before */
818
+ );
1178
819
  }
1179
- /// @internal
1180
- toString() {
1181
- let result = [];
1182
- for (let index = 0; index < this.buffer.length; ) {
1183
- result.push(this.childString(index));
1184
- index = this.buffer[index + 3];
1185
- }
1186
- return result.join(",");
820
+ enter(pos, side, mode = 0) {
821
+ if (mode & IterMode.ExcludeBuffers)
822
+ return null;
823
+ let { buffer } = this.context;
824
+ let index = buffer.findChild(this.index + 4, buffer.buffer[this.index + 3], side > 0 ? 1 : -1, pos - this.context.start, side);
825
+ return index < 0 ? null : new BufferNode(this.context, this, index);
1187
826
  }
1188
- /// @internal
1189
- childString(index) {
1190
- let id = this.buffer[index], endIndex = this.buffer[index + 3];
1191
- let type = this.set.types[id], result = type.name;
1192
- if (/\W/.test(result) && !type.isError)
1193
- result = JSON.stringify(result);
1194
- index += 4;
1195
- if (endIndex == index)
1196
- return result;
1197
- let children = [];
1198
- while (index < endIndex) {
1199
- children.push(this.childString(index));
1200
- index = this.buffer[index + 3];
1201
- }
1202
- return result + "(" + children.join(",") + ")";
827
+ get parent() {
828
+ return this._parent || this.context.parent.nextSignificantParent();
1203
829
  }
1204
- /// @internal
1205
- findChild(startIndex, endIndex, dir, pos, side) {
1206
- let { buffer } = this, pick = -1;
1207
- for (let i = startIndex; i != endIndex; i = buffer[i + 3]) {
1208
- if (checkSide(side, pos, buffer[i + 1], buffer[i + 2])) {
1209
- pick = i;
1210
- if (dir > 0)
1211
- break;
1212
- }
1213
- }
1214
- return pick;
1215
- }
1216
- /// @internal
1217
- slice(startI, endI, from) {
1218
- let b = this.buffer;
1219
- let copy = new Uint16Array(endI - startI), len = 0;
1220
- for (let i = startI, j = 0; i < endI; ) {
1221
- copy[j++] = b[i++];
1222
- copy[j++] = b[i++] - from;
1223
- let to = copy[j++] = b[i++] - from;
1224
- copy[j++] = b[i++] - startI;
1225
- len = Math.max(len, to);
1226
- }
1227
- return new TreeBuffer(copy, len, this.set);
1228
- }
1229
- };
1230
- function checkSide(side, pos, from, to) {
1231
- switch (side) {
1232
- case -2:
1233
- return from < pos;
1234
- case -1:
1235
- return to >= pos && from < pos;
1236
- case 0:
1237
- return from < pos && to > pos;
1238
- case 1:
1239
- return from <= pos && to > pos;
1240
- case 2:
1241
- return to > pos;
1242
- case 4:
1243
- return true;
1244
- }
1245
- }
1246
- function enterUnfinishedNodesBefore(node, pos) {
1247
- let scan = node.childBefore(pos);
1248
- while (scan) {
1249
- let last = scan.lastChild;
1250
- if (!last || last.to != scan.to)
1251
- break;
1252
- if (last.type.isError && last.from == last.to) {
1253
- node = scan;
1254
- scan = last.prevSibling;
1255
- } else {
1256
- scan = last;
1257
- }
1258
- }
1259
- return node;
1260
- }
1261
- function resolveNode(node, pos, side, overlays) {
1262
- var _a;
1263
- while (node.from == node.to || (side < 1 ? node.from >= pos : node.from > pos) || (side > -1 ? node.to <= pos : node.to < pos)) {
1264
- let parent = !overlays && node instanceof TreeNode && node.index < 0 ? null : node.parent;
1265
- if (!parent)
1266
- return node;
1267
- node = parent;
1268
- }
1269
- let mode = overlays ? 0 : IterMode.IgnoreOverlays;
1270
- if (overlays)
1271
- for (let scan = node, parent = scan.parent; parent; scan = parent, parent = scan.parent) {
1272
- if (scan instanceof TreeNode && scan.index < 0 && ((_a = parent.enter(pos, side, mode)) === null || _a === void 0 ? void 0 : _a.from) != scan.from)
1273
- node = parent;
1274
- }
1275
- for (; ; ) {
1276
- let inner = node.enter(pos, side, mode);
1277
- if (!inner)
1278
- return node;
1279
- node = inner;
1280
- }
1281
- }
1282
- var TreeNode = class {
1283
- constructor(_tree, from, index, _parent) {
1284
- this._tree = _tree;
1285
- this.from = from;
1286
- this.index = index;
1287
- this._parent = _parent;
1288
- }
1289
- get type() {
1290
- return this._tree.type;
1291
- }
1292
- get name() {
1293
- return this._tree.type.name;
1294
- }
1295
- get to() {
1296
- return this.from + this._tree.length;
1297
- }
1298
- nextChild(i, dir, pos, side, mode = 0) {
1299
- for (let parent = this; ; ) {
1300
- for (let { children, positions } = parent._tree, e = dir > 0 ? children.length : -1; i != e; i += dir) {
1301
- let next = children[i], start = positions[i] + parent.from;
1302
- if (!checkSide(side, pos, start, start + next.length))
1303
- continue;
1304
- if (next instanceof TreeBuffer) {
1305
- if (mode & IterMode.ExcludeBuffers)
1306
- continue;
1307
- let index = next.findChild(0, next.buffer.length, dir, pos - start, side);
1308
- if (index > -1)
1309
- return new BufferNode(new BufferContext(parent, next, i, start), null, index);
1310
- } else if (mode & IterMode.IncludeAnonymous || (!next.type.isAnonymous || hasChild(next))) {
1311
- let mounted;
1312
- if (!(mode & IterMode.IgnoreMounts) && next.props && (mounted = next.prop(NodeProp.mounted)) && !mounted.overlay)
1313
- return new TreeNode(mounted.tree, start, i, parent);
1314
- let inner = new TreeNode(next, start, i, parent);
1315
- return mode & IterMode.IncludeAnonymous || !inner.type.isAnonymous ? inner : inner.nextChild(dir < 0 ? next.children.length - 1 : 0, dir, pos, side);
1316
- }
1317
- }
1318
- if (mode & IterMode.IncludeAnonymous || !parent.type.isAnonymous)
1319
- return null;
1320
- if (parent.index >= 0)
1321
- i = parent.index + dir;
1322
- else
1323
- i = dir < 0 ? -1 : parent._parent._tree.children.length;
1324
- parent = parent._parent;
1325
- if (!parent)
1326
- return null;
1327
- }
1328
- }
1329
- get firstChild() {
1330
- return this.nextChild(
1331
- 0,
1332
- 1,
1333
- 0,
1334
- 4
1335
- /* Side.DontCare */
1336
- );
1337
- }
1338
- get lastChild() {
1339
- return this.nextChild(
1340
- this._tree.children.length - 1,
1341
- -1,
830
+ externalSibling(dir) {
831
+ return this._parent ? null : this.context.parent.nextChild(
832
+ this.context.index + dir,
833
+ dir,
1342
834
  0,
1343
835
  4
1344
836
  /* Side.DontCare */
1345
837
  );
1346
838
  }
1347
- childAfter(pos) {
1348
- return this.nextChild(
1349
- 0,
1350
- 1,
1351
- pos,
1352
- 2
1353
- /* Side.After */
1354
- );
1355
- }
1356
- childBefore(pos) {
1357
- return this.nextChild(
1358
- this._tree.children.length - 1,
1359
- -1,
1360
- pos,
1361
- -2
1362
- /* Side.Before */
1363
- );
1364
- }
1365
- enter(pos, side, mode = 0) {
1366
- let mounted;
1367
- if (!(mode & IterMode.IgnoreOverlays) && (mounted = this._tree.prop(NodeProp.mounted)) && mounted.overlay) {
1368
- let rPos = pos - this.from;
1369
- for (let { from, to } of mounted.overlay) {
1370
- if ((side > 0 ? from <= rPos : from < rPos) && (side < 0 ? to >= rPos : to > rPos))
1371
- return new TreeNode(mounted.tree, mounted.overlay[0].from + this.from, -1, this);
1372
- }
1373
- }
1374
- return this.nextChild(0, 1, pos, side, mode);
1375
- }
1376
- nextSignificantParent() {
1377
- let val = this;
1378
- while (val.type.isAnonymous && val._parent)
1379
- val = val._parent;
1380
- return val;
1381
- }
1382
- get parent() {
1383
- return this._parent ? this._parent.nextSignificantParent() : null;
1384
- }
1385
839
  get nextSibling() {
1386
- return this._parent && this.index >= 0 ? this._parent.nextChild(
1387
- this.index + 1,
1388
- 1,
1389
- 0,
1390
- 4
1391
- /* Side.DontCare */
1392
- ) : null;
840
+ let { buffer } = this.context;
841
+ let after = buffer.buffer[this.index + 3];
842
+ if (after < (this._parent ? buffer.buffer[this._parent.index + 3] : buffer.buffer.length))
843
+ return new BufferNode(this.context, this._parent, after);
844
+ return this.externalSibling(1);
1393
845
  }
1394
846
  get prevSibling() {
1395
- return this._parent && this.index >= 0 ? this._parent.nextChild(
1396
- this.index - 1,
847
+ let { buffer } = this.context;
848
+ let parentStart = this._parent ? this._parent.index + 4 : 0;
849
+ if (this.index == parentStart)
850
+ return this.externalSibling(-1);
851
+ return new BufferNode(this.context, this._parent, buffer.findChild(
852
+ parentStart,
853
+ this.index,
1397
854
  -1,
1398
855
  0,
1399
856
  4
1400
857
  /* Side.DontCare */
1401
- ) : null;
858
+ ));
1402
859
  }
1403
860
  cursor(mode = 0) {
1404
861
  return new TreeCursor(this, mode);
1405
862
  }
1406
863
  get tree() {
1407
- return this._tree;
864
+ return null;
1408
865
  }
1409
866
  toTree() {
1410
- return this._tree;
867
+ let children = [], positions = [];
868
+ let { buffer } = this.context;
869
+ let startI = this.index + 4, endI = buffer.buffer[this.index + 3];
870
+ if (endI > startI) {
871
+ let from = buffer.buffer[this.index + 1];
872
+ children.push(buffer.slice(startI, endI, from));
873
+ positions.push(0);
874
+ }
875
+ return new Tree(this.type, children, positions, this.to - this.from);
1411
876
  }
1412
877
  resolve(pos, side = 0) {
1413
878
  return resolveNode(this, pos, side, false);
@@ -1418,17 +883,17 @@ var TreeNode = class {
1418
883
  enterUnfinishedNodesBefore(pos) {
1419
884
  return enterUnfinishedNodesBefore(this, pos);
1420
885
  }
886
+ /// @internal
887
+ toString() {
888
+ return this.context.buffer.childString(this.index);
889
+ }
1421
890
  getChild(type, before = null, after = null) {
1422
- let r2 = getChildren(this, type, before, after);
1423
- return r2.length ? r2[0] : null;
891
+ let r = getChildren(this, type, before, after);
892
+ return r.length ? r[0] : null;
1424
893
  }
1425
894
  getChildren(type, before = null, after = null) {
1426
895
  return getChildren(this, type, before, after);
1427
896
  }
1428
- /// @internal
1429
- toString() {
1430
- return this._tree.toString();
1431
- }
1432
897
  get node() {
1433
898
  return this;
1434
899
  }
@@ -1436,203 +901,28 @@ var TreeNode = class {
1436
901
  return matchNodeContext(this, context);
1437
902
  }
1438
903
  };
1439
- function getChildren(node, type, before, after) {
1440
- let cur = node.cursor(), result = [];
1441
- if (!cur.firstChild())
1442
- return result;
1443
- if (before != null) {
1444
- while (!cur.type.is(before))
1445
- if (!cur.nextSibling())
1446
- return result;
904
+ var TreeCursor = class {
905
+ /// Shorthand for `.type.name`.
906
+ get name() {
907
+ return this.type.name;
1447
908
  }
1448
- for (; ; ) {
1449
- if (after != null && cur.type.is(after))
1450
- return result;
1451
- if (cur.type.is(type))
1452
- result.push(cur.node);
1453
- if (!cur.nextSibling())
1454
- return after == null ? result : [];
1455
- }
1456
- }
1457
- function matchNodeContext(node, context, i = context.length - 1) {
1458
- for (let p = node.parent; i >= 0; p = p.parent) {
1459
- if (!p)
1460
- return false;
1461
- if (!p.type.isAnonymous) {
1462
- if (context[i] && context[i] != p.name)
1463
- return false;
1464
- i--;
1465
- }
1466
- }
1467
- return true;
1468
- }
1469
- var BufferContext = class {
1470
- constructor(parent, buffer, index, start) {
1471
- this.parent = parent;
1472
- this.buffer = buffer;
1473
- this.index = index;
1474
- this.start = start;
1475
- }
1476
- };
1477
- var BufferNode = class {
1478
- get name() {
1479
- return this.type.name;
1480
- }
1481
- get from() {
1482
- return this.context.start + this.context.buffer.buffer[this.index + 1];
1483
- }
1484
- get to() {
1485
- return this.context.start + this.context.buffer.buffer[this.index + 2];
1486
- }
1487
- constructor(context, _parent, index) {
1488
- this.context = context;
1489
- this._parent = _parent;
1490
- this.index = index;
1491
- this.type = context.buffer.set.types[context.buffer.buffer[index]];
1492
- }
1493
- child(dir, pos, side) {
1494
- let { buffer } = this.context;
1495
- let index = buffer.findChild(this.index + 4, buffer.buffer[this.index + 3], dir, pos - this.context.start, side);
1496
- return index < 0 ? null : new BufferNode(this.context, this, index);
1497
- }
1498
- get firstChild() {
1499
- return this.child(
1500
- 1,
1501
- 0,
1502
- 4
1503
- /* Side.DontCare */
1504
- );
1505
- }
1506
- get lastChild() {
1507
- return this.child(
1508
- -1,
1509
- 0,
1510
- 4
1511
- /* Side.DontCare */
1512
- );
1513
- }
1514
- childAfter(pos) {
1515
- return this.child(
1516
- 1,
1517
- pos,
1518
- 2
1519
- /* Side.After */
1520
- );
1521
- }
1522
- childBefore(pos) {
1523
- return this.child(
1524
- -1,
1525
- pos,
1526
- -2
1527
- /* Side.Before */
1528
- );
1529
- }
1530
- enter(pos, side, mode = 0) {
1531
- if (mode & IterMode.ExcludeBuffers)
1532
- return null;
1533
- let { buffer } = this.context;
1534
- let index = buffer.findChild(this.index + 4, buffer.buffer[this.index + 3], side > 0 ? 1 : -1, pos - this.context.start, side);
1535
- return index < 0 ? null : new BufferNode(this.context, this, index);
1536
- }
1537
- get parent() {
1538
- return this._parent || this.context.parent.nextSignificantParent();
1539
- }
1540
- externalSibling(dir) {
1541
- return this._parent ? null : this.context.parent.nextChild(
1542
- this.context.index + dir,
1543
- dir,
1544
- 0,
1545
- 4
1546
- /* Side.DontCare */
1547
- );
1548
- }
1549
- get nextSibling() {
1550
- let { buffer } = this.context;
1551
- let after = buffer.buffer[this.index + 3];
1552
- if (after < (this._parent ? buffer.buffer[this._parent.index + 3] : buffer.buffer.length))
1553
- return new BufferNode(this.context, this._parent, after);
1554
- return this.externalSibling(1);
1555
- }
1556
- get prevSibling() {
1557
- let { buffer } = this.context;
1558
- let parentStart = this._parent ? this._parent.index + 4 : 0;
1559
- if (this.index == parentStart)
1560
- return this.externalSibling(-1);
1561
- return new BufferNode(this.context, this._parent, buffer.findChild(
1562
- parentStart,
1563
- this.index,
1564
- -1,
1565
- 0,
1566
- 4
1567
- /* Side.DontCare */
1568
- ));
1569
- }
1570
- cursor(mode = 0) {
1571
- return new TreeCursor(this, mode);
1572
- }
1573
- get tree() {
1574
- return null;
1575
- }
1576
- toTree() {
1577
- let children = [], positions = [];
1578
- let { buffer } = this.context;
1579
- let startI = this.index + 4, endI = buffer.buffer[this.index + 3];
1580
- if (endI > startI) {
1581
- let from = buffer.buffer[this.index + 1];
1582
- children.push(buffer.slice(startI, endI, from));
1583
- positions.push(0);
1584
- }
1585
- return new Tree(this.type, children, positions, this.to - this.from);
1586
- }
1587
- resolve(pos, side = 0) {
1588
- return resolveNode(this, pos, side, false);
1589
- }
1590
- resolveInner(pos, side = 0) {
1591
- return resolveNode(this, pos, side, true);
1592
- }
1593
- enterUnfinishedNodesBefore(pos) {
1594
- return enterUnfinishedNodesBefore(this, pos);
1595
- }
1596
- /// @internal
1597
- toString() {
1598
- return this.context.buffer.childString(this.index);
1599
- }
1600
- getChild(type, before = null, after = null) {
1601
- let r2 = getChildren(this, type, before, after);
1602
- return r2.length ? r2[0] : null;
1603
- }
1604
- getChildren(type, before = null, after = null) {
1605
- return getChildren(this, type, before, after);
1606
- }
1607
- get node() {
1608
- return this;
1609
- }
1610
- matchContext(context) {
1611
- return matchNodeContext(this, context);
1612
- }
1613
- };
1614
- var TreeCursor = class {
1615
- /// Shorthand for `.type.name`.
1616
- get name() {
1617
- return this.type.name;
1618
- }
1619
- /// @internal
1620
- constructor(node, mode = 0) {
1621
- this.mode = mode;
1622
- this.buffer = null;
1623
- this.stack = [];
1624
- this.index = 0;
1625
- this.bufferNode = null;
1626
- if (node instanceof TreeNode) {
1627
- this.yieldNode(node);
1628
- } else {
1629
- this._tree = node.context.parent;
1630
- this.buffer = node.context;
1631
- for (let n = node._parent; n; n = n._parent)
1632
- this.stack.unshift(n.index);
1633
- this.bufferNode = node;
1634
- this.yieldBuf(node.index);
1635
- }
909
+ /// @internal
910
+ constructor(node, mode = 0) {
911
+ this.mode = mode;
912
+ this.buffer = null;
913
+ this.stack = [];
914
+ this.index = 0;
915
+ this.bufferNode = null;
916
+ if (node instanceof TreeNode) {
917
+ this.yieldNode(node);
918
+ } else {
919
+ this._tree = node.context.parent;
920
+ this.buffer = node.context;
921
+ for (let n = node._parent; n; n = n._parent)
922
+ this.stack.unshift(n.index);
923
+ this.bufferNode = node;
924
+ this.yieldBuf(node.index);
925
+ }
1636
926
  }
1637
927
  yieldNode(node) {
1638
928
  if (!node)
@@ -2148,7 +1438,7 @@ var Parser = class {
2148
1438
  startParse(input, fragments, ranges) {
2149
1439
  if (typeof input == "string")
2150
1440
  input = new StringInput(input);
2151
- ranges = !ranges ? [new Range(0, input.length)] : ranges.length ? ranges.map((r2) => new Range(r2.from, r2.to)) : [new Range(0, 0)];
1441
+ ranges = !ranges ? [new Range(0, input.length)] : ranges.length ? ranges.map((r) => new Range(r.from, r.to)) : [new Range(0, 0)];
2152
1442
  return this.createParse(input, fragments || [], ranges);
2153
1443
  }
2154
1444
  /// Run a full parse, returning the resulting tree.
@@ -2897,11 +2187,11 @@ var InputStream = class {
2897
2187
  if (from >= this.range.from && to <= this.range.to)
2898
2188
  return this.input.read(from, to);
2899
2189
  let result = "";
2900
- for (let r2 of this.ranges) {
2901
- if (r2.from >= to)
2190
+ for (let r of this.ranges) {
2191
+ if (r.from >= to)
2902
2192
  break;
2903
- if (r2.to > from)
2904
- result += this.input.read(Math.max(r2.from, from), Math.min(r2.to, to));
2193
+ if (r.to > from)
2194
+ result += this.input.read(Math.max(r.from, from), Math.min(r.to, to));
2905
2195
  }
2906
2196
  return result;
2907
2197
  }
@@ -3532,7 +2822,7 @@ var LRParser = class extends Parser {
3532
2822
  this.minRepeatTerm = nodeNames.length;
3533
2823
  for (let i = 0; i < spec.repeatNodeCount; i++)
3534
2824
  nodeNames.push("");
3535
- let topTerms = Object.keys(spec.topRules).map((r2) => spec.topRules[r2][1]);
2825
+ let topTerms = Object.keys(spec.topRules).map((r) => spec.topRules[r][1]);
3536
2826
  let nodeProps = [];
3537
2827
  for (let i = 0; i < nodeNames.length; i++)
3538
2828
  nodeProps.push([]);
@@ -3712,13 +3002,13 @@ var LRParser = class extends Parser {
3712
3002
  }
3713
3003
  if (config.tokenizers)
3714
3004
  copy.tokenizers = this.tokenizers.map((t) => {
3715
- let found = config.tokenizers.find((r2) => r2.from == t);
3005
+ let found = config.tokenizers.find((r) => r.from == t);
3716
3006
  return found ? found.to : t;
3717
3007
  });
3718
3008
  if (config.specializers) {
3719
3009
  copy.specializers = this.specializers.slice();
3720
3010
  copy.specializerSpecs = this.specializerSpecs.map((s, i) => {
3721
- let found = config.specializers.find((r2) => r2.from == s.external);
3011
+ let found = config.specializers.find((r) => r.from == s.external);
3722
3012
  if (!found)
3723
3013
  return s;
3724
3014
  let spec = Object.assign(Object.assign({}, s), { external: found.to });
@@ -3828,14 +3118,14 @@ var parser = LRParser.deserialize({
3828
3118
  });
3829
3119
 
3830
3120
  // ../vuu-filter-parser/src/FilterTreeWalker.ts
3831
- var import_vuu_utils3 = require("@vuu-ui/vuu-utils");
3121
+ var import_vuu_utils = require("@vuu-ui/vuu-utils");
3832
3122
  var _filter;
3833
3123
  var FilterExpression = class {
3834
3124
  constructor() {
3835
3125
  __privateAdd(this, _filter, void 0);
3836
3126
  }
3837
3127
  setFilterCombinatorOp(op, filter = __privateGet(this, _filter)) {
3838
- if ((0, import_vuu_utils3.isMultiClauseFilter)(filter) && filter.op === op) {
3128
+ if ((0, import_vuu_utils.isMultiClauseFilter)(filter) && filter.op === op) {
3839
3129
  return;
3840
3130
  } else {
3841
3131
  __privateSet(this, _filter, {
@@ -3847,14 +3137,14 @@ var FilterExpression = class {
3847
3137
  add(filter) {
3848
3138
  if (__privateGet(this, _filter) === void 0) {
3849
3139
  __privateSet(this, _filter, filter);
3850
- } else if ((0, import_vuu_utils3.isMultiClauseFilter)(__privateGet(this, _filter))) {
3140
+ } else if ((0, import_vuu_utils.isMultiClauseFilter)(__privateGet(this, _filter))) {
3851
3141
  __privateGet(this, _filter).filters.push(filter);
3852
3142
  } else {
3853
3143
  throw Error(`Invalid filter passed to FilterExpression`);
3854
3144
  }
3855
3145
  }
3856
3146
  setColumn(column, filter = __privateGet(this, _filter)) {
3857
- if ((0, import_vuu_utils3.isMultiClauseFilter)(filter)) {
3147
+ if ((0, import_vuu_utils.isMultiClauseFilter)(filter)) {
3858
3148
  const target = filter.filters.at(-1);
3859
3149
  if (target) {
3860
3150
  this.setColumn(column, target);
@@ -3864,7 +3154,7 @@ var FilterExpression = class {
3864
3154
  }
3865
3155
  }
3866
3156
  setOp(value, filter = __privateGet(this, _filter)) {
3867
- if ((0, import_vuu_utils3.isMultiClauseFilter)(filter)) {
3157
+ if ((0, import_vuu_utils.isMultiClauseFilter)(filter)) {
3868
3158
  const target = filter.filters.at(-1);
3869
3159
  if (target) {
3870
3160
  this.setOp(value, target);
@@ -3875,15 +3165,15 @@ var FilterExpression = class {
3875
3165
  }
3876
3166
  setValue(value, filter = __privateGet(this, _filter)) {
3877
3167
  var _a;
3878
- if ((0, import_vuu_utils3.isMultiClauseFilter)(filter)) {
3168
+ if ((0, import_vuu_utils.isMultiClauseFilter)(filter)) {
3879
3169
  const target = filter.filters.at(-1);
3880
3170
  if (target) {
3881
3171
  this.setValue(value, target);
3882
3172
  }
3883
- } else if ((0, import_vuu_utils3.isMultiValueFilter)(filter)) {
3173
+ } else if ((0, import_vuu_utils.isMultiValueFilter)(filter)) {
3884
3174
  (_a = filter.values) != null ? _a : filter.values = [];
3885
3175
  filter.values.push(value);
3886
- } else if ((0, import_vuu_utils3.isSingleValueFilter)(filter)) {
3176
+ } else if ((0, import_vuu_utils.isSingleValueFilter)(filter)) {
3887
3177
  filter.value = value;
3888
3178
  }
3889
3179
  }
@@ -3947,7 +3237,7 @@ var strictParser = parser.configure({ strict: true });
3947
3237
 
3948
3238
  // src/filter-input/useCodeMirrorEditor.ts
3949
3239
  var import_classnames = __toESM(require_classnames(), 1);
3950
- var import_react7 = require("react");
3240
+ var import_react2 = require("react");
3951
3241
 
3952
3242
  // src/filter-input/FilterLanguage.ts
3953
3243
  var import_vuu_codemirror = require("@vuu-ui/vuu-codemirror");
@@ -4052,7 +3342,7 @@ var vuuTheme = import_vuu_codemirror3.EditorView.theme(
4052
3342
 
4053
3343
  // src/filter-input/useFilterAutoComplete.ts
4054
3344
  var import_vuu_codemirror4 = require("@vuu-ui/vuu-codemirror");
4055
- var import_react6 = require("react");
3345
+ var import_react = require("react");
4056
3346
  var getOperator = (node, state) => {
4057
3347
  let maybeColumnNode = node.prevSibling || node.parent;
4058
3348
  while (maybeColumnNode && !["Column", "Operator", "In"].includes(maybeColumnNode.name)) {
@@ -4122,7 +3412,7 @@ var getSetValues = (node, state) => {
4122
3412
  return values;
4123
3413
  };
4124
3414
  var useAutoComplete = (suggestionProvider, onSubmit, existingFilter) => {
4125
- const makeSuggestions = (0, import_react6.useCallback)(
3415
+ const makeSuggestions = (0, import_react.useCallback)(
4126
3416
  async (context, suggestionType, optionalArgs = {}) => {
4127
3417
  const { startsWith = "" } = optionalArgs;
4128
3418
  const options = await suggestionProvider.getSuggestions(
@@ -4133,7 +3423,7 @@ var useAutoComplete = (suggestionProvider, onSubmit, existingFilter) => {
4133
3423
  },
4134
3424
  [suggestionProvider]
4135
3425
  );
4136
- return (0, import_react6.useCallback)(
3426
+ return (0, import_react.useCallback)(
4137
3427
  async (context) => {
4138
3428
  var _a, _b;
4139
3429
  const { state, pos } = context;
@@ -4317,15 +3607,15 @@ var useCodeMirrorEditor = ({
4317
3607
  onSubmitFilter,
4318
3608
  suggestionProvider
4319
3609
  }) => {
4320
- const editorRef = (0, import_react7.useRef)(null);
4321
- const onSubmit = (0, import_react7.useRef)(noop);
4322
- const viewRef = (0, import_react7.useRef)();
3610
+ const editorRef = (0, import_react2.useRef)(null);
3611
+ const onSubmit = (0, import_react2.useRef)(noop);
3612
+ const viewRef = (0, import_react2.useRef)();
4323
3613
  const completionFn = useAutoComplete(
4324
3614
  suggestionProvider,
4325
3615
  onSubmit,
4326
3616
  existingFilter
4327
3617
  );
4328
- const [createState, clearInput] = (0, import_react7.useMemo)(() => {
3618
+ const [createState, clearInput] = (0, import_react2.useMemo)(() => {
4329
3619
  const parseFilter2 = () => {
4330
3620
  const view = getView(viewRef);
4331
3621
  const source = view.state.doc.toString();
@@ -4400,7 +3690,7 @@ var useCodeMirrorEditor = ({
4400
3690
  };
4401
3691
  return [createState2, clearInput2];
4402
3692
  }, [completionFn, onSubmitFilter]);
4403
- (0, import_react7.useEffect)(() => {
3693
+ (0, import_react2.useEffect)(() => {
4404
3694
  if (!editorRef.current) {
4405
3695
  throw Error("editor not in dom");
4406
3696
  }
@@ -4417,7 +3707,7 @@ var useCodeMirrorEditor = ({
4417
3707
  };
4418
3708
 
4419
3709
  // src/filter-input/FilterInput.tsx
4420
- var import_jsx_runtime7 = require("react/jsx-runtime");
3710
+ var import_jsx_runtime = require("react/jsx-runtime");
4421
3711
  var classBase = "vuuFilterInput";
4422
3712
  var FilterInput = ({
4423
3713
  existingFilter,
@@ -4432,18 +3722,18 @@ var FilterInput = ({
4432
3722
  onSubmitFilter,
4433
3723
  suggestionProvider
4434
3724
  });
4435
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { ...props, className: classBase, children: [
4436
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4437
- import_core2.Button,
3725
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { ...props, className: classBase, children: [
3726
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
3727
+ import_core.Button,
4438
3728
  {
4439
3729
  className: `${classBase}-FilterButton`,
4440
3730
  "data-icon": iconName,
4441
3731
  tabIndex: -1
4442
3732
  }
4443
3733
  ),
4444
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: `${classBase}-Editor`, ref: editorRef }),
4445
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4446
- import_core2.Button,
3734
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: `${classBase}-Editor`, ref: editorRef }),
3735
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
3736
+ import_core.Button,
4447
3737
  {
4448
3738
  className: `${classBase}-ClearButton`,
4449
3739
  "data-icon": "close-circle",
@@ -4455,17 +3745,17 @@ var FilterInput = ({
4455
3745
 
4456
3746
  // src/filter-input/useFilterSuggestionProvider.ts
4457
3747
  var import_vuu_codemirror6 = require("@vuu-ui/vuu-codemirror");
4458
- var import_vuu_data_react2 = require("@vuu-ui/vuu-data-react");
4459
- var import_react8 = require("react");
3748
+ var import_vuu_data_react = require("@vuu-ui/vuu-data-react");
3749
+ var import_react3 = require("react");
4460
3750
 
4461
3751
  // src/filter-input/filterInfo.ts
4462
- var import_vuu_utils4 = require("@vuu-ui/vuu-utils");
3752
+ var import_vuu_utils2 = require("@vuu-ui/vuu-utils");
4463
3753
  var filterInfo = (filterName, filterQuery) => {
4464
- const rootElement = (0, import_vuu_utils4.createEl)("div", "vuuFunctionDoc");
4465
- const headingElement = (0, import_vuu_utils4.createEl)("div", "function-heading");
4466
- const nameElement = (0, import_vuu_utils4.createEl)("span", "function-name", filterName);
3754
+ const rootElement = (0, import_vuu_utils2.createEl)("div", "vuuFunctionDoc");
3755
+ const headingElement = (0, import_vuu_utils2.createEl)("div", "function-heading");
3756
+ const nameElement = (0, import_vuu_utils2.createEl)("span", "function-name", filterName);
4467
3757
  headingElement.appendChild(nameElement);
4468
- const child2 = (0, import_vuu_utils4.createEl)("p", void 0, filterQuery);
3758
+ const child2 = (0, import_vuu_utils2.createEl)("p", void 0, filterQuery);
4469
3759
  rootElement.appendChild(headingElement);
4470
3760
  rootElement.appendChild(child2);
4471
3761
  return rootElement;
@@ -4550,11 +3840,11 @@ var useFilterSuggestionProvider = ({
4550
3840
  namedFilters,
4551
3841
  saveOptions = defaultSaveOptions,
4552
3842
  table,
4553
- typeaheadHook: useTypeahead = import_vuu_data_react2.useTypeaheadSuggestions
3843
+ typeaheadHook: useTypeahead = import_vuu_data_react.useTypeaheadSuggestions
4554
3844
  }) => {
4555
- const latestSuggestionsRef = (0, import_react8.useRef)();
3845
+ const latestSuggestionsRef = (0, import_react3.useRef)();
4556
3846
  const getTypeaheadSuggestions = useTypeahead();
4557
- const getSuggestions = (0, import_react8.useCallback)(
3847
+ const getSuggestions = (0, import_react3.useCallback)(
4558
3848
  async (suggestionType, options = NONE) => {
4559
3849
  const {
4560
3850
  columnName,
@@ -4602,7 +3892,7 @@ var useFilterSuggestionProvider = ({
4602
3892
  );
4603
3893
  }
4604
3894
  const prefix = Array.isArray(selection) ? selection.length === 0 ? "[" : "," : "";
4605
- const params = (0, import_vuu_data_react2.getTypeaheadParams)(
3895
+ const params = (0, import_vuu_data_react.getTypeaheadParams)(
4606
3896
  table,
4607
3897
  columnName,
4608
3898
  startsWith
@@ -4644,7 +3934,7 @@ var useFilterSuggestionProvider = ({
4644
3934
  },
4645
3935
  [columns, getTypeaheadSuggestions, namedFilters, saveOptions, table]
4646
3936
  );
4647
- const isPartialMatch = (0, import_react8.useCallback)(
3937
+ const isPartialMatch = (0, import_react3.useCallback)(
4648
3938
  async (valueType, columnName, pattern) => {
4649
3939
  const suggestions = (
4650
3940
  // latestSuggestions && latestSuggestions.length > 0
@@ -4664,204 +3954,486 @@ var useFilterSuggestionProvider = ({
4664
3954
  },
4665
3955
  [getSuggestions]
4666
3956
  );
4667
- return {
4668
- getSuggestions,
4669
- isPartialMatch
4670
- };
3957
+ return {
3958
+ getSuggestions,
3959
+ isPartialMatch
3960
+ };
3961
+ };
3962
+
3963
+ // src/filter-toolbar/FilterToolbar.tsx
3964
+ var import_salt_lab4 = require("@heswell/salt-lab");
3965
+ var import_classnames2 = __toESM(require_classnames(), 1);
3966
+
3967
+ // src/filter-toolbar/useFilterToolbar.tsx
3968
+ var import_vuu_utils3 = require("@vuu-ui/vuu-utils");
3969
+ var import_salt_lab3 = require("@heswell/salt-lab");
3970
+
3971
+ // src/filter-toolbar/FilterDropdown.tsx
3972
+ var import_salt_lab = require("@heswell/salt-lab");
3973
+ var import_react4 = require("react");
3974
+ var import_jsx_runtime2 = require("react/jsx-runtime");
3975
+ var isString = (s) => typeof s === "string";
3976
+ var stripQuotes = (selected) => {
3977
+ if (isString(selected)) {
3978
+ if (selected.startsWith('"') && selected.endsWith('"')) {
3979
+ return selected.slice(1, -1);
3980
+ } else {
3981
+ return selected;
3982
+ }
3983
+ } else {
3984
+ return selected.map(stripQuotes);
3985
+ }
3986
+ };
3987
+ var FilterDropdown = ({
3988
+ column,
3989
+ selected: selectedProp,
3990
+ suggestionProvider,
3991
+ ...props
3992
+ }) => {
3993
+ const selected = selectedProp != null ? stripQuotes(selectedProp) : void 0;
3994
+ const initialValues = Array.isArray(selected) ? selected : selected != null ? [selected] : [];
3995
+ const [values, setValues] = (0, import_react4.useState)(initialValues);
3996
+ console.log({ initialValues });
3997
+ const handleOpenChange = (0, import_react4.useCallback)(
3998
+ async (isOpen) => {
3999
+ if (isOpen) {
4000
+ const values2 = await suggestionProvider.getSuggestions("columnValue", {
4001
+ columnName: column
4002
+ });
4003
+ console.log({ values: values2 });
4004
+ setValues(values2.map((suggestion) => suggestion.label));
4005
+ }
4006
+ },
4007
+ [column, suggestionProvider]
4008
+ );
4009
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
4010
+ import_salt_lab.Dropdown,
4011
+ {
4012
+ ...props,
4013
+ onOpenChange: handleOpenChange,
4014
+ selected,
4015
+ source: values
4016
+ }
4017
+ );
4018
+ };
4019
+
4020
+ // src/filter-toolbar/FilterDropdownMultiSelect.tsx
4021
+ var import_salt_lab2 = require("@heswell/salt-lab");
4022
+ var import_react5 = require("react");
4023
+ var import_jsx_runtime3 = require("react/jsx-runtime");
4024
+ var isString2 = (s) => typeof s === "string";
4025
+ var stripQuotes2 = (selected) => {
4026
+ if (selected === void 0) {
4027
+ return void 0;
4028
+ } else if (isString2(selected)) {
4029
+ if (selected.startsWith('"') && selected.endsWith('"')) {
4030
+ return selected.slice(1, -1);
4031
+ } else {
4032
+ return selected;
4033
+ }
4034
+ } else {
4035
+ return selected.map(stripQuotes2);
4036
+ }
4037
+ };
4038
+ var FilterDropdownMultiSelect = ({
4039
+ column,
4040
+ selected: selectedProp,
4041
+ suggestionProvider,
4042
+ ...props
4043
+ }) => {
4044
+ const selected = stripQuotes2(selectedProp);
4045
+ const initialValues = Array.isArray(selected) ? selected : selected != null ? [selected] : [];
4046
+ const [values, setValues] = (0, import_react5.useState)(initialValues);
4047
+ const handleOpenChange = (0, import_react5.useCallback)(
4048
+ async (isOpen) => {
4049
+ if (isOpen) {
4050
+ const values2 = await suggestionProvider.getSuggestions("columnValue", {
4051
+ columnName: column
4052
+ });
4053
+ console.log({ values: values2 });
4054
+ setValues(values2.map((suggestion) => suggestion.label));
4055
+ }
4056
+ },
4057
+ [column, suggestionProvider]
4058
+ );
4059
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
4060
+ import_salt_lab2.Dropdown,
4061
+ {
4062
+ ...props,
4063
+ onOpenChange: handleOpenChange,
4064
+ selected,
4065
+ selectionStrategy: "multiple",
4066
+ source: values
4067
+ }
4068
+ );
4069
+ };
4070
+
4071
+ // src/filter-toolbar/useFilterToolbar.tsx
4072
+ var import_jsx_runtime4 = require("react/jsx-runtime");
4073
+ var filterToControl = (filter, suggestionProvider) => {
4074
+ if ((0, import_vuu_utils3.isNamedFilter)(filter)) {
4075
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
4076
+ import_salt_lab3.ToggleButton,
4077
+ {
4078
+ className: "vuuToggleButton",
4079
+ toggled: true,
4080
+ variant: "secondary",
4081
+ children: filter.name
4082
+ }
4083
+ );
4084
+ }
4085
+ if ((0, import_vuu_utils3.isSingleValueFilter)(filter)) {
4086
+ const { column, value } = filter;
4087
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
4088
+ import_salt_lab3.ToolbarField,
4089
+ {
4090
+ className: "vuuFilterDropdown",
4091
+ label: column,
4092
+ labelPlacement: "top",
4093
+ children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
4094
+ FilterDropdown,
4095
+ {
4096
+ column,
4097
+ selected: value.toString(),
4098
+ selectionStrategy: "default",
4099
+ source: [value.toString()],
4100
+ suggestionProvider,
4101
+ style: { width: 100 }
4102
+ }
4103
+ )
4104
+ },
4105
+ column
4106
+ );
4107
+ }
4108
+ if ((0, import_vuu_utils3.isMultiValueFilter)(filter)) {
4109
+ const values = filter.values.map((v) => v.toString());
4110
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
4111
+ import_salt_lab3.ToolbarField,
4112
+ {
4113
+ className: "vuuFilterDropdown",
4114
+ label: filter.column,
4115
+ labelPlacement: "top",
4116
+ children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
4117
+ FilterDropdownMultiSelect,
4118
+ {
4119
+ column: filter.column,
4120
+ selected: values,
4121
+ source: values,
4122
+ suggestionProvider,
4123
+ style: { width: 100 }
4124
+ }
4125
+ )
4126
+ },
4127
+ filter.column
4128
+ );
4129
+ }
4130
+ return filter.filters.map(
4131
+ (filter2) => filterToControl(filter2, suggestionProvider)
4132
+ );
4133
+ };
4134
+ var useFilterToolbar = ({
4135
+ filter,
4136
+ suggestionProvider
4137
+ }) => {
4138
+ if (filter) {
4139
+ return filterToControl(filter, suggestionProvider);
4140
+ }
4141
+ return [];
4142
+ };
4143
+
4144
+ // src/filter-toolbar/FilterToolbar.tsx
4145
+ var import_jsx_runtime5 = require("react/jsx-runtime");
4146
+ var FilterToolbar = ({
4147
+ className,
4148
+ filter,
4149
+ suggestionProvider,
4150
+ ...props
4151
+ }) => {
4152
+ console.log(`FilterToolbar ${JSON.stringify(filter, null, 2)}`);
4153
+ const toolbarItems = useFilterToolbar({ filter, suggestionProvider });
4154
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_salt_lab4.Toolbar, { className: (0, import_classnames2.default)("vuuFilterToolbar", className), ...props, children: toolbarItems });
4155
+ };
4156
+
4157
+ // src/filter-utils.ts
4158
+ var import_vuu_utils4 = require("@vuu-ui/vuu-utils");
4159
+ var AND = "and";
4160
+ var EQUALS = "=";
4161
+ var GREATER_THAN = ">";
4162
+ var LESS_THAN = "<";
4163
+ var OR = "or";
4164
+ var STARTS_WITH = "starts";
4165
+ var ENDS_WITH = "ends";
4166
+ var IN = "in";
4167
+ var filterClauses = (filter, clauses = []) => {
4168
+ if (filter) {
4169
+ if ((0, import_vuu_utils4.isMultiClauseFilter)(filter)) {
4170
+ filter.filters.forEach((f) => clauses.push(...filterClauses(f)));
4171
+ } else {
4172
+ clauses.push(filter);
4173
+ }
4174
+ }
4175
+ return clauses;
4176
+ };
4177
+ var DEFAULT_ADD_FILTER_OPTS = {
4178
+ combineWith: "and"
4179
+ };
4180
+ var addFilter = (existingFilter, filter, { combineWith = AND } = DEFAULT_ADD_FILTER_OPTS) => {
4181
+ var _a;
4182
+ if (includesNoValues(filter)) {
4183
+ if ((0, import_vuu_utils4.isMultiClauseFilter)(filter)) {
4184
+ } else {
4185
+ existingFilter = removeFilterForColumn(existingFilter, {
4186
+ name: filter.column
4187
+ });
4188
+ }
4189
+ } else if (includesAllValues(filter)) {
4190
+ if ((0, import_vuu_utils4.isMultiClauseFilter)(filter)) {
4191
+ }
4192
+ return removeFilterForColumn(existingFilter, { name: (_a = filter.column) != null ? _a : "" });
4193
+ }
4194
+ if (!existingFilter) {
4195
+ return filter;
4196
+ }
4197
+ if (!filter) {
4198
+ return existingFilter;
4199
+ }
4200
+ if (existingFilter.op === AND && filter.op === AND) {
4201
+ return {
4202
+ op: AND,
4203
+ filters: combine(existingFilter.filters, filter.filters)
4204
+ };
4205
+ }
4206
+ if (existingFilter.op === AND) {
4207
+ const filters = replaceOrInsert(existingFilter.filters, filter);
4208
+ return filters.length > 1 ? { op: AND, filters } : filters[0];
4209
+ }
4210
+ if (filter.op === AND) {
4211
+ return { op: AND, filters: filter.filters.concat(existingFilter) };
4212
+ }
4213
+ if (filterEquals(existingFilter, filter, true)) {
4214
+ return filter;
4215
+ }
4216
+ if (canMerge(existingFilter, filter)) {
4217
+ return merge(existingFilter, filter);
4218
+ }
4219
+ return { op: combineWith, filters: [existingFilter, filter] };
4220
+ };
4221
+ var includesNoValues = (filter) => {
4222
+ if (!filter) {
4223
+ return false;
4224
+ }
4225
+ if ((0, import_vuu_utils4.isInFilter)(filter) && filter.values.length === 0) {
4226
+ return true;
4227
+ }
4228
+ return (0, import_vuu_utils4.isAndFilter)(filter) && filter.filters.some((f) => includesNoValues(f));
4229
+ };
4230
+ var includesAllValues = (filter) => {
4231
+ if (!filter) {
4232
+ return false;
4233
+ }
4234
+ if (filter.op === STARTS_WITH && filter.value === "") {
4235
+ return true;
4236
+ }
4237
+ return filter.op === STARTS_WITH && filter.value === "";
4238
+ };
4239
+ var replaceOrInsert = (filters, filter) => {
4240
+ return filters.concat(filter);
4241
+ };
4242
+ var merge = (f1, f2) => {
4243
+ if (includesNoValues(f2)) {
4244
+ return f2;
4245
+ }
4246
+ if ((0, import_vuu_utils4.isInFilter)(f1) && (0, import_vuu_utils4.isInFilter)(f2)) {
4247
+ return {
4248
+ ...f1,
4249
+ values: [
4250
+ ...f1.values,
4251
+ ...f2.values.filter(
4252
+ (v) => !f1.values.includes(v)
4253
+ )
4254
+ ]
4255
+ };
4256
+ } else if ((0, import_vuu_utils4.isInFilter)(f1) && f2.op === EQUALS) {
4257
+ return {
4258
+ ...f1,
4259
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
4260
+ // @ts-ignore
4261
+ values: f1.values.concat([f2.value])
4262
+ };
4263
+ } else if (f1.op === EQUALS && f2.op === EQUALS) {
4264
+ return {
4265
+ column: f1.column,
4266
+ op: IN,
4267
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
4268
+ // @ts-ignore
4269
+ values: [f1.value, f2.value]
4270
+ };
4271
+ }
4272
+ return f2;
4273
+ };
4274
+ var combine = (existingFilters, replacementFilters) => {
4275
+ const equivalentType = ({ op: t1 }, { op: t2 }) => {
4276
+ return t1 === t2 || t1[0] === t2[0];
4277
+ };
4278
+ const replaces = (existingFilter, replacementFilter) => {
4279
+ return existingFilter.column === replacementFilter.column && equivalentType(existingFilter, replacementFilter);
4280
+ };
4281
+ const stillApplicable = (existingFilter) => replacementFilters.some(
4282
+ (replacementFilter) => replaces(existingFilter, replacementFilter)
4283
+ ) === false;
4284
+ return existingFilters.filter(stillApplicable).concat(replacementFilters);
4285
+ };
4286
+ var removeFilter = (sourceFilter, filterToRemove) => {
4287
+ if (filterEquals(sourceFilter, filterToRemove, true)) {
4288
+ return null;
4289
+ }
4290
+ if (sourceFilter.op !== AND) {
4291
+ throw Error(
4292
+ `removeFilter cannot remove ${JSON.stringify(
4293
+ filterToRemove
4294
+ )} from ${JSON.stringify(sourceFilter)}`
4295
+ );
4296
+ }
4297
+ const filters = sourceFilter.filters.filter(
4298
+ (f) => !filterEquals(f, filterToRemove)
4299
+ );
4300
+ return filters.length > 0 ? { type: AND, filters } : null;
4301
+ };
4302
+ var splitFilterOnColumn = (columnName, filter) => {
4303
+ if (!filter) {
4304
+ return [void 0, void 0];
4305
+ }
4306
+ if (filter.column === columnName) {
4307
+ return [filter, void 0];
4308
+ }
4309
+ if (filter.op !== AND) {
4310
+ return [void 0, filter];
4311
+ }
4312
+ const [[columnFilter = void 0], filters] = (0, import_vuu_utils4.partition)(
4313
+ filter.filters,
4314
+ (f) => f.column === columnName
4315
+ );
4316
+ return filters.length === 1 ? [columnFilter, filters[0]] : [columnFilter, { op: AND, filters }];
4671
4317
  };
4672
-
4673
- // src/filter-toolbar/FilterToolbar.tsx
4674
- var import_salt_lab8 = require("@heswell/salt-lab");
4675
- var import_classnames2 = __toESM(require_classnames(), 1);
4676
-
4677
- // src/filter-toolbar/useFilterToolbar.tsx
4678
- var import_vuu_utils5 = require("@vuu-ui/vuu-utils");
4679
- var import_salt_lab7 = require("@heswell/salt-lab");
4680
-
4681
- // src/filter-toolbar/FilterDropdown.tsx
4682
- var import_salt_lab5 = require("@heswell/salt-lab");
4683
- var import_react9 = require("react");
4684
- var import_jsx_runtime8 = require("react/jsx-runtime");
4685
- var isString = (s) => typeof s === "string";
4686
- var stripQuotes = (selected) => {
4687
- if (isString(selected)) {
4688
- if (selected.startsWith('"') && selected.endsWith('"')) {
4689
- return selected.slice(1, -1);
4690
- } else {
4691
- return selected;
4692
- }
4693
- } else {
4694
- return selected.map(stripQuotes);
4318
+ var overrideColName = (filter, column) => {
4319
+ if ((0, import_vuu_utils4.isMultiClauseFilter)(filter)) {
4320
+ return {
4321
+ op: filter.op,
4322
+ filters: filter.filters.map((f) => overrideColName(f, column))
4323
+ };
4695
4324
  }
4325
+ return { ...filter, column };
4696
4326
  };
4697
- var FilterDropdown = ({
4698
- column,
4699
- selected: selectedProp,
4700
- suggestionProvider,
4701
- ...props
4702
- }) => {
4703
- const selected = selectedProp != null ? stripQuotes(selectedProp) : void 0;
4704
- const initialValues = Array.isArray(selected) ? selected : selected != null ? [selected] : [];
4705
- const [values, setValues] = (0, import_react9.useState)(initialValues);
4706
- console.log({ initialValues });
4707
- const handleOpenChange = (0, import_react9.useCallback)(
4708
- async (isOpen) => {
4709
- if (isOpen) {
4710
- const values2 = await suggestionProvider.getSuggestions("columnValue", {
4711
- columnName: column
4712
- });
4713
- console.log({ values: values2 });
4714
- setValues(values2.map((suggestion) => suggestion.label));
4715
- }
4716
- },
4717
- [column, suggestionProvider]
4718
- );
4719
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
4720
- import_salt_lab5.Dropdown,
4721
- {
4722
- ...props,
4723
- onOpenChange: handleOpenChange,
4724
- selected,
4725
- source: values
4726
- }
4727
- );
4327
+ var filterIncludesColumn = (filter, column) => {
4328
+ if (!filter) {
4329
+ return false;
4330
+ }
4331
+ const { op, column: filterColName } = filter;
4332
+ switch (op) {
4333
+ case AND:
4334
+ case OR:
4335
+ return filter.filters != null && filter.filters.some((f) => filterIncludesColumn(f, column));
4336
+ default:
4337
+ return filterColName === column.name;
4338
+ }
4728
4339
  };
4729
-
4730
- // src/filter-toolbar/FilterDropdownMultiSelect.tsx
4731
- var import_salt_lab6 = require("@heswell/salt-lab");
4732
- var import_react10 = require("react");
4733
- var import_jsx_runtime9 = require("react/jsx-runtime");
4734
- var isString2 = (s) => typeof s === "string";
4735
- var stripQuotes2 = (selected) => {
4736
- if (selected === void 0) {
4340
+ var removeFilterForColumn = (sourceFilter, column) => {
4341
+ const colName = column.name;
4342
+ if (!sourceFilter) {
4737
4343
  return void 0;
4738
- } else if (isString2(selected)) {
4739
- if (selected.startsWith('"') && selected.endsWith('"')) {
4740
- return selected.slice(1, -1);
4741
- } else {
4742
- return selected;
4344
+ }
4345
+ if (sourceFilter.column === colName) {
4346
+ return void 0;
4347
+ }
4348
+ if ((0, import_vuu_utils4.isAndFilter)(sourceFilter) || (0, import_vuu_utils4.isOrFilter)(sourceFilter)) {
4349
+ const { op } = sourceFilter;
4350
+ const filters = sourceFilter.filters;
4351
+ const otherColFilters = filters.filter((f) => f.column !== colName);
4352
+ switch (otherColFilters.length) {
4353
+ case 0:
4354
+ return void 0;
4355
+ case 1:
4356
+ return otherColFilters[0];
4357
+ default:
4358
+ return { op, filters: otherColFilters };
4743
4359
  }
4744
- } else {
4745
- return selected.map(stripQuotes2);
4746
4360
  }
4361
+ return sourceFilter;
4747
4362
  };
4748
- var FilterDropdownMultiSelect = ({
4749
- column,
4750
- selected: selectedProp,
4751
- suggestionProvider,
4752
- ...props
4753
- }) => {
4754
- const selected = stripQuotes2(selectedProp);
4755
- const initialValues = Array.isArray(selected) ? selected : selected != null ? [selected] : [];
4756
- const [values, setValues] = (0, import_react10.useState)(initialValues);
4757
- const handleOpenChange = (0, import_react10.useCallback)(
4758
- async (isOpen) => {
4759
- if (isOpen) {
4760
- const values2 = await suggestionProvider.getSuggestions("columnValue", {
4761
- columnName: column
4762
- });
4763
- console.log({ values: values2 });
4764
- setValues(values2.map((suggestion) => suggestion.label));
4765
- }
4766
- },
4767
- [column, suggestionProvider]
4768
- );
4769
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
4770
- import_salt_lab6.Dropdown,
4771
- {
4772
- ...props,
4773
- onOpenChange: handleOpenChange,
4774
- selected,
4775
- selectionStrategy: "multiple",
4776
- source: values
4777
- }
4778
- );
4363
+ var canMerge = (f1, f2) => f1.column === f2.column && (f1.op === "=" || f1.op === "in") && (f2.op === "=" || f2.op === "in");
4364
+ var sameValues = (arr1, arr2) => {
4365
+ if (arr1 === arr2) {
4366
+ return true;
4367
+ }
4368
+ if (arr1.length === arr2.length) {
4369
+ const a = arr1.slice().sort();
4370
+ const b = arr2.slice().sort();
4371
+ return a.join("|") === b.join("|");
4372
+ }
4373
+ return false;
4779
4374
  };
4780
-
4781
- // src/filter-toolbar/useFilterToolbar.tsx
4782
- var import_jsx_runtime10 = require("react/jsx-runtime");
4783
- var filterToControl = (filter, suggestionProvider) => {
4784
- if ((0, import_vuu_utils5.isNamedFilter)(filter)) {
4785
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
4786
- import_salt_lab7.ToggleButton,
4787
- {
4788
- className: "vuuToggleButton",
4789
- toggled: true,
4790
- variant: "secondary",
4791
- children: filter.name
4792
- }
4793
- );
4375
+ var filterEquals = (f1, f2, strict = false) => {
4376
+ if (!strict) {
4377
+ return true;
4794
4378
  }
4795
- if ((0, import_vuu_utils5.isSingleValueFilter)(filter)) {
4796
- const { column, value } = filter;
4797
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
4798
- import_salt_lab7.ToolbarField,
4799
- {
4800
- className: "vuuFilterDropdown",
4801
- label: column,
4802
- labelPlacement: "top",
4803
- children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
4804
- FilterDropdown,
4805
- {
4806
- column,
4807
- selected: value.toString(),
4808
- selectionStrategy: "default",
4809
- source: [value.toString()],
4810
- suggestionProvider,
4811
- style: { width: 100 }
4812
- }
4813
- )
4814
- },
4815
- column
4816
- );
4379
+ if (f1 && f2 && canMerge(f1, f2)) {
4380
+ return f1.op === f2.op && ((0, import_vuu_utils4.isSingleValueFilter)(f1) && (0, import_vuu_utils4.isSingleValueFilter)(f2) && f1.value === f2.value || (0, import_vuu_utils4.isMultiValueFilter)(f1) && (0, import_vuu_utils4.isMultiValueFilter)(f2) && sameValues(f1.values, f2.values));
4817
4381
  }
4818
- if ((0, import_vuu_utils5.isMultiValueFilter)(filter)) {
4819
- const values = filter.values.map((v) => v.toString());
4820
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
4821
- import_salt_lab7.ToolbarField,
4822
- {
4823
- className: "vuuFilterDropdown",
4824
- label: filter.column,
4825
- labelPlacement: "top",
4826
- children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
4827
- FilterDropdownMultiSelect,
4828
- {
4829
- column: filter.column,
4830
- selected: values,
4831
- source: values,
4832
- suggestionProvider,
4833
- style: { width: 100 }
4834
- }
4835
- )
4836
- },
4837
- filter.column
4838
- );
4382
+ return false;
4383
+ };
4384
+ var updateFilter = (filter, newFilter, mode) => {
4385
+ if (filter && newFilter) {
4386
+ if (mode === "replace") {
4387
+ return newFilter;
4388
+ }
4389
+ if (filter.op === "and") {
4390
+ return {
4391
+ ...filter,
4392
+ filters: filter.filters.concat(newFilter)
4393
+ };
4394
+ }
4395
+ const { column: columnName } = newFilter;
4396
+ if (columnName) {
4397
+ const existingClause = newFilter.column ? (0, import_vuu_utils4.extractFilterForColumn)(filter, columnName) : void 0;
4398
+ if (existingClause && columnName) {
4399
+ const result = removeFilterForColumn(filter, { name: columnName });
4400
+ return updateFilter(result, newFilter, "add");
4401
+ }
4402
+ }
4403
+ return {
4404
+ op: "and",
4405
+ filters: [filter, newFilter]
4406
+ };
4839
4407
  }
4840
- return filter.filters.map(
4841
- (filter2) => filterToControl(filter2, suggestionProvider)
4842
- );
4408
+ if (newFilter) {
4409
+ return newFilter;
4410
+ }
4411
+ return filter;
4843
4412
  };
4844
- var useFilterToolbar = ({
4845
- filter,
4846
- suggestionProvider
4847
- }) => {
4848
- if (filter) {
4849
- return filterToControl(filter, suggestionProvider);
4413
+ var getTypeaheadFilter = (column, filterValues, isStartsWithFilter) => {
4414
+ if (filterValues.length === 0) {
4415
+ return void 0;
4850
4416
  }
4851
- return [];
4417
+ if (isStartsWithFilter) {
4418
+ const startsWith = filterValues[0].substring(0, filterValues[0].length - 3);
4419
+ return {
4420
+ column,
4421
+ op: "starts",
4422
+ value: `"${startsWith}"`
4423
+ };
4424
+ }
4425
+ return {
4426
+ column,
4427
+ op: "in",
4428
+ values: filterValues.map((value) => `"${value}"`)
4429
+ };
4852
4430
  };
4853
-
4854
- // src/filter-toolbar/FilterToolbar.tsx
4855
- var import_jsx_runtime11 = require("react/jsx-runtime");
4856
- var FilterToolbar = ({
4857
- className,
4858
- filter,
4859
- suggestionProvider,
4860
- ...props
4861
- }) => {
4862
- console.log(`FilterToolbar ${JSON.stringify(filter, null, 2)}`);
4863
- const toolbarItems = useFilterToolbar({ filter, suggestionProvider });
4864
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_salt_lab8.Toolbar, { className: (0, import_classnames2.default)("vuuFilterToolbar", className), ...props, children: toolbarItems });
4431
+ var getNumericFilter = (column, operator, value) => {
4432
+ if (operator === void 0)
4433
+ return void 0;
4434
+ if (value === void 0 || isNaN(value))
4435
+ return void 0;
4436
+ return { column, op: operator, value };
4865
4437
  };
4866
4438
  /*! Bundled license information:
4867
4439