@bpmn-io/form-js-playground 1.19.0 → 1.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -30837,16 +30837,16 @@
30837
30837
  }
30838
30838
  }
30839
30839
  }
30840
- function scrollableParents(dom) {
30840
+ function scrollableParents(dom, getX = true) {
30841
30841
  let doc = dom.ownerDocument,
30842
- x,
30843
- y;
30842
+ x = null,
30843
+ y = null;
30844
30844
  for (let cur = dom.parentNode; cur;) {
30845
- if (cur == doc.body || x && y) {
30845
+ if (cur == doc.body || (!getX || x) && y) {
30846
30846
  break;
30847
30847
  } else if (cur.nodeType == 1) {
30848
30848
  if (!y && cur.scrollHeight > cur.clientHeight) y = cur;
30849
- if (!x && cur.scrollWidth > cur.clientWidth) x = cur;
30849
+ if (getX && !x && cur.scrollWidth > cur.clientWidth) x = cur;
30850
30850
  cur = cur.assignedSlot || cur.parentNode;
30851
30851
  } else if (cur.nodeType == 11) {
30852
30852
  cur = cur.host;
@@ -30975,6 +30975,7 @@
30975
30975
  }
30976
30976
  }
30977
30977
  function isScrolledToBottom(elt) {
30978
+ if (elt instanceof Window) return elt.pageYOffset > Math.max(0, elt.document.documentElement.scrollHeight - elt.innerHeight - 4);
30978
30979
  return elt.scrollTop > Math.max(1, elt.scrollHeight - elt.clientHeight - 4);
30979
30980
  }
30980
30981
  function textNodeBefore(startNode, startOffset) {
@@ -32822,7 +32823,7 @@
32822
32823
  }
32823
32824
  } else if (tile.isText()) {
32824
32825
  this.builder.ensureLine(null);
32825
- if (!from && to == tile.length) {
32826
+ if (!from && to == tile.length && !this.cache.reused.has(tile)) {
32826
32827
  this.builder.addText(tile.text, activeMarks, openMarks, this.cache.reuse(tile));
32827
32828
  } else {
32828
32829
  this.cache.add(tile);
@@ -32937,7 +32938,8 @@
32937
32938
  for (let parent = text.parentNode;; parent = parent.parentNode) {
32938
32939
  let tile = Tile.get(parent);
32939
32940
  if (parent == this.view.contentDOM) break;
32940
- if (tile instanceof MarkTile) marks.push(tile);else if (tile === null || tile === void 0 ? void 0 : tile.isLine()) line = tile;else if (parent.nodeName == "DIV" && !line && parent != this.view.contentDOM) line = new LineTile(parent, lineBaseAttrs);else marks.push(MarkTile.of(new MarkDecoration({
32941
+ if (tile instanceof MarkTile) marks.push(tile);else if (tile === null || tile === void 0 ? void 0 : tile.isLine()) line = tile;else if (tile instanceof BlockWrapperTile) ; // Ignore
32942
+ else if (parent.nodeName == "DIV" && !line && parent != this.view.contentDOM) line = new LineTile(parent, lineBaseAttrs);else if (!line) marks.push(MarkTile.of(new MarkDecoration({
32941
32943
  tagName: parent.nodeName.toLowerCase(),
32942
32944
  attributes: getAttrs(parent)
32943
32945
  }), parent));
@@ -33116,6 +33118,7 @@
33116
33118
  if (composition || changes.length) {
33117
33119
  let oldTile = this.tile;
33118
33120
  let builder = new TileUpdate(this.view, oldTile, this.blockWrappers, this.decorations, this.dynamicDecorationMap);
33121
+ if (composition && Tile.get(composition.text)) builder.cache.reused.set(Tile.get(composition.text), 2 /* Reused.DOM */);
33119
33122
  this.tile = builder.run(changes, composition);
33120
33123
  destroyDropped(oldTile, builder.cache.reused);
33121
33124
  }
@@ -33560,6 +33563,18 @@
33560
33563
  offsetHeight
33561
33564
  } = this.view.scrollDOM;
33562
33565
  scrollRectIntoView(this.view.scrollDOM, targetRect, range.head < range.anchor ? -1 : 1, target.x, target.y, Math.max(Math.min(target.xMargin, offsetWidth), -offsetWidth), Math.max(Math.min(target.yMargin, offsetHeight), -offsetHeight), this.view.textDirection == Direction.LTR);
33566
+ // On mobile browsers, the visual viewport may be smaller than the
33567
+ // actual reported viewport, causing scrollRectIntoView to fail to
33568
+ // scroll properly. Unfortunately, this visual viewport cannot be
33569
+ // updated directly, and scrollIntoView is the only way a script
33570
+ // can affect it. So this tries to kludge around the problem by
33571
+ // calling scrollIntoView on the scroll target's line.
33572
+ if (window.visualViewport && window.innerHeight - window.visualViewport.height > 1 && (rect.top > window.pageYOffset + window.visualViewport.offsetTop + window.visualViewport.height || rect.bottom < window.pageYOffset + window.visualViewport.offsetTop)) {
33573
+ let line = this.view.docView.lineAt(range.head, 1);
33574
+ if (line) line.dom.scrollIntoView({
33575
+ block: "nearest"
33576
+ });
33577
+ }
33563
33578
  }
33564
33579
  lineHasWidget(pos) {
33565
33580
  let scan = child => child.isWidget() || child.children.some(scan);
@@ -33803,7 +33818,7 @@
33803
33818
  let goal = start.goalColumn,
33804
33819
  startY;
33805
33820
  let rect = view.contentDOM.getBoundingClientRect();
33806
- let startCoords = view.coordsAtPos(startPos, start.assoc || -1),
33821
+ let startCoords = view.coordsAtPos(startPos, (start.empty ? start.assoc : 0) || (forward ? 1 : -1)),
33807
33822
  docTop = view.documentTop;
33808
33823
  if (startCoords) {
33809
33824
  if (goal == null) goal = startCoords.left - rect.left;
@@ -33886,7 +33901,7 @@
33886
33901
  if (block.type == BlockType.Text) {
33887
33902
  if (scanY < 0 ? block.to < view.viewport.from : block.from > view.viewport.to) break;
33888
33903
  // Check whether we aren't landing on the top/bottom padding of the line
33889
- let rect = view.docView.coordsAt(scanY < 0 ? block.from : block.to, scanY);
33904
+ let rect = view.docView.coordsAt(scanY < 0 ? block.from : block.to, scanY > 0 ? -1 : 1);
33890
33905
  if (rect && (scanY < 0 ? rect.top <= yOffset + docTop : rect.bottom >= yOffset + docTop)) break;
33891
33906
  }
33892
33907
  let halfLine = view.viewState.heightOracle.textHeight / 2;
@@ -33905,82 +33920,163 @@
33905
33920
  // Here we know we're in a line, so run the logic for inline layout
33906
33921
  let line = view.docView.lineAt(block.from, 2);
33907
33922
  if (!line || line.length != block.length) line = view.docView.lineAt(block.from, -2);
33908
- return posAtCoordsInline(view, line, block.from, x, y);
33923
+ return new InlineCoordsScan(view, x, y, view.textDirectionAt(block.from)).scanTile(line, block.from);
33909
33924
  }
33910
- // Scan through the rectangles for the content of a tile, finding the
33911
- // one closest to the given coordinates, prefering closeness in Y over
33912
- // closeness in X.
33913
- //
33914
- // If this is a text tile, go character-by-character. For line or mark
33915
- // tiles, check each non-point-widget child, and descend text or mark
33916
- // tiles with a recursive call.
33917
- //
33918
- // For non-wrapped, purely left-to-right text, this could use a binary
33919
- // search. But because this seems to be fast enough, for how often it
33920
- // is called, there's not currently a specialized implementation for
33921
- // that.
33922
- function posAtCoordsInline(view, tile, offset, x, y) {
33923
- let closest = -1,
33924
- closestRect = null;
33925
- let dxClosest = 1e9,
33926
- dyClosest = 1e9;
33927
- let rowTop = y,
33928
- rowBot = y;
33929
- let checkRects = (rects, index) => {
33930
- for (let i = 0; i < rects.length; i++) {
33931
- let rect = rects[i];
33932
- if (rect.top == rect.bottom) continue;
33933
- let dx = rect.left > x ? rect.left - x : rect.right < x ? x - rect.right : 0;
33934
- let dy = rect.top > y ? rect.top - y : rect.bottom < y ? y - rect.bottom : 0;
33935
- if (rect.top <= rowBot && rect.bottom >= rowTop) {
33936
- // Rectangle is in the current row
33937
- rowTop = Math.min(rect.top, rowTop);
33938
- rowBot = Math.max(rect.bottom, rowBot);
33939
- dy = 0;
33940
- }
33941
- if (closest < 0 || (dy - dyClosest || dx - dxClosest) < 0) {
33942
- if (closest >= 0 && dyClosest && dxClosest < dx && closestRect.top <= rowBot - 2 && closestRect.bottom >= rowTop + 2) {
33943
- // Retroactively set dy to 0 if the current match is in this row.
33944
- dyClosest = 0;
33925
+ class InlineCoordsScan {
33926
+ constructor(view, x, y, baseDir) {
33927
+ this.view = view;
33928
+ this.x = x;
33929
+ this.y = y;
33930
+ this.baseDir = baseDir;
33931
+ // Cached bidi info
33932
+ this.line = null;
33933
+ this.spans = null;
33934
+ }
33935
+ bidiSpansAt(pos) {
33936
+ if (!this.line || this.line.from > pos || this.line.to < pos) {
33937
+ this.line = this.view.state.doc.lineAt(pos);
33938
+ this.spans = this.view.bidiSpans(this.line);
33939
+ }
33940
+ return this;
33941
+ }
33942
+ baseDirAt(pos, side) {
33943
+ let {
33944
+ line,
33945
+ spans
33946
+ } = this.bidiSpansAt(pos);
33947
+ let level = spans[BidiSpan.find(spans, pos - line.from, -1, side)].level;
33948
+ return level == this.baseDir;
33949
+ }
33950
+ dirAt(pos, side) {
33951
+ let {
33952
+ line,
33953
+ spans
33954
+ } = this.bidiSpansAt(pos);
33955
+ return spans[BidiSpan.find(spans, pos - line.from, -1, side)].dir;
33956
+ }
33957
+ // Used to short-circuit bidi tests for content with a uniform direction
33958
+ bidiIn(from, to) {
33959
+ let {
33960
+ spans,
33961
+ line
33962
+ } = this.bidiSpansAt(from);
33963
+ return spans.length > 1 || spans.length && (spans[0].level != this.baseDir || spans[0].to + line.from < to);
33964
+ }
33965
+ // Scan through the rectangles for the content of a tile with inline
33966
+ // content, looking for one that overlaps the queried position
33967
+ // vertically andis
33968
+ // closest horizontally. The caller is responsible for dividing its
33969
+ // content into N pieces, and pass an array with N+1 positions
33970
+ // (including the position after the last piece). For a text tile,
33971
+ // these will be character clusters, for a composite tile, these
33972
+ // will be child tiles.
33973
+ scan(positions, getRects) {
33974
+ let lo = 0,
33975
+ hi = positions.length - 1,
33976
+ seen = new Set();
33977
+ let bidi = this.bidiIn(positions[0], positions[hi]);
33978
+ let above, below;
33979
+ let closestI = -1,
33980
+ closestDx = 1e9,
33981
+ closestRect;
33982
+ // Because, when the content is bidirectional, a regular binary
33983
+ // search is hard to perform (the content order does not
33984
+ // correspond to visual order), this loop does something between a
33985
+ // regular binary search and a full scan, depending on what it can
33986
+ // get away with. The outer hi/lo bounds are only adjusted for
33987
+ // elements that are part of the base order.
33988
+ //
33989
+ // To make sure all elements inside those bounds are visited,
33990
+ // eventually, we keep a set of seen indices, and if the midpoint
33991
+ // has already been handled, we start in a random index within the
33992
+ // current bounds and scan forward until we find an index that
33993
+ // hasn't been seen yet.
33994
+ search: while (lo < hi) {
33995
+ let dist = hi - lo,
33996
+ mid = lo + hi >> 1;
33997
+ adjust: if (seen.has(mid)) {
33998
+ let scan = lo + Math.floor(Math.random() * dist);
33999
+ for (let i = 0; i < dist; i++) {
34000
+ if (!seen.has(scan)) {
34001
+ mid = scan;
34002
+ break adjust;
34003
+ }
34004
+ scan++;
34005
+ if (scan == hi) scan = lo; // Wrap around
34006
+ }
34007
+ break search; // No index found, we're done
34008
+ }
34009
+ seen.add(mid);
34010
+ let rects = getRects(mid);
34011
+ if (rects) for (let i = 0; i < rects.length; i++) {
34012
+ let rect = rects[i],
34013
+ side = 0;
34014
+ if (rect.bottom < this.y) {
34015
+ if (!above || above.bottom < rect.bottom) above = rect;
34016
+ side = 1;
34017
+ } else if (rect.top > this.y) {
34018
+ if (!below || below.top > rect.top) below = rect;
34019
+ side = -1;
33945
34020
  } else {
33946
- closest = index;
33947
- dxClosest = dx;
33948
- dyClosest = dy;
33949
- closestRect = rect;
34021
+ let off = rect.left > this.x ? this.x - rect.left : rect.right < this.x ? this.x - rect.right : 0;
34022
+ let dx = Math.abs(off);
34023
+ if (dx < closestDx) {
34024
+ closestI = mid;
34025
+ closestDx = dx;
34026
+ closestRect = rect;
34027
+ }
34028
+ if (off) side = off < 0 == (this.baseDir == Direction.LTR) ? -1 : 1;
33950
34029
  }
34030
+ // Narrow binary search when it is safe to do so
34031
+ if (side == -1 && (!bidi || this.baseDirAt(positions[mid], 1))) hi = mid;else if (side == 1 && (!bidi || this.baseDirAt(positions[mid + 1], -1))) lo = mid + 1;
33951
34032
  }
33952
34033
  }
33953
- };
33954
- if (tile.isText()) {
33955
- for (let i = 0; i < tile.length;) {
33956
- let next = findClusterBreak(tile.text, i);
33957
- checkRects(textRange(tile.dom, i, next).getClientRects(), i);
33958
- if (!dxClosest && !dyClosest) break;
33959
- i = next;
33960
- }
33961
- let after = x > (closestRect.left + closestRect.right) / 2 == (dirAt(view, closest + offset) == Direction.LTR);
33962
- return after ? new PosAssoc(offset + findClusterBreak(tile.text, closest), -1) : new PosAssoc(offset + closest, 1);
33963
- } else {
34034
+ // If no element with y overlap is found, find the nearest element
34035
+ // on the y axis, move this.y into it, and retry the scan.
34036
+ if (!closestRect) {
34037
+ let side = above && (!below || this.y - above.bottom < below.top - this.y) ? above : below;
34038
+ this.y = (side.top + side.bottom) / 2;
34039
+ return this.scan(positions, getRects);
34040
+ }
34041
+ let ltr = (bidi ? this.dirAt(positions[closestI], 1) : this.baseDir) == Direction.LTR;
34042
+ return {
34043
+ i: closestI,
34044
+ // Test whether x is closes to the start or end of this element
34045
+ after: this.x > (closestRect.left + closestRect.right) / 2 == ltr
34046
+ };
34047
+ }
34048
+ scanText(tile, offset) {
34049
+ let positions = [];
34050
+ for (let i = 0; i < tile.length; i = findClusterBreak(tile.text, i)) positions.push(offset + i);
34051
+ positions.push(offset + tile.length);
34052
+ let scan = this.scan(positions, i => {
34053
+ let off = positions[i] - offset,
34054
+ end = positions[i + 1] - offset;
34055
+ return textRange(tile.dom, off, end).getClientRects();
34056
+ });
34057
+ return scan.after ? new PosAssoc(positions[scan.i + 1], -1) : new PosAssoc(positions[scan.i], 1);
34058
+ }
34059
+ scanTile(tile, offset) {
33964
34060
  if (!tile.length) return new PosAssoc(offset, 1);
33965
- for (let i = 0; i < tile.children.length; i++) {
34061
+ if (tile.children.length == 1) {
34062
+ // Short-circuit single-child tiles
34063
+ let child = tile.children[0];
34064
+ if (child.isText()) return this.scanText(child, offset);else if (child.isComposite()) return this.scanTile(child, offset);
34065
+ }
34066
+ let positions = [offset];
34067
+ for (let i = 0, pos = offset; i < tile.children.length; i++) positions.push(pos += tile.children[i].length);
34068
+ let scan = this.scan(positions, i => {
33966
34069
  let child = tile.children[i];
33967
- if (child.flags & 48 /* TileFlag.PointWidget */) continue;
33968
- let rects = (child.dom.nodeType == 1 ? child.dom : textRange(child.dom, 0, child.length)).getClientRects();
33969
- checkRects(rects, i);
33970
- if (!dxClosest && !dyClosest) break;
33971
- }
33972
- let inner = tile.children[closest],
33973
- innerOff = tile.posBefore(inner, offset);
33974
- if (inner.isComposite() || inner.isText()) return posAtCoordsInline(view, inner, innerOff, Math.max(closestRect.left, Math.min(closestRect.right, x)), y);
33975
- let after = x > (closestRect.left + closestRect.right) / 2 == (dirAt(view, closest + offset) == Direction.LTR);
33976
- return after ? new PosAssoc(innerOff + inner.length, -1) : new PosAssoc(innerOff, 1);
34070
+ if (child.flags & 48 /* TileFlag.PointWidget */) return null;
34071
+ return (child.dom.nodeType == 1 ? child.dom : textRange(child.dom, 0, child.length)).getClientRects();
34072
+ });
34073
+ let child = tile.children[scan.i],
34074
+ pos = positions[scan.i];
34075
+ if (child.isText()) return this.scanText(child, pos);
34076
+ if (child.isComposite()) return this.scanTile(child, pos);
34077
+ return scan.after ? new PosAssoc(positions[scan.i + 1], -1) : new PosAssoc(pos, 1);
33977
34078
  }
33978
34079
  }
33979
- function dirAt(view, pos) {
33980
- let line = view.state.doc.lineAt(pos),
33981
- spans = view.bidiSpans(line);
33982
- return spans[BidiSpan.find(view.bidiSpans(line), pos - line.from, -1, 1)].dir;
33983
- }
33984
34080
  const LineBreakPlaceholder = "\uffff";
33985
34081
  class DOMReader {
33986
34082
  constructor(points, view) {
@@ -34174,7 +34270,10 @@
34174
34270
  let {
34175
34271
  newSel
34176
34272
  } = domChange,
34177
- sel = view.state.selection.main;
34273
+ {
34274
+ state
34275
+ } = view,
34276
+ sel = state.selection.main;
34178
34277
  let lastKey = view.inputState.lastKeyTime > Date.now() - 100 ? view.inputState.lastKeyCode : -1;
34179
34278
  if (domChange.bounds) {
34180
34279
  let {
@@ -34189,8 +34288,17 @@
34189
34288
  preferredPos = sel.to;
34190
34289
  preferredSide = "end";
34191
34290
  }
34192
- let diff = findDiff$1(view.state.doc.sliceString(from, to, LineBreakPlaceholder), domChange.text, preferredPos - from, preferredSide);
34193
- if (diff) {
34291
+ let cmp = state.doc.sliceString(from, to, LineBreakPlaceholder),
34292
+ selEnd,
34293
+ diff;
34294
+ if (!sel.empty && sel.from >= from && sel.to <= to && (domChange.typeOver || cmp != domChange.text) && cmp.slice(0, sel.from - from) == domChange.text.slice(0, sel.from - from) && cmp.slice(sel.to - from) == domChange.text.slice(selEnd = domChange.text.length - (cmp.length - (sel.to - from)))) {
34295
+ // This looks like a selection replacement
34296
+ change = {
34297
+ from: sel.from,
34298
+ to: sel.to,
34299
+ insert: Text$2.of(domChange.text.slice(sel.from - from, selEnd).split(LineBreakPlaceholder))
34300
+ };
34301
+ } else if (diff = findDiff$1(cmp, domChange.text, preferredPos - from, preferredSide)) {
34194
34302
  // Chrome inserts two newlines when pressing shift-enter at the
34195
34303
  // end of a line. DomChange drops one of those.
34196
34304
  if (browser.chrome && lastKey == 13 && diff.toB == diff.from + 2 && domChange.text.slice(diff.from, diff.toB) == LineBreakPlaceholder + LineBreakPlaceholder) diff.toB--;
@@ -34200,18 +34308,11 @@
34200
34308
  insert: Text$2.of(domChange.text.slice(diff.from, diff.toB).split(LineBreakPlaceholder))
34201
34309
  };
34202
34310
  }
34203
- } else if (newSel && (!view.hasFocus && view.state.facet(editable) || sameSelPos(newSel, sel))) {
34311
+ } else if (newSel && (!view.hasFocus && state.facet(editable) || sameSelPos(newSel, sel))) {
34204
34312
  newSel = null;
34205
34313
  }
34206
34314
  if (!change && !newSel) return false;
34207
- if (!change && domChange.typeOver && !sel.empty && newSel && newSel.main.empty) {
34208
- // Heuristic to notice typing over a selected character
34209
- change = {
34210
- from: sel.from,
34211
- to: sel.to,
34212
- insert: view.state.doc.slice(sel.from, sel.to)
34213
- };
34214
- } else if ((browser.mac || browser.android) && change && change.from == change.to && change.from == sel.head - 1 && /^\. ?$/.test(change.insert.toString()) && view.contentDOM.getAttribute("autocorrect") == "off") {
34315
+ if ((browser.mac || browser.android) && change && change.from == change.to && change.from == sel.head - 1 && /^\. ?$/.test(change.insert.toString()) && view.contentDOM.getAttribute("autocorrect") == "off") {
34215
34316
  // Detect insert-period-on-double-space Mac and Android behavior,
34216
34317
  // and transform it into a regular space insert.
34217
34318
  if (newSel && change.insert.length == 2) newSel = EditorSelection.single(newSel.main.anchor - 1, newSel.main.head - 1);
@@ -34220,16 +34321,7 @@
34220
34321
  to: change.to,
34221
34322
  insert: Text$2.of([change.insert.toString().replace(".", " ")])
34222
34323
  };
34223
- } else if (change && change.from >= sel.from && change.to <= sel.to && (change.from != sel.from || change.to != sel.to) && sel.to - sel.from - (change.to - change.from) <= 4) {
34224
- // If the change is inside the selection and covers most of it,
34225
- // assume it is a selection replace (with identical characters at
34226
- // the start/end not included in the diff)
34227
- change = {
34228
- from: sel.from,
34229
- to: sel.to,
34230
- insert: view.state.doc.slice(sel.from, change.from).append(change.insert).append(view.state.doc.slice(change.to, sel.to))
34231
- };
34232
- } else if (view.state.doc.lineAt(sel.from).to < sel.to && view.docView.lineHasWidget(sel.to) && view.inputState.insertingTextAt > Date.now() - 50) {
34324
+ } else if (state.doc.lineAt(sel.from).to < sel.to && view.docView.lineHasWidget(sel.to) && view.inputState.insertingTextAt > Date.now() - 50) {
34233
34325
  // For a cross-line insertion, Chrome and Safari will crudely take
34234
34326
  // the text of the line after the selection, flattening any
34235
34327
  // widgets, and move it into the joined line. This tries to detect
@@ -34238,7 +34330,7 @@
34238
34330
  change = {
34239
34331
  from: sel.from,
34240
34332
  to: sel.to,
34241
- insert: view.state.toText(view.inputState.insertingText)
34333
+ insert: state.toText(view.inputState.insertingText)
34242
34334
  };
34243
34335
  } else if (browser.chrome && change && change.from == change.to && change.from == sel.head && change.insert.toString() == "\n " && view.lineWrapping) {
34244
34336
  // In Chrome, if you insert a space at the start of a wrapped
@@ -34259,7 +34351,7 @@
34259
34351
  if (view.inputState.lastSelectionTime > Date.now() - 50) {
34260
34352
  if (view.inputState.lastSelectionOrigin == "select") scrollIntoView = true;
34261
34353
  userEvent = view.inputState.lastSelectionOrigin;
34262
- if (userEvent == "select.pointer") newSel = skipAtomsForSelection(view.state.facet(atomicRanges).map(f => f(view)), newSel);
34354
+ if (userEvent == "select.pointer") newSel = skipAtomsForSelection(state.facet(atomicRanges).map(f => f(view)), newSel);
34263
34355
  }
34264
34356
  view.dispatch({
34265
34357
  selection: newSel,
@@ -34445,6 +34537,7 @@
34445
34537
  this.lastFocusTime = 0;
34446
34538
  this.lastScrollTop = 0;
34447
34539
  this.lastScrollLeft = 0;
34540
+ this.lastWheelEvent = 0;
34448
34541
  // On iOS, some keys need to have their default behavior happen
34449
34542
  // (after which we retroactively handle them and reset the DOM) to
34450
34543
  // avoid messing up the virtual keyboard state.
@@ -34865,6 +34958,9 @@
34865
34958
  view.inputState.lastScrollTop = view.scrollDOM.scrollTop;
34866
34959
  view.inputState.lastScrollLeft = view.scrollDOM.scrollLeft;
34867
34960
  };
34961
+ observers.wheel = observers.mousewheel = view => {
34962
+ view.inputState.lastWheelEvent = Date.now();
34963
+ };
34868
34964
  handlers.keydown = (view, event) => {
34869
34965
  view.inputState.setSelectionOrigin("select");
34870
34966
  if (event.keyCode == 27 && view.inputState.tabFocusMode != 0) view.inputState.tabFocusMode = Date.now() + 2000;
@@ -35130,8 +35226,7 @@
35130
35226
  // spans multiple elements including this CodeMirror. The copy event may
35131
35227
  // bubble through CodeMirror (e.g. when CodeMirror is the first or the last
35132
35228
  // element in the selection), but we should let the parent handle it.
35133
- let domSel = getSelection(view.root);
35134
- if (domSel && !hasSelection(view.contentDOM, domSel)) return false;
35229
+ if (!hasSelection(view.contentDOM, view.observer.selectionRange)) return false;
35135
35230
  let {
35136
35231
  text,
35137
35232
  ranges,
@@ -36113,7 +36208,8 @@
36113
36208
  }
36114
36209
  }
36115
36210
  class ViewState {
36116
- constructor(state) {
36211
+ constructor(view, state) {
36212
+ this.view = view;
36117
36213
  this.state = state;
36118
36214
  // These are contentDOM-local coordinates
36119
36215
  this.pixelViewport = {
@@ -36129,12 +36225,14 @@
36129
36225
  this.contentDOMHeight = 0; // contentDOM.getBoundingClientRect().height
36130
36226
  this.editorHeight = 0; // scrollDOM.clientHeight, unscaled
36131
36227
  this.editorWidth = 0; // scrollDOM.clientWidth, unscaled
36132
- this.scrollTop = 0; // Last seen scrollDOM.scrollTop, scaled
36133
- this.scrolledToBottom = false;
36134
36228
  // The CSS-transformation scale of the editor (transformed size /
36135
36229
  // concrete size)
36136
36230
  this.scaleX = 1;
36137
36231
  this.scaleY = 1;
36232
+ // Last seen vertical offset of the element at the top of the scroll
36233
+ // container, or top of the window if there's no wrapping scroller
36234
+ this.scrollOffset = 0;
36235
+ this.scrolledToBottom = false;
36138
36236
  // The vertical position (document-relative) to which to anchor the
36139
36237
  // scroll position. -1 means anchor to the end of the document.
36140
36238
  this.scrollAnchorPos = 0;
@@ -36171,6 +36269,7 @@
36171
36269
  this.updateViewportLines();
36172
36270
  this.lineGaps = this.ensureLineGaps([]);
36173
36271
  this.lineGapDeco = Decoration.set(this.lineGaps.map(gap => gap.draw(this, false)));
36272
+ this.scrollParent = view.scrollDOM;
36174
36273
  this.computeVisibleRanges();
36175
36274
  }
36176
36275
  updateForViewport() {
@@ -36212,7 +36311,7 @@
36212
36311
  let contentChanges = update.changedRanges;
36213
36312
  let heightChanges = ChangedRange.extendWithRanges(contentChanges, heightRelevantDecoChanges(prevDeco, this.stateDeco, update ? update.changes : ChangeSet.empty(this.state.doc.length)));
36214
36313
  let prevHeight = this.heightMap.height;
36215
- let scrollAnchor = this.scrolledToBottom ? null : this.scrollAnchorAt(this.scrollTop);
36314
+ let scrollAnchor = this.scrolledToBottom ? null : this.scrollAnchorAt(this.scrollOffset);
36216
36315
  clearHeightChangeFlag();
36217
36316
  this.heightMap = this.heightMap.applyChanges(this.stateDeco, update.startState.doc, this.heightOracle.setDoc(this.state.doc), heightChanges);
36218
36317
  if (this.heightMap.height != prevHeight || heightChangeFlag) update.flags |= 2 /* UpdateFlag.Height */;
@@ -36234,13 +36333,16 @@
36234
36333
  if (scrollTarget) this.scrollTarget = scrollTarget;
36235
36334
  if (!this.mustEnforceCursorAssoc && (update.selectionSet || update.focusChanged) && update.view.lineWrapping && update.state.selection.main.empty && update.state.selection.main.assoc && !update.state.facet(nativeSelectionHidden)) this.mustEnforceCursorAssoc = true;
36236
36335
  }
36237
- measure(view) {
36238
- let dom = view.contentDOM,
36336
+ measure() {
36337
+ let {
36338
+ view
36339
+ } = this,
36340
+ dom = view.contentDOM,
36239
36341
  style = window.getComputedStyle(dom);
36240
36342
  let oracle = this.heightOracle;
36241
36343
  let whiteSpace = style.whiteSpace;
36242
36344
  this.defaultTextDirection = style.direction == "rtl" ? Direction.RTL : Direction.LTR;
36243
- let refresh = this.heightOracle.mustRefreshForWrapping(whiteSpace) || this.mustMeasureContent;
36345
+ let refresh = this.heightOracle.mustRefreshForWrapping(whiteSpace) || this.mustMeasureContent === "refresh";
36244
36346
  let domRect = dom.getBoundingClientRect();
36245
36347
  let measureContent = refresh || this.mustMeasureContent || this.contentDOMHeight != domRect.height;
36246
36348
  this.contentDOMHeight = domRect.height;
@@ -36272,12 +36374,18 @@
36272
36374
  this.editorWidth = view.scrollDOM.clientWidth;
36273
36375
  result |= 16 /* UpdateFlag.Geometry */;
36274
36376
  }
36275
- let scrollTop = view.scrollDOM.scrollTop * this.scaleY;
36276
- if (this.scrollTop != scrollTop) {
36377
+ let scrollParent = scrollableParents(this.view.contentDOM, false).y;
36378
+ if (scrollParent != this.scrollParent) {
36379
+ this.scrollParent = scrollParent;
36277
36380
  this.scrollAnchorHeight = -1;
36278
- this.scrollTop = scrollTop;
36381
+ this.scrollOffset = 0;
36279
36382
  }
36280
- this.scrolledToBottom = isScrolledToBottom(view.scrollDOM);
36383
+ let scrollOffset = this.getScrollOffset();
36384
+ if (this.scrollOffset != scrollOffset) {
36385
+ this.scrollAnchorHeight = -1;
36386
+ this.scrollOffset = scrollOffset;
36387
+ }
36388
+ this.scrolledToBottom = isScrolledToBottom(this.scrollParent || view.win);
36281
36389
  // Pixel viewport
36282
36390
  let pixelViewport = (this.printing ? fullPixelRange : visiblePixelRange)(dom, this.paddingTop);
36283
36391
  let dTop = pixelViewport.top - this.pixelViewport.top,
@@ -36539,9 +36647,13 @@
36539
36647
  lineBlockAtHeight(height) {
36540
36648
  return height >= this.viewportLines[0].top && height <= this.viewportLines[this.viewportLines.length - 1].bottom && this.viewportLines.find(l => l.top <= height && l.bottom >= height) || scaleBlock(this.heightMap.lineAt(this.scaler.fromDOM(height), QueryType$1.ByHeight, this.heightOracle, 0, 0), this.scaler);
36541
36649
  }
36542
- scrollAnchorAt(scrollTop) {
36543
- let block = this.lineBlockAtHeight(scrollTop + 8);
36544
- return block.from >= this.viewport.from || this.viewportLines[0].top - scrollTop > 200 ? block : this.viewportLines[0];
36650
+ getScrollOffset() {
36651
+ let base = this.scrollParent == this.view.scrollDOM ? this.scrollParent.scrollTop : (this.scrollParent ? this.scrollParent.getBoundingClientRect().top : 0) - this.view.contentDOM.getBoundingClientRect().top;
36652
+ return base * this.scaleY;
36653
+ }
36654
+ scrollAnchorAt(scrollOffset) {
36655
+ let block = this.lineBlockAtHeight(scrollOffset + 8);
36656
+ return block.from >= this.viewport.from || this.viewportLines[0].top - scrollOffset > 200 ? block : this.viewportLines[0];
36545
36657
  }
36546
36658
  elementAtHeight(height) {
36547
36659
  return scaleBlock(this.heightMap.blockAt(this.scaler.fromDOM(height), this.heightOracle, 0, 0), this.scaler);
@@ -37856,7 +37968,7 @@
37856
37968
  this.dispatchTransactions = config.dispatchTransactions || dispatch && (trs => trs.forEach(tr => dispatch(tr, this))) || (trs => this.update(trs));
37857
37969
  this.dispatch = this.dispatch.bind(this);
37858
37970
  this._root = config.root || getRoot(config.parent) || document;
37859
- this.viewState = new ViewState(config.state || EditorState.create(config));
37971
+ this.viewState = new ViewState(this, config.state || EditorState.create(config));
37860
37972
  if (config.scrollTo && config.scrollTo.is(scrollIntoView$1)) this.viewState.scrollTarget = config.scrollTo.value.clip(this.viewState.state);
37861
37973
  this.plugins = this.state.facet(viewPlugin).map(spec => new PluginInstance(spec));
37862
37974
  for (let plugin of this.plugins) plugin.update(this);
@@ -37869,7 +37981,7 @@
37869
37981
  this.updateState = 0 /* UpdateState.Idle */;
37870
37982
  this.requestMeasure();
37871
37983
  if ((_a = document.fonts) === null || _a === void 0 ? void 0 : _a.ready) document.fonts.ready.then(() => {
37872
- this.viewState.mustMeasureContent = true;
37984
+ this.viewState.mustMeasureContent = "refresh";
37873
37985
  this.requestMeasure();
37874
37986
  });
37875
37987
  }
@@ -37991,7 +38103,7 @@
37991
38103
  let hadFocus = this.hasFocus;
37992
38104
  try {
37993
38105
  for (let plugin of this.plugins) plugin.destroy(this);
37994
- this.viewState = new ViewState(newState);
38106
+ this.viewState = new ViewState(this, newState);
37995
38107
  this.plugins = newState.facet(viewPlugin).map(spec => new PluginInstance(spec));
37996
38108
  this.pluginMap.clear();
37997
38109
  for (let plugin of this.plugins) plugin.update(this);
@@ -38057,28 +38169,28 @@
38057
38169
  this.measureScheduled = 0; // Prevent requestMeasure calls from scheduling another animation frame
38058
38170
  if (flush) this.observer.forceFlush();
38059
38171
  let updated = null;
38060
- let sDOM = this.scrollDOM,
38061
- scrollTop = sDOM.scrollTop * this.scaleY;
38172
+ let scroll = this.viewState.scrollParent,
38173
+ scrollOffset = this.viewState.getScrollOffset();
38062
38174
  let {
38063
38175
  scrollAnchorPos,
38064
38176
  scrollAnchorHeight
38065
38177
  } = this.viewState;
38066
- if (Math.abs(scrollTop - this.viewState.scrollTop) > 1) scrollAnchorHeight = -1;
38178
+ if (Math.abs(scrollOffset - this.viewState.scrollOffset) > 1) scrollAnchorHeight = -1;
38067
38179
  this.viewState.scrollAnchorHeight = -1;
38068
38180
  try {
38069
38181
  for (let i = 0;; i++) {
38070
38182
  if (scrollAnchorHeight < 0) {
38071
- if (isScrolledToBottom(sDOM)) {
38183
+ if (isScrolledToBottom(scroll || this.win)) {
38072
38184
  scrollAnchorPos = -1;
38073
38185
  scrollAnchorHeight = this.viewState.heightMap.height;
38074
38186
  } else {
38075
- let block = this.viewState.scrollAnchorAt(scrollTop);
38187
+ let block = this.viewState.scrollAnchorAt(scrollOffset);
38076
38188
  scrollAnchorPos = block.from;
38077
38189
  scrollAnchorHeight = block.top;
38078
38190
  }
38079
38191
  }
38080
38192
  this.updateState = 1 /* UpdateState.Measuring */;
38081
- let changed = this.viewState.measure(this);
38193
+ let changed = this.viewState.measure();
38082
38194
  if (!changed && !this.measureRequests.length && this.viewState.scrollTarget == null) break;
38083
38195
  if (i > 5) {
38084
38196
  console.warn(this.measureRequests.length ? "Measure loop restarted more than 5 times" : "Viewport failed to stabilize");
@@ -38125,10 +38237,10 @@
38125
38237
  continue;
38126
38238
  } else {
38127
38239
  let newAnchorHeight = scrollAnchorPos < 0 ? this.viewState.heightMap.height : this.viewState.lineBlockAt(scrollAnchorPos).top;
38128
- let diff = newAnchorHeight - scrollAnchorHeight;
38129
- if (diff > 1 || diff < -1) {
38130
- scrollTop = scrollTop + diff;
38131
- sDOM.scrollTop = scrollTop / this.scaleY;
38240
+ let diff = (newAnchorHeight - scrollAnchorHeight) / this.scaleY;
38241
+ if ((diff > 1 || diff < -1) && (scroll == this.scrollDOM || this.hasFocus || Math.max(this.inputState.lastWheelEvent, this.inputState.lastTouchTime) > Date.now() - 100)) {
38242
+ scrollOffset = scrollOffset + diff;
38243
+ if (scroll) scroll.scrollTop += diff;else this.win.scrollBy(0, diff);
38132
38244
  scrollAnchorHeight = -1;
38133
38245
  continue;
38134
38246
  }
@@ -45568,16 +45680,19 @@
45568
45680
  function changeLineComment(option, state, ranges = state.selection.ranges) {
45569
45681
  let lines = [];
45570
45682
  let prevLine = -1;
45571
- for (let {
45683
+ ranges: for (let {
45572
45684
  from,
45573
45685
  to
45574
45686
  } of ranges) {
45575
45687
  let startI = lines.length,
45576
- minIndent = 1e9;
45577
- let token = getConfig(state, from).line;
45578
- if (!token) continue;
45688
+ minIndent = 1e9,
45689
+ token;
45579
45690
  for (let pos = from; pos <= to;) {
45580
45691
  let line = state.doc.lineAt(pos);
45692
+ if (token == undefined) {
45693
+ token = getConfig(state, line.from).line;
45694
+ if (!token) continue ranges;
45695
+ }
45581
45696
  if (line.from > prevLine && (from == to || to > line.from)) {
45582
45697
  prevLine = line.from;
45583
45698
  let indent = /^\s*/.exec(line.text)[0].length;
@@ -45914,7 +46029,7 @@
45914
46029
  let branch = side == 0 /* BranchName.Done */ ? this.done : this.undone;
45915
46030
  if (branch.length == 0) return null;
45916
46031
  let event = branch[branch.length - 1],
45917
- selection = event.selectionsAfter[0] || state.selection;
46032
+ selection = event.selectionsAfter[0] || (event.startSelection ? event.startSelection.map(event.changes.invertedDesc, 1) : state.selection);
45918
46033
  if (onlySelection && event.selectionsAfter.length) {
45919
46034
  return state.update({
45920
46035
  selection: event.selectionsAfter[event.selectionsAfter.length - 1],
@@ -55302,6 +55417,9 @@ Please report this to https://github.com/markedjs/marked.`, e) {
55302
55417
  // flatpicker logic that was lost when setting allowInput to true
55303
55418
  instance.config.onOpen = [() => instance.calendarContainer.addEventListener('focusout', onCalendarFocusOut), () => instance.calendarContainer.addEventListener('mousedown', onCalendarMouseDown)];
55304
55419
  instance.config.onClose = [() => instance.calendarContainer.removeEventListener('focusout', onCalendarFocusOut), () => instance.calendarContainer.removeEventListener('mousedown', onCalendarMouseDown)];
55420
+ return () => {
55421
+ instance.destroy();
55422
+ };
55305
55423
  }, [disallowPassedDates]);
55306
55424
 
55307
55425
  // onChange is updated dynamically, so not to re-render the flatpicker every time it changes
@@ -63467,53 +63585,17 @@ Please report this to https://github.com/markedjs/marked.`, e) {
63467
63585
  */
63468
63586
 
63469
63587
  /**
63470
- * FEEL built-ins available with Camunda / feel-scala.
63588
+ * List of standard FEEL built-in functions (excluding Camunda-specific extensions).
63471
63589
  *
63472
63590
  * @type { Builtin[] }
63473
63591
  */
63474
- const camundaBuiltins = [{
63592
+ const feelBuiltins = [{
63475
63593
  "name": "not",
63476
63594
  "type": "function",
63477
63595
  "params": [{
63478
63596
  "name": "negand"
63479
63597
  }],
63480
63598
  "info": "<p>Returns the logical negation of the given value.</p>\n<p><strong>Function signature</strong></p>\n<pre><code class=\"language-feel\">not(negand: boolean): boolean\n</code></pre>\n<p><strong>Examples</strong></p>\n<pre><code class=\"language-feel\">not(true)\n// false\n\nnot(null)\n// null\n</code></pre>\n"
63481
- }, {
63482
- "name": "is defined",
63483
- "type": "function",
63484
- "params": [{
63485
- "name": "value"
63486
- }],
63487
- "info": "<p><em>Camunda Extension</em></p>\n<p>Checks if a given value is not <code>null</code>. If the value is <code>null</code> then the function returns <code>false</code>.\nOtherwise, the function returns <code>true</code>.</p>\n<p><strong>Function signature</strong></p>\n<pre><code class=\"language-feel\">is defined(value: Any): boolean\n</code></pre>\n<p><strong>Examples</strong></p>\n<pre><code class=\"language-feel\">is defined(1)\n// true\n\nis defined(null)\n// false\n\nis defined(x)\n// false - if no variable &quot;x&quot; exists\n\nis defined(x.y)\n// false - if no variable &quot;x&quot; exists or it doesn&#39;t have a property &quot;y&quot;\n</code></pre>\n<p>:::caution Breaking change</p>\n<p>This function worked differently in previous versions. It returned <code>true</code> if the value was <code>null</code>.\nSince this version, the function returns <code>false</code> if the value is <code>null</code>.</p>\n<p>:::</p>\n"
63488
- }, {
63489
- "name": "get or else",
63490
- "type": "function",
63491
- "params": [{
63492
- "name": "value"
63493
- }, {
63494
- "name": "default"
63495
- }],
63496
- "info": "<p><em>Camunda Extension</em></p>\n<p>Return the provided value parameter if not <code>null</code>, otherwise return the default parameter</p>\n<p><strong>Function signature</strong></p>\n<pre><code class=\"language-feel\">get or else(value: Any, default: Any): Any\n</code></pre>\n<p><strong>Examples</strong></p>\n<pre><code class=\"language-feel\">get or else(&quot;this&quot;, &quot;default&quot;)\n// &quot;this&quot;\n\nget or else(null, &quot;default&quot;)\n// &quot;default&quot;\n\nget or else(null, null)\n// null\n</code></pre>\n"
63497
- }, {
63498
- "name": "assert",
63499
- "type": "function",
63500
- "params": [{
63501
- "name": "value"
63502
- }, {
63503
- "name": "condition"
63504
- }],
63505
- "info": "<p><em>Camunda Extension</em></p>\n<p>Verify that the given condition is met. If the condition is <code>true</code>, the function returns the value.\nOtherwise, the evaluation fails with an error.</p>\n<p><strong>Function signature</strong></p>\n<pre><code class=\"language-feel\">assert(value: Any, condition: Any)\n</code></pre>\n<p><strong>Examples</strong></p>\n<pre><code class=\"language-feel\">assert(x, x != null)\n// &quot;value&quot; - if x is &quot;value&quot;\n// error - if x is null or doesn&#39;t exist\n\nassert(x, x &gt;= 0)\n// 4 - if x is 4\n// error - if x is less than zero\n</code></pre>\n"
63506
- }, {
63507
- "name": "assert",
63508
- "type": "function",
63509
- "params": [{
63510
- "name": "value"
63511
- }, {
63512
- "name": "condition"
63513
- }, {
63514
- "name": "cause"
63515
- }],
63516
- "info": "<p><em>Camunda Extension</em></p>\n<p>Verify that the given condition is met. If the condition is <code>true</code>, the function returns the value.\nOtherwise, the evaluation fails with an error containing the given message.</p>\n<p><strong>Function signature</strong></p>\n<pre><code class=\"language-feel\">assert(value: Any, condition: Any, cause: String)\n</code></pre>\n<p><strong>Examples</strong></p>\n<pre><code class=\"language-feel\">assert(x, x != null, &quot;&#39;x&#39; should not be null&quot;)\n// &quot;value&quot; - if x is &quot;value&quot;\n// error(&#39;x&#39; should not be null) - if x is null or doesn&#39;t exist\n\nassert(x, x &gt;= 0, &quot;&#39;x&#39; should be positive&quot;)\n// 4 - if x is 4\n// error(&#39;x&#39; should be positive) - if x is less than zero\n</code></pre>\n"
63517
63599
  }, {
63518
63600
  "name": "get value",
63519
63601
  "type": "function",
@@ -63523,15 +63605,6 @@ Please report this to https://github.com/markedjs/marked.`, e) {
63523
63605
  "name": "key"
63524
63606
  }],
63525
63607
  "info": "<p>Returns the value of the context entry with the given key.</p>\n<p><strong>Function signature</strong></p>\n<pre><code class=\"language-feel\">get value(context: context, key: string): Any\n</code></pre>\n<p><strong>Examples</strong></p>\n<pre><code class=\"language-feel\">get value({foo: 123}, &quot;foo&quot;)\n// 123\n\nget value({a: 1}, &quot;b&quot;)\n// null\n</code></pre>\n"
63526
- }, {
63527
- "name": "get value",
63528
- "type": "function",
63529
- "params": [{
63530
- "name": "context"
63531
- }, {
63532
- "name": "keys"
63533
- }],
63534
- "info": "<p><em>Camunda Extension</em></p>\n<p>Returns the value of the context entry for a context path defined by the given keys.</p>\n<p>If <code>keys</code> contains the keys <code>[k1, k2]</code> then it returns the value at the nested entry <code>k1.k2</code> of the context.</p>\n<p>If <code>keys</code> are empty or the nested entry defined by the keys doesn&#39;t exist in the context, it returns <code>null</code>.</p>\n<p><strong>Function signature</strong></p>\n<pre><code class=\"language-feel\">get value(context: context, keys: list&lt;string&gt;): Any\n</code></pre>\n<p><strong>Examples</strong></p>\n<pre><code class=\"language-feel\">get value({x:1, y: {z:0}}, [&quot;y&quot;, &quot;z&quot;])\n// 0\n\nget value({x: {y: {z:0}}}, [&quot;x&quot;, &quot;y&quot;])\n// {z:0}\n\nget value({a: {b: 3}}, [&quot;b&quot;])\n// null\n</code></pre>\n"
63535
63608
  }, {
63536
63609
  "name": "get entries",
63537
63610
  "type": "function",
@@ -63545,43 +63618,45 @@ Please report this to https://github.com/markedjs/marked.`, e) {
63545
63618
  "params": [{
63546
63619
  "name": "context"
63547
63620
  }, {
63548
- "name": "key"
63621
+ "name": "keys"
63549
63622
  }, {
63550
63623
  "name": "value"
63551
63624
  }],
63552
- "info": "<p>Adds a new entry with the given key and value to the context. Returns a new context that includes the entry.</p>\n<p>If an entry for the same key already exists in the context, it overrides the value.</p>\n<p><strong>Function signature</strong></p>\n<pre><code class=\"language-feel\">context put(context: context, key: string, value: Any): context\n</code></pre>\n<p><strong>Examples</strong></p>\n<pre><code class=\"language-feel\">context put({x:1}, &quot;y&quot;, 2)\n// {x:1, y:2}\n</code></pre>\n<p>:::info\nThe function <code>context put()</code> replaced the previous function <code>put()</code> (Camunda Extension). The\nprevious function is deprecated and should not be used anymore.\n:::</p>\n"
63625
+ "info": "<p>Adds a new entry with the given value to the context. The path of the entry is defined by the keys. Returns a new context that includes the entry.</p>\n<p>If <code>keys</code> contains the keys <code>[k1, k2]</code> then it adds the nested entry <code>k1.k2 = value</code> to the context.</p>\n<p>If an entry for the same keys already exists in the context, it overrides the value.</p>\n<p>If <code>keys</code> are empty, it returns <code>null</code>.</p>\n<p><strong>Function signature</strong></p>\n<pre><code class=\"language-feel\">context put(context: context, keys: list&lt;string&gt;, value: Any): context\n</code></pre>\n<p><strong>Examples</strong></p>\n<pre><code class=\"language-feel\">context put({x:1}, [&quot;y&quot;], 2)\n// {x:1, y:2}\n\ncontext put({x:1, y: {z:0}}, [&quot;y&quot;, &quot;z&quot;], 2)\n// {x:1, y: {z:2}}\n\ncontext put({x:1}, [&quot;y&quot;, &quot;z&quot;], 2)\n// {x:1, y: {z:2}}\n</code></pre>\n"
63553
63626
  }, {
63554
- "name": "context put",
63627
+ "name": "string",
63555
63628
  "type": "function",
63556
63629
  "params": [{
63557
- "name": "context"
63558
- }, {
63559
- "name": "keys"
63560
- }, {
63561
- "name": "value"
63630
+ "name": "from"
63562
63631
  }],
63563
- "info": "<p>Adds a new entry with the given value to the context. The path of the entry is defined by the keys. Returns a new context that includes the entry.</p>\n<p>If <code>keys</code> contains the keys <code>[k1, k2]</code> then it adds the nested entry <code>k1.k2 = value</code> to the context.</p>\n<p>If an entry for the same keys already exists in the context, it overrides the value.</p>\n<p>If <code>keys</code> are empty, it returns <code>null</code>.</p>\n<p><strong>Function signature</strong></p>\n<pre><code class=\"language-feel\">context put(context: context, keys: list&lt;string&gt;, value: Any): context\n</code></pre>\n<p><strong>Examples</strong></p>\n<pre><code class=\"language-feel\">context put({x:1}, [&quot;y&quot;], 2)\n// {x:1, y:2}\n\ncontext put({x:1, y: {z:0}}, [&quot;y&quot;, &quot;z&quot;], 2)\n// {x:1, y: {z:2}}\n\ncontext put({x:1}, [&quot;y&quot;, &quot;z&quot;], 2)\n// {x:1, y: {z:2}}\n</code></pre>\n"
63632
+ "info": "<p>Returns the given value as a string representation.</p>\n<p><strong>Function signature</strong></p>\n<pre><code class=\"language-feel\">string(from: Any): string\n</code></pre>\n<p><strong>Examples</strong></p>\n<pre><code class=\"language-feel\">string(1.1)\n// &quot;1.1&quot;\n\nstring(date(&quot;2012-12-25&quot;))\n// &quot;2012-12-25&quot;\n</code></pre>\n"
63564
63633
  }, {
63565
- "name": "context merge",
63634
+ "name": "number",
63566
63635
  "type": "function",
63567
63636
  "params": [{
63568
- "name": "contexts"
63637
+ "name": "from"
63569
63638
  }],
63570
- "info": "<p>Union the given contexts. Returns a new context that includes all entries of the given contexts.</p>\n<p>If an entry for the same key already exists in a context, it overrides the value. The entries are overridden in the same order as in the list of contexts.</p>\n<p><strong>Function signature</strong></p>\n<pre><code class=\"language-feel\">context merge(contexts: list&lt;context&gt;): context\n</code></pre>\n<p><strong>Examples</strong></p>\n<pre><code class=\"language-feel\">context merge([{x:1}, {y:2}])\n// {x:1, y:2}\n\ncontext merge([{x:1, y: 0}, {y:2}])\n// {x:1, y:2}\n</code></pre>\n<p>:::info\nThe function <code>context merge()</code> replaced the previous function <code>put all()</code> (Camunda Extension). The\nprevious function is deprecated and should not be used anymore.\n:::</p>\n"
63639
+ "info": "<p>Parses the given string to a number.</p>\n<p>Returns <code>null</code> if the string is not a number.</p>\n<p><strong>Function signature</strong></p>\n<pre><code class=\"language-feel\">number(from: string): number\n</code></pre>\n<p><strong>Examples</strong></p>\n<pre><code class=\"language-feel\">number(&quot;1500.5&quot;)\n// 1500.5\n</code></pre>\n"
63571
63640
  }, {
63572
- "name": "string",
63641
+ "name": "number",
63573
63642
  "type": "function",
63574
63643
  "params": [{
63575
63644
  "name": "from"
63645
+ }, {
63646
+ "name": "grouping separator"
63576
63647
  }],
63577
- "info": "<p>Returns the given value as a string representation.</p>\n<p><strong>Function signature</strong></p>\n<pre><code class=\"language-feel\">string(from: Any): string\n</code></pre>\n<p><strong>Examples</strong></p>\n<pre><code class=\"language-feel\">string(1.1)\n// &quot;1.1&quot;\n\nstring(date(&quot;2012-12-25&quot;))\n// &quot;2012-12-25&quot;\n</code></pre>\n"
63648
+ "info": "<p>Parses the given string to a number using the specified grouping separator.</p>\n<p>Returns <code>null</code> if the string is not a number.</p>\n<p><strong>Function signature</strong></p>\n<pre><code class=\"language-feel\">number(from: string, grouping separator: string): number\n</code></pre>\n<p><strong>Examples</strong></p>\n<pre><code class=\"language-feel\">number(&quot;1,500&quot;, &quot;,&quot;)\n// 1500\n</code></pre>\n"
63578
63649
  }, {
63579
63650
  "name": "number",
63580
63651
  "type": "function",
63581
63652
  "params": [{
63582
63653
  "name": "from"
63654
+ }, {
63655
+ "name": "grouping separator"
63656
+ }, {
63657
+ "name": "decimal separator"
63583
63658
  }],
63584
- "info": "<p>Parses the given string to a number.</p>\n<p>Returns <code>null</code> if the string is not a number.</p>\n<p><strong>Function signature</strong></p>\n<pre><code class=\"language-feel\">number(from: string): number\n</code></pre>\n<p><strong>Examples</strong></p>\n<pre><code class=\"language-feel\">number(&quot;1500.5&quot;)\n// 1500.5\n</code></pre>\n"
63659
+ "info": "<p>Parses the given string to a number using the specified grouping and decimal separators.</p>\n<p>Returns <code>null</code> if the string is not a number.</p>\n<p><strong>Function signature</strong></p>\n<pre><code class=\"language-feel\">number(from: string, grouping separator: string, decimal separator: string): number\n</code></pre>\n<p><strong>Examples</strong></p>\n<pre><code class=\"language-feel\">number(&quot;1 500.5&quot;, &quot; &quot;, &quot;.&quot;)\n// 1500.5\n</code></pre>\n"
63585
63660
  }, {
63586
63661
  "name": "context",
63587
63662
  "type": "function",
@@ -63644,7 +63719,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
63644
63719
  "params": [{
63645
63720
  "name": "from"
63646
63721
  }],
63647
- "info": "<p>Parses the given string into a date and time.</p>\n<p>Returns <code>null</code> if the string is not a valid calendar date. For example, <code>&quot;2024-06-31T10:00:00&quot;</code> is invalid because\nJune has only 30 days.</p>\n<p><strong>Function signature</strong></p>\n<pre><code class=\"language-feel\">date and time(from: string): date and time\n</code></pre>\n<p><strong>Examples</strong></p>\n<pre><code class=\"language-feel\">date and time(&quot;2018-04-29T09:30:00&quot;)\n// date and time(&quot;2018-04-29T09:30:00&quot;)\n</code></pre>\n"
63722
+ "info": "<p>Parses the given string into a date and time. The function supports strings in the format <code>YYYY-MM-DDThh:mm:ss</code> with\noptional timezone information either as offset (e.g., <code>+01:00</code> or <code>Z</code>), as IANA timezone ID (e.g., <code>@Europe/Berlin</code>), or\nas a combination of both (e.g., <code>+01:00[Europe/Berlin]</code>).</p>\n<p>Returns <code>null</code> if the string is not a valid calendar date. For example, <code>&quot;2024-06-31T10:00:00&quot;</code> is invalid because\nJune has only 30 days.</p>\n<p><strong>Function signature</strong></p>\n<pre><code class=\"language-feel\">date and time(from: string): date and time\n</code></pre>\n<p><strong>Examples</strong></p>\n<pre><code class=\"language-feel\">date and time(&quot;2018-04-29T09:30:00&quot;)\n// date and time(&quot;2018-04-29T09:30:00&quot;)\n\ndate and time(&quot;2018-04-29T09:30:00+02:00&quot;)\n// date and time(&quot;2018-04-29T09:30:00+02:00&quot;)\n\ndate and time(&quot;2018-04-29T09:30:00@Europe/Berlin&quot;)\n// date and time(&quot;2018-04-29T09:30:00@Europe/Berlin&quot;)\n\ndate and time(&quot;2018-04-29T09:30:00+02:00[Europe/Berlin]&quot;)\n// date and time(&quot;2018-04-29T09:30:00@Europe/Berlin&quot;)\n</code></pre>\n"
63648
63723
  }, {
63649
63724
  "name": "date and time",
63650
63725
  "type": "function",
@@ -63654,15 +63729,6 @@ Please report this to https://github.com/markedjs/marked.`, e) {
63654
63729
  "name": "time"
63655
63730
  }],
63656
63731
  "info": "<p>Returns a date and time from the given components.</p>\n<p><strong>Function signature</strong></p>\n<pre><code class=\"language-feel\">date and time(date: date, time: time): date and time\n</code></pre>\n<pre><code class=\"language-feel\">date and time(date: date and time, time: time): date and time\n</code></pre>\n<p>Returns a date and time value that consists of the date component of <code>date</code> combined with <code>time</code>.</p>\n<p><strong>Examples</strong></p>\n<pre><code class=\"language-feel\">date and time(date(&quot;2012-12-24&quot;),time(&quot;T23:59:00&quot;))\n// date and time(&quot;2012-12-24T23:59:00&quot;)\n\ndate and time(date and time(&quot;2012-12-25T11:00:00&quot;),time(&quot;T23:59:00&quot;))\n// date and time(&quot;2012-12-25T23:59:00&quot;)\n</code></pre>\n"
63657
- }, {
63658
- "name": "date and time",
63659
- "type": "function",
63660
- "params": [{
63661
- "name": "date"
63662
- }, {
63663
- "name": "timezone"
63664
- }],
63665
- "info": "<p><em>Camunda Extension</em></p>\n<p>Returns the given date and time value at the given timezone.</p>\n<p>If <code>date</code> has a different timezone than <code>timezone</code> then it adjusts the time to match the local time of <code>timezone</code>.</p>\n<p><strong>Function signature</strong></p>\n<pre><code class=\"language-feel\">date and time(date: date and time, timezone: string): date and time\n</code></pre>\n<p><strong>Examples</strong></p>\n<pre><code class=\"language-feel\">date and time(@&quot;2020-07-31T14:27:30@Europe/Berlin&quot;, &quot;America/Los_Angeles&quot;)\n// date and time(&quot;2020-07-31T05:27:30@America/Los_Angeles&quot;)\n\ndate and time(@&quot;2020-07-31T14:27:30&quot;, &quot;Z&quot;)\n// date and time(&quot;2020-07-31T12:27:30Z&quot;)\n</code></pre>\n"
63666
63732
  }, {
63667
63733
  "name": "duration",
63668
63734
  "type": "function",
@@ -63679,6 +63745,20 @@ Please report this to https://github.com/markedjs/marked.`, e) {
63679
63745
  "name": "to"
63680
63746
  }],
63681
63747
  "info": "<p>Returns the years and months duration between <code>from</code> and <code>to</code>.</p>\n<p><strong>Function signature</strong></p>\n<pre><code class=\"language-feel\">years and months duration(from: date, to: date): years and months duration\n</code></pre>\n<p><strong>Examples</strong></p>\n<pre><code class=\"language-feel\">years and months duration(date(&quot;2011-12-22&quot;), date(&quot;2013-08-24&quot;))\n// duration(&quot;P1Y8M&quot;)\n</code></pre>\n"
63748
+ }, {
63749
+ "name": "from json",
63750
+ "type": "function",
63751
+ "params": [{
63752
+ "name": "value"
63753
+ }],
63754
+ "info": "<p>Parses a JSON string into a FEEL value. The function converts JSON primitives, objects, and arrays into their corresponding FEEL types.</p>\n<p>Returns <code>null</code> if the string is not a valid JSON value.</p>\n<p><strong>Function signature</strong></p>\n<pre><code class=\"language-feel\">from json(value: string): Any\n</code></pre>\n<p><strong>Examples</strong></p>\n<pre><code class=\"language-feel\">from json(&quot;{\\&quot;a\\&quot;: 1, \\&quot;b\\&quot;: 2}&quot;)\n// {a: 1, b: 2}\n\nfrom json(&quot;true&quot;)\n// true\n\nfrom json(&quot;\\&quot;2023-06-14\\&quot;&quot;)\n// &quot;2023-06-14&quot;\n</code></pre>\n"
63755
+ }, {
63756
+ "name": "to json",
63757
+ "type": "function",
63758
+ "params": [{
63759
+ "name": "value"
63760
+ }],
63761
+ "info": "<p>Converts a FEEL value into a JSON string. The function converts FEEL primitives, contexts, and lists into their\ncorresponding JSON types. Temporal values are converted to their ISO 8601 string representation, including timezone\ninformation for date and time values (format: <code>2025-11-24T10:00:00+01:00[Europe/Berlin]</code>).</p>\n<p><strong>Function signature</strong></p>\n<pre><code class=\"language-feel\">to json(value: Any): string\n</code></pre>\n<p><strong>Examples</strong></p>\n<pre><code class=\"language-feel\">to json({a: 1, b: 2})\n// &quot;{\\&quot;a\\&quot;:1,\\&quot;b\\&quot;:2}&quot;\n\nto json(true)\n// &quot;true&quot;\n\nto json(@&quot;2023-06-14&quot;)\n// &quot;\\&quot;2023-06-14\\&quot;&quot;\n\nto json(@&quot;2025-11-24T10:00:00@Europe/Berlin&quot;)\n// &quot;\\&quot;2025-11-24T10:00:00+01:00[Europe/Berlin]\\&quot;&quot;\n\nto json(@&quot;P3Y&quot;)\n// &quot;\\&quot;P3Y\\&quot;&quot;\n</code></pre>\n"
63682
63762
  }, {
63683
63763
  "name": "list contains",
63684
63764
  "type": "function",
@@ -63851,13 +63931,6 @@ Please report this to https://github.com/markedjs/marked.`, e) {
63851
63931
  "name": "list"
63852
63932
  }],
63853
63933
  "info": "<p>Returns the given list without duplicates.</p>\n<p><strong>Function signature</strong></p>\n<pre><code class=\"language-feel\">distinct values(list: list): list\n</code></pre>\n<p><strong>Examples</strong></p>\n<pre><code class=\"language-feel\">distinct values([1,2,3,2,1])\n// [1,2,3]\n</code></pre>\n"
63854
- }, {
63855
- "name": "duplicate values",
63856
- "type": "function",
63857
- "params": [{
63858
- "name": "list"
63859
- }],
63860
- "info": "<p><em>Camunda Extension</em></p>\n<p>Returns all duplicate values of the given list.</p>\n<p><strong>Function signature</strong></p>\n<pre><code class=\"language-feel\">duplicate values(list: list): list\n</code></pre>\n<p><strong>Examples</strong></p>\n<pre><code class=\"language-feel\">duplicate values([1,2,3,2,1])\n// [1,2]\n</code></pre>\n"
63861
63934
  }, {
63862
63935
  "name": "flatten",
63863
63936
  "type": "function",
@@ -63890,90 +63963,6 @@ Please report this to https://github.com/markedjs/marked.`, e) {
63890
63963
  "name": "delimiter"
63891
63964
  }],
63892
63965
  "info": "<p>Joins a list of strings into a single string. This is similar to\nJava&#39;s <a href=\"https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/stream/Collectors.html#joining(java.lang.CharSequence,java.lang.CharSequence,java.lang.CharSequence)\">joining</a>\nfunction.</p>\n<p>If an item of the list is <code>null</code>, the item is ignored for the result string. If an item is\nneither a string nor <code>null</code>, the function returns <code>null</code> instead of a string.</p>\n<p>The resulting string contains a <code>delimiter</code> between each element.</p>\n<p><strong>Function signature</strong></p>\n<pre><code class=\"language-feel\">string join(list: list&lt;string&gt;, delimiter: string): string\n</code></pre>\n<p><strong>Examples</strong></p>\n<pre><code class=\"language-feel\">string join([&quot;a&quot;], &quot;X&quot;)\n// &quot;a&quot;\n\nstring join([&quot;a&quot;,&quot;b&quot;,&quot;c&quot;], &quot;, &quot;)\n// &quot;a, b, c&quot;\n</code></pre>\n"
63893
- }, {
63894
- "name": "string join",
63895
- "type": "function",
63896
- "params": [{
63897
- "name": "list"
63898
- }, {
63899
- "name": "delimiter"
63900
- }, {
63901
- "name": "prefix"
63902
- }, {
63903
- "name": "suffix"
63904
- }],
63905
- "info": "<p><em>Camunda Extension</em></p>\n<p>Joins a list of strings into a single string. This is similar to\nJava&#39;s <a href=\"https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/stream/Collectors.html#joining(java.lang.CharSequence,java.lang.CharSequence,java.lang.CharSequence)\">joining</a>\nfunction.</p>\n<p>If an item of the list is <code>null</code>, the item is ignored for the result string. If an item is\nneither a string nor <code>null</code>, the function returns <code>null</code> instead of a string.</p>\n<p>The resulting string starts with <code>prefix</code>, contains a <code>delimiter</code> between each element, and ends\nwith <code>suffix</code>.</p>\n<p><strong>Function signature</strong></p>\n<pre><code class=\"language-feel\">string join(list: list&lt;string&gt;, delimiter: string, prefix: string, suffix: string): string\n</code></pre>\n<p><strong>Examples</strong></p>\n<pre><code class=\"language-feel\">string join([&quot;a&quot;,&quot;b&quot;,&quot;c&quot;], &quot;, &quot;, &quot;[&quot;, &quot;]&quot;)\n// &quot;[a, b, c]&quot;\n</code></pre>\n"
63906
- }, {
63907
- "name": "is empty",
63908
- "type": "function",
63909
- "params": [{
63910
- "name": "list"
63911
- }],
63912
- "info": "<p><em>Camunda Extension</em></p>\n<p>Returns <code>true</code> if the given list is empty. Otherwise, returns <code>false</code>.</p>\n<p><strong>Function signature</strong></p>\n<pre><code class=\"language-feel\">is empty(list: list): boolean\n</code></pre>\n<p><strong>Examples</strong></p>\n<pre><code class=\"language-feel\">is empty([])\n// true\n\nis empty([1,2,3])\n// false\n</code></pre>\n"
63913
- }, {
63914
- "name": "partition",
63915
- "type": "function",
63916
- "params": [{
63917
- "name": "list"
63918
- }, {
63919
- "name": "size"
63920
- }],
63921
- "info": "<p><em>Camunda Extension</em></p>\n<p>Returns consecutive sublists of a list, each of the same size (the final list may be smaller).</p>\n<p>If <code>size</code> is less than <code>0</code>, it returns <code>null</code>.</p>\n<p><strong>Function signature</strong></p>\n<pre><code class=\"language-feel\">partition(list: list, size: number): list\n</code></pre>\n<p><strong>Examples</strong></p>\n<pre><code class=\"language-feel\">partition([1,2,3,4,5], 2)\n// [[1,2], [3,4], [5]]\n\npartition([], 2)\n// []\n\npartition([1,2], 0)\n// null\n</code></pre>\n"
63922
- }, {
63923
- "name": "fromAi",
63924
- "type": "function",
63925
- "params": [{
63926
- "name": "value"
63927
- }],
63928
- "info": "<p><em>Camunda Extension</em></p>\n<p>Returns the unmodified <code>value</code> parameter.</p>\n<ul>\n<li>The purpose of this function is solely to tag the value as being generated by an AI integration.</li>\n<li>The actual handling is not performed by the FEEL engine, but by a custom integration such as a connector or a job worker.</li>\n</ul>\n<p>The main use case of this function is to be used in combination with\nthe <a href=\"../../../connectors/out-of-the-box-connectors/agentic-ai-aiagent.md\">AI Agent connector</a>.</p>\n<p>See the following function overloads for additional function parameters.</p>\n<p><strong>Function signature</strong></p>\n<pre><code class=\"language-feel\">fromAi(value: Any): Any\n</code></pre>\n<p><strong>Examples</strong></p>\n<pre><code class=\"language-feel\">fromAi(toolCall.searchQuery)\n// toolCall.searchQuery contents\n\nfromAi(toolCall.userId)\n// toolCall.userId contents\n\nfromAi(&quot;A&quot;)\n// &quot;A&quot; - does not make much sense and might be flagged as an error by the integration consuming the definition\n</code></pre>\n"
63929
- }, {
63930
- "name": "fromAi",
63931
- "type": "function",
63932
- "params": [{
63933
- "name": "value"
63934
- }, {
63935
- "name": "description"
63936
- }],
63937
- "info": "<p><em>Camunda Extension</em></p>\n<p>Returns the unmodified <code>value</code> parameter.</p>\n<p>In addition to the previous overload, it also accepts an optional <code>description</code> parameter to provide a textual description of the value.</p>\n<p><strong>Function signature</strong></p>\n<pre><code class=\"language-feel\">fromAi(value: Any, description: string): Any\n</code></pre>\n<p><strong>Examples</strong></p>\n<pre><code class=\"language-feel\">fromAi(toolCall.searchQuery, &quot;The search query used to find the best match.&quot;)\n// toolCall.searchQuery contents\n\nfromAi(toolCall.searchQuery, null)\n// toolCall.searchQuery contents\n</code></pre>\n"
63938
- }, {
63939
- "name": "fromAi",
63940
- "type": "function",
63941
- "params": [{
63942
- "name": "value"
63943
- }, {
63944
- "name": "description"
63945
- }, {
63946
- "name": "type"
63947
- }],
63948
- "info": "<p><em>Camunda Extension</em></p>\n<p>Returns the unmodified <code>value</code> parameter.</p>\n<p>In addition to the previous overload, it also accepts an optional <code>type</code> parameter to provide type information about the value.</p>\n<p><strong>Function signature</strong></p>\n<pre><code class=\"language-feel\">fromAi(value: Any, description: string, type: string): Any\n</code></pre>\n<p><strong>Examples</strong></p>\n<pre><code class=\"language-feel\">fromAi(toolCall.searchQuery, &quot;The search query used to find the best match.&quot;, &quot;string&quot;)\n// toolCall.searchQuery contents\n\nfromAi(toolCall.userId, &quot;The user&#39;s ID&quot;, &quot;number&quot;)\n// toolCall.userId contents\n\nfromAi(toolCall.userId, null, &quot;number&quot;)\n// toolCall.userId contents\n\nfromAi(value: toolCall.userId, type: &quot;number&quot;)\n// toolCall.userId contents\n</code></pre>\n"
63949
- }, {
63950
- "name": "fromAi",
63951
- "type": "function",
63952
- "params": [{
63953
- "name": "value"
63954
- }, {
63955
- "name": "description"
63956
- }, {
63957
- "name": "type"
63958
- }, {
63959
- "name": "schema"
63960
- }],
63961
- "info": "<p><em>Camunda Extension</em></p>\n<p>Returns the unmodified <code>value</code> parameter.</p>\n<p>In addition to the previous overload, it also accepts an optional <code>schema</code> parameter to provide a (partial) <a href=\"https://json-schema.org/\">JSON schema</a> for the value.</p>\n<ul>\n<li>The schema is not validated by the FEEL engine but might be by a custom integration consuming the information.</li>\n<li>From the engine side it is possible to specify both a <code>type</code> and a <code>schema</code>, and it depends on the integration as to which value takes precedence.</li>\n</ul>\n<p><strong>Function signature</strong></p>\n<pre><code class=\"language-feel\">fromAi(value: Any, description: string, type: string, schema: context): Any\n</code></pre>\n<p><strong>Examples</strong></p>\n<pre><code class=\"language-feel\">fromAi(toolCall.documentType, &quot;The document type to provide&quot;, &quot;string&quot;, {\n enum: [&quot;invoice&quot;, &quot;receipt&quot;, &quot;contract&quot;]\n})\n// toolCall.documentType contents\n\nfromAi(value: toolCall.documentType, description: &quot;The document type to provide&quot;, schema: {\n type: &quot;string&quot;,\n enum: [&quot;invoice&quot;, &quot;receipt&quot;, &quot;contract&quot;]\n})\n// toolCall.documentType contents\n\nfromAi(toolCall.tags, &quot;Tags to apply to the blog post&quot;, &quot;array&quot;, {\n items: {\n type: &quot;string&quot;\n }\n})\n// toolCall.tags contents\n</code></pre>\n"
63962
- }, {
63963
- "name": "fromAi",
63964
- "type": "function",
63965
- "params": [{
63966
- "name": "value"
63967
- }, {
63968
- "name": "description"
63969
- }, {
63970
- "name": "type"
63971
- }, {
63972
- "name": "schema"
63973
- }, {
63974
- "name": "options"
63975
- }],
63976
- "info": "<p><em>Camunda Extension</em></p>\n<p>Returns the unmodified <code>value</code> parameter.</p>\n<p>In addition to the previous overload, it also accepts an optional <code>options</code> parameter to provide additional options for the integration handling the value definition.</p>\n<p><strong>Function signature</strong></p>\n<pre><code class=\"language-feel\">fromAi(value: Any, description: string, type: string, schema: context, options: context): Any\n</code></pre>\n<p><strong>Examples</strong></p>\n<pre><code class=\"language-feel\">fromAi(toolCall.documentType, &quot;The document type to provide&quot;, &quot;string&quot;, null, {\n strict: true,\n required: false\n})\n// toolCall.documentType contents\n\nfromAi(value: toolCall.documentType, options: {\n strict: true,\n required: false\n})\n// toolCall.documentType contents\n</code></pre>\n"
63977
63966
  }, {
63978
63967
  "name": "decimal",
63979
63968
  "type": "function",
@@ -64102,11 +64091,6 @@ Please report this to https://github.com/markedjs/marked.`, e) {
64102
64091
  "name": "number"
64103
64092
  }],
64104
64093
  "info": "<p>Returns <code>true</code> if the given is even. Otherwise, returns <code>false</code>.</p>\n<p><strong>Function signature</strong></p>\n<pre><code class=\"language-feel\">even(number: number): boolean\n</code></pre>\n<p><strong>Examples</strong></p>\n<pre><code class=\"language-feel\">even(5)\n// false\n\neven(2)\n// true\n</code></pre>\n"
64105
- }, {
64106
- "name": "random number",
64107
- "type": "function",
64108
- "params": [],
64109
- "info": "<p><em>Camunda Extension</em></p>\n<p>Returns a random number between <code>0</code> and <code>1</code>.</p>\n<p><strong>Function signature</strong></p>\n<pre><code class=\"language-feel\">random number(): number\n</code></pre>\n<p><strong>Examples</strong></p>\n<pre><code class=\"language-feel\">random number()\n// 0.9701618132579795\n</code></pre>\n"
64110
64094
  }, {
64111
64095
  "name": "before",
64112
64096
  "type": "function",
@@ -64489,6 +64473,226 @@ Please report this to https://github.com/markedjs/marked.`, e) {
64489
64473
  "name": "delimiter"
64490
64474
  }],
64491
64475
  "info": "<p>Splits the given value into a list of substrings, breaking at each occurrence of the <code>delimiter</code> pattern.</p>\n<p><strong>Function signature</strong></p>\n<pre><code class=\"language-feel\">split(string: string, delimiter: string): list&lt;string&gt;\n</code></pre>\n<p>The <code>delimiter</code> is a string that contains a regular expression.</p>\n<p><strong>Examples</strong></p>\n<pre><code class=\"language-feel\">split(&quot;John Doe&quot;, &quot;\\s&quot; )\n// [&quot;John&quot;, &quot;Doe&quot;]\n\nsplit(&quot;a;b;c;;&quot;, &quot;;&quot;)\n// [&quot;a&quot;, &quot;b&quot;, &quot;c&quot;, &quot;&quot;, &quot;&quot;]\n</code></pre>\n"
64476
+ }, {
64477
+ "name": "now",
64478
+ "type": "function",
64479
+ "params": [],
64480
+ "info": "<p>Returns the current date and time including the timezone.</p>\n<p><strong>Function signature</strong></p>\n<pre><code class=\"language-feel\">now(): date and time\n</code></pre>\n<p><strong>Examples</strong></p>\n<pre><code class=\"language-feel\">now()\n// date and time(&quot;2020-07-31T14:27:30@Europe/Berlin&quot;)\n</code></pre>\n"
64481
+ }, {
64482
+ "name": "today",
64483
+ "type": "function",
64484
+ "params": [],
64485
+ "info": "<p>Returns the current date.</p>\n<p><strong>Function signature</strong></p>\n<pre><code class=\"language-feel\">today(): date\n</code></pre>\n<p><strong>Examples</strong></p>\n<pre><code class=\"language-feel\">today()\n// date(&quot;2020-07-31&quot;)\n</code></pre>\n"
64486
+ }, {
64487
+ "name": "day of week",
64488
+ "type": "function",
64489
+ "params": [{
64490
+ "name": "date"
64491
+ }],
64492
+ "info": "<p>Returns the day of the week according to the Gregorian calendar. Note that it always returns the English name of the day.</p>\n<p><strong>Function signature</strong></p>\n<pre><code class=\"language-feel\">day of week(date: date): string\n</code></pre>\n<pre><code class=\"language-feel\">day of week(date: date and time): string\n</code></pre>\n<p><strong>Examples</strong></p>\n<pre><code class=\"language-feel\">day of week(date(&quot;2019-09-17&quot;))\n// &quot;Tuesday&quot;\n\nday of week(date and time(&quot;2019-09-17T12:00:00&quot;))\n// &quot;Tuesday&quot;\n</code></pre>\n"
64493
+ }, {
64494
+ "name": "day of year",
64495
+ "type": "function",
64496
+ "params": [{
64497
+ "name": "date"
64498
+ }],
64499
+ "info": "<p>Returns the Gregorian number of the day within the year.</p>\n<p><strong>Function signature</strong></p>\n<pre><code class=\"language-feel\">day of year(date: date): number\n</code></pre>\n<pre><code class=\"language-feel\">day of year(date: date and time): number\n</code></pre>\n<p><strong>Examples</strong></p>\n<pre><code class=\"language-feel\">day of year(date(&quot;2019-09-17&quot;))\n// 260\n\nday of year(date and time(&quot;2019-09-17T12:00:00&quot;))\n// 260\n</code></pre>\n"
64500
+ }, {
64501
+ "name": "week of year",
64502
+ "type": "function",
64503
+ "params": [{
64504
+ "name": "date"
64505
+ }],
64506
+ "info": "<p>Returns the Gregorian number of the week within the year, according to ISO 8601.</p>\n<p><strong>Function signature</strong></p>\n<pre><code class=\"language-feel\">week of year(date: date): number\n</code></pre>\n<pre><code class=\"language-feel\">week of year(date: date and time): number\n</code></pre>\n<p><strong>Examples</strong></p>\n<pre><code class=\"language-feel\">week of year(date(&quot;2019-09-17&quot;))\n// 38\n\nweek of year(date and time(&quot;2019-09-17T12:00:00&quot;))\n// 38\n</code></pre>\n"
64507
+ }, {
64508
+ "name": "month of year",
64509
+ "type": "function",
64510
+ "params": [{
64511
+ "name": "date"
64512
+ }],
64513
+ "info": "<p>Returns the month of the year according to the Gregorian calendar. Note that it always returns the English name of the month.</p>\n<p><strong>Function signature</strong></p>\n<pre><code class=\"language-feel\">month of year(date: date): string\n</code></pre>\n<pre><code class=\"language-feel\">month of year(date: date and time): string\n</code></pre>\n<p><strong>Examples</strong></p>\n<pre><code class=\"language-feel\">month of year(date(&quot;2019-09-17&quot;))\n// &quot;September&quot;\n\nmonth of year(date and time(&quot;2019-09-17T12:00:00&quot;))\n// &quot;September&quot;\n</code></pre>\n"
64514
+ }, {
64515
+ "name": "abs",
64516
+ "type": "function",
64517
+ "params": [{
64518
+ "name": "n"
64519
+ }],
64520
+ "info": "<p>Returns the absolute value of a given duration.</p>\n<p><strong>Function signature</strong></p>\n<pre><code class=\"language-feel\">abs(n: days and time duration): days and time duration\n</code></pre>\n<pre><code class=\"language-feel\">abs(n: years and months duration): years and months duration\n</code></pre>\n<p><strong>Examples</strong></p>\n<pre><code class=\"language-feel\">abs(duration(&quot;-PT5H&quot;))\n// &quot;duration(&quot;PT5H&quot;)&quot;\n\nabs(duration(&quot;PT5H&quot;))\n// &quot;duration(&quot;PT5H&quot;)&quot;\n\nabs(duration(&quot;-P2M&quot;))\n// duration(&quot;P2M&quot;)\n</code></pre>\n"
64521
+ }];
64522
+
64523
+ /**
64524
+ * List of FEEL camunda extensions.
64525
+ *
64526
+ * @type { Builtin[] }
64527
+ */
64528
+ const camundaExtensions = [{
64529
+ "name": "is defined",
64530
+ "type": "function",
64531
+ "params": [{
64532
+ "name": "value"
64533
+ }],
64534
+ "info": "<p><em>Camunda Extension</em></p>\n<p>Checks if a given value is not <code>null</code>. If the value is <code>null</code> then the function returns <code>false</code>.\nOtherwise, the function returns <code>true</code>.</p>\n<p><strong>Function signature</strong></p>\n<pre><code class=\"language-feel\">is defined(value: Any): boolean\n</code></pre>\n<p><strong>Examples</strong></p>\n<pre><code class=\"language-feel\">is defined(1)\n// true\n\nis defined(null)\n// false\n\nis defined(x)\n// false - if no variable &quot;x&quot; exists\n\nis defined(x.y)\n// false - if no variable &quot;x&quot; exists or it doesn&#39;t have a property &quot;y&quot;\n</code></pre>\n<p>:::caution Breaking change</p>\n<p>This function worked differently in previous versions. It returned <code>true</code> if the value was <code>null</code>.\nSince this version, the function returns <code>false</code> if the value is <code>null</code>.</p>\n<p>:::</p>\n"
64535
+ }, {
64536
+ "name": "get or else",
64537
+ "type": "function",
64538
+ "params": [{
64539
+ "name": "value"
64540
+ }, {
64541
+ "name": "default"
64542
+ }],
64543
+ "info": "<p><em>Camunda Extension</em></p>\n<p>Return the provided value parameter if not <code>null</code>, otherwise return the default parameter</p>\n<p><strong>Function signature</strong></p>\n<pre><code class=\"language-feel\">get or else(value: Any, default: Any): Any\n</code></pre>\n<p><strong>Examples</strong></p>\n<pre><code class=\"language-feel\">get or else(&quot;this&quot;, &quot;default&quot;)\n// &quot;this&quot;\n\nget or else(null, &quot;default&quot;)\n// &quot;default&quot;\n\nget or else(null, null)\n// null\n</code></pre>\n"
64544
+ }, {
64545
+ "name": "assert",
64546
+ "type": "function",
64547
+ "params": [{
64548
+ "name": "value"
64549
+ }, {
64550
+ "name": "condition"
64551
+ }],
64552
+ "info": "<p><em>Camunda Extension</em></p>\n<p>Verify that the given condition is met. If the condition is <code>true</code>, the function returns the value.\nOtherwise, the evaluation fails with an error.</p>\n<p><strong>Function signature</strong></p>\n<pre><code class=\"language-feel\">assert(value: Any, condition: Any)\n</code></pre>\n<p><strong>Examples</strong></p>\n<pre><code class=\"language-feel\">assert(x, x != null)\n// &quot;value&quot; - if x is &quot;value&quot;\n// error - if x is null or doesn&#39;t exist\n\nassert(x, x &gt;= 0)\n// 4 - if x is 4\n// error - if x is less than zero\n</code></pre>\n"
64553
+ }, {
64554
+ "name": "assert",
64555
+ "type": "function",
64556
+ "params": [{
64557
+ "name": "value"
64558
+ }, {
64559
+ "name": "condition"
64560
+ }, {
64561
+ "name": "cause"
64562
+ }],
64563
+ "info": "<p><em>Camunda Extension</em></p>\n<p>Verify that the given condition is met. If the condition is <code>true</code>, the function returns the value.\nOtherwise, the evaluation fails with an error containing the given message.</p>\n<p><strong>Function signature</strong></p>\n<pre><code class=\"language-feel\">assert(value: Any, condition: Any, cause: String)\n</code></pre>\n<p><strong>Examples</strong></p>\n<pre><code class=\"language-feel\">assert(x, x != null, &quot;&#39;x&#39; should not be null&quot;)\n// &quot;value&quot; - if x is &quot;value&quot;\n// error(&#39;x&#39; should not be null) - if x is null or doesn&#39;t exist\n\nassert(x, x &gt;= 0, &quot;&#39;x&#39; should be positive&quot;)\n// 4 - if x is 4\n// error(&#39;x&#39; should be positive) - if x is less than zero\n</code></pre>\n"
64564
+ }, {
64565
+ "name": "get value",
64566
+ "type": "function",
64567
+ "params": [{
64568
+ "name": "context"
64569
+ }, {
64570
+ "name": "keys"
64571
+ }],
64572
+ "info": "<p><em>Camunda Extension</em></p>\n<p>Returns the value of the context entry for a context path defined by the given keys.</p>\n<p>If <code>keys</code> contains the keys <code>[k1, k2]</code> then it returns the value at the nested entry <code>k1.k2</code> of the context.</p>\n<p>If <code>keys</code> are empty or the nested entry defined by the keys doesn&#39;t exist in the context, it returns <code>null</code>.</p>\n<p><strong>Function signature</strong></p>\n<pre><code class=\"language-feel\">get value(context: context, keys: list&lt;string&gt;): Any\n</code></pre>\n<p><strong>Examples</strong></p>\n<pre><code class=\"language-feel\">get value({x:1, y: {z:0}}, [&quot;y&quot;, &quot;z&quot;])\n// 0\n\nget value({x: {y: {z:0}}}, [&quot;x&quot;, &quot;y&quot;])\n// {z:0}\n\nget value({a: {b: 3}}, [&quot;b&quot;])\n// null\n</code></pre>\n"
64573
+ }, {
64574
+ "name": "context put",
64575
+ "type": "function",
64576
+ "params": [{
64577
+ "name": "context"
64578
+ }, {
64579
+ "name": "key"
64580
+ }, {
64581
+ "name": "value"
64582
+ }],
64583
+ "info": "<p>Adds a new entry with the given key and value to the context. Returns a new context that includes the entry.</p>\n<p>If an entry for the same key already exists in the context, it overrides the value.</p>\n<p><strong>Function signature</strong></p>\n<pre><code class=\"language-feel\">context put(context: context, key: string, value: Any): context\n</code></pre>\n<p><strong>Examples</strong></p>\n<pre><code class=\"language-feel\">context put({x:1}, &quot;y&quot;, 2)\n// {x:1, y:2}\n</code></pre>\n<p>:::info\nThe function <code>context put()</code> replaced the previous function <code>put()</code> (Camunda Extension). The\nprevious function is deprecated and should not be used anymore.\n:::</p>\n"
64584
+ }, {
64585
+ "name": "context merge",
64586
+ "type": "function",
64587
+ "params": [{
64588
+ "name": "contexts"
64589
+ }],
64590
+ "info": "<p>Union the given contexts. Returns a new context that includes all entries of the given contexts.</p>\n<p>If an entry for the same key already exists in a context, it overrides the value. The entries are overridden in the same order as in the list of contexts.</p>\n<p><strong>Function signature</strong></p>\n<pre><code class=\"language-feel\">context merge(contexts: list&lt;context&gt;): context\n</code></pre>\n<p><strong>Examples</strong></p>\n<pre><code class=\"language-feel\">context merge([{x:1}, {y:2}])\n// {x:1, y:2}\n\ncontext merge([{x:1, y: 0}, {y:2}])\n// {x:1, y:2}\n</code></pre>\n<p>:::info\nThe function <code>context merge()</code> replaced the previous function <code>put all()</code> (Camunda Extension). The\nprevious function is deprecated and should not be used anymore.\n:::</p>\n"
64591
+ }, {
64592
+ "name": "date and time",
64593
+ "type": "function",
64594
+ "params": [{
64595
+ "name": "date"
64596
+ }, {
64597
+ "name": "timezone"
64598
+ }],
64599
+ "info": "<p><em>Camunda Extension</em></p>\n<p>Returns the given date and time value at the given timezone.</p>\n<p>If <code>date</code> has a different timezone than <code>timezone</code> then it adjusts the time to match the local time of <code>timezone</code>.</p>\n<p><strong>Function signature</strong></p>\n<pre><code class=\"language-feel\">date and time(date: date and time, timezone: string): date and time\n</code></pre>\n<p><strong>Examples</strong></p>\n<pre><code class=\"language-feel\">date and time(@&quot;2020-07-31T14:27:30@Europe/Berlin&quot;, &quot;America/Los_Angeles&quot;)\n// date and time(&quot;2020-07-31T05:27:30@America/Los_Angeles&quot;)\n\ndate and time(@&quot;2020-07-31T14:27:30&quot;, &quot;Z&quot;)\n// date and time(&quot;2020-07-31T12:27:30Z&quot;)\n</code></pre>\n"
64600
+ }, {
64601
+ "name": "duplicate values",
64602
+ "type": "function",
64603
+ "params": [{
64604
+ "name": "list"
64605
+ }],
64606
+ "info": "<p><em>Camunda Extension</em></p>\n<p>Returns all duplicate values of the given list.</p>\n<p><strong>Function signature</strong></p>\n<pre><code class=\"language-feel\">duplicate values(list: list): list\n</code></pre>\n<p><strong>Examples</strong></p>\n<pre><code class=\"language-feel\">duplicate values([1,2,3,2,1])\n// [1,2]\n</code></pre>\n"
64607
+ }, {
64608
+ "name": "string join",
64609
+ "type": "function",
64610
+ "params": [{
64611
+ "name": "list"
64612
+ }, {
64613
+ "name": "delimiter"
64614
+ }, {
64615
+ "name": "prefix"
64616
+ }, {
64617
+ "name": "suffix"
64618
+ }],
64619
+ "info": "<p><em>Camunda Extension</em></p>\n<p>Joins a list of strings into a single string. This is similar to\nJava&#39;s <a href=\"https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/stream/Collectors.html#joining(java.lang.CharSequence,java.lang.CharSequence,java.lang.CharSequence)\">joining</a>\nfunction.</p>\n<p>If an item of the list is <code>null</code>, the item is ignored for the result string. If an item is\nneither a string nor <code>null</code>, the function returns <code>null</code> instead of a string.</p>\n<p>The resulting string starts with <code>prefix</code>, contains a <code>delimiter</code> between each element, and ends\nwith <code>suffix</code>.</p>\n<p><strong>Function signature</strong></p>\n<pre><code class=\"language-feel\">string join(list: list&lt;string&gt;, delimiter: string, prefix: string, suffix: string): string\n</code></pre>\n<p><strong>Examples</strong></p>\n<pre><code class=\"language-feel\">string join([&quot;a&quot;,&quot;b&quot;,&quot;c&quot;], &quot;, &quot;, &quot;[&quot;, &quot;]&quot;)\n// &quot;[a, b, c]&quot;\n</code></pre>\n"
64620
+ }, {
64621
+ "name": "is empty",
64622
+ "type": "function",
64623
+ "params": [{
64624
+ "name": "list"
64625
+ }],
64626
+ "info": "<p><em>Camunda Extension</em></p>\n<p>Returns <code>true</code> if the given list is empty. Otherwise, returns <code>false</code>.</p>\n<p><strong>Function signature</strong></p>\n<pre><code class=\"language-feel\">is empty(list: list): boolean\n</code></pre>\n<p><strong>Examples</strong></p>\n<pre><code class=\"language-feel\">is empty([])\n// true\n\nis empty([1,2,3])\n// false\n</code></pre>\n"
64627
+ }, {
64628
+ "name": "partition",
64629
+ "type": "function",
64630
+ "params": [{
64631
+ "name": "list"
64632
+ }, {
64633
+ "name": "size"
64634
+ }],
64635
+ "info": "<p><em>Camunda Extension</em></p>\n<p>Returns consecutive sublists of a list, each of the same size (the final list may be smaller).</p>\n<p>If <code>size</code> is less than <code>0</code>, it returns <code>null</code>.</p>\n<p><strong>Function signature</strong></p>\n<pre><code class=\"language-feel\">partition(list: list, size: number): list\n</code></pre>\n<p><strong>Examples</strong></p>\n<pre><code class=\"language-feel\">partition([1,2,3,4,5], 2)\n// [[1,2], [3,4], [5]]\n\npartition([], 2)\n// []\n\npartition([1,2], 0)\n// null\n</code></pre>\n"
64636
+ }, {
64637
+ "name": "fromAi",
64638
+ "type": "function",
64639
+ "params": [{
64640
+ "name": "value"
64641
+ }],
64642
+ "info": "<p><em>Camunda Extension</em></p>\n<p>Returns the unmodified <code>value</code> parameter.</p>\n<ul>\n<li>The purpose of this function is solely to tag the value as being generated by an AI integration.</li>\n<li>The actual handling is not performed by the FEEL engine, but by a custom integration such as a connector or a job worker.</li>\n</ul>\n<p>The main use case of this function is for <a href=\"../../../connectors/out-of-the-box-connectors/agentic-ai-aiagent-tool-definitions.md\">tool definitions</a> used by the <a href=\"../../../connectors/out-of-the-box-connectors/agentic-ai-aiagent.md\">AI Agent connector</a>.</p>\n<p>See the following function overloads for additional function parameters.</p>\n<p><strong>Function signature</strong></p>\n<pre><code class=\"language-feel\">fromAi(value: Any): Any\n</code></pre>\n<p><strong>Examples</strong></p>\n<pre><code class=\"language-feel\">fromAi(toolCall.searchQuery)\n// toolCall.searchQuery contents\n\nfromAi(toolCall.userId)\n// toolCall.userId contents\n</code></pre>\n"
64643
+ }, {
64644
+ "name": "fromAi",
64645
+ "type": "function",
64646
+ "params": [{
64647
+ "name": "value"
64648
+ }, {
64649
+ "name": "description"
64650
+ }],
64651
+ "info": "<p><em>Camunda Extension</em></p>\n<p>Returns the unmodified <code>value</code> parameter.</p>\n<p>In addition to the previous overload, it also accepts an optional <code>description</code> parameter to provide a textual description of the value. The description must be <code>null</code> or a string constant.</p>\n<p><strong>Function signature</strong></p>\n<pre><code class=\"language-feel\">fromAi(value: Any, description: string): Any\n</code></pre>\n<p><strong>Examples</strong></p>\n<pre><code class=\"language-feel\">fromAi(toolCall.searchQuery, &quot;The search query used to find the best match.&quot;)\n// toolCall.searchQuery contents\n\nfromAi(toolCall.searchQuery, null)\n// toolCall.searchQuery contents\n</code></pre>\n"
64652
+ }, {
64653
+ "name": "fromAi",
64654
+ "type": "function",
64655
+ "params": [{
64656
+ "name": "value"
64657
+ }, {
64658
+ "name": "description"
64659
+ }, {
64660
+ "name": "type"
64661
+ }],
64662
+ "info": "<p><em>Camunda Extension</em></p>\n<p>Returns the unmodified <code>value</code> parameter.</p>\n<p>In addition to the previous overload, it also accepts an optional <code>type</code> parameter to provide type information about the value. The type must be <code>null</code> or a string constant.</p>\n<p><strong>Function signature</strong></p>\n<pre><code class=\"language-feel\">fromAi(value: Any, description: string, type: string): Any\n</code></pre>\n<p><strong>Examples</strong></p>\n<pre><code class=\"language-feel\">fromAi(toolCall.searchQuery, &quot;The search query used to find the best match.&quot;, &quot;string&quot;)\n// toolCall.searchQuery contents\n\nfromAi(toolCall.userId, &quot;The user&#39;s ID&quot;, &quot;number&quot;)\n// toolCall.userId contents\n\nfromAi(toolCall.userId, null, &quot;number&quot;)\n// toolCall.userId contents\n\nfromAi(value: toolCall.userId, type: &quot;number&quot;)\n// toolCall.userId contents\n</code></pre>\n"
64663
+ }, {
64664
+ "name": "fromAi",
64665
+ "type": "function",
64666
+ "params": [{
64667
+ "name": "value"
64668
+ }, {
64669
+ "name": "description"
64670
+ }, {
64671
+ "name": "type"
64672
+ }, {
64673
+ "name": "schema"
64674
+ }],
64675
+ "info": "<p><em>Camunda Extension</em></p>\n<p>Returns the unmodified <code>value</code> parameter.</p>\n<p>In addition to the previous overload, it also accepts an optional <code>schema</code> parameter to provide a (partial) <a href=\"https://json-schema.org/\">JSON schema</a> for the value.</p>\n<ul>\n<li>The schema must be <code>null</code> or a context (map) containing only constant values. For example, function calls within the schema are not supported.</li>\n<li>The schema is not validated by the FEEL engine but might be by a custom integration consuming the information.</li>\n<li>From the engine side it is possible to specify both a <code>type</code> and a <code>schema</code>, and it depends on the integration as to which value takes precedence. The <a href=\"../../../connectors/out-of-the-box-connectors/agentic-ai-aiagent.md\">AI Agent connector</a> will override any type specified in the schema if the <code>type</code> parameter is also provided.</li>\n</ul>\n<p><strong>Function signature</strong></p>\n<pre><code class=\"language-feel\">fromAi(value: Any, description: string, type: string, schema: context): Any\n</code></pre>\n<p><strong>Examples</strong></p>\n<pre><code class=\"language-feel\">fromAi(toolCall.documentType, &quot;The document type to provide&quot;, &quot;string&quot;, {\n enum: [&quot;invoice&quot;, &quot;receipt&quot;, &quot;contract&quot;]\n})\n// toolCall.documentType contents\n\nfromAi(value: toolCall.documentType, description: &quot;The document type to provide&quot;, schema: {\n type: &quot;string&quot;,\n enum: [&quot;invoice&quot;, &quot;receipt&quot;, &quot;contract&quot;]\n})\n// toolCall.documentType contents\n\nfromAi(toolCall.tags, &quot;Tags to apply to the blog post&quot;, &quot;array&quot;, {\n items: {\n type: &quot;string&quot;\n }\n})\n// toolCall.tags contents\n</code></pre>\n"
64676
+ }, {
64677
+ "name": "fromAi",
64678
+ "type": "function",
64679
+ "params": [{
64680
+ "name": "value"
64681
+ }, {
64682
+ "name": "description"
64683
+ }, {
64684
+ "name": "type"
64685
+ }, {
64686
+ "name": "schema"
64687
+ }, {
64688
+ "name": "options"
64689
+ }],
64690
+ "info": "<p><em>Camunda Extension</em></p>\n<p>Returns the unmodified <code>value</code> parameter.</p>\n<p>In addition to the previous overload, it also accepts an optional <code>options</code> parameter to provide additional options for the integration handling the value definition.</p>\n<ul>\n<li>The options parameter must be <code>null</code> or a context (map) containing only constant values. For example, function calls within options are not supported.</li>\n</ul>\n<p><strong>Function signature</strong></p>\n<pre><code class=\"language-feel\">fromAi(value: Any, description: string, type: string, schema: context, options: context): Any\n</code></pre>\n<p><strong>Examples</strong></p>\n<pre><code class=\"language-feel\">fromAi(toolCall.documentType, &quot;The document type to provide&quot;, &quot;string&quot;, null, {\n required: false\n})\n// toolCall.documentType contents\n\nfromAi(value: toolCall.documentType, options: {\n required: false\n})\n// toolCall.documentType contents\n</code></pre>\n"
64691
+ }, {
64692
+ "name": "random number",
64693
+ "type": "function",
64694
+ "params": [],
64695
+ "info": "<p><em>Camunda Extension</em></p>\n<p>Returns a random number between <code>0</code> and <code>1</code>.</p>\n<p><strong>Function signature</strong></p>\n<pre><code class=\"language-feel\">random number(): number\n</code></pre>\n<p><strong>Examples</strong></p>\n<pre><code class=\"language-feel\">random number()\n// 0.9701618132579795\n</code></pre>\n"
64492
64696
  }, {
64493
64697
  "name": "extract",
64494
64698
  "type": "function",
@@ -64524,51 +64728,6 @@ Please report this to https://github.com/markedjs/marked.`, e) {
64524
64728
  "name": "string"
64525
64729
  }],
64526
64730
  "info": "<p><em>Camunda Extension</em></p>\n<p>Returns <code>true</code> if the given string is blank (empty or contains only whitespaces).</p>\n<p><strong>Function signature</strong></p>\n<pre><code class=\"language-feel\">is blank(string: string): boolean\n</code></pre>\n<p><strong>Examples</strong></p>\n<pre><code class=\"language-feel\">is blank(&quot;&quot;)\n// true\n\nis blank(&quot; &quot;)\n// true\n\nis blank(&quot;hello world&quot;)\n// false\n</code></pre>\n"
64527
- }, {
64528
- "name": "now",
64529
- "type": "function",
64530
- "params": [],
64531
- "info": "<p>Returns the current date and time including the timezone.</p>\n<p><strong>Function signature</strong></p>\n<pre><code class=\"language-feel\">now(): date and time\n</code></pre>\n<p><strong>Examples</strong></p>\n<pre><code class=\"language-feel\">now()\n// date and time(&quot;2020-07-31T14:27:30@Europe/Berlin&quot;)\n</code></pre>\n"
64532
- }, {
64533
- "name": "today",
64534
- "type": "function",
64535
- "params": [],
64536
- "info": "<p>Returns the current date.</p>\n<p><strong>Function signature</strong></p>\n<pre><code class=\"language-feel\">today(): date\n</code></pre>\n<p><strong>Examples</strong></p>\n<pre><code class=\"language-feel\">today()\n// date(&quot;2020-07-31&quot;)\n</code></pre>\n"
64537
- }, {
64538
- "name": "day of week",
64539
- "type": "function",
64540
- "params": [{
64541
- "name": "date"
64542
- }],
64543
- "info": "<p>Returns the day of the week according to the Gregorian calendar. Note that it always returns the English name of the day.</p>\n<p><strong>Function signature</strong></p>\n<pre><code class=\"language-feel\">day of week(date: date): string\n</code></pre>\n<pre><code class=\"language-feel\">day of week(date: date and time): string\n</code></pre>\n<p><strong>Examples</strong></p>\n<pre><code class=\"language-feel\">day of week(date(&quot;2019-09-17&quot;))\n// &quot;Tuesday&quot;\n\nday of week(date and time(&quot;2019-09-17T12:00:00&quot;))\n// &quot;Tuesday&quot;\n</code></pre>\n"
64544
- }, {
64545
- "name": "day of year",
64546
- "type": "function",
64547
- "params": [{
64548
- "name": "date"
64549
- }],
64550
- "info": "<p>Returns the Gregorian number of the day within the year.</p>\n<p><strong>Function signature</strong></p>\n<pre><code class=\"language-feel\">day of year(date: date): number\n</code></pre>\n<pre><code class=\"language-feel\">day of year(date: date and time): number\n</code></pre>\n<p><strong>Examples</strong></p>\n<pre><code class=\"language-feel\">day of year(date(&quot;2019-09-17&quot;))\n// 260\n\nday of year(date and time(&quot;2019-09-17T12:00:00&quot;))\n// 260\n</code></pre>\n"
64551
- }, {
64552
- "name": "week of year",
64553
- "type": "function",
64554
- "params": [{
64555
- "name": "date"
64556
- }],
64557
- "info": "<p>Returns the Gregorian number of the week within the year, according to ISO 8601.</p>\n<p><strong>Function signature</strong></p>\n<pre><code class=\"language-feel\">week of year(date: date): number\n</code></pre>\n<pre><code class=\"language-feel\">week of year(date: date and time): number\n</code></pre>\n<p><strong>Examples</strong></p>\n<pre><code class=\"language-feel\">week of year(date(&quot;2019-09-17&quot;))\n// 38\n\nweek of year(date and time(&quot;2019-09-17T12:00:00&quot;))\n// 38\n</code></pre>\n"
64558
- }, {
64559
- "name": "month of year",
64560
- "type": "function",
64561
- "params": [{
64562
- "name": "date"
64563
- }],
64564
- "info": "<p>Returns the month of the year according to the Gregorian calendar. Note that it always returns the English name of the month.</p>\n<p><strong>Function signature</strong></p>\n<pre><code class=\"language-feel\">month of year(date: date): string\n</code></pre>\n<pre><code class=\"language-feel\">month of year(date: date and time): string\n</code></pre>\n<p><strong>Examples</strong></p>\n<pre><code class=\"language-feel\">month of year(date(&quot;2019-09-17&quot;))\n// &quot;September&quot;\n\nmonth of year(date and time(&quot;2019-09-17T12:00:00&quot;))\n// &quot;September&quot;\n</code></pre>\n"
64565
- }, {
64566
- "name": "abs",
64567
- "type": "function",
64568
- "params": [{
64569
- "name": "n"
64570
- }],
64571
- "info": "<p>Returns the absolute value of a given duration.</p>\n<p><strong>Function signature</strong></p>\n<pre><code class=\"language-feel\">abs(n: days and time duration): days and time duration\n</code></pre>\n<pre><code class=\"language-feel\">abs(n: years and months duration): years and months duration\n</code></pre>\n<p><strong>Examples</strong></p>\n<pre><code class=\"language-feel\">abs(duration(&quot;-PT5H&quot;))\n// &quot;duration(&quot;PT5H&quot;)&quot;\n\nabs(duration(&quot;PT5H&quot;))\n// &quot;duration(&quot;PT5H&quot;)&quot;\n\nabs(duration(&quot;-P2M&quot;))\n// duration(&quot;P2M&quot;)\n</code></pre>\n"
64572
64731
  }, {
64573
64732
  "name": "last day of month",
64574
64733
  "type": "function",
@@ -64578,6 +64737,13 @@ Please report this to https://github.com/markedjs/marked.`, e) {
64578
64737
  "info": "<p><em>Camunda Extension</em></p>\n<p>Takes the month of the given date or date-time value and returns the last day of this month.</p>\n<p><strong>Function signature</strong></p>\n<pre><code class=\"language-feel\">last day of month(date: date): date\n</code></pre>\n<pre><code class=\"language-feel\">last day of month(date: date and time): date\n</code></pre>\n<p><strong>Examples</strong></p>\n<pre><code class=\"language-feel\">last day of month(date(&quot;2022-10-01&quot;))\n// date(&quot;2022-10-31&quot;))\n\nlast day of month(date and time(&quot;2022-10-16T12:00:00&quot;))\n// date(&quot;2022-10-31&quot;))\n</code></pre>\n"
64579
64738
  }];
64580
64739
 
64740
+ /**
64741
+ * Collection of builtins of camunda scala FEEL.
64742
+ *
64743
+ * @type { Builtin[] }
64744
+ */
64745
+ const camundaBuiltins = [...feelBuiltins, ...camundaExtensions];
64746
+
64581
64747
  var linter = [linter$1(cmFeelLinter())];
64582
64748
  const baseTheme$2 = EditorView.theme({
64583
64749
  '& .cm-content': {
@@ -65107,6 +65273,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
65107
65273
  builtins = domifiedBuiltins,
65108
65274
  variables = []
65109
65275
  }) {
65276
+ this._events = mitt();
65110
65277
  const changeHandler = EditorView.updateListener.of(update => {
65111
65278
  if (update.docChanged) {
65112
65279
  onChange(update.state.doc.toString());
@@ -65117,10 +65284,12 @@ Please report this to https://github.com/markedjs/marked.`, e) {
65117
65284
  if (!diagnosticEffects.length) {
65118
65285
  return;
65119
65286
  }
65120
- const messages = diagnosticEffects.flatMap(effect => effect.value);
65121
- onLint(messages);
65287
+ const diagnostics = diagnosticEffects.flatMap(effect => effect.value);
65288
+ this._events.emit('lint', {
65289
+ diagnostics
65290
+ });
65122
65291
  });
65123
- const keyHandler = EditorView.domEventHandlers({
65292
+ const keyHandler = EditorView.domEventObservers({
65124
65293
  keydown: onKeyDown
65125
65294
  });
65126
65295
  if (typeof tooltipContainer === 'string') {
@@ -65140,6 +65309,9 @@ Please report this to https://github.com/markedjs/marked.`, e) {
65140
65309
  if (readOnly) {
65141
65310
  extensions.push(EditorView.editable.of(false));
65142
65311
  }
65312
+ this.on('lint', ({
65313
+ diagnostics
65314
+ }) => onLint(diagnostics));
65143
65315
  this._cmEditor = new EditorView({
65144
65316
  state: EditorState.create({
65145
65317
  doc: value,
@@ -65185,6 +65357,22 @@ Please report this to https://github.com/markedjs/marked.`, e) {
65185
65357
  }
65186
65358
  };
65187
65359
 
65360
+ /**
65361
+ * @param {string} eventName
65362
+ * @param {(event) => any} callback
65363
+ */
65364
+ FeelEditor$1.prototype.on = function (eventName, callback) {
65365
+ this._events.on(eventName, callback);
65366
+ };
65367
+
65368
+ /**
65369
+ * @param {string} eventName
65370
+ * @param {(event) => any} [callback]
65371
+ */
65372
+ FeelEditor$1.prototype.off = function (eventName, callback) {
65373
+ this._events.off(eventName, callback);
65374
+ };
65375
+
65188
65376
  /**
65189
65377
  * Returns the current selection ranges. If no text is selected, a single
65190
65378
  * range with the start and end index at the cursor position will be returned.
@@ -65222,15 +65410,12 @@ Please report this to https://github.com/markedjs/marked.`, e) {
65222
65410
  };
65223
65411
 
65224
65412
  /*!
65225
- * tabbable 6.2.0
65413
+ * tabbable 6.4.0
65226
65414
  * @license MIT, https://github.com/focus-trap/tabbable/blob/master/LICENSE
65227
65415
  */
65228
65416
  // NOTE: separate `:not()` selectors has broader browser support than the newer
65229
65417
  // `:not([inert], [inert] *)` (Feb 2023)
65230
- // CAREFUL: JSDom does not support `:not([inert] *)` as a selector; using it causes
65231
- // the entire query to fail, resulting in no nodes found, which will break a lot
65232
- // of things... so we have to rely on JS to identify nodes inside an inert container
65233
- var candidateSelectors = ['input:not([inert])', 'select:not([inert])', 'textarea:not([inert])', 'a[href]:not([inert])', 'button:not([inert])', '[tabindex]:not(slot):not([inert])', 'audio[controls]:not([inert])', 'video[controls]:not([inert])', '[contenteditable]:not([contenteditable="false"]):not([inert])', 'details>summary:first-of-type:not([inert])', 'details:not([inert])'];
65418
+ var candidateSelectors = ['input:not([inert]):not([inert] *)', 'select:not([inert]):not([inert] *)', 'textarea:not([inert]):not([inert] *)', 'a[href]:not([inert]):not([inert] *)', 'button:not([inert]):not([inert] *)', '[tabindex]:not(slot):not([inert]):not([inert] *)', 'audio[controls]:not([inert]):not([inert] *)', 'video[controls]:not([inert]):not([inert] *)', '[contenteditable]:not([contenteditable="false"]):not([inert]):not([inert] *)', 'details>summary:first-of-type:not([inert]):not([inert] *)', 'details:not([inert]):not([inert] *)'];
65234
65419
  var candidateSelector = /* #__PURE__ */candidateSelectors.join(',');
65235
65420
  var NoElement = typeof Element === 'undefined';
65236
65421
  var matches = NoElement ? function () {} : Element.prototype.matches || Element.prototype.msMatchesSelector || Element.prototype.webkitMatchesSelector;
@@ -65243,13 +65428,13 @@ Please report this to https://github.com/markedjs/marked.`, e) {
65243
65428
 
65244
65429
  /**
65245
65430
  * Determines if a node is inert or in an inert ancestor.
65246
- * @param {Element} [node]
65431
+ * @param {Node} [node]
65247
65432
  * @param {boolean} [lookUp] If true and `node` is not inert, looks up at ancestors to
65248
65433
  * see if any of them are inert. If false, only `node` itself is considered.
65249
65434
  * @returns {boolean} True if inert itself or by way of being in an inert ancestor.
65250
65435
  * False if `node` is falsy.
65251
65436
  */
65252
- var isInert = function isInert(node, lookUp) {
65437
+ var _isInert = function isInert(node, lookUp) {
65253
65438
  var _node$getAttribute;
65254
65439
  if (lookUp === void 0) {
65255
65440
  lookUp = true;
@@ -65263,10 +65448,10 @@ Please report this to https://github.com/markedjs/marked.`, e) {
65263
65448
  // NOTE: this could also be handled with `node.matches('[inert], :is([inert] *)')`
65264
65449
  // if it weren't for `matches()` not being a function on shadow roots; the following
65265
65450
  // code works for any kind of node
65266
- // CAREFUL: JSDom does not appear to support certain selectors like `:not([inert] *)`
65267
- // so it likely would not support `:is([inert] *)` either...
65268
- var result = inert || lookUp && node && isInert(node.parentNode); // recursive
65269
-
65451
+ var result = inert || lookUp && node && (
65452
+ // closest does not exist on shadow roots, so we fall back to a manual
65453
+ // lookup upward, in case it is not defined.
65454
+ typeof node.closest === 'function' ? node.closest('[inert]') : _isInert(node.parentNode));
65270
65455
  return result;
65271
65456
  };
65272
65457
 
@@ -65292,8 +65477,8 @@ Please report this to https://github.com/markedjs/marked.`, e) {
65292
65477
  */
65293
65478
  var getCandidates = function getCandidates(el, includeContainer, filter) {
65294
65479
  // even if `includeContainer=false`, we still have to check it for inertness because
65295
- // if it's inert, all its children are inert
65296
- if (isInert(el)) {
65480
+ // if it's inert (either by itself or via its parent), then all its children are inert
65481
+ if (_isInert(el)) {
65297
65482
  return [];
65298
65483
  }
65299
65484
  var candidates = Array.prototype.slice.apply(el.querySelectorAll(candidateSelector));
@@ -65338,12 +65523,12 @@ Please report this to https://github.com/markedjs/marked.`, e) {
65338
65523
  * @param {IterativeOptions} options
65339
65524
  * @returns {Array.<Element|CandidateScope>}
65340
65525
  */
65341
- var getCandidatesIteratively = function getCandidatesIteratively(elements, includeContainer, options) {
65526
+ var _getCandidatesIteratively = function getCandidatesIteratively(elements, includeContainer, options) {
65342
65527
  var candidates = [];
65343
65528
  var elementsToCheck = Array.from(elements);
65344
65529
  while (elementsToCheck.length) {
65345
65530
  var element = elementsToCheck.shift();
65346
- if (isInert(element, false)) {
65531
+ if (_isInert(element, false)) {
65347
65532
  // no need to look up since we're drilling down
65348
65533
  // anything inside this container will also be inert
65349
65534
  continue;
@@ -65352,7 +65537,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
65352
65537
  // add shadow dom slot scope (slot itself cannot be focusable)
65353
65538
  var assigned = element.assignedElements();
65354
65539
  var content = assigned.length ? assigned : element.children;
65355
- var nestedCandidates = getCandidatesIteratively(content, true, options);
65540
+ var nestedCandidates = _getCandidatesIteratively(content, true, options);
65356
65541
  if (options.flatten) {
65357
65542
  candidates.push.apply(candidates, nestedCandidates);
65358
65543
  } else {
@@ -65376,7 +65561,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
65376
65561
  // no inert look up because we're already drilling down and checking for inertness
65377
65562
  // on the way down, so all containers to this root node should have already been
65378
65563
  // vetted as non-inert
65379
- var validShadowRoot = !isInert(shadowRoot, false) && (!options.shadowRootFilter || options.shadowRootFilter(element));
65564
+ var validShadowRoot = !_isInert(shadowRoot, false) && (!options.shadowRootFilter || options.shadowRootFilter(element));
65380
65565
  if (shadowRoot && validShadowRoot) {
65381
65566
  // add shadow dom scope IIF a shadow root node was given; otherwise, an undisclosed
65382
65567
  // shadow exists, so look at light dom children as fallback BUT create a scope for any
@@ -65384,7 +65569,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
65384
65569
  // children of the web component element (which has the shadow), in the light dom, but
65385
65570
  // slotted somewhere _inside_ the undisclosed shadow) -- the scope is created below,
65386
65571
  // _after_ we return from this recursive call
65387
- var _nestedCandidates = getCandidatesIteratively(shadowRoot === true ? element.children : shadowRoot.children, true, options);
65572
+ var _nestedCandidates = _getCandidatesIteratively(shadowRoot === true ? element.children : shadowRoot.children, true, options);
65388
65573
  if (options.flatten) {
65389
65574
  candidates.push.apply(candidates, _nestedCandidates);
65390
65575
  } else {
@@ -65561,6 +65746,28 @@ Please report this to https://github.com/markedjs/marked.`, e) {
65561
65746
  var isHidden = function isHidden(node, _ref) {
65562
65747
  var displayCheck = _ref.displayCheck,
65563
65748
  getShadowRoot = _ref.getShadowRoot;
65749
+ if (displayCheck === 'full-native') {
65750
+ if ('checkVisibility' in node) {
65751
+ // Chrome >= 105, Edge >= 105, Firefox >= 106, Safari >= 17.4
65752
+ // @see https://developer.mozilla.org/en-US/docs/Web/API/Element/checkVisibility#browser_compatibility
65753
+ var visible = node.checkVisibility({
65754
+ // Checking opacity might be desirable for some use cases, but natively,
65755
+ // opacity zero elements _are_ focusable and tabbable.
65756
+ checkOpacity: false,
65757
+ opacityProperty: false,
65758
+ contentVisibilityAuto: true,
65759
+ visibilityProperty: true,
65760
+ // This is an alias for `visibilityProperty`. Contemporary browsers
65761
+ // support both. However, this alias has wider browser support (Chrome
65762
+ // >= 105 and Firefox >= 106, vs. Chrome >= 121 and Firefox >= 122), so
65763
+ // we include it anyway.
65764
+ checkVisibilityCSS: true
65765
+ });
65766
+ return !visible;
65767
+ }
65768
+ // Fall through to manual visibility checks
65769
+ }
65770
+
65564
65771
  // NOTE: visibility will be `undefined` if node is detached from the document
65565
65772
  // (see notes about this further down), which means we will consider it visible
65566
65773
  // (this is legacy behavior from a very long way back)
@@ -65574,7 +65781,10 @@ Please report this to https://github.com/markedjs/marked.`, e) {
65574
65781
  if (matches.call(nodeUnderDetails, 'details:not([open]) *')) {
65575
65782
  return true;
65576
65783
  }
65577
- if (!displayCheck || displayCheck === 'full' || displayCheck === 'legacy-full') {
65784
+ if (!displayCheck || displayCheck === 'full' ||
65785
+ // full-native can run this branch when it falls through in case
65786
+ // Element#checkVisibility is unsupported
65787
+ displayCheck === 'full-native' || displayCheck === 'legacy-full') {
65578
65788
  if (typeof getShadowRoot === 'function') {
65579
65789
  // figure out if we should consider the node to be in an undisclosed shadow and use the
65580
65790
  // 'non-zero-area' fallback
@@ -65683,11 +65893,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
65683
65893
  return false;
65684
65894
  };
65685
65895
  var isNodeMatchingSelectorFocusable = function isNodeMatchingSelectorFocusable(options, node) {
65686
- if (node.disabled ||
65687
- // we must do an inert look up to filter out any elements inside an inert ancestor
65688
- // because we're limited in the type of selectors we can use in JSDom (see related
65689
- // note related to `candidateSelectors`)
65690
- isInert(node) || isHiddenInput(node) || isHidden(node, options) ||
65896
+ if (node.disabled || isHiddenInput(node) || isHidden(node, options) ||
65691
65897
  // For a details element with a summary, the summary element gets the focus
65692
65898
  isDetailsWithSummary(node) || isDisabledFromFieldset(node)) {
65693
65899
  return false;
@@ -65700,7 +65906,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
65700
65906
  }
65701
65907
  return true;
65702
65908
  };
65703
- var isValidShadowRootTabbable = function isValidShadowRootTabbable(shadowHostNode) {
65909
+ var isShadowRootTabbable = function isShadowRootTabbable(shadowHostNode) {
65704
65910
  var tabIndex = parseInt(shadowHostNode.getAttribute('tabindex'), 10);
65705
65911
  if (isNaN(tabIndex) || tabIndex >= 0) {
65706
65912
  return true;
@@ -65714,14 +65920,14 @@ Please report this to https://github.com/markedjs/marked.`, e) {
65714
65920
  * @param {Array.<Element|CandidateScope>} candidates
65715
65921
  * @returns Element[]
65716
65922
  */
65717
- var sortByOrder = function sortByOrder(candidates) {
65923
+ var _sortByOrder = function sortByOrder(candidates) {
65718
65924
  var regularTabbables = [];
65719
65925
  var orderedTabbables = [];
65720
65926
  candidates.forEach(function (item, i) {
65721
65927
  var isScope = !!item.scopeParent;
65722
65928
  var element = isScope ? item.scopeParent : item;
65723
65929
  var candidateTabindex = getSortOrderTabIndex(element, isScope);
65724
- var elements = isScope ? sortByOrder(item.candidates) : element;
65930
+ var elements = isScope ? _sortByOrder(item.candidates) : element;
65725
65931
  if (candidateTabindex === 0) {
65726
65932
  isScope ? regularTabbables.push.apply(regularTabbables, elements) : regularTabbables.push(element);
65727
65933
  } else {
@@ -65743,22 +65949,22 @@ Please report this to https://github.com/markedjs/marked.`, e) {
65743
65949
  options = options || {};
65744
65950
  var candidates;
65745
65951
  if (options.getShadowRoot) {
65746
- candidates = getCandidatesIteratively([container], options.includeContainer, {
65952
+ candidates = _getCandidatesIteratively([container], options.includeContainer, {
65747
65953
  filter: isNodeMatchingSelectorTabbable.bind(null, options),
65748
65954
  flatten: false,
65749
65955
  getShadowRoot: options.getShadowRoot,
65750
- shadowRootFilter: isValidShadowRootTabbable
65956
+ shadowRootFilter: isShadowRootTabbable
65751
65957
  });
65752
65958
  } else {
65753
65959
  candidates = getCandidates(container, options.includeContainer, isNodeMatchingSelectorTabbable.bind(null, options));
65754
65960
  }
65755
- return sortByOrder(candidates);
65961
+ return _sortByOrder(candidates);
65756
65962
  };
65757
65963
  var focusable = function focusable(container, options) {
65758
65964
  options = options || {};
65759
65965
  var candidates;
65760
65966
  if (options.getShadowRoot) {
65761
- candidates = getCandidatesIteratively([container], options.includeContainer, {
65967
+ candidates = _getCandidatesIteratively([container], options.includeContainer, {
65762
65968
  filter: isNodeMatchingSelectorFocusable.bind(null, options),
65763
65969
  flatten: true,
65764
65970
  getShadowRoot: options.getShadowRoot
@@ -65778,7 +65984,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
65778
65984
  }
65779
65985
  return isNodeMatchingSelectorTabbable(options, node);
65780
65986
  };
65781
- var focusableCandidateSelector = /* #__PURE__ */candidateSelectors.concat('iframe').join(',');
65987
+ var focusableCandidateSelector = /* #__PURE__ */candidateSelectors.concat('iframe:not([inert]):not([inert] *)').join(',');
65782
65988
  var isFocusable = function isFocusable(node, options) {
65783
65989
  options = options || {};
65784
65990
  if (!node) {
@@ -65791,7 +65997,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
65791
65997
  };
65792
65998
 
65793
65999
  /*!
65794
- * focus-trap 7.6.5
66000
+ * focus-trap 8.0.0
65795
66001
  * @license MIT, https://github.com/focus-trap/focus-trap/blob/master/LICENSE
65796
66002
  */
65797
66003
  function _arrayLikeToArray(r, a) {
@@ -65802,6 +66008,79 @@ Please report this to https://github.com/markedjs/marked.`, e) {
65802
66008
  function _arrayWithoutHoles(r) {
65803
66009
  if (Array.isArray(r)) return _arrayLikeToArray(r);
65804
66010
  }
66011
+ function asyncGeneratorStep(n, t, e, r, o, a, c) {
66012
+ try {
66013
+ var i = n[a](c),
66014
+ u = i.value;
66015
+ } catch (n) {
66016
+ return void e(n);
66017
+ }
66018
+ i.done ? t(u) : Promise.resolve(u).then(r, o);
66019
+ }
66020
+ function _asyncToGenerator(n) {
66021
+ return function () {
66022
+ var t = this,
66023
+ e = arguments;
66024
+ return new Promise(function (r, o) {
66025
+ var a = n.apply(t, e);
66026
+ function _next(n) {
66027
+ asyncGeneratorStep(a, r, o, _next, _throw, "next", n);
66028
+ }
66029
+ function _throw(n) {
66030
+ asyncGeneratorStep(a, r, o, _next, _throw, "throw", n);
66031
+ }
66032
+ _next(void 0);
66033
+ });
66034
+ };
66035
+ }
66036
+ function _createForOfIteratorHelper(r, e) {
66037
+ var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"];
66038
+ if (!t) {
66039
+ if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e) {
66040
+ t && (r = t);
66041
+ var n = 0,
66042
+ F = function () {};
66043
+ return {
66044
+ s: F,
66045
+ n: function () {
66046
+ return n >= r.length ? {
66047
+ done: true
66048
+ } : {
66049
+ done: false,
66050
+ value: r[n++]
66051
+ };
66052
+ },
66053
+ e: function (r) {
66054
+ throw r;
66055
+ },
66056
+ f: F
66057
+ };
66058
+ }
66059
+ throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
66060
+ }
66061
+ var o,
66062
+ a = true,
66063
+ u = false;
66064
+ return {
66065
+ s: function () {
66066
+ t = t.call(r);
66067
+ },
66068
+ n: function () {
66069
+ var r = t.next();
66070
+ return a = r.done, r;
66071
+ },
66072
+ e: function (r) {
66073
+ u = true, o = r;
66074
+ },
66075
+ f: function () {
66076
+ try {
66077
+ a || null == t.return || t.return();
66078
+ } finally {
66079
+ if (u) throw o;
66080
+ }
66081
+ }
66082
+ };
66083
+ }
65805
66084
  function _defineProperty(e, r, t) {
65806
66085
  return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
65807
66086
  value: t,
@@ -65837,6 +66116,114 @@ Please report this to https://github.com/markedjs/marked.`, e) {
65837
66116
  }
65838
66117
  return e;
65839
66118
  }
66119
+ function _regenerator() {
66120
+ /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/babel/babel/blob/main/packages/babel-helpers/LICENSE */
66121
+ var e,
66122
+ t,
66123
+ r = "function" == typeof Symbol ? Symbol : {},
66124
+ n = r.iterator || "@@iterator",
66125
+ o = r.toStringTag || "@@toStringTag";
66126
+ function i(r, n, o, i) {
66127
+ var c = n && n.prototype instanceof Generator ? n : Generator,
66128
+ u = Object.create(c.prototype);
66129
+ return _regeneratorDefine(u, "_invoke", function (r, n, o) {
66130
+ var i,
66131
+ c,
66132
+ u,
66133
+ f = 0,
66134
+ p = o || [],
66135
+ y = false,
66136
+ G = {
66137
+ p: 0,
66138
+ n: 0,
66139
+ v: e,
66140
+ a: d,
66141
+ f: d.bind(e, 4),
66142
+ d: function (t, r) {
66143
+ return i = t, c = 0, u = e, G.n = r, a;
66144
+ }
66145
+ };
66146
+ function d(r, n) {
66147
+ for (c = r, u = n, t = 0; !y && f && !o && t < p.length; t++) {
66148
+ var o,
66149
+ i = p[t],
66150
+ d = G.p,
66151
+ l = i[2];
66152
+ r > 3 ? (o = l === n) && (u = i[(c = i[4]) ? 5 : (c = 3, 3)], i[4] = i[5] = e) : i[0] <= d && ((o = r < 2 && d < i[1]) ? (c = 0, G.v = n, G.n = i[1]) : d < l && (o = r < 3 || i[0] > n || n > l) && (i[4] = r, i[5] = n, G.n = l, c = 0));
66153
+ }
66154
+ if (o || r > 1) return a;
66155
+ throw y = true, n;
66156
+ }
66157
+ return function (o, p, l) {
66158
+ if (f > 1) throw TypeError("Generator is already running");
66159
+ for (y && 1 === p && d(p, l), c = p, u = l; (t = c < 2 ? e : u) || !y;) {
66160
+ i || (c ? c < 3 ? (c > 1 && (G.n = -1), d(c, u)) : G.n = u : G.v = u);
66161
+ try {
66162
+ if (f = 2, i) {
66163
+ if (c || (o = "next"), t = i[o]) {
66164
+ if (!(t = t.call(i, u))) throw TypeError("iterator result is not an object");
66165
+ if (!t.done) return t;
66166
+ u = t.value, c < 2 && (c = 0);
66167
+ } else 1 === c && (t = i.return) && t.call(i), c < 2 && (u = TypeError("The iterator does not provide a '" + o + "' method"), c = 1);
66168
+ i = e;
66169
+ } else if ((t = (y = G.n < 0) ? u : r.call(n, G)) !== a) break;
66170
+ } catch (t) {
66171
+ i = e, c = 1, u = t;
66172
+ } finally {
66173
+ f = 1;
66174
+ }
66175
+ }
66176
+ return {
66177
+ value: t,
66178
+ done: y
66179
+ };
66180
+ };
66181
+ }(r, o, i), true), u;
66182
+ }
66183
+ var a = {};
66184
+ function Generator() {}
66185
+ function GeneratorFunction() {}
66186
+ function GeneratorFunctionPrototype() {}
66187
+ t = Object.getPrototypeOf;
66188
+ var c = [][n] ? t(t([][n]())) : (_regeneratorDefine(t = {}, n, function () {
66189
+ return this;
66190
+ }), t),
66191
+ u = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(c);
66192
+ function f(e) {
66193
+ return Object.setPrototypeOf ? Object.setPrototypeOf(e, GeneratorFunctionPrototype) : (e.__proto__ = GeneratorFunctionPrototype, _regeneratorDefine(e, o, "GeneratorFunction")), e.prototype = Object.create(u), e;
66194
+ }
66195
+ return GeneratorFunction.prototype = GeneratorFunctionPrototype, _regeneratorDefine(u, "constructor", GeneratorFunctionPrototype), _regeneratorDefine(GeneratorFunctionPrototype, "constructor", GeneratorFunction), GeneratorFunction.displayName = "GeneratorFunction", _regeneratorDefine(GeneratorFunctionPrototype, o, "GeneratorFunction"), _regeneratorDefine(u), _regeneratorDefine(u, o, "Generator"), _regeneratorDefine(u, n, function () {
66196
+ return this;
66197
+ }), _regeneratorDefine(u, "toString", function () {
66198
+ return "[object Generator]";
66199
+ }), (_regenerator = function () {
66200
+ return {
66201
+ w: i,
66202
+ m: f
66203
+ };
66204
+ })();
66205
+ }
66206
+ function _regeneratorDefine(e, r, n, t) {
66207
+ var i = Object.defineProperty;
66208
+ try {
66209
+ i({}, "", {});
66210
+ } catch (e) {
66211
+ i = 0;
66212
+ }
66213
+ _regeneratorDefine = function (e, r, n, t) {
66214
+ function o(r, n) {
66215
+ _regeneratorDefine(e, r, function (e) {
66216
+ return this._invoke(r, n, e);
66217
+ });
66218
+ }
66219
+ r ? i ? i(e, r, {
66220
+ value: n,
66221
+ enumerable: !t,
66222
+ configurable: !t,
66223
+ writable: !t
66224
+ }) : e[r] = n : (o("next", 0), o("throw", 1), o("return", 2));
66225
+ }, _regeneratorDefine(e, r, n, t);
66226
+ }
65840
66227
  function _toConsumableArray(r) {
65841
66228
  return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread();
65842
66229
  }
@@ -65862,12 +66249,18 @@ Please report this to https://github.com/markedjs/marked.`, e) {
65862
66249
  }
65863
66250
  }
65864
66251
  var activeFocusTraps = {
66252
+ // Returns the trap from the top of the stack.
66253
+ getActiveTrap: function getActiveTrap(trapStack) {
66254
+ if ((trapStack === null || trapStack === void 0 ? void 0 : trapStack.length) > 0) {
66255
+ return trapStack[trapStack.length - 1];
66256
+ }
66257
+ return null;
66258
+ },
66259
+ // Pauses the currently active trap, then adds a new trap to the stack.
65865
66260
  activateTrap: function activateTrap(trapStack, trap) {
65866
- if (trapStack.length > 0) {
65867
- var activeTrap = trapStack[trapStack.length - 1];
65868
- if (activeTrap !== trap) {
65869
- activeTrap._setPausedState(true);
65870
- }
66261
+ var activeTrap = activeFocusTraps.getActiveTrap(trapStack);
66262
+ if (trap !== activeTrap) {
66263
+ activeFocusTraps.pauseTrap(trapStack);
65871
66264
  }
65872
66265
  var trapIndex = trapStack.indexOf(trap);
65873
66266
  if (trapIndex === -1) {
@@ -65878,13 +66271,24 @@ Please report this to https://github.com/markedjs/marked.`, e) {
65878
66271
  trapStack.push(trap);
65879
66272
  }
65880
66273
  },
66274
+ // Removes the trap from the top of the stack, then unpauses the next trap down.
65881
66275
  deactivateTrap: function deactivateTrap(trapStack, trap) {
65882
66276
  var trapIndex = trapStack.indexOf(trap);
65883
66277
  if (trapIndex !== -1) {
65884
66278
  trapStack.splice(trapIndex, 1);
65885
66279
  }
65886
- if (trapStack.length > 0 && !trapStack[trapStack.length - 1]._isManuallyPaused()) {
65887
- trapStack[trapStack.length - 1]._setPausedState(false);
66280
+ activeFocusTraps.unpauseTrap(trapStack);
66281
+ },
66282
+ // Pauses the trap at the top of the stack.
66283
+ pauseTrap: function pauseTrap(trapStack) {
66284
+ var activeTrap = activeFocusTraps.getActiveTrap(trapStack);
66285
+ activeTrap === null || activeTrap === void 0 || activeTrap._setPausedState(true);
66286
+ },
66287
+ // Unpauses the trap at the top of the stack.
66288
+ unpauseTrap: function unpauseTrap(trapStack) {
66289
+ var activeTrap = activeFocusTraps.getActiveTrap(trapStack);
66290
+ if (activeTrap && !activeTrap._isManuallyPaused()) {
66291
+ activeTrap._setPausedState(false);
65888
66292
  }
65889
66293
  }
65890
66294
  };
@@ -65947,29 +66351,31 @@ Please report this to https://github.com/markedjs/marked.`, e) {
65947
66351
  returnFocusOnDeactivate: true,
65948
66352
  escapeDeactivates: true,
65949
66353
  delayInitialFocus: true,
66354
+ isolateSubtrees: false,
65950
66355
  isKeyForward: isKeyForward,
65951
66356
  isKeyBackward: isKeyBackward
65952
66357
  }, userOptions);
65953
66358
  var state = {
65954
66359
  // containers given to createFocusTrap()
65955
- // @type {Array<HTMLElement>}
66360
+ /** @type {Array<HTMLElement>} */
65956
66361
  containers: [],
65957
66362
  // list of objects identifying tabbable nodes in `containers` in the trap
65958
66363
  // NOTE: it's possible that a group has no tabbable nodes if nodes get removed while the trap
65959
66364
  // is active, but the trap should never get to a state where there isn't at least one group
65960
66365
  // with at least one tabbable node in it (that would lead to an error condition that would
65961
66366
  // result in an error being thrown)
65962
- // @type {Array<{
65963
- // container: HTMLElement,
65964
- // tabbableNodes: Array<HTMLElement>, // empty if none
65965
- // focusableNodes: Array<HTMLElement>, // empty if none
65966
- // posTabIndexesFound: boolean,
65967
- // firstTabbableNode: HTMLElement|undefined,
65968
- // lastTabbableNode: HTMLElement|undefined,
65969
- // firstDomTabbableNode: HTMLElement|undefined,
65970
- // lastDomTabbableNode: HTMLElement|undefined,
65971
- // nextTabbableNode: (node: HTMLElement, forward: boolean) => HTMLElement|undefined
65972
- // }>}
66367
+ /** @type {Array<{
66368
+ * container: HTMLElement,
66369
+ * tabbableNodes: Array<HTMLElement>, // empty if none
66370
+ * focusableNodes: Array<HTMLElement>, // empty if none
66371
+ * posTabIndexesFound: boolean,
66372
+ * firstTabbableNode: HTMLElement|undefined,
66373
+ * lastTabbableNode: HTMLElement|undefined,
66374
+ * firstDomTabbableNode: HTMLElement|undefined,
66375
+ * lastDomTabbableNode: HTMLElement|undefined,
66376
+ * nextTabbableNode: (node: HTMLElement, forward: boolean) => HTMLElement|undefined
66377
+ * }>}
66378
+ */
65973
66379
  containerGroups: [],
65974
66380
  // same order/length as `containers` list
65975
66381
 
@@ -65978,6 +66384,12 @@ Please report this to https://github.com/markedjs/marked.`, e) {
65978
66384
  // NOTE: same order as `containers` and `containerGroups`, but __not necessarily__
65979
66385
  // the same length
65980
66386
  tabbableGroups: [],
66387
+ // references to nodes that are siblings to the ancestors of this trap's containers.
66388
+ /** @type {Set<HTMLElement>} */
66389
+ adjacentElements: new Set(),
66390
+ // references to nodes that were inert or aria-hidden before the trap was activated.
66391
+ /** @type {Set<HTMLElement>} */
66392
+ alreadySilent: new Set(),
65981
66393
  nodeFocusedBeforeActivation: null,
65982
66394
  mostRecentlyFocusedNode: null,
65983
66395
  active: false,
@@ -66366,7 +66778,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
66366
66778
  var checkPointerDown = function checkPointerDown(e) {
66367
66779
  var target = getActualTarget(e);
66368
66780
  if (findContainerIndex(target, e) >= 0) {
66369
- // allow the click since it ocurred inside the trap
66781
+ // allow the click since it occurred inside the trap
66370
66782
  return;
66371
66783
  }
66372
66784
  if (valueOrHandler(config.clickOutsideDeactivates, e)) {
@@ -66549,9 +66961,15 @@ Please report this to https://github.com/markedjs/marked.`, e) {
66549
66961
  // EVENT LISTENERS
66550
66962
  //
66551
66963
 
66964
+ /**
66965
+ * Adds listeners to the document necessary for trapping focus and attempts to set focus
66966
+ * to the configured initial focus node. Does nothing if the trap isn't active.
66967
+ * @returns {Promise<void>} Resolved (always) once the initial focus node has been focused.
66968
+ * Also resolved if the trap isn't active.
66969
+ */
66552
66970
  var addListeners = function addListeners() {
66553
66971
  if (!state.active) {
66554
- return;
66972
+ return Promise.resolve();
66555
66973
  }
66556
66974
 
66557
66975
  // There can be only one listening focus trap at a time
@@ -66559,9 +66977,21 @@ Please report this to https://github.com/markedjs/marked.`, e) {
66559
66977
 
66560
66978
  // Delay ensures that the focused element doesn't capture the event
66561
66979
  // that caused the focus trap activation.
66562
- state.delayInitialFocusTimer = config.delayInitialFocus ? delay(function () {
66980
+ /** @type {Promise<void>} */
66981
+ var promise;
66982
+ if (config.delayInitialFocus) {
66983
+ // NOTE: Promise constructor callback is called synchronously, which is what we want
66984
+ // since we need to capture the timer ID immediately
66985
+ promise = new Promise(function (resolve) {
66986
+ state.delayInitialFocusTimer = delay(function () {
66987
+ _tryFocus(getInitialFocusNode());
66988
+ resolve();
66989
+ });
66990
+ });
66991
+ } else {
66992
+ promise = Promise.resolve();
66563
66993
  _tryFocus(getInitialFocusNode());
66564
- }) : _tryFocus(getInitialFocusNode());
66994
+ }
66565
66995
  doc.addEventListener('focusin', checkFocusIn, true);
66566
66996
  doc.addEventListener('mousedown', checkPointerDown, {
66567
66997
  capture: true,
@@ -66580,7 +67010,75 @@ Please report this to https://github.com/markedjs/marked.`, e) {
66580
67010
  passive: false
66581
67011
  });
66582
67012
  doc.addEventListener('keydown', checkEscapeKey);
66583
- return trap;
67013
+ return promise;
67014
+ };
67015
+
67016
+ /**
67017
+ * Traverses up the DOM from each of `containers`, collecting references to
67018
+ * the elements that are siblings to `container` or an ancestor of `container`.
67019
+ * @param {Array<HTMLElement>} containers
67020
+ */
67021
+ var collectAdjacentElements = function collectAdjacentElements(containers) {
67022
+ // Re-activate all adjacent elements & clear previous collection.
67023
+ if (state.active && !state.paused) {
67024
+ trap._setSubtreeIsolation(false);
67025
+ }
67026
+ state.adjacentElements.clear();
67027
+ state.alreadySilent.clear();
67028
+
67029
+ // Collect all ancestors of all containers to avoid redundant processing.
67030
+ var containerAncestors = new Set();
67031
+ var adjacentElements = new Set();
67032
+
67033
+ // Compile all elements adjacent to the focus trap containers & lineage.
67034
+ var _iterator = _createForOfIteratorHelper(containers),
67035
+ _step;
67036
+ try {
67037
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
67038
+ var container = _step.value;
67039
+ containerAncestors.add(container);
67040
+ var insideShadowRoot = typeof ShadowRoot !== 'undefined' && container.getRootNode() instanceof ShadowRoot;
67041
+ var current = container;
67042
+ while (current) {
67043
+ containerAncestors.add(current);
67044
+ var parent = current.parentElement;
67045
+ var siblings = [];
67046
+ if (parent) {
67047
+ siblings = parent.children;
67048
+ } else if (!parent && insideShadowRoot) {
67049
+ siblings = current.getRootNode().children;
67050
+ parent = current.getRootNode().host;
67051
+ insideShadowRoot = typeof ShadowRoot !== 'undefined' && parent.getRootNode() instanceof ShadowRoot;
67052
+ }
67053
+
67054
+ // Add all the children, we'll remove container lineage later.
67055
+ var _iterator2 = _createForOfIteratorHelper(siblings),
67056
+ _step2;
67057
+ try {
67058
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
67059
+ var child = _step2.value;
67060
+ adjacentElements.add(child);
67061
+ }
67062
+ } catch (err) {
67063
+ _iterator2.e(err);
67064
+ } finally {
67065
+ _iterator2.f();
67066
+ }
67067
+ current = parent;
67068
+ }
67069
+ }
67070
+
67071
+ // Multi-container traps may overlap.
67072
+ // Remove elements within container lineages.
67073
+ } catch (err) {
67074
+ _iterator.e(err);
67075
+ } finally {
67076
+ _iterator.f();
67077
+ }
67078
+ containerAncestors.forEach(function (el) {
67079
+ adjacentElements["delete"](el);
67080
+ });
67081
+ state.adjacentElements = adjacentElements;
66584
67082
  };
66585
67083
  var removeListeners = function removeListeners() {
66586
67084
  if (!state.active) {
@@ -66650,26 +67148,73 @@ Please report this to https://github.com/markedjs/marked.`, e) {
66650
67148
  var onActivate = getOption(activateOptions, 'onActivate');
66651
67149
  var onPostActivate = getOption(activateOptions, 'onPostActivate');
66652
67150
  var checkCanFocusTrap = getOption(activateOptions, 'checkCanFocusTrap');
66653
- if (!checkCanFocusTrap) {
66654
- updateTabbableNodes();
67151
+
67152
+ // If a currently-active trap is isolating its subtree, we need to remove
67153
+ // that isolation to allow the new trap to find tabbable nodes.
67154
+ var preexistingTrap = activeFocusTraps.getActiveTrap(trapStack);
67155
+ var revertState = false;
67156
+ if (preexistingTrap && !preexistingTrap.paused) {
67157
+ var _preexistingTrap$_set;
67158
+ // [#1729] method MAY not exist if using `trapStack` option to share stack with older
67159
+ // versions of Focus-trap in the same DOM so use optional chaining here just in case
67160
+ // since this is a trap we may not have created from this instance of the library
67161
+ (_preexistingTrap$_set = preexistingTrap._setSubtreeIsolation) === null || _preexistingTrap$_set === void 0 || _preexistingTrap$_set.call(preexistingTrap, false);
67162
+ revertState = true;
66655
67163
  }
66656
- state.active = true;
66657
- state.paused = false;
66658
- state.nodeFocusedBeforeActivation = _getActiveElement(doc);
66659
- onActivate === null || onActivate === void 0 || onActivate();
66660
- var finishActivation = function finishActivation() {
66661
- if (checkCanFocusTrap) {
67164
+ try {
67165
+ if (!checkCanFocusTrap) {
66662
67166
  updateTabbableNodes();
66663
67167
  }
66664
- addListeners();
66665
- updateObservedNodes();
66666
- onPostActivate === null || onPostActivate === void 0 || onPostActivate();
66667
- };
66668
- if (checkCanFocusTrap) {
66669
- checkCanFocusTrap(state.containers.concat()).then(finishActivation, finishActivation);
66670
- return this;
67168
+ state.active = true;
67169
+ state.paused = false;
67170
+ state.nodeFocusedBeforeActivation = _getActiveElement(doc);
67171
+ onActivate === null || onActivate === void 0 || onActivate();
67172
+ var finishActivation = /*#__PURE__*/function () {
67173
+ var _ref6 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee() {
67174
+ return _regenerator().w(function (_context) {
67175
+ while (1) switch (_context.n) {
67176
+ case 0:
67177
+ if (checkCanFocusTrap) {
67178
+ updateTabbableNodes();
67179
+ }
67180
+
67181
+ // NOTE: wait for initial focus node to get focused before we potentially isolate
67182
+ // the subtrees with aria-hidden while focus is still in some other subtree and
67183
+ // not yet in the trap, resulting in some browsers (e.g. Chrome) logging to the
67184
+ // console that they, "Blocked aria-hidden on an element because its descendant
67185
+ // retained focus..."
67186
+ _context.n = 1;
67187
+ return addListeners();
67188
+ case 1:
67189
+ trap._setSubtreeIsolation(true);
67190
+ updateObservedNodes();
67191
+ onPostActivate === null || onPostActivate === void 0 || onPostActivate();
67192
+ case 2:
67193
+ return _context.a(2);
67194
+ }
67195
+ }, _callee);
67196
+ }));
67197
+ return function finishActivation() {
67198
+ return _ref6.apply(this, arguments);
67199
+ };
67200
+ }();
67201
+ if (checkCanFocusTrap) {
67202
+ checkCanFocusTrap(state.containers.concat()).then(finishActivation, finishActivation);
67203
+ return this;
67204
+ }
67205
+ finishActivation();
67206
+ } catch (error) {
67207
+ // If our activation throws an exception and the stack hasn't changed,
67208
+ // we need to re-enable the prior trap's subtree isolation.
67209
+ if (preexistingTrap === activeFocusTraps.getActiveTrap(trapStack) && revertState) {
67210
+ var _preexistingTrap$_set2;
67211
+ // [#1729] method MAY not exist if using `trapStack` option to share stack with older
67212
+ // versions of Focus-trap in the same DOM so use optional chaining here just in case
67213
+ // since this is a trap we may not have created from this instance of the library
67214
+ (_preexistingTrap$_set2 = preexistingTrap._setSubtreeIsolation) === null || _preexistingTrap$_set2 === void 0 || _preexistingTrap$_set2.call(preexistingTrap, true);
67215
+ }
67216
+ throw error;
66671
67217
  }
66672
- finishActivation();
66673
67218
  return this;
66674
67219
  },
66675
67220
  deactivate: function deactivate(deactivateOptions) {
@@ -66683,6 +67228,15 @@ Please report this to https://github.com/markedjs/marked.`, e) {
66683
67228
  }, deactivateOptions);
66684
67229
  clearTimeout(state.delayInitialFocusTimer); // noop if undefined
66685
67230
  state.delayInitialFocusTimer = undefined;
67231
+
67232
+ // Prior to removing this trap from the trapStack, we need to remove any applications of `inert`.
67233
+ // This allows the next trap down to update its tabbable nodes properly.
67234
+ //
67235
+ // If this trap is not top of the stack, don't change any current isolation.
67236
+ if (!state.paused) {
67237
+ trap._setSubtreeIsolation(false);
67238
+ }
67239
+ state.alreadySilent.clear();
66686
67240
  removeListeners();
66687
67241
  state.active = false;
66688
67242
  state.paused = false;
@@ -66730,8 +67284,14 @@ Please report this to https://github.com/markedjs/marked.`, e) {
66730
67284
  state.containers = elementsAsArray.map(function (element) {
66731
67285
  return typeof element === 'string' ? doc.querySelector(element) : element;
66732
67286
  });
67287
+ if (config.isolateSubtrees) {
67288
+ collectAdjacentElements(state.containers);
67289
+ }
66733
67290
  if (state.active) {
66734
67291
  updateTabbableNodes();
67292
+ if (!state.paused) {
67293
+ trap._setSubtreeIsolation(true);
67294
+ }
66735
67295
  }
66736
67296
  updateObservedNodes();
66737
67297
  return this;
@@ -66754,19 +67314,84 @@ Please report this to https://github.com/markedjs/marked.`, e) {
66754
67314
  var onPostPause = getOption(options, 'onPostPause');
66755
67315
  onPause === null || onPause === void 0 || onPause();
66756
67316
  removeListeners();
67317
+ trap._setSubtreeIsolation(false);
66757
67318
  updateObservedNodes();
66758
67319
  onPostPause === null || onPostPause === void 0 || onPostPause();
66759
67320
  } else {
66760
67321
  var onUnpause = getOption(options, 'onUnpause');
66761
67322
  var onPostUnpause = getOption(options, 'onPostUnpause');
66762
67323
  onUnpause === null || onUnpause === void 0 || onUnpause();
66763
- updateTabbableNodes();
66764
- addListeners();
66765
- updateObservedNodes();
66766
- onPostUnpause === null || onPostUnpause === void 0 || onPostUnpause();
67324
+ var finishUnpause = /*#__PURE__*/function () {
67325
+ var _ref7 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee2() {
67326
+ return _regenerator().w(function (_context2) {
67327
+ while (1) switch (_context2.n) {
67328
+ case 0:
67329
+ updateTabbableNodes();
67330
+
67331
+ // NOTE: wait for initial focus node to get focused before we potentially isolate
67332
+ // the subtrees with aria-hidden while focus is still in some other subtree and
67333
+ // not yet in the trap, resulting in some browsers (e.g. Chrome) logging to the
67334
+ // console that they, "Blocked aria-hidden on an element because its descendant
67335
+ // retained focus..."
67336
+ _context2.n = 1;
67337
+ return addListeners();
67338
+ case 1:
67339
+ trap._setSubtreeIsolation(true);
67340
+ updateObservedNodes();
67341
+ onPostUnpause === null || onPostUnpause === void 0 || onPostUnpause();
67342
+ case 2:
67343
+ return _context2.a(2);
67344
+ }
67345
+ }, _callee2);
67346
+ }));
67347
+ return function finishUnpause() {
67348
+ return _ref7.apply(this, arguments);
67349
+ };
67350
+ }();
67351
+ finishUnpause();
66767
67352
  }
66768
67353
  return this;
66769
67354
  }
67355
+ },
67356
+ _setSubtreeIsolation: {
67357
+ value: function value(isEnabled) {
67358
+ if (config.isolateSubtrees) {
67359
+ state.adjacentElements.forEach(function (el) {
67360
+ var _el$getAttribute;
67361
+ if (isEnabled) {
67362
+ switch (config.isolateSubtrees) {
67363
+ case 'aria-hidden':
67364
+ // check both attribute and property to ensure initial state is captured
67365
+ // correctly across different browsers and test environments (like JSDOM)
67366
+ if (el.ariaHidden === 'true' || ((_el$getAttribute = el.getAttribute('aria-hidden')) === null || _el$getAttribute === void 0 ? void 0 : _el$getAttribute.toLowerCase()) === 'true') {
67367
+ state.alreadySilent.add(el);
67368
+ }
67369
+ el.setAttribute('aria-hidden', 'true');
67370
+ break;
67371
+ default:
67372
+ // check both attribute and property to ensure initial state is captured
67373
+ // correctly across different browsers and test environments (like JSDOM)
67374
+ if (el.inert || el.hasAttribute('inert')) {
67375
+ state.alreadySilent.add(el);
67376
+ }
67377
+ el.setAttribute('inert', true);
67378
+ break;
67379
+ }
67380
+ } else {
67381
+ if (state.alreadySilent.has(el)) ;else {
67382
+ switch (config.isolateSubtrees) {
67383
+ case 'aria-hidden':
67384
+ el.removeAttribute('aria-hidden');
67385
+ break;
67386
+ default:
67387
+ el.removeAttribute('inert');
67388
+ break;
67389
+ }
67390
+ }
67391
+ }
67392
+ });
67393
+ }
67394
+ }
66770
67395
  }
66771
67396
  });
66772
67397
 
@@ -73340,6 +73965,8 @@ Please report this to https://github.com/markedjs/marked.`, e) {
73340
73965
  hideDelay = 250
73341
73966
  } = props;
73342
73967
  const [visible, setVisible] = h(false);
73968
+ const [tooltipPosition, setTooltipPosition] = h(null);
73969
+ const [arrowOffset, setArrowOffset] = h(null);
73343
73970
  const showTimeoutRef = _$2(null);
73344
73971
  const hideTimeoutRef = _$2(null);
73345
73972
  const wrapperRef = _$2(null);
@@ -73393,6 +74020,20 @@ Please report this to https://github.com/markedjs/marked.`, e) {
73393
74020
  document.removeEventListener('mousedown', handleClickOutside);
73394
74021
  };
73395
74022
  }, [visible, hide]);
74023
+ y$1(() => {
74024
+ if (!visible || position) {
74025
+ setTooltipPosition(null);
74026
+ setArrowOffset(null);
74027
+ return;
74028
+ }
74029
+ if (!wrapperRef.current || !tooltipRef.current) return;
74030
+ const {
74031
+ tooltipPosition: newPosition,
74032
+ arrowOffset: newArrowOffset
74033
+ } = getTooltipPosition(wrapperRef.current, tooltipRef.current, direction);
74034
+ setTooltipPosition(newPosition);
74035
+ setArrowOffset(newArrowOffset);
74036
+ }, [visible, position]);
73396
74037
  const handleMouseLeave = ({
73397
74038
  relatedTarget
73398
74039
  }) => {
@@ -73428,12 +74069,14 @@ Please report this to https://github.com/markedjs/marked.`, e) {
73428
74069
  e.code === 'Escape' && hide(false);
73429
74070
  };
73430
74071
  const renderTooltip = () => {
74072
+ const tooltipStyle = position || (tooltipPosition ? `right: ${tooltipPosition.right}; top: ${tooltipPosition.top}px;` : undefined);
74073
+ const arrowStyle = arrowOffset != null ? `margin-top: ${arrowOffset}px;` : undefined;
73431
74074
  return o("div", {
73432
74075
  class: `bio-properties-panel-tooltip ${direction}`,
73433
74076
  role: "tooltip",
73434
74077
  id: "bio-properties-panel-tooltip",
73435
74078
  "aria-labelledby": forId,
73436
- style: position || getTooltipPosition(wrapperRef.current),
74079
+ style: tooltipStyle,
73437
74080
  ref: tooltipRef,
73438
74081
  onClick: e => e.stopPropagation(),
73439
74082
  onMouseEnter: handleTooltipMouseEnter,
@@ -73442,7 +74085,8 @@ Please report this to https://github.com/markedjs/marked.`, e) {
73442
74085
  class: "bio-properties-panel-tooltip-content",
73443
74086
  children: value
73444
74087
  }), o("div", {
73445
- class: "bio-properties-panel-tooltip-arrow"
74088
+ class: "bio-properties-panel-tooltip-arrow",
74089
+ style: arrowStyle
73446
74090
  })]
73447
74091
  });
73448
74092
  };
@@ -73461,11 +74105,47 @@ Please report this to https://github.com/markedjs/marked.`, e) {
73461
74105
 
73462
74106
  // helper
73463
74107
 
73464
- function getTooltipPosition(refElement) {
74108
+ function getTooltipPosition(refElement, tooltipElement, direction) {
74109
+ if (!refElement) {
74110
+ return {
74111
+ tooltipPosition: null,
74112
+ arrowOffset: null
74113
+ };
74114
+ }
73465
74115
  const refPosition = refElement.getBoundingClientRect();
73466
74116
  const right = `calc(100% - ${refPosition.x}px)`;
73467
- const top = `${refPosition.top - 10}px`;
73468
- return `right: ${right}; top: ${top};`;
74117
+ let top = refPosition.top - 10;
74118
+ let arrowOffset = null;
74119
+
74120
+ // Ensure that the tooltip is within the viewport, adjust the top position if needed.
74121
+ // This is only relevant for the 'right' direction for now
74122
+ if (tooltipElement && direction === 'right') {
74123
+ const tooltipRect = tooltipElement.getBoundingClientRect();
74124
+ const viewportHeight = window.innerHeight;
74125
+ const minTop = 0;
74126
+ const maxTop = viewportHeight - tooltipRect.height;
74127
+ const originalTop = top;
74128
+ if (top > maxTop) {
74129
+ top = maxTop;
74130
+ }
74131
+ if (top < minTop) {
74132
+ top = minTop;
74133
+ }
74134
+
74135
+ // Adjust the arrow position if the tooltip had to be moved to stay within viewport
74136
+ if (top !== originalTop) {
74137
+ const defaultMarginTop = 16;
74138
+ const topDiff = top - originalTop;
74139
+ arrowOffset = defaultMarginTop - topDiff;
74140
+ }
74141
+ }
74142
+ return {
74143
+ tooltipPosition: {
74144
+ right,
74145
+ top
74146
+ },
74147
+ arrowOffset
74148
+ };
73469
74149
  }
73470
74150
 
73471
74151
  /**
@@ -73703,12 +74383,17 @@ Please report this to https://github.com/markedjs/marked.`, e) {
73703
74383
  * The `callback` reference is static and can be safely used in external
73704
74384
  * libraries or as a prop that does not cause rerendering of children.
73705
74385
  *
74386
+ * The ref update is deferred to useLayoutEffect to prevent stale-closure
74387
+ * bugs when Chrome fires blur on elements removed during re-render.
74388
+ *
73706
74389
  * @param {Function} callback function with changing reference
73707
74390
  * @returns {Function} static function reference
73708
74391
  */
73709
74392
  function useStaticCallback(callback) {
73710
74393
  const callbackRef = _$2(callback);
73711
- callbackRef.current = callback;
74394
+ y$1(() => {
74395
+ callbackRef.current = callback;
74396
+ });
73712
74397
  return T$3((...args) => callbackRef.current(...args), []);
73713
74398
  }
73714
74399
  function useElementVisible(element) {
@@ -74964,7 +75649,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
74964
75649
  inline: inline,
74965
75650
  tooltip: tooltip,
74966
75651
  element: element
74967
- }), o(Description$1, {
75652
+ }, element), o(Description$1, {
74968
75653
  forId: id,
74969
75654
  element: element,
74970
75655
  value: description
@@ -75137,7 +75822,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
75137
75822
  const noop$2 = () => {};
75138
75823
 
75139
75824
  /**
75140
- * @typedef {'required'|'optional'|'static'} FeelType
75825
+ * @typedef {'required'|'optional'|'optional-default-enabled'|'static'} FeelType
75141
75826
  */
75142
75827
 
75143
75828
  /**
@@ -75180,7 +75865,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
75180
75865
  OptionalComponent = OptionalFeelInput,
75181
75866
  tooltip
75182
75867
  } = props;
75183
- const [localValue, setLocalValue] = h(value);
75868
+ const [localValue, setLocalValue] = h(getInitialFeelLocalValue(feel, value));
75184
75869
  const editorRef = useShowEntryEvent(id);
75185
75870
  const containerRef = _$2();
75186
75871
  const onInput = T$3(newValue => {
@@ -75189,8 +75874,8 @@ Please report this to https://github.com/markedjs/marked.`, e) {
75189
75874
  const newModelValue = newValue === '' || newValue === '=' ? undefined : newValue;
75190
75875
  commitValue(newModelValue);
75191
75876
  }, [commitValue]);
75192
- const feelActive = isString$2(localValue) && localValue.startsWith('=') || feel === 'required';
75193
- const feelOnlyValue = isString$2(localValue) && localValue.startsWith('=') ? localValue.substring(1) : localValue;
75877
+ const feelActive = isFeelActive(feel, localValue);
75878
+ const feelOnlyValue = getFeelValue(localValue);
75194
75879
  const feelLanguageContext = q$2(FeelLanguageContext);
75195
75880
  const [focus, _setFocus] = h(undefined);
75196
75881
  const {
@@ -75253,7 +75938,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
75253
75938
  };
75254
75939
  const handleOnKeyDown = e => {
75255
75940
  if (isCmdWithChar(e)) {
75256
- handleInput.flush();
75941
+ handleInput.flush?.();
75257
75942
  }
75258
75943
  };
75259
75944
  const handleLint = useStaticCallback((lint = []) => {
@@ -75377,7 +76062,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
75377
76062
  ref: containerRef,
75378
76063
  children: [o(FeelIndicator, {
75379
76064
  active: feelActive,
75380
- disabled: feel !== 'optional' || disabled,
76065
+ disabled: !isFeelOptional(feel) || disabled,
75381
76066
  onClick: handleFeelToggle
75382
76067
  }), feelActive ? o(FeelEditor, {
75383
76068
  name: id,
@@ -75835,6 +76520,68 @@ Please report this to https://github.com/markedjs/marked.`, e) {
75835
76520
  return `bio-properties-panel-${id}`;
75836
76521
  }
75837
76522
 
76523
+ /**
76524
+ * Determine if FEEL is optional for the configured {@link FeelType}.
76525
+ *
76526
+ * @param {FeelType} feelType
76527
+ *
76528
+ * @return {boolean}
76529
+ */
76530
+ function isFeelOptional(feelType) {
76531
+ return feelType === 'optional' || feelType === 'optional-default-enabled';
76532
+ }
76533
+
76534
+ /**
76535
+ * Determine if FEEL editing is currently active.
76536
+ *
76537
+ * @param {FeelType} feelType
76538
+ * @param {string} localValue
76539
+ *
76540
+ * @return {boolean}
76541
+ */
76542
+ function isFeelActive(feelType, localValue) {
76543
+ if (feelType === 'required') {
76544
+ return true;
76545
+ }
76546
+ if (isString$2(localValue)) {
76547
+ if (localValue.startsWith('=')) {
76548
+ return true;
76549
+ }
76550
+ }
76551
+ return false;
76552
+ }
76553
+
76554
+ /**
76555
+ * @template T
76556
+ * @param {T} value
76557
+ *
76558
+ * @return {string|T}
76559
+ */
76560
+ function getFeelValue(value) {
76561
+ if (isString$2(value) && value.startsWith('=')) {
76562
+ return value.substring(1);
76563
+ }
76564
+ return value;
76565
+ }
76566
+
76567
+ /**
76568
+ * Initialize local FEEL value.
76569
+ *
76570
+ * `optional-default-enabled` starts in FEEL mode if no value or empty string is provided.
76571
+ *
76572
+ * @template T
76573
+ * @param {FeelType} feelType
76574
+ * @param {T} value
76575
+ *
76576
+ * @return {string|T}
76577
+ */
76578
+ function getInitialFeelLocalValue(feelType, value) {
76579
+ if (feelType === 'optional-default-enabled' && (value === undefined || value === '')) {
76580
+ return '=';
76581
+ }
76582
+ return value;
76583
+ }
76584
+
75838
76585
  /**
75839
76586
  * @typedef { { value: string, label: string, disabled: boolean, children: { value: string, label: string, disabled: boolean } } } Option
75840
76587
  */
@@ -76085,7 +76832,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
76085
76832
  };
76086
76833
  const handleOnKeyDown = e => {
76087
76834
  if (isCmdWithChar(e)) {
76088
- handleInput.flush();
76835
+ handleInput.flush?.();
76089
76836
  }
76090
76837
  };
76091
76838
  y$1(() => {
@@ -76300,7 +77047,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
76300
77047
  }, [value]);
76301
77048
  const handleOnKeyDown = e => {
76302
77049
  if (isCmdWithChar(e)) {
76303
- handleInput.flush();
77050
+ handleInput.flush?.();
76304
77051
  }
76305
77052
  };
76306
77053
  return o("div", {
@@ -76668,6 +77415,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
76668
77415
  class: "bio-properties-panel-popup__title",
76669
77416
  children: title
76670
77417
  }), children, showCloseButton && o("button", {
77418
+ type: "button",
76671
77419
  title: closeButtonTooltip,
76672
77420
  class: "bio-properties-panel-popup__close",
76673
77421
  onClick: onClose,
@@ -81380,7 +82128,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
81380
82128
  event.stopPropagation();
81381
82129
  return editField(field, ['properties'], removeKey(properties, key));
81382
82130
  };
81383
- const id = `property-${field.id}-${index}`;
82131
+ const id = `property-${index}`;
81384
82132
  return {
81385
82133
  autoFocusEntry: id + '-key',
81386
82134
  entries: CustomValueEntry({
@@ -83691,6 +84439,9 @@ Please report this to https://github.com/markedjs/marked.`, e) {
83691
84439
  if (['Object', '{'].includes(nodeBefore.type.name)) {
83692
84440
  finalOptions = objectOptions;
83693
84441
  }
84442
+ if (nodeBefore.type.name === ',' && nodeBefore.parent?.type.name === 'Object') {
84443
+ finalOptions = objectOptions;
84444
+ }
83694
84445
  if (nodeBefore.type.name === 'PropertyName') {
83695
84446
  context.explicit = true;
83696
84447
  finalOptions = propertyNameOptions;
@@ -83698,6 +84449,9 @@ Please report this to https://github.com/markedjs/marked.`, e) {
83698
84449
  if (['Property', '[', 'Array'].includes(nodeBefore.type.name)) {
83699
84450
  finalOptions = propertyValueOptions;
83700
84451
  }
84452
+ if (nodeBefore.type.name === ':' && nodeBefore.parent?.type.name === 'Property') {
84453
+ finalOptions = propertyValueOptions;
84454
+ }
83701
84455
  if (word.from == word.to && !context.explicit) {
83702
84456
  return null;
83703
84457
  }
@@ -83787,6 +84541,9 @@ Please report this to https://github.com/markedjs/marked.`, e) {
83787
84541
  };
83788
84542
  function createPlaceholderLinterExtension() {
83789
84543
  return linter$1(view => {
84544
+ if (!container) {
84545
+ return [];
84546
+ }
83790
84547
  const placeholders = view.dom.querySelectorAll('.cm-placeholder');
83791
84548
  if (placeholders.length > 0) {
83792
84549
  classes(container).add(NO_LINT_CLS);
@@ -83893,7 +84650,6 @@ Please report this to https://github.com/markedjs/marked.`, e) {
83893
84650
  const load = T$3((schema, data) => {
83894
84651
  formEditorRef.current.importSchema(schema, data);
83895
84652
  inputDataRef.current.setValue(toString(data));
83896
- setSchema(schema);
83897
84653
  setData(data);
83898
84654
  }, []);
83899
84655
 
@@ -84039,7 +84795,9 @@ Please report this to https://github.com/markedjs/marked.`, e) {
84039
84795
  getResultView: () => outputDataRef.current,
84040
84796
  getSchema: () => formEditorRef.current.getSchema(),
84041
84797
  saveSchema: () => formEditorRef.current.saveSchema(),
84042
- setSchema: setSchema,
84798
+ setSchema: newSchema => {
84799
+ return formEditorRef.current.importSchema(newSchema);
84800
+ },
84043
84801
  setData: setData
84044
84802
  };
84045
84803
  onInit();