UNPKG

graph-explorer

Version:

Graph Explorer can be used to explore and RDF graphs in SPARQL endpoints or on the web.

13,581 lines 594 kB
(function() {	try {		if (typeof document != "undefined") {			var elementStyle = document.createElement("style");			elementStyle.appendChild(document.createTextNode(".graph-explorer {\n  --ge-font-sans: \"Inter\", system-ui, -apple-system, BlinkMacSystemFont,\n    \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif;\n  --ge-font-mono: \"SFMono-Regular\", \"JetBrains Mono\", \"Fira Code\", ui-monospace,\n    Menlo, Consolas, monospace;\n  --ge-bg: #f1f5f9;\n  --ge-surface: #ffffff;\n  --ge-surface-2: #f8fafc;\n  --ge-surface-3: #f1f5f9;\n  --ge-border: #e5e9f0;\n  --ge-border-strong: #cbd5e1;\n  --ge-text: #0f172a;\n  --ge-text-muted: #475569;\n  --ge-text-subtle: #94a3b8;\n  --ge-accent: #4f46e5;\n  --ge-accent-hover: #4338ca;\n  --ge-accent-fg: #ffffff;\n  --ge-accent-soft: #eef2ff;\n  --ge-accent-soft-border: #c7d2fe;\n  --ge-success: #16a34a;\n  --ge-success-hover: #15803d;\n  --ge-danger: #dc2626;\n  --ge-danger-hover: #b91c1c;\n  --ge-warning: #f59e0b;\n  --ge-canvas: #fbfcfe;\n  --ge-canvas-dot: #dbe2ee;\n  --ge-radius-sm: 6px;\n  --ge-radius: 8px;\n  --ge-radius-lg: 12px;\n  --ge-radius-pill: 999px;\n  --ge-shadow-xs: 0 1px 2px rgba(15, 23, 42, 0.06);\n  --ge-shadow-sm: 0 1px 3px rgba(15, 23, 42, 0.08),\n    0 1px 2px rgba(15, 23, 42, 0.06);\n  --ge-shadow-md: 0 6px 16px rgba(15, 23, 42, 0.1),\n    0 2px 6px rgba(15, 23, 42, 0.06);\n  --ge-shadow-lg: 0 16px 40px rgba(15, 23, 42, 0.16),\n    0 6px 12px rgba(15, 23, 42, 0.08);\n  --ge-ring: 0 0 0 3px rgba(79, 70, 229, 0.28);\n  --ge-transition: 0.18s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n.graph-explorer-spinner__arrow {\n  animation-name: graph-explorer-spinner-rotation;\n  animation-duration: 1.5s;\n  animation-timing-function: cubic-bezier(0.645, 0.045, 0.355, 1);\n  animation-iteration-count: infinite;\n}\n.graph-explorer-spinner[data-error=true] .graph-explorer-spinner__arrow {\n  animation-iteration-count: 1;\n}\n\n@keyframes graph-explorer-spinner-rotation {\n  0% {\n    transform: rotate(0deg);\n  }\n  100% {\n    transform: rotate(360deg);\n  }\n}\n.clearfix:before, .clearfix:after {\n  display: table;\n  content: \"\";\n}\n.clearfix:after {\n  clear: both;\n}\n\n.graph-explorer-label {\n  display: inline-block;\n  max-width: 100%;\n  margin-bottom: 5px;\n  font-weight: 700;\n}\n\n.graph-explorer-btn {\n  display: inline-flex;\n  align-items: center;\n  justify-content: center;\n  gap: 6px;\n  padding: 7px 13px;\n  margin-bottom: 0;\n  font-size: 13px;\n  font-weight: 500;\n  line-height: 1.4;\n  text-align: center;\n  white-space: nowrap;\n  vertical-align: middle;\n  touch-action: manipulation;\n  cursor: pointer;\n  user-select: none;\n  background-image: none;\n  border: 1px solid transparent;\n  border-radius: var(--ge-radius-sm);\n  text-transform: none;\n  transition: background-color var(--ge-transition), border-color var(--ge-transition), box-shadow var(--ge-transition), color var(--ge-transition);\n}\n.graph-explorer-btn:focus-visible {\n  outline: none;\n  box-shadow: var(--ge-ring);\n}\n.graph-explorer-btn[disabled] {\n  cursor: not-allowed;\n  opacity: 0.55;\n  box-shadow: none;\n}\n\n.graph-explorer-btn-default {\n  background-color: var(--ge-surface);\n  border-color: var(--ge-border-strong);\n  color: var(--ge-text-muted);\n  box-shadow: var(--ge-shadow-xs);\n}\n.graph-explorer-btn-default:hover {\n  background-color: var(--ge-surface-3);\n  border-color: var(--ge-border-strong);\n  color: var(--ge-text);\n}\n.graph-explorer-btn-default.active {\n  background-color: var(--ge-accent-soft);\n  border-color: var(--ge-accent-soft-border);\n  color: var(--ge-accent-hover);\n}\n.graph-explorer-btn-default.active:hover {\n  background-color: var(--ge-accent-soft);\n  border-color: var(--ge-accent);\n}\n.graph-explorer-btn-default[disabled], .graph-explorer-btn-default[disabled]:hover, .graph-explorer-btn-default[disabled].active, .graph-explorer-btn-default[disabled].active:hover {\n  background-color: var(--ge-surface-3);\n  color: var(--ge-text-subtle);\n}\n\n.graph-explorer-btn-primary {\n  color: var(--ge-accent-fg);\n  background-color: var(--ge-accent);\n  border-color: var(--ge-accent);\n  box-shadow: var(--ge-shadow-xs);\n}\n.graph-explorer-btn-primary:hover, .graph-explorer-btn-primary:focus, .graph-explorer-btn-primary:active {\n  background-color: var(--ge-accent-hover);\n  border-color: var(--ge-accent-hover);\n}\n.graph-explorer-btn-primary.active {\n  border-color: var(--ge-accent-hover);\n}\n.graph-explorer-btn-primary[disabled], .graph-explorer-btn-primary[disabled]:hover, .graph-explorer-btn-primary[disabled]:focus, .graph-explorer-btn-primary[disabled]:active, .graph-explorer-btn-primary[disabled].active {\n  background-color: var(--ge-accent);\n}\n\n.graph-explorer-btn-success {\n  background-color: var(--ge-success);\n  border-color: var(--ge-success);\n  color: #fff;\n  box-shadow: var(--ge-shadow-xs);\n}\n.graph-explorer-btn-success:hover {\n  background-color: var(--ge-success-hover);\n  border-color: var(--ge-success-hover);\n}\n\n.graph-explorer-btn-danger {\n  background-color: var(--ge-danger);\n  border-color: var(--ge-danger);\n  color: #fff;\n  box-shadow: var(--ge-shadow-xs);\n}\n.graph-explorer-btn-danger:hover {\n  background-color: var(--ge-danger-hover);\n  border-color: var(--ge-danger-hover);\n}\n\n.graph-explorer-btn-group {\n  position: relative;\n  display: inline-block;\n  vertical-align: middle;\n}\n.graph-explorer-btn-group > .graph-explorer-btn, .graph-explorer-btn-group > .graph-explorer-btn-group {\n  position: relative;\n  float: left;\n}\n.graph-explorer-btn-group > .graph-explorer-btn:hover,\n.graph-explorer-btn-group > .graph-explorer-btn:focus,\n.graph-explorer-btn-group > .graph-explorer-btn.active,\n.graph-explorer-btn-group > .graph-explorer-btn.active:hover {\n  z-index: 2;\n}\n.graph-explorer-btn-group .graph-explorer-btn + .graph-explorer-btn,\n.graph-explorer-btn-group .graph-explorer-btn + .graph-explorer-btn-group,\n.graph-explorer-btn-group .graph-explorer-btn-group + .graph-explorer-btn,\n.graph-explorer-btn-group .graph-explorer-btn-group + .graph-explorer-btn-group {\n  margin-left: -1px;\n}\n.graph-explorer-btn-group > .graph-explorer-btn:first-child {\n  margin-left: 0;\n}\n.graph-explorer-btn-group-sm > .graph-explorer-btn {\n  font-size: 12px;\n  line-height: 1.5;\n  padding: 5px 10px;\n}\n.graph-explorer-btn-group-xs > .graph-explorer-btn {\n  font-size: 12px;\n  line-height: 1.5;\n  padding: 1px 5px;\n}\n\n.graph-explorer-form-control {\n  display: block;\n  width: 100%;\n  height: 36px;\n  margin: 0;\n  padding: 7px 12px;\n  font-size: 14px;\n  line-height: 1.5;\n  color: var(--ge-text);\n  background: var(--ge-surface);\n  border: 1px solid var(--ge-border-strong);\n  border-radius: var(--ge-radius-sm);\n  transition: border-color var(--ge-transition), box-shadow var(--ge-transition);\n}\n.graph-explorer-form-control::placeholder {\n  color: var(--ge-text-subtle);\n}\n.graph-explorer-form-control:focus {\n  border-color: var(--ge-accent);\n  outline: 0;\n  box-shadow: var(--ge-ring);\n}\n.graph-explorer-form-control:disabled {\n  background-color: var(--ge-surface-3);\n  cursor: not-allowed;\n  opacity: 0.6;\n}\n\n.graph-explorer-input-group {\n  position: relative;\n  display: flex;\n  align-items: stretch;\n}\n.graph-explorer-input-group .graph-explorer-form-control {\n  position: relative;\n  z-index: 2;\n  flex: 1 1 auto;\n  width: 1%;\n  margin-bottom: 0;\n}\n.graph-explorer-input-group .graph-explorer-form-control:not(:last-child) {\n  border-top-right-radius: 0;\n  border-bottom-right-radius: 0;\n}\n\n.graph-explorer-input-group-btn {\n  display: flex;\n  align-items: stretch;\n  position: relative;\n  font-size: 0;\n  white-space: nowrap;\n}\n.graph-explorer-input-group-btn > .graph-explorer-btn {\n  height: 100%;\n  margin-left: -1px;\n  z-index: 2;\n}\n.graph-explorer-input-group-btn:last-child > .graph-explorer-btn {\n  border-top-left-radius: 0;\n  border-bottom-left-radius: 0;\n}\n\n.graph-explorer-list-group {\n  margin: 0;\n  padding: 0;\n}\n\n.graph-explorer-list-group-item:last-child {\n  margin-bottom: 0;\n}\n\n.graph-explorer-list-group-item {\n  position: relative;\n  display: block;\n  padding: 10px 14px;\n  margin-bottom: -1px;\n  background-color: var(--ge-surface);\n  border: 1px solid var(--ge-border);\n}\n.graph-explorer-list-group-item:first-child {\n  border-top-left-radius: var(--ge-radius-sm);\n  border-top-right-radius: var(--ge-radius-sm);\n}\n.graph-explorer-list-group-item:last-child {\n  border-bottom-left-radius: var(--ge-radius-sm);\n  border-bottom-right-radius: var(--ge-radius-sm);\n}\n\n.graph-explorer-badge {\n  display: inline-block;\n  min-width: 10px;\n  font-size: 11px;\n  font-weight: 600;\n  line-height: 1;\n  color: var(--ge-text-muted);\n  text-align: center;\n  white-space: nowrap;\n  vertical-align: middle;\n  background-color: var(--ge-surface-3);\n  border: 1px solid var(--ge-border);\n  padding: 3px 8px;\n  border-radius: var(--ge-radius-pill);\n}\n\n.graph-explorer-overlayed-element {\n  cursor: move;\n  outline: none;\n}\n\n.graph-explorer-overlayed-element,\n.graph-explorer-exported-element {\n  box-sizing: border-box;\n  color: var(--ge-text, #0f172a);\n  font-family: var(--ge-font-sans, \"Inter\", system-ui, -apple-system, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif);\n  font-size: 14px;\n  line-height: 1.5;\n}\n.graph-explorer-overlayed-element img,\n.graph-explorer-exported-element img {\n  vertical-align: middle;\n}\n\n.graph-explorer-exported-element *, .graph-explorer-exported-element *:before, .graph-explorer-exported-element *:after {\n  box-sizing: inherit;\n}\n\n.graph-explorer-overlayed-element--blurred {\n  filter: grayscale(100%);\n  opacity: 0.5;\n}\n\n.graph-explorer-link__wrap {\n  stroke-width: 12px;\n  stroke-linejoin: round;\n  stroke-linecap: round;\n  stroke: transparent;\n  fill: none;\n}\n.graph-explorer-link:hover .graph-explorer-link__wrap {\n  stroke: rgba(140, 140, 140, 0.44);\n}\n.graph-explorer-link__vertex {\n  cursor: all-scroll;\n}\n.graph-explorer-link:not(:hover) .graph-explorer-link__vertex {\n  fill: transparent;\n}\n.graph-explorer-link__vertex-tools {\n  opacity: 0;\n  cursor: pointer;\n}\n.graph-explorer-link__vertex-tools > circle {\n  fill: gray;\n}\n.graph-explorer-link__vertex-tools > path {\n  stroke: white;\n}\n.graph-explorer-link__vertex-tools:hover > circle {\n  fill: black;\n}\n.graph-explorer-link:hover .graph-explorer-link__vertex-tools {\n  opacity: 0.8;\n}\n.graph-explorer-link--blurred {\n  opacity: 0.5;\n}\n\n.graph-explorer-paper-area {\n  flex: auto;\n  width: 0;\n  display: flex;\n  position: relative;\n  cursor: default;\n  background-color: var(--ge-canvas);\n}\n.graph-explorer-paper-area__area {\n  flex: auto;\n  overflow: hidden;\n  background-image: radial-gradient(var(--ge-canvas-dot) 1px, transparent 1px);\n  background-attachment: local;\n}\n.graph-explorer-paper-area__widgets {\n  position: absolute;\n  left: 0;\n  top: 0;\n}\n.graph-explorer-paper-area__watermark {\n  background-size: cover;\n  width: 8%;\n  max-width: 130px;\n  min-width: 50px;\n  position: absolute;\n  top: 15px;\n  right: 25px;\n  cursor: pointer;\n  opacity: 0.3;\n  transition: opacity 0.3s;\n}\n.graph-explorer-paper-area__watermark:hover {\n  opacity: 0.5;\n}\n.graph-explorer-paper-area--hide-scrollbars {\n  overflow: hidden;\n}\n\n.graph-explorer-paper {\n  position: relative;\n}\n\n.graph-explorer-exported-watermark {\n  opacity: 0.3;\n  transition: opacity 0.3s;\n}\n\n.graph-explorer-paper-area--animated .graph-explorer-overlayed-element {\n  transition: transform 0.5s ease-in-out;\n}\n.graph-explorer-paper-area--animated .graph-explorer-link-layer, .graph-explorer-paper-area--animated .graph-explorer-paper-area__widgets {\n  transition: none;\n  opacity: 0;\n}\n\n.graph-explorer-link-layer, .graph-explorer-paper-area__widgets {\n  transition: opacity 0.5s ease-in-out;\n}\n\n.graph-explorer-loading-widget {\n  left: 0;\n  right: 0;\n  top: 0;\n  bottom: 0;\n  margin: auto;\n  position: absolute;\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  background: rgba(255, 255, 255, 0.9);\n  z-index: 10;\n}\n\n.graph-explorer-authoring-state__item-error {\n  align-self: flex-end;\n  margin: 0px 5px;\n  display: flex;\n  align-items: center;\n  cursor: help;\n}\n.graph-explorer-authoring-state__item-error-icon {\n  background: url(\"data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20style='fill:%20white'%20viewBox='0%200%20576%20512'%3e%3crect%20style='fill:%20white'%20width='160'%20height='340'%20x='207.9998'%20y='136'%20ry='0'%20/%3e%3cpath%20style='fill:%20red'%20d='M569.517%20440.013C587.975%20472.007%20564.806%20512%20527.94%20512H48.054c-36.937%200-59.999-40.055-41.577-71.987L246.423%2023.985c18.467-32.009%2064.72-31.951%2083.154%200l239.94%20416.028zM288%20354c-25.405%200-46%2020.595-46%2046s20.595%2046%2046%2046%2046-20.595%2046-46-20.595-46-46-46zm-43.673-165.346l7.418%20136c.347%206.364%205.609%2011.346%2011.982%2011.346h48.546c6.373%200%2011.635-4.982%2011.982-11.346l7.418-136c.375-6.874-5.098-12.654-11.982-12.654h-63.383c-6.884%200-12.356%205.78-11.981%2012.654z'/%3e%3c/svg%3e\");\n  height: 15px;\n  width: 17px;\n}\n.graph-explorer-authoring-state__state-label {\n  font-weight: bold;\n  margin-right: 5px;\n}\n.graph-explorer-authoring-state__state-cancel {\n  color: #3f87a6;\n  cursor: pointer;\n}\n.graph-explorer-authoring-state__state-cancel:hover {\n  text-decoration: underline;\n}\n.graph-explorer-authoring-state__state-indicator {\n  position: absolute;\n}\n.graph-explorer-authoring-state__state-indicator-container {\n  position: relative;\n}\n.graph-explorer-authoring-state__state-indicator-body {\n  position: absolute;\n  white-space: nowrap;\n  display: flex;\n  align-items: center;\n  bottom: 0;\n  background: rgba(255, 255, 255, 0.7);\n  border-radius: 5px;\n}\n\n.graph-explorer-authoring-tools {\n  margin: 10px;\n}\n.graph-explorer-authoring-tools__create-entity {\n  display: flex;\n  flex-wrap: wrap;\n  align-items: center;\n  justify-content: center;\n  width: 100%;\n  white-space: normal;\n}\n.graph-explorer-authoring-tools__type-label {\n  color: black;\n  border: black 1px dashed;\n  background: rgb(255, 210, 33);\n  padding: 0 0.5em 0 0.5em;\n  word-wrap: break-word;\n}\n\n.graph-explorer-class-tree {\n  flex: auto;\n  display: flex;\n  flex-direction: column;\n}\n.graph-explorer-class-tree__filter {\n  flex-shrink: 0;\n  margin: 10px 0 10px 0;\n}\n.graph-explorer-class-tree__filter-group {\n  margin-left: 10px;\n  margin-right: 10px;\n}\n.graph-explorer-class-tree__only-creatable {\n  display: block;\n  margin-top: 5px;\n}\n.graph-explorer-class-tree__tree {\n  border-top: 1px solid var(--ge-border);\n  padding: 6px 8px;\n  overflow: auto;\n}\n.graph-explorer-class-tree__spinner {\n  align-self: center;\n  /* center vertically in flexbox */\n  margin: auto;\n}\n\n.graph-explorer-class-leaf {\n  margin: 1px 0;\n}\n.graph-explorer-class-leaf__row {\n  display: flex;\n  align-items: center;\n  white-space: nowrap;\n  user-select: none;\n}\n.graph-explorer-class-leaf__row > * {\n  flex-shrink: 0;\n}\n.graph-explorer-class-leaf__body {\n  display: flex;\n  align-items: center;\n  text-decoration: none;\n  font-size: 14px;\n  padding: 4px 6px;\n  border: 1px solid transparent;\n  border-radius: var(--ge-radius-sm);\n  transition: background var(--ge-transition), border-color var(--ge-transition);\n}\n.graph-explorer-class-leaf__body:hover {\n  background: var(--ge-surface-3);\n  border-color: transparent;\n  cursor: pointer;\n}\n.graph-explorer-class-leaf__body--selected {\n  background-color: var(--ge-accent-soft);\n  border-color: var(--ge-accent-soft-border);\n}\n.graph-explorer-class-leaf__body--selected:hover {\n  background-color: var(--ge-accent-soft);\n}\n.graph-explorer-class-leaf__icon-container {\n  height: 18px;\n}\n.graph-explorer-class-leaf__icon {\n  display: block;\n  height: 100%;\n}\n.graph-explorer-class-leaf__label {\n  margin-left: 7px;\n  color: var(--ge-text);\n}\n.graph-explorer-class-leaf__highlighted-term {\n  font-weight: bold;\n}\n.graph-explorer-class-leaf__count {\n  margin-left: 5px;\n}\n.graph-explorer-class-leaf__children {\n  margin-left: 20px;\n}\n.graph-explorer-class-leaf__no-toggle {\n  display: inline-block;\n  width: 22px;\n  height: 22px;\n}\n.graph-explorer-class-leaf__toggle {\n  display: inline-block;\n  width: 12px;\n  height: 12px;\n  margin: 5px;\n  border-radius: var(--ge-radius-sm);\n}\n.graph-explorer-class-leaf__toggle:hover:not(:empty) {\n  background: var(--ge-surface-3);\n  cursor: pointer;\n}\n.graph-explorer-class-leaf__toggle-icon {\n  display: block;\n  height: 100%;\n}\n.graph-explorer-class-leaf__create {\n  margin-left: 5px;\n}\n.graph-explorer-class-leaf__create > button {\n  cursor: move;\n}\n\n.graph-explorer-connections-menu {\n  height: 100%;\n  display: flex;\n  flex-direction: column;\n}\n.graph-explorer-connections-menu__sort-switch {\n  display: none;\n}\n.graph-explorer-connections-menu__sort-switch:checked + .graph-explorer-connections-menu__sort-switch-label {\n  color: var(--ge-accent);\n  opacity: 1;\n}\n.graph-explorer-connections-menu__sort-switch-label {\n  cursor: pointer;\n  display: block;\n  margin: 0;\n  opacity: 0.4;\n  text-align: center;\n}\n.graph-explorer-connections-menu__sort-switch-label:hover {\n  opacity: 1;\n}\n.graph-explorer-connections-menu__search-line-input {\n  flex: 1 1 100%;\n}\n\n.graph-explorer-connections-menu_bread-crumbs {\n  padding: 10px;\n  padding-bottom: 0px;\n  overflow: hidden;\n  text-overflow: ellipsis;\n  height: 27px;\n  min-height: 27px;\n  flex-grow: 0;\n}\n\n.graph-explorer-connections-menu__title-label {\n  position: absolute;\n  top: -11px;\n  left: 10px;\n  background: var(--ge-surface);\n  color: var(--ge-text);\n  font-weight: 600;\n  padding-left: 6px;\n  padding-right: 6px;\n  border-radius: var(--ge-radius-sm);\n}\n\n.graph-explorer-connections-menu_search-line {\n  padding: 10px;\n  display: flex;\n  align-items: center;\n  flex: 0 0 auto;\n}\n\n.graph-explorer-connections-menu_search-line-sort-switches {\n  flex: 0 0 20px;\n  margin-left: 10px;\n}\n\n.graph-explorer-connections-menu_links-list {\n  padding: 5px;\n  overflow-x: hidden;\n  overflow-y: auto;\n  border-top: 1px solid var(--ge-border);\n  flex-grow: 1;\n  margin: 0;\n}\n\n.ocm_links-list-empty {\n  display: flex;\n  align-items: center;\n}\n\n.graph-explorer-connections-menu_links-list__empty {\n  width: 100%;\n  position: relative;\n  font-size: x-large;\n  color: #cbcbcb;\n  text-align: center;\n}\n\n.graph-explorer-connections-menu__loading,\n.graph-explorer-connections-menu__error {\n  width: 100%;\n  height: 100%;\n  position: relative;\n  font-size: x-large;\n  display: flex;\n  color: #cbcbcb;\n  align-items: center;\n  justify-content: center;\n}\n\n.graph-explorer-connections-menu__loading-objects {\n  border: 1px solid gray;\n  flex-grow: 1;\n  box-shadow: inset 0px 0px 23px -8px gray;\n  background-color: whitesmoke;\n  position: relative;\n  font-size: x-large;\n  display: flex;\n  color: #cbcbcb;\n  align-items: center;\n  justify-content: center;\n  margin-bottom: 5px;\n}\n\n.graph-explorer-connections-menu__move-to-filter {\n  display: flex;\n  padding: 5px 10px;\n  user-select: none;\n  cursor: pointer;\n}\n.graph-explorer-connections-menu__move-to-filter:hover {\n  background-color: #e6e6e6;\n}\n\n.link-in-popup-menu {\n  display: flex;\n  overflow: hidden;\n  padding: 0 5px 0 0;\n  align-items: center;\n  margin-bottom: 4px;\n  background: #f7f7f7;\n}\n.link-in-popup-menu__link-title {\n  flex-grow: 1;\n  overflow: hidden;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  margin: 5px 0px 5px 5px;\n}\n.link-in-popup-menu__count {\n  flex-shrink: 0;\n  margin-left: 10px;\n}\n.link-in-popup-menu__navigate-button {\n  float: right;\n  background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVUAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAN1wAADdcBQiibeAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAGrSURBVHic7dYxSgNRGEXhGwOuRQyCi1AR3IHoUiwFW21cj5sRC3tFgrExzUBIMmPmP76cD145MxcODyYRyrTgm+dJDpO8F3xbHRdJPpK8JZkVb9l7yxiL32OUQt0YRim0KoZRCqyLYZQRbRrDKCOYZbsYy/Oa5Khgb/MmSZ6yfRBvyg4ZBcgoQEYBMgqQUYCMAmQUIKMAGQXIKEBGATIKkFGAjAJkFKChUY7Hn9w+owAZBcgoQEYBMgqQUYCMAjRJ8hijoBgFyChARgEyCpBRgIwCZBQgowANjXI6/uT2DYkyT3I5/uT2GQXIKEBGATIKkFGAsFEOdvViuEWSlyTfPZ6dJjn72zm6SvKZfjfkuWBv04wBYgwQY4AYA8QYIH1jzJPcFext2pAYtwV7m2YMEGOAGAPEGCDGADEGiDFAjAFiDBBjgBgDxBggxgAxBogxQIwBMiTGTcHephkDxBggxgAxBogxQIwBYgwQY4AYA8QYIMYAMQaIMUCMAWIMkJMkX+kX47pg7164jzcDZ9MoxhjRuijGKLAqijEKdaMYA2AZxRggD/HXVv/FDxh8HInEGLhOAAAAAElFTkSuQmCC\");\n  width: 16px;\n  height: 16px;\n  opacity: 0.5;\n  margin-left: 10px;\n  min-width: 16px;\n  background-size: cover;\n}\n.link-in-popup-menu__navigate-button:hover {\n  opacity: 1;\n}\n.link-in-popup-menu__filter-button {\n  background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVUAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjExR/NCNwAAAuxJREFUeF7t3V1u4jAYhWFu+FkDIHHBGlgZILbBjtN8M/labEywYzs+js8rHYFUqGo/6twNXTHGWIVdLpduv993x+ORm3Fy53L3A8Nf8sX+gSuw4e7NCFJuBAEbQcBGELARBGxOkNPp9PZCbp4Nd2/2eDy67Xb79mIu7+TO5e775+/d7/dut9u9vYnLM7lrufP++eeIMs+8MDSi5F0QhkaUPJuEoREl7aIwNKKkWRIMjShxS4qhEWXasmBoRAlbVgyNKH6bBUMjyvhmxdCI4l4RDI0o5opiaET5PwgMrXUUKAytVRRIDK01FGgMrRWUKjC0paNUhaEtFaVKDG1pKFVjaEtBWQSGVjvKojC0WlEWiaHVhrJoDK0WlCYwNHSUpjA0VJQmMTQ0lKYxNBQUSIyu697mkXEwa16VRoHCcCHoPDMOZ827UihwvxkuCFlAxgGtBTU3ChyGFIkhGYe0FtxcKJAYUiSGZBzU2qRyo8BiSIggUi4UaAwJFURKjQKPISGDSKlQqsCQEEHsn+N2u3Xr9dr+3t6T98r36J/jVwOIJJ8r1T9M2vDeOqoFJOajP5wfXYGaHp4gIDlAfg9SYP8iyPBIEIAIAhZBwCIIWAQBiyBgKcQLSGjG4a1NiiAEwYkgYCGCuCKIf8bhrSWLIP4Zh7eWLIL4ZxzeWrKaBZmAYhzeWrKaBpEFZBzeWrKaB5F5ZhzeWrIIMswj4/DWkkWQl33JOLy1ZBHEsZIRZGQlIkjCpYgggfvU2NdCIojnvuXzGp8I8mW+hbx2LIIkXIqaAaklgoDVDIjrn5gciy0GxPl3AlFzXV6OxTYVZPTvBCLmurwci20KSDX/je011+XlWGyhIFViSK7Ly7HYQkCqxZBcl5djsfmCVI0huS4vx2LzAakeQ3JdXo7F9g1kERiS6/JyLLYxkMVg1NQnEGIUygVCjILZIMQo3CsIMQBSEGKAdDgcus1mQwyUzudzd71eiYHS8/kkBpu71eoHWjSksuGbaS0AAAAASUVORK5CYII=\");\n  background-size: 20px 20px;\n  width: 20px;\n  height: 20px;\n  opacity: 0.4;\n  margin-left: 10px;\n}\n.link-in-popup-menu__filter-button:hover {\n  opacity: 1;\n}\n.link-in-popup-menu:hover {\n  background-color: #e2e2e2;\n}\n\n.link-in-popup-menu_direction {\n  background: rgba(219, 219, 219, 0.35);\n  min-height: 30px;\n  padding: 5px 0px 5px 10px;\n  display: flex;\n  align-items: center;\n}\n\n.link-in-popup-menu_direction__in-direction {\n  background: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAbCAYAAAAOEM1uAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAZEQAAGREBkIelaAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAG2SURBVFiFzde9axRRFMbhJ3Hjx0YRgkWElGIRGyVgaaG9XQpBrNIETJHKjxBSJCA2NiIWdhYKgoqCIELq/AU2tiJpAiliDMHEWEyKZfdO5szHrr4wzcx77vnNnXPnnktcK9jBwYCuLcwNBeHGsIGovyltDweNbYOHg9Eo4D9Tq0bsGj40BXKoO5isEjiht4ifHuE/qVpJvO/O049PvIxN/MBMH8ZP6pzeGVxK+C4kfAsl8vTMYBnI1x1Bv3E54bmWSHCAx2KfvBbgKGbxJAfOIcS7HMjnKCqpWoBRtfE5B/IVRsoAtnAGd3GlQchd/NE7Y7dwCtPYiw72xuD216KFk/zN3Ii+SYOajhqHZUU9aK1GjS3M4xumFK+yMuPexLHEsy9YbChPJR3HW+na+yjbBvNU+zdzHbcxfoTnUw7cS8XNSS3AFx1B6zif8FzKgXsmVj6VAduyFrwzcCUHcL/L9yiaJAUYXRRjON1172zC9xX3ZS+ziTk8KAFYWWX7wRGcqJAnudVV1RTu1YhP6WL3jWjXO4HvzbLE9N8fmqKAv/SpNyvQdmorSmlHVvhX1TsJltFPPPwL/+nTC6wUIf8AAAAASUVORK5CYII=\") 0 0 no-repeat;\n  flex-shrink: 0;\n  width: 22px;\n  height: 15px;\n  margin: 0 14px 0 0;\n  background-size: contain;\n  opacity: 0.5;\n}\n\n.link-in-popup-menu_direction__out-direction {\n  background: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAbCAYAAAAOEM1uAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAZEQAAGREBkIelaAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAGCSURBVFiFzdi9ShxRFAfwn+uiaAoRVBQbbfMEFqIoFja+QCoLLQQr8R0sbdIJgTQiSgT1AcTKzkdIQhpTaOlX0GyK2WJ2c8d1Pt0/XBjOnTnnP+eerxnYxj0aJa9nfEOvlLirgFx8zaQhV8Ng2jfKiVT2amWxKAr1gOwElwXpH8NWXiXtMbKZV2EMHwP6F2P7dR1O8T2PeBW/8EMHp5TpwWGtJewF06JEuWmzu4ueqgnC55juw6ZsHE8B218F8qJsgkS1b0Grh74EbDdwioGqCYbQj6MEkhcYIlxm3opZrGEyh47eJqH22JvDOZbJ5sEJ4Rgqeh1nLTMr6Mv4bBpMZSV4hj9FMknA96wxeC3qCOvyxWAd88L17wobdHkWV0VwxP+e3ksgd6LiOrgtyvhn7DRlo3gM2K68kwziNqb7QTSC9eN3m9136cWvjVuf8FOHaSZPJ8mLfRw0r/8m3RQiuIQPBZEY67CfSCyOsttV0hG/CV3/0VQTTbxVIrW9rv6z8A+8NRQ5z9bcwQAAAABJRU5ErkJggg==\") 0 0 no-repeat;\n  flex-shrink: 0;\n  width: 22px;\n  height: 15px;\n  margin: 0 8px 0 6px;\n  background-size: contain;\n  opacity: 0.5;\n}\n\n.graph-explorer-connections-menu_links-list__loading {\n  text-align: center;\n  width: 100%;\n  position: relative;\n  font-size: x-large;\n  color: #cbcbcb;\n}\n\n.graph-explorer-connections-menu_links-list__hr {\n  margin-top: 10px;\n  margin-bottom: 10px;\n}\n\n.graph-explorer-connections-menu_objects-panel {\n  flex-grow: 1;\n  padding: 10px;\n  position: relative;\n  display: flex;\n  flex-direction: column;\n  padding-top: 0px;\n}\n\n.graph-explorer-connections-menu_objects-panel__select-all {\n  white-space: nowrap;\n  margin-bottom: 5px;\n  display: flex;\n}\n.graph-explorer-connections-menu_objects-panel__select-all input {\n  margin-right: 5px;\n}\n.graph-explorer-connections-menu_objects-panel__select-all input:disabled {\n  opacity: 0.3;\n}\n\n.graph-explorer-connections-menu_objects-panel_bottom-panel {\n  height: 25px;\n  white-space: nowrap;\n  display: flex;\n  justify-content: space-between;\n}\n\n.graph-explorer-connections-menu_objects-panel_bottom-panel__count-label {\n  height: 25px;\n  float: left;\n  padding: 0px 5px;\n  font-size: larger;\n  display: flex;\n  align-items: center;\n  max-width: 60%;\n}\n\n.graph-explorer-connections-menu_objects-panel_bottom-panel__extra-elements {\n  color: gray;\n  cursor: help;\n}\n\n.graph-explorer-btn.graph-explorer-connections-menu_objects-panel_bottom-panel__add-button {\n  height: 25px;\n  padding-top: 1px;\n  padding-bottom: 2px;\n}\n\n.graph-explorer-connections-menu_objects-panel_objects-list {\n  border: 1px solid gray;\n  height: 0;\n  flex-grow: 1;\n  overflow-x: hidden;\n  overflow-y: scroll;\n  padding: 5px;\n  margin-bottom: 5px;\n}\n\n.graph-explorer-connections-menu__link {\n  color: var(--ge-accent);\n  cursor: pointer;\n  text-decoration: none;\n}\n.graph-explorer-connections-menu__link:hover {\n  text-decoration: underline;\n}\n\n.graph-explorer-dialog {\n  background: var(--ge-surface);\n  border: 1px solid var(--ge-border);\n  border-radius: var(--ge-radius-lg);\n  box-shadow: var(--ge-shadow-lg);\n  position: absolute;\n}\n.graph-explorer-dialog__caption {\n  font-weight: 600;\n  position: absolute;\n  top: -11px;\n  left: 10px;\n  background: var(--ge-surface);\n  color: var(--ge-text);\n  padding-left: 6px;\n  padding-right: 6px;\n  border-radius: var(--ge-radius-sm);\n}\n.graph-explorer-dialog__close-button {\n  background: transparent url(\"data:image/svg+xml,%3csvg%20aria-hidden='true'%20focusable='false'%20data-prefix='far'%20data-icon='times-circle'%20class='svg-inline--fa%20fa-times-circle%20fa-w-16'%20role='img'%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20512%20512'%3e%3cpath%20fill='currentColor'%20d='M256%208C119%208%208%20119%208%20256s111%20248%20248%20248%20248-111%20248-248S393%208%20256%208zm0%20448c-110.5%200-200-89.5-200-200S145.5%2056%20256%2056s200%2089.5%20200%20200-89.5%20200-200%20200zm101.8-262.2L295.6%20256l62.2%2062.2c4.7%204.7%204.7%2012.3%200%2017l-22.6%2022.6c-4.7%204.7-12.3%204.7-17%200L256%20295.6l-62.2%2062.2c-4.7%204.7-12.3%204.7-17%200l-22.6-22.6c-4.7-4.7-4.7-12.3%200-17l62.2-62.2-62.2-62.2c-4.7-4.7-4.7-12.3%200-17l22.6-22.6c4.7-4.7%2012.3-4.7%2017%200l62.2%2062.2%2062.2-62.2c4.7-4.7%2012.3-4.7%2017%200l22.6%2022.6c4.7%204.7%204.7%2012.3%200%2017z'%3e%3c/path%3e%3c/svg%3e\");\n  background-size: contain;\n  border: 0 none;\n  cursor: pointer;\n  display: block;\n  outline: none;\n  padding: 0;\n  position: absolute;\n  top: -22px;\n  right: -22px;\n  height: 20px;\n  width: 20px;\n  opacity: 0.5;\n  transition: 0.3s;\n}\n.graph-explorer-dialog__close-button:hover {\n  opacity: 1;\n}\n\n.graph-explorer-dialog__bottom-right-handle {\n  position: absolute;\n  bottom: 0;\n  right: 0;\n  width: 0;\n  height: 0;\n  border-style: solid;\n  border-width: 0 0 10px 10px;\n  border-color: transparent transparent rgba(0, 0, 0, 0.38) transparent;\n  cursor: nwse-resize;\n}\n.graph-explorer-dialog__bottom-right-handle::before {\n  content: \"\";\n  position: absolute;\n  bottom: -10px;\n  right: 0;\n  width: 0;\n  height: 0;\n  border-style: solid;\n  border-width: 0 0 5px 5px;\n  border-color: transparent transparent rgba(0, 0, 0, 0.38) transparent;\n}\n.graph-explorer-dialog__bottom-right-handle:hover {\n  border-color: transparent transparent rgba(0, 0, 0, 0.5) transparent;\n}\n\n.graph-explorer-dialog__bottom-handle, .graph-explorer-dialog__right-handle {\n  position: absolute;\n  opacity: 0;\n  background-color: black;\n}\n.graph-explorer-dialog__bottom-handle:hover, .graph-explorer-dialog__right-handle:hover {\n  opacity: 0.1;\n}\n\n.graph-explorer-dialog__bottom-handle {\n  bottom: 0;\n  width: 100%;\n  height: 5px;\n  cursor: ns-resize;\n}\n\n.graph-explorer-dialog__right-handle {\n  top: 0;\n  right: 0;\n  width: 5px;\n  height: 100%;\n  cursor: ew-resize;\n}\n\n.graph-explorer-edit-form {\n  height: 100%;\n  display: flex;\n  flex-direction: column;\n}\n.graph-explorer-edit-form__body {\n  overflow: auto;\n  padding: 10px;\n  flex: 1 1 100%;\n  display: flex;\n  flex-direction: column;\n  position: relative;\n}\n.graph-explorer-edit-form__controls {\n  border-top: 1px solid #ccc;\n  padding: 10px;\n  text-align: right;\n  flex: 0 0 auto;\n}\n.graph-explorer-edit-form__apply-button {\n  margin-right: 5px;\n}\n.graph-explorer-edit-form__form-row {\n  display: block;\n  margin-bottom: 10px;\n}\n.graph-explorer-edit-form__element-selector {\n  flex-grow: 1;\n  display: flex;\n  flex-direction: column;\n}\n.graph-explorer-edit-form__search {\n  flex-shrink: 0;\n  position: relative;\n}\n.graph-explorer-edit-form__search-icon {\n  opacity: 0.6;\n  position: absolute;\n  top: 50%;\n  left: 10px;\n  margin-top: -7px;\n}\n.graph-explorer-edit-form__search-input {\n  padding-left: 33px;\n}\n.graph-explorer-edit-form__existing-elements-list {\n  flex: 1 1 0;\n  margin-top: 7px;\n  padding-right: 10px;\n  overflow-y: scroll;\n}\n.graph-explorer-edit-form__separator {\n  margin: 7px 0;\n  overflow: hidden;\n  text-align: center;\n}\n.graph-explorer-edit-form__separator-text {\n  color: #555;\n  display: inline-block;\n  font-size: 13px;\n  position: relative;\n}\n.graph-explorer-edit-form__separator-text:before, .graph-explorer-edit-form__separator-text:after {\n  content: \"\";\n  border-top: 1px solid;\n  position: absolute;\n  top: 50%;\n  margin: 0 10px;\n  width: 500px;\n}\n.graph-explorer-edit-form__separator-text:before {\n  left: 100%;\n}\n.graph-explorer-edit-form__separator-text:after {\n  right: 100%;\n}\n.graph-explorer-edit-form__progress {\n  position: absolute;\n  bottom: 0;\n  left: 0;\n  right: 0;\n}\n.graph-explorer-edit-form__control-row {\n  position: relative;\n  padding-bottom: 18px;\n}\n.graph-explorer-edit-form__control-error {\n  color: red;\n  position: absolute;\n  bottom: 0;\n  left: 0;\n}\n\n.graph-explorer-halo {\n  position: absolute;\n  pointer-events: none;\n  border: 1.5px dashed var(--ge-accent);\n  border-radius: var(--ge-radius);\n  box-shadow: 0 0 0 4px rgba(79, 70, 229, 0.12);\n}\n.graph-explorer-halo__navigate {\n  position: absolute;\n  background-color: transparent;\n  background-size: contain;\n  background-repeat: no-repeat;\n  background-position: center;\n  border: 0 none;\n  cursor: pointer;\n  outline: none;\n  padding: 0;\n  pointer-events: auto;\n  width: 20px;\n  height: 20px;\n  opacity: 0.5;\n  transition: opacity 0.3s;\n}\n.graph-explorer-halo__navigate:hover {\n  opacity: 1;\n}\n.graph-explorer-halo__navigate[disabled] {\n  cursor: not-allowed;\n  opacity: 0.2;\n}\n.graph-explorer-halo__navigate {\n  top: 50%;\n  margin-top: -10px;\n  right: -22px;\n}\n.graph-explorer-halo__navigate--open {\n  background-image: url(\"data:image/svg+xml,%3c?xml%20version='1.0'%20encoding='UTF-8'%20standalone='no'?%3e%3csvg%20xmlns:svg='http://www.w3.org/2000/svg'%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20110%20110'%20version='1.1'%20width='500'%20height='500'%3e%3cpath%20d='M%2055.105965,54.648825%20M%2082.182422,8.0521107%20A%2053.892377,53.892377%200%201%200%2028.029508,101.24554%2053.892377,53.892377%200%201%200%2082.182422,8.0521107%20Z%20M%2055.105965,54.648825%20M%2076.692536,17.499824%20A%2042.965432,42.965432%200%200%201%2033.519393,91.797827%2042.965432,42.965432%200%200%201%2076.692536,17.499824%20Z'%20style='stroke-width:1.06812763;fill:%23000000'%20/%3e%3cpath%20style='fill:%23000000;stroke:none;stroke-width:0.25893259px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1'%20d='M%2025.29481,56.552597%20C%2078.882863,29.834905%2079.035536,29.834905%2079.035536,29.834905%20L%2052.165174,84.18632%2049.56974,59.3007%20Z'%20/%3e%3c/svg%3e\");\n}\n.graph-explorer-halo__navigate--closed {\n  background-image: url(\"data:image/svg+xml,%3c?xml%20version='1.0'%20encoding='UTF-8'%20standalone='no'?%3e%3csvg%20xmlns:svg='http://www.w3.org/2000/svg'%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20110%20110'%20version='1.1'%20width='500'%20height='500'%3e%3cpath%20d='M%2055.105965,54.648825%20M%2082.182422,8.0521107%20A%2053.892377,53.892377%200%201%200%2028.029508,101.24554%2053.892377,53.892377%200%201%200%2082.182422,8.0521107%20Z%20M%2055.105965,54.648825%20M%2076.692536,17.499824%20A%2042.965432,42.965432%200%200%201%2033.519393,91.797827%2042.965432,42.965432%200%200%201%2076.692536,17.499824%20Z'%20style='stroke-width:1.06812763'%20/%3e%3cpath%20d='M%2070.749364,31.224635%2078.426933,38.910146%2063.054265,54.266973%2078.41107,69.639662%2070.725571,77.317242%2055.368766,61.944553%2039.996098,77.301379%2032.318529,69.615869%2047.691197,54.259042%2032.334392,38.886353%20l%207.685499,-7.67758%2015.356805,15.372689%20z'%20style='stroke-width:1.17913187'%20/%3e%3c/svg%3e\");\n}\n.graph-explorer-halo__folow {\n  position: absolute;\n  background-color: transparent;\n  background-size: contain;\n  background-repeat: no-repeat;\n  background-position: center;\n  border: 0 none;\n  cursor: pointer;\n  outline: none;\n  padding: 0;\n  pointer-events: auto;\n  width: 20px;\n  height: 20px;\n  opacity: 0.5;\n  transition: opacity 0.3s;\n}\n.graph-explorer-halo__folow:hover {\n  opacity: 1;\n}\n.graph-explorer-halo__folow[disabled] {\n  cursor: not-allowed;\n  opacity: 0.2;\n}\n.graph-explorer-halo__folow {\n  top: 50%;\n  margin-top: -10px;\n  left: -22px;\n  background-image: url(\"data:image/svg+xml,%3c?xml%20version='1.0'%20encoding='utf-8'?%3e%3csvg%20version='1.1'%20id='Layer_1'%20xmlns='http://www.w3.org/2000/svg'%20xmlns:xlink='http://www.w3.org/1999/xlink'%20x='0px'%20y='0px'%20width='512px'%20height='512px'%20viewBox='0%200%20512%20512'%20enable-background='new%200%200%20512%20512'%20xml:space='preserve'%3e%3cpath%20fill='%23010101'%20d='M459.654,233.373l-90.531,90.5c-49.969,50-131.031,50-181,0c-7.875-7.844-14.031-16.688-19.438-25.813%20l42.063-42.063c2-2.016,4.469-3.172,6.828-4.531c2.906,9.938,7.984,19.344,15.797,27.156c24.953,24.969,65.563,24.938,90.5,0%20l90.5-90.5c24.969-24.969,24.969-65.563,0-90.516c-24.938-24.953-65.531-24.953-90.5,0l-32.188,32.219%20c-26.109-10.172-54.25-12.906-81.641-8.891l68.578-68.578c50-49.984,131.031-49.984,181.031,0%20C509.623,102.342,509.623,183.389,459.654,233.373z%20M220.326,382.186l-32.203,32.219c-24.953,24.938-65.563,24.938-90.516,0%20c-24.953-24.969-24.953-65.563,0-90.531l90.516-90.5c24.969-24.969,65.547-24.969,90.5,0c7.797,7.797,12.875,17.203,15.813,27.125%20c2.375-1.375,4.813-2.5,6.813-4.5l42.063-42.047c-5.375-9.156-11.563-17.969-19.438-25.828c-49.969-49.984-131.031-49.984-181.016,0%20l-90.5,90.5c-49.984,50-49.984,131.031,0,181.031c49.984,49.969,131.031,49.969,181.016,0l68.594-68.594%20C274.561,395.092,246.42,392.342,220.326,382.186z'/%3e%3c/svg%3e\");\n}\n.graph-explorer-halo__remove {\n  position: absolute;\n  background-color: transparent;\n  background-size: contain;\n  background-repeat: no-repeat;\n  background-position: center;\n  border: 0 none;\n  cursor: pointer;\n  outline: none;\n  padding: 0;\n  pointer-events: auto;\n  width: 20px;\n  height: 20px;\n  opacity: 0.5;\n  transition: opacity 0.3s;\n}\n.graph-explorer-halo__remove:hover {\n  opacity: 1;\n}\n.graph-explorer-halo__remove[disabled] {\n  cursor: not-allowed;\n  opacity: 0.2;\n}\n.graph-explorer-halo__remove {\n  top: -22px;\n  right: -22px;\n  background-image: url(\"data:image/svg+xml,%3c?xml%20version='1.0'%20encoding='UTF-8'%20standalone='no'?%3e%3csvg%20xmlns:svg='http://www.w3.org/2000/svg'%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20110%20110'%20version='1.1'%20width='500'%20height='500'%3e%3cpath%20d='M%2082.182422,8.0521107%20C%2056.44775,-6.9018137%2023.463185,1.8377258%208.5092706,27.57238%20-6.4446434,53.307034%202.2948357,86.291616%2028.029508,101.24554%2053.76418,116.19946%2086.748746,107.45993%20101.70266,81.725271%20116.65657,55.990616%20107.91709,23.006035%2082.182422,8.0521107%20Z%20M%2071.75602,28.578553%2082.28685,38.846984%2065.453479,56.373296%2083.064738,73.314301%2072.796937,83.844485%2055.169736,66.657039%2039.010998,83.228711%2028.480167,72.96028%2044.639378,56.389069%2028.415211,40.568631%2038.683013,30.038446%2054.938893,45.85871%20Z'%20style='fill:%23000000;stroke-width:1.06812763'%20/%3e%3c/svg%3e\");\n}\n.graph-explorer-halo__expand {\n  position: absolute;\n  background-color: transparent;\n  background-size: contain;\n  background-repeat: no-repeat;\n  background-position: center;\n  border: 0 none;\n  cursor: pointer;\n  outline: none;\n  padding: 0;\n  pointer-events: auto;\n  width: 20px;\n  height: 20px;\n  opacity: 0.5;\n  transition: opacity 0.3s;\n}\n.graph-explorer-halo__expand:hover {\n  opacity: 1;\n}\n.graph-explorer-halo__expand[disabled] {\n  cursor: not-allowed;\n  opacity: 0.2;\n}\n.graph-explorer-halo__expand {\n  bottom: -22px;\n  left: 50%;\n  margin-left: -10px;\n}\n.graph-explorer-halo__expand--open {\n  background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4AIMDxQ3d8lonQAAABl0RVh0Q29tbWVudABDcmVhdGVkIHdpdGggR0lNUFeBDhcAAAEOSURBVEjH7dXNK0RhFAbwXxRyZyIlKwtlMbvZkUIW9rOThezEniIf/4E/UYgkGwskaTI2V51uF/NxZ6LuU+/ivec5z/Pe9+McSpQoUeK/YTgz38AEbgv2WcUkHvKCS2ilY7tA0/VU8w2NPMICHoP5TgGmy0HvBfXviNN4D+TdHkzn8BG05n9LmMJdSNjvwrSOZtjiWruJFdwE86MOTGshr4m1TlddxWsQOW5zwTFnsdtzquAyCJ39wJ3Fc+Cu9HozR3ERBE9zODOZF7FV1FtM8BSET0JsKC0MX7FG0VVuHFeZbR/Bffi22a8SO5Y58/inh/2u70lahVph7A2quVRxnZoeDLqzJTgvG3yJP4dPo59Rw97b1k8AAAAASUVORK5CYII=\");\n}\n.graph-explorer-halo__expand--closed {\n  background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4AIMDx0nu7zDsAAAABl0RVh0Q29tbWVudABDcmVhdGVkIHdpdGggR0lNUFeBDhcAAAD+SURBVEjH7ZQxa8JQFIU/HFSqXQri1KHQwc2txaLi4N5NHMRNdFeoqPkH/YlFRRBxcVAREakuEQ7RiDWJWHgHAuHl3Pu9e/PuAyOjO1QM+L419BEYAjugdctKlzb08DSChkaBvgCn8v4VFPQBGAjIAsLARNbKQbR3LoCufAs5Kv/0CxoBfiRx74QnCczEU/EKjTv+qXXG+wwsxJvzMjIrSdS5cKMa835NpSNJ0P5DbEritkDh0sAnYCzBzSu6lbahO2Btb+asEsBGoHUP5+MF+JVcr27GN8fJrPkwEVnJt7Q7caSMmKo+3gFFabnrjJeAjwBuvbxbtUZGRkb/R3tcflA+OTpkkAAAAABJRU5ErkJggg==\");\n}\n.graph-explorer-halo__add-to-filter {\n  position: absolute;\n  background-color: transparent;\n  background-size: contain;\n  background-repeat: no-repeat;\n  background-position: center;\n  border: 0 none;\n  cursor: pointer;\n  outline: none;\n  padding: 0;\n  pointer-events: auto;\n  width: 20px;\n  height: 20px;\n  opacity: 0.5;\n  transition: opacity 0.3s;\n}\n.graph-explorer-halo__add-to-filter:hover {\n  opacity: 1;\n}\n.graph-explorer-halo__add-to-filter[disabled] {\n  cursor: not-allowed;\n  opacity: 0.2;\n}\n.graph-explorer-halo__add-to-filter {\n  bottom: -22px;\n  right: -22px;\n  background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVUAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjExR/NCNwAAAuxJREFUeF7t3V1u4jAYhWFu+FkDIHHBGlgZILbBjtN8M/labEywYzs+js8rHYFUqGo/6twNXTHGWIVdLpduv993x+ORm3Fy53L3A8Nf8sX+gSuw4e7NCFJuBAEbQcBGELARBGxOkNPp9PZCbp4Nd2/2eDy67Xb79mIu7+TO5e775+/d7/dut9u9vYnLM7lrufP++eeIMs+8MDSi5F0QhkaUPJuEoREl7aIwNKKkWRIMjShxS4qhEWXasmBoRAlbVgyNKH6bBUMjyvhmxdCI4l4RDI0o5opiaET5PwgMrXUUKAytVRRIDK01FGgMrRWUKjC0paNUhaEtFaVKDG1pKFVjaEtBWQSGVjvKojC0WlEWiaHVhrJoDK0WlCYwNHSUpjA0VJQmMTQ0lKYxNBQUSIyu697mkXEwa16VRoHCcCHoPDMOZ827UihwvxkuCFlAxgGtBTU3ChyGFIkhGYe0FtxcKJAYUiSGZBzU2qRyo8BiSIggUi4UaAwJFURKjQKPISGDSKlQqsCQEEHsn+N2u3Xr9dr+3t6T98r36J/jVwOIJJ8r1T9M2vDeOqoFJOajP5wfXYGaHp4gIDlAfg9SYP8iyPBIEIAIAhZBwCIIWAQBiyBgKcQLSGjG4a1NiiAEwYkgYCGCuCKIf8bhrSWLIP4Zh7eWLIL4ZxzeWrKaBZmAYhzeWrKaBpEFZBzeWrKaB5F5ZhzeWrIIMswj4/DWkkWQl33JOLy1ZBHEsZIRZGQlIkjCpYgggfvU2NdCIojnvuXzGp8I8mW+hbx2LIIkXIqaAaklgoDVDIjrn5gciy0GxPl3AlFzXV6OxTYVZPTvBCLmurwci20KSDX/je011+XlWGyhIFViSK7Ly7HYQkCqxZBcl5djsfmCVI0huS4vx2LzAakeQ3JdXo7F9g1kERiS6/JyLLYxkMVg1NQnEGIUygVCjILZIMQo3CsIMQBSEGKAdDgcus1mQwyUzudzd71eiYHS8/kkBpu71eoHWjSksuGbaS0AAAAASUVORK5CYII=\");\n}\n.graph-explorer-halo__revert {\n  position: absolute;\n  background-color: transparent;\n  background-size: contain;\n  background-repeat: no-repeat;\n  background-position: center;\n  border: 0 none;\n  cursor: pointer;\n  outline: none;\n  padding: 0;\n  pointer-events: auto;\n  width: 20px;\n  height: 20px;\n  opacity: 0.5;\n  transition: opacity 0.3s;\n}\n.graph-explorer-halo__revert:hover {\n  opacity: 1;\n}\n.graph-explorer-halo__revert[disabled] {\n  cursor: not-allowed;\n  opacity: 0.2;\n}\n.graph-explorer-halo__revert {\n  top: -22px;\n  left: 50%;\n  margin-left: -10px;\n  background-image: url(\"data:image/svg+xml,%3csvg%20aria-hidden='true'%20data-prefix='fas'%20data-icon='undo'%20class='svg-inline--fa%20fa-undo%20fa-w-16'%20role='img'%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20512%20512'%3e%3cpath%20fill='currentColor'%20d='M212.333%20224.333H12c-6.627%200-12-5.373-12-12V12C0%205.373%205.373%200%2012%200h48c6.627%200%2012%205.373%2012%2012v78.112C117.773%2039.279%20184.26%207.47%20258.175%208.007c136.906.994%20246.448%20111.623%20246.157%20248.532C504.041%20393.258%20393.12%20504%20256.333%20504c-64.089%200-122.496-24.313-166.51-64.215-5.099-4.622-5.334-12.554-.467-17.42l33.967-33.967c4.474-4.474%2011.662-4.717%2016.401-.525C170.76%20415.336%20211.58%20432%20256.333%20432c97.268%200%20176-78.716%20176-176%200-97.267-78.716-176-176-176-58.496%200-110.28%2028.476-142.274%2072.333h98.274c6.627%200%2012%205.373%2012%2012v48c0%206.627-5.373%2012-12%2012z'%3e%3c/path%3e%3c/svg%3e\");\n}\n.graph-explorer-halo__establish-connection {\n  position: absolute;\n  background-color: transparent;\n  background-size: contain;\n  background-repeat: no-repeat;\n  background-position: center;\n  border: 0 none;\n  cursor: pointer;\n  outline: none;\n  padding: 0;\n  pointer-events: auto;\n  width: 20px;\n  height: 20px;\n  opacity: 0.5;\n  transition: opacity 0.3s;\n}\n.graph-explorer-halo__establish-connection:hover {\n  opacity: 1;\n}\n.graph-explorer-halo__establish-connection[disabled] {\n  cursor: not-allowed;\n  opacity: 0.2;\n}\n.graph-explorer-halo__establish-connection {\n  bottom: -22px;\n  left: -22px;\n  background-image: url(\"data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20384%20512'%3e%3cpath%20d='M256%20144V32c0-17.673%2014.327-32%2032-32s32%2014.327%2032%2032v112h-64zm112%2016H16c-8.837%200-16%207.163-16%2016v32c0%208.837%207.163%2016%2016%2016h16v32c0%2077.406%2054.969%20141.971%20128%20156.796V512h64v-99.204c73.031-14.825%20128-79.39%20128-156.796v-32h16c8.837%200%2016-7.163%2016-16v-32c0-8.837-7.163-16-16-16zm-240-16V32c0-17.673-14.327-32-32-32S64%2014.327%2064%2032v112h64z'/%3e%3c/svg%3e\");\n}\n.graph-explorer-halo__establish-connection-spinner {\n  position: absolute;\n  width: 20px;\n  height: 20px;\n  bottom: -22px;\n  left: -22px;\n}\n\n.graph-explorer-halo-link__button {\n  background: transparent;\n  border: 0 none;\n  cursor: pointer;\n  padding: 0;\n  position: absolute;\n  opacity: 0.8;\n  outline: none;\n  transition: opacity 0.3s;\n}\n.graph-explorer-halo-link__button:hover {\n  opacity: 1;\n}\n.graph-explorer-halo-link__button[disabled] {\n  cursor: not-allowed;\n  opacity: 0.5;\n}\n.graph-explorer-halo-link__edit {\n  background-color: #ccc;\n  background-position: 50%;\n  background-repeat: no-repeat;\n  background-size: 60%;\n  border-radius: 10px;\n  height: 20px;\n  width: 20px;\n  background-image: url(\"data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20576%20512'%3e%3cpath%20d='M402.6%2083.2l90.2%2090.2c3.8%203.8%203.8%2010%200%2013.8L274.4%20405.6l-92.8%2010.3c-12.4%201.4-22.9-9.1-21.5-21.5l10.3-92.8L388.8%2083.2c3.8-3.8%2010-3.8%2013.8%200zm162-22.9l-48.8-48.8c-15.2-15.2-39.9-15.2-55.2%200l-35.4%2035.4c-3.8%203.8-3.8%2010%200%2013.8l90.2%2090.2c3.8%203.8%2010%203.8%2013.8%200l35.4-35.4c15.2-15.3%2015.2-40%200-55.2zM384%20346.2V448H64V128h229.8c3.2%200%206.2-1.3%208.5-3.5l40-40c7.6-7.6%202.2-20.5-8.5-20.5H48C21.5%2064%200%2085.5%200%20112v352c0%2026.5%2021.5%2048%2048%2048h352c26.5%200%2048-21.5%2048-48V306.2c0-10.7-12.9-16-20.5-8.5l-40%2040c-2.2%202.3-3.5%205.3-3.5%208.5z'/%3e%3c/svg%3e\");\n}\n.graph-explorer-halo-link__delete {\n  background-color: #ccc;\n  background-position: 50%;\n  background-repeat: no-repeat;\n  background-size: 60%;\n  border-radius: 10px;\n  height: 20px;\n  width: 20px;\n  background-image: url(\"data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20448%20512'%3e%3cpath%20d='M0%2084V56c0-13.3%2010.7-24%2024-24h112l9.4-18.7c4-8.2%2012.3-13.3%2021.4-13.3h114.3c9.1%200%2017.4%205.1%2021.5%2013.3L312%2032h112c13.3%200%2024%2010.7%2024%2024v28c0%206.6-5.4%2012-12%2012H12C5.4%2096%200%2090.6%200%2084zm416%2056v324c0%2026.5-21.5%2048-48%2048H80c-26.5%200-48-21.5-48-48V140c0-6.6%205.4-12%2012-12h360c6.6%200%2012%205.4%2012%2012zm-272%2068c0-8.8-7.2-16-16-16s-16%207.2-16%2016v224c0%208.8%207.2%2016%2016%2016s16-7.2%2016-16V208zm96%200c0-8.8-7.2-16-16-16s-16%207.2-16%2016v224c0%208.8%207.2%2016%2016%2016s16-7.2%2016-16V208zm96%200c0-8.8-7.2-16-16-16s-16%207.2-16%2016v224c0%208.8%207.2%2016%2016%2016s16-7.2%2016-16V208z'/%3e%3c/svg%3e\");\n}\n.graph-explorer-halo-link__spinner {\n  position: absolute;\n}\n.graph-explorer-halo-link__edit-label-button {\n  background: transparent url(\"data:image/svg+xml,%3csvg%20aria-hidden='true'%20data-prefix='fas'%20data-icon='pen-square'%20class='svg-inline--fa%20fa-pen-square%20fa-w-14'%20role='img'%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20448%20512'%3e%3cpath%20fill='currentColor'%20d='M400%20480H48c-26.5%200-48-21.5-48-48V80c0-26.5%2021.5-48%2048-48h352c26.5%200%2048%2021.5%2048%2048v352c0%2026.5-21.5%2048-48%2048zM238.1%20177.9L102.4%20313.6l-6.3%2057.1c-.8%207.6%205.6%2014.1%2013.3%2013.3l57.1-6.3L302.2%20242c2.3-2.3%202.3-6.1%200-8.5L246.7%20178c-2.5-2.4-6.3-2.4-8.6-.1zM345%20165.1L314.9%20135c-9.4-9.4-24.6-9.4-33.9%200l-23.1%2023.1c-2.3%202.3-2.3%206.1%200%208.5l55.5%2055.5c2.3%202.3%206.1%202.3%208.5%200L345%20199c9.3-9.3%209.3-24.5%200-33.9z'%3e%3c/path%3e%3c/svg%3e\") no-repeat;\n  background-size: cover;\n  border: 0 none;\n  cursor: pointer;\n  padding: 0;\n  position: absolute;\n  margin-left: 5px;\n  outline: none;\n  opacity: 0.5;\n  transition: opacity 0.3s;\n}\n.graph-explorer-halo-link__edit-label-button:hover {\n  opacity: 1;\n}\n\n.graph-explorer-instances-search {\n  flex: auto;\n  display: flex;\n  flex-direction: column;\n}\n.graph-explorer-instances-search__criteria {\n  flex-shrink: 0;\n  margin: 10px 0 10px 0;\n}\n.graph-explorer-instances-search__criterions {\n  padding-left: 15px;\n  margin-bottom: 10px;\n}\n.graph-explorer-instances-search__criterions:empty {\n  margin-bottom: 0;\n}\n.graph-explorer-instances-search__criterion {\n  display: block;\n  position: relative;\n  width: 100%;\n}\n.graph-explorer-instances-search__criterion-class, .graph-explorer-instances-search__criterion-element, .graph-explorer-instances-search__criterion-link-type {\n  display: inline-block;\n  padding: 2px 10px;\n  border-radius: var(--ge-radius-pill);\n  border: 1px solid transparent;\n  font-size: 12px;\n  font-weight: 500;\n  word-wrap: break-word;\n}\n.graph-explorer-instances-search__criterion-class {\n  background: #fef3c7;\n  border-color: #fcd34d;\n  color: #92400e;\n}\n.graph-explorer-instances-search__criterion-element {\n  background: #ffedd5;\n  border-color: #fdba74;\n  color: #9a3412;\n}\n.graph-explorer-instances-search__criterion-link-type {\n  background: #dcfce7;\n  border-color: #86efac;\n  color: #166534;\n}\n.graph-explorer-instances-search__link-direction {\n  height: 1em;\n  opacity: 0.5;\n}\n.graph-explorer-instances-search__criterion-remove {\n  float: right;\n  margin: 0 10px 4px 4px;\n}\n.graph-explorer-instances-search__text-criteria {\n  margin: 0 10px;\n}\n.graph-explorer-instances-search__rest {\n  padding: 10px 10px 0 10px;\n  border-top: 1px solid var(--ge-border);\n}\n.graph-explorer-instances-search__results {\n  padding-left: 0;\n  padding-top: 10px;\n  margin: 0 10px 0 10px;\n  outline: none;\n}\n.graph-explorer-instances-search[data-state=finished] .graph-explorer-instances-search__results:empty:before {\n  content: \"No items correspond to the specified criteria.\";\n  font-style: italic;\n}\n.graph-explorer-instances-search__rest-end {\n  margin: 5px 0 10px 0;\n}\n.graph-explorer-instances-search__load-more {\n  width: 100%;\n}\n\n.link-types-toolbox {\n  flex: auto;\n  display: flex;\n  flex-direction: column;\n  margin-bottom: 0;\n}\n.link-types-toolbox__heading {\n  padding: 10px;\n}\n.link-types-toolbox__searching-box {\n  display: flex;\n  align-items: center;\n}\n.link-types-toolbox__clearSearch {\n  margin-left: -25px;\n  -webkit-appearance: none;\n  padding: 0;\n  cursor: pointer;\n  background: 0 0;\n  border: 0;\n}\n.link-types-toolbox__switch-all {\n  margin-top: 5px;\n}\n.link-types-toolbox__rest {\n  border-top: 1px solid #dddddd;\n  flex: auto;\n  display: flex;\n  flex-direction: column;\n}\n\n.link-types-toolbox .panel-heading {\n  flex-shrink: 0;\n  -webkit-flex-shrink: 0; /* safari 8 */\n}\n\n.link-types-toolbox ul {\n  margin-bottom: 0;\n}\n\n.link-types-toolbox .links-heading {\n  margin-left: 0.4em;\n}\n\n.link-types-toolbox .links-heading span {\n  border: black 1px dashed;\n  background: rgb(255, 131, 92);\n  padding: 0 0.5em 0 0.5em;\n  word-wrap: break-word;\n  line-height: 1.3;\n}\n\n.link-types-toolbox__heading .link-types-toolbox-controls {\n  padding: 5px 15px;\n  font-size: 14px;\n  font-style: italic;\n}\n\n.link-types-toolbox__heading .link-types-toolbox-controls > span {\n  padding-left: 0.3em;\n}\n\n.graph-explorer-list-group .linkInToolBox {\n  padding: 0 0 0 5px;\n  word-break: break-word;\n}\n\n.linkInToolBox > div {\n  display: inline;\n}\n.linkInToolBox__new-tag {\n  margin-left: 0.5em;\n  white-space: normal;\n  word-wrap: normal;\n  border-radius: 2px;\n  padding: 0 5px;\n  background: orange;\n}\n.linkInToolBox .graph-explorer-badge {\n  display: none;\n  margin-left: 0.5em;\n  white-space: normal;\n  word-wrap: normal;\n}\n.linkInToolBox .link-title {\n  font-size: 16px;\n  color: black;\n  display: inline;\n}\n.linkInToolBox .graph-explorer-btn-group {\n  float: left;\n  margin-top: 2px;\n  margin-right: 6px;\n  margin-bottom: 2px;\n}\n.linkInToolBox .graph-explorer-btn.graph-explorer-btn-default {\n  border-color: rgb(195, 195, 195);\n}\n.linkInToolBox__filter-button {\n  display: none;\n  float: right;\n  background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVUAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjExR/NCNwAAAuxJREFUeF7t3V1u4jAYhWFu+FkDIHHBGlgZILbBjtN8M/labEywYzs+js8rHYFUqGo/6twNXTHGWIVdLpduv993x+ORm3Fy53L3A8Nf8sX+gSuw4e7NCFJuBAEbQcBGELARBGxOkNPp9PZCbp4Nd2/2eDy67Xb79mIu7+TO5e775+/d7/dut9u9vYnLM7lrufP++eeIMs+8MDSi5F0QhkaUPJuEoREl7aIwNKKkWRIMjShxS4qhEWXasmBoRAlbVgyNKH6bBUMjyvhmxdCI4l4RDI0o5opiaET5PwgMrXUUKAytVRRIDK01FGgMrRWUKjC0paNUhaEtFaVKDG1pKFVjaEtBWQSGVjvKojC0WlEWiaHVhrJoDK0WlCYwNHSUpjA0VJQmMTQ0lKYxNBQUSIyu697mkXEwa16VRoHCcCHoPDMOZ827UihwvxkuCFlAxgGtBTU3ChyGFIkhGYe0FtxcKJAYUiSGZBzU2qRyo8BiSIggUi4UaAwJFURKjQKPISGDSKlQqsCQEEHsn+N2u3Xr9dr+3t6T98r36J/jVwOIJJ8r1T9M2vDeOqoFJOajP5wfXYGaHp4gIDlAfg9SYP8iyPBIEIAIAhZBwCIIWAQBiyBgKcQLSGjG4a1NiiAEwYkgYCGCuCKIf8bhrSWLIP4Zh7eWLIL4ZxzeWrKaBZmAYhzeWrKaBpEFZBzeWrKaB5F5ZhzeWrIIMswj4/DWkkWQl33JOLy1ZBHEsZIRZGQlIkjCpYgggfvU2NdCIojnvuXzGp8I8mW+hbx2LIIkXIqaAaklgoDVDIjrn5gciy0GxPl3AlFzXV6OxTYVZPTvBCLmurwci20KSDX/je011+XlWGyhIFViSK7Ly7HYQkCqxZBcl5djsfmCVI0huS4vx2LzAakeQ3JdXo7F9g1kERiS6/JyLLYxkMVg1NQnEGIUygVCjILZIMQo3CsIMQBSEGKAdDgcus1mQwyUzudzd71eiYHS8/kkBpu71eoHWjSksuGbaS0AAAAASUVORK5CYII=\");\n  background-size: 20px 20px;\n  width: 20px;\n  height: 20px;\n  margin: 3px;\n  cursor: pointer;\n  opacity: 0.4;\n  transition: opacity 200ms 0ms;\n}\n.linkInToolBox:hover .linkInToolBox__filter-button {\n  opacity: 1;\n  transition: opacity 200ms 0ms;\n}\n\n.connected-links .linkInToolBox .graph-explorer-badge {\n  /* show connection count badge only in \"Connected to Element\" list */\n  display: inline;\n}\n\n.connected-links .linkInToolBox__filter-button {\n  /* show filter button only in \"Connected to Element\" list */\n  display: inline;\n}\n\n.graph-explorer-list-element-view {\n  position: relative;\n  display: block;\n  background: var(--ge-text-subtle);\n  padding: 2px 2px 2px 6px;\n  border-radius: var(--ge-radius-sm);\n  margin: 0 0 4px 0;\n  opacity: 1;\n  cursor: move;\n  user-select: none;\n  box-shadow: var(--ge-shadow-xs);\n  transition: box-shadow var(--ge-transition), transform var(--ge-transition);\n}\n.graph-explorer-list-element-view:hover {\n  box-shadow: var(--ge-shadow-sm);\n}\n.graph-explorer-list-element-view--disabled {\n  opacity: 0.4;\n  cursor: default;\n  box-shadow: none;\n}\n.graph-explorer-list-element-view__label {\n  background: var(--ge-surface);\n  border-radius: 0 var(--ge-radius-sm) var(--ge-radius-sm) 0;\n  font-family: var(--ge-font-mono);\n  font-size: 13px;\n  color: var(--ge-text);\n  min-height: 1.4em;\n  padding: 3px 8px;\n  overflow-wrap: break-word;\n}\n\n.graph-explorer-text-highlight {\n  font-weight: 700;\n  color: var(--ge-accent-hover);\n}\n\n.graph-explorer-navigator {\n  display: block;\n  position: absolute;\n  bottom: 25px;\n  right: 25px;\n  overflow: hidden;\n}\n.graph-explorer .graph-explorer-navigator {\n  box-sizing: content-box;\n}\n.graph-explorer-navigator {\n  background: var(--ge-surface);\n  border: 1px solid var(--ge-border);\n  border-radius: var(--ge-radius);\n  box-shadow: var(--ge-shadow-md);\n  transition: width 0.3s, height 0.3s;\n}\n.graph-explorer-navigator--collapsed {\n  width: 26px;\n  height: 26px;\n}\n.graph-explorer-navigator > canvas {\n  transition: opacity 0.3s;\n}\n.graph-explorer-navigator--expanded > canvas {\n  opacity: 1;\n}\n.graph-explorer-navigator--collapsed > canvas {\n  opacity: 0;\n}\n.graph-explorer-navigator__toggle {\n  position: absolute;\n  background: transparent;\n  border: none;\n  outline: none;\n  padding: 4px;\n  opacity: 0.5;\n  transition: opacity 0.3s;\n}\n.graph-explorer-navigator__toggle:hover {\n  opacity: 1;\n}\n.graph-explorer-navigator--expanded .graph-explorer-navigator__toggle {\n  top: 5px;\n  left: 5px;\n}\n.graph-explorer-navigator--collapsed .graph-explorer-navigator__toggle {\n  top: 0px;\n  left: 0px;\n}\n.graph-explorer-navigator__toggle-icon {\n  width: 18px;\n  height: 18px;\n  background-size: 18px 18px;\n  background-repeat: no-repeat;\n}\n.graph-explorer-navigator--expanded .graph-explorer-navigator__toggle-icon {\n  background-image: url(\"data:image/svg+xml,%3csvg%20aria-hidden='true'%20focusable='false'%20data-prefix='far'%20data-icon='minus-square'%20class='svg-inline--fa%20fa-minus-square%20fa-w-14'%20role='img'%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20448%20512'%3e%3cpath%20fill='currentColor'%20d='M108%20284c-6.6%200-12-5.4-12-12v-32c0-6.6%205.4-12%2012-12h232c6.6%200%2012%205.4%2012%2012v32c0%206.6-5.4%2012-12%2012H108zM448%2080v352c0%2026.5-21.5%2048-48%2048H48c-26.5%200-48-21.5-48-48V80c0-26.5%2021.5-48%2048-48h352c26.5%200%2048%2021.5%2048%2048zm-48%20346V86c0-3.3-2.7-6-6-6H54c-3.3%200-6%202.7-6%206v340c0%203.3%202.7%206%206%206h340c3.3%200%206-2.7%206-6z'%3e%3c/path%3e%3c/svg%3e\");\n}\n.graph-explorer-navigator--collapsed .graph-explorer-navigator__toggle-icon {\n  background-image: url(\"data:image/svg+xml,%3csvg%20aria-hidden='true'%20focusable='false'%20data-prefix='far'%20data-icon='plus-square'%20class='svg-inline--fa%20fa-plus-square%20fa-w-14'%20role='img'%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20448%20512'%3e%3cpath%20fill='currentColor'%20d='M352%20240v32c0%206.6-5.4%2012-12%2012h-88v88c0%206.6-5.4%2012-12%2012h-32c-6.6%200-12-5.4-12-12v-88h-88c-6.6%200-12-5.4-12-12v-32c0-6.6%205.4-12%2012-12h88v-88c0-6.6%205.4-12%2012-12h32c6.6%200%2012%205.4%2012%2012v88h88c6.6%200%2012%205.4%2012%2012zm96-160v352c0%2026.5-21.5%2048-48%2048H48c-26.5%200-48-21.5-48-48V80c0-26.5%2021.5-48%2048-48h352c26.5%200%2048%2021.5%2048%2048zm-48%20346V86c0-3.3-2.7-6-6-6H54c-3.3%200-6%202.7-6%206v340c0%203.3%202.7%206%206%206h340c3.3%200%206-2.7%206-6z'%3e%3c/path%3e%3c/svg%3e\");\n}\n\n@keyframes graph-explorer-progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n.graph-explorer-progress-bar {\n  flex-shrink: 0;\n  -webkit-flex-shrink: 0; /* safari 8 */\n  width: 100%;\n  background-color: var(--ge-surface-3);\n  background-repeat: repeat-x;\n  overflow: hidden;\n}\n.graph-explorer-progress-bar__bar {\n  float: left;\n  height: 100%;\n  font-size: 12px;\n  line-height: 20px;\n  color: #fff;\n  text-align: center;\n  transition: width 0.6s ease;\n  background-color: var(--ge-accent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-repeat: repeat-x;\n  background-size: 40px 40px;\n  animation: graph-explorer-progress-bar-stripes 2s linear infinite;\n}\n.graph-explorer-progress-bar--error .graph-explorer-progress-bar__bar {\n  background-color: var(--ge-danger);\n}\n.graph-explorer-progress-bar--loading, .graph-explorer-progress-bar--error {\n  /* property name | duration | delay */\n  transition: height 300ms 300ms;\n}\n.graph-explorer-progress-bar--completed {\n  /* property name | duration | delay */\n  transition: height 200ms 0ms;\n}\n\n.graph-explorer-search-results {\n  margin: 0;\n  padding: 0;\n  outline: none;\n}\n\n.graph-explorer-accordion {\n  flex: auto;\n  display: flex;\n  height: 100%;\n  width: 100%;\n}\n.graph-explorer-accordion--scrollable {\n  overflow: auto;\n}\n.graph-explorer-accordion--vertical {\n  flex-direction: column;\n}\n.graph-explorer-accordion--vertical:not(.graph-explorer-accordion--resizing) > .graph-explorer-accordion-item {\n  transition: height 0.3s ease-in-out;\n}\n\n.graph-explorer-accordion-item {\n  display: flex;\n  position: relative;\n  flex: auto;\n}\n.graph-explorer-accordion-item--resizing > .graph-explorer-accordion-item__handle, .graph-explorer-accordion-item__handle:hover {\n  background: rgba(0, 0, 0, 0.1);\n}\n.graph-explorer-accordion-item--vertical {\n  border-top: 1px solid var(--ge-border);\n}\n.graph-explorer-accordion-item--vertical:first-child {\n  border-top-width: 0;\n}\n.graph-explorer-accordion-item--horizontal {\n  border-right: 1px solid var(--ge-border);\n}\n.graph-explorer-accordion-item--horizontal:last-child {\n  border-right-width: 0;\n}\n.graph-explorer-accordion-item__handle {\n  position: absolute;\n  z-index: 2;\n}\n.graph-explorer-accordion-item__handle-vertical {\n  height: 5px;\n  bottom: -2.5px;\n  left: 0;\n  width: 100%;\n  cursor: ns-resize;\n}\n.graph-explorer-accordion-item__handle-horizontal {\n  height: 100%;\n  top: 0;\n  right: -2.5px;\n  width: 5px;\n  cursor: ew-resize;\n}\n.graph-explorer-accordion-item__handle-btn {\n  background: var(--ge-surface);\n  border: 2px solid var(--ge-accent);\n  box-shadow: var(--ge-shadow-sm);\n  border-radius: 10px;\n  cursor: pointer;\n  height: 20px;\n  position: absolute;\n  top: 50%;\n  margin-top: -10px;\n  width: 20px;\n  z-index: 20;\n  transition: 0.3s;\n}\n.graph-explorer-accordion-item__handle-btn::before {\n  background-position: 0 0;\n  background-repeat: no-repeat;\n  background-size: cover;\n  content: \"\";\n  height: 8px;\n  position: absolute;\n  top: 50%;\n  left: 50%;\n  margin-top: -4px;\n  margin-left: -4px;\n  width: 8px;\n  transition: background 0.3s;\n}\n.graph-explorer-accordion-item__handle-btn:hover {\n  background: var(--ge-accent);\n}\n.graph-explorer-accordion-item__handle-btn-left {\n  left: 100%;\n  margin-left: -10px;\n}\n.graph-explorer-accordion-item__handle-btn-left:before {\n  background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAACXSURBVHjaYvz//z8DIbBlyxYmIDUTiI/6+PgsQJZjJGQAVPMcIE4E4n9AnAA0ZDFRBqBphoELQGwKNOQPiMNEoubLQOwG04zTADyanYGaXyOrZaJEM4YBpGpGMYAczXgDkVgANwBoCyiOU4B4PpK8LhDvBbpOlCgXkGMIhhdINQRrGJBiCO2SMg6XgPh9yEmZkdLsDBBgAMUxZ3KEE1BeAAAAAElFTkSuQmCC\");\n}\n.graph-explorer-accordion-item__handle-btn-left:hover:before {\n  background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAACXSURBVHjaYvz//z8DIfD+/XsmIDUTiI8KCgouQJZjJGQAVPMcIE4E4n9AnAA0ZDFRBqBphoELQGwKNOQPiMNEoubLQOwG04zTADyanYGaXyOrZaJEM4YBpGpGMYAczXgDkVgANwBoCyiOU4B4PpK8LhDvBbpOlCgXkGMIhhdINQRrGJBiCO2SMg6XgPh9yEmZkdLsDBBgAKQBZhCkUF/8AAAAAElFTkSuQmCC\");\n}\n.graph-explorer-accordion-item__handle-btn-right {\n  right: 100%;\n  margin-right: -10px;\n}\n.graph-explorer-accordion-item__handle-btn-right:before {\n  background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAACdSURBVHjaYvz//z8DMtiyZUsCkLIG4nQfH59/DAQAI7IBQM2xQGoBEDMB8XwgTiFkCNwAoGYWIHUaiA2Q5AkawgRjABX9AVJuQHwZST4RiOcADWciaADUkNdAypkUQzAESTUEq6mkGILTb8QawsRAIcBpANAWUSC1F4h18UUrEyWasRpAimYMA0jVTJOk3AfE/4jVjJEbycnOAAEGABIyZ3LVo9KqAAAAAElFTkSuQmCC\");\n}\n.graph-explorer-accordion-item__handle-btn-right:hover:before {\n  background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAACeSURBVHjaYvz//z8DMnj//n0CkLIG4nRBQcF/DAQAC5rmWCA1F4iZgJgZyE8hZAgjzAVAxSDDTgOxAZL8fCDGawgTjAFU9AdIuQHxZST5RCCeAzSciaABUENeAylnUgzBECTVEKymkmIITr8RawgTA4UApwFAW0SB1F4g1sUXrUyUaMZqACmaMQwgVTNNknIfEP8jVjOKC8jNzgABBgBosmVE6sxD1QAAAABJRU5ErkJggg==\");\n}\n.graph-explorer-accordion-item--collapsed .graph-explorer-accordion-item__handle-btn:before {\n  transform: rotate(180deg);\n}\n.graph-explorer-accordion-item__inner {\n  flex: auto;\n  display: flex;\n  flex-direction: column;\n  overflow: hidden;\n}\n.graph-explorer-accordion-item__body {\n  flex: 1 1 0px;\n  display: flex;\n  flex-direction: column;\n  background: var(--ge-surface);\n}\n.graph-explorer-accordion-item__header {\n  padding: 11px 12px 11px 24px;\n  position: relative;\n  flex-shrink: 0;\n  font-size: 11px;\n  font-weight: 600;\n  letter-spacing: 0.06em;\n  text-transform: uppercase;\n  color: var(--ge-text-muted);\n  background: var(--ge-surface-2);\n  border-bottom: 1px solid var(--ge-border);\n  cursor: pointer;\n  transition: background var(--ge-transition), color var(--ge-transition);\n  /* unselectable */\n  -webkit-touch-callout: none;\n  -webkit-user-select: none;\n  -moz-user-select: none;\n  -ms-user-select: none;\n  user-select: none;\n}\n.graph-explorer-accordion-item__header:hover {\n  background: var(--ge-surface-3);\n  color: var(--ge-text);\n}\n.graph-explorer-accordion-item__header:before {\n  border-top: 5px solid var(--ge-text-subtle);\n  border-left: 4px solid transparent;\n  border-right: 4px solid transparent;\n  content: \"\";\n  position: absolute;\n  top: 50%;\n  left: 9px;\n  margin-top: -2px;\n  transition: transform 0.15s ease;\n}\n.graph-explorer-accordion-item--collapsed .graph-explorer-accordion-item__header:before {\n  -webkit-transform: rotate(-90deg);\n  -moz-transform: rotate(-90deg);\n  -ms-transform: rotate(-90deg);\n  transform: rotate(-90deg);\n}\n.graph-explorer-accordion-item--collapsed .graph-explorer-accordion-item__body {\n  display: none;\n}\n\n.graph-explorer-drag-resizable-column.graph-explorer-drag-resizable-column--docked-bottom .graph-explorer-drag-resizable-column__handle,\n.graph-explorer-drag-resizable-column.graph-explorer-drag-resizable-column--docked-top .graph-explorer-drag-resizable-column__handle {\n  height: 8px;\n  width: 100%;\n  top: initial;\n  left: 0;\n  cursor: ns-resize;\n}\n.graph-explorer-drag-resizable-column.graph-explorer-drag-resizable-column--docked-bottom .graph-explorer-drag-resizable-column__handle-btn,\n.graph-explorer-drag-resizable-column.graph-explorer-drag-resizable-column--docked-top .graph-explorer-drag-resizable-column__handle-btn {\n  height: 100%;\n  width: 40px;\n  top: 0;\n  left: 50%;\n  margin-left: -20px;\n  margin-top: 0px;\n}\n\n.graph-explorer-drag-resizable-column {\n  display: flex;\n  flex-direction: column;\n  position: relative;\n}\n.graph-explorer-drag-resizable-column__handle {\n  background: #fff url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAAECAYAAACp8Z5+AAAAHElEQVQIW2PcvHnzf19fX0YGKIAzMARgKjFUAABdvQgFy9518AAAAABJRU5ErkJggg==\") repeat;\n  width: 8px;\n  height: 100%;\n  position: absolute;\n  top: 0;\n  left: initial;\n  z-index: 2;\n  -webkit-transition: 0.3s;\n  -moz-transition: 0.3s;\n  transition: 0.3s;\n  cursor: ew-resize;\n}\n.graph-explorer-drag-resizable-column__handle-btn {\n  background: #eee;\n  cursor: pointer;\n  height: 40px;\n  position: absolute;\n  top: 50%;\n  left: 0;\n  margin-top: -20px;\n  width: 100%;\n  z-index: 1;\n  -webkit-transition: 0.3s;\n  -moz-transition: 0.3s;\n  transition: 0.3s;\n}\n.graph-explorer-drag-resizable-column__handle-btn::before {\n  background-position: 0 0;\n  background-repeat: no-repeat;\n  background-size: cover;\n  content: \"\";\n  height: 6px;\n  position: absolute;\n  top: 50%;\n  left: 50%;\n  margin-top: -3px;\n  margin-left: -3px;\n  width: 6px;\n  -webkit-transition: 0.3s;\n  -moz-transition: 0.3s;\n  transition: 0.3s;\n}\n.graph-explorer-drag-resizable-column__handle-btn:hover {\n  background: #b3b3b3;\n  transform: scale(1.2);\n}\n.graph-explorer-drag-resizable-column--closed .graph-explorer-drag-resizable-column__handle-btn::before {\n  transform: rotate(180deg);\n}\n.graph-explorer-drag-resizable-column--docked-left {\n  margin-right: 8px;\n}\n.graph-explorer-drag-resizable-column--docked-left .graph-explorer-drag-resizable-column__handle {\n  right: -8px;\n}\n.graph-explorer-drag-resizable-column--docked-left .graph-explorer-drag-resizable-column__handle-btn::before {\n  background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAACXSURBVHjaYvz//z8DIbBlyxYmIDUTiI/6+PgsQJZjJGQAVPMcIE4E4n9AnAA0ZDFRBqBphoELQGwKNOQPiMNEoubLQOwG04zTADyanYGaXyOrZaJEM4YBpGpGMYAczXgDkVgANwBoCyiOU4B4PpK8LhDvBbpOlCgXkGMIhhdINQRrGJBiCO2SMg6XgPh9yEmZkdLsDBBgAMUxZ3KEE1BeAAAAAElFTkSuQmCC\");\n}\n.graph-explorer-drag-resizable-column--docked-left .graph-explorer-drag-resizable-column__handle-btn:hover::before {\n  background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAACXSURBVHjaYvz//z8DIfD+/XsmIDUTiI8KCgouQJZjJGQAVPMcIE4E4n9AnAA0ZDFRBqBphoELQGwKNOQPiMNEoubLQOwG04zTADyanYGaXyOrZaJEM4YBpGpGMYAczXgDkVgANwBoCyiOU4B4PpK8LhDvBbpOlCgXkGMIhhdINQRrGJBiCO2SMg6XgPh9yEmZkdLsDBBgAKQBZhCkUF/8AAAAAElFTkSuQmCC\");\n}\n.graph-explorer-drag-resizable-column--docked-right {\n  margin-left: 8px;\n}\n.graph-explorer-drag-resizable-column--docked-right .graph-explorer-drag-resizable-column__handle {\n  left: -8px;\n}\n.graph-explorer-drag-resizable-column--docked-right .graph-explorer-drag-resizable-column__handle-btn::before {\n  background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAACdSURBVHjaYvz//z8DMtiyZUsCkLIG4nQfH59/DAQAI7IBQM2xQGoBEDMB8XwgTiFkCNwAoGYWIHUaiA2Q5AkawgRjABX9AVJuQHwZST4RiOcADWciaADUkNdAypkUQzAESTUEq6mkGILTb8QawsRAIcBpANAWUSC1F4h18UUrEyWasRpAimYMA0jVTJOk3AfE/4jVjJEbycnOAAEGABIyZ3LVo9KqAAAAAElFTkSuQmCC\");\n}\n.graph-explorer-drag-resizable-column--docked-right .graph-explorer-drag-resizable-column__handle-btn:hover::before {\n  background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAACeSURBVHjaYvz//z8DMnj//n0CkLIG4nRBQcF/DAQAC5rmWCA1F4iZgJgZyE8hZAgjzAVAxSDDTgOxAZL8fCDGawgTjAFU9AdIuQHxZST5RCCeAzSciaABUENeAylnUgzBECTVEKymkmIITr8RawgTA4UApwFAW0SB1F4g1sUXrUyUaMZqACmaMQwgVTNNknIfEP8jVjOKC8jNzgABBgBosmVE6sxD1QAAAABJRU5ErkJggg==\");\n}\n.graph-explorer-drag-resizable-column--docked-top {\n  margin-bottom: 8px;\n}\n.graph-explorer-drag-resizable-column--docked-top .graph-explorer-drag-resizable-column__handle {\n  bottom: -8px;\n}\n.graph-explorer-drag-resizable-column--docked-top .graph-explorer-drag-resizable-column__handle-btn::before {\n  background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAA30lEQVQ4T7WTzw2CMBSH37Ou4BiemICYeODABiYSmcAJOoELiPHgBiXhYGKYgBNjuIJQ80ghBfsaEmKPbb/v90v/ICwcuJAHr0BKuaIAKWXLBbECgoMgyAisqirlJE6BBScm+c5JfgQOuG/vlIwEHpiVDAIGrg25tQ5x1KQTcLAQYkfrTdO8AMApQR8cRdGbBEVRbDgJ5nl+BYDUqlhTcg/384wkQ6XUERFvAECPxgkzklZrferOQCl1QMSzEGI/TZ6+QNPkqbW+xHH8GG6hLMt1GIafOX/D3vvfzzSnzRcwRIO9lTALYQAAAABJRU5ErkJggg==\");\n}\n.graph-explorer-drag-resizable-column--docked-top .graph-explorer-drag-resizable-column__handle-btn:hover::before {\n  background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAA1ElEQVQ4T7WTQQrCMBBF88Usu2jBY3gKwVsIij2BB/ECVlx4C8FT9BhCZ9FlpV9SmlJrphSKWSZ57w+ZCczMhZm8GRWQXLgAALUWpAocXBRF5sAkSVJNEhR4GMDBCUjeNMmPYAj70jXJl0CDxySdQIHzFl5rkkagwdbajTuvquppjAlKMAZHUfRygrIsV6pERC4k016fc5fsYb8fkgDIICJ7kldjjBuaIKxIagDH5g1EZEfyZK3dDpOHE9hW8gBwjuP43u/CEsB7yt8g2d3972eaUs0Hvw2bpYUKd8YAAAAASUVORK5CYII=\");\n}\n.graph-explorer-drag-resizable-column--docked-bottom {\n  margin-top: 8px;\n}\n.graph-explorer-drag-resizable-column--docked-bottom .graph-explorer-drag-resizable-column__handle {\n  top: -8px;\n}\n.graph-explorer-drag-resizable-column--docked-bottom .graph-explorer-drag-resizable-column__handle-btn::before {\n  background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAA60lEQVQ4T62TzQ2CQBBGv3FtwTI8UQEx8cCBDkw0UoEVbAU2IMaDHSwJBxNDBZwswxZc1ixhCbI/IUGOy7w3s7MzhJkfzeTRC6qqWsZx/JkiHMa2AiHEjohOjLFtkiTvkKQsy5WU8qGUOqdpeichxJ6IrgAWAF6MsY1P0sFPAGsAjVLqSEVRXABkg6xOyQg24TlxzhdRFOUADj6JB77VdZ21PQhJ9H8ppSnb5GhhznnTv4JP0hH6zhasD37mwCMZPkqf2RxagxSQWLBVgbE6JE7YKxg1FqZhrgEL7oKupJM1vun83zJNWSJXzBeWo4O9On9s3QAAAABJRU5ErkJggg==\");\n}\n.graph-explorer-drag-resizable-column--docked-bottom .graph-explorer-drag-resizable-column__handle-btn:hover::before {\n  background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAA5klEQVQ4T62TQQrCMBBF5xez7KIFj+EpBG8hKPYEHsQLWHHhLQRP4TGEZtFlpF8S2hJtUgo1q5DMf/NnJoHMXJiplx5AcgHgPQXoxzqA1npL8qiU2qRp+hqD1HW9NMbcAZyyLLtBa70jeRGRRESeSql1DNKKHyKyEpEGwMECziQLL2sQ8iN24QBKkEyqqioB7GOQkJjkNc/zwvVgDGLvjTGdbZejFwONP4Wgk9aVrXkgdmX4HY846UP8zN3h4CHFICHxwIFn86ucmDgK8Btr967bQBN6YKN/wZbTzjsoHnUw5U/8BfABHFmbpQyQ0q0AAAAASUVORK5CYII=\");\n}\n\n.introjs-tooltiptext {\n  color: #333;\n  font-family: \"Helvetica Neue\", \"Helvetica\", \"Arial\", sans-serif;\n  font-size: 14px;\n  line-height: 1.42857;\n}\n\n.graph-explorer-toolbar {\n  display: inline-flex;\n  align-items: center;\n  padding: 6px;\n  background: var(--ge-surface);\n  border: 1px solid var(--ge-border);\n  border-radius: var(--ge-radius-lg);\n  box-shadow: var(--ge-shadow-md);\n}\n.graph-explorer-toolbar .graph-explorer-btn-group {\n  display: inline-flex;\n  align-items: center;\n  flex-wrap: wrap;\n  gap: 2px;\n}\n.graph-explorer-toolbar .graph-explorer-btn-group > .graph-explorer-btn,\n.graph-explorer-toolbar .graph-explorer-btn-group > .graph-explorer-btn-group {\n  float: none;\n  margin-left: 0;\n}\n.graph-explorer-toolbar .graph-explorer-btn-default {\n  background: transparent;\n  border-color: transparent;\n  box-shadow: none;\n  color: var(--ge-text-muted);\n}\n.graph-explorer-toolbar .graph-explorer-btn-default:hover {\n  background: var(--ge-surface-3);\n  border-color: transparent;\n  color: var(--ge-text);\n}\n.graph-explorer-toolbar .graph-explorer-btn-default.active {\n  background: var(--ge-accent-soft);\n  border-color: transparent;\n  color: var(--ge-accent-hover);\n}\n.graph-explorer-toolbar__language-selector {\n  display: inline-flex;\n  align-items: center;\n  margin-left: 8px;\n  padding-left: 10px;\n  border-left: 1px solid var(--ge-border);\n  color: var(--ge-text-muted);\n  font-size: 13px;\n}\n.graph-explorer-toolbar__language-selector > label {\n  margin-right: 8px;\n  margin-bottom: 0;\n  font-weight: 500;\n}\n.graph-explorer-toolbar__language-selector > label > span {\n  vertical-align: middle;\n}\n.graph-explorer-toolbar__language-selector > select {\n  height: 32px;\n  padding: 0 10px;\n  background: var(--ge-surface);\n  border: 1px solid var(--ge-border-strong);\n  border-radius: var(--ge-radius-sm);\n  color: var(--ge-text);\n  cursor: pointer;\n  transition: border-color var(--ge-transition), box-shadow var(--ge-transition);\n}\n.graph-explorer-toolbar__language-selector > select:focus {\n  outline: none;\n  border-color: var(--ge-accent);\n  box-shadow: var(--ge-ring);\n}\n.graph-explorer-toolbar__toggle {\n  line-height: 1;\n}\n.graph-explorer-toolbar__toggle:after {\n  background-position: center;\n  background-repeat: no-repeat;\n  content: \"\";\n  display: block;\n  height: 14px;\n  margin: 2px 0;\n  width: 14px;\n}\n.graph-explorer-toolbar__toggle-left:after {\n  background-image: url(\"data:image/svg+xml,%3csvg%20version='1.1'%20xmlns='http://www.w3.org/2000/svg'%20width='12'%20height='12'%20viewBox='0%200%20469.333%20469.333'%3e%3cpath%20fill='%23333'%20d='M448,0H21.333C9.552,0,0,9.552,0,21.333V448c0,11.781,9.552,21.333,21.333,21.333H448c11.781,0,21.333-9.552,21.333-21.333V21.333C469.333,9.552,459.781,0,448,0z%20M138.667,426.667h-96v-384h96V426.667zM426.667,426.667H181.333v-384h245.333V426.667z'/%3e%3c/svg%3e\");\n}\n.graph-explorer-toolbar__toggle-right:after {\n  background-image: url(\"data:image/svg+xml,%3csvg%20version='1.1'%20xmlns='http://www.w3.org/2000/svg'%20width='12'%20height='12'%20viewBox='0%200%20469.333%20469.333'%3e%3cpath%20fill='%23333'%20d='M448,0H21.333C9.552,0,0,9.552,0,21.333V448c0,11.781,9.552,21.333,21.333,21.333H448c11.781,0,21.333-9.552,21.333-21.333V21.333C469.333,9.552,459.781,0,448,0z%20M288,426.667H42.667v-384H288V426.667zM426.667,426.667h-96v-384h96V426.667z'/%3e%3c/svg%3e\");\n}\n.graph-explorer-toolbar__toggle-left.active:after {\n  background-image: url(\"data:image/svg+xml,%3csvg%20version='1.1'%20xmlns='http://www.w3.org/2000/svg'%20width='12'%20height='12'%20viewBox='0%200%20469.333%20469.333'%3e%3cpath%20fill='%23333'%20d='m%2030.5,235.66084%200,-205.208259%2059.6835,0%2059.68352,0%200,205.208259%200,205.20828%20-59.68352,0%20-59.6835,0%200,-205.20828%20z'/%3e%3cpath%20fill='%23333'%20d='M448,0H21.333C9.552,0,0,9.552,0,21.333V448c0,11.781,9.552,21.333,21.333,21.333H448c11.781,0,21.333-9.552,21.333-21.333V21.333C469.333,9.552,459.781,0,448,0z%20M138.667,426.667h-96v-384h96V426.667zM426.667,426.667H181.333v-384h245.333V426.667z'/%3e%3c/svg%3e\");\n}\n.graph-explorer-toolbar__toggle-right.active:after {\n  background-image: url(\"data:image/svg+xml,%3csvg%20version='1.1'%20xmlns='http://www.w3.org/2000/svg'%20width='12'%20height='12'%20viewBox='0%200%20469.333%20469.333'%3e%3cpath%20fill='%23333'%20d='m%20318.9149,233.50816%200,-205.208262%2059.6835,0%2059.68351,0%200,205.208262%200,205.20828%20-59.68351,0%20-59.6835,0%200,-205.20828%20z'/%3e%3cpath%20fill='%23333'%20d='M448,0H21.333C9.552,0,0,9.552,0,21.333V448c0,11.781,9.552,21.333,21.333,21.333H448c11.781,0,21.333-9.552,21.333-21.333V21.333C469.333,9.552,459.781,0,448,0z%20M288,426.667H42.667v-384H288V426.667zM426.667,426.667h-96v-384h96V426.667z'/%3e%3c/svg%3e\");\n}\n.graph-explorer-toolbar__layout-group {\n  display: inline-flex;\n  align-items: center;\n  margin-left: 5px;\n  height: 32px;\n}\n.graph-explorer-toolbar__layout-group > label {\n  margin-right: 5px;\n  margin-bottom: 0;\n}\n.graph-explorer-toolbar__layout-group .btn-group, .graph-explorer-toolbar__layout-group button {\n  height: 100%;\n}\n\n.graph-explorer-toolbar .graph-explorer-toolbar__undo,\n.graph-explorer-toolbar .graph-explorer-toolbar__redo {\n  display: none;\n}\n\n.graph-explorer {\n  display: flex;\n  flex-direction: column;\n  height: 100%;\n  box-sizing: border-box;\n  white-space: initial;\n  color: var(--ge-text);\n  background: var(--ge-bg);\n  font-family: var(--ge-font-sans);\n  font-size: 14px;\n  line-height: 1.5;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  text-rendering: optimizeLegibility;\n}\n.graph-explorer *, .graph-explorer *:before, .graph-explorer *:after {\n  box-sizing: inherit;\n}\n.graph-explorer__toolbar-widget {\n  position: absolute;\n  left: 10px;\n  top: 10px;\n}\n.graph-explorer__workspace {\n  display: flex;\n  flex: auto;\n  overflow: hidden;\n  flex-direction: column;\n}\n.graph-explorer__main-panel {\n  display: flex;\n  flex: auto;\n  overflow: hidden;\n  width: 0;\n}\n.graph-explorer--unselectable {\n  -webkit-touch-callout: none;\n  -webkit-user-select: none;\n  -moz-user-select: none;\n  -ms-user-select: none;\n  user-select: none;\n}\n.graph-explorer--horizontal-resizing * {\n  cursor: ew-resize !important;\n}\n.graph-explorer--vertical-resizing * {\n  cursor: ns-resize !important;\n}\n.graph-explorer h4 {\n  font-size: 18px;\n  font-weight: 600;\n  line-height: 1.2;\n  letter-spacing: -0.01em;\n  margin-top: 10px;\n  margin-bottom: 10px;\n}\n.graph-explorer select {\n  color: inherit;\n  margin: 0;\n  font: inherit;\n  line-height: inherit;\n  text-transform: none;\n}\n.graph-explorer hr {\n  border: 0;\n  border-top: 1px solid var(--ge-border);\n  height: 0;\n}\n.graph-explorer ::-webkit-scrollbar {\n  width: 10px;\n  height: 10px;\n}\n.graph-explorer ::-webkit-scrollbar-thumb {\n  background: var(--ge-border-strong);\n  border: 3px solid transparent;\n  background-clip: content-box;\n  border-radius: var(--ge-radius-pill);\n}\n.graph-explorer ::-webkit-scrollbar-thumb:hover {\n  background: var(--ge-text-subtle);\n  border: 3px solid transparent;\n  background-clip: content-box;\n}\n.graph-explorer ::-webkit-scrollbar-track {\n  background: transparent;\n}\n\n.graph-explorer-scrollable {\n  flex: 1 1 0px;\n  overflow-y: scroll;\n}\n\n.graph-explorer-scrollable > * {\n  position: relative;\n}\n\n.jstree-icon.jstree-themeicon.jstree-themeicon-custom {\n  background-size: contain !important;\n}\n\n.graph-explorer-default-template, .graph-explorer-group-template__wrap {\n  max-width: 450px;\n  float: left;\n  border-radius: var(--ge-radius-lg);\n  border-style: solid;\n  border-width: 1px;\n  overflow: hidden;\n  box-shadow: var(--ge-shadow-md);\n}\n.graph-explorer-default-template__thumbnail {\n  text-align: center;\n}\n.graph-explorer-default-template__thumbnail > img {\n  max-width: 200px;\n}\n.graph-explorer-default-template[data-expanded=true] .graph-explorer-default-template__thumbnail > img, [data-expanded=true].graph-explorer-group-template__wrap .graph-explorer-default-template__thumbnail > img {\n  max-width: 350px;\n}\n\n.graph-explorer-default-template_type-line, .graph-explorer-group-template__type-line {\n  padding: 0px 7px;\n  color: white;\n  height: 18px;\n  margin-bottom: 2px;\n  overflow: hidden;\n  display: flex;\n  align-items: baseline;\n  margin-top: -3px;\n}\n\ndiv.graph-explorer-default-template_type-line__icon, div.graph-explorer-group-template__type-line-icon {\n  position: inherit !important;\n  margin-right: 4px;\n}\n\n.graph-explorer-default-template_type-line_text-container, .graph-explorer-group-template__type-line-text-container {\n  flex-grow: 1;\n  overflow: hidden;\n  text-overflow: ellipsis;\n  width: 0;\n}\n\n.graph-explorer-default-template_type-line_text-container__text, .graph-explorer-group-template__type-line-text {\n  display: inline;\n  white-space: nowrap;\n  font-size: 12px;\n}\n\n.graph-explorer-default-template_body, .graph-explorer-group-template__body {\n  border-bottom-left-radius: 12px;\n  border-bottom-right-radius: 12px;\n  border-top-style: solid;\n  border-top-width: 1px;\n  background: white;\n  padding: 7px 10px 8px 10px;\n  overflow: hidden;\n  display: flex;\n  flex-direction: column;\n}\n\n.graph-explorer-default-template_body__label, .graph-explorer-group-template__label {\n  font-size: 18px;\n  font-weight: 600;\n  letter-spacing: -0.01em;\n  color: var(--ge-text);\n  overflow: hidden;\n  text-overflow: ellipsis;\n  margin-bottom: 0;\n  white-space: nowrap;\n  word-wrap: break-word;\n}\n\n.graph-explorer-default-template_body_expander {\n  width: 100%;\n  overflow: hidden;\n  display: flex;\n}\n\n.graph-explorer-default-template_body_expander__iri_label {\n  font-size: 12px;\n  font-weight: 100;\n  margin-right: 15px;\n  color: #b6b6b6;\n}\n\n.graph-explorer-default-template_body_expander_iri {\n  font-size: 12px;\n  width: 100%;\n  overflow: hidden;\n  white-space: nowrap;\n  text-overflow: ellipsis;\n}\n\n.graph-explorer-default-template_body_expander_iri__link {\n  color: #b6b6b6;\n}\n\n.graph-explorer-default-template_body_expander__hr {\n  margin: 5px 0px 5px 0px;\n}\n\n.graph-explorer-default-template_body_expander_property-table {\n  font-size: 15px;\n  font-weight: 100;\n  margin-bottom: 5px;\n  max-height: 200px;\n  overflow-y: scroll;\n  overflow-x: hidden;\n}\n\n.graph-explorer-default-template_body_expander_property-table_row {\n  white-space: nowrap;\n}\n\n.graph-explorer-default-template_body_expander_property-table_row__key {\n  display: inline-block;\n  width: 50%;\n  text-overflow: ellipsis;\n  overflow: hidden;\n  vertical-align: top;\n}\n\n.graph-explorer-default-template_body_expander_property-table_row_key {\n  display: inline-block;\n  width: 50%;\n  text-overflow: ellipsis;\n  overflow: hidden;\n  vertical-align: top;\n}\n\n.graph-explorer-default-template_body_expander_property-table_row_key_values {\n  display: inline-block;\n  width: 50%;\n  text-overflow: ellipsis;\n  overflow: hidden;\n}\n\n.graph-explorer-default-template_body_expander_property-table_row_key_values__value {\n  width: 100%;\n  overflow: hidden;\n  text-overflow: ellipsis;\n  white-space: initial;\n  padding-right: 10px;\n}\n\n.graph-explorer-group-template {\n  overflow: hidden;\n}\n.graph-explorer-group-template__wrap {\n  max-width: none;\n}\n.graph-explorer-group-template__body {\n  overflow: visible;\n}\n.graph-explorer-group-template__embedded-layer {\n  margin-top: 7px;\n}\n.graph-explorer-group-template .graph-explorer-paper__canvas {\n  border-color: #fff;\n}\n\n.graph-explorer-standard-template {\n  min-width: 180px;\n  max-width: 400px;\n  float: left;\n}\n.graph-explorer-standard-template__main {\n  border-radius: var(--ge-radius);\n  border: 1px solid;\n  overflow: hidden;\n  box-shadow: var(--ge-shadow-md);\n}\n.graph-explorer-standard-template__body {\n  margin-left: 8px;\n  border-radius: 0 var(--ge-radius) var(--ge-radius) 0;\n  border-left: 1px solid;\n  padding: 4px 0;\n  background: var(--ge-surface);\n}\n.graph-explorer-standard-template__body-horizontal {\n  display: flex;\n  align-items: center;\n  justify-content: space-between;\n  overflow: hidden;\n}\n.graph-explorer-standard-template__body-content {\n  flex-grow: 1;\n  min-width: 0;\n  margin-right: 12px;\n}\n.graph-explorer-standard-template__label {\n  font-size: 18px;\n  font-weight: 600;\n  letter-spacing: -0.01em;\n  white-space: nowrap;\n  overflow: hidden;\n  text-overflow: ellipsis;\n}\n.graph-explorer-standard-template__thumbnail {\n  font-size: 26px;\n  margin: 5px 10px;\n  flex-shrink: 0;\n  width: 50px;\n  height: 50px;\n  display: flex;\n  justify-content: center;\n  align-items: center;\n}\n.graph-explorer-standard-template__thumbnail-image {\n  max-height: 100%;\n  max-width: 100%;\n}\n.graph-explorer-standard-template__thumbnail-icon {\n  max-height: 26px;\n  max-width: 26px;\n}\n.graph-explorer-standard-template__photo {\n  border-bottom: 1px solid;\n}\n.graph-explorer-standard-template__photo-image {\n  width: 100%;\n  border-radius: 2px 2px 0 0;\n}\n.graph-explorer-standard-template__type {\n  white-space: nowrap;\n  overflow: hidden;\n  text-overflow: ellipsis;\n  font-size: 11px;\n  font-style: italic;\n  color: #999;\n  display: flex;\n}\n.graph-explorer-standard-template__type-value {\n  width: 0;\n  flex-grow: 1;\n  overflow: hidden;\n  text-overflow: ellipsis;\n}\n.graph-explorer-standard-template__iri {\n  width: 100%;\n  overflow: hidden;\n  display: flex;\n}\n.graph-explorer-standard-template__iri-key {\n  font-size: 12px;\n  margin-right: 4px;\n  color: #b6b6b6;\n}\n.graph-explorer-standard-template__iri-value {\n  font-size: 12px;\n  width: 100%;\n  overflow: hidden;\n  white-space: nowrap;\n  text-overflow: ellipsis;\n}\n.graph-explorer-standard-template__iri-value a {\n  color: #b6b6b6;\n}\n.graph-explorer-standard-template__hr {\n  margin: 5px 0;\n}\n.graph-explorer-standard-template__properties {\n  font-size: 15px;\n  max-height: 200px;\n  overflow-y: scroll;\n  overflow-x: hidden;\n}\n.graph-explorer-standard-template__propertites-row {\n  white-space: nowrap;\n}\n.graph-explorer-standard-template__properties-key {\n  display: inline-block;\n  width: 50%;\n  text-overflow: ellipsis;\n  overflow: hidden;\n  vertical-align: top;\n}\n.graph-explorer-standard-template__properties-values {\n  display: inline-block;\n  width: 50%;\n  text-overflow: ellipsis;\n  overflow: hidden;\n}\n.graph-explorer-standard-template__properties-value {\n  width: 100%;\n  overflow: hidden;\n  text-overflow: ellipsis;\n  white-space: initial;\n  padding-right: 10px;\n}\n.graph-explorer-standard-template__pinned-props {\n  border-top: 1px solid;\n  margin: 0 5px;\n}\n.graph-explorer-standard-template__dropdown {\n  border-radius: var(--ge-radius);\n  background-color: var(--ge-surface);\n  margin-top: 6px;\n  border: 1px solid;\n  box-shadow: var(--ge-shadow-md);\n}\n.graph-explorer-standard-template__dropdown-content {\n  width: 100%;\n  padding: 9px;\n}\n.graph-explorer-standard-template__actions {\n  display: flex;\n  justify-content: space-between;\n}\n.graph-explorer-standard-template__actions button {\n  padding: 5px;\n  min-width: 60px;\n}/*$vite$:1*/"));			document.head.appendChild(elementStyle);		}	} catch (e) {		console.error("vite-plugin-css-injected-by-js", e);	}})();
(function(global, factory) {
	typeof exports === "object" && typeof module !== "undefined" ? factory(exports, require("react"), require("d3-color"), require("lodash"), require("n3"), require("webcola"), require("react-dom/client"), require("file-saverjs")) : typeof define === "function" && define.amd ? define([
		"exports",
		"react",
		"d3-color",
		"lodash",
		"n3",
		"webcola",
		"react-dom/client",
		"file-saverjs"
	], factory) : (global = typeof globalThis !== "undefined" ? globalThis : global || self, factory(global.GraphExplorer = {}, global.React, global.d3, global._, global.N3, global.cola, global.ReactDOM, global.saveAs));
})(this, function(exports, react, d3_color, lodash, n3, webcola, react_dom_client, file_saverjs) {
	Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
	//#region \0rolldown/runtime.js
	var __create = Object.create;
	var __defProp = Object.defineProperty;
	var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
	var __getOwnPropNames = Object.getOwnPropertyNames;
	var __getProtoOf = Object.getPrototypeOf;
	var __hasOwnProp = Object.prototype.hasOwnProperty;
	var __exportAll = (all, no_symbols) => {
		let target = {};
		for (var name in all) __defProp(target, name, {
			get: all[name],
			enumerable: true
		});
		if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
		return target;
	};
	var __copyProps = (to, from, except, desc) => {
		if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
			key = keys[i];
			if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
				get: ((k) => from[k]).bind(null, key),
				enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
			});
		}
		return to;
	};
	var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
		value: mod,
		enumerable: true
	}) : target, mod));
	//#endregion
	react = __toESM(react);
	n3 = __toESM(n3);
	webcola = __toESM(webcola);
	file_saverjs = __toESM(file_saverjs);
	//#region src/graph-explorer/data/utils.ts
	/** Generates random 32-digit hexadecimal string. */
	function generate128BitID() {
		function random32BitDigits() {
			return Math.floor((1 + Math.random()) * 4294967296).toString(16).substring(1);
		}
		return random32BitDigits() + random32BitDigits() + random32BitDigits() + random32BitDigits();
	}
	/**
	* Calculate a 32 bit FNV-1a hash
	* Found here: https://gist.github.com/vaiorabbit/5657561
	* Ref.: http://isthe.com/chongo/tech/comp/fnv/
	*
	* @param {string} str the input value
	* @param {integer} [seed] optionally pass the hash of the previous chunk
	* @returns {integer}
	*/
	function hashFnv32a(str, seed = 2166136261) {
		let i, l, hval = seed & 2147483647;
		for (i = 0, l = str.length; i < l; i++) {
			hval ^= str.charCodeAt(i);
			hval += (hval << 1) + (hval << 4) + (hval << 7) + (hval << 8) + (hval << 24);
		}
		return hval >>> 0;
	}
	/**
	* Extracts local name for URI the same way as it's done in RDF4J.
	*/
	function getUriLocalName(uri) {
		let index = uri.indexOf("#");
		if (index < 0) index = uri.lastIndexOf("/");
		if (index < 0) index = uri.lastIndexOf(":");
		if (index < 0) return;
		return uri.substring(index + 1);
	}
	//#endregion
	//#region src/graph-explorer/data/model.ts
	function isIriProperty(e) {
		return e && e.type === "uri";
	}
	function isLiteralProperty(e) {
		return e && e.type === "string";
	}
	function sameLink(left, right) {
		return left.linkTypeId === right.linkTypeId && left.sourceId === right.sourceId && left.targetId === right.targetId;
	}
	function hashLink(link) {
		const { linkTypeId, sourceId, targetId } = link;
		let hash = hashFnv32a(linkTypeId);
		hash = hash * 31 + hashFnv32a(sourceId);
		hash = hash * 31 + hashFnv32a(targetId);
		return hash;
	}
	function sameElement(left, right) {
		return left.id === right.id && isArraysEqual(left.types, right.types) && isLiteralsEqual(left.label.values, right.label.values) && left.image === right.image && isPropertiesEqual(left.properties, right.properties) && (!left.sources && !right.sources || left.sources && right.sources && isArraysEqual(left.sources, right.sources));
	}
	function isArraysEqual(left, right) {
		if (left.length !== right.length) return false;
		for (let i = 0; i < left.length; i++) if (left[i] !== right[i]) return false;
		return true;
	}
	function isLiteralsEqual(left, right) {
		if (left.length !== right.length) return false;
		for (let i = 0; i < left.length; i++) {
			const leftValue = left[i];
			const rightValue = right[i];
			if (leftValue.value !== rightValue.value || leftValue.language !== rightValue.language) return false;
		}
		return true;
	}
	function isIriPropertiesEqual(left, right) {
		if (!isIriProperty(left) || !isIriProperty(right)) return false;
		if (left.values.length !== right.values.length) return false;
		for (let i = 0; i < left.values.length; i++) {
			const leftValue = left.values[i];
			const rightValue = right.values[i];
			if (leftValue.value !== rightValue.value) return false;
		}
		return true;
	}
	function isLiteralPropertiesEqual(left, right) {
		if (!isLiteralProperty(left) || !isLiteralProperty(right)) return false;
		return isLiteralsEqual(left.values, right.values);
	}
	function isPropertiesEqual(left, right) {
		if (Object.keys(left).length !== Object.keys(right).length) return false;
		for (const key in left.properties) if (key in left.properties) {
			const leftProperty = left[key];
			const rightProperty = right[key];
			if (!rightProperty) return false;
			if (!isIriPropertiesEqual(leftProperty, rightProperty) && !isLiteralPropertiesEqual(leftProperty, rightProperty)) return false;
		}
		return true;
	}
	//#endregion
	//#region src/graph-explorer/customization/templates/utils.ts
	function getProperty(props, id) {
		if (props && props[id]) return getPropertyValues(props[id]).join(", ");
		else return;
	}
	function getPropertyValues(property) {
		if (isIriProperty(property)) return property.values.map(({ value }) => value);
		else if (isLiteralProperty(property)) return property.values.map(({ value }) => value);
		return [];
	}
	//#endregion
	//#region src/graph-explorer/customization/templates/default.tsx
	var CLASS_NAME$25 = "graph-explorer-default-template";
	var DefaultElementTemplate = class extends react.Component {
		render() {
			const props = this.props;
			const image = props.imgUrl ? /* @__PURE__ */ react.createElement("div", { className: `${CLASS_NAME$25}__thumbnail` }, /* @__PURE__ */ react.createElement("img", { src: props.imgUrl })) : void 0;
			const expander = props.isExpanded ? /* @__PURE__ */ react.createElement("div", null, /* @__PURE__ */ react.createElement("div", { className: "graph-explorer-default-template_body_expander" }, /* @__PURE__ */ react.createElement("div", { className: "graph-explorer-default-template_body_expander__iri_label" }, "IRI:"), /* @__PURE__ */ react.createElement("div", { className: "graph-explorer-default-template_body_expander_iri" }, /* @__PURE__ */ react.createElement("a", {
				className: "graph-explorer-default-template_body_expander_iri__link",
				href: props.iri,
				title: props.iri
			}, props.iri))), /* @__PURE__ */ react.createElement("hr", { className: "graph-explorer-default-template_body_expander__hr" }), this.renderPropertyTable()) : null;
			return /* @__PURE__ */ react.createElement("div", {
				className: "graph-explorer-default-template",
				style: {
					backgroundColor: props.color,
					borderColor: props.color
				},
				"data-expanded": this.props.isExpanded
			}, /* @__PURE__ */ react.createElement("div", {
				className: "graph-explorer-default-template_type-line",
				title: props.label
			}, /* @__PURE__ */ react.createElement("div", {
				className: "graph-explorer-default-template_type-line__icon",
				"aria-hidden": "true"
			}, /* @__PURE__ */ react.createElement("img", { src: props.iconUrl })), /* @__PURE__ */ react.createElement("div", {
				title: props.types,
				className: "graph-explorer-default-template_type-line_text-container"
			}, /* @__PURE__ */ react.createElement("div", { className: "graph-explorer-default-template_type-line_text-container__text" }, props.types))), image, /* @__PURE__ */ react.createElement("div", {
				className: "graph-explorer-default-template_body",
				style: { borderColor: props.color }
			}, /* @__PURE__ */ react.createElement("span", {
				className: "graph-explorer-default-template_body__label",
				title: props.label
			}, props.label), expander));
		}
		renderPropertyTable() {
			const { propsAsList } = this.props;
			if (propsAsList && propsAsList.length > 0) return /* @__PURE__ */ react.createElement("div", { className: "graph-explorer-default-template_body_expander_property-table" }, propsAsList.map((prop) => {
				const values = getPropertyValues(prop.property).map((text, index) => /* @__PURE__ */ react.createElement("div", {
					className: "graph-explorer-default-template_body_expander_property-table_row_key_values__value",
					key: index,
					title: text
				}, text));
				return /* @__PURE__ */ react.createElement("div", {
					key: prop.id,
					className: "graph-explorer-default-template_body_expander_property-table_row"
				}, /* @__PURE__ */ react.createElement("div", {
					title: prop.name + " (" + prop.id + ")",
					className: "graph-explorer-default-template_body_expander_property-table_row__key"
				}, prop.name), /* @__PURE__ */ react.createElement("div", { className: "graph-explorer-default-template_body_expander_property-table_row_key_values" }, values));
			}));
			else return /* @__PURE__ */ react.createElement("div", null, "no properties");
		}
	};
	//#endregion
	//#region src/graph-explorer/data/schema.ts
	var DIAGRAM_CONTEXT_URL_V1 = "https://graph-explorer.org/context/v1.json";
	var PLACEHOLDER_ELEMENT_TYPE = "http://graph-explorer.org/NewEntity";
	var PLACEHOLDER_LINK_TYPE = "http://graph-explorer.org/NewLink";
	var GRAPH_EXPLORER_ID_URL_PREFIX = "http://graph-explorer.org/data/";
	var GenerateID = {
		forElement() {
			return `${GRAPH_EXPLORER_ID_URL_PREFIX}e_${generate128BitID()}`;
		},
		forLink() {
			return `${GRAPH_EXPLORER_ID_URL_PREFIX}l_${generate128BitID()}`;
		}
	};
	var TemplateProperties = {
		PinnedProperties: "graph-explorer:pinnedProperties",
		CustomLabel: "graph-explorer:customLabel"
	};
	//#endregion
	//#region src/graph-explorer/viewUtils/events.ts
	var EventSource = class {
		constructor() {
			this.listeners = /* @__PURE__ */ new Map();
		}
		on(eventKey, listener) {
			let listeners = this.listeners.get(eventKey);
			if (!listeners) {
				listeners = [];
				this.listeners.set(eventKey, listeners);
			}
			listeners.push(listener);
		}
		onAny(listener) {
			let listeners = this.anyListeners;
			if (!listeners) {
				listeners = [];
				this.anyListeners = listeners;
			}
			listeners.push(listener);
		}
		off(eventKey, listener) {
			const listeners = this.listeners.get(eventKey);
			if (!listeners) return;
			const index = listeners.indexOf(listener);
			if (index >= 0) listeners.splice(index, 1);
		}
		offAny(listener) {
			const listeners = this.anyListeners;
			if (!listeners) return;
			const index = listeners.indexOf(listener);
			if (index >= 0) listeners.splice(index, 1);
		}
		trigger(eventKey, data) {
			const listeners = this.listeners.get(eventKey);
			if (listeners) for (const listener of listeners) listener(data, eventKey);
			if (this.anyListeners) for (const anyListener of this.anyListeners) anyListener({ [eventKey]: data }, eventKey);
		}
	};
	var EventObserver = class {
		constructor() {
			this.unsubscribeByKey = /* @__PURE__ */ new Map();
			this.onDispose = [];
		}
		listen(events, eventKey, listener) {
			events.on(eventKey, listener);
			this.onDispose.push(() => events.off(eventKey, listener));
		}
		listenAny(events, listener) {
			events.onAny(listener);
			this.onDispose.push(() => events.offAny(listener));
		}
		listenOnce(events, eventKey, listener) {
			let handled = false;
			const onceListener = (data, key) => {
				handled = true;
				events.off(eventKey, onceListener);
				listener(data, key);
			};
			events.on(eventKey, onceListener);
			this.onDispose.push(() => {
				if (handled) return;
				events.off(eventKey, onceListener);
			});
		}
		stopListening() {
			for (const unsubscribe of this.onDispose) unsubscribe();
			this.onDispose.length = 0;
			this.unsubscribeByKey.forEach((unsubscribers) => {
				for (const unsubscribe of unsubscribers) unsubscribe();
			});
			this.unsubscribeByKey.clear();
		}
	};
	//#endregion
	//#region src/graph-explorer/diagram/geometry.ts
	var Vector = {
		equals(a, b) {
			return a.x === b.x && a.y === b.y;
		},
		length({ x, y }) {
			return Math.sqrt(x * x + y * y);
		},
		normalize({ x, y }) {
			if (x === 0 && y === 0) return {
				x,
				y
			};
			const inverseLength = 1 / Math.sqrt(x * x + y * y);
			return {
				x: x * inverseLength,
				y: y * inverseLength
			};
		},
		dot({ x: x1, y: y1 }, { x: x2, y: y2 }) {
			return x1 * x2 + y1 * y2;
		},
		cross2D({ x: x1, y: y1 }, { x: x2, y: y2 }) {
			return x1 * y2 - y1 * x2;
		}
	};
	var Rect = { center({ x, y, width, height }) {
		return {
			x: x + width / 2,
			y: y + height / 2
		};
	} };
	function boundsOf(element) {
		const { x, y } = element.position;
		const { width, height } = element.size;
		return {
			x,
			y,
			width,
			height
		};
	}
	function intersectRayFromRectangleCenter(sourceRect, rayTarget) {
		const isTargetInsideRect = sourceRect.width === 0 || sourceRect.height === 0 || rayTarget.x > sourceRect.x && rayTarget.x < sourceRect.x + sourceRect.width && rayTarget.y > sourceRect.y && rayTarget.y < sourceRect.y + sourceRect.height;
		const halfWidth = sourceRect.width / 2;
		const halfHeight = sourceRect.height / 2;
		const center = {
			x: sourceRect.x + halfWidth,
			y: sourceRect.y + halfHeight
		};
		if (isTargetInsideRect) return center;
		const direction = Vector.normalize({
			x: rayTarget.x - center.x,
			y: rayTarget.y - center.y
		});
		const rightDirection = {
			x: Math.abs(direction.x),
			y: direction.y
		};
		if (Vector.cross2D({
			x: halfWidth,
			y: -halfHeight
		}, rightDirection) > 0 && Vector.cross2D({
			x: halfWidth,
			y: halfHeight
		}, rightDirection) < 0) return {
			x: center.x + halfWidth * Math.sign(direction.x),
			y: center.y + halfWidth * direction.y / Math.abs(direction.x)
		};
		else return {
			x: center.x + halfHeight * direction.x / Math.abs(direction.y),
			y: center.y + halfHeight * Math.sign(direction.y)
		};
	}
	function isPolylineEqual(left, right) {
		if (left === right) return true;
		if (left.length !== right.length) return false;
		for (let i = 0; i < left.length; i++) {
			const a = left[i];
			const b = right[i];
			if (!(a.x === b.x && a.y === b.y)) return false;
		}
		return true;
	}
	function computePolyline(source, target, vertices) {
		const sourceRect = boundsOf(source);
		const targetRect = boundsOf(target);
		const startPoint = intersectRayFromRectangleCenter(sourceRect, vertices.length > 0 ? vertices[0] : Rect.center(targetRect));
		const endPoint = intersectRayFromRectangleCenter(targetRect, vertices.length > 0 ? vertices[vertices.length - 1] : Rect.center(sourceRect));
		return [
			startPoint,
			...vertices,
			endPoint
		];
	}
	function computePolylineLength(polyline) {
		let previous;
		return polyline.reduce((acc, point) => {
			const segmentLength = previous ? Vector.length({
				x: point.x - previous.x,
				y: point.y - previous.y
			}) : 0;
			previous = point;
			return acc + segmentLength;
		}, 0);
	}
	function getPointAlongPolyline(polyline, offset) {
		if (polyline.length === 0) throw new Error("Cannot compute a point for empty polyline");
		if (offset < 0) return polyline[0];
		let currentOffset = 0;
		for (let i = 1; i < polyline.length; i++) {
			const previous = polyline[i - 1];
			const point = polyline[i];
			const segment = {
				x: point.x - previous.x,
				y: point.y - previous.y
			};
			const segmentLength = Vector.length(segment);
			const newOffset = currentOffset + segmentLength;
			if (offset < newOffset) {
				const leftover = (offset - currentOffset) / segmentLength;
				return {
					x: previous.x + leftover * segment.x,
					y: previous.y + leftover * segment.y
				};
			} else currentOffset = newOffset;
		}
		return polyline[polyline.length - 1];
	}
	function findNearestSegmentIndex(polyline, location) {
		let minDistance = Infinity;
		let foundIndex = 0;
		for (let i = 0; i < polyline.length - 1; i++) {
			const pivot = polyline[i];
			const next = polyline[i + 1];
			const target = {
				x: location.x - pivot.x,
				y: location.y - pivot.y
			};
			const segment = {
				x: next.x - pivot.x,
				y: next.y - pivot.y
			};
			const segmentLength = Vector.length(segment);
			const projectionToSegment = Vector.dot(target, segment) / segmentLength;
			if (projectionToSegment < 0 || projectionToSegment > segmentLength) continue;
			const distanceToSegment = Math.abs(Vector.cross2D(target, segment)) / segmentLength;
			if (distanceToSegment < minDistance) {
				minDistance = distanceToSegment;
				foundIndex = i;
			}
		}
		return foundIndex;
	}
	function findElementAtPoint(elements, point) {
		for (let i = elements.length - 1; i >= 0; i--) {
			const element = elements[i];
			const { x, y, width, height } = boundsOf(element);
			if (element.temporary) continue;
			if (point.x >= x && point.x <= x + width && point.y >= y && point.y <= y + height) return element;
		}
	}
	function computeGrouping(elements) {
		const grouping = /* @__PURE__ */ new Map();
		for (const element of elements) {
			const group = element.group;
			if (typeof group === "string") {
				let children = grouping.get(group);
				if (!children) {
					children = [];
					grouping.set(group, children);
				}
				children.push(element);
			}
		}
		return grouping;
	}
	//#endregion
	//#region src/graph-explorer/diagram/elements.ts
	var LinkDirection = /* @__PURE__ */ function(LinkDirection) {
		LinkDirection["in"] = "in";
		LinkDirection["out"] = "out";
		return LinkDirection;
	}({});
	var Element$1 = class {
		constructor(props) {
			this.source = new EventSource();
			this.events = this.source;
			this.links = [];
			const { id, data, position = {
				x: 0,
				y: 0
			}, size = {
				width: 0,
				height: 0
			}, expanded = false, group, elementState, temporary = false } = props;
			this.id = id;
			this._data = data;
			this._position = position;
			this._size = size;
			this._expanded = expanded;
			this._group = group;
			this._elementState = elementState;
			this._temporary = temporary;
		}
		get iri() {
			return this._data.id;
		}
		get data() {
			return this._data;
		}
		setData(value) {
			const previous = this._data;
			if (previous === value) return;
			this._data = value;
			this.source.trigger("changeData", {
				source: this,
				previous
			});
			updateLinksToReferByNewIri(this, previous.id, value.id);
		}
		get position() {
			return this._position;
		}
		setPosition(value) {
			const previous = this._position;
			if (previous.x === value.x && previous.y === value.y) return;
			this._position = value;
			this.source.trigger("changePosition", {
				source: this,
				previous
			});
		}
		get size() {
			return this._size;
		}
		setSize(value) {
			const previous = this._size;
			if (previous.width === value.width && previous.height === value.height) return;
			this._size = value;
			this.source.trigger("changeSize", {
				source: this,
				previous
			});
		}
		get isExpanded() {
			return this._expanded;
		}
		setExpanded(value) {
			const previous = this._expanded;
			if (previous === value) return;
			this._expanded = value;
			this.source.trigger("changeExpanded", {
				source: this,
				previous
			});
		}
		get group() {
			return this._group;
		}
		setGroup(value) {
			const previous = this._group;
			if (previous === value) return;
			this._group = value;
			this.source.trigger("changeGroup", {
				source: this,
				previous
			});
		}
		get elementState() {
			return this._elementState;
		}
		setElementState(value) {
			const previous = this._elementState;
			if (previous === value) return;
			this._elementState = value;
			this.source.trigger("changeElementState", {
				source: this,
				previous
			});
		}
		get temporary() {
			return this._temporary;
		}
		focus() {
			this.source.trigger("requestedFocus", { source: this });
		}
		requestGroupContent() {
			this.source.trigger("requestedGroupContent", { source: this });
		}
		addToFilter(linkType, direction) {
			this.source.trigger("requestedAddToFilter", {
				source: this,
				linkType,
				direction
			});
		}
		redraw() {
			this.source.trigger("requestedRedraw", { source: this });
		}
	};
	function updateLinksToReferByNewIri(element, oldIri, newIri) {
		if (oldIri === newIri) return;
		for (const link of element.links) {
			let data = link.data;
			if (data.sourceId === oldIri) data = {
				...data,
				sourceId: newIri
			};
			if (data.targetId === oldIri) data = {
				...data,
				targetId: newIri
			};
			link.setData(data);
		}
	}
	var FatClassModel = class {
		constructor(props) {
			this.source = new EventSource();
			this.events = this.source;
			const { id, label = [], count } = props;
			this.id = id;
			this._label = label;
			this._count = count;
		}
		get label() {
			return this._label;
		}
		setLabel(value) {
			const previous = this._label;
			if (previous === value) return;
			this._label = value;
			this.source.trigger("changeLabel", {
				source: this,
				previous
			});
		}
		get count() {
			return this._count;
		}
		setCount(value) {
			const previous = this._count;
			if (previous === value) return;
			this._count = value;
			this.source.trigger("changeCount", {
				source: this,
				previous
			});
		}
	};
	var RichProperty = class {
		constructor(props) {
			this.source = new EventSource();
			this.events = this.source;
			const { id, label = [] } = props;
			this.id = id;
			this._label = label;
		}
		get label() {
			return this._label;
		}
		setLabel(value) {
			const previous = this._label;
			if (previous === value) return;
			this._label = value;
			this.source.trigger("changeLabel", {
				source: this,
				previous
			});
		}
	};
	var Link = class {
		constructor(props) {
			this.source = new EventSource();
			this.events = this.source;
			const { id = GenerateID.forLink(), typeId, sourceId, targetId, data, vertices = [], linkState } = props;
			this.id = id;
			this._typeId = typeId;
			this._sourceId = sourceId;
			this._targetId = targetId;
			this._data = data;
			this._vertices = vertices;
			this._linkState = linkState;
		}
		get typeId() {
			return this._typeId;
		}
		get sourceId() {
			return this._sourceId;
		}
		get targetId() {
			return this._targetId;
		}
		get data() {
			return this._data;
		}
		setData(value) {
			const previous = this._data;
			if (previous === value) return;
			this._data = value;
			this._typeId = value.linkTypeId;
			this.source.trigger("changeData", {
				source: this,
				previous
			});
		}
		get labelBounds() {
			return this._labelBounds;
		}
		setLabelBounds(value) {
			const previous = this._labelBounds;
			if (previous === value) return;
			this._labelBounds = value;
			this.source.trigger("changeLabelBounds", {
				source: this,
				previous
			});
		}
		get layoutOnly() {
			return this._layoutOnly;
		}
		setLayoutOnly(value) {
			const previous = this._layoutOnly;
			if (previous === value) return;
			this._layoutOnly = value;
			this.source.trigger("changeLayoutOnly", {
				source: this,
				previous
			});
		}
		get vertices() {
			return this._vertices;
		}
		setVertices(value) {
			const previous = this._vertices;
			if (isPolylineEqual(this._vertices, value)) return;
			this._vertices = value;
			this.source.trigger("changeVertices", {
				source: this,
				previous
			});
		}
		get linkState() {
			return this._linkState;
		}
		setLinkState(value) {
			const previous = this._linkState;
			if (previous === value) return;
			this._linkState = value;
			this.source.trigger("changeLinkState", {
				source: this,
				previous
			});
		}
	};
	function linkMarkerKey(linkTypeIndex, startMarker) {
		return `graph-explorer-${startMarker ? "mstart" : "mend"}-${linkTypeIndex}`;
	}
	/**
	* Properties:
	*     visible: boolean
	*     showLabel: boolean
	*     isNew?: boolean
	*     label?: { values: LocalizedString[] }
	*/
	var FatLinkType = class {
		constructor(props) {
			this.source = new EventSource();
			this.events = this.source;
			this._isNew = false;
			this._visible = true;
			this._showLabel = true;
			const { id, index, label = [] } = props;
			this.id = id;
			this._index = index;
			this._label = label;
		}
		get index() {
			return this._index;
		}
		setIndex(value) {
			if (typeof this._index === "number") throw new Error("Cannot set index for link type more than once.");
			this._index = value;
		}
		get label() {
			return this._label;
		}
		setLabel(value) {
			const previous = this._label;
			if (previous === value) return;
			this._label = value;
			this.source.trigger("changeLabel", {
				source: this,
				previous
			});
		}
		get visible() {
			return this._visible;
		}
		get showLabel() {
			return this._showLabel;
		}
		setVisibility(params) {
			if (this._visible === params.visible && this._showLabel === params.showLabel) return;
			const preventLoading = Boolean(params.preventLoading) || this._visible === params.visible;
			this._visible = params.visible;
			this._showLabel = params.showLabel;
			this.source.trigger("changeVisibility", {
				source: this,
				preventLoading
			});
		}
		get isNew() {
			return this._isNew;
		}
		setIsNew(value) {
			const previous = this._isNew;
			if (previous === value) return;
			this._isNew = value;
			this.source.trigger("changeIsNew", {
				source: this,
				previous
			});
		}
	};
	var LinkVertex = class {
		constructor(link, vertexIndex) {
			this.link = link;
			this.vertexIndex = vertexIndex;
		}
		createAt(location) {
			const vertices = [...this.link.vertices];
			vertices.splice(this.vertexIndex, 0, location);
			this.link.setVertices(vertices);
		}
		moveTo(location) {
			const vertices = [...this.link.vertices];
			vertices.splice(this.vertexIndex, 1, location);
			this.link.setVertices(vertices);
		}
		remove() {
			const vertices = [...this.link.vertices];
			vertices.splice(this.vertexIndex, 1);
			this.link.setVertices(vertices);
		}
	};
	//#endregion
	//#region src/graph-explorer/viewUtils/async.ts
	var BatchingScheduler = class {
		constructor(waitingTime = 0) {
			this.waitingTime = waitingTime;
			this.useAnimationFrame = waitingTime === 0;
			this.runSynchronously = this.runSynchronously.bind(this);
		}
		schedule() {
			if (typeof this.scheduled === "undefined") if (this.useAnimationFrame) this.scheduled = requestAnimationFrame(this.runSynchronously);
			else this.scheduled = Number(setTimeout(this.runSynchronously, this.waitingTime));
		}
		runSynchronously() {
			if (this.cancelScheduledTimeout()) this.run();
		}
		dispose() {
			this.cancelScheduledTimeout();
		}
		cancelScheduledTimeout() {
			if (typeof this.scheduled !== "undefined") {
				if (this.useAnimationFrame) cancelAnimationFrame(this.scheduled);
				else clearTimeout(this.scheduled);
				this.scheduled = void 0;
				return true;
			}
			return false;
		}
	};
	var BufferingQueue = class extends BatchingScheduler {
		constructor(onFetch, waitingTime = 200) {
			super(waitingTime);
			this.onFetch = onFetch;
			this.fetchingQueue = Object.create(null);
		}
		push(key) {
			this.fetchingQueue[key] = true;
			this.schedule();
		}
		clear() {
			this.fetchingQueue = Object.create(null);
		}
		run() {
			const { fetchingQueue, onFetch } = this;
			this.fetchingQueue = Object.create(null);
			onFetch(Object.keys(fetchingQueue));
		}
	};
	var Debouncer = class extends BatchingScheduler {
		call(callback) {
			this.callback = callback;
			this.schedule();
		}
		run() {
			const callback = this.callback;
			callback();
		}
	};
	var Cancellation = class {
		static {
			this.NEVER_SIGNAL = {
				aborted: false,
				addEventListener: () => {},
				removeEventListener: () => {}
			};
		}
		constructor() {
			this.source = new EventSource();
			this.aborted = false;
			this.signal = new class {
				constructor(parent) {
					this.parent = parent;
				}
				get aborted() {
					return this.parent.aborted;
				}
				addEventListener(event, handler) {
					if (event !== "abort") return;
					if (this.parent.source) this.parent.source.on("abort", handler);
					else handler();
				}
				removeEventListener(event, handler) {
					if (event !== "abort") return;
					if (this.parent.source) this.parent.source.off("abort", handler);
				}
			}(this);
		}
		abort() {
			if (this.aborted) return;
			this.aborted = true;
			this.source.trigger("abort", void 0);
			this.source = void 0;
		}
	};
	var CancellationToken = {
		throwIfAborted(ct) {
			if (ct.aborted) throw new CancelledError();
		},
		mapCancelledToNull(ct, promise) {
			const onResolve = (value) => {
				if (ct.aborted) return null;
				return value;
			};
			const onReject = (err) => {
				if (ct.aborted) return null;
				return Promise.reject(err);
			};
			return promise.then(onResolve, onReject);
		}
	};
	var CancelledError = class CancelledError extends Error {
		constructor(message = "Operation was cancelled") {
			super(message);
			this.name = CancelledError.name;
			Object.setPrototypeOf(this, CancelledError.prototype);
		}
	};
	function delay(timeout) {
		return new Promise((resolve) => setTimeout(resolve, timeout));
	}
	function animateInterval(duration, onProgress, cancellation) {
		return new Promise((resolve) => {
			let animationFrameId;
			let start;
			const animate = (time) => {
				if (cancellation && cancellation.signal.aborted) return;
				start = start || time;
				let timePassed = time - start;
				if (timePassed > duration) timePassed = duration;
				onProgress(timePassed / duration);
				if (timePassed < duration) animationFrameId = requestAnimationFrame(animate);
				else resolve();
			};
			cancellation.signal.addEventListener("abort", () => {
				cancelAnimationFrame(animationFrameId);
				resolve();
			});
			animationFrameId = requestAnimationFrame(animate);
		});
	}
	function easeInOutBezier(t) {
		if (t < 0) return 0;
		if (t > 1) return 1;
		return t * t * (3 - 2 * t);
	}
	//#endregion
	//#region src/graph-explorer/viewUtils/keyedObserver.ts
	var KeyedObserver = class {
		constructor(subscribe) {
			this.subscribe = subscribe;
			this.observedKeys = /* @__PURE__ */ new Map();
		}
		observe(keys) {
			if (keys.length === 0 && this.observedKeys.size === 0) return;
			const newObservedKeys = /* @__PURE__ */ new Map();
			for (const key of keys) {
				if (newObservedKeys.has(key)) continue;
				let unsubscribe = this.observedKeys.get(key);
				if (!unsubscribe) unsubscribe = this.subscribe(key);
				newObservedKeys.set(key, unsubscribe);
			}
			this.observedKeys.forEach((unsubscribe, key) => {
				if (!newObservedKeys.has(key)) unsubscribe();
			});
			this.observedKeys = newObservedKeys;
		}
		stopListening() {
			this.observe([]);
		}
	};
	function observeElementTypes(model, event, listener) {
		return new KeyedObserver((key) => {
			const type = model.getClass(key);
			if (type) {
				type.events.on(event, listener);
				return () => type.events.off(event, listener);
			}
		});
	}
	function observeProperties(model, event, listener) {
		return new KeyedObserver((key) => {
			const property = model.getProperty(key);
			if (property) {
				property.events.on(event, listener);
				return () => property.events.off(event, listener);
			}
		});
	}
	function observeLinkTypes(model, event, listener) {
		return new KeyedObserver((key) => {
			const type = model.createLinkType(key);
			if (type) {
				type.events.on(event, listener);
				return () => type.events.off(event, listener);
			}
		});
	}
	//#endregion
	//#region src/graph-explorer/diagram/history.ts
	function createAction(title, action) {
		return {
			title,
			invoke: action
		};
	}
	function effectAction(title, body) {
		const perform = {
			title,
			invoke: () => {
				body();
				return skip;
			}
		};
		const skip = {
			title: "Skipped effect: " + title,
			invoke: () => perform
		};
		return perform;
	}
	var Command = {
		create: createAction,
		effect: effectAction
	};
	var NonRememberingHistory = class {
		constructor() {
			this.source = new EventSource();
			this.events = this.source;
			this.undoStack = [];
			this.redoStack = [];
			this.storeBatch = () => {};
			this.discardBatch = () => {};
		}
		reset() {
			this.source.trigger("historyChanged", { hasChanges: false });
		}
		undo() {
			throw new Error("Undo is unsupported");
		}
		redo() {
			throw new Error("Redo is unsupported");
		}
		execute(command) {
			command.invoke();
			this.source.trigger("historyChanged", { hasChanges: true });
		}
		registerToUndo(_command) {
			this.source.trigger("historyChanged", { hasChanges: true });
		}
		startBatch(_title) {
			return {
				history: this,
				store: this.storeBatch,
				discard: this.discardBatch
			};
		}
	};
	//#endregion
	//#region src/graph-explorer/diagram/commands.ts
	var RestoreGeometry = class RestoreGeometry {
		constructor(elementState, linkState) {
			this.elementState = elementState;
			this.linkState = linkState;
			this.title = "Move elements and links";
		}
		static capture(model) {
			return RestoreGeometry.captureElementsAndLinks(model.elements, model.links);
		}
		static captureElementsAndLinks(elements, links) {
			return new RestoreGeometry(elements.map((element) => ({
				element,
				position: element.position
			})), links.map((link) => ({
				link,
				vertices: link.vertices
			})));
		}
		hasChanges() {
			return this.elementState.length > 0 || this.linkState.length > 0;
		}
		filterOutUnchanged() {
			return new RestoreGeometry(this.elementState.filter(({ element, position }) => !Vector.equals(element.position, position)), this.linkState.filter(({ link, vertices }) => !isPolylineEqual(link.vertices, vertices)));
		}
		invoke() {
			const previous = RestoreGeometry.captureElementsAndLinks(this.elementState.map((state) => state.element), this.linkState.map((state) => state.link));
			for (const { element, position } of [...this.elementState].reverse()) element.setPosition(position);
			for (const { link, vertices } of this.linkState) link.setVertices(vertices);
			return previous;
		}
	};
	function restoreCapturedLinkGeometry(link) {
		const vertices = link.vertices;
		return Command.create("Change link vertices", () => {
			const capturedInverse = restoreCapturedLinkGeometry(link);
			link.setVertices(vertices);
			return capturedInverse;
		});
	}
	function setElementExpanded(element, expanded) {
		const title = expanded ? "Expand element" : "Collapse element";
		return Command.create(title, () => {
			element.setExpanded(expanded);
			return setElementExpanded(element, !expanded);
		});
	}
	function changeLinkTypeVisibility(params) {
		const { linkType, visible, showLabel, preventLoading } = params;
		return Command.create("Change link type visibility", () => {
			const previousVisible = linkType.visible;
			const previousShowLabel = linkType.showLabel;
			linkType.setVisibility({
				visible,
				showLabel,
				preventLoading
			});
			return changeLinkTypeVisibility({
				linkType,
				visible: previousVisible,
				showLabel: previousShowLabel,
				preventLoading
			});
		});
	}
	function setElementData(model, target, data) {
		const elements = model.elements.filter((el) => el.iri === target);
		const previous = elements.length > 0 ? elements[0].data : void 0;
		return Command.create("Set element data", () => {
			for (const element of model.elements.filter((el) => el.iri === target)) element.setData(data);
			return setElementData(model, data.id, previous);
		});
	}
	function setLinkData(model, oldData, newData) {
		if (!sameLink(oldData, newData)) throw new Error("Cannot change typeId, sourceId or targetId when changing link data");
		return Command.create("Set link data", () => {
			for (const link of model.links) if (sameLink(link.data, oldData)) link.setData(newData);
			return setLinkData(model, newData, oldData);
		});
	}
	//#endregion
	//#region images/icons/class.svg
	var class_default = "data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeD0iMHB4IiB5PSIwcHgiIHZpZXdCb3g9IjAgMCAyNiAyNiI+CiAgICA8dGV4dCB4PSIzIiB5PSIyMiIgY2xhc3M9InRleHQiIGZpbGw9IiNlYWFjNzciCiAgICAgICAgc3R5bGU9ImZvbnQtZmFtaWx5OiAnSGVsdmV0aWNhIE5ldWUnLCAnSGVsdmV0aWNhJywgJ0FyaWFsJywgc2Fucy1zZXJpZjsgZm9udC1zaXplOiAyNnB4OyBmb250LXdlaWdodDogYm9sZDsiPgogICAgICAgIEMKICAgIDwvdGV4dD4KPC9zdmc+Cg==";
	//#endregion
	//#region images/icons/objectProperty.svg
	var objectProperty_default = "data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeD0iMHB4IiB5PSIwcHgiIHZpZXdCb3g9IjAgMCAyNiAyNiI+CiAgICA8dGV4dCB4PSIwIiB5PSIyMCIgY2xhc3M9InRleHQiIGZpbGw9IiMzNGM3ZjMiCiAgICAgICAgc3R5bGU9ImZvbnQtZmFtaWx5OiAnSGVsdmV0aWNhIE5ldWUnLCAnSGVsdmV0aWNhJywgJ0FyaWFsJywgc2Fucy1zZXJpZjsgZm9udC1zaXplOiAxOHB4OyBmb250LXdlaWdodDogYm9sZDsiPgogICAgICAgIE9QCiAgICA8L3RleHQ+Cjwvc3ZnPgo=";
	//#endregion
	//#region images/icons/datatypeProperty.svg
	var datatypeProperty_default = "data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeD0iMHB4IiB5PSIwcHgiIHZpZXdCb3g9IjAgMCAyNiAyNiI+CiAgICA8dGV4dCB4PSIwIiB5PSIyMCIgY2xhc3M9InRleHQiIGZpbGw9IiMzNGM3ZjMiCiAgICAgICAgc3R5bGU9ImZvbnQtZmFtaWx5OiAnSGVsdmV0aWNhIE5ldWUnLCAnSGVsdmV0aWNhJywgJ0FyaWFsJywgc2Fucy1zZXJpZjsgZm9udC1zaXplOiAxOHB4OyBmb250LXdlaWdodDogYm9sZDsiPgogICAgICAgIERQCiAgICA8L3RleHQ+Cjwvc3ZnPgo=";
	//#endregion
	//#region images/icons/person.svg
	var person_default = "data:image/svg+xml,%3csvg%20version='1.1'%20xmlns='http://www.w3.org/2000/svg'%20x='0px'%20y='0px'%20viewBox='0%200%20350%20350'%3e%3cpath%20fill='%23eb7777'%20d='M175,171.173c38.914,0,70.463-38.318,70.463-85.586C245.463,38.318,235.105,0,175,0s-70.465,38.318-70.465,85.587%20C104.535,132.855,136.084,171.173,175,171.173z'/%3e%3cpath%20fill='%23eb7777'%20d='M41.909,301.853C41.897,298.971,41.885,301.041,41.909,301.853L41.909,301.853z'/%3e%3cpath%20fill='%23eb7777'%20d='M308.085,304.104C308.123,303.315,308.098,298.63,308.085,304.104L308.085,304.104z'/%3e%3cpath%20fill='%23eb7777'%20d='M307.935,298.397c-1.305-82.342-12.059-105.805-94.352-120.657c0,0-11.584,14.761-38.584,14.761%20s-38.586-14.761-38.586-14.761c-81.395,14.69-92.803,37.805-94.303,117.982c-0.123,6.547-0.18,6.891-0.202,6.131%20c0.005,1.424,0.011,4.058,0.011,8.651c0,0,19.592,39.496,133.08,39.496c113.486,0,133.08-39.496,133.08-39.496%20c0-2.951,0.002-5.003,0.005-6.399C308.062,304.575,308.018,303.664,307.935,298.397z'/%3e%3c/svg%3e";
	//#endregion
	//#region images/icons/country.svg
	var country_default = "data:image/svg+xml,%3csvg%20version='1.1'%20xmlns='http://www.w3.org/2000/svg'%20x='0px'%20y='0px'%20viewBox='0%200%20512%20512'%3e%3cpath%20fill='%2377ca98'%20d='M472.928,34.752c-4.416-3.008-10.016-3.552-14.944-1.6c-1.024,0.416-106.88,42.048-195.168,0.384%20C186.72-2.432,102.912,14.4,64,25.76V16c0-8.832-7.168-16-16-16c-8.832,0-16,7.168-16,16v32v256v192c0,8.832,7.168,16,16,16%20c8.832,0,16-7.168,16-16V315.328c28.384-9.184,112.608-31.136,185.184,3.136c34.592,16.352,70.784,21.792,103.648,21.792%20c63.2,0,114.016-20.128,117.184-21.408c6.016-2.464,9.984-8.32,9.984-14.848V48C480,42.688,477.344,37.728,472.928,34.752z'/%3e%3c/svg%3e";
	//#endregion
	//#region images/icons/organization.svg
	var organization_default = "data:image/svg+xml,%3csvg%20version='1.1'%20xmlns='http://www.w3.org/2000/svg'%20x='0px'%20y='0px'%20viewBox='0%200%20512%20512'%3e%3cpath%20fill='%2377ca98'%20d='M155,0H15C6.716,0,0,6.716,0,15v35h170V15C170,6.716,163.284,0,155,0z'/%3e%3cpath%20fill='%2377ca98'%20d='M504.464,142.989c-4.662-2.674-10.397-2.651-15.036,0.063L341,229.852V156c0-5.374-2.875-10.337-7.536-13.011%20c-4.662-2.674-10.397-2.651-15.036,0.063L170,229.852V80H0v417c0,8.284,6.716,15,15,15h482c8.284,0,15-6.716,15-15V156%20C512,150.626,509.125,145.663,504.464,142.989z%20M230,406.5c0,8.284-6.716,15-15,15h-60c-8.284,0-15-6.716-15-15v-60%20c0-8.284,6.716-15,15-15h60c8.284,0,15,6.716,15,15V406.5z%20M401,406.5c0,8.284-6.716,15-15,15h-60c-8.284,0-15-6.716-15-15v-60%20c0-8.284,6.716-15,15-15h60c8.284,0,15,6.716,15,15V406.5z'/%3e%3c/svg%3e";
	//#endregion
	//#region images/icons/location.svg
	var location_default = "data:image/svg+xml,%3csvg%20version='1.1'%20xmlns='http://www.w3.org/2000/svg'%20x='0px'%20y='0px'%20width='47.825px'%20height='47.825px'%20viewBox='0%200%2047.825%2047.825'%3e%3cpath%20fill='%23bebc71'%20d='M36.439,12.646c0-6.919-5.608-12.527-12.528-12.527S11.384,5.727,11.384,12.646c0,9.913,12.527,24.582,12.527,24.582%20S36.439,22.508,36.439,12.646z%20M17.733,11.898c0-3.413,2.767-6.179,6.179-6.179s6.179,2.766,6.179,6.179%20c0,3.413-2.767,6.179-6.179,6.179S17.733,15.311,17.733,11.898z'/%3e%3ccircle%20fill='%23bebc71'%20cx='23.911'%20cy='11.898'%20r='3.038'/%3e%3cpath%20fill='%23bebc71'%20d='M30.994,32.87c-1.021,1.476-1.979,2.761-2.777,3.793c7.916,0.476,13.104,2.185,15.034,3.456%20c-2.261,1.491-8.979,3.587-19.338,3.587c-10.358,0-17.077-2.097-19.338-3.587c1.93-1.271,7.114-2.979,15.022-3.455%20c-0.8-1.032-1.759-2.316-2.781-3.792C7.075,33.831,0,36.713,0,40.118c0,4.19,10.707,7.588,23.913,7.588%20c13.207,0,23.912-3.396,23.912-7.588C47.827,36.711,40.744,33.828,30.994,32.87z'/%3e%3c/svg%3e";
	//#endregion
	//#region images/icons/event.svg
	var event_default = "data:image/svg+xml,%3csvg%20version='1.1'%20xmlns='http://www.w3.org/2000/svg'%20x='0px'%20y='0px'%20width='97.473px'%20height='97.473px'%20viewBox='0%200%2097.473%2097.473'%3e%3crect%20fill='%23b4b1fb'%20x='41.569'%20y='47.753'%20width='14.333'%20height='14.333'/%3e%3crect%20fill='%23b4b1fb'%20x='41.569'%20y='67.754'%20width='14.333'%20height='14.332'/%3e%3crect%20fill='%23b4b1fb'%20x='18.569'%20y='67.754'%20width='14.333'%20height='14.332'/%3e%3crect%20fill='%23b4b1fb'%20x='18.569'%20y='47.753'%20width='14.333'%20height='14.333'/%3e%3cpath%20fill='%23b4b1fb'%20d='M95.472,14.466H84.427V2.701c0-1.104-0.896-2-2-2H65.811c-1.104,0-2,0.896-2,2v11.765H33.662V2.701c0-1.104-0.896-2-2-2%20H15.045c-1.104,0-2,0.896-2,2v11.765H2c-1.104,0-2,0.896-2,2v78.305c0,1.104,0.896,2,2,2h93.473c1.104,0,2-0.896,2-2V16.466%20C97.472,15.362,96.576,14.466,95.472,14.466z%20M69.645,8.037c0-0.828,0.672-1.5,1.5-1.5h5.947c0.829,0,1.5,0.672,1.5,1.5v20.34%20c0,0.828-0.671,1.5-1.5,1.5h-5.947c-0.828,0-1.5-0.672-1.5-1.5V8.037z%20M18.88,8.037c0-0.828,0.671-1.5,1.5-1.5h5.947%20c0.829,0,1.5,0.672,1.5,1.5v20.34c0,0.828-0.671,1.5-1.5,1.5H20.38c-0.829,0-1.5-0.672-1.5-1.5V8.037z%20M87.068,84.902%20c0,0.828-0.67,1.5-1.5,1.5H11.903c-0.829,0-1.5-0.672-1.5-1.5v-40c0-0.828,0.671-1.5,1.5-1.5h73.666c0.83,0,1.5,0.672,1.5,1.5%20V84.902z'/%3e%3crect%20fill='%23b4b1fb'%20x='64.568'%20y='47.753'%20width='14.334'%20height='14.333'/%3e%3crect%20fill='%23b4b1fb'%20x='64.568'%20y='67.754'%20width='14.334'%20height='14.332'/%3e%3c/svg%3e";
	//#endregion
	//#region images/icons/object.svg
	var object_default = "data:image/svg+xml,%3csvg%20version='1.1'%20xmlns='http://www.w3.org/2000/svg'%20x='0px'%20y='0px'%20width='50px'%20height='50px'%20viewBox='0%200%2050%2050'%3e%3cpath%20fill='%2353ccb2'%20d='M26.12,14.488c0.879-1.468,2.27-3.569,4.027-5.585h0.002c1.488-1.711,4.402-3.907,4.402-3.907%20c0.438-0.331,0.391-0.792-0.107-1.024l-3.522-1.646c-0.498-0.233-1.175-0.063-1.505,0.376c0,0-2.605,3.737-5.671,11.692%20c-9.48-4.288-18.491,1.718-18.491,12.162c0,10.909,8.393,27.48,19.743,22.478c11.954,5.173,19.749-11.568,19.749-22.478%20C44.747,16.022,36.647,9.846,26.12,14.488z'/%3e%3cpath%20fill='%2353ccb2'%20d='M23.997,10.955c0.548-0.046,1.032-0.531,1.076-1.078c0,0,0.352-4.266-2.621-7.242c-2.982-2.977-7.24-2.622-7.24-2.622%20c-0.548,0.046-1.032,0.531-1.077,1.078c0,0-0.358,4.268,2.619,7.245C19.729,11.31,23.997,10.955,23.997,10.955z'/%3e%3c/svg%3e";
	//#endregion
	//#region src/graph-explorer/customization/defaultTypeStyles.ts
	var DefaultTypeStyleBundle = (types) => {
		if (types.indexOf("http://www.w3.org/2002/07/owl#Class") !== -1 || types.indexOf("http://www.w3.org/2000/01/rdf-schema#Class") !== -1) return {
			color: "#eaac77",
			icon: class_default
		};
		else if (types.indexOf("http://www.w3.org/2002/07/owl#ObjectProperty") !== -1) return {
			color: "#34c7f3",
			icon: objectProperty_default
		};
		else if (types.indexOf("http://www.w3.org/2002/07/owl#DatatypeProperty") !== -1) return {
			color: "#34c7f3",
			icon: datatypeProperty_default
		};
		else if (types.indexOf("http://xmlns.com/foaf/0.1/Person") !== -1 || types.indexOf("http://www.wikidata.org/entity/Q5") !== -1) return {
			color: "#eb7777",
			icon: person_default
		};
		else if (types.indexOf("http://www.wikidata.org/entity/Q6256") !== -1) return {
			color: "#77ca98",
			icon: country_default
		};
		else if (types.indexOf("http://schema.org/Organization") !== -1 || types.indexOf("http://dbpedia.org/ontology/Organisation") !== -1 || types.indexOf("http://xmlns.com/foaf/0.1/Organization") !== -1 || types.indexOf("http://www.wikidata.org/entity/Q43229") !== -1) return {
			color: "#77ca98",
			icon: organization_default
		};
		else if (types.indexOf("http://www.wikidata.org/entity/Q618123") !== -1) return {
			color: "#bebc71",
			icon: location_default
		};
		else if (types.indexOf("http://www.wikidata.org/entity/Q1190554") !== -1) return {
			color: "#b4b1fb",
			icon: event_default
		};
		else if (types.indexOf("http://www.wikidata.org/entity/Q488383") !== -1) return {
			color: "#53ccb2",
			icon: object_default
		};
		else return;
	};
	//#endregion
	//#region src/graph-explorer/customization/defaultLinkStyles.ts
	var LINK_SHOW_IRI = { renderLink: (link) => ({ properties: [{
		position: .5,
		attrs: { text: {
			text: [{
				value: link.typeId,
				language: ""
			}],
			fill: "gray",
			"font-size": 12,
			"font-weight": "lighter"
		} }
	}] }) };
	var LINK_SUB_CLASS_OF = {
		markerTarget: {
			fill: "#f8a485",
			stroke: "#cf8e76"
		},
		renderLink: () => ({ connection: {
			stroke: "#f8a485",
			"stroke-width": 2
		} })
	};
	var LINK_DOMAIN = {
		markerTarget: {
			fill: "#34c7f3",
			stroke: "#38b5db"
		},
		renderLink: () => ({ connection: {
			stroke: "#34c7f3",
			"stroke-width": 2
		} })
	};
	var LINK_RANGE = {
		markerTarget: {
			fill: "#34c7f3",
			stroke: "#38b5db"
		},
		renderLink: () => ({ connection: {
			stroke: "#34c7f3",
			"stroke-width": 2
		} })
	};
	var LINK_TYPE_OF = {
		markerTarget: {
			fill: "#8cd965",
			stroke: "#5b9a3b"
		},
		renderLink: () => ({ connection: {
			stroke: "#8cd965",
			"stroke-width": 2
		} })
	};
	var DefaultLinkTemplateBundle = (type) => {
		if (type === "http://www.w3.org/2000/01/rdf-schema#subClassOf") return LINK_SUB_CLASS_OF;
		else if (type === "http://www.w3.org/2000/01/rdf-schema#domain") return LINK_DOMAIN;
		else if (type === "http://www.w3.org/2000/01/rdf-schema#range") return LINK_RANGE;
		else if (type === "http://www.w3.org/1999/02/22-rdf-syntax-ns#type") return LINK_TYPE_OF;
		else if (type === "http://graph-explorer.org/NewLink") return { markerTarget: { fill: "none" } };
		else return;
	};
	//#endregion
	//#region src/graph-explorer/data/sparql/sparqlModels.ts
	function isRdfBlank(e) {
		return e && e.type === "bnode";
	}
	function isRdfIri(e) {
		return e && e.type === "uri";
	}
	function isRdfLiteral(e) {
		return e && e.type === "literal";
	}
	function isBlankBinding(binding) {
		const blank = binding;
		return blank.blankTrgProp !== void 0 || blank.blankTrg !== void 0 || blank.blankSrcProp !== void 0 || blank.blankSrc !== void 0;
	}
	var ENCODED_PREFIX = "sparql-blank:";
	var BLANK_NODE_QUERY_PARAMETERS = "?blankTrgProp ?blankTrg ?blankSrc ?blankSrcProp ?listHead";
	var BLANK_NODE_QUERY = `
    OPTIONAL {
        FILTER (ISBLANK(?inst)).
        {
            ?inst ?blankTrgProp ?blankTrg.
            ?blankSrc ?blankSrcProp ?inst.
            FILTER NOT EXISTS { ?inst rdf:first _:smth1 }.
            BIND("blankNode" as ?blankType)
        } UNION {
            ?inst rdf:rest*/rdf:first ?blankTrg.
            ?blankSrc ?blankSrcProp ?inst.
            _:smth2 rdf:first ?blankTrg.
            BIND(?blankSrcProp as ?blankTrgProp)
            BIND("listHead" as ?blankType)
            FILTER NOT EXISTS { _:smth3 rdf:rest ?inst }.
        } UNION {
            ?listHead rdf:rest* ?inst.
            FILTER NOT EXISTS { _:smth4 rdf:rest ?listHead }.

            ?listHead rdf:rest*/rdf:first ?blankTrg.
            ?blankSrc ?blankSrcProp ?listHead.
            _:smth5 rdf:first ?blankTrg.
            BIND(?blankSrcProp as ?blankTrgProp)
            BIND("listHead" as ?blankType)
        }
    }
`;
	function isEncodedBlank(id) {
		return id.startsWith(ENCODED_PREFIX);
	}
	var QueryExecutor = class {
		constructor(queryFunction) {
			this.queryFunction = queryFunction;
			this.queryDictionary = {};
		}
		executeQuery(query) {
			const execution = this.queryDictionary[query];
			if (execution) return execution;
			else {
				this.queryDictionary[query] = this.queryFunction(query).then((response) => {
					delete this.queryDictionary[query];
					return response;
				});
				return this.queryDictionary[query];
			}
		}
	};
	function updateFilterResults(result, queryFunction, settings) {
		const completeBindings = [];
		const blankBindings = [];
		for (const binding of result.results.bindings) if (isBlankBinding(binding)) blankBindings.push(binding);
		else completeBindings.push(binding);
		return processBlankBindings(blankBindings, (callBackQuery) => {
			return queryFunction(callBackQuery);
		}, settings).then((processedBindings) => {
			result.results.bindings = completeBindings.concat(processedBindings);
			return result;
		});
	}
	function processBlankBindings(blankBindings, queryFunction, settings) {
		const bindingGroupsById = {};
		for (const binding of blankBindings) {
			if (binding.newInst) binding.inst = binding.newInst;
			if (!bindingGroupsById[binding.inst.value]) bindingGroupsById[binding.inst.value] = [];
			bindingGroupsById[binding.inst.value].push(binding);
		}
		const relatedBlankBindnings = [];
		for (const b of blankBindings) if (isRdfBlank(b.blankTrg)) relatedBlankBindnings.push([b]);
		return loadRelatedBlankNodes(relatedBlankBindnings, new QueryExecutor(queryFunction), settings).then((loadedGroupsById) => {
			const idsMap = getEncodedIdDictionary(loadedGroupsById);
			const groups = Object.keys(bindingGroupsById).map((key) => bindingGroupsById[key]);
			for (const group of groups) {
				for (const blankBinding of group) {
					if (!blankBinding.label) blankBinding.label = createLabelForBlankBinding(blankBinding);
					const encodedId4LoadedElement = idsMap[blankBinding.blankTrg.value];
					if (encodedId4LoadedElement) blankBinding.blankTrg.value = encodedId4LoadedElement;
				}
				updateGroupIds(group, encodeId(group));
			}
			return blankBindings;
		});
	}
	function getEncodedIdDictionary(blankBindingGroups) {
		const idDictionary = {};
		const keys = Object.keys(blankBindingGroups);
		for (const key of keys) {
			idDictionary[key] = encodeId(blankBindingGroups[key]);
			updateGroupIds(blankBindingGroups[key], idDictionary[key]);
		}
		return idDictionary;
	}
	function updateGroupIds(group, newId) {
		for (const loadedBlankBinding of group) loadedBlankBinding.inst.value = newId;
	}
	function encodeId(blankBindings) {
		const bindingSet = {};
		for (const binding of blankBindings) {
			const { inst: _inst, ...exceptInst } = binding;
			const encodedBinding = JSON.stringify(exceptInst);
			bindingSet[encodedBinding] = exceptInst;
		}
		const normalizedBindings = Object.keys(bindingSet).sort().map((key) => bindingSet[key]);
		return ENCODED_PREFIX + encodeURI(JSON.stringify(normalizedBindings));
	}
	function decodeId(id) {
		if (!isEncodedBlank(id)) return;
		try {
			const clearId = id.substring(13, id.length);
			return JSON.parse(decodeURI(clearId)).map((binding) => {
				binding.inst = {
					type: "uri",
					value: id
				};
				return binding;
			});
		} catch (_error) {
			return;
		}
	}
	function createLabelForBlankBinding(bn) {
		if (bn.blankType.value === "listHead") return {
			type: "literal",
			value: "RDFList",
			"xml:lang": ""
		};
		else return {
			type: "literal",
			value: bn.class ? getUriLocalName(bn.class.value) || bn.class.value : "anonymous",
			"xml:lang": ""
		};
	}
	function loadRelatedBlankNodes(blankChains, queryExecutor, settings, recursionDeep) {
		recursionDeep = recursionDeep || 1;
		if (recursionDeep > 3) return Promise.resolve({});
		const promises = blankChains.map((chain) => ({
			query: getQueryForChain(chain, settings),
			chain
		})).map((pair) => queryExecutor.executeQuery(pair.query).then((response) => ({
			response,
			chain: pair.chain
		})));
		return Promise.all(promises).then((results) => {
			const recursionPromises = [];
			const loadedBlankBindings = {};
			for (const result of results) {
				const bindings = result.response.results.bindings;
				if (bindings.length > 0) {
					const relatedBlankBindings = [];
					for (const binding of bindings) if (isRdfBlank(binding.blankTrg)) relatedBlankBindings.push(result.chain.concat([binding]));
					recursionPromises.push(loadRelatedBlankNodes(relatedBlankBindings, queryExecutor, settings, recursionDeep + 1).then((loadedGroupsById) => {
						const idsMap = getEncodedIdDictionary(loadedGroupsById);
						const mergedResults = {};
						for (const binding of bindings) {
							binding.label = createLabelForBlankBinding(binding);
							const encodedId = idsMap[binding.blankTrg.value];
							if (encodedId) binding.blankTrg.value = encodedId;
							if (!mergedResults[binding.inst.value]) mergedResults[binding.inst.value] = [];
							mergedResults[binding.inst.value].push(binding);
						}
						Object.keys(mergedResults).forEach((key) => {
							const group = mergedResults[key];
							const originalId = group[0].inst.value;
							loadedBlankBindings[originalId] = group;
						});
						return true;
					}));
				}
			}
			return Promise.all(recursionPromises).then(() => {
				return loadedBlankBindings;
			});
		});
	}
	function getQueryForChain(blankNodes, sparqlDataProviderSettings) {
		function getQueryBlock(blankNode, index, maxIndex) {
			const trustableTrgProp = index === 0 || blankNode.blankType.value !== "listHead";
			const sourceId = index > 0 ? "?inst" + (index - 1) : "<" + blankNode.blankSrc.value + ">";
			const sourcePropId = trustableTrgProp ? index > 0 ? "?blankTrgProp" + (index - 1) : "<" + blankNode.blankSrcProp.value + ">" : "?anyType" + index;
			const instPostfix = index === maxIndex ? "" : index.toString();
			const targetPropId = trustableTrgProp ? "<" + blankNode.blankTrgProp.value + ">" : "?anyType0" + index;
			return `
        # ======================
        ${sourceId} ${sourcePropId} ?blankSrc${index}.
        ${index === 0 && blankNode.blankType.value === "listHead" ? `
            ?blankSrc${index} rdf:rest*/rdf:first ?inst${instPostfix}.
            ` : `?blankSrc${index} ${targetPropId} ?inst${instPostfix}.`}
        BIND (<${blankNode.blankTrgProp.value}> as ?blankSrcProp${index}).
        FILTER (ISBLANK(?inst${instPostfix})).
        {
            ?inst${instPostfix} ?blankTrgProp${instPostfix} ?blankTrg${instPostfix}.
            BIND("blankNode" as ?blankType${instPostfix}).
            FILTER NOT EXISTS { ?inst${instPostfix} rdf:first _:smth1${index} }.
        } UNION {
            ?inst${instPostfix} rdf:rest*/rdf:first ?blankTrg${instPostfix}.
            ?blankSrc${index} ?blankSrcProp${index} ?inst${instPostfix}.
            _:smth2${index} rdf:first ?blankTrg${instPostfix}.
            BIND(?blankSrcProp${index} as ?blankTrgProp${instPostfix})
            BIND("listHead" as ?blankType${instPostfix})
            FILTER NOT EXISTS { _:smth3${index} rdf:rest ?inst${instPostfix} }.
        }
        OPTIONAL {
            ?inst${instPostfix} rdf:type ?class${instPostfix}.
        }
    `;
		}
		const body = blankNodes.map((bn, index) => getQueryBlock(bn, index, blankNodes.length - 1)).join("\n");
		return `${sparqlDataProviderSettings.defaultPrefix}
    SELECT ?inst ?class ?label ?blankTrgProp ?blankTrg ?blankType
        WHERE {
           ${body}
        }
    `;
	}
	function elementInfo(elementIds) {
		return {
			head: void 0,
			results: { bindings: getElementBindings(elementIds.filter((id) => isEncodedBlank(id))) }
		};
	}
	function linksInfo(elementIds) {
		return {
			head: void 0,
			results: { bindings: getLinkBinding(elementIds) }
		};
	}
	function linkTypesOf(params) {
		return {
			head: void 0,
			results: { bindings: getLinkCountBinding(params.elementId) }
		};
	}
	function filter(params) {
		const filterResponse = {
			head: void 0,
			results: { bindings: [] }
		};
		if (params.limit === 0) params.limit = 100;
		if (params.elementTypeId) filterResponse.results.bindings = [];
		else if (params.refElementId && params.refElementLinkId) filterResponse.results.bindings = getAllRelatedByLinkTypeElements(params.refElementId, params.refElementLinkId, params.linkDirection);
		else if (params.refElementId) filterResponse.results.bindings = getAllRelatedElements(params.refElementId);
		if (params.text && filterResponse.results.bindings.length !== 0) filterResponse.results.bindings = filterResponse.results.bindings.filter((be) => be.inst.value.toLowerCase().indexOf(params.text) !== -1);
		return filterResponse;
	}
	function getElementTypes$1(elementIds) {
		const bindings = [];
		for (const id of elementIds) {
			const blankBindings = decodeId(id);
			if (blankBindings) {
				for (const be of blankBindings) if (isRdfIri(be.inst) && be.class) bindings.push({
					inst: be.inst,
					class: be.class
				});
			}
		}
		return {
			head: void 0,
			results: { bindings }
		};
	}
	function getAllRelatedByLinkTypeElements(refElementId, refElementLinkId, linkDirection) {
		const blankElements = (decodeId(refElementId) || []).concat(decodeId(refElementLinkId) || []);
		let bindings = [];
		if (blankElements.length > 0) {
			for (const be of blankElements) if (linkDirection === "in") {
				if (be.inst.value === refElementId && (isRdfIri(be.blankSrc) || isRdfBlank(be.blankSrc)) && refElementLinkId === be.blankSrcProp.value) if (isRdfIri(be.blankSrc)) bindings.push({ inst: be.blankSrc });
				else bindings = bindings.concat(decodeId(be.blankSrc.value) || [{ inst: be.blankSrc }]);
				else if (be.blankTrg.value === refElementId && refElementLinkId === be.blankTrgProp.value) bindings.push(be);
			} else if (be.inst.value === refElementId && (isRdfIri(be.blankTrg) || isRdfBlank(be.blankTrg)) && refElementLinkId === be.blankTrgProp.value) if (isRdfIri(be.blankTrg)) bindings.push({ inst: be.blankTrg });
			else bindings = bindings.concat(decodeId(be.blankTrg.value) || [{ inst: be.blankTrg }]);
			else if (be.blankSrc.value === refElementId && refElementLinkId === be.blankSrcProp.value) bindings.push(be);
		}
		return bindings;
	}
	function getAllRelatedElements(id) {
		const blankElements = decodeId(id);
		let bindings = [];
		if (blankElements) {
			for (const be of blankElements) if (be.inst.value === id || id === be.blankSrc.value || id === be.blankTrg.value) {
				bindings.push(be);
				if (isRdfIri(be.blankSrc)) bindings.push({ inst: be.blankSrc });
				else if (isRdfBlank(be.blankSrc)) bindings = bindings.concat(decodeId(be.blankSrc.value) || [{ inst: be.blankSrc }]);
				if (isRdfIri(be.blankTrg)) bindings.push({ inst: be.blankTrg });
				else if (isRdfBlank(be.blankTrg)) bindings = bindings.concat(decodeId(be.blankTrg.value) || [{ inst: be.blankTrg }]);
			}
		}
		return bindings;
	}
	function getElementBindings(ids) {
		let blankElements = [];
		for (const id of ids) if (decodeId(id)) blankElements = blankElements.concat(decodeId(id));
		return blankElements.filter((be) => {
			return ids.indexOf(be.inst.value) !== -1;
		});
	}
	function getLinkBinding(ids) {
		let blankElements = [];
		for (const id of ids) if (decodeId(id)) blankElements = blankElements.concat(decodeId(id));
		const bindings = [];
		for (const be of blankElements) if (ids.indexOf(be.inst.value) !== -1) {
			if ((isRdfIri(be.blankSrc) || isRdfBlank(be.blankSrc)) && isRdfIri(be.blankSrcProp) && ids.indexOf(be.blankSrc.value) !== -1) bindings.push({
				source: be.blankSrc,
				type: be.blankSrcProp,
				target: be.inst
			});
			if ((isRdfIri(be.blankTrg) || isRdfBlank(be.blankTrg)) && isRdfIri(be.blankTrgProp) && ids.indexOf(be.blankTrg.value) !== -1) bindings.push({
				source: be.inst,
				type: be.blankTrgProp,
				target: be.blankTrg
			});
		}
		return bindings;
	}
	function getLinkCountBinding(id) {
		const blankElements = decodeId(id);
		const dictionary = {};
		for (const be of blankElements) if (id === be.inst.value) {
			if ((isRdfIri(be.blankTrg) || isRdfBlank(be.blankTrg)) && isRdfIri(be.blankTrgProp)) {
				if ((isRdfIri(be.blankSrc) || isRdfBlank(be.blankSrc)) && isRdfIri(be.blankSrcProp)) {
					if (!dictionary[be.blankSrcProp.value]) dictionary[be.blankSrcProp.value] = {
						link: be.blankSrcProp,
						inCount: {
							type: "literal",
							value: "1",
							"xml:lang": ""
						},
						outCount: {
							type: "literal",
							value: "0",
							"xml:lang": ""
						}
					};
				}
				if (!dictionary[be.blankTrgProp.value]) dictionary[be.blankTrgProp.value] = {
					link: be.blankTrgProp,
					inCount: {
						type: "literal",
						value: "0",
						"xml:lang": ""
					},
					outCount: {
						type: "literal",
						value: "1",
						"xml:lang": ""
					}
				};
				else dictionary[be.blankTrgProp.value].outCount.value = (+dictionary[be.blankTrgProp.value].outCount.value + 1).toString();
			}
		}
		return Object.keys(dictionary).map((k) => dictionary[k]);
	}
	//#endregion
	//#region src/graph-explorer/diagram/linkRouter.ts
	var DefaultLinkRouter = class {
		constructor(gap = 20) {
			this.gap = gap;
		}
		route(model) {
			const routings = /* @__PURE__ */ new Map();
			for (const link of model.links) {
				if (routings.has(link.id)) continue;
				const { sourceId, targetId } = link;
				if (!sourceId || !targetId) continue;
				else if (sourceId === targetId) this.routeFeedbackSiblingLinks(model, sourceId, routings);
				else this.routeNormalSiblingLinks(model, sourceId, targetId, routings);
			}
			return routings;
		}
		routeFeedbackSiblingLinks(model, elementId, routings) {
			const element = model.getElement(elementId);
			const { x, y } = element.position;
			const { width, height } = element.size;
			let index = 0;
			for (const sibling of element.links) {
				if (routings.has(sibling.id) || hasUserPlacedVertices(sibling)) continue;
				const { sourceId, targetId } = sibling;
				if (sourceId === targetId) {
					const offset = this.gap * (index + 1);
					const vertices = [
						{
							x: x - offset,
							y: y + height / 2
						},
						{
							x: x - offset,
							y: y - offset
						},
						{
							x: x + width / 2,
							y: y - offset
						}
					];
					routings.set(sibling.id, {
						linkId: sibling.id,
						vertices
					});
					index++;
				}
			}
		}
		routeNormalSiblingLinks(model, sourceId, targetId, routings) {
			const source = model.getElement(sourceId);
			const target = model.getElement(targetId);
			const sourceCenter = centerOfElement(source);
			const targetCenter = centerOfElement(target);
			const midPoint = {
				x: (sourceCenter.x + targetCenter.x) / 2,
				y: (sourceCenter.y + targetCenter.y) / 2
			};
			const direction = Vector.normalize({
				x: targetCenter.x - sourceCenter.x,
				y: targetCenter.y - sourceCenter.y
			});
			const siblings = source.links.filter((link) => (link.sourceId === targetId || link.targetId === targetId) && !routings.has(link.id) && !hasUserPlacedVertices(link));
			if (siblings.length <= 1) return;
			const indexModifier = siblings.length % 2 ? 0 : 1;
			siblings.forEach((sibling, siblingIndex) => {
				const index = siblingIndex + indexModifier;
				const offset = this.gap * Math.ceil(index / 2) - (indexModifier ? this.gap / 2 : 0);
				const offsetDirection = index % 2 ? {
					x: -direction.y,
					y: direction.x
				} : {
					x: direction.y,
					y: -direction.x
				};
				const vertex = {
					x: midPoint.x + offsetDirection.x * offset,
					y: midPoint.y + offsetDirection.y * offset
				};
				routings.set(sibling.id, {
					linkId: sibling.id,
					vertices: [vertex],
					labelTextAnchor: this.getLabelAlignment(direction, siblingIndex, siblings.length)
				});
			});
		}
		getLabelAlignment(connectionDirection, siblingIndex, siblingCount) {
			const angle = Math.atan2(connectionDirection.y, connectionDirection.x);
			const absoluteAngle = Math.abs(angle);
			const isHorizontal = absoluteAngle < Math.PI * 1 / 8 || absoluteAngle > Math.PI * 7 / 8;
			const isTop = angle < 0;
			const isBottom = angle > 0;
			const firstOuter = siblingCount - 2;
			const secondOuter = siblingCount - 1;
			if (!isHorizontal) {
				if (isTop && siblingIndex === secondOuter || isBottom && siblingIndex === firstOuter) return "end";
				else if (isTop && siblingIndex === firstOuter || isBottom && siblingIndex === secondOuter) return "start";
			}
			return "middle";
		}
	};
	function hasUserPlacedVertices(link) {
		const vertices = link.vertices;
		return vertices && vertices.length > 0;
	}
	function centerOfElement(element) {
		const { x, y } = element.position;
		const { width, height } = element.size;
		return {
			x: x + width / 2,
			y: y + height / 2
		};
	}
	//#endregion
	//#region src/graph-explorer/diagram/view.ts
	var IriClickIntent = /* @__PURE__ */ function(IriClickIntent) {
		IriClickIntent["JumpToEntity"] = "jumpToEntity";
		IriClickIntent["OpenEntityIri"] = "openEntityIri";
		IriClickIntent["OpenOtherIri"] = "openOtherIri";
		return IriClickIntent;
	}({});
	var RenderingLayer = /* @__PURE__ */ function(RenderingLayer) {
		RenderingLayer[RenderingLayer["Element"] = 1] = "Element";
		RenderingLayer[RenderingLayer["ElementSize"] = 2] = "ElementSize";
		RenderingLayer[RenderingLayer["PaperArea"] = 3] = "PaperArea";
		RenderingLayer[RenderingLayer["Link"] = 4] = "Link";
		RenderingLayer[RenderingLayer["Editor"] = 5] = "Editor";
		RenderingLayer[RenderingLayer["FirstToUpdate"] = 1] = "FirstToUpdate";
		RenderingLayer[RenderingLayer["LastToUpdate"] = 5] = "LastToUpdate";
		return RenderingLayer;
	}({});
	var WidgetAttachment = /* @__PURE__ */ function(WidgetAttachment) {
		WidgetAttachment[WidgetAttachment["Viewport"] = 1] = "Viewport";
		WidgetAttachment[WidgetAttachment["OverElements"] = 2] = "OverElements";
		WidgetAttachment[WidgetAttachment["OverLinks"] = 3] = "OverLinks";
		return WidgetAttachment;
	}({});
	var DiagramView = class {
		constructor(model, options = {}) {
			this.model = model;
			this.options = options;
			this.listener = new EventObserver();
			this.source = new EventSource();
			this.events = this.source;
			this.disposed = false;
			this.colorSeed = 195935983;
			this._language = "en";
			this.linkTemplates = /* @__PURE__ */ new Map();
			this.routings = /* @__PURE__ */ new Map();
			this.resolveTypeStyle = options.typeStyleResolver || DefaultTypeStyleBundle;
			this.resolveLinkTemplate = options.linkTemplateResolver || DefaultLinkTemplateBundle;
			this.resolveElementTemplate = options.elementTemplateResolver || DefaultElementTemplateBundle;
			this.initRouting();
		}
		initRouting() {
			this.router = this.options.linkRouter || new DefaultLinkRouter();
			this.updateRoutings();
			this.listener.listen(this.model.events, "changeCells", () => this.updateRoutings());
			this.listener.listen(this.model.events, "linkEvent", ({ key: _key, data }) => {
				if (data.changeVertices) this.updateRoutings();
			});
			this.listener.listen(this.model.events, "elementEvent", ({ key: _key, data }) => {
				if (data.changePosition || data.changeSize) this.updateRoutings();
			});
		}
		updateRoutings() {
			const previousRoutes = this.routings;
			const computedRoutes = this.router.route(this.model);
			previousRoutes.forEach((previous, linkId) => {
				const computed = computedRoutes.get(linkId);
				if (computed && sameRoutedLink(previous, computed)) computedRoutes.set(linkId, previous);
			});
			this.routings = computedRoutes;
			this.source.trigger("updateRoutings", {
				source: this,
				previous: previousRoutes
			});
		}
		getRoutings() {
			return this.routings;
		}
		getRouting(linkId) {
			return this.routings.get(linkId);
		}
		getLanguage() {
			return this._language;
		}
		setLanguage(value) {
			if (!value) throw new Error("Cannot set empty language.");
			const previous = this._language;
			if (previous === value) return;
			this._language = value;
			this.source.trigger("changeLanguage", {
				source: this,
				previous
			});
		}
		getLinkTemplates() {
			return this.linkTemplates;
		}
		performSyncUpdate() {
			for (let layer = 1; layer <= 5; layer++) this.source.trigger("syncUpdate", { layer });
		}
		onIriClick(iri, element, clickIntent, event) {
			event.persist();
			event.preventDefault();
			const { onIriClick } = this.options;
			if (onIriClick) onIriClick({
				iri,
				element,
				clickIntent,
				originalEvent: event
			});
		}
		setPaperWidget(widget) {
			const { key, widget: element, attachment } = widget;
			const widgets = { [key]: element ? {
				element,
				attachment
			} : void 0 };
			this.source.trigger("updateWidgets", { widgets });
		}
		setHandlerForNextDropOnPaper(handler) {
			this.dropOnPaperHandler = handler;
		}
		_tryHandleDropOnPaper(e) {
			const { dropOnPaperHandler } = this;
			if (dropOnPaperHandler) {
				this.dropOnPaperHandler = void 0;
				dropOnPaperHandler(e);
				return true;
			}
			return false;
		}
		selectLabel(labels, language) {
			const targetLanguage = typeof language === "undefined" ? this.getLanguage() : language;
			const { selectLabelLanguage = defaultSelectLabel } = this.options;
			return selectLabelLanguage(labels, targetLanguage);
		}
		formatLabel(labels, fallbackIri, language) {
			return resolveLabel(this.selectLabel(labels, language), fallbackIri);
		}
		getElementTypeString(elementModel) {
			return elementModel.types.map((typeId) => {
				const type = this.model.createClass(typeId);
				return this.formatLabel(type.label, type.id);
			}).sort().join(", ");
		}
		getTypeStyle(types) {
			types.sort();
			const customStyle = this.resolveTypeStyle(types);
			const icon = customStyle ? customStyle.icon : void 0;
			let color;
			if (customStyle && customStyle.color) color = (0, d3_color.hcl)(customStyle.color);
			else color = {
				h: getHueFromClasses(types, this.colorSeed),
				c: 40,
				l: 75
			};
			return {
				icon,
				color
			};
		}
		formatIri(iri) {
			if (isEncodedBlank(iri)) return "(blank node)";
			return `<${iri}>`;
		}
		getElementTemplate(types) {
			return this.resolveElementTemplate(types) || StandardTemplate;
		}
		createLinkTemplate(linkType) {
			const existingTemplate = this.linkTemplates.get(linkType.id);
			if (existingTemplate) return existingTemplate;
			let template = {};
			const result = this.resolveLinkTemplate(linkType.id);
			if (result) template = (0, lodash.cloneDeep)(result);
			fillLinkTemplateDefaults(template);
			this.linkTemplates.set(linkType.id, template);
			this.source.trigger("changeLinkTemplates", {});
			return template;
		}
		dispose() {
			if (this.disposed) return;
			this.source.trigger("dispose", {});
			this.listener.stopListening();
			this.disposed = true;
		}
		get highlighter() {
			return this._highlighter;
		}
		setHighlighter(value) {
			const previous = this._highlighter;
			if (previous === value) return;
			this._highlighter = value;
			this.source.trigger("changeHighlight", {
				source: this,
				previous
			});
		}
		_setElementDecorator(decorator) {
			this._elementDecorator = decorator;
		}
		_decorateElement(element) {
			return this._elementDecorator(element);
		}
	};
	function sameRoutedLink(a, b) {
		return a.linkId === b.linkId && a.labelTextAnchor === b.labelTextAnchor && isPolylineEqual(a.vertices, b.vertices);
	}
	function getHueFromClasses(classes, seed) {
		let hash = seed;
		for (const name of classes) hash = hashFnv32a(name, hash);
		return 360 * ((hash === void 0 ? 0 : hash) / 2147483647);
	}
	function fillLinkTemplateDefaults(template) {
		(0, lodash.defaultsDeep)(template, { markerTarget: {
			d: "M0,0 L0,8 L9,4 z",
			width: 9,
			height: 8,
			fill: "black"
		} });
		if (!template.renderLink) template.renderLink = () => ({});
	}
	function defaultSelectLabel(texts, language) {
		if (texts.length === 0) return;
		let defaultValue;
		let englishValue;
		for (const text of texts) if (text.language === language) return text;
		else if (text.language === "") defaultValue = text;
		else if (text.language === "en") englishValue = text;
		return defaultValue !== void 0 ? defaultValue : englishValue !== void 0 ? englishValue : texts[0];
	}
	function resolveLabel(label, fallbackIri) {
		if (label) return label.value;
		return getUriLocalName(fallbackIri) || fallbackIri;
	}
	//#endregion
	//#region src/graph-explorer/diagram/elementLayer.tsx
	var ElementLayer = class extends react.Component {
		constructor(props, context) {
			super(props, context);
			this.listener = new EventObserver();
			this.redrawBatch = {
				requests: /* @__PURE__ */ new Map(),
				forAll: 0
			};
			this.delatedRedraw = new Debouncer();
			this.sizeRequests = /* @__PURE__ */ new Map();
			this.delayedUpdateSizes = new Debouncer();
			this.onMount = (layer) => {
				this.layer = layer;
			};
			this.requestRedraw = (element, request) => {
				if ((this.redrawBatch.forAll | request) === this.redrawBatch.forAll) return;
				const existing = this.redrawBatch.requests.get(element.id);
				this.redrawBatch.requests.set(element.id, existing | request);
				this.delatedRedraw.call(this.redrawElements);
			};
			this.redrawElements = () => {
				const props = this.props;
				this.setState((state) => ({ elementStates: applyRedrawRequests(props.view, props.group, this.redrawBatch, state.elementStates) }));
			};
			this.requestSizeUpdate = (element, node) => {
				this.sizeRequests.set(element.id, {
					element,
					node
				});
				this.delayedUpdateSizes.call(this.recomputeQueuedSizes);
			};
			this.recomputeQueuedSizes = () => {
				const batch = this.sizeRequests;
				this.sizeRequests = /* @__PURE__ */ new Map();
				batch.forEach(({ element, node }) => {
					const { clientWidth, clientHeight } = node;
					element.setSize({
						width: clientWidth,
						height: clientHeight
					});
				});
			};
			const { view, group } = this.props;
			this.state = { elementStates: applyRedrawRequests(view, group, this.redrawBatch, /* @__PURE__ */ new Map()) };
		}
		render() {
			const { view, style } = this.props;
			const { elementStates } = this.state;
			const elementsToRender = [];
			for (const { id } of view.model.elements) {
				const state = elementStates.get(id);
				if (state) elementsToRender.push(state);
			}
			return /* @__PURE__ */ react.createElement("div", {
				className: "graph-explorer-element-layer",
				ref: this.onMount,
				style
			}, elementsToRender.map((state) => {
				const overlayElement = /* @__PURE__ */ react.createElement(OverlayedElement, {
					key: state.element.id,
					state,
					view,
					onInvalidate: this.requestRedraw,
					onResize: this.requestSizeUpdate
				});
				const elementDecorator = view._decorateElement(state.element);
				if (elementDecorator) return /* @__PURE__ */ react.createElement("div", { key: state.element.id }, overlayElement, elementDecorator);
				return overlayElement;
			}));
		}
		componentDidMount() {
			const { view } = this.props;
			this.listener.listen(view.model.events, "changeCells", (e) => {
				if (e.updateAll) this.requestRedrawAll(0);
				else if (e.changedElement) this.requestRedraw(e.changedElement, 0);
			});
			this.listener.listen(view.events, "changeLanguage", () => {
				this.requestRedrawAll(3);
			});
			this.listener.listen(view.events, "changeHighlight", () => {
				this.requestRedrawAll(5);
			});
			this.listener.listen(view.model.events, "elementEvent", ({ data }) => {
				const invalidatesTemplate = data.changeData || data.changeExpanded || data.changeElementState;
				if (invalidatesTemplate) this.requestRedraw(invalidatesTemplate.source, 3);
				const invalidatesRender = data.changePosition || data.requestedRedraw;
				if (invalidatesRender) this.requestRedraw(invalidatesRender.source, 1);
			});
			this.listener.listen(view.events, "syncUpdate", ({ layer }) => {
				if (layer === RenderingLayer.Element) this.delatedRedraw.runSynchronously();
				else if (layer === RenderingLayer.ElementSize) this.delayedUpdateSizes.runSynchronously();
			});
		}
		componentDidUpdate(nextProps) {
			if (this.props.group !== nextProps.group) this.setState((state) => ({ elementStates: applyRedrawRequests(nextProps.view, nextProps.group, this.redrawBatch, state.elementStates) }));
		}
		componentWillUnmount() {
			this.listener.stopListening();
			this.delatedRedraw.dispose();
			this.delayedUpdateSizes.dispose();
		}
		requestRedrawAll(request) {
			this.redrawBatch.forAll |= request;
			this.delatedRedraw.call(this.redrawElements);
		}
	};
	function applyRedrawRequests(view, targetGroup, batch, previous) {
		const computed = /* @__PURE__ */ new Map();
		for (const element of view.model.elements) {
			if (element.group !== targetGroup) continue;
			const elementId = element.id;
			if (previous.has(elementId)) {
				let state = previous.get(elementId);
				const request = (batch.requests.get(elementId) || 0) | batch.forAll;
				if (request & 1) state = {
					element,
					templateProps: (request & 3) === 3 ? computeTemplateProps(state.element, view) : state.templateProps,
					blurred: (request & 5) === 5 ? computeIsBlurred(state.element, view) : state.blurred
				};
				computed.set(elementId, state);
				batch.requests.delete(elementId);
			} else computed.set(element.id, {
				element,
				templateProps: computeTemplateProps(element, view),
				blurred: computeIsBlurred(element, view)
			});
		}
		batch.forAll = 0;
		return computed;
	}
	var ElementContext = react.createContext(null);
	var OverlayedElement = class extends react.Component {
		constructor(..._args) {
			super(..._args);
			this.element = null;
			this.listener = new EventObserver();
			this.disposed = false;
			this.rerenderTemplate = () => {
				if (this.disposed) return;
				this.props.onInvalidate(this.props.state.element, 3);
			};
			this.onMount = (node) => {
				this.element = node;
				if (!node) return;
				const { state, onResize } = this.props;
				onResize(state.element, node);
			};
			this.onLoadOrErrorEvent = () => {
				const { state, onResize } = this.props;
				if (this.element) onResize(state.element, this.element);
			};
			this.onClick = (e) => {
				if (e.target instanceof HTMLElement && e.target.localName === "a") {
					const anchor = e.target;
					const { view, state } = this.props;
					const clickIntent = e.target.getAttribute("data-iri-click-intent") === IriClickIntent.OpenEntityIri ? IriClickIntent.OpenEntityIri : IriClickIntent.OpenOtherIri;
					view.onIriClick(decodeURI(anchor.href), state.element, clickIntent, e);
				}
			};
			this.onDoubleClick = (e) => {
				e.preventDefault();
				e.stopPropagation();
				const { view, state: { element } } = this.props;
				view.model.history.execute(setElementExpanded(element, !element.isExpanded));
			};
		}
		render() {
			const { state: { element, blurred } } = this.props;
			if (element.temporary) return /* @__PURE__ */ react.createElement("div", null);
			const { x = 0, y = 0 } = element.position;
			const transform = `translate(${x}px,${y}px)`;
			const className = `graph-explorer-overlayed-element ${blurred ? "graph-explorer-overlayed-element--blurred" : ""}`;
			return /* @__PURE__ */ react.createElement(ElementContext.Provider, { value: { graphExplorerElement: { element } } }, /* @__PURE__ */ react.createElement("div", {
				className,
				"data-element-id": element.id,
				style: {
					position: "absolute",
					transform
				},
				tabIndex: 0,
				ref: this.onMount,
				onLoad: this.onLoadOrErrorEvent,
				onError: this.onLoadOrErrorEvent,
				onClick: this.onClick,
				onDoubleClick: this.onDoubleClick
			}, /* @__PURE__ */ react.createElement(TemplatedElement, this.props)));
		}
		componentDidMount() {
			const { state, view } = this.props;
			this.listener.listen(state.element.events, "requestedFocus", () => {
				if (this.element) this.element.focus();
			});
			this.typesObserver = observeElementTypes(view.model, "changeLabel", this.rerenderTemplate);
			this.propertiesObserver = observeProperties(view.model, "changeLabel", this.rerenderTemplate);
			this.observeTypes();
		}
		componentWillUnmount() {
			this.listener.stopListening();
			this.typesObserver.stopListening();
			this.propertiesObserver.stopListening();
			this.disposed = true;
		}
		shouldComponentUpdate(nextProps) {
			return this.props.state !== nextProps.state;
		}
		componentDidUpdate() {
			this.observeTypes();
			if (this.element) this.props.onResize(this.props.state.element, this.element);
		}
		observeTypes() {
			const { state: { element } } = this.props;
			this.typesObserver.observe(element.data.types);
			this.propertiesObserver.observe(Object.keys(element.data.properties));
		}
	};
	var TemplatedElement = class extends react.Component {
		render() {
			const { state, view } = this.props;
			const { element, templateProps } = state;
			const templateClass = view.getElementTemplate(element.data.types);
			this.cachedTemplateClass = templateClass;
			this.cachedTemplateProps = templateProps;
			return react.createElement(templateClass, templateProps);
		}
		shouldComponentUpdate(nextProps) {
			const templateClass = nextProps.view.getElementTemplate(nextProps.state.element.data.types);
			return !(this.cachedTemplateClass === templateClass && this.cachedTemplateProps === nextProps.state.templateProps);
		}
	};
	function computeTemplateProps(model, view) {
		const types = model.data.types.length > 0 ? view.getElementTypeString(model.data) : "Thing";
		const label = view.formatLabel(model.data.label.values, model.iri);
		const { color, icon } = computeStyleFor(model, view);
		const propsAsList = computePropertyTable(model, view);
		return {
			elementId: model.id,
			data: model.data,
			iri: model.iri,
			types,
			label,
			color,
			iconUrl: icon,
			imgUrl: model.data.image,
			isExpanded: model.isExpanded,
			props: model.data.properties,
			propsAsList
		};
	}
	function computePropertyTable(model, view) {
		if (!model.data.properties) return [];
		const propTable = Object.keys(model.data.properties).map((key) => {
			const property = view.model.createProperty(key);
			return {
				id: key,
				name: view.formatLabel(property.label, key),
				property: model.data.properties[key]
			};
		});
		propTable.sort((a, b) => {
			const aLabel = (a.name || a.id).toLowerCase();
			const bLabel = (b.name || b.id).toLowerCase();
			return aLabel.localeCompare(bLabel);
		});
		return propTable;
	}
	function computeStyleFor(model, view) {
		const { color: { h, c, l }, icon } = view.getTypeStyle(model.data.types);
		return {
			icon,
			color: (0, d3_color.hcl)(h, c, l).toString()
		};
	}
	function computeIsBlurred(element, view) {
		return view.highlighter && !view.highlighter(element);
	}
	//#endregion
	//#region src/graph-explorer/diagram/linkLayer.tsx
	var CLASS_NAME$24 = "graph-explorer-link-layer";
	var LinkLayer = class extends react.Component {
		constructor(..._args) {
			super(..._args);
			this.listener = new EventObserver();
			this.delayedUpdate = new Debouncer();
			this.updateState = 1;
			this.scheduledToUpdate = /* @__PURE__ */ new Set();
			this.scheduleUpdateAll = () => {
				if (this.updateState !== 2) {
					this.updateState = 2;
					this.scheduledToUpdate = /* @__PURE__ */ new Set();
				}
				this.delayedUpdate.call(this.performUpdate);
			};
			this.performUpdate = () => {
				this.forceUpdate();
			};
			this.getLinks = () => {
				const { view, links, group } = this.props;
				if (!group) return links;
				const nestedElements = computeDeepNestedElements(computeGrouping(view.model.elements), group);
				return links.filter((link) => {
					const { sourceId, targetId } = link;
					const source = view.model.getElement(sourceId);
					const target = view.model.getElement(targetId);
					if (!source || !target) return false;
					const sourceGroup = source.group;
					const targetGroup = target.group;
					return nestedElements[sourceGroup] || nestedElements[targetGroup];
				});
			};
		}
		componentDidMount() {
			const { view } = this.props;
			const scheduleUpdateElementLinks = (element) => {
				for (const link of element.links) this.scheduleUpdateLink(link.id);
			};
			this.listener.listen(view.events, "changeLanguage", this.scheduleUpdateAll);
			this.listener.listen(view.events, "changeHighlight", this.scheduleUpdateAll);
			const updateChangedRoutes = (changed, previous) => {
				changed.forEach((routing, linkId) => {
					if (previous.get(linkId) !== routing) this.scheduleUpdateLink(linkId);
				});
			};
			this.listener.listen(view.events, "updateRoutings", ({ previous }) => {
				const newRoutes = view.getRoutings();
				updateChangedRoutes(newRoutes, previous);
				updateChangedRoutes(previous, newRoutes);
			});
			this.listener.listen(view.model.events, "changeCells", (e) => {
				if (e.updateAll) this.scheduleUpdateAll();
				else {
					if (e.changedElement) scheduleUpdateElementLinks(e.changedElement);
					if (e.changedLinks) for (const link of e.changedLinks) this.scheduleUpdateLink(link.id);
				}
			});
			this.listener.listen(view.model.events, "elementEvent", ({ data }) => {
				const elementEvent = data.changePosition || data.changeSize;
				if (!elementEvent) return;
				scheduleUpdateElementLinks(elementEvent.source);
			});
			this.listener.listen(view.model.events, "linkEvent", ({ data }) => {
				const linkEvent = data.changeData || data.changeLayoutOnly || data.changeVertices || data.changeLinkState;
				if (linkEvent) this.scheduleUpdateLink(linkEvent.source.id);
			});
			this.listener.listen(view.model.events, "linkTypeEvent", ({ data }) => {
				const linkTypeEvent = data.changeLabel || data.changeVisibility;
				if (!linkTypeEvent) return;
				const linkTypeId = linkTypeEvent.source.id;
				for (const link of view.model.linksOfType(linkTypeId)) this.scheduleUpdateLink(link.id);
			});
			this.listener.listen(view.events, "syncUpdate", ({ layer }) => {
				if (layer !== RenderingLayer.Link) return;
				this.delayedUpdate.runSynchronously();
			});
		}
		shouldComponentUpdate() {
			return false;
		}
		componentWillUnmount() {
			this.listener.stopListening();
			this.delayedUpdate.dispose();
		}
		scheduleUpdateLink(linkId) {
			if (this.updateState === 1) this.scheduledToUpdate.add(linkId);
			this.delayedUpdate.call(this.performUpdate);
		}
		popShouldUpdatePredicate() {
			const { updateState, scheduledToUpdate } = this;
			this.scheduledToUpdate = /* @__PURE__ */ new Set();
			this.updateState = 1;
			return updateState === 2 ? () => true : (link) => scheduledToUpdate.has(link.id);
		}
		render() {
			const { view } = this.props;
			const shouldUpdate = this.popShouldUpdatePredicate();
			return /* @__PURE__ */ react.createElement("g", { className: CLASS_NAME$24 }, this.getLinks().map((model) => /* @__PURE__ */ react.createElement(LinkView, {
				key: model.id,
				view,
				model,
				shouldUpdate: shouldUpdate(model),
				route: view.getRouting(model.id)
			})));
		}
	};
	function computeDeepNestedElements(grouping, groupId) {
		const deepChildren = {};
		function collectNestedItems(parentId) {
			deepChildren[parentId] = true;
			const children = grouping.get(parentId);
			if (!children) return;
			for (const element of children) {
				if (element.group !== parentId) continue;
				collectNestedItems(element.id);
			}
		}
		collectNestedItems(groupId);
		return deepChildren;
	}
	var LINK_CLASS = "graph-explorer-link";
	var LABEL_GROUPING_PRECISION = 100;
	var TEMPORARY_LABEL_LINES = /* @__PURE__ */ new Map();
	var LinkView = class extends react.Component {
		constructor(props, context) {
			super(props, context);
			this.onRemoveLinkVertex = (vertex) => {
				this.props.view.model.history.registerToUndo(restoreCapturedLinkGeometry(vertex.link));
				vertex.remove();
			};
			this.onBoundsUpdate = (newBounds) => {
				const { model } = this.props;
				model.setLabelBounds(newBounds);
			};
			this.grabLinkTemplate(this.props);
		}
		componentDidUpdate(nextProps) {
			if (this.linkType.id !== nextProps.model.typeId) this.grabLinkTemplate(nextProps);
		}
		shouldComponentUpdate(nextProps, _nextState) {
			return nextProps.shouldUpdate;
		}
		grabLinkTemplate(props) {
			this.linkType = props.view.model.getLinkType(props.model.typeId);
			this.template = props.view.createLinkTemplate(this.linkType);
		}
		render() {
			const { view, model, route } = this.props;
			const source = view.model.getElement(model.sourceId);
			const target = view.model.getElement(model.targetId);
			if (!(source && target)) return null;
			const verticesDefinedByUser = model.vertices || [];
			const polyline = computePolyline(source, target, route ? route.vertices : verticesDefinedByUser);
			const path = "M" + polyline.map(({ x, y }) => `${x},${y}`).join(" L");
			const { index: typeIndex, showLabel } = this.linkType;
			const style = this.template.renderLink(model);
			const pathAttributes = getPathAttributes(model, style);
			const className = `${LINK_CLASS} ${view.highlighter && !view.highlighter(model) ? `${LINK_CLASS}--blurred` : ""}`;
			return /* @__PURE__ */ react.createElement("g", {
				className,
				"data-link-id": model.id,
				"data-source-id": source.id,
				"data-target-id": target.id
			}, /* @__PURE__ */ react.createElement("path", {
				className: `${LINK_CLASS}__connection`,
				d: path,
				...pathAttributes,
				markerStart: `url(#${linkMarkerKey(typeIndex, true)})`,
				markerEnd: `url(#${linkMarkerKey(typeIndex, false)})`
			}), /* @__PURE__ */ react.createElement("path", {
				className: `${LINK_CLASS}__wrap`,
				d: path
			}), showLabel ? this.renderLabels(polyline, style) : void 0, this.renderVertices(verticesDefinedByUser, pathAttributes.stroke));
		}
		renderVertices(vertices, fill) {
			const elements = [];
			const vertexClass = `${LINK_CLASS}__vertex`;
			const vertexRadius = 10;
			let index = 0;
			for (const { x, y } of vertices) {
				elements.push(/* @__PURE__ */ react.createElement("circle", {
					key: index * 2,
					"data-vertex": index,
					className: vertexClass,
					cx: x,
					cy: y,
					r: vertexRadius,
					fill
				}));
				elements.push(/* @__PURE__ */ react.createElement(VertexTools, {
					key: index * 2 + 1,
					className: `${LINK_CLASS}__vertex-tools`,
					model: this.props.model,
					vertexIndex: index,
					vertexRadius,
					x,
					y,
					onRemove: this.onRemoveLinkVertex
				}));
				index++;
			}
			return /* @__PURE__ */ react.createElement("g", { className: `${LINK_CLASS}__vertices` }, elements);
		}
		renderLabels(polyline, style) {
			const { view, model, route } = this.props;
			const labels = computeLinkLabels(model, style, view);
			let textAnchor = "middle";
			if (route && route.labelTextAnchor) textAnchor = route.labelTextAnchor;
			const polylineLength = computePolylineLength(polyline);
			TEMPORARY_LABEL_LINES.clear();
			return /* @__PURE__ */ react.createElement("g", { className: `${LINK_CLASS}__labels` }, labels.map((label, index) => {
				const { x, y } = getPointAlongPolyline(polyline, polylineLength * label.offset);
				const groupKey = Math.round(label.offset * LABEL_GROUPING_PRECISION) / LABEL_GROUPING_PRECISION;
				const line = TEMPORARY_LABEL_LINES.get(groupKey) || 0;
				TEMPORARY_LABEL_LINES.set(groupKey, line + 1);
				return /* @__PURE__ */ react.createElement(LinkLabel, {
					key: index,
					x,
					y,
					line,
					label,
					textAnchor,
					onBoundsUpdate: index === 0 ? this.onBoundsUpdate : void 0
				});
			}));
		}
	};
	function computeLinkLabels(model, style, view) {
		const labels = [];
		const labelStyle = style.label || {};
		const labelTexts = labelStyle.attrs && labelStyle.attrs.text ? labelStyle.attrs.text.text : void 0;
		let text;
		let title = labelStyle.title;
		if (labelTexts && labelTexts.length > 0) text = view.selectLabel(labelTexts);
		else {
			const type = view.model.getLinkType(model.typeId);
			text = view.selectLabel(type.label) || {
				value: view.formatLabel(type.label, type.id),
				language: ""
			};
			if (title === void 0) title = `${text.value} ${view.formatIri(model.typeId)}`;
		}
		labels.push({
			offset: labelStyle.position || .5,
			text,
			title,
			attributes: {
				text: getLabelTextAttributes(labelStyle),
				rect: getLabelRectAttributes(labelStyle)
			}
		});
		if (style.properties) for (const property of style.properties) {
			if (!(property.attrs && property.attrs.text && property.attrs.text.text)) continue;
			labels.push({
				offset: property.position || .5,
				text: view.selectLabel(property.attrs.text.text),
				title: property.title,
				attributes: {
					text: getLabelTextAttributes(property),
					rect: getLabelRectAttributes(property)
				}
			});
		}
		return labels;
	}
	function getPathAttributes(model, style) {
		const connectionAttributes = style.connection || {};
		const defaultStrokeDasharray = model.layoutOnly ? "5,5" : void 0;
		const { fill = "none", stroke = "black", "stroke-width": strokeWidth, "stroke-dasharray": strokeDasharray = defaultStrokeDasharray } = connectionAttributes;
		return {
			fill,
			stroke,
			strokeWidth,
			strokeDasharray
		};
	}
	function getLabelTextAttributes(label) {
		const { fill = "black", stroke = "none", "stroke-width": strokeWidth = 0, "font-family": fontFamily = "\"Helvetica Neue\", \"Helvetica\", \"Arial\", sans-serif", "font-size": fontSize = "inherit", "font-weight": fontWeight = "bold" } = label.attrs ? label.attrs.text : {};
		return {
			fill,
			stroke,
			strokeWidth,
			fontFamily,
			fontSize,
			fontWeight
		};
	}
	function getLabelRectAttributes(label) {
		const { fill = "white", stroke = "none", "stroke-width": strokeWidth = 0 } = label.attrs && label.attrs.rect ? label.attrs.rect : {};
		return {
			fill,
			stroke,
			strokeWidth
		};
	}
	var GROUPED_LABEL_MARGIN = 2;
	var LinkLabel = class extends react.Component {
		constructor(props) {
			super(props);
			this.shouldUpdateBounds = true;
			this.onTextMount = (text) => {
				this.text = text;
			};
			this.state = {
				width: 0,
				height: 0
			};
		}
		render() {
			const { x, y, label, line, textAnchor } = this.props;
			const { width, height } = this.state;
			const { x: rectX, y: rectY } = this.getLabelRectangle(width, height);
			const transform = line === 0 ? void 0 : `translate(0, ${line * (height + GROUPED_LABEL_MARGIN)}px)`;
			return /* @__PURE__ */ react.createElement("g", { style: transform ? { transform } : void 0 }, label.title ? /* @__PURE__ */ react.createElement("title", null, label.title) : void 0, /* @__PURE__ */ react.createElement("rect", {
				x: rectX,
				y: rectY,
				width,
				height,
				style: label.attributes.rect
			}), /* @__PURE__ */ react.createElement("text", {
				ref: this.onTextMount,
				x,
				y,
				dy: "0.6ex",
				textAnchor,
				style: label.attributes.text
			}, label.text.value));
		}
		getLabelRectangle(width, height) {
			const { x, y, textAnchor } = this.props;
			let xOffset = 0;
			if (textAnchor === "middle") xOffset = -width / 2;
			else if (textAnchor === "end") xOffset = -width;
			return {
				x: x + xOffset,
				y: y - height / 2,
				width,
				height
			};
		}
		componentDidMount() {
			this.recomputeBounds(this.props);
		}
		componentWillUnmount() {
			const { onBoundsUpdate } = this.props;
			onBoundsUpdate(void 0);
		}
		componentDidUpdate(_nextProps) {
			this.shouldUpdateBounds = true;
		}
		UNSAFE_componentWillReceiveProps() {
			this.recomputeBounds(this.props);
		}
		recomputeBounds(_props) {
			if (this.shouldUpdateBounds) {
				const { onBoundsUpdate } = this.props;
				this.shouldUpdateBounds = false;
				const bounds = this.text.getBBox();
				if (onBoundsUpdate) onBoundsUpdate(this.getLabelRectangle(bounds.width, bounds.height));
				this.setState({
					width: bounds.width,
					height: bounds.height
				});
			}
		}
	};
	var VertexTools = class extends react.Component {
		constructor(..._args2) {
			super(..._args2);
			this.onRemoveVertex = (e) => {
				if (e.button !== 0) return;
				e.preventDefault();
				e.stopPropagation();
				const { onRemove, model, vertexIndex } = this.props;
				onRemove(new LinkVertex(model, vertexIndex));
			};
		}
		render() {
			const { className, vertexRadius, x, y } = this.props;
			const transform = `translate(${x + 2 * vertexRadius},${y - 2 * vertexRadius})scale(${vertexRadius})`;
			return /* @__PURE__ */ react.createElement("g", {
				className,
				transform,
				onMouseDown: this.onRemoveVertex
			}, /* @__PURE__ */ react.createElement("title", null, "Remove vertex"), /* @__PURE__ */ react.createElement("circle", { r: 1 }), /* @__PURE__ */ react.createElement("path", {
				d: "M-0.5,-0.5 L0.5,0.5 M0.5,-0.5 L-0.5,0.5",
				strokeWidth: 2 / vertexRadius
			}));
		}
	};
	var LinkMarkers = class extends react.Component {
		constructor(..._args3) {
			super(..._args3);
			this.listener = new EventObserver();
			this.delayedUpdate = new Debouncer();
		}
		render() {
			const { view } = this.props;
			const markers = [];
			view.getLinkTemplates().forEach((template, linkTypeId) => {
				const type = view.model.getLinkType(linkTypeId);
				if (!type) return;
				const typeIndex = type.index;
				if (template.markerSource) markers.push(/* @__PURE__ */ react.createElement(LinkMarker, {
					key: typeIndex * 2,
					linkTypeIndex: typeIndex,
					style: template.markerSource,
					isStartMarker: true
				}));
				if (template.markerTarget) markers.push(/* @__PURE__ */ react.createElement(LinkMarker, {
					key: typeIndex * 2 + 1,
					linkTypeIndex: typeIndex,
					style: template.markerTarget,
					isStartMarker: false
				}));
			});
			return /* @__PURE__ */ react.createElement("defs", null, markers);
		}
		componentDidMount() {
			const { view } = this.props;
			this.listener.listen(view.events, "syncUpdate", ({ layer }) => {
				if (layer !== RenderingLayer.Link) return;
				this.delayedUpdate.runSynchronously();
			});
			this.listener.listen(view.events, "changeLinkTemplates", () => {
				this.delayedUpdate.call(() => this.forceUpdate());
			});
		}
		shouldComponentUpdate() {
			return false;
		}
		componentWillUnmount() {
			this.listener.stopListening();
			this.delayedUpdate.dispose();
		}
	};
	var SVG_NAMESPACE$1 = "http://www.w3.org/2000/svg";
	var LinkMarker = class extends react.Component {
		constructor(..._args4) {
			super(..._args4);
			this.onMarkerMount = (marker) => {
				if (!marker) return;
				const { linkTypeIndex, isStartMarker, style } = this.props;
				marker.setAttribute("id", linkMarkerKey(linkTypeIndex, isStartMarker));
				marker.setAttribute("markerWidth", style.width.toString());
				marker.setAttribute("markerHeight", style.height.toString());
				marker.setAttribute("orient", "auto");
				const xOffset = isStartMarker ? 0 : style.width - 1;
				marker.setAttribute("refX", xOffset.toString());
				marker.setAttribute("refY", (style.height / 2).toString());
				marker.setAttribute("markerUnits", "userSpaceOnUse");
				const path = document.createElementNS(SVG_NAMESPACE$1, "path");
				path.setAttribute("d", style.d);
				if (style.fill !== void 0) path.setAttribute("fill", style.fill);
				if (style.stroke !== void 0) path.setAttribute("stroke", style.stroke);
				if (style.strokeWidth !== void 0) path.setAttribute("stroke-width", style.strokeWidth);
				marker.appendChild(path);
			};
		}
		render() {
			return /* @__PURE__ */ react.createElement("marker", { ref: this.onMarkerMount });
		}
		shouldComponentUpdate() {
			return false;
		}
	};
	//#endregion
	//#region src/graph-explorer/diagram/paper.tsx
	var CLASS_NAME$23 = "graph-explorer-paper";
	var Paper = class extends react.Component {
		constructor(..._args) {
			super(..._args);
			this.onMouseDown = (e) => {
				const { view, onPointerDown } = this.props;
				const cell = e.target instanceof Element ? findCell(e.target, e.currentTarget, view.model) : void 0;
				if (onPointerDown) onPointerDown(e, cell);
			};
		}
		render() {
			const { view, group, paperTransform, linkLayerWidgets, elementLayerWidgets } = this.props;
			const { width, height, originX, originY, scale, paddingX, paddingY } = paperTransform;
			const scaledWidth = width * scale;
			const scaledHeight = height * scale;
			const style = {
				width: scaledWidth + paddingX,
				height: scaledHeight + paddingY,
				marginLeft: paddingX,
				marginTop: paddingY,
				paddingRight: paddingX,
				paddingBottom: paddingY
			};
			const htmlTransformStyle = {
				position: "absolute",
				left: 0,
				top: 0,
				transform: `scale(${scale},${scale})translate(${originX}px,${originY}px)`
			};
			return /* @__PURE__ */ react.createElement("div", {
				className: CLASS_NAME$23,
				style,
				onMouseDown: this.onMouseDown
			}, /* @__PURE__ */ react.createElement(TransformedSvgCanvas, {
				className: `${CLASS_NAME$23}__canvas`,
				style: { overflow: "visible" },
				paperTransform
			}, /* @__PURE__ */ react.createElement(LinkMarkers, { view }), /* @__PURE__ */ react.createElement(LinkLayer, {
				view,
				links: view.model.links,
				group
			})), linkLayerWidgets, /* @__PURE__ */ react.createElement(ElementLayer, {
				view,
				group,
				style: htmlTransformStyle
			}), elementLayerWidgets);
		}
	};
	function findCell(bottom, top, model) {
		let target = bottom;
		let vertexIndex;
		while (true) {
			if (target instanceof Element) {
				if (target.hasAttribute("data-element-id")) return model.getElement(target.getAttribute("data-element-id"));
				else if (target.hasAttribute("data-link-id")) {
					const link = model.getLinkById(target.getAttribute("data-link-id"));
					return typeof vertexIndex === "number" ? new LinkVertex(link, vertexIndex) : link;
				} else if (target.hasAttribute("data-vertex")) vertexIndex = Number(target.getAttribute("data-vertex"));
			}
			if (!target || target === top) break;
			target = target.parentNode;
		}
	}
	var TransformedSvgCanvas = class TransformedSvgCanvas extends react.Component {
		static {
			this.SVG_STYLE = {
				position: "absolute",
				top: 0,
				left: 0
			};
		}
		render() {
			const { paperTransform, style, children, ...otherProps } = this.props;
			const { width, height, originX, originY, scale } = paperTransform;
			const scaledWidth = width * scale;
			const scaledHeight = height * scale;
			let svgStyle = TransformedSvgCanvas.SVG_STYLE;
			if (style) svgStyle = {
				...svgStyle,
				...style
			};
			return /* @__PURE__ */ react.createElement("svg", {
				width: scaledWidth,
				height: scaledHeight,
				style: svgStyle,
				...otherProps
			}, /* @__PURE__ */ react.createElement("g", { transform: `scale(${scale},${scale})translate(${originX},${originY})` }, children));
		}
	};
	/**
	* @returns scrollable pane size in non-scaled pane coords.
	*/
	function totalPaneSize(pt) {
		return {
			x: pt.width * pt.scale + pt.paddingX * 2,
			y: pt.height * pt.scale + pt.paddingY * 2
		};
	}
	/**
	* @returns scrollable pane top-left corner position in non-scaled pane coords.
	*/
	function paneTopLeft(pt) {
		return {
			x: -pt.paddingX,
			y: -pt.paddingY
		};
	}
	function paneFromPaperCoords(paper, pt) {
		return {
			x: (paper.x + pt.originX) * pt.scale,
			y: (paper.y + pt.originY) * pt.scale
		};
	}
	function paperFromPaneCoords(pane, pt) {
		return {
			x: pane.x / pt.scale - pt.originX,
			y: pane.y / pt.scale - pt.originY
		};
	}
	//#endregion
	//#region src/graph-explorer/viewUtils/toSvg.ts
	var SVG_NAMESPACE = "http://www.w3.org/2000/svg";
	/**
	* Padding (in px) for <foreignObject> elements of exported SVG to
	* mitigate issues with elements body overflow caused by missing styles
	* in exported image.
	*/
	var FOREIGN_OBJECT_SIZE_PADDING = 2;
	var BORDER_PADDING = 100;
	function toSVG(options) {
		return exportSVG(options).then((svg) => new XMLSerializer().serializeToString(svg));
	}
	function exportSVG(options) {
		const { contentBox: bbox, watermarkSvg } = options;
		const { svgClone, imageBounds } = clonePaperSvg(options, FOREIGN_OBJECT_SIZE_PADDING);
		const paddedWidth = bbox.width + 2 * BORDER_PADDING;
		const paddedHeight = bbox.height + 2 * BORDER_PADDING;
		if (options.preserveDimensions) {
			svgClone.setAttribute("width", paddedWidth.toString());
			svgClone.setAttribute("height", paddedHeight.toString());
		} else {
			svgClone.setAttribute("width", "100%");
			svgClone.setAttribute("height", "100%");
		}
		const viewBox = {
			x: bbox.x - BORDER_PADDING,
			y: bbox.y - BORDER_PADDING,
			width: paddedWidth,
			height: paddedHeight
		};
		svgClone.setAttribute("viewBox", `${viewBox.x} ${viewBox.y} ${viewBox.width} ${viewBox.height}`);
		addWatermark(svgClone, viewBox, watermarkSvg);
		const images = [];
		foreachNode(svgClone.querySelectorAll("img"), (node) => images.push(node));
		return Promise.all(images.map((img) => {
			const exportKey = img.getAttribute("export-key");
			img.removeAttribute("export-key");
			if (exportKey) {
				const { width, height } = imageBounds[exportKey];
				img.setAttribute("width", width.toString());
				img.setAttribute("height", height.toString());
				if (!options.convertImagesToDataUris) return Promise.resolve();
				return exportAsDataUri(img).then((dataUri) => {
					if (dataUri && dataUri !== "data:image/svg+xml,") img.src = dataUri;
				}).catch((err) => {
					console.warn("Failed to export image: " + img.src, err);
				});
			} else return Promise.resolve();
		})).then(() => {
			const exportedCssText = extractCSSFromDocument(svgClone);
			const exportedVariables = extractCSSVariables(options.paper.closest(".graph-explorer"));
			const defs = document.createElementNS("http://www.w3.org/2000/svg", "defs");
			defs.innerHTML = `<style>${exportedVariables}\n${exportedCssText}</style>`;
			svgClone.insertBefore(defs, svgClone.firstChild);
			if (options.elementsToRemoveSelector) foreachNode(svgClone.querySelectorAll(options.elementsToRemoveSelector), (node) => node.remove());
			return svgClone;
		});
	}
	function addWatermark(svg, viewBox, watermarkSvg) {
		const WATERMARK_CLASS = "graph-explorer-exported-watermark";
		const WATERMARK_MAX_WIDTH = 120;
		const WATERMARK_PADDING = 20;
		const image = document.createElementNS(SVG_NAMESPACE, "image");
		image.setAttributeNS("http://www.w3.org/1999/xlink", "href", watermarkSvg);
		image.setAttribute("class", WATERMARK_CLASS);
		const width = Math.min(viewBox.width * .2, WATERMARK_MAX_WIDTH);
		const x = viewBox.x + viewBox.width - width - WATERMARK_PADDING;
		const y = viewBox.y + WATERMARK_PADDING;
		image.setAttribute("x", x.toString());
		image.setAttribute("y", y.toString());
		image.setAttribute("width", width.toString());
		image.setAttribute("opacity", "0.3");
		svg.insertBefore(image, svg.firstChild);
	}
	function forEachStyleRule(callback) {
		for (let i = 0; i < document.styleSheets.length; i++) {
			let rules;
			try {
				const cssSheet = document.styleSheets[i];
				rules = cssSheet.cssRules || cssSheet.rules;
				if (!rules) continue;
			} catch (_e) {
				continue;
			}
			for (let j = 0; j < rules.length; j++) {
				const rule = rules[j];
				if (rule instanceof CSSStyleRule) callback(rule);
			}
		}
	}
	/**
	* The exported SVG is detached from the workspace, so CSS custom properties
	* (the design tokens) declared on the workspace root are not in scope and every
	* `var(--…)` reference in the exported rules would resolve to nothing, dropping
	* colours, radii and shadows. Re-declare the resolved values on the exported
	* root so the export matches what is on the canvas.
	*/
	function extractCSSVariables(source) {
		if (!source) return "";
		const computed = getComputedStyle(source);
		const declarations = /* @__PURE__ */ new Map();
		forEachStyleRule((rule) => {
			for (let i = 0; i < rule.style.length; i++) {
				const property = rule.style.item(i);
				if (!property.startsWith("--") || declarations.has(property)) continue;
				const value = computed.getPropertyValue(property).trim();
				if (value) declarations.set(property, value);
			}
		});
		if (declarations.size === 0) return "";
		return `svg { ${Array.from(declarations, ([name, value]) => `${name}: ${value};`).join(" ")} }`;
	}
	function extractCSSFromDocument(targetSubtree) {
		const exportedRules = /* @__PURE__ */ new Set();
		forEachStyleRule((rule) => {
			try {
				if (targetSubtree.querySelector(rule.selectorText)) exportedRules.add(rule);
			} catch (_e) {}
		});
		const exportedCssTexts = [];
		exportedRules.forEach((rule) => exportedCssTexts.push(rule.cssText));
		return exportedCssTexts.join("\n");
	}
	function clonePaperSvg(options, elementSizePadding) {
		const { model, paper, getOverlayedElement } = options;
		const svgClone = paper.cloneNode(true);
		svgClone.removeAttribute("class");
		svgClone.removeAttribute("style");
		function findViewport() {
			let child = svgClone.firstChild;
			while (child) {
				if (child instanceof SVGGElement) return child;
				child = child.nextSibling;
			}
		}
		const viewport = findViewport();
		viewport.removeAttribute("transform");
		const imageBounds = {};
		for (const element of model.elements) {
			const modelId = element.id;
			const overlayedView = getOverlayedElement(modelId);
			if (!overlayedView) continue;
			const elementRoot = document.createElementNS(SVG_NAMESPACE, "g");
			const overlayedViewContent = overlayedView.firstChild.cloneNode(true);
			elementRoot.setAttribute("class", "graph-explorer-exported-element");
			const newRoot = document.createElementNS(SVG_NAMESPACE, "foreignObject");
			newRoot.appendChild(overlayedViewContent);
			const { x, y, width, height } = boundsOf(element);
			newRoot.setAttribute("transform", `translate(${x},${y})`);
			newRoot.setAttribute("width", (width + elementSizePadding).toString());
			newRoot.setAttribute("height", (height + elementSizePadding).toString());
			elementRoot.appendChild(newRoot);
			viewport.appendChild(elementRoot);
			const clonedNodes = overlayedViewContent.querySelectorAll("img");
			foreachNode(overlayedView.querySelectorAll("img"), (img, index) => {
				const exportKey = (0, lodash.uniqueId)("export-key-");
				clonedNodes[index].setAttribute("export-key", exportKey);
				imageBounds[exportKey] = {
					width: img.clientWidth,
					height: img.clientHeight
				};
			});
		}
		return {
			svgClone,
			imageBounds
		};
	}
	function exportAsDataUri(original) {
		const url = original.src;
		if (!url || url.startsWith("data:")) return Promise.resolve(url);
		return loadCrossOriginImage(original.src).then((image) => {
			const canvas = document.createElement("canvas");
			canvas.width = image.width;
			canvas.height = image.height;
			canvas.getContext("2d").drawImage(image, 0, 0);
			const extensionMatch = url.match(/\.([a-zA-Z0-9]+)[^.a-zA-Z0-9]?[^.]*$/);
			const extension = extensionMatch ? extensionMatch[1].toLowerCase() : "png";
			try {
				const mimeType = "image/" + (extension === "jpg" ? "jpeg" : extension);
				const dataUri = canvas.toDataURL(mimeType);
				return Promise.resolve(dataUri);
			} catch (_e) {
				if (extension !== "svg") return Promise.reject("Failed to convert image to data URI");
				return fetch(url).then((response) => response.text()).then((svg) => svg.length > 0 ? "data:image/svg+xml," + encodeURIComponent(svg) : "");
			}
		});
	}
	function loadCrossOriginImage(src) {
		const image = new Image();
		image.crossOrigin = "anonymous";
		const promise = new Promise((resolve, reject) => {
			image.onload = () => resolve(image);
			image.onerror = (ev) => reject(ev);
		});
		image.src = src;
		return promise;
	}
	function foreachNode(nodeList, callback) {
		for (let i = 0; i < nodeList.length; i++) callback(nodeList[i], i);
	}
	var MAX_CANVAS_LENGTH = 4096;
	async function toDataURL(options) {
		const { paper: _paper, mimeType = "image/png" } = options;
		const svg = await exportSVG({
			...options,
			convertImagesToDataUris: true,
			mockImages: false,
			preserveDimensions: true
		});
		const svgBox = {
			width: Number(svg.getAttribute("width")),
			height: Number(svg.getAttribute("height"))
		};
		const { innerSize, outerSize, offset } = computeAutofit(svgBox, typeof options.width === "number" || typeof options.height === "number" ? {
			width: options.width,
			height: options.height
		} : fallbackContainerSize(svgBox));
		svg.setAttribute("width", innerSize.width.toString());
		svg.setAttribute("height", innerSize.height.toString());
		const svgString = new XMLSerializer().serializeToString(svg);
		const { canvas, context } = createCanvas(outerSize.width, outerSize.height, options.backgroundColor);
		const image = await loadImage("data:image/svg+xml," + encodeURIComponent(svgString));
		context.drawImage(image, offset.x, offset.y, innerSize.width, innerSize.height);
		return canvas.toDataURL(mimeType, options.quality);
		function createCanvas(canvasWidth, canvasHeight, backgroundColor) {
			const cnv = document.createElement("canvas");
			cnv.width = canvasWidth;
			cnv.height = canvasHeight;
			const cnt = cnv.getContext("2d");
			if (backgroundColor) {
				cnt.fillStyle = backgroundColor;
				cnt.fillRect(0, 0, canvasWidth, canvasHeight);
			}
			return {
				canvas: cnv,
				context: cnt
			};
		}
	}
	function loadImage(source) {
		return new Promise((resolve, reject) => {
			const image = new Image();
			image.onload = function() {
				resolve(image);
			};
			image.onerror = function(ev) {
				reject(ev);
			};
			image.src = source;
		});
	}
	function computeAutofit(itemSize, containerSize) {
		const fit = fitRectKeepingAspectRatio(itemSize.width, itemSize.height, containerSize.width, containerSize.height);
		const innerSize = {
			width: Math.floor(fit.width),
			height: Math.floor(fit.height)
		};
		const outerSize = {
			width: typeof containerSize.width === "number" ? containerSize.width : innerSize.width,
			height: typeof containerSize.height === "number" ? containerSize.height : innerSize.height
		};
		return {
			innerSize,
			outerSize,
			offset: {
				x: Math.round((outerSize.width - innerSize.width) / 2),
				y: Math.round((outerSize.height - innerSize.height) / 2)
			}
		};
	}
	function fallbackContainerSize(itemSize) {
		const maxResolutionScale = Math.min(MAX_CANVAS_LENGTH / itemSize.width, MAX_CANVAS_LENGTH / itemSize.height);
		const resolutionScale = Math.min(2, maxResolutionScale);
		return {
			width: Math.floor(itemSize.width * resolutionScale),
			height: Math.floor(itemSize.height * resolutionScale)
		};
	}
	function fitRectKeepingAspectRatio(sourceWidth, sourceHeight, targetWidth, targetHeight) {
		if (!(typeof targetWidth === "number" || typeof targetHeight === "number")) return {
			width: sourceWidth,
			height: sourceHeight
		};
		const sourceAspectRatio = sourceWidth / sourceHeight;
		targetWidth = typeof targetWidth === "number" ? targetWidth : targetHeight * sourceAspectRatio;
		targetHeight = typeof targetHeight === "number" ? targetHeight : targetWidth / sourceAspectRatio;
		if (targetHeight * sourceAspectRatio <= targetWidth) return {
			width: targetHeight * sourceAspectRatio,
			height: targetHeight
		};
		else return {
			width: targetWidth,
			height: targetWidth / sourceAspectRatio
		};
	}
	/**
	* Creates and returns a blob from a data URL (either base64 encoded or not).
	*
	* @param {string} dataURL The data URL to convert.
	* @return {Blob} A blob representing the array buffer data.
	*/
	function dataURLToBlob(dataURL) {
		const BASE64_MARKER = ";base64,";
		if (dataURL.indexOf(BASE64_MARKER) === -1) {
			const parts = dataURL.split(",");
			const contentType = parts[0].split(":")[1];
			const raw = decodeURIComponent(parts[1]);
			return new Blob([raw], { type: contentType });
		} else {
			const parts = dataURL.split(BASE64_MARKER);
			const contentType = parts[0].split(":")[1];
			const raw = window.atob(parts[1]);
			const rawLength = raw.length;
			const uInt8Array = new Uint8Array(rawLength);
			for (let i = 0; i < rawLength; ++i) uInt8Array[i] = raw.charCodeAt(i);
			return new Blob([uInt8Array], { type: contentType });
		}
	}
	//#endregion
	//#region src/graph-explorer/diagram/paperArea.tsx
	var PaperAreaContext = react.createContext(null);
	var CLASS_NAME$22 = "graph-explorer-paper-area";
	var DEFAULT_ANIMATION_DURATION = 500;
	var LEFT_MOUSE_BUTTON = 0;
	var MIDDLE_MOUSE_BUTTON = 1;
	/** Spacing of the background dot grid, in paper (unscaled) coordinates. */
	var GRID_STEP = 24;
	var PaperArea = class extends react.Component {
		get zoomOptions() {
			const { min = .2, max = 2, step = .1, maxFit = 1, fitPadding = 20, requireCtrl = true } = this.props.zoomOptions || {};
			return {
				min,
				max,
				step,
				maxFit,
				fitPadding,
				requireCtrl
			};
		}
		constructor(props, context) {
			super(props, context);
			this.listener = new EventObserver();
			this.source = new EventSource();
			this.events = this.source;
			this.widgets = {};
			this.pageSize = {
				x: 1500,
				y: 800
			};
			this.cssAnimations = 0;
			this.delayedPaperAdjust = new Debouncer();
			this.onOuterMount = (outer) => {
				this.outer = outer;
			};
			this.onAreaMount = (area) => {
				this.area = area;
			};
			this.onWidgetsMouseDown = (e) => {
				e.stopPropagation();
			};
			this.adjustPaper = (callback) => {
				const { clientWidth, clientHeight } = this.area;
				const adjusted = {
					...this.computeAdjustedBox(),
					paddingX: Math.ceil(clientWidth),
					paddingY: Math.ceil(clientHeight)
				};
				const previous = this.state;
				if (!(adjusted.paperWidth === previous.paperWidth && adjusted.paperHeight === previous.paperHeight && adjusted.originX === previous.originX && adjusted.originY === previous.originY && adjusted.paddingX === previous.paddingX && adjusted.paddingY === previous.paddingY)) {
					this.scrollBeforeUpdate = {
						left: this.area.scrollLeft,
						top: this.area.scrollTop
					};
					this.setState(adjusted, callback);
				} else if (callback) callback();
			};
			this.onPaperPointerDown = (e, cell) => {
				if (this.movingState) return;
				const restore = RestoreGeometry.capture(this.props.view.model);
				const batch = this.props.view.model.history.startBatch(restore.title);
				if (cell && e.button === LEFT_MOUSE_BUTTON) if (cell instanceof Element$1) {
					e.preventDefault();
					this.startMoving(e, cell);
					this.listenToPointerMove(e, cell, batch, restore);
				} else {
					e.preventDefault();
					this.listenToPointerMove(e, cell, batch, restore);
				}
				else {
					e.preventDefault();
					this.listenToPointerMove(e, void 0, batch, restore);
				}
			};
			this.onAreaPointerDown = (e) => {
				if (e.target === this.area) this.onPaperPointerDown(e, void 0);
			};
			this.onPointerMove = (e) => {
				if (!this.movingState || this.scrollBeforeUpdate) return;
				const { origin, target, panning } = this.movingState;
				const pageOffsetX = e.pageX - origin.pageX;
				const pageOffsetY = e.pageY - origin.pageY;
				if (Math.abs(pageOffsetX) >= 1 && Math.abs(pageOffsetY) >= 1) this.movingState.pointerMoved = true;
				if (typeof target === "undefined") {
					if (panning) {
						this.area.scrollLeft = this.panningScrollOrigin.scrollLeft - pageOffsetX;
						this.area.scrollTop = this.panningScrollOrigin.scrollTop - pageOffsetY;
					}
					this.source.trigger("pointerMove", {
						source: this,
						sourceEvent: e,
						target,
						panning
					});
				} else if (target instanceof Element$1) {
					const { x, y } = this.pageToPaperCoords(e.pageX, e.pageY);
					const { pointerX, pointerY, elementX, elementY } = this.movingElementOrigin;
					target.setPosition({
						x: elementX + x - pointerX,
						y: elementY + y - pointerY
					});
					this.source.trigger("pointerMove", {
						source: this,
						sourceEvent: e,
						target,
						panning
					});
					this.props.view.performSyncUpdate();
				} else if (target instanceof Link) {
					const location = this.pageToPaperCoords(e.pageX, e.pageY);
					const linkVertex = this.generateLinkVertex(target, location);
					linkVertex.createAt(location);
					this.movingState.target = linkVertex;
				} else if (target instanceof LinkVertex) {
					const location = this.pageToPaperCoords(e.pageX, e.pageY);
					target.moveTo(location);
					this.source.trigger("pointerMove", {
						source: this,
						sourceEvent: e,
						target,
						panning
					});
					this.props.view.performSyncUpdate();
				}
			};
			this.stopListeningToPointerMove = (e) => {
				const movingState = this.movingState;
				this.movingState = void 0;
				if (movingState) {
					document.removeEventListener("mousemove", this.onPointerMove);
					document.removeEventListener("mouseup", this.stopListeningToPointerMove);
				}
				if (e && movingState) {
					const { pointerMoved, target, batch, restoreGeometry } = movingState;
					this.source.trigger("pointerUp", {
						source: this,
						sourceEvent: e,
						target,
						panning: movingState.panning,
						triggerAsClick: !pointerMoved
					});
					const restore = restoreGeometry.filterOutUnchanged();
					if (restore.hasChanges()) batch.history.registerToUndo(restore);
					batch.store();
				}
			};
			this.onWheel = (e) => {
				if (this.shouldStartZooming(e)) {
					e.preventDefault();
					const delta = Math.max(-1, Math.min(1, e.deltaY || e.deltaX));
					const pivot = this.pageToPaperCoords(e.pageX, e.pageY);
					this.zoomBy(-delta * .1, { pivot });
				}
			};
			this.onDragOver = (e) => {
				if (e.preventDefault) e.preventDefault();
				e.dataTransfer.dropEffect = "move";
				const { x: _x, y: _y } = clientCoordsFor(this.area, e);
				return false;
			};
			this.onDragDrop = (e) => {
				if (this.props.onDragDrop) {
					const { x, y } = clientCoordsFor(this.area, e);
					const paperPosition = this.clientToPaperCoords(x, y);
					this.props.onDragDrop(e, paperPosition);
				}
			};
			this.onScroll = () => {
				this.source.trigger("scroll", { source: this });
			};
			this.applyViewportState = (targetState) => {
				const scale = targetState.scale.x;
				const paperCenter = targetState.center;
				this.setState({ scale }, () => {
					const { originX, originY, paddingX, paddingY } = this.state;
					const scrollCenterX = (paperCenter.x + originX) * scale;
					const scrollCenterY = (paperCenter.y + originY) * scale;
					const { clientWidth, clientHeight } = this.area;
					this.area.scrollLeft = scrollCenterX - clientWidth / 2 + paddingX;
					this.area.scrollTop = scrollCenterY - clientHeight / 2 + paddingY;
					if (this.props.onZoom) this.props.onZoom(scale, scale);
				});
			};
			this.state = {
				paperWidth: this.pageSize.x,
				paperHeight: this.pageSize.y,
				originX: 0,
				originY: 0,
				scale: 1,
				paddingX: 0,
				paddingY: 0,
				renderedWidgets: []
			};
		}
		render() {
			const { view, watermarkSvg, watermarkUrl } = this.props;
			const { paperWidth, paperHeight, originX, originY, scale, paddingX, paddingY, renderedWidgets } = this.state;
			const paperTransform = {
				width: paperWidth,
				height: paperHeight,
				originX,
				originY,
				scale,
				paddingX,
				paddingY
			};
			const widgetProps = {
				paperArea: this,
				paperTransform
			};
			let areaClass = `${CLASS_NAME$22}__area`;
			if (this.props.hideScrollBars) areaClass += ` ${CLASS_NAME$22}--hide-scrollbars`;
			let componentClass = CLASS_NAME$22;
			if (this.isAnimatingGraph()) componentClass += ` ${CLASS_NAME$22}--animated`;
			const gridStep = GRID_STEP * scale;
			const gridStyle = {
				backgroundSize: `${gridStep}px ${gridStep}px`,
				backgroundPosition: `${paddingX + originX * scale}px ${paddingY + originY * scale}px`
			};
			return /* @__PURE__ */ react.createElement(PaperAreaContext.Provider, { value: { paperArea: {
				paperArea: this,
				view
			} } }, /* @__PURE__ */ react.createElement("div", {
				className: componentClass,
				ref: this.onOuterMount
			}, /* @__PURE__ */ react.createElement("div", {
				className: areaClass,
				ref: this.onAreaMount,
				style: gridStyle,
				onMouseDown: this.onAreaPointerDown
			}, /* @__PURE__ */ react.createElement(Paper, {
				view,
				paperTransform,
				onPointerDown: this.onPaperPointerDown,
				linkLayerWidgets: /* @__PURE__ */ react.createElement("div", {
					className: `${CLASS_NAME$22}__widgets`,
					onMouseDown: this.onWidgetsMouseDown
				}, renderedWidgets.filter((w) => w.attachment === WidgetAttachment.OverLinks).map((widget) => react.cloneElement(widget.element, widgetProps))),
				elementLayerWidgets: /* @__PURE__ */ react.createElement("div", {
					className: `${CLASS_NAME$22}__widgets`,
					onMouseDown: this.onWidgetsMouseDown
				}, renderedWidgets.filter((w) => w.attachment === WidgetAttachment.OverElements).map((widget) => react.cloneElement(widget.element, widgetProps)))
			}), watermarkSvg ? /* @__PURE__ */ react.createElement("a", {
				href: watermarkUrl,
				target: "_blank",
				rel: "noopener noreferrer"
			}, /* @__PURE__ */ react.createElement("img", {
				className: `${CLASS_NAME$22}__watermark`,
				src: watermarkSvg,
				draggable: false
			})) : null), renderedWidgets.filter((w) => w.attachment === WidgetAttachment.Viewport).map((widget) => {
				return react.cloneElement(widget.element, widgetProps);
			})));
		}
		componentDidMount() {
			this.adjustPaper(() => this.centerTo());
			const { view } = this.props;
			const delayedAdjust = () => this.delayedPaperAdjust.call(this.adjustPaper);
			this.listener.listen(view.model.events, "changeCells", delayedAdjust);
			this.listener.listen(view.model.events, "elementEvent", ({ data }) => {
				if (data.changePosition || data.changeSize) delayedAdjust();
			});
			this.listener.listen(view.model.events, "linkEvent", ({ data }) => {
				if (data.changeVertices) delayedAdjust();
			});
			this.listener.listen(view.events, "syncUpdate", ({ layer }) => {
				if (layer !== RenderingLayer.PaperArea) return;
				this.delayedPaperAdjust.runSynchronously();
			});
			this.listener.listen(view.events, "updateWidgets", ({ widgets }) => {
				this.updateWidgets(widgets);
			});
			this.area.addEventListener("dragover", this.onDragOver);
			this.area.addEventListener("drop", this.onDragDrop);
			this.area.addEventListener("scroll", this.onScroll);
			this.area.addEventListener("wheel", this.onWheel, { passive: false });
		}
		componentDidUpdate(prevProps, prevState) {
			if (this.scrollBeforeUpdate) {
				const { scale, originX, originY, paddingX, paddingY } = this.state;
				const scrollX = (originX - prevState.originX) * scale + (paddingX - prevState.paddingX);
				const scrollY = (originY - prevState.originY) * scale + (paddingY - prevState.paddingY);
				const scrollLeft = this.scrollBeforeUpdate.left + scrollX;
				const scrollTop = this.scrollBeforeUpdate.top + scrollY;
				this.area.scrollLeft = scrollLeft;
				this.area.scrollTop = scrollTop;
				this.scrollBeforeUpdate = void 0;
			}
		}
		componentWillUnmount() {
			this.stopListeningToPointerMove();
			this.listener.stopListening();
			this.area.removeEventListener("dragover", this.onDragOver);
			this.area.removeEventListener("drop", this.onDragDrop);
			this.area.removeEventListener("scroll", this.onScroll);
			this.area.removeEventListener("wheel", this.onWheel);
		}
		updateWidgets(update) {
			this.widgets = {
				...this.widgets,
				...update
			};
			const renderedWidgets = Object.keys(this.widgets).filter((key) => this.widgets[key]).map((key) => {
				const widget = this.widgets[key];
				const element = react.cloneElement(widget.element, { key });
				return {
					...widget,
					element
				};
			});
			this.setState({ renderedWidgets });
		}
		pageToPaperCoords(pageX, pageY) {
			const { left, top } = this.area.getBoundingClientRect();
			return this.clientToPaperCoords(pageX - (left + window.pageXOffset), pageY - (top + window.pageYOffset));
		}
		clientToPaperCoords(areaClientX, areaClientY) {
			const { x: paneX, y: paneY } = this.clientToScrollablePaneCoords(areaClientX, areaClientY);
			return this.scrollablePaneToPaperCoords(paneX, paneY);
		}
		clientToScrollablePaneCoords(areaClientX, areaClientY) {
			const { paddingX, paddingY } = this.state;
			return {
				x: areaClientX + this.area.scrollLeft - paddingX,
				y: areaClientY + this.area.scrollTop - paddingY
			};
		}
		scrollablePaneToPaperCoords(paneX, paneY) {
			const { scale, originX, originY } = this.state;
			return {
				x: paneX / scale - originX,
				y: paneY / scale - originY
			};
		}
		paperToScrollablePaneCoords(paperX, paperY) {
			const { scale, originX, originY } = this.state;
			return {
				x: (paperX + originX) * scale,
				y: (paperY + originY) * scale
			};
		}
		/** Returns bounding box of paper content in paper coordinates. */
		getContentFittingBox() {
			const { elements, links } = this.props.view.model;
			return getContentFittingBox(elements, links);
		}
		/** Returns paper size in paper coordinates. */
		getPaperSize() {
			const { paperWidth: width, paperHeight: height, scale } = this.state;
			return {
				width: width / scale,
				height: height / scale
			};
		}
		getAreaMetrics() {
			const { clientWidth, clientHeight, offsetWidth, offsetHeight } = this.area;
			return {
				clientWidth,
				clientHeight,
				offsetWidth,
				offsetHeight
			};
		}
		computeAdjustedBox() {
			const bbox = this.getContentFittingBox();
			const bboxLeft = bbox.x;
			const bboxTop = bbox.y;
			const bboxRight = bbox.x + bbox.width;
			const bboxBottom = bbox.y + bbox.height;
			const { x: gridWidth, y: gridHeight } = this.pageSize;
			const bboxGrid = {
				left: Math.floor(bboxLeft / gridWidth),
				top: Math.floor(bboxTop / gridHeight),
				right: Math.ceil(bboxRight / gridWidth),
				bottom: Math.ceil(bboxBottom / gridHeight)
			};
			const originX = -bboxGrid.left * gridWidth;
			const originY = -bboxGrid.top * gridHeight;
			return {
				paperWidth: Math.max(bboxGrid.right - bboxGrid.left, 1) * gridWidth,
				paperHeight: Math.max(bboxGrid.bottom - bboxGrid.top, 1) * gridHeight,
				originX,
				originY
			};
		}
		shouldStartZooming(e) {
			return Boolean(e.ctrlKey) && Boolean(this.zoomOptions.requireCtrl) || !this.zoomOptions.requireCtrl;
		}
		shouldStartPanning(e) {
			if (e.button === MIDDLE_MOUSE_BUTTON) return true;
			const modifierPressed = e.ctrlKey || e.shiftKey || e.altKey;
			return e.button === LEFT_MOUSE_BUTTON && !modifierPressed;
		}
		startMoving(e, element) {
			const { x: pointerX, y: pointerY } = this.pageToPaperCoords(e.pageX, e.pageY);
			const { x: elementX, y: elementY } = element.position;
			this.movingElementOrigin = {
				pointerX,
				pointerY,
				elementX,
				elementY
			};
		}
		startPanning(_event) {
			const { scrollLeft, scrollTop } = this.area;
			this.panningScrollOrigin = {
				scrollLeft,
				scrollTop
			};
			this.clearTextSelectionInArea();
		}
		/** Clears accidental text selection in the diagram area. */
		clearTextSelectionInArea() {
			if (document.getSelection) {
				const selection = document.getSelection();
				if (selection.removeAllRanges) selection.removeAllRanges();
			}
		}
		generateLinkVertex(link, location) {
			const previous = link.vertices;
			const vertices = previous ? [...previous] : [];
			const model = this.props.view.model;
			return new LinkVertex(link, findNearestSegmentIndex(computePolyline(model.getElement(link.sourceId), model.getElement(link.targetId), vertices), location));
		}
		listenToPointerMove(event, cell, batch, restoreGeometry) {
			if (this.movingState) return;
			const panning = cell === void 0 && this.shouldStartPanning(event);
			if (panning) this.startPanning(event);
			const { pageX, pageY } = event;
			this.movingState = {
				origin: {
					pageX,
					pageY
				},
				target: cell,
				panning,
				pointerMoved: false,
				batch,
				restoreGeometry
			};
			document.addEventListener("mousemove", this.onPointerMove);
			document.addEventListener("mouseup", this.stopListeningToPointerMove);
			this.source.trigger("pointerDown", {
				source: this,
				sourceEvent: event,
				target: cell,
				panning
			});
		}
		centerTo(paperPosition, options = {}) {
			const { paperWidth, paperHeight } = this.state;
			const viewportState = { center: paperPosition || {
				x: paperWidth / 2,
				y: paperHeight / 2
			} };
			return this.setViewportState(viewportState, options);
		}
		centerContent(options = {}) {
			const bbox = this.getContentFittingBox();
			return this.centerTo({
				x: bbox.x + bbox.width / 2,
				y: bbox.y + bbox.height / 2
			}, options);
		}
		getScale() {
			return this.state.scale;
		}
		setScale(value, options) {
			let scale = value;
			const { min, max } = this.zoomOptions;
			scale = Math.max(scale, min);
			scale = Math.min(scale, max);
			let viewportState;
			if (options && options.pivot) {
				const { x, y } = options.pivot;
				const paperCenter = this.clientToPaperCoords(this.area.clientWidth / 2, this.area.clientHeight / 2);
				const previousScale = this.state.scale;
				const scaledBy = scale / previousScale;
				viewportState = {
					center: {
						x: x - (x - paperCenter.x) / scaledBy,
						y: y - (y - paperCenter.y) / scaledBy
					},
					scale: {
						x: scale,
						y: scale
					}
				};
			} else viewportState = { scale: {
				x: scale,
				y: scale
			} };
			return this.setViewportState(viewportState, options);
		}
		zoomBy(value, options) {
			return this.setScale(this.getScale() + value, options);
		}
		zoomIn(scaleOptions) {
			return this.zoomBy(this.zoomOptions.step, scaleOptions);
		}
		zoomOut(scaleOptions) {
			return this.zoomBy(-this.zoomOptions.step, scaleOptions);
		}
		zoomToFit(options = {}) {
			if (options.elements && options.elements.size === 0) return;
			if (this.props.view.model.elements.length === 0) return this.centerTo();
			let elements;
			if (options.elements) {
				const selectionElements = [];
				options.elements.forEach((el) => selectionElements.push(el));
				elements = selectionElements;
			} else elements = this.props.view.model.elements;
			const bbox = getContentFittingBox(elements, []);
			return this.zoomToFitRect(bbox, options);
		}
		zoomToFitRect(bbox, options = {}) {
			const { clientWidth, clientHeight } = this.area;
			if (bbox.width === 0) return;
			const { width } = fitRectKeepingAspectRatio(bbox.width, bbox.height, clientWidth, clientHeight);
			let scale = width / bbox.width;
			const { min, maxFit } = this.zoomOptions;
			scale = Math.max(scale, min);
			scale = Math.min(scale, maxFit);
			const viewPortState = {
				center: {
					x: bbox.x + bbox.width / 2,
					y: bbox.y + bbox.height / 2
				},
				scale: {
					x: scale,
					y: scale
				}
			};
			return this.setViewportState(viewPortState, options);
		}
		makeToSVGOptions() {
			const svg = this.area.querySelector(".graph-explorer-paper__canvas");
			if (!svg) throw new Error("Cannot find SVG canvas to export");
			return {
				model: this.props.view.model,
				paper: svg,
				contentBox: this.getContentFittingBox(),
				getOverlayedElement: (id) => this.area.querySelector(`[data-element-id='${id}']`),
				preserveDimensions: true,
				convertImagesToDataUris: true,
				elementsToRemoveSelector: ".graph-explorer-link__vertex-tools",
				watermarkSvg: this.props.watermarkSvg
			};
		}
		exportSVG() {
			return toSVG(this.makeToSVGOptions());
		}
		exportPNG(options) {
			return toDataURL({
				...options,
				...this.makeToSVGOptions()
			});
		}
		isAnimatingGraph() {
			return this.cssAnimations > 0;
		}
		/**
		* Starts animation for graph elements and links.
		*
		* @param setupChanges immediately called function to perform animatable changes on graph
		* @param duration animation duration in milliseconds (requires custom CSS to override)
		* @returns promise which resolves when this animation ends
		*/
		animateGraph(setupChanges, duration) {
			this.changeGraphAnimationCount(1);
			setupChanges();
			return delay(typeof duration === "number" ? duration : DEFAULT_ANIMATION_DURATION).then(() => this.onGraphAnimationEnd());
		}
		onGraphAnimationEnd() {
			this.changeGraphAnimationCount(-1);
		}
		changeGraphAnimationCount(change) {
			const newValue = this.cssAnimations + change;
			if (newValue < 0) return;
			const previous = this.isAnimatingGraph();
			this.cssAnimations = newValue;
			if (previous !== this.isAnimatingGraph()) {
				this.forceUpdate();
				this.source.trigger("changeAnimatingGraph", {
					source: this,
					previous
				});
			}
		}
		get viewportState() {
			const { clientWidth, clientHeight } = this.area;
			const { originX, originY, paddingX, paddingY, scale } = this.state;
			const scrollCenterX = this.area.scrollLeft + clientWidth / 2 - paddingX;
			const scrollCenterY = this.area.scrollTop + clientHeight / 2 - paddingY;
			return {
				center: {
					x: scrollCenterX / scale - originX,
					y: scrollCenterY / scale - originY
				},
				scale: {
					x: scale,
					y: scale
				}
			};
		}
		setViewportState(state, options) {
			if (this.viewportAnimation) this.viewportAnimation.cancellation.abort();
			const from = this.viewportState;
			const to = {
				...from,
				...state
			};
			if (options && (options.animate || options.duration > 0)) {
				const viewportAnimation = {
					from,
					to,
					cancellation: new Cancellation()
				};
				const awaitPromise = animateInterval(typeof options.duration === "number" ? options.duration : DEFAULT_ANIMATION_DURATION, (progress) => {
					const t = easeInOutBezier(progress);
					const computed = {
						center: {
							x: from.center.x + (to.center.x - from.center.x) * t,
							y: from.center.y + (to.center.y - from.center.y) * t
						},
						scale: {
							x: from.scale.x + (to.scale.x - from.scale.x) * t,
							y: from.scale.y + (to.scale.y - from.scale.y) * t
						}
					};
					this.applyViewportState(computed);
				}, viewportAnimation.cancellation);
				this.viewportAnimation = viewportAnimation;
				return awaitPromise.then(() => {
					this.viewportAnimation = void 0;
				});
			} else {
				this.applyViewportState(to);
				return Promise.resolve();
			}
		}
	};
	function clientCoordsFor(container, e) {
		const targetBox = (e.target instanceof SVGElement && e.target.ownerSVGElement !== null ? e.target.ownerSVGElement : e.target).getBoundingClientRect();
		const containerBox = container.getBoundingClientRect();
		return {
			x: e.offsetX + (targetBox.left - containerBox.left),
			y: e.offsetY + (targetBox.top - containerBox.top)
		};
	}
	function getContentFittingBox(elements, links) {
		let minX = Infinity, minY = Infinity;
		let maxX = -Infinity, maxY = -Infinity;
		for (const element of elements) {
			const { x, y } = element.position;
			const size = element.size;
			minX = Math.min(minX, x);
			minY = Math.min(minY, y);
			maxX = Math.max(maxX, x + size.width);
			maxY = Math.max(maxY, y + size.height);
		}
		for (const link of links) {
			const vertices = link.vertices || [];
			for (const { x, y } of vertices) {
				minX = Math.min(minX, x);
				minY = Math.min(minY, y);
				maxX = Math.max(maxX, x);
				maxY = Math.max(maxY, y);
			}
		}
		return {
			x: Number.isFinite(minX) ? minX : 0,
			y: Number.isFinite(minY) ? minY : 0,
			width: Number.isFinite(minX) && Number.isFinite(maxX) ? maxX - minX : 0,
			height: Number.isFinite(minY) && Number.isFinite(maxY) ? maxY - minY : 0
		};
	}
	//#endregion
	//#region src/graph-explorer/diagram/embeddedLayer.tsx
	var EmbeddedLayerInner = class extends react.Component {
		constructor(props) {
			super(props);
			this.listener = new EventObserver();
			this.nestedElementListener = new EventObserver();
			this.layerOffsetLeft = 0;
			this.layerOffsetTop = 0;
			this.isApplyingParentMove = false;
			this.isNestedElementMoving = false;
			this.previousPositions = [];
			this.moveNestedElements = (offsetX, offsetY) => {
				this.isApplyingParentMove = true;
				try {
					for (const element of this.getNestedElements()) {
						const { x, y } = element.position;
						const newPosition = {
							x: x + offsetX,
							y: y + offsetY
						};
						element.setPosition(newPosition);
					}
				} finally {
					this.isApplyingParentMove = false;
					this.recomputeSelfBounds();
				}
			};
			this.recomputeSelfBounds = () => {
				if (this.isApplyingParentMove) return;
				const { element } = this.props.context.graphExplorerElement;
				const { x: offsetX, y: offsetY, width: paperWidth, height: paperHeight } = this.getContentFittingBox();
				if (this.isNestedElementMoving) {
					const position = {
						x: offsetX - this.layerOffsetLeft,
						y: offsetY - this.layerOffsetTop
					};
					element.setPosition(position);
				}
				this.setState({
					offsetX,
					offsetY,
					paperWidth,
					paperHeight
				}, () => element.redraw());
			};
			this.onPaperPointerDown = (e, cell) => {
				if (e.button !== 0) return;
				if (cell && cell instanceof Element$1) {
					e.preventDefault();
					this.isNestedElementMoving = true;
				}
			};
			this.onLayerInit = (layer) => {
				if (!layer) return;
				const { left, top } = this.calculateOffset(layer);
				this.layerOffsetLeft = left;
				this.layerOffsetTop = top;
			};
			this.state = {
				paperWidth: 0,
				paperHeight: 0,
				offsetX: 0,
				offsetY: 0
			};
		}
		componentDidMount() {
			const { element } = this.props.context.graphExplorerElement;
			const { paperArea, view } = this.props.context.paperArea;
			this.listener.listen(view.model.events, "changeGroupContent", ({ group }) => {
				if (group === element.id) {
					this.listenNestedElements(this.getNestedElements());
					const { offsetX, offsetY } = this.getOffset();
					this.moveNestedElements(offsetX, offsetY);
				}
			});
			this.listener.listen(element.events, "changePosition", () => {
				if (this.isNestedElementMoving) return;
				const { offsetX, offsetY } = this.getOffset();
				const { x, y } = this.getContentFittingBox();
				const diffX = offsetX - x;
				const diffY = offsetY - y;
				this.moveNestedElements(diffX, diffY);
				this.setState({
					offsetX,
					offsetY
				});
			});
			this.listener.listen(paperArea.events, "pointerUp", (_e) => {
				this.isNestedElementMoving = false;
			});
			const nestedElements = this.getNestedElements();
			this.listenNestedElements(nestedElements);
			if (nestedElements.length > 0) {
				const { x: offsetX, y: offsetY, width: paperWidth, height: paperHeight } = this.getContentFittingBox();
				this.setState({
					offsetX,
					offsetY,
					paperWidth,
					paperHeight
				}, () => element.redraw());
			} else element.requestGroupContent();
		}
		listenNestedElements(nestedElements) {
			const listener = new EventObserver();
			for (const nestedElement of nestedElements) {
				listener.listen(nestedElement.events, "changePosition", this.recomputeSelfBounds);
				listener.listen(nestedElement.events, "changeSize", this.recomputeSelfBounds);
			}
			this.nestedElementListener.stopListening();
			this.nestedElementListener = listener;
		}
		componentWillUnmount() {
			this.listener.stopListening();
			this.nestedElementListener.stopListening();
			this.removeElements();
			this.setState({
				paperWidth: 0,
				paperHeight: 0,
				offsetX: 0,
				offsetY: 0
			});
		}
		getNestedElements() {
			const { element } = this.props.context.graphExplorerElement;
			const { view } = this.props.context.paperArea;
			return view.model.elements.filter((el) => el.group === element.id);
		}
		getContentFittingBox() {
			return getContentFittingBox(this.getNestedElements(), []);
		}
		removeElements() {
			const { view } = this.props.context.paperArea;
			const batch = view.model.history.startBatch();
			for (const element of this.getNestedElements()) view.model.removeElement(element.id);
			batch.discard();
		}
		getOffset() {
			const { element } = this.props.context.graphExplorerElement;
			const { x: elementX, y: elementY } = element.position;
			return {
				offsetX: elementX + this.layerOffsetLeft,
				offsetY: elementY + this.layerOffsetTop
			};
		}
		calculateOffset(layer) {
			const { paperArea } = this.props.context.paperArea;
			const scale = paperArea.getScale();
			const parent = findParentElement(layer);
			const { left, top } = layer.getBoundingClientRect();
			const { left: parentLeft, top: parentTop } = parent.getBoundingClientRect();
			return {
				left: (left - parentLeft) / scale,
				top: (top - parentTop) / scale
			};
		}
		render() {
			const { element } = this.props.context.graphExplorerElement;
			const { view } = this.props.context.paperArea;
			const { paperWidth, paperHeight, offsetX, offsetY } = this.state;
			const paperTransform = {
				width: paperWidth,
				height: paperHeight,
				originX: -offsetX,
				originY: -offsetY,
				scale: 1,
				paddingX: 0,
				paddingY: 0
			};
			return /* @__PURE__ */ react.createElement("div", {
				className: "graph-explorer-embedded-layer",
				ref: this.onLayerInit
			}, /* @__PURE__ */ react.createElement(Paper, {
				view,
				paperTransform,
				onPointerDown: this.onPaperPointerDown,
				group: element.id
			}));
		}
	};
	function EmbeddedLayer() {
		const elementContext = react.useContext(ElementContext);
		const paperAreaContext = react.useContext(PaperAreaContext);
		return /* @__PURE__ */ react.createElement(EmbeddedLayerInner, { context: {
			...elementContext,
			...paperAreaContext
		} });
	}
	function findParentElement(layer) {
		const parent = layer.parentElement;
		if (!parent) throw new Error("Cannot find parent diagram element for EmbeddedLayer");
		else if (parent.hasAttribute("data-element-id")) return parent;
		else return findParentElement(parent);
	}
	//#endregion
	//#region src/graph-explorer/customization/templates/group.tsx
	var CLASS = "graph-explorer-group-template";
	var GroupTemplate = class extends react.Component {
		render() {
			const { label, iconUrl, types, color, isExpanded } = this.props;
			return /* @__PURE__ */ react.createElement("div", { className: CLASS }, /* @__PURE__ */ react.createElement("div", {
				className: `${CLASS}__wrap`,
				style: {
					backgroundColor: color,
					borderColor: color
				}
			}, /* @__PURE__ */ react.createElement("div", {
				className: `${CLASS}__type-line`,
				title: label
			}, /* @__PURE__ */ react.createElement("div", { className: `${CLASS}__type-line-icon` }, /* @__PURE__ */ react.createElement("img", { src: iconUrl })), /* @__PURE__ */ react.createElement("div", {
				title: types,
				className: `${CLASS}__type-line-text-container`
			}, /* @__PURE__ */ react.createElement("div", { className: `${CLASS}__type-line-text` }, types))), /* @__PURE__ */ react.createElement("div", {
				className: `${CLASS}__body`,
				style: { borderColor: color }
			}, /* @__PURE__ */ react.createElement("span", {
				className: `${CLASS}__label`,
				title: label
			}, label), isExpanded ? /* @__PURE__ */ react.createElement("div", { className: `${CLASS}__embedded-layer` }, /* @__PURE__ */ react.createElement(EmbeddedLayer, null)) : null)));
		}
	};
	//#endregion
	//#region src/graph-explorer/workspace/workspaceContext.ts
	var WorkspaceEventKey = /* @__PURE__ */ function(WorkspaceEventKey) {
		WorkspaceEventKey["searchUpdateCriteria"] = "search:updateCriteria";
		WorkspaceEventKey["searchQueryItem"] = "search:queryItems";
		WorkspaceEventKey["connectionsLoadLinks"] = "connections:loadLinks";
		WorkspaceEventKey["connectionsExpandLink"] = "connections:expandLink";
		WorkspaceEventKey["connectionsLoadElements"] = "connections:loadElements";
		WorkspaceEventKey["editorChangeSelection"] = "editor:changeSelection";
		WorkspaceEventKey["editorToggleDialog"] = "editor:toggleDialog";
		WorkspaceEventKey["editorAddElements"] = "editor:addElements";
		return WorkspaceEventKey;
	}({});
	var WorkspaceContext = (0, react.createContext)(null);
	//#endregion
	//#region src/graph-explorer/viewUtils/collections.ts
	function objectValues(obj) {
		const items = [];
		for (const key in obj) {
			if (!Object.prototype.hasOwnProperty.call(obj, key)) continue;
			items.push(obj[key]);
		}
		return items;
	}
	function isEmptyMap(map) {
		for (const key in map) if (Object.prototype.hasOwnProperty.call(map, key)) return false;
		return true;
	}
	/**
	* Clones Map collection. Required due to IE11 not supporing `new Map(map)`.
	*/
	function cloneMap(map) {
		const clone = /* @__PURE__ */ new Map();
		map.forEach((value, key) => clone.set(key, value));
		return clone;
	}
	/**
	* Clones Set collection. Required due to IE11 not supporing `new Set(set)`.
	*/
	function cloneSet(set) {
		const clone = /* @__PURE__ */ new Set();
		set.forEach((item) => clone.add(item));
		return clone;
	}
	function getOrCreateArrayInMap(map, key) {
		let values = map.get(key);
		if (!values) {
			values = [];
			map.set(key, values);
		}
		return values;
	}
	function getOrCreateSetInMap(map, key) {
		let values = map.get(key);
		if (!values) {
			values = /* @__PURE__ */ new Set();
			map.set(key, values);
		}
		return values;
	}
	var OrderedMap = class {
		constructor() {
			this.mapping = /* @__PURE__ */ new Map();
			this.ordered = [];
		}
		reorder(compare) {
			this.ordered.sort(compare);
		}
		get items() {
			return this.ordered;
		}
		get(key) {
			return this.mapping.get(key);
		}
		push(key, value) {
			if (this.mapping.has(key)) {
				const previous = this.mapping.get(key);
				if (previous === value) return;
				const index = this.ordered.indexOf(previous);
				this.ordered.splice(index, 1);
			}
			this.mapping.set(key, value);
			this.ordered.push(value);
		}
		delete(key) {
			if (!this.mapping.has(key)) return;
			const previous = this.mapping.get(key);
			const index = this.ordered.indexOf(previous);
			this.ordered.splice(index, 1);
			this.mapping.delete(key);
			return previous;
		}
	};
	var HashMap = class HashMap {
		constructor(hashCode, equals) {
			this.hashCode = hashCode;
			this.equals = equals;
			this.map = /* @__PURE__ */ new Map();
			this._size = 0;
		}
		get size() {
			return this._size;
		}
		has(key) {
			const items = this.map.get(this.hashCode(key));
			if (!items) return false;
			return Boolean(items.find((p) => this.equals(p.key, key)));
		}
		get(key) {
			const items = this.map.get(this.hashCode(key));
			if (!items) return;
			const pair = items.find((p) => this.equals(p.key, key));
			return pair ? pair.value : void 0;
		}
		set(key, value) {
			const hash = this.hashCode(key);
			let items = this.map.get(hash);
			if (items) {
				const index = items.findIndex((p) => this.equals(p.key, key));
				if (index >= 0) items.splice(index, 1);
				else this._size++;
				items.push({
					key,
					value
				});
			} else {
				items = [{
					key,
					value
				}];
				this.map.set(hash, items);
				this._size++;
			}
			return this;
		}
		delete(key) {
			const items = this.map.get(this.hashCode(key));
			if (!items) return false;
			const index = items.findIndex((p) => this.equals(p.key, key));
			if (index >= 0) {
				items.splice(index, 1);
				this._size--;
				return true;
			} else return false;
		}
		clear() {
			this.map.clear();
			this._size = 0;
		}
		forEach(callback) {
			this.map.forEach((items) => {
				for (const { key, value } of items) callback(value, key, this);
			});
		}
		clone() {
			const clone = new HashMap(this.hashCode, this.equals);
			clone._size = this.size;
			this.map.forEach((value, key) => clone.map.set(key, [...value]));
			return clone;
		}
	};
	var MoveDirection = /* @__PURE__ */ function(MoveDirection) {
		MoveDirection[MoveDirection["ToStart"] = -1] = "ToStart";
		MoveDirection[MoveDirection["ToEnd"] = 1] = "ToEnd";
		return MoveDirection;
	}({});
	function makeMoveComparator(items, selected, moveDirection) {
		const orderMap = /* @__PURE__ */ new Map();
		const selectionIndexOffset = moveDirection * items.length;
		items.forEach((item, index) => {
			orderMap.set(item, index);
		});
		for (const selectedItem of selected) orderMap.set(selectedItem, selectionIndexOffset + orderMap.get(selectedItem));
		return (a, b) => {
			const orderA = orderMap.get(a);
			const orderB = orderMap.get(b);
			return orderA > orderB ? 1 : orderA < orderB ? -1 : 0;
		};
	}
	//#endregion
	//#region src/graph-explorer/editor/authoringState.ts
	var AuthoringKind = /* @__PURE__ */ function(AuthoringKind) {
		AuthoringKind["ChangeElement"] = "changeElement";
		AuthoringKind["ChangeLink"] = "changeLink";
		return AuthoringKind;
	}({});
	var AuthoringState = {
		empty: {
			elements: /* @__PURE__ */ new Map(),
			links: new HashMap(hashLink, sameLink)
		},
		isEmpty(state) {
			return state.elements.size === 0 && state.links.size === 0;
		},
		clone(index) {
			return {
				elements: cloneMap(index.elements),
				links: index.links.clone()
			};
		},
		has(state, event) {
			return event.type === "changeElement" ? state.elements.get(event.after.id) === event : state.links.get(event.after) === event;
		},
		discard(state, discarded) {
			if (!this.has(state, discarded)) return state;
			const newState = this.clone(state);
			if (discarded.type === "changeElement") {
				newState.elements.delete(discarded.after.id);
				if (!discarded.before) state.links.forEach((e) => {
					if (isLinkConnectedToElement(e.after, discarded.after.id)) newState.links.delete(e.after);
				});
			} else newState.links.delete(discarded.after);
			return newState;
		},
		addElement(state, item) {
			const event = {
				type: "changeElement",
				after: item,
				deleted: false
			};
			const newState = this.clone(state);
			newState.elements.set(event.after.id, event);
			return newState;
		},
		addLink(state, item) {
			const event = {
				type: "changeLink",
				after: item,
				deleted: false
			};
			const newState = this.clone(state);
			newState.links.set(event.after, event);
			return newState;
		},
		changeElement(state, before, after) {
			const newState = this.clone(state);
			newState.elements.delete(before.id);
			const previous = state.elements.get(before.id);
			if (previous && !previous.before) {
				newState.elements.set(after.id, {
					type: "changeElement",
					after,
					deleted: false
				});
				if (before.id !== after.id) state.links.forEach((e) => {
					if (!e.before && isLinkConnectedToElement(e.after, before.id)) {
						const updatedLink = updateLinkToReferByNewIri(e.after, before.id, after.id);
						newState.links.delete(e.after);
						newState.links.set(updatedLink, {
							type: "changeLink",
							after: updatedLink,
							deleted: false
						});
					}
				});
			} else {
				const iriChanged = after.id !== before.id;
				const previousBefore = previous ? previous.before : void 0;
				newState.elements.set(before.id, {
					type: "changeElement",
					before: previousBefore || before,
					after: iriChanged ? {
						...after,
						id: before.id
					} : after,
					newIri: iriChanged ? after.id : void 0,
					deleted: false
				});
			}
			return newState;
		},
		changeLink(state, before, after) {
			if (!sameLink(before, after)) throw new Error("Cannot move link to another element or change its type");
			const newState = this.clone(state);
			const previous = state.links.get(before);
			newState.links.set(before, {
				type: "changeLink",
				before: previous ? previous.before : void 0,
				after,
				deleted: false
			});
			return newState;
		},
		deleteElement(state, model) {
			const newState = this.clone(state);
			newState.elements.delete(model.id);
			state.links.forEach((e) => {
				if (isLinkConnectedToElement(e.after, model.id)) newState.links.delete(e.after);
			});
			if (!this.isNewElement(state, model.id)) newState.elements.set(model.id, {
				type: "changeElement",
				before: model,
				after: model,
				deleted: true
			});
			return newState;
		},
		deleteLink(state, target) {
			const newState = this.clone(state);
			newState.links.delete(target);
			if (!this.isNewLink(state, target)) newState.links.set(target, {
				type: "changeLink",
				before: target,
				after: target,
				deleted: true
			});
			return newState;
		},
		deleteNewLinksConnectedToElements(state, elementIris) {
			const newState = this.clone(state);
			state.links.forEach((e) => {
				if (!e.before) {
					const target = e.after;
					if (elementIris.has(target.sourceId) || elementIris.has(target.targetId)) newState.links.delete(target);
				}
			});
			return newState;
		},
		isNewElement(state, target) {
			const event = state.elements.get(target);
			return event && event.type === "changeElement" && !event.before;
		},
		isDeletedElement(state, target) {
			const event = state.elements.get(target);
			return event && event.deleted;
		},
		isElementWithModifiedIri(state, target) {
			const event = state.elements.get(target);
			return event && event.type === "changeElement" && event.before && Boolean(event.newIri);
		},
		isNewLink(state, linkModel) {
			const event = state.links.get(linkModel);
			return event && !event.before;
		},
		isDeletedLink(state, linkModel) {
			const event = state.links.get(linkModel);
			return event && event.deleted || this.isDeletedElement(state, linkModel.sourceId) || this.isDeletedElement(state, linkModel.targetId);
		},
		isUncertainLink(state, linkModel) {
			return !this.isDeletedLink(state, linkModel) && (this.isElementWithModifiedIri(state, linkModel.sourceId) || this.isElementWithModifiedIri(state, linkModel.targetId));
		}
	};
	function isLinkConnectedToElement(link, elementIri) {
		return link.sourceId === elementIri || link.targetId === elementIri;
	}
	function updateLinkToReferByNewIri(link, oldIri, newIri) {
		return {
			...link,
			sourceId: link.sourceId === oldIri ? newIri : link.sourceId,
			targetId: link.targetId === oldIri ? newIri : link.targetId
		};
	}
	//#endregion
	//#region src/graph-explorer/editor/authoredEntity.tsx
	/**
	* Component to simplify tracking changes in validation messages (property and link type labels).
	*/
	var AuthoredEntityInner = class extends react.Component {
		constructor(props) {
			super(props);
			this.queryCancellation = new Cancellation();
			this.onChangeAuthoringState = (e) => {
				const { source: editor, previous } = e;
				const iri = this.props.templateProps.data.id;
				if (editor.authoringState.elements.get(iri) !== previous.elements.get(iri)) this.queryAllowedActions();
			};
			this.onEdit = () => {
				const { editor } = this.props.context.workspace;
				const { elementId } = this.props.templateProps;
				const element = editor.model.getElement(elementId);
				editor.showEditEntityForm(element);
			};
			this.onDelete = () => {
				const { editor } = this.props.context.workspace;
				const { data } = this.props.templateProps;
				editor.deleteEntity(data.id);
			};
			this.state = {};
		}
		componentDidMount() {
			const { editor } = this.props.context.workspace;
			editor.events.on("changeAuthoringState", this.onChangeAuthoringState);
			this.queryAllowedActions();
		}
		componentDidUpdate(prevProps) {
			if (!(this.props.templateProps.data === prevProps.templateProps.data && this.props.templateProps.isExpanded === prevProps.templateProps.isExpanded)) this.queryAllowedActions();
		}
		componentWillUnmount() {
			const { editor } = this.props.context.workspace;
			editor.events.off("changeAuthoringState", this.onChangeAuthoringState);
			this.queryCancellation.abort();
		}
		queryAllowedActions() {
			const { isExpanded, data } = this.props.templateProps;
			if (!isExpanded) return;
			this.queryCancellation.abort();
			this.queryCancellation = new Cancellation();
			const { editor } = this.props.context.workspace;
			if (!editor.metadataApi || AuthoringState.isDeletedElement(editor.authoringState, data.id)) this.setState({
				canEdit: false,
				canDelete: false
			});
			else {
				this.queryCanEdit(data);
				this.queryCanDelete(data);
			}
		}
		queryCanEdit(data) {
			const { editor } = this.props.context.workspace;
			const signal = this.queryCancellation.signal;
			this.setState({ canEdit: void 0 });
			CancellationToken.mapCancelledToNull(signal, editor.metadataApi.canEditElement(data, signal)).then((canEdit) => {
				if (canEdit === null) return;
				this.setState({ canEdit });
			});
		}
		queryCanDelete(data) {
			const { editor } = this.props.context.workspace;
			const signal = this.queryCancellation.signal;
			this.setState({ canDelete: void 0 });
			CancellationToken.mapCancelledToNull(signal, editor.metadataApi.canDeleteElement(data, signal)).then((canDelete) => {
				if (canDelete === null) return;
				this.setState({ canDelete });
			});
		}
		render() {
			const { children: renderTemplate } = this.props;
			const { view } = this.props.context.paperArea;
			const { editor } = this.props.context.workspace;
			const { canEdit, canDelete } = this.state;
			const iri = this.props.templateProps.iri;
			const elementEvent = editor.authoringState.elements.get(iri);
			return renderTemplate({
				editor,
				view,
				canEdit,
				canDelete,
				editedIri: elementEvent && elementEvent.type === AuthoringKind.ChangeElement ? elementEvent.newIri : void 0,
				onEdit: this.onEdit,
				onDelete: this.onDelete
			});
		}
	};
	function AuthoredEntity(props) {
		const paperAreaContext = react.useContext(PaperAreaContext);
		const workspaceContext = react.useContext(WorkspaceContext);
		return /* @__PURE__ */ react.createElement(AuthoredEntityInner, {
			...props,
			context: {
				...paperAreaContext,
				...workspaceContext
			}
		});
	}
	//#endregion
	//#region src/graph-explorer/viewUtils/spinner.tsx
	var CLASS_NAME$21 = "graph-explorer-spinner";
	var Spinner = class extends react.Component {
		render() {
			const { position = {
				x: 0,
				y: 0
			}, size = 50, statusText, errorOccured } = this.props;
			const textLeftMargin = 5;
			const pathGeometry = "m3.47,-19.7 a20,20 0 1,1 -6.95,0 m0,0 l-6,5 m6,-5 l-8,-0" + (errorOccured ? "M-8,-8L8,8M-8,8L8,-8" : "");
			return /* @__PURE__ */ react.createElement("g", {
				className: CLASS_NAME$21,
				"data-error": errorOccured,
				transform: `translate(${position.x},${position.y})`
			}, /* @__PURE__ */ react.createElement("g", { className: `${CLASS_NAME$21}__arrow` }, /* @__PURE__ */ react.createElement("path", {
				d: pathGeometry,
				transform: `scale(0.02)scale(${size})`,
				fill: "none",
				stroke: errorOccured ? "red" : "black",
				strokeWidth: "3",
				strokeLinecap: "round"
			})), /* @__PURE__ */ react.createElement("text", {
				style: { dominantBaseline: "middle" },
				x: size / 2 + textLeftMargin
			}, statusText));
		}
	};
	var HtmlSpinner = class extends react.Component {
		render() {
			const { width, height } = this.props;
			const size = Math.min(width, height);
			return /* @__PURE__ */ react.createElement("svg", {
				width,
				height
			}, /* @__PURE__ */ react.createElement(Spinner, {
				size,
				position: {
					x: width / 2,
					y: height / 2
				}
			}));
		}
	};
	//#endregion
	//#region src/graph-explorer/customization/templates/standard.tsx
	var FOAF_NAME = "http://xmlns.com/foaf/0.1/name";
	var CLASS_NAME$20 = "graph-explorer-standard-template";
	var StandardTemplate = class extends react.Component {
		render() {
			return /* @__PURE__ */ react.createElement(AuthoredEntity, { templateProps: this.props }, (context) => this.renderTemplate(context));
		}
		renderTemplate(context) {
			const { color, types, isExpanded, iri, propsAsList } = this.props;
			const label = this.getLabel();
			const { editor } = context;
			const leftStripeColor = AuthoringState.isNewElement(editor.authoringState, iri) ? "white" : color;
			const pinnedProperties = this.findPinnedProperties(context);
			return /* @__PURE__ */ react.createElement("div", { className: CLASS_NAME$20 }, /* @__PURE__ */ react.createElement("div", {
				className: `${CLASS_NAME$20}__main`,
				style: {
					backgroundColor: leftStripeColor,
					borderColor: color
				}
			}, /* @__PURE__ */ react.createElement("div", {
				className: `${CLASS_NAME$20}__body`,
				style: { borderLeftColor: color }
			}, /* @__PURE__ */ react.createElement("div", { className: `${CLASS_NAME$20}__body-horizontal` }, this.renderThumbnail(), /* @__PURE__ */ react.createElement("div", { className: `${CLASS_NAME$20}__body-content` }, /* @__PURE__ */ react.createElement("div", {
				title: types,
				className: `${CLASS_NAME$20}__type`
			}, /* @__PURE__ */ react.createElement("div", { className: `${CLASS_NAME$20}__type-value` }, this.getTypesLabel())), /* @__PURE__ */ react.createElement("div", {
				className: `${CLASS_NAME$20}__label`,
				title: label
			}, label))), pinnedProperties ? /* @__PURE__ */ react.createElement("div", {
				className: `${CLASS_NAME$20}__pinned-props`,
				style: { borderColor: color }
			}, this.renderProperties(pinnedProperties)) : null)), isExpanded ? /* @__PURE__ */ react.createElement("div", {
				className: `${CLASS_NAME$20}__dropdown`,
				style: { borderColor: color }
			}, this.renderPhoto(), /* @__PURE__ */ react.createElement("div", { className: `${CLASS_NAME$20}__dropdown-content` }, this.renderIri(context), this.renderProperties(propsAsList), editor.inAuthoringMode ? /* @__PURE__ */ react.createElement("hr", { className: `${CLASS_NAME$20}__hr` }) : null, editor.inAuthoringMode ? this.renderActions(context) : null)) : null);
		}
		findPinnedProperties(context) {
			const { isExpanded, propsAsList, elementId } = this.props;
			if (isExpanded) return;
			const templateState = context.view.model.getElement(elementId).elementState;
			if (!templateState) return;
			const pinned = templateState[TemplateProperties.PinnedProperties];
			if (!pinned) return;
			const filtered = propsAsList.filter((prop) => Boolean(pinned[prop.id]));
			return filtered.length === 0 ? void 0 : filtered;
		}
		renderProperties(propsAsList) {
			if (!propsAsList.length) return /* @__PURE__ */ react.createElement("div", null, "no properties");
			return /* @__PURE__ */ react.createElement("div", { className: `${CLASS_NAME$20}__properties` }, propsAsList.map(({ name, id, property }) => {
				const propertyValues = getPropertyValues(property);
				return /* @__PURE__ */ react.createElement("div", {
					key: id,
					className: `${CLASS_NAME$20}__properties-row`
				}, /* @__PURE__ */ react.createElement("div", {
					className: `${CLASS_NAME$20}__properties-key`,
					title: `${name} (${id})`
				}, name), /* @__PURE__ */ react.createElement("div", { className: `${CLASS_NAME$20}__properties-values` }, propertyValues.map((text, index) => /* @__PURE__ */ react.createElement("div", {
					className: `${CLASS_NAME$20}__properties-value`,
					key: index,
					title: text
				}, text))));
			}));
		}
		renderPhoto() {
			const { color, imgUrl } = this.props;
			if (!imgUrl) return null;
			return /* @__PURE__ */ react.createElement("div", {
				className: `${CLASS_NAME$20}__photo`,
				style: { borderColor: color }
			}, /* @__PURE__ */ react.createElement("img", {
				src: imgUrl,
				className: `${CLASS_NAME$20}__photo-image`
			}));
		}
		renderIri(context) {
			const { iri } = this.props;
			const finalIri = context.editedIri === void 0 ? iri : context.editedIri;
			return /* @__PURE__ */ react.createElement("div", null, /* @__PURE__ */ react.createElement("div", { className: `${CLASS_NAME$20}__iri` }, /* @__PURE__ */ react.createElement("div", { className: `${CLASS_NAME$20}__iri-key` }, "IRI", context.editedIri ? "\xA0(edited)" : "", ":"), /* @__PURE__ */ react.createElement("div", { className: `${CLASS_NAME$20}__iri-value` }, isEncodedBlank(finalIri) ? /* @__PURE__ */ react.createElement("span", null, "(blank node)") : /* @__PURE__ */ react.createElement("a", {
				href: finalIri,
				title: finalIri,
				"data-iri-click-intent": "openEntityIri"
			}, finalIri))), /* @__PURE__ */ react.createElement("hr", { className: `${CLASS_NAME$20}__hr` }));
		}
		renderThumbnail() {
			const { color, imgUrl, iconUrl } = this.props;
			if (imgUrl) return /* @__PURE__ */ react.createElement("div", {
				className: `${CLASS_NAME$20}__thumbnail`,
				"aria-hidden": "true"
			}, /* @__PURE__ */ react.createElement("img", {
				src: imgUrl,
				className: `${CLASS_NAME$20}__thumbnail-image`
			}));
			else if (iconUrl) return /* @__PURE__ */ react.createElement("div", {
				className: `${CLASS_NAME$20}__thumbnail`,
				"aria-hidden": "true"
			}, /* @__PURE__ */ react.createElement("img", {
				src: iconUrl,
				className: `${CLASS_NAME$20}__thumbnail-icon`
			}));
			const typeLabel = this.getTypesLabel();
			return /* @__PURE__ */ react.createElement("div", {
				className: `${CLASS_NAME$20}__thumbnail`,
				"aria-hidden": "true",
				style: { color }
			}, typeLabel.length > 0 ? typeLabel.charAt(0).toUpperCase() : "✳");
		}
		getTypesLabel() {
			return this.props.types;
		}
		getLabel() {
			const { label, props } = this.props;
			return getProperty(props, FOAF_NAME) || label;
		}
		renderActions(context) {
			const { canEdit, canDelete, onEdit, onDelete } = context;
			const SPINNER_WIDTH = 15;
			const SPINNER_HEIGHT = 12;
			return /* @__PURE__ */ react.createElement("div", { className: `${CLASS_NAME$20}__actions` }, /* @__PURE__ */ react.createElement("button", {
				type: "button",
				className: "graph-explorer-btn graph-explorer-btn-default",
				title: canDelete ? "Delete entity" : "Deletion is unavailable for the selected element",
				disabled: !canDelete,
				onClick: onDelete
			}, /* @__PURE__ */ react.createElement("span", { className: "fa fa-trash" }), "\xA0", canEdit === void 0 ? /* @__PURE__ */ react.createElement(HtmlSpinner, {
				width: SPINNER_WIDTH,
				height: SPINNER_HEIGHT
			}) : "Delete"), /* @__PURE__ */ react.createElement("button", {
				type: "button",
				className: "graph-explorer-btn graph-explorer-btn-default",
				title: canEdit ? "Edit entity" : "Editing is unavailable for the selected element",
				disabled: !canEdit,
				onClick: onEdit
			}, /* @__PURE__ */ react.createElement("span", { className: "fa fa-edit" }), "\xA0", canEdit === void 0 ? /* @__PURE__ */ react.createElement(HtmlSpinner, {
				width: SPINNER_WIDTH,
				height: SPINNER_HEIGHT
			}) : "Edit"));
		}
	};
	//#endregion
	//#region src/graph-explorer/customization/templates/index.ts
	var DefaultElementTemplateBundle = (_types) => void 0;
	//#endregion
	//#region src/graph-explorer/data/demo/provider.ts
	var DemoDataProvider = class {
		constructor(allClasses, allLinkTypes, allElements, allLinks) {
			this.allClasses = allClasses;
			this.allLinkTypes = allLinkTypes;
			this.allElements = allElements;
			this.allLinks = allLinks;
		}
		simulateNetwork(result) {
			const MEAN_DELAY = 200;
			const cloned = (0, lodash.cloneDeep)(result);
			const delay = -Math.log(Math.random()) * MEAN_DELAY;
			return new Promise((resolve) => {
				setTimeout(() => resolve(cloned), delay);
			});
		}
		classTree() {
			return this.simulateNetwork(this.allClasses);
		}
		classInfo(params) {
			const classIds = params.classIds || [];
			return this.simulateNetwork(this.allClasses.filter((cl) => classIds.indexOf(cl.id)));
		}
		linkTypes() {
			return this.simulateNetwork(this.allLinkTypes);
		}
		linkTypesInfo(params) {
			const types = (0, lodash.keyBy)(params.linkTypeIds);
			const linkTypes = this.allLinkTypes.filter((type) => types[type.id]);
			return this.simulateNetwork(linkTypes);
		}
		elementInfo(params) {
			const elements = params.elementIds.map((elementId) => this.allElements[elementId]).filter((element) => element !== void 0);
			return this.simulateNetwork((0, lodash.keyBy)(elements, (element) => element.id));
		}
		linksInfo(params) {
			const nodes = (0, lodash.keyBy)(params.elementIds);
			const types = (0, lodash.keyBy)(params.linkTypeIds);
			const links = this.allLinks.filter((link) => types[link.linkTypeId] && nodes[link.sourceId] && nodes[link.targetId]);
			return this.simulateNetwork(links);
		}
		linkTypesOf(params) {
			const counts = {};
			for (const link of this.allLinks) if (link.sourceId === params.elementId || link.targetId === params.elementId) {
				const linkCount = counts[link.linkTypeId];
				const isSource = link.sourceId === params.elementId;
				if (linkCount) if (isSource) linkCount.outCount++;
				else linkCount.inCount++;
				else counts[link.linkTypeId] = isSource ? {
					id: link.linkTypeId,
					inCount: 0,
					outCount: 1
				} : {
					id: link.linkTypeId,
					inCount: 1,
					outCount: 0
				};
			}
			return this.simulateNetwork((0, lodash.map)(counts));
		}
		linkElements(params) {
			return this.filter({
				refElementId: params.elementId,
				refElementLinkId: params.linkId,
				linkDirection: params.direction,
				limit: params.limit,
				offset: params.offset,
				languageCode: ""
			});
		}
		filter(params) {
			if (params.limit === void 0) params.limit = 100;
			if (params.offset > 0) return Promise.resolve({});
			let filtered = {};
			if (params.elementTypeId) (0, lodash.each)(this.allElements, (element) => {
				if (element.types.indexOf(params.elementTypeId) >= 0) filtered[element.id] = element;
			});
			else if (params.refElementId) {
				const filteredLinks = params.refElementLinkId ? this.allLinks.filter((link) => link.linkTypeId === params.refElementLinkId) : this.allLinks;
				const nodeId = params.refElementId;
				for (const link of filteredLinks) {
					let linkedElementId;
					if (link.sourceId === nodeId && params.linkDirection !== "in") linkedElementId = link.targetId;
					else if (link.targetId === nodeId && params.linkDirection !== "out") linkedElementId = link.sourceId;
					if (linkedElementId !== void 0) {
						const linkedElement = this.allElements[linkedElementId];
						if (linkedElement) filtered[linkedElement.id] = linkedElement;
					}
				}
			} else if (params.text) filtered = this.allElements;
			else return Promise.reject(/* @__PURE__ */ new Error("This type of filter is not implemented"));
			if (params.text) {
				const filteredByText = {};
				const text = params.text.toLowerCase();
				(0, lodash.each)(filtered, (element) => {
					if (element.id.toLowerCase().indexOf(text) >= 0 || element.label.values.some((label) => label.value.toLowerCase().indexOf(text) >= 0)) filteredByText[element.id] = element;
				});
				return this.simulateNetwork(filteredByText);
			} else return this.simulateNetwork(filtered);
		}
	};
	//#endregion
	//#region src/graph-explorer/data/sparql/responseHandler.ts
	var LABEL_URI = "http://www.w3.org/2000/01/rdf-schema#label";
	var RDF_TYPE_URI = "http://www.w3.org/1999/02/22-rdf-syntax-ns#type";
	var EMPTY_MAP = /* @__PURE__ */ new Map();
	function getClassTree(response) {
		const treeNodes = createClassMap(response.results.bindings);
		const allNodes = [];
		treeNodes.forEach((node) => {
			allNodes.push(node);
			node.parents.forEach((parent) => {
				treeNodes.get(parent).children.push(node);
			});
			node.parents = void 0;
		});
		const withoutCycles = breakCyclesAndCalculateCounts(allNodes);
		const leafs = /* @__PURE__ */ new Set();
		for (const node of withoutCycles) for (const child of node.children) leafs.add(child.id);
		return withoutCycles.filter((node) => !leafs.has(node.id));
	}
	function flattenClassTree(classTree) {
		const all = [];
		const visitClasses = (classes) => {
			for (const model of classes) {
				all.push(model);
				visitClasses(model.children);
			}
		};
		visitClasses(classTree);
		return all;
	}
	function createClassMap(bindings) {
		const treeNodes = /* @__PURE__ */ new Map();
		for (const binding of bindings) {
			if (!isRdfIri(binding.class)) continue;
			const classIri = binding.class.value;
			let node = treeNodes.get(classIri);
			if (!node) {
				node = createEmptyModel(classIri);
				treeNodes.set(classIri, node);
			}
			if (binding.label) appendLabel(node.label, getLocalizedString(binding.label));
			if (binding.parent) {
				const parentIri = binding.parent.value;
				node.parents.add(parentIri);
			}
			if (binding.instcount) node.count = getInstCount(binding.instcount);
		}
		for (const binding of bindings) if (binding.parent) {
			const parentIri = binding.parent.value;
			if (!treeNodes.has(parentIri)) treeNodes.set(parentIri, createEmptyModel(parentIri));
		}
		function createEmptyModel(iri) {
			return {
				id: iri,
				children: [],
				label: { values: [] },
				count: void 0,
				parents: /* @__PURE__ */ new Set()
			};
		}
		return treeNodes;
	}
	function breakCyclesAndCalculateCounts(tree) {
		const visiting = /* @__PURE__ */ new Set();
		function reduceChildren(acc, node) {
			if (visiting.has(node.id)) return acc;
			if (!node.children) return;
			visiting.add(node.id);
			node.children = node.children.reduce(reduceChildren, []);
			visiting.delete(node.id);
			let childCount;
			node.children.forEach(({ count }) => {
				if (count === void 0) return;
				childCount = childCount === void 0 ? count : childCount + count;
			});
			if (childCount !== void 0) node.count = node.count === void 0 ? childCount : node.count + childCount;
			acc.push(node);
			return acc;
		}
		return tree.reduce(reduceChildren, []);
	}
	function getClassInfo(response) {
		const classes = {};
		for (const binding of response.results.bindings) {
			if (!binding.class) continue;
			const id = binding.class.value;
			const model = classes[id];
			if (model) {
				appendLabel(model.label, getLocalizedString(binding.label));
				const instanceCount = getInstCount(binding.instcount);
				if (instanceCount !== void 0) model.count = Math.max(model.count, instanceCount);
			} else {
				const label = getLocalizedString(binding.label);
				classes[id] = {
					id,
					children: [],
					label: { values: label ? [label] : [] },
					count: getInstCount(binding.instcount)
				};
			}
		}
		const classesList = [];
		for (const id in classes) {
			if (!Object.prototype.hasOwnProperty.call(classes, id)) continue;
			const model = classes[id];
			classesList.push(model);
		}
		return classesList;
	}
	function getPropertyInfo(response) {
		const models = {};
		for (const sProperty of response.results.bindings) {
			const sPropertyTypeId = sProperty.property.value;
			if (models[sPropertyTypeId]) {
				if (sProperty.label) {
					const label = models[sPropertyTypeId].label;
					if (label.values.length === 1 && !label.values[0].language) label.values = [];
					label.values.push(getLocalizedString(sProperty.label));
				}
			} else models[sPropertyTypeId] = getPropertyModel(sProperty);
		}
		return models;
	}
	function getLinkTypes(response) {
		const sInst = response.results.bindings;
		const linkTypes = [];
		const linkTypesMap = {};
		for (const sLink of sInst) {
			const sInstTypeId = sLink.link.value;
			if (linkTypesMap[sInstTypeId]) {
				if (sLink.label) {
					const label = linkTypesMap[sInstTypeId].label;
					if (label.values.length === 1 && !label.values[0].language) label.values = [];
					label.values.push(getLocalizedString(sLink.label));
				}
			} else {
				linkTypesMap[sInstTypeId] = getLinkTypeInfo(sLink);
				linkTypes.push(linkTypesMap[sInstTypeId]);
			}
		}
		return linkTypes;
	}
	function triplesToElementBinding(triples) {
		const map = {};
		const convertedResponse = {
			head: { vars: [
				"inst",
				"class",
				"label",
				"blankType",
				"propType",
				"propValue"
			] },
			results: { bindings: [] }
		};
		for (const triple of triples) {
			const trippleId = triple.subject.value;
			if (!map[trippleId]) map[trippleId] = createAndPushBinding(triple);
			if (triple.predicate.value === LABEL_URI && isRdfLiteral(triple.object)) {
				if (map[trippleId].label) map[trippleId] = createAndPushBinding(triple);
				map[trippleId].label = triple.object;
			} else if (triple.predicate.value === RDF_TYPE_URI && isRdfIri(triple.object) && isRdfIri(triple.predicate)) {
				if (map[trippleId].class) map[trippleId] = createAndPushBinding(triple);
				map[trippleId].class = triple.object;
			} else if (!isRdfBlank(triple.object) && isRdfIri(triple.predicate)) {
				if (map[trippleId].propType) map[trippleId] = createAndPushBinding(triple);
				map[trippleId].propType = triple.predicate;
				map[trippleId].propValue = triple.object;
			}
		}
		function createAndPushBinding(tripple) {
			const binding = { inst: tripple.subject };
			convertedResponse.results.bindings.push(binding);
			return binding;
		}
		return convertedResponse;
	}
	function getElementsInfo(response, types = EMPTY_MAP, propertyByPredicate = EMPTY_MAP, openWorldProperties = true) {
		const instancesMap = {};
		for (const binding of response.results.bindings) {
			if (!isRdfIri(binding.inst)) continue;
			const iri = binding.inst.value;
			let model = instancesMap[iri];
			if (!model) {
				model = emptyElementInfo(iri);
				instancesMap[iri] = model;
			}
			enrichElement(model, binding);
		}
		if (!openWorldProperties || propertyByPredicate.size > 0) for (const iri in instancesMap) {
			if (!Object.hasOwnProperty.call(instancesMap, iri)) continue;
			const model = instancesMap[iri];
			model.properties = mapPropertiesByConfig(model, types.get(model.id), propertyByPredicate, openWorldProperties);
		}
		return instancesMap;
	}
	function mapPropertiesByConfig(model, modelTypes, propertyByPredicate, openWorldProperties) {
		const mapped = {};
		for (const propertyIri in model.properties) {
			if (!Object.hasOwnProperty.call(model.properties, propertyIri)) continue;
			const properties = propertyByPredicate.get(propertyIri);
			if (properties && properties.length > 0) {
				for (const property of properties) if (typeMatchesDomain(property, modelTypes)) mapped[property.id] = model.properties[propertyIri];
			} else if (openWorldProperties) mapped[propertyIri] = model.properties[propertyIri];
		}
		return mapped;
	}
	function enrichElementsWithImages(response, elementsInfo) {
		const respElements = response.results.bindings;
		for (const respEl of respElements) {
			const elementInfo = elementsInfo[respEl.inst.value];
			if (elementInfo) elementInfo.image = respEl.image.value;
		}
	}
	function getElementTypes(response) {
		const types = /* @__PURE__ */ new Map();
		for (const binding of response.results.bindings) if (isRdfIri(binding.inst) && isRdfIri(binding.class)) {
			const element = binding.inst.value;
			const type = binding.class.value;
			getOrCreateSetInMap(types, element).add(type);
		}
		return types;
	}
	function getLinksInfo(response, types = EMPTY_MAP, linkByPredicateType = EMPTY_MAP, openWorldLinks = true) {
		const sparqlLinks = response.results.bindings;
		const links = new HashMap(hashLink, sameLink);
		for (const binding of sparqlLinks) {
			const model = {
				sourceId: binding.source.value,
				linkTypeId: binding.type.value,
				targetId: binding.target.value,
				properties: {}
			};
			if (links.has(model)) {
				if (binding.propType) mergeProperties$1(links.get(model).properties, binding.propType, binding.propValue);
			} else {
				if (binding.propType) mergeProperties$1(model.properties, binding.propType, binding.propValue);
				const linkConfigs = linkByPredicateType.get(model.linkTypeId);
				if (linkConfigs && linkConfigs.length > 0) {
					for (const linkConfig of linkConfigs) if (typeMatchesDomain(linkConfig, types.get(model.sourceId))) {
						const mappedModel = isDirectLink(linkConfig) ? {
							...model,
							linkTypeId: linkConfig.id
						} : model;
						links.set(mappedModel, mappedModel);
					}
				} else if (openWorldLinks) links.set(model, model);
			}
		}
		const linkArray = [];
		links.forEach((value) => linkArray.push(value));
		return linkArray;
	}
	function getLinksTypesOf(response) {
		return response.results.bindings.filter((b) => !isRdfBlank(b.link)).map((sLink) => getLinkCount(sLink));
	}
	function getLinksTypeIds(response, linkByPredicateType = EMPTY_MAP, openWorldLinks = true) {
		const linkTypes = [];
		for (const binding of response.results.bindings) {
			if (!isRdfIri(binding.link)) continue;
			const linkConfigs = linkByPredicateType.get(binding.link.value);
			if (linkConfigs && linkConfigs.length > 0) for (const linkConfig of linkConfigs) {
				const mappedLinkType = isDirectLink(linkConfig) ? linkConfig.id : binding.link.value;
				linkTypes.push(mappedLinkType);
			}
			else if (openWorldLinks) linkTypes.push(binding.link.value);
		}
		return linkTypes;
	}
	function getLinkStatistics(response) {
		for (const binding of response.results.bindings) if (isRdfIri(binding.link)) return getLinkCount(binding);
	}
	function getFilteredData(response, sourceTypes, linkByPredicateType = EMPTY_MAP, openWorldLinks = true) {
		const instancesMap = {};
		const resultTypes = /* @__PURE__ */ new Map();
		const outPredicates = /* @__PURE__ */ new Map();
		const inPredicates = /* @__PURE__ */ new Map();
		for (const binding of response.results.bindings) {
			if (!isRdfIri(binding.inst) && !isRdfBlank(binding.inst)) continue;
			const iri = binding.inst.value;
			let model = instancesMap[iri];
			if (!model) {
				model = emptyElementInfo(iri);
				instancesMap[iri] = model;
			}
			enrichElement(model, binding);
			if (isRdfIri(binding.classAll)) getOrCreateSetInMap(resultTypes, iri).add(binding.classAll.value);
			if (!openWorldLinks && binding.link && binding.direction) getOrCreateSetInMap(binding.direction.value === "out" ? outPredicates : inPredicates, model.id).add(binding.link.value);
		}
		if (!openWorldLinks) for (const id of Object.keys(instancesMap)) {
			const model = instancesMap[id];
			const targetTypes = resultTypes.get(model.id);
			if (!(matchesDomainForLink(sourceTypes, outPredicates.get(model.id), linkByPredicateType) && matchesDomainForLink(targetTypes, inPredicates.get(model.id), linkByPredicateType))) delete instancesMap[id];
		}
		return instancesMap;
	}
	function matchesDomainForLink(types, predicates, linkByPredicateType) {
		if (!predicates) return true;
		let hasMatch = false;
		predicates.forEach((predicate) => {
			const matched = linkByPredicateType.get(predicate);
			if (matched) {
				for (const link of matched) if (typeMatchesDomain(link, types)) hasMatch = true;
			}
		});
		return hasMatch;
	}
	function isDirectLink(link) {
		return !/[?$][a-zA-Z]+\b/.test(link.path);
	}
	function isDirectProperty(property) {
		return !/[?$][a-zA-Z]+\b/.test(property.path);
	}
	function typeMatchesDomain(config, types) {
		if (!config.domain || config.domain.length === 0) return true;
		else if (!types) return false;
		else {
			for (const type of config.domain) if (types.has(type)) return true;
			return false;
		}
	}
	/**
	* Modifies properties with merging with new values, couls be new peroperty or new value for existing properties.
	* @param properties
	* @param propType
	* @param propValue
	*/
	function mergeProperties$1(properties, propType, propValue) {
		let property = properties[propType.value];
		if (isRdfIri(propValue)) {
			if (!property) property = {
				type: "uri",
				values: []
			};
			if (isIriProperty(property) && property.values.every(({ value }) => value !== propValue.value)) property.values = [...property.values, propValue];
		} else if (isRdfLiteral(propValue)) {
			if (!property) property = {
				type: "string",
				values: []
			};
			const propertyValue = getLocalizedString(propValue);
			if (isLiteralProperty(property) && property.values.every((value) => !isLocalizedEqual(value, propertyValue))) property.values = [...property.values, propertyValue];
		}
		properties[propType.value] = property;
	}
	function enrichElement(element, sInst) {
		if (!element) return;
		if (sInst.label) {
			const label = getLocalizedString(sInst.label);
			if (element.label.values.every((value) => !isLocalizedEqual(value, label))) element.label.values.push(label);
		}
		if (sInst.class && element.types.indexOf(sInst.class.value) < 0) element.types.push(sInst.class.value);
		if (sInst.propType && sInst.propType.value !== LABEL_URI) mergeProperties$1(element.properties, sInst.propType, sInst.propValue);
	}
	function appendLabel(container, newLabel) {
		if (!newLabel) return;
		for (const existing of container.values) if (isLocalizedEqual(existing, newLabel)) return;
		container.values.push(newLabel);
	}
	function isLocalizedEqual(left, right) {
		return left.language === right.language && left.value === right.value;
	}
	function getLocalizedString(label) {
		if (label) return {
			value: label.value,
			language: label["xml:lang"],
			datatype: label.datatype ? { value: label.datatype } : void 0
		};
		else return;
	}
	function getInstCount(instcount) {
		return instcount ? +instcount.value : void 0;
	}
	function getPropertyModel(node) {
		const label = getLocalizedString(node.label);
		return {
			id: node.property.value,
			label: { values: label ? [label] : [] }
		};
	}
	function getLinkCount(sLinkType) {
		return {
			id: sLinkType.link.value,
			inCount: getInstCount(sLinkType.inCount),
			outCount: getInstCount(sLinkType.outCount)
		};
	}
	function emptyElementInfo(id) {
		return {
			id,
			label: { values: [] },
			types: [],
			properties: {}
		};
	}
	function getLinkTypeInfo(sLinkInfo) {
		if (!sLinkInfo) return;
		const label = getLocalizedString(sLinkInfo.label);
		return {
			id: sLinkInfo.link.value,
			label: { values: label ? [label] : [] },
			count: getInstCount(sLinkInfo.instcount)
		};
	}
	function prependAdditionalBindings(base, additional) {
		if (!additional) return base;
		return {
			head: { vars: base.head.vars },
			results: { bindings: [...additional.results.bindings, ...base.results.bindings] }
		};
	}
	//#endregion
	//#region src/graph-explorer/data/sparql/sparqlDataProviderSettings.ts
	var RDFSettings = {
		linkConfigurations: [],
		openWorldLinks: false,
		propertyConfigurations: [],
		openWorldProperties: false,
		linksInfoQuery: `SELECT ?source ?type ?target
            WHERE {
                \${linkConfigurations}
                VALUES (?source) {\${ids}}
                VALUES (?target) {\${ids}}
            }`,
		defaultPrefix: "",
		schemaLabelProperty: "rdfs:label",
		dataLabelProperty: "rdfs:label",
		fullTextSearch: {
			prefix: "",
			queryPattern: ``,
			elementFirst: false
		},
		classTreeQuery: ``,
		classInfoQuery: `SELECT ?class ?label ?instcount WHERE {
    VALUES(?class) {\${ids}}
    OPTIONAL { ?class \${schemaLabelProperty} ?label }
    BIND("" as ?instcount)
}`,
		linkTypesQuery: `SELECT DISTINCT ?link ?instcount ?label WHERE {
    \${linkTypesPattern}
    OPTIONAL { ?link \${schemaLabelProperty} ?label }
}`,
		linkTypesPattern: ``,
		linkTypesInfoQuery: `SELECT ?link ?label WHERE {
    VALUES(?link) {\${ids}}
    OPTIONAL { ?link \${schemaLabelProperty} ?label }
}`,
		propertyInfoQuery: `SELECT ?property ?label WHERE {
    VALUES(?property) {\${ids}}
    OPTIONAL { ?property \${schemaLabelProperty} ?label }
}`,
		elementInfoQuery: ``,
		imageQueryPattern: ``,
		linkTypesOfQuery: ``,
		linkTypesStatisticsQuery: ``,
		filterRefElementLinkPattern: "",
		filterTypePattern: ``,
		filterAdditionalRestriction: ``,
		filterElementInfoPattern: ``
	};
	var WikidataSettingsOverride = {
		defaultPrefix: `PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
 PREFIX rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
 PREFIX wdt: <http://www.wikidata.org/prop/direct/>
 PREFIX wd: <http://www.wikidata.org/entity/>
 PREFIX owl:  <http://www.w3.org/2002/07/owl#>

`,
		schemaLabelProperty: "rdfs:label",
		dataLabelProperty: "rdfs:label",
		fullTextSearch: {
			prefix: "PREFIX bds: <http://www.bigdata.com/rdf/search#>\n",
			queryPattern: `
              ?inst rdfs:label ?searchLabel.
              SERVICE bds:search {
                     ?searchLabel bds:search "\${text}*" ;
                                  bds:minRelevance '0.5' ;
                                  bds:matchAllTerms 'true' .
              }
              BIND(IF(STRLEN(?strInst) > 33,
                            0-<http://www.w3.org/2001/XMLSchema#integer>(SUBSTR(?strInst, 33)),
                            -10000) as ?score)
            `
		},
		classTreeQuery: `
            SELECT distinct ?class ?label ?parent WHERE {
              ?class rdfs:label ?label.
              { ?class wdt:P279 wd:Q35120. }
                UNION
              { ?parent wdt:P279 wd:Q35120.
                ?class wdt:P279 ?parent. }
                UNION
              { ?parent wdt:P279/wdt:P279 wd:Q35120.
                ?class wdt:P279 ?parent. }
            }
        `,
		linkTypesPattern: `?link wdt:P279* wd:Q18616576.
    BIND(0 as ?instcount)
`,
		elementInfoQuery: `
        CONSTRUCT {
            ?inst rdf:type ?class .
            ?inst rdfs:label ?label .
            ?inst ?propType ?propValue.
        } WHERE {
            VALUES (?inst) {\${ids}}
            OPTIONAL {
                ?inst wdt:P31 ?class
            }
            OPTIONAL {?inst rdfs:label ?label}
            OPTIONAL {
                \${propertyConfigurations}
                FILTER (isLiteral(?propValue))
            }
        }
    `,
		imageQueryPattern: ` { ?inst ?linkType ?fullImage } union { ?inst wdt:P163/wdt:P18 ?fullImage }
                BIND(CONCAT("https://commons.wikimedia.org/w/thumb.php?f=",
                    STRAFTER(STR(?fullImage), "Special:FilePath/"), "&w=200") AS ?image)`,
		linkTypesOfQuery: `
        SELECT DISTINCT ?link
        WHERE {
            \${linkConfigurations}
            ?claim <http://wikiba.se/ontology#directClaim> ?link .
        }
    `,
		linkTypesStatisticsQuery: `
        SELECT (\${linkId} as ?link) (COUNT(?outObject) AS ?outCount) (COUNT(?inObject) AS ?inCount)
        WHERE {
            {
                {
                    SELECT DISTINCT ?outObject WHERE {
                        \${linkConfigurationOut}
                        FILTER(ISIRI(?outObject))
                        ?outObject ?someprop ?someobj.
                    }
                    LIMIT 101
                }
            } UNION {
                {
                    SELECT DISTINCT ?inObject WHERE {
                        \${linkConfigurationIn}
                        FILTER(ISIRI(?inObject))
                        ?inObject ?someprop ?someobj.
                    }
                    LIMIT 101
                }
            }
        }
    `,
		filterRefElementLinkPattern: "?claim <http://wikiba.se/ontology#directClaim> ?link .",
		filterTypePattern: `?inst wdt:P31 ?instType. ?instType wdt:P279* ?class`,
		filterAdditionalRestriction: `FILTER ISIRI(?inst)
                        BIND(STR(?inst) as ?strInst)
                        FILTER exists {?inst ?someprop ?someobj}
`,
		filterElementInfoPattern: `OPTIONAL {?inst wdt:P31 ?foundClass}
                BIND (coalesce(?foundClass, owl:Thing) as ?class)
                OPTIONAL {?inst rdfs:label ?label}
`
	};
	var WikidataSettings = {
		...RDFSettings,
		...WikidataSettingsOverride
	};
	var OWLRDFSSettingsOverride = {
		defaultPrefix: `PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
 PREFIX rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
 PREFIX owl:  <http://www.w3.org/2002/07/owl#>
`,
		schemaLabelProperty: "rdfs:label",
		dataLabelProperty: "rdfs:label",
		fullTextSearch: {
			prefix: "",
			queryPattern: ` OPTIONAL {?inst \${dataLabelProperty} ?search1}
        FILTER regex(COALESCE(str(?search1), str(?extractedLabel)), "\${text}", "i")
        BIND(0 as ?score)
`,
			extractLabel: true
		},
		classTreeQuery: `
            SELECT ?class ?label ?parent
            WHERE {
                {
                    ?class a rdfs:Class
                } UNION {
                    ?class a owl:Class
                }
                FILTER ISIRI(?class)
                OPTIONAL {?class rdfs:label ?label}
                OPTIONAL {?class rdfs:subClassOf ?parent. FILTER ISIRI(?parent)}
            }
        `,
		linkTypesPattern: `{  ?link a rdf:Property
                    } UNION {
                    ?link a owl:ObjectProperty
                }
                BIND('' as ?instcount)
    `,
		elementInfoQuery: `
        CONSTRUCT {
            ?inst rdf:type ?class .
            ?inst rdfs:label ?label .
            ?inst ?propType ?propValue.
        } WHERE {
            VALUES (?inst) {\${ids}}
            OPTIONAL { ?inst a ?class }
            OPTIONAL {?inst \${dataLabelProperty} ?label}
            OPTIONAL {
                \${propertyConfigurations}
                FILTER (isLiteral(?propValue))
            }
        }
    `,
		imageQueryPattern: `{ ?inst ?linkType ?image } UNION { [] ?linkType ?inst. BIND(?inst as ?image) }`,
		linkTypesOfQuery: `
        SELECT DISTINCT ?link
        WHERE {
            \${linkConfigurations}
        }
    `,
		linkTypesStatisticsQuery: `
        SELECT ?link ?outCount ?inCount
        WHERE {
            {
                SELECT (\${linkId} as ?link) (count(?outObject) as ?outCount) WHERE {
                    \${linkConfigurationOut}
                    \${navigateElementFilterOut}
                } LIMIT 101
            } {
                SELECT (\${linkId} as ?link) (count(?inObject) as ?inCount) WHERE {
                    \${linkConfigurationIn}
                    \${navigateElementFilterIn}
                } LIMIT 101
            }
        }
    `,
		filterRefElementLinkPattern: "",
		filterTypePattern: `?inst a ?instType. ?instType rdfs:subClassOf* ?class`,
		filterElementInfoPattern: `OPTIONAL {?inst rdf:type ?foundClass}
                BIND (coalesce(?foundClass, owl:Thing) as ?class)
                OPTIONAL {?inst \${dataLabelProperty} ?label}`,
		filterAdditionalRestriction: ""
	};
	var OWLRDFSSettings = {
		...RDFSettings,
		...OWLRDFSSettingsOverride
	};
	var OWLStatsOverride = { classTreeQuery: `
        SELECT ?class ?instcount ?label ?parent
        WHERE {
            {SELECT ?class (count(?inst) as ?instcount)
                WHERE {
                    ?inst rdf:type ?class.
                    FILTER ISIRI(?class)
                } GROUP BY ?class } UNION
            {
                ?class rdf:type rdfs:Class
            } UNION {
                ?class rdf:type owl:Class
            }
            OPTIONAL {?class rdfs:label ?label}
            OPTIONAL {?class rdfs:subClassOf ?parent. FILTER ISIRI(?parent)}
        }
    ` };
	var OWLStatsSettings = {
		...OWLRDFSSettings,
		...OWLStatsOverride
	};
	var DBPediaOverride = {
		fullTextSearch: {
			prefix: "PREFIX dbo: <http://dbpedia.org/ontology/>\n",
			queryPattern: `
              ?inst rdfs:label ?searchLabel.
              ?searchLabel bif:contains "\${text}".
              ?inst dbo:wikiPageID ?origScore .
              BIND(0-?origScore as ?score)
        `
		},
		classTreeQuery: `
        SELECT distinct ?class ?label ?parent WHERE {
            ?class rdfs:label ?label.
            OPTIONAL {?class rdfs:subClassOf ?parent}
            ?root rdfs:subClassOf owl:Thing.
            ?class rdfs:subClassOf? | rdfs:subClassOf/rdfs:subClassOf ?root
        }
    `,
		elementInfoQuery: `
        CONSTRUCT {
            ?inst rdf:type ?class .
            ?inst rdfs:label ?label .
            ?inst ?propType ?propValue.
        } WHERE {
            VALUES (?inst) {\${ids}}
            ?inst a ?class .
            ?inst rdfs:label ?label .
            FILTER (!contains(str(?class), 'http://dbpedia.org/class/yago'))
            OPTIONAL {
                \${propertyConfigurations}
                FILTER (isLiteral(?propValue))
            }
        }
    `,
		filterTypePattern: `?inst a ?instType. ?instType rdfs:subClassOf* ?class`,
		filterElementInfoPattern: `
        OPTIONAL {?inst rdf:type ?foundClass. FILTER (!contains(str(?foundClass), 'http://dbpedia.org/class/yago'))}
        BIND (coalesce(?foundClass, owl:Thing) as ?class)
        OPTIONAL {?inst \${dataLabelProperty} ?label}`,
		imageQueryPattern: ` { ?inst ?linkType ?fullImage } UNION { [] ?linkType ?inst. BIND(?inst as ?fullImage) }
            BIND(CONCAT("https://commons.wikimedia.org/w/thumb.php?f=",
            STRAFTER(STR(?fullImage), "Special:FilePath/"), "&w=200") AS ?image)
    `
	};
	var DBPediaSettings = {
		...OWLRDFSSettings,
		...DBPediaOverride
	};
	var QLeverOverride = { fullTextSearch: {
		prefix: "PREFIX ql: <http://qlever.cs.uni-freiburg.de/builtin-functions/>\n",
		queryPatternPerWord: `
              ?inst \${dataLabelProperty} ?searchLabel .
              ?searchLabel ql:has-word "\${word}" .
        `
	} };
	var QLeverSettings = {
		...OWLRDFSSettings,
		...QLeverOverride
	};
	//#endregion
	//#region src/graph-explorer/data/sparql/turtle.ts
	function parseTurtleText(turtleText) {
		return new Promise((resolve, reject) => {
			const triples = [];
			new n3.Parser().parse(turtleText, (error, triple, _hash) => {
				if (error) reject(error);
				else if (triple) triples.push({
					subject: n3toRdfNode(triple.subject),
					predicate: n3toRdfNode(triple.predicate),
					object: n3toRdfNode(triple.object)
				});
				else resolve(triples);
			});
		});
	}
	function n3toRdfNode(entity) {
		if (n3.Util.isLiteral(entity)) {
			const literal = entity;
			return {
				type: "literal",
				value: literal.value,
				datatype: literal.datatype.value,
				"xml:lang": literal.language
			};
		} else return {
			type: "uri",
			value: entity.value
		};
	}
	//#endregion
	//#region src/graph-explorer/data/sparql/sparqlDataProvider.ts
	var SparqlQueryMethod = /* @__PURE__ */ function(SparqlQueryMethod) {
		SparqlQueryMethod[SparqlQueryMethod["GET"] = 1] = "GET";
		SparqlQueryMethod[SparqlQueryMethod["POST"] = 2] = "POST";
		return SparqlQueryMethod;
	}({});
	var SparqlDataProvider = class {
		constructor(options, settings = OWLStatsSettings) {
			this.linkByPredicate = /* @__PURE__ */ new Map();
			this.linkById = /* @__PURE__ */ new Map();
			this.propertyByPredicate = /* @__PURE__ */ new Map();
			const { queryFunction = queryInternal } = options;
			this.options = {
				...options,
				queryFunction
			};
			this.settings = settings;
			for (const link of settings.linkConfigurations) {
				this.linkById.set(link.id, link);
				const predicate = isDirectLink(link) ? link.path : link.id;
				getOrCreateArrayInMap(this.linkByPredicate, predicate).push(link);
			}
			this.openWorldLinks = settings.linkConfigurations.length === 0 || Boolean(settings.openWorldLinks);
			for (const property of settings.propertyConfigurations) {
				const predicate = isDirectProperty(property) ? property.path : property.id;
				getOrCreateArrayInMap(this.propertyByPredicate, predicate).push(property);
			}
			this.openWorldProperties = settings.propertyConfigurations.length === 0 || Boolean(settings.openWorldProperties);
		}
		async classTree() {
			const { defaultPrefix, schemaLabelProperty, classTreeQuery } = this.settings;
			if (!classTreeQuery) return [];
			const query = defaultPrefix + resolveTemplate(classTreeQuery, { schemaLabelProperty });
			const classTree = getClassTree(await this.executeSparqlQuery(query));
			if (this.options.prepareLabels) await attachLabels(flattenClassTree(classTree), this.options.prepareLabels);
			return classTree;
		}
		async propertyInfo(params) {
			const { defaultPrefix, schemaLabelProperty, propertyInfoQuery } = this.settings;
			let properties;
			if (propertyInfoQuery) {
				const query = defaultPrefix + resolveTemplate(propertyInfoQuery, {
					ids: params.propertyIds.map(escapeIri).map((id) => ` ( ${id} )`).join(" "),
					schemaLabelProperty
				});
				properties = getPropertyInfo(await this.executeSparqlQuery(query));
			} else {
				properties = {};
				for (const id of params.propertyIds) properties[id] = {
					id,
					label: { values: [] }
				};
			}
			if (this.options.prepareLabels) await attachLabels(objectValues(properties), this.options.prepareLabels);
			return properties;
		}
		async classInfo(params) {
			const { defaultPrefix, schemaLabelProperty, classInfoQuery } = this.settings;
			let classes;
			if (classInfoQuery) {
				const query = defaultPrefix + resolveTemplate(classInfoQuery, {
					ids: params.classIds.map(escapeIri).map((id) => ` ( ${id} )`).join(" "),
					schemaLabelProperty
				});
				classes = getClassInfo(await this.executeSparqlQuery(query));
			} else classes = params.classIds.map((id) => ({
				id,
				label: { values: [] },
				children: []
			}));
			if (this.options.prepareLabels) await attachLabels(classes, this.options.prepareLabels);
			return classes;
		}
		async linkTypesInfo(params) {
			const { defaultPrefix, schemaLabelProperty, linkTypesInfoQuery } = this.settings;
			let linkTypes;
			if (linkTypesInfoQuery) {
				const query = defaultPrefix + resolveTemplate(linkTypesInfoQuery, {
					ids: params.linkTypeIds.map(escapeIri).map((id) => ` ( ${id} )`).join(" "),
					schemaLabelProperty
				});
				linkTypes = getLinkTypes(await this.executeSparqlQuery(query));
			} else linkTypes = params.linkTypeIds.map((id) => ({
				id,
				label: { values: [] }
			}));
			if (this.options.prepareLabels) await attachLabels(linkTypes, this.options.prepareLabels);
			return linkTypes;
		}
		async linkTypes() {
			const { defaultPrefix, schemaLabelProperty, linkTypesQuery, linkTypesPattern } = this.settings;
			if (!linkTypesQuery) return [];
			const query = defaultPrefix + resolveTemplate(linkTypesQuery, {
				linkTypesPattern,
				schemaLabelProperty
			});
			const linkTypes = getLinkTypes(await this.executeSparqlQuery(query));
			if (this.options.prepareLabels) await attachLabels(linkTypes, this.options.prepareLabels);
			return linkTypes;
		}
		async elementInfo(params) {
			const nonBlankResources = params.elementIds.filter((id) => !isEncodedBlank(id));
			const blankNodeResponse = this.options.acceptBlankNodes ? elementInfo(params.elementIds) : void 0;
			let triples;
			if (nonBlankResources.length > 0) {
				const ids = nonBlankResources.map(escapeIri).map((id) => ` (${id})`).join(" ");
				const { defaultPrefix, dataLabelProperty, elementInfoQuery } = this.settings;
				const query = defaultPrefix + resolveTemplate(elementInfoQuery, {
					ids,
					dataLabelProperty,
					propertyConfigurations: this.formatPropertyInfo()
				});
				triples = await this.executeSparqlConstruct(query);
			} else triples = [];
			const types = this.queryManyElementTypes(this.settings.propertyConfigurations.length > 0 ? params.elementIds : []);
			const elementModels = getElementsInfo(prependAdditionalBindings(triplesToElementBinding(triples), blankNodeResponse), await types, this.propertyByPredicate, this.openWorldProperties);
			if (this.options.prepareLabels) await attachLabels(objectValues(elementModels), this.options.prepareLabels);
			if (this.options.prepareImages) await prepareElementImages(this.options.prepareImages, elementModels);
			else if (this.options.imagePropertyUris && this.options.imagePropertyUris.length) await this.attachImages(elementModels, this.options.imagePropertyUris);
			return elementModels;
		}
		async attachImages(elementsInfo, types) {
			const ids = Object.keys(elementsInfo).filter((id) => !isEncodedBlank(id)).map(escapeIri).map((id) => ` ( ${id} )`).join(" ");
			const typesString = types.map(escapeIri).map((id) => ` ( ${id} )`).join(" ");
			const query = this.settings.defaultPrefix + `
            SELECT ?inst ?linkType ?image
            WHERE {{
                VALUES (?inst) {${ids}}
                VALUES (?linkType) {${typesString}}
                ${this.settings.imageQueryPattern}
            }}
        `;
			try {
				enrichElementsWithImages(await this.executeSparqlQuery(query), elementsInfo);
			} catch (err) {
				console.error(err);
			}
		}
		async linksInfo(params) {
			const nonBlankResources = params.elementIds.filter((id) => !isEncodedBlank(id));
			const blankNodeResponse = this.options.acceptBlankNodes ? linksInfo(params.elementIds) : void 0;
			const linkConfigurations = this.formatLinkLinks();
			let bindings;
			let types;
			if (nonBlankResources.length > 0) {
				const ids = nonBlankResources.map(escapeIri).map((id) => ` ( ${id} )`).join(" ");
				const linksInfoQuery = this.settings.defaultPrefix + resolveTemplate(this.settings.linksInfoQuery, {
					ids,
					linkConfigurations
				});
				bindings = this.executeSparqlQuery(linksInfoQuery);
				types = this.queryManyElementTypes(params.elementIds);
			} else {
				bindings = Promise.resolve({
					head: { vars: [] },
					results: { bindings: [] }
				});
				types = this.queryManyElementTypes([]);
			}
			return getLinksInfo(prependAdditionalBindings(await bindings, blankNodeResponse), await types, this.linkByPredicate, this.openWorldLinks);
		}
		async linkTypesOf(params) {
			if (this.options.acceptBlankNodes && isEncodedBlank(params.elementId)) return Promise.resolve(getLinksTypesOf(linkTypesOf(params)));
			const { defaultPrefix, linkTypesOfQuery, linkTypesStatisticsQuery, filterTypePattern } = this.settings;
			const elementIri = escapeIri(params.elementId);
			const forAll = this.formatLinkUnion(params.elementId, void 0, void 0, "?outObject", "?inObject", false);
			if (forAll.usePredicatePart) {
				forAll.unionParts.push(`{ ${elementIri} ?link ?outObject }`);
				forAll.unionParts.push(`{ ?inObject ?link ${elementIri} }`);
			}
			const query = defaultPrefix + resolveTemplate(linkTypesOfQuery, {
				elementIri,
				linkConfigurations: forAll.unionParts.join("\nUNION\n")
			});
			const linkTypeIds = getLinksTypeIds(await this.executeSparqlQuery(query), this.linkByPredicate, this.openWorldLinks);
			const navigateElementFilterOut = this.options.acceptBlankNodes ? `FILTER (IsIri(?outObject) || IsBlank(?outObject))` : `FILTER IsIri(?outObject)`;
			const navigateElementFilterIn = this.options.acceptBlankNodes ? `FILTER (IsIri(?inObject) || IsBlank(?inObject))` : `FILTER IsIri(?inObject)`;
			const foundLinkStats = [];
			await Promise.all(linkTypeIds.map(async (linkId) => {
				const linkConfig = this.linkById.get(linkId);
				let linkConfigurationOut;
				let linkConfigurationIn;
				if (!linkConfig || isDirectLink(linkConfig)) {
					const predicate = escapeIri(linkConfig && isDirectLink(linkConfig) ? linkConfig.path : linkId);
					linkConfigurationOut = `${elementIri} ${predicate} ?outObject`;
					linkConfigurationIn = `?inObject ${predicate} ${elementIri}`;
				} else {
					linkConfigurationOut = this.formatLinkPath(linkConfig.path, elementIri, "?outObject");
					linkConfigurationIn = this.formatLinkPath(linkConfig.path, "?inObject", elementIri);
				}
				if (linkConfig && linkConfig.domain?.length > 0) {
					const commaSeparatedDomains = linkConfig.domain.map(escapeIri).join(", ");
					const restrictionOut = filterTypePattern.replace(/[?$]inst\b/g, elementIri);
					const restrictionIn = filterTypePattern.replace(/[?$]inst\b/g, "?inObject");
					linkConfigurationOut += ` { ${restrictionOut} FILTER(?class IN (${commaSeparatedDomains})) }`;
					linkConfigurationIn += ` { ${restrictionIn} FILTER(?class IN (${commaSeparatedDomains})) }`;
				}
				const statsQuery = defaultPrefix + resolveTemplate(linkTypesStatisticsQuery, {
					linkId: escapeIri(linkId),
					elementIri,
					linkConfigurationOut,
					linkConfigurationIn,
					navigateElementFilterOut,
					navigateElementFilterIn
				});
				const linkStats = getLinkStatistics(await this.executeSparqlQuery(statsQuery));
				if (linkStats) foundLinkStats.push(linkStats);
			}));
			return foundLinkStats;
		}
		linkElements(params) {
			return this.filter({
				refElementId: params.elementId,
				refElementLinkId: params.linkId,
				linkDirection: params.direction,
				limit: params.limit,
				offset: params.offset,
				languageCode: ""
			});
		}
		async filter(baseParams) {
			const params = { ...baseParams };
			if (params.limit === void 0) params.limit = 100;
			const types = this.querySingleElementTypes(params.refElementId && this.settings.linkConfigurations.length > 0 ? params.refElementId : void 0);
			const blankFiltration = this.options.acceptBlankNodes ? filter(params) : void 0;
			if (blankFiltration && blankFiltration.results.bindings.length > 0) return getFilteredData(blankFiltration, await types, this.linkByPredicate, this.openWorldLinks);
			const filterQuery = this.createFilterQuery(params);
			const bindings = await this.executeSparqlQuery(filterQuery);
			let bindingsWithBlanks;
			if (this.options.acceptBlankNodes) bindingsWithBlanks = await updateFilterResults(bindings, (blankQuery) => this.executeSparqlQuery(blankQuery), this.settings);
			else bindingsWithBlanks = bindings;
			const elementModels = getFilteredData(bindingsWithBlanks, await types, this.linkByPredicate, this.openWorldLinks);
			if (this.options.prepareLabels) await attachLabels(objectValues(elementModels), this.options.prepareLabels);
			return elementModels;
		}
		createFilterQuery(params) {
			if (!params.refElementId && params.refElementLinkId) throw new Error("Cannot execute refElementLink filter without refElement");
			let outerProjection = "?inst ?class ?label ?blankType";
			let innerProjection = "?inst";
			let refQueryPart = "";
			let refQueryTypes = "";
			if (params.refElementId) {
				outerProjection += " ?link ?direction";
				innerProjection += " ?link ?direction";
				refQueryPart = this.createRefQueryPart({
					elementId: params.refElementId,
					linkId: params.refElementLinkId,
					direction: params.linkDirection
				});
				if (this.settings.linkConfigurations.length > 0) {
					outerProjection += " ?classAll";
					refQueryTypes = this.settings.filterTypePattern.replace(/[?$]class\b/g, "?classAll");
				}
			}
			let elementTypePart = "";
			if (params.elementTypeId) {
				const elementTypeIri = escapeIri(params.elementTypeId);
				elementTypePart = this.settings.filterTypePattern.replace(/[?$]class\b/g, elementTypeIri);
				elementTypePart += " .";
			}
			const { defaultPrefix, fullTextSearch, dataLabelProperty } = this.settings;
			let textSearchPart = "";
			if (params.text) {
				innerProjection += " ?score";
				if (this.settings.fullTextSearch.extractLabel) textSearchPart += sparqlExtractLabel("?inst", "?extractedLabel");
				if (fullTextSearch.queryPatternPerWord) textSearchPart = params.text.trim().split(/\s+/).filter(Boolean).map((word) => resolveTemplate(fullTextSearch.queryPatternPerWord, {
					word: escapeSparqlStringLiteral(word),
					dataLabelProperty
				})).join("\n") + "\nBIND(0 as ?score)";
				else textSearchPart = resolveTemplate(fullTextSearch.queryPattern, {
					text: params.text,
					dataLabelProperty
				});
			}
			const blankNodes = this.options.acceptBlankNodes;
			if (blankNodes) outerProjection += ` ${BLANK_NODE_QUERY_PARAMETERS}`;
			return `${defaultPrefix}
            ${fullTextSearch.prefix}

        SELECT ${outerProjection}
        WHERE {
            {
                SELECT DISTINCT ${innerProjection} WHERE {
                    ${fullTextSearch.elementFirst ? "" : textSearchPart}
                    ${elementTypePart}
                    ${refQueryPart}
                    ${fullTextSearch.elementFirst ? textSearchPart : ""}
                    ${this.settings.filterAdditionalRestriction}
                }
                ${textSearchPart ? "ORDER BY DESC(?score)" : ""}
                LIMIT ${params.limit} OFFSET ${params.offset}
            }
            ${refQueryTypes}
            ${resolveTemplate(this.settings.filterElementInfoPattern, { dataLabelProperty })}
            ${blankNodes ? BLANK_NODE_QUERY : ""}
        } ${textSearchPart ? "ORDER BY DESC(?score)" : ""}
        `;
		}
		executeSparqlQuery(query) {
			const method = this.options.queryMethod ? this.options.queryMethod : 1;
			return executeSparqlQuery(this.options.endpointUrl, query, method, this.options.queryFunction);
		}
		executeSparqlConstruct(query) {
			const method = this.options.queryMethod ? this.options.queryMethod : 1;
			return executeSparqlConstruct(this.options.endpointUrl, query, method, this.options.queryFunction);
		}
		createRefQueryPart(params) {
			const { elementId, linkId, direction } = params;
			const { unionParts, usePredicatePart } = this.formatLinkUnion(elementId, linkId, direction, "?inst", "?inst", true);
			if (usePredicatePart) {
				const refElementIRI = escapeIri(params.elementId);
				let refLinkType;
				if (linkId) {
					const link = this.linkById.get(linkId);
					refLinkType = link && isDirectLink(link) ? escapeIri(link.path) : escapeIri(linkId);
				}
				const linkPattern = refLinkType || "?link";
				const bindType = refLinkType ? `BIND(${refLinkType} as ?link)` : "";
				const blankFilter = this.options.acceptBlankNodes ? "FILTER(isIri(?inst) || isBlank(?inst))" : "FILTER(isIri(?inst))";
				if (!direction || direction === "out") unionParts.push(`{ ${refElementIRI} ${linkPattern} ?inst BIND("out" as ?direction) ${bindType} ${blankFilter} }`);
				if (!direction || direction === "in") unionParts.push(`{ ?inst ${linkPattern} ${refElementIRI} BIND("in" as ?direction) ${bindType} ${blankFilter} }`);
			}
			let resultPattern = unionParts.length === 0 ? "FILTER(false)" : unionParts.join(`\nUNION\n`);
			if (!linkId && this.settings.filterRefElementLinkPattern.length > 0) resultPattern += `\n${this.settings.filterRefElementLinkPattern}`;
			return resultPattern;
		}
		formatLinkUnion(refElementIri, linkIri, direction, outElementVar, inElementVar, bindDirection) {
			const { linkConfigurations } = this.settings;
			const fixedIri = escapeIri(refElementIri);
			const unionParts = [];
			let hasDirectLink = false;
			for (const link of linkConfigurations) {
				if (linkIri && link.id !== linkIri) continue;
				if (isDirectLink(link)) hasDirectLink = true;
				else {
					const linkType = escapeIri(link.id);
					if (!direction || direction === "out") {
						const path = this.formatLinkPath(link.path, fixedIri, outElementVar);
						const boundedDirection = bindDirection ? `BIND("out" as ?direction) ` : "";
						unionParts.push(`{ ${path} BIND(${linkType} as ?link) ${boundedDirection}}`);
					}
					if (!direction || direction === "in") {
						const path = this.formatLinkPath(link.path, inElementVar, fixedIri);
						const boundedDirection = bindDirection ? `BIND("in" as ?direction) ` : "";
						unionParts.push(`{ ${path} BIND(${linkType} as ?link) ${boundedDirection}}`);
					}
				}
			}
			return {
				unionParts,
				usePredicatePart: this.openWorldLinks || hasDirectLink
			};
		}
		formatLinkLinks() {
			const unionParts = [];
			let hasDirectLink = false;
			for (const link of this.settings.linkConfigurations) if (isDirectLink(link)) hasDirectLink = true;
			else {
				const linkType = escapeIri(link.id);
				unionParts.push(`{ ${this.formatLinkPath(link.path, "?source", "?target")} BIND(${linkType} as ?type) }`);
			}
			if (this.openWorldLinks || hasDirectLink) unionParts.push(`{ ?source ?type ?target }`);
			return unionParts.join("\nUNION\n");
		}
		formatLinkPath(path, source, target) {
			return path.replace(/[?$]source\b/g, source).replace(/[?$]target\b/g, target);
		}
		formatPropertyInfo() {
			const unionParts = [];
			let hasDirectProperty = false;
			for (const property of this.settings.propertyConfigurations) if (isDirectProperty(property)) hasDirectProperty = true;
			else {
				const propType = escapeIri(property.id);
				const formatted = this.formatPropertyPath(property.path, "?inst", "?propValue");
				unionParts.push(`{ ${formatted} BIND(${propType} as ?propType) }`);
			}
			if (this.openWorldProperties || hasDirectProperty) unionParts.push(`{ ?inst ?propType ?propValue }`);
			return unionParts.join("\nUNION\n");
		}
		formatPropertyPath(path, subject, value) {
			return path.replace(/[?$]inst\b/g, subject).replace(/[?$]value\b/g, value);
		}
		async querySingleElementTypes(element) {
			return (await this.queryManyElementTypes(element ? [element] : [])).get(element);
		}
		async queryManyElementTypes(elements) {
			if (elements.length === 0) return /* @__PURE__ */ new Map();
			const { filterTypePattern } = this.settings;
			const ids = elements.filter((iri) => !isEncodedBlank(iri)).map((iri) => `(${escapeIri(iri)})`).join(" ");
			const query = resolveTemplate(this.settings.defaultPrefix + `SELECT ?inst ?class { VALUES(?inst) { \${ids} } \${filterTypePattern} }`, {
				ids,
				filterTypePattern
			});
			let response = await this.executeSparqlQuery(query);
			if (this.options.acceptBlankNodes && elements.find(isEncodedBlank)) {
				const blankResponse = getElementTypes$1(elements);
				response = prependAdditionalBindings(response, blankResponse);
			}
			return getElementTypes(response);
		}
	};
	async function attachLabels(items, fetchLabels) {
		const resources = /* @__PURE__ */ new Set();
		for (const item of items) {
			if (isEncodedBlank(item.id)) continue;
			resources.add(item.id);
		}
		const labels = await fetchLabels(resources);
		for (const item of items) if (labels.has(item.id)) item.label = { values: labels.get(item.id) };
	}
	function prepareElementImages(fetchImages, elementsInfo) {
		return fetchImages(elementsInfo).then((images) => {
			for (const iri in images) if (Object.prototype.hasOwnProperty.call(images, iri) && elementsInfo[iri]) elementsInfo[iri].image = images[iri];
		});
	}
	function resolveTemplate(template, values) {
		let result = template;
		for (const replaceKey in values) {
			if (!Object.prototype.hasOwnProperty.call(values, replaceKey)) continue;
			const replaceValue = values[replaceKey];
			if (replaceValue) result = result.replace(new RegExp("\\${" + replaceKey + "}", "g"), replaceValue);
		}
		return result;
	}
	function executeSparqlQuery(endpoint, query, method, queryFunction) {
		let internalQuery;
		if (method === 1) internalQuery = queryFunction({
			url: appendQueryParams(endpoint, { query }),
			headers: { Accept: "application/sparql-results+json" },
			method: "GET"
		});
		else internalQuery = queryFunction({
			url: endpoint,
			body: query,
			headers: {
				Accept: "application/sparql-results+json",
				"Content-Type": "application/sparql-query; charset=UTF-8"
			},
			method: "POST"
		});
		return internalQuery.then((response) => {
			if (response.ok) return response.json();
			else {
				const error = new Error(response.statusText);
				error.response = response;
				throw error;
			}
		});
	}
	function executeSparqlConstruct(endpoint, query, method, queryFunction) {
		let internalQuery;
		if (method === 1) internalQuery = queryFunction({
			url: appendQueryParams(endpoint, { query }),
			headers: { Accept: "text/turtle" },
			method: "GET"
		});
		else internalQuery = queryFunction({
			url: endpoint,
			body: query,
			headers: {
				Accept: "text/turtle",
				"Content-Type": "application/sparql-query; charset=UTF-8"
			},
			method: "POST"
		});
		return internalQuery.then((response) => {
			if (response.ok) return response.text();
			else {
				const error = new Error(response.statusText);
				error.response = response;
				throw error;
			}
		}).then(parseTurtleText);
	}
	function appendQueryParams(endpoint, queryParams = {}) {
		return endpoint + ((endpoint.indexOf("?") < 0 ? "?" : "&") + Object.keys(queryParams).map((key) => `${key}=${encodeURIComponent(queryParams[key])}`).join("&"));
	}
	function queryInternal(params) {
		return fetch(params.url, {
			method: params.method,
			body: params.body,
			credentials: "same-origin",
			mode: "cors",
			cache: "default",
			headers: params.headers
		});
	}
	function sparqlExtractLabel(subject, label) {
		return `
        BIND ( str( ${subject} ) as ?uriStr)
        BIND ( strafter(?uriStr, "#") as ?label3)
        BIND ( strafter(strafter(?uriStr, "//"), "/") as ?label6)
        BIND ( strafter(?label6, "/") as ?label5)
        BIND ( strafter(?label5, "/") as ?label4)
        BIND (if (?label3 != "", ?label3,
            if (?label4 != "", ?label4,
            if (?label5 != "", ?label5, ?label6))) as ${label})
    `;
	}
	function escapeIri(iri) {
		if (typeof iri !== "string") throw new Error(`Cannot escape IRI of type "${typeof iri}"`);
		return `<${iri}>`;
	}
	/** Escapes a value for embedding in a double-quoted SPARQL string literal. */
	function escapeSparqlStringLiteral(value) {
		return value.replace(/\\/g, "\\\\").replace(/"/g, "\\\"").replace(/\n/g, "\\n").replace(/\r/g, "\\r");
	}
	//#endregion
	//#region src/graph-explorer/data/composite/mergeUtils.ts
	var DATA_PROVIDER_PROPERTY = "http://graph-explorer.org/property/DataProvider";
	function mergeClassTree(composite) {
		const lists = composite.filter((r) => r.response).map(({ useInStats, response }) => ({
			useInStats,
			classes: classTreeToArray(response)
		}));
		const dictionary = {};
		const topLevelModels = {};
		const childrenMap = {};
		for (const { useInStats, classes } of lists) for (const model of classes) {
			const childrenIds = childrenMap[model.id] || [];
			model.children.map((ch) => ch.id).forEach((id) => {
				if (childrenIds.indexOf(id) === -1) childrenIds.push(id);
			});
			model.children = [];
			if (!useInStats) delete model.count;
			if (!dictionary[model.id]) {
				topLevelModels[model.id] = model;
				dictionary[model.id] = model;
				childrenMap[model.id] = childrenIds;
			} else {
				topLevelModels[model.id] = mergeClassModel(dictionary[model.id], model);
				dictionary[model.id] = topLevelModels[model.id];
			}
		}
		const models = Object.keys(dictionary).map((key) => dictionary[key]);
		for (const m of models) m.children = (childrenMap[m.id] || []).map((id) => {
			delete topLevelModels[id];
			return dictionary[id];
		});
		return Object.keys(topLevelModels).map((key) => topLevelModels[key]);
	}
	function mergePropertyInfo(response) {
		const result = {};
		const props = response.filter((r) => r.response).map((r) => r.response);
		for (const model of props) {
			const keys = Object.keys(model);
			for (const key of keys) {
				const prop = model[key];
				if (!result[key]) result[key] = prop;
				else result[key].label = mergeLabels(result[key].label, prop.label);
			}
		}
		return result;
	}
	function mergeClassInfo(response) {
		const dictionaries = response.filter((r) => r.response).map((r) => r.response);
		const dictionary = {};
		for (const models of dictionaries) for (const model of models) if (!dictionary[model.id]) dictionary[model.id] = model;
		else dictionary[model.id] = mergeClassModel(dictionary[model.id], model);
		return Object.keys(dictionary).map((key) => dictionary[key]);
	}
	function mergeLinkTypesInfo(response) {
		const lists = response.filter((r) => r.response).map((r) => r.response);
		const mergeLinkType = (a, b) => {
			return {
				id: a.id,
				label: mergeLabels(a.label, b.label),
				count: a.count + b.count
			};
		};
		const dictionary = {};
		for (const linkTypes of lists) for (const linkType of linkTypes) if (!dictionary[linkType.id]) dictionary[linkType.id] = linkType;
		else dictionary[linkType.id] = mergeLinkType(dictionary[linkType.id], linkType);
		return Object.keys(dictionary).map((key) => dictionary[key]);
	}
	function mergeLinkTypes(response) {
		return mergeLinkTypesInfo(response);
	}
	function mergeElementInfo(response) {
		const mergeElementModels = (a, b) => {
			const types = a.types;
			for (const t of b.types) if (types.indexOf(t) === -1) types.push(t);
			const sources = [];
			for (const s of a.sources) if (sources.indexOf(s) === -1) sources.push(s);
			for (const s of b.sources) if (sources.indexOf(s) === -1) sources.push(s);
			return {
				id: a.id,
				label: mergeLabels(a.label, b.label),
				types,
				image: a.image || b.image,
				properties: mergeProperties(a.properties, b.properties),
				sources
			};
		};
		const dictionary = {};
		for (const resp of response) {
			if (!resp.response) continue;
			const list = Object.keys(resp.response).map((k) => resp.response[k]);
			for (const em of list) {
				em.sources = [resp.dataSourceName];
				em.properties[DATA_PROVIDER_PROPERTY] = {
					type: "string",
					values: [{
						value: resp.dataSourceName,
						language: ""
					}]
				};
				if (!dictionary[em.id]) dictionary[em.id] = em;
				else dictionary[em.id] = mergeElementModels(dictionary[em.id], em);
			}
		}
		return dictionary;
	}
	function mergeProperties(a, b) {
		const aLists = Object.keys(a);
		const bLists = Object.keys(b);
		const result = {};
		function createIdForProperty(baseId) {
			let counter = 1;
			while (result[baseId + "_" + counter]) counter++;
			return baseId + "_" + counter;
		}
		for (const pKey of aLists) {
			const prop = a[pKey];
			if (!result[pKey]) result[pKey] = prop;
			else result[createIdForProperty(pKey)] = prop;
		}
		for (const pKey of bLists) {
			const prop = b[pKey];
			if (!result[pKey]) result[pKey] = prop;
			else result[createIdForProperty(pKey)] = prop;
		}
		return result;
	}
	function mergeLinksInfo(response) {
		const lists = response.filter((r) => r.response).map((r) => r.response);
		const resultInfo = [];
		function compareLinksInfo(a, b) {
			return a.sourceId === b.sourceId && a.targetId === b.targetId && a.linkTypeId === b.linkTypeId;
		}
		for (const linkInfo of lists) for (const linkModel of linkInfo) if (!resultInfo.some((l) => compareLinksInfo(l, linkModel))) resultInfo.push(linkModel);
		return resultInfo;
	}
	function mergeLinkTypesOf(response) {
		const lists = response.filter((r) => r.response).map((r) => r.response);
		const dictionary = {};
		const merge = (a, b) => {
			return {
				id: a.id,
				inCount: a.inCount + b.inCount,
				outCount: a.outCount + b.outCount
			};
		};
		for (const linkCount of lists) for (const lCount of linkCount) if (!dictionary[lCount.id]) dictionary[lCount.id] = lCount;
		else dictionary[lCount.id] = merge(lCount, dictionary[lCount.id]);
		return Object.keys(dictionary).map((key) => dictionary[key]);
	}
	function mergeLinkElements(response) {
		return mergeElementInfo(response);
	}
	function mergeFilter(response) {
		return mergeElementInfo(response);
	}
	function classTreeToArray(models) {
		let resultArray = models;
		function getDescendants(model) {
			let descendants = model.children || [];
			for (const descendant of descendants) {
				const nextGeneration = getDescendants(descendant);
				descendants = descendants.concat(nextGeneration);
			}
			return descendants;
		}
		for (const model of models) {
			const descendants = getDescendants(model);
			resultArray = resultArray.concat(descendants);
		}
		return resultArray;
	}
	function mergeLabels(a, b) {
		function compareLabels(l1, l2) {
			return l1.language === l2.language && l1.value === l2.value;
		}
		const mergedValuesList = a.values;
		for (const locStr of b.values) if (!mergedValuesList.some((l) => compareLabels(l, locStr))) mergedValuesList.push(locStr);
		return { values: mergedValuesList };
	}
	function mergeCounts(a, b) {
		if (a === void 0 && b === void 0) return;
		return (a || 0) + (b || 0);
	}
	function mergeClassModel(a, b) {
		const childrenDictionary = {};
		for (const child of a.children.concat(b.children)) if (!childrenDictionary[child.id]) childrenDictionary[child.id] = child;
		return {
			id: a.id,
			label: mergeLabels(a.label, b.label),
			count: mergeCounts(a.count, b.count),
			children: Object.keys(childrenDictionary).map((key) => childrenDictionary[key])
		};
	}
	//#endregion
	//#region src/graph-explorer/data/composite/composite.ts
	function isDefinition(dp) {
		const definition = dp;
		return definition.name !== void 0 && definition.dataProvider !== void 0;
	}
	var CompositeDataProvider = class {
		constructor(dataProviders, params) {
			this.mergeMode = "fetchAll";
			let dpCounter = 1;
			this.dataProviders = dataProviders.map((dp) => {
				if (isDefinition(dp)) return dp;
				else return {
					name: "dataProvider_" + dpCounter++,
					dataProvider: dp
				};
			});
			if (params && params.mergeMode) this.mergeMode = params.mergeMode;
		}
		classTree() {
			return this.fetchSequentially("classTree", mergeClassTree, void 0);
		}
		propertyInfo(params) {
			if (this.mergeMode === "fetchAll") return this.fetchSequentially("propertyInfo", mergePropertyInfo, params);
			else {
				let propertyIds = params.propertyIds;
				return this.queueProcessResults((previousResult, dp) => {
					propertyIds = propertyIds.filter((id) => !previousResult || !previousResult[id]);
					return propertyIds.length > 0 ? dp.dataProvider.propertyInfo({ propertyIds }) : void 0;
				}).then(mergePropertyInfo);
			}
		}
		classInfo(params) {
			if (this.mergeMode === "fetchAll") return this.fetchSequentially("classInfo", mergeClassInfo, params);
			else {
				let classIds = params.classIds;
				return this.queueProcessResults((previousResult, dp) => {
					classIds = classIds.filter((id) => !previousResult || previousResult.map((cm) => cm.id).indexOf(id) === -1);
					return classIds.length > 0 ? dp.dataProvider.classInfo({ classIds }) : void 0;
				}).then(mergeClassInfo);
			}
		}
		linkTypesInfo(params) {
			if (this.mergeMode === "fetchAll") return this.fetchSequentially("linkTypesInfo", mergeLinkTypesInfo, params);
			else {
				let linkTypeIds = params.linkTypeIds;
				return this.queueProcessResults((previousResult, dp) => {
					linkTypeIds = linkTypeIds.filter((id) => !previousResult || previousResult.map((lt) => lt.id).indexOf(id) === -1);
					return linkTypeIds.length > 0 ? dp.dataProvider.linkTypesInfo({ linkTypeIds }) : void 0;
				}).then(mergeLinkTypesInfo);
			}
		}
		linkTypes() {
			return this.fetchSequentially("linkTypes", mergeLinkTypes, void 0);
		}
		elementInfo(params) {
			if (this.mergeMode === "fetchAll") return this.fetchSequentially("elementInfo", mergeElementInfo, params);
			else {
				let elementIds = params.elementIds;
				return this.queueProcessResults((previousResult, dp) => {
					elementIds = elementIds.filter((id) => !previousResult || !previousResult[id]);
					return elementIds.length > 0 ? dp.dataProvider.elementInfo({ elementIds }) : void 0;
				}).then(mergeElementInfo);
			}
		}
		linksInfo(params) {
			if (this.mergeMode === "fetchAll") return this.fetchSequentially("linksInfo", mergeLinksInfo, params);
			else {
				let elementIds = params.elementIds;
				return this.queueProcessResults((previousResult, dp) => {
					elementIds = elementIds.filter((id) => {
						if (previousResult) {
							for (const linkModel of previousResult) if (linkModel.sourceId === id) return false;
						}
						return true;
					});
					return elementIds.length > 0 ? dp.dataProvider.linksInfo({
						elementIds,
						linkTypeIds: params.linkTypeIds
					}) : void 0;
				}).then(mergeLinksInfo);
			}
		}
		linkTypesOf(params) {
			if (this.mergeMode === "fetchAll") return this.fetchSequentially("linkTypesOf", mergeLinkTypesOf, params);
			else return this.queueProcessResults((previousResult, dp) => {
				if (!previousResult || previousResult && previousResult.length === 0) return dp.dataProvider.linkTypesOf(params);
				else return;
			}).then(mergeLinkTypesOf);
		}
		linkElements(params) {
			if (this.mergeMode === "fetchAll") return this.fetchSequentially("linkElements", mergeLinkElements, params);
			else return this.queueProcessResults((previousResult, dp) => {
				if (!previousResult || previousResult && Object.keys(previousResult).length === 0) return dp.dataProvider.linkElements(params);
				else return;
			}).then(mergeLinkElements);
		}
		filter(params) {
			if (this.mergeMode === "fetchAll") return this.fetchSequentially("filter", mergeFilter, params);
			else return this.queueProcessResults((previousResult, dp) => {
				if (!previousResult || previousResult && Object.keys(previousResult).length === 0) return dp.dataProvider.filter(params);
				else return;
			}).then(mergeFilter);
		}
		processResults(responsePromise, dpName, useProviderInStats) {
			return responsePromise.then((response) => ({
				dataSourceName: dpName,
				useInStats: useProviderInStats,
				response
			})).catch((error) => {
				console.error(error);
				return {
					dataSourceName: dpName,
					useInStats: useProviderInStats,
					response: void 0
				};
			});
		}
		queueProcessResults(callBack) {
			let counter = 0;
			const responseList = [];
			const recursiveCall = (result) => {
				if (this.dataProviders.length > counter) {
					const dp = this.dataProviders[counter++];
					const callBackResult = callBack(result, dp);
					if (!callBackResult) return Promise.resolve(responseList);
					return callBackResult.then((newResult) => {
						responseList.push({
							dataSourceName: dp.name,
							response: newResult
						});
						return recursiveCall(newResult);
					}).catch((error) => {
						console.error(error);
						return recursiveCall(result);
					});
				} else return Promise.resolve(responseList);
			};
			return recursiveCall();
		}
		fetchSequentially(functionName, mergeFunction, params) {
			const resultPromises = this.dataProviders.map((dp) => {
				const providerMethod = dp.dataProvider[functionName];
				return this.processResults(providerMethod.call(dp.dataProvider, params), dp.name, dp.useInStats);
			});
			return Promise.all(resultPromises).then(mergeFunction);
		}
	};
	//#endregion
	//#region src/graph-explorer/editor/serializedDiagram.ts
	var serializedCellProperties = [
		"id",
		"type",
		"size",
		"angle",
		"isExpanded",
		"position",
		"iri",
		"group",
		"typeId",
		"source",
		"target",
		"vertices"
	];
	function emptyDiagram() {
		return {
			"@context": DIAGRAM_CONTEXT_URL_V1,
			"@type": "Diagram",
			layoutData: emptyLayoutData(),
			linkTypeOptions: []
		};
	}
	function emptyLayoutData() {
		return {
			"@type": "Layout",
			elements: [],
			links: []
		};
	}
	function convertToSerializedDiagram(params) {
		const elements = [];
		const links = [];
		for (const cell of params.layoutData.cells) {
			const newCell = (0, lodash.pick)(cell, serializedCellProperties);
			if (newCell.type === "GraphExplorer.Element" || newCell.type === "element") newCell.type = "Element";
			if (newCell.type === "link") newCell.type = "Link";
			if (!newCell.iri) newCell.iri = newCell.id;
			newCell["@id"] = newCell.id;
			delete newCell.id;
			newCell["@type"] = newCell.type;
			delete newCell.type;
			switch (newCell["@type"]) {
				case "Element":
					elements.push(newCell);
					break;
				case "Link":
					newCell.source["@id"] = newCell.source.id;
					delete newCell.source.id;
					newCell.target["@id"] = newCell.target.id;
					delete newCell.target.id;
					newCell.property = newCell.typeId;
					delete newCell.typeId;
					links.push(newCell);
					break;
			}
		}
		return {
			...emptyDiagram(),
			layoutData: {
				"@type": "Layout",
				elements,
				links
			},
			linkTypeOptions: params.linkTypeOptions
		};
	}
	function makeSerializedDiagram(params) {
		const diagram = {
			...emptyDiagram(),
			linkTypeOptions: params.linkTypeOptions
		};
		if (params.layoutData) diagram.layoutData = params.layoutData;
		return diagram;
	}
	function makeLayoutData(modelElements, modelLinks) {
		return {
			"@type": "Layout",
			elements: modelElements.map((element) => ({
				"@type": "Element",
				"@id": element.id,
				iri: element.iri,
				position: element.position,
				size: element.size,
				isExpanded: element.isExpanded,
				group: element.group,
				elementState: element.elementState
			})),
			links: modelLinks.map((link) => ({
				"@type": "Link",
				"@id": link.id,
				property: link.typeId,
				source: { "@id": link.sourceId },
				target: { "@id": link.targetId },
				vertices: [...link.vertices],
				linkState: link.linkState
			}))
		};
	}
	//#endregion
	//#region src/graph-explorer/viewUtils/layout.ts
	function groupForceLayout(params) {
		new webcola.Layout().nodes(params.nodes).links(params.links).avoidOverlaps(params.avoidOvelaps).convergenceThreshold(1e-9).jaccardLinkLengths(params.preferredLinkLength).handleDisconnected(true).start(30, 0, 10, void 0, false);
	}
	function groupRemoveOverlaps(nodes) {
		const nodeRectangles = [];
		for (const node of nodes) nodeRectangles.push(new webcola.Rectangle(node.x, node.x + node.width, node.y, node.y + node.height));
		webcola.removeOverlaps(nodeRectangles);
		for (let i = 0; i < nodeRectangles.length; i++) {
			const node = nodes[i];
			const rectangle = nodeRectangles[i];
			node.x = rectangle.x;
			node.y = rectangle.y;
		}
	}
	function translateToPositiveQuadrant(positions, offset) {
		let minX = Infinity, minY = Infinity;
		positions.forEach((position) => {
			minX = Math.min(minX, position.x);
			minY = Math.min(minY, position.y);
		});
		const { x, y } = offset;
		positions.forEach((position, key) => {
			positions.set(key, {
				x: position.x - minX + x,
				y: position.y - minY + y
			});
		});
	}
	function uniformGrid(params) {
		return (cellIndex) => {
			const row = Math.floor(cellIndex / params.rows);
			return {
				x: (cellIndex - row * params.rows) * params.cellSize.x,
				y: row * params.cellSize.y,
				width: params.cellSize.x,
				height: params.cellSize.y
			};
		};
	}
	function padded(nodes, padding, transform) {
		if (padding) for (const node of nodes) {
			node.x -= padding.x;
			node.y -= padding.y;
			node.width += 2 * padding.x;
			node.height += 2 * padding.y;
		}
		transform();
		if (padding) for (const node of nodes) {
			node.x += padding.x;
			node.y += padding.y;
			node.width -= 2 * padding.x;
			node.height -= 2 * padding.y;
		}
	}
	function biasFreePadded(nodes, padding, transform) {
		const nodeSizeMap = /* @__PURE__ */ new Map();
		const possibleCompression = {
			x: Infinity,
			y: Infinity
		};
		for (const node of nodes) {
			nodeSizeMap.set(node.id, {
				width: node.width,
				height: node.height
			});
			const maxSide = Math.max(node.width, node.height);
			const compressionX = node.width ? maxSide / node.width : 1;
			const compressionY = node.height ? maxSide / node.height : 1;
			possibleCompression.x = Math.min(1 + (compressionX - 1), possibleCompression.x);
			possibleCompression.y = Math.min(1 + (compressionY - 1), possibleCompression.y);
			node.height = maxSide;
			node.width = maxSide;
		}
		padded(nodes, padding, () => transform());
		const fittingBox = getContentFittingBoxForLayout(nodes);
		for (const node of nodes) {
			const size = nodeSizeMap.get(node.id);
			node.x = (node.x - fittingBox.x) / possibleCompression.x + fittingBox.x;
			node.y = (node.y - fittingBox.y) / possibleCompression.y + fittingBox.y;
			node.height = size.height;
			node.width = size.width;
		}
	}
	function calculateLayout(params) {
		const grouping = computeGrouping(params.model.elements);
		const { layoutFunction, model, fixedElements, selectedElements } = params;
		if (selectedElements && selectedElements.size <= 1) return {
			positions: /* @__PURE__ */ new Map(),
			nestedLayouts: [],
			keepAveragePosition: false
		};
		return internalRecursion(params.group);
		function internalRecursion(group) {
			const elementsToProcess = group ? grouping.get(group) : model.elements.filter((el) => el.group === void 0);
			const elements = selectedElements ? elementsToProcess.filter((el) => selectedElements.has(el)) : elementsToProcess;
			const nestedLayouts = [];
			for (const element of elements) if (grouping.has(element.id)) nestedLayouts.push(internalRecursion(element.id));
			const nodes = [];
			const nodeById = {};
			for (const element of elements) {
				const { x, y, width, height } = boundsOf(element);
				const node = {
					id: element.id,
					x,
					y,
					width,
					height,
					fixed: fixedElements && fixedElements.has(element) ? 1 : 0
				};
				nodeById[element.id] = node;
				nodes.push(node);
			}
			const links = [];
			for (const link of model.links) {
				if (!model.isSourceAndTargetVisible(link)) continue;
				const source = model.sourceOf(link);
				const target = model.targetOf(link);
				const sourceNode = nodeById[source.id];
				const targetNode = nodeById[target.id];
				if (sourceNode && targetNode) links.push({
					source: sourceNode,
					target: targetNode
				});
			}
			layoutFunction(nodes, links, group);
			const positions = /* @__PURE__ */ new Map();
			for (const node of nodes) positions.set(node.id, {
				x: node.x,
				y: node.y
			});
			return {
				positions,
				group,
				nestedLayouts,
				keepAveragePosition: Boolean(selectedElements)
			};
		}
	}
	function applyLayout(model, layout) {
		const { positions, group, nestedLayouts, keepAveragePosition } = layout;
		const elements = model.elements.filter(({ id }) => positions.has(id));
		for (const nestedLayout of nestedLayouts) applyLayout(model, nestedLayout);
		if (group) translateToPositiveQuadrant(positions, getContentFittingBox(elements, []));
		const averagePosition = keepAveragePosition ? calculateAveragePosition(elements) : void 0;
		for (const element of elements) element.setPosition(positions.get(element.id));
		if (keepAveragePosition) {
			const newAveragePosition = calculateAveragePosition(elements);
			const averageDiff = {
				x: averagePosition.x - newAveragePosition.x,
				y: averagePosition.y - newAveragePosition.y
			};
			positions.forEach((position, elementId) => {
				model.getElement(elementId).setPosition({
					x: position.x + averageDiff.x,
					y: position.y + averageDiff.y
				});
			});
		}
	}
	function calculateAveragePosition(position) {
		let xSum = 0;
		let ySum = 0;
		for (const element of position) {
			xSum += element.position.x + element.size.width / 2;
			ySum += element.position.y + element.size.height / 2;
		}
		return {
			x: xSum / position.length,
			y: ySum / position.length
		};
	}
	function placeElementsAround(params) {
		const { model, elements, targetElement, prefferedLinksLength } = params;
		const targetElementBounds = boundsOf(targetElement);
		const targetPosition = {
			x: targetElementBounds.x + targetElementBounds.width / 2,
			y: targetElementBounds.y + targetElementBounds.height / 2
		};
		let outgoingAngle = 0;
		if (targetElement.links.length > 0) {
			const averageSourcePosition = calculateAveragePosition(targetElement.links.map((link) => {
				const linkSource = model.sourceOf(link);
				return linkSource !== targetElement ? linkSource : model.targetOf(link);
			}));
			const vectorDiff = {
				x: targetPosition.x - averageSourcePosition.x,
				y: targetPosition.y - averageSourcePosition.y
			};
			if (vectorDiff.x !== 0 || vectorDiff.y !== 0) outgoingAngle = Math.atan2(vectorDiff.y, vectorDiff.x);
		}
		const step = Math.min(Math.PI / elements.length, Math.PI / 6);
		const elementsSteck = [].concat(elements);
		const placeElementFromSteck = (curAngle, element) => {
			if (element) {
				const size = element.size;
				element.setPosition({
					x: targetPosition.x + prefferedLinksLength * Math.cos(curAngle) - size.width / 2,
					y: targetPosition.y + prefferedLinksLength * Math.sin(curAngle) - size.height / 2
				});
			}
		};
		if (elementsSteck.length % 2 === 0) for (let angle = step / 2; elementsSteck.length > 0; angle += step) {
			placeElementFromSteck(outgoingAngle - angle, elementsSteck.pop());
			placeElementFromSteck(outgoingAngle + angle, elementsSteck.pop());
		}
		else {
			placeElementFromSteck(outgoingAngle, elementsSteck.pop());
			for (let angle = step; elementsSteck.length > 0; angle += step) {
				placeElementFromSteck(outgoingAngle - angle, elementsSteck.pop());
				placeElementFromSteck(outgoingAngle + angle, elementsSteck.pop());
			}
		}
		return new Promise((resolve) => {
			const listener = new EventObserver();
			listener.listen(model.events, "changeCells", () => {
				listener.stopListening();
				removeOverlaps({
					model,
					padding: {
						x: 15,
						y: 15
					}
				});
				resolve(true);
			});
		});
	}
	function removeOverlaps(params) {
		const { padding, model, group, fixedElements, selectedElements } = params;
		return calculateLayout({
			model,
			group,
			fixedElements,
			selectedElements,
			layoutFunction: (nodes) => {
				padded(nodes, padding, () => groupRemoveOverlaps(nodes));
			}
		});
	}
	function forceLayout(params) {
		const { model, group, fixedElements, selectedElements } = params;
		return calculateLayout({
			model,
			group,
			fixedElements,
			selectedElements,
			layoutFunction: (nodes, links) => {
				if (fixedElements && fixedElements.size > 0) biasFreePadded(nodes, {
					x: 50,
					y: 50
				}, () => groupForceLayout({
					nodes,
					links,
					preferredLinkLength: 200,
					avoidOvelaps: true
				}));
				else {
					groupForceLayout({
						nodes,
						links,
						preferredLinkLength: 200
					});
					biasFreePadded(nodes, {
						x: 50,
						y: 50
					}, () => groupRemoveOverlaps(nodes));
				}
			}
		});
	}
	function getContentFittingBoxForLayout(nodes) {
		let minX = Infinity, minY = Infinity;
		let maxX = -Infinity, maxY = -Infinity;
		for (const node of nodes) {
			const { x, y, width, height } = node;
			minX = Math.min(minX, x);
			minY = Math.min(minY, y);
			maxX = Math.max(maxX, x + width);
			maxY = Math.max(maxY, y + height);
		}
		return {
			x: Number.isFinite(minX) ? minX : 0,
			y: Number.isFinite(minY) ? minY : 0,
			width: Number.isFinite(minX) && Number.isFinite(maxX) ? maxX - minX : 0,
			height: Number.isFinite(minY) && Number.isFinite(maxY) ? maxY - minY : 0
		};
	}
	//#endregion
	//#region src/graph-explorer/data/sparql/graphBuilder.ts
	var GREED_STEP = 150;
	var GraphBuilder = class {
		constructor(dataProvider) {
			this.dataProvider = dataProvider;
		}
		createGraph(graph) {
			return this.dataProvider.elementInfo({ elementIds: graph.elementIds }).then((elementsInfo) => ({
				preloadedElements: elementsInfo,
				diagram: makeLayout(graph.elementIds, graph.links)
			}));
		}
		getGraphFromRDFGraph(graph) {
			const { elementIds, links } = makeGraphItems(graph);
			return this.createGraph({
				elementIds,
				links
			});
		}
		getGraphFromTurtleGraph(graph) {
			return parseTurtleText(graph).then((triples) => this.getGraphFromRDFGraph(triples));
		}
	};
	function makeGraphItems(response) {
		const elements = {};
		const links = [];
		for (const { subject, predicate, object } of response) {
			if (subject.type === "uri" && !elements[subject.value]) elements[subject.value] = true;
			if (object.type === "uri" && !elements[object.value]) elements[object.value] = true;
			if (subject.type === "uri" && object.type === "uri") links.push({
				linkTypeId: predicate.value,
				sourceId: subject.value,
				targetId: object.value
			});
		}
		return {
			elementIds: Object.keys(elements),
			links
		};
	}
	function makeLayout(elementsIds, linksInfo) {
		const grid = uniformGrid({
			rows: Math.ceil(Math.sqrt(elementsIds.length)),
			cellSize: {
				x: GREED_STEP,
				y: GREED_STEP
			}
		});
		const elements = elementsIds.map((id, index) => {
			const { x, y } = grid(index);
			return {
				"@type": "Element",
				"@id": GenerateID.forElement(),
				iri: id,
				position: {
					x,
					y
				}
			};
		});
		const layoutElementsMap = (0, lodash.keyBy)(elements, "iri");
		const links = [];
		linksInfo.forEach((link, _index) => {
			const source = layoutElementsMap[link.sourceId];
			const target = layoutElementsMap[link.targetId];
			if (!source || !target) return;
			links.push({
				"@type": "Link",
				"@id": GenerateID.forLink(),
				property: link.linkTypeId,
				source: { "@id": source["@id"] },
				target: { "@id": target["@id"] }
			});
		});
		return makeSerializedDiagram({
			layoutData: {
				"@type": "Layout",
				elements,
				links
			},
			linkTypeOptions: []
		});
	}
	//#endregion
	//#region src/graph-explorer/data/sparql/sparqlGraphBuilder.ts
	var DEFAULT_PREFIX = "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>\n PREFIX rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>\n PREFIX owl:  <http://www.w3.org/2002/07/owl#>\n\n";
	var SparqlGraphBuilder = class {
		constructor(dataProvider) {
			this.dataProvider = dataProvider;
			this.graphBuilder = new GraphBuilder(dataProvider);
		}
		getGraphFromConstruct(constructQuery) {
			const query = DEFAULT_PREFIX + constructQuery;
			return this.dataProvider.executeSparqlConstruct(query).then((graph) => this.graphBuilder.getGraphFromRDFGraph(graph));
		}
	};
	//#endregion
	//#region src/graph-explorer/diagram/graph.ts
	var Graph = class Graph {
		constructor() {
			this.source = new EventSource();
			this.events = this.source;
			this.elements = new OrderedMap();
			this.links = new OrderedMap();
			this.classesById = /* @__PURE__ */ new Map();
			this.propertiesById = /* @__PURE__ */ new Map();
			this.linkTypes = /* @__PURE__ */ new Map();
			this.onElementEvent = (data, key) => {
				this.source.trigger("elementEvent", {
					key,
					data
				});
			};
			this.onLinkEvent = (data, key) => {
				this.source.trigger("linkEvent", {
					key,
					data
				});
			};
			this.onLinkTypeEvent = (data, key) => {
				this.source.trigger("linkTypeEvent", {
					key,
					data
				});
			};
			this.onClassEvent = (data, key) => {
				this.source.trigger("classEvent", {
					key,
					data
				});
			};
		}
		static {
			this.nextLinkTypeIndex = 0;
		}
		getElements() {
			return this.elements.items;
		}
		getLinks() {
			return this.links.items;
		}
		getLink(linkId) {
			return this.links.get(linkId);
		}
		findLink(linkTypeId, sourceId, targetId) {
			const source = this.getElement(sourceId);
			if (!source) return;
			const index = findLinkIndex(source.links, linkTypeId, sourceId, targetId);
			return index >= 0 ? source.links[index] : void 0;
		}
		sourceOf(link) {
			return this.getElement(link.sourceId);
		}
		targetOf(link) {
			return this.getElement(link.targetId);
		}
		reorderElements(compare) {
			this.elements.reorder(compare);
		}
		getElement(elementId) {
			return this.elements.get(elementId);
		}
		addElement(element) {
			if (this.getElement(element.id)) throw new Error(`Element '${element.id}' already exists.`);
			element.events.onAny(this.onElementEvent);
			this.elements.push(element.id, element);
			this.source.trigger("changeCells", {
				updateAll: false,
				changedElement: element
			});
		}
		removeElement(elementId) {
			const element = this.elements.get(elementId);
			if (element) {
				const options = { silent: true };
				const changedLinks = [...element.links];
				for (const link of changedLinks) this.removeLink(link.id, options);
				this.elements.delete(elementId);
				element.events.offAny(this.onElementEvent);
				this.source.trigger("changeCells", {
					updateAll: false,
					changedElement: element,
					changedLinks
				});
			}
		}
		addLink(link) {
			if (this.getLink(link.id)) throw new Error(`Link '${link.id}' already exists.`);
			if (!this.getLinkType(link.typeId)) throw new Error(`Link type '${link.typeId}' not found.`);
			this.registerLink(link);
		}
		registerLink(link) {
			this.sourceOf(link).links.push(link);
			if (link.sourceId !== link.targetId) this.targetOf(link).links.push(link);
			link.events.onAny(this.onLinkEvent);
			this.links.push(link.id, link);
			this.source.trigger("changeCells", {
				updateAll: false,
				changedLinks: [link]
			});
		}
		removeLink(linkId, options) {
			const link = this.links.delete(linkId);
			if (link) {
				const { typeId, sourceId, targetId } = link;
				link.events.offAny(this.onLinkEvent);
				this.removeLinkReferences(typeId, sourceId, targetId);
				if (!(options && options.silent)) this.source.trigger("changeCells", {
					updateAll: false,
					changedLinks: [link]
				});
			}
		}
		removeLinkReferences(linkTypeId, sourceId, targetId) {
			const source = this.getElement(sourceId);
			if (source) removeLinkFrom(source.links, linkTypeId, sourceId, targetId);
			const target = this.getElement(targetId);
			if (target) removeLinkFrom(target.links, linkTypeId, sourceId, targetId);
		}
		getLinkTypes() {
			const result = [];
			this.linkTypes.forEach((type) => result.push(type));
			return result;
		}
		getLinkType(linkTypeId) {
			return this.linkTypes.get(linkTypeId);
		}
		addLinkType(linkType) {
			if (this.getLinkType(linkType.id)) throw new Error(`Link type '${linkType.id}' already exists.`);
			linkType.setIndex(Graph.nextLinkTypeIndex++);
			linkType.events.onAny(this.onLinkTypeEvent);
			this.linkTypes.set(linkType.id, linkType);
		}
		getProperty(propertyId) {
			return this.propertiesById.get(propertyId);
		}
		addProperty(property) {
			if (this.getProperty(property.id)) throw new Error(`Property '${property.id}' already exists.`);
			this.propertiesById.set(property.id, property);
		}
		getClass(classId) {
			return this.classesById.get(classId);
		}
		getClasses() {
			const classes = [];
			this.classesById.forEach((richClass) => classes.push(richClass));
			return classes;
		}
		addClass(classModel) {
			if (this.getClass(classModel.id)) throw new Error(`Class '${classModel.id}' already exists.`);
			classModel.events.onAny(this.onClassEvent);
			this.classesById.set(classModel.id, classModel);
		}
	};
	function removeLinkFrom(links, linkTypeId, sourceId, targetId) {
		if (!links) return;
		while (true) {
			const index = findLinkIndex(links, linkTypeId, sourceId, targetId);
			if (index < 0) break;
			links.splice(index, 1);
		}
	}
	function findLinkIndex(haystack, linkTypeId, sourceId, targetId) {
		for (let i = 0; i < haystack.length; i++) {
			const link = haystack[i];
			if (link.sourceId === sourceId && link.targetId === targetId && link.typeId === linkTypeId) return i;
		}
		return -1;
	}
	//#endregion
	//#region src/graph-explorer/diagram/model.ts
	/**
	* Model of diagram.
	*/
	var DiagramModel = class {
		constructor(history) {
			this.history = history;
			this.source = new EventSource();
			this.events = this.source;
			this.graph = new Graph();
			this.graphListener = new EventObserver();
		}
		get elements() {
			return this.graph.getElements();
		}
		get links() {
			return this.graph.getLinks();
		}
		getElement(elementId) {
			return this.graph.getElement(elementId);
		}
		getLinkById(linkId) {
			return this.graph.getLink(linkId);
		}
		linksOfType(linkTypeId) {
			return this.graph.getLinks().filter((link) => link.typeId === linkTypeId);
		}
		findLink(linkTypeId, sourceId, targetId) {
			return this.graph.findLink(linkTypeId, sourceId, targetId);
		}
		sourceOf(link) {
			return this.getElement(link.sourceId);
		}
		targetOf(link) {
			return this.getElement(link.targetId);
		}
		isSourceAndTargetVisible(link) {
			return Boolean(this.sourceOf(link) && this.targetOf(link));
		}
		resetGraph() {
			if (this.graphListener) {
				this.graphListener.stopListening();
				this.graphListener = new EventObserver();
			}
			this.graph = new Graph();
		}
		subscribeGraph() {
			this.graphListener.listen(this.graph.events, "changeCells", (e) => {
				this.source.trigger("changeCells", e);
			});
			this.graphListener.listen(this.graph.events, "elementEvent", (e) => {
				this.source.trigger("elementEvent", e);
			});
			this.graphListener.listen(this.graph.events, "linkEvent", (e) => {
				this.source.trigger("linkEvent", e);
			});
			this.graphListener.listen(this.graph.events, "linkTypeEvent", (e) => {
				this.source.trigger("linkTypeEvent", e);
			});
			this.graphListener.listen(this.graph.events, "classEvent", (e) => {
				this.source.trigger("classEvent", e);
			});
			this.source.trigger("changeCells", { updateAll: true });
		}
		reorderElements(compare) {
			this.graph.reorderElements(compare);
		}
		createElement(elementIriOrModel, group) {
			const elementIri = typeof elementIriOrModel === "string" ? elementIriOrModel : elementIriOrModel.id;
			const elements = this.elements.filter((el) => el.iri === elementIri && el.group === group);
			if (elements.length > 0) return elements[0];
			let data = typeof elementIriOrModel === "string" ? placeholderDataFromIri(elementIri) : elementIriOrModel;
			data = {
				...data,
				id: data.id
			};
			const element = new Element$1({
				id: GenerateID.forElement(),
				data,
				group
			});
			this.addElement(element);
			return element;
		}
		addElement(element) {
			this.history.execute(addElement(this.graph, element, []));
		}
		removeElement(elementId) {
			const element = this.getElement(elementId);
			if (element) this.history.execute(removeElement(this.graph, element));
		}
		addLink(link) {
			const { typeId, sourceId, targetId, data } = link;
			if (data && data.linkTypeId !== typeId) throw new Error("linkTypeId must match linkType.id");
			const existingLink = this.findLink(typeId, sourceId, targetId);
			if (existingLink) {
				if (link.data) {
					existingLink.setLayoutOnly(false);
					existingLink.setData(data);
				}
				return existingLink;
			}
			const linkType = this.createLinkType(link.typeId);
			const source = this.getElement(sourceId);
			const target = this.getElement(targetId);
			if (!(linkType.visible && source && target)) return;
			if (!link.data) link.setData({
				linkTypeId: typeId,
				sourceId: source.iri,
				targetId: target.iri
			});
			this.graph.addLink(link);
			return link;
		}
		removeLink(linkId) {
			this.graph.removeLink(linkId);
		}
		getClass(classIri) {
			return this.graph.getClass(classIri);
		}
		createClass(classIri) {
			const existing = this.graph.getClass(classIri);
			if (existing) return existing;
			const classModel = new FatClassModel({ id: classIri });
			this.addClass(classModel);
			return classModel;
		}
		addClass(model) {
			this.graph.addClass(model);
		}
		getLinkType(linkTypeIri) {
			return this.graph.getLinkType(linkTypeIri);
		}
		createLinkType(linkTypeIri) {
			const existing = this.graph.getLinkType(linkTypeIri);
			if (existing) return existing;
			const linkType = new FatLinkType({ id: linkTypeIri });
			this.graph.addLinkType(linkType);
			return linkType;
		}
		getProperty(propertyTypeIri) {
			return this.graph.getProperty(propertyTypeIri);
		}
		createProperty(propertyIri) {
			const existing = this.graph.getProperty(propertyIri);
			if (existing) return existing;
			const property = new RichProperty({ id: propertyIri });
			this.graph.addProperty(property);
			return property;
		}
		triggerChangeGroupContent(group) {
			this.source.trigger("changeGroupContent", { group });
		}
		createTemporaryElement() {
			const target = new Element$1({
				id: GenerateID.forElement(),
				data: placeholderDataFromIri(""),
				temporary: true
			});
			this.graph.addElement(target);
			return target;
		}
	};
	function placeholderDataFromIri(iri) {
		return {
			id: iri,
			types: [],
			label: { values: [] },
			properties: {}
		};
	}
	function addElement(graph, element, connectedLinks) {
		return Command.create("Add element", () => {
			graph.addElement(element);
			for (const link of connectedLinks) if (!(graph.getLink(link.id) || graph.findLink(link.typeId, link.sourceId, link.targetId))) graph.addLink(link);
			return removeElement(graph, element);
		});
	}
	function removeElement(graph, element) {
		return Command.create("Remove element", () => {
			const connectedLinks = [...element.links];
			graph.removeElement(element.id);
			return addElement(graph, element, connectedLinks);
		});
	}
	//#endregion
	//#region src/graph-explorer/editor/dataFetcher.ts
	var DataFetcher = class {
		constructor(graph, dataProvider) {
			this.graph = graph;
			this.dataProvider = dataProvider;
			this.classQueue = new BufferingQueue((classIds) => {
				this.dataProvider.classInfo({ classIds }).then(this.onClassesLoaded);
			});
			this.linkTypeQueue = new BufferingQueue((linkTypeIds) => {
				this.dataProvider.linkTypesInfo({ linkTypeIds }).then(this.onLinkTypesLoaded);
			});
			this.propertyTypeQueue = new BufferingQueue((propertyIds) => {
				this.dataProvider.propertyInfo({ propertyIds }).then(this.onPropertyTypesLoaded);
			});
			this.onElementInfoLoaded = (elements) => {
				for (const element of this.graph.getElements()) {
					const loadedModel = elements[element.iri];
					if (loadedModel) element.setData(loadedModel);
				}
			};
			this.onClassesLoaded = (classInfos) => {
				for (const { id, label, count } of classInfos) {
					const model = this.graph.getClass(id);
					if (!model) continue;
					model.setLabel(label.values);
					if (typeof count === "number") model.setCount(count);
				}
			};
			this.onLinkTypesLoaded = (linkTypesInfo) => {
				for (const { id, label } of linkTypesInfo) {
					const model = this.graph.getLinkType(id);
					if (!model) continue;
					model.setLabel(label.values);
				}
			};
			this.onPropertyTypesLoaded = (propertyModels) => {
				for (const propId in propertyModels) {
					if (!Object.prototype.hasOwnProperty.call(propertyModels, propId)) continue;
					const { id, label } = propertyModels[propId];
					const targetProperty = this.graph.getProperty(id);
					if (targetProperty) targetProperty.setLabel(label.values);
				}
			};
		}
		fetchElementData(elementIris) {
			if (elementIris.length === 0) return Promise.resolve();
			return this.dataProvider.elementInfo({ elementIds: [...elementIris] }).then(this.onElementInfoLoaded);
		}
		fetchClass(model) {
			this.classQueue.push(model.id);
		}
		fetchLinkType(linkType) {
			this.linkTypeQueue.push(linkType.id);
		}
		fetchPropertyType(propertyType) {
			if (!this.dataProvider.propertyInfo) return;
			this.propertyTypeQueue.push(propertyType.id);
		}
	};
	//#endregion
	//#region src/graph-explorer/editor/asyncModel.ts
	var AsyncModel = class extends DiagramModel {
		constructor(history, groupByProperties) {
			super(history);
			this.groupByProperties = groupByProperties;
			this.linkSettings = {};
			this.onLinkTypeVisibilityChanged = (e) => {
				if (e.source.visible) {
					if (!e.preventLoading) this.requestLinksOfType([e.source.id]);
				} else for (const link of this.linksOfType(e.source.id)) this.graph.removeLink(link.id);
			};
		}
		get asyncSource() {
			return this.source;
		}
		get dataProvider() {
			return this._dataProvider;
		}
		subscribeGraph() {
			super.subscribeGraph();
			this.graphListener.listen(this.graph.events, "linkTypeEvent", (e) => {
				if (e.key === "changeVisibility") this.onLinkTypeVisibilityChanged(e.data[e.key], e.key);
			});
		}
		setDataProvider(dataProvider) {
			this._dataProvider = dataProvider;
			this.fetcher = new DataFetcher(this.graph, dataProvider);
		}
		createNewDiagram(dataProvider) {
			this.resetGraph();
			this.setDataProvider(dataProvider);
			this.asyncSource.trigger("loadingStart", { source: this });
			return this.dataProvider.linkTypes().then((linkTypes) => {
				const allLinkTypes = this.initLinkTypes(linkTypes);
				return this.loadAndRenderLayout({
					allLinkTypes,
					markLinksAsLayoutOnly: false
				});
			}).catch((error) => {
				console.error(error);
				this.asyncSource.trigger("loadingError", {
					source: this,
					error
				});
				return Promise.reject(error);
			});
		}
		importLayout(params) {
			this.resetGraph();
			this.setDataProvider(params.dataProvider);
			this.asyncSource.trigger("loadingStart", { source: this });
			return this.dataProvider.linkTypes().then((linkTypes) => {
				const allLinkTypes = this.initLinkTypes(linkTypes);
				const diagram = params.diagram ? params.diagram : emptyDiagram();
				this.setLinkSettings(diagram.linkTypeOptions);
				const loadingModels = this.loadAndRenderLayout({
					layoutData: diagram.layoutData,
					preloadedElements: params.preloadedElements || {},
					markLinksAsLayoutOnly: params.validateLinks || false,
					allLinkTypes,
					hideUnusedLinkTypes: params.hideUnusedLinkTypes
				});
				const requestingLinks = params.validateLinks ? this.requestLinksOfType() : Promise.resolve();
				return Promise.all([loadingModels, requestingLinks]);
			}).then(() => {
				this.asyncSource.trigger("loadingSuccess", { source: this });
			}).catch((error) => {
				console.error(error);
				this.asyncSource.trigger("loadingError", {
					source: this,
					error
				});
				return Promise.reject(error);
			});
		}
		exportLayout() {
			return makeSerializedDiagram({
				layoutData: makeLayoutData(this.graph.getElements(), this.graph.getLinks()),
				linkTypeOptions: this.graph.getLinkTypes().filter((linkType) => (!linkType.visible || !linkType.showLabel) && linkType.id !== "http://graph-explorer.org/NewLink").map(({ id, visible, showLabel }) => ({
					"@type": "LinkTypeOptions",
					property: id,
					visible,
					showLabel
				}))
			});
		}
		initLinkTypes(linkTypes) {
			const types = [];
			for (const { id, label } of linkTypes) {
				const linkType = new FatLinkType({
					id,
					label: label.values
				});
				this.graph.addLinkType(linkType);
				types.push(linkType);
			}
			return types;
		}
		setLinkSettings(settings) {
			if (!settings) return;
			for (const setting of settings) {
				const { visible = true, showLabel = true } = setting;
				const linkTypeId = setting.property;
				this.linkSettings[linkTypeId] = {
					"@type": "LinkTypeOptions",
					property: linkTypeId,
					visible,
					showLabel
				};
				const linkType = this.getLinkType(linkTypeId);
				if (linkType) linkType.setVisibility({
					visible,
					showLabel
				});
			}
		}
		loadAndRenderLayout(params) {
			const { layoutData = emptyLayoutData(), preloadedElements = {}, markLinksAsLayoutOnly, hideUnusedLinkTypes } = params;
			const elementIrisToRequestData = [];
			const usedLinkTypes = {};
			for (const layoutElement of layoutData.elements) {
				const { "@id": id, iri, position, size, isExpanded, group, elementState } = layoutElement;
				const template = preloadedElements[iri];
				const element = new Element$1({
					id,
					data: template || placeholderDataFromIri(iri),
					position,
					size,
					expanded: isExpanded,
					group,
					elementState
				});
				this.graph.addElement(element);
				if (!template) elementIrisToRequestData.push(element.iri);
			}
			for (const layoutLink of layoutData.links) {
				const { "@id": id, property, source, target, vertices, linkState } = layoutLink;
				const linkType = this.createLinkType(property);
				usedLinkTypes[linkType.id] = linkType;
				const link = this.addLink(new Link({
					id,
					typeId: linkType.id,
					sourceId: source["@id"],
					targetId: target["@id"],
					vertices,
					linkState
				}));
				if (link) link.setLayoutOnly(markLinksAsLayoutOnly);
			}
			this.subscribeGraph();
			const requestingModels = this.requestElementData(elementIrisToRequestData);
			if (hideUnusedLinkTypes && params.allLinkTypes) this.hideUnusedLinkTypes(params.allLinkTypes, usedLinkTypes);
			return requestingModels;
		}
		hideUnusedLinkTypes(allTypes, usedTypes) {
			for (const linkType of allTypes) if (!usedTypes[linkType.id]) linkType.setVisibility({
				visible: false,
				showLabel: linkType.showLabel
			});
		}
		requestElementData(elementIris) {
			return this.fetcher.fetchElementData(elementIris);
		}
		requestLinksOfType(linkTypeIds) {
			const linkTypes = linkTypeIds || this.graph.getLinkTypes().filter((type) => type.visible).map((type) => type.id);
			return this.dataProvider.linksInfo({
				elementIds: this.graph.getElements().map((element) => element.iri),
				linkTypeIds: linkTypes
			}).then((links) => this.onLinkInfoLoaded(links));
		}
		createClass(classId) {
			if (this.graph.getClass(classId)) return super.getClass(classId);
			const classModel = super.createClass(classId);
			this.fetcher.fetchClass(classModel);
			return classModel;
		}
		createLinkType(linkTypeId) {
			if (this.graph.getLinkType(linkTypeId)) return super.createLinkType(linkTypeId);
			const linkType = super.createLinkType(linkTypeId);
			const setting = this.linkSettings[linkType.id];
			if (setting) {
				const { visible, showLabel } = setting;
				linkType.setVisibility({
					visible,
					showLabel,
					preventLoading: true
				});
			}
			this.fetcher.fetchLinkType(linkType);
			return linkType;
		}
		createProperty(propertyIri) {
			if (this.graph.getProperty(propertyIri)) return super.createProperty(propertyIri);
			const property = super.createProperty(propertyIri);
			this.fetcher.fetchPropertyType(property);
			return property;
		}
		onLinkInfoLoaded(links) {
			let allowToCreate;
			const cancel = () => {
				allowToCreate = false;
			};
			for (const linkModel of links) {
				this.createLinkType(linkModel.linkTypeId);
				allowToCreate = true;
				this.asyncSource.trigger("createLoadedLink", {
					source: this,
					model: linkModel,
					cancel
				});
				if (allowToCreate) this.createLinks(linkModel);
			}
		}
		createLinks(data) {
			const sources = this.graph.getElements().filter((el) => el.iri === data.sourceId);
			const targets = this.graph.getElements().filter((el) => el.iri === data.targetId);
			const typeId = data.linkTypeId;
			for (const source of sources) for (const target of targets) this.addLink(new Link({
				typeId,
				sourceId: source.id,
				targetId: target.id,
				data
			}));
		}
		loadEmbeddedElements(elementIri) {
			const elements = this.groupByProperties.map((groupBy) => this.dataProvider.linkElements({
				elementId: elementIri,
				linkId: groupBy.linkType,
				offset: 0,
				direction: groupBy.linkDirection
			}));
			return Promise.all(elements).then((res) => res.reduce((memo, current) => Object.assign(memo, current), {}));
		}
	};
	function requestElementData(model, elementIris) {
		return Command.effect("Fetch element data", () => {
			model.requestElementData(elementIris);
		});
	}
	function restoreLinksBetweenElements(model) {
		return Command.effect("Restore links between elements", () => {
			model.requestLinksOfType();
		});
	}
	//#endregion
	//#region src/graph-explorer/workspace/draggableHandle.tsx
	var DraggableHandle = class extends react.Component {
		constructor(..._args) {
			super(..._args);
			this.isHoldingMouse = false;
			this.onHandleMouseDown = (e) => {
				if (e.target !== e.currentTarget) return;
				if (this.isHoldingMouse) return;
				if (e.button !== 0) return;
				this.isHoldingMouse = true;
				this.originPageX = e.pageX;
				this.originPageY = e.pageY;
				document.addEventListener("mousemove", this.onMouseMove);
				document.addEventListener("mouseup", this.onMouseUp);
				this.props.onBeginDragHandle(e);
			};
			this.onMouseMove = (e) => {
				if (!this.isHoldingMouse) return;
				e.preventDefault();
				this.props.onDragHandle(e, e.pageX - this.originPageX, e.pageY - this.originPageY);
			};
			this.onMouseUp = (e) => {
				this.removeListeners();
				if (this.props.onEndDragHandle) this.props.onEndDragHandle(e);
			};
		}
		render() {
			const { onBeginDragHandle: _onBeginDragHandle, onDragHandle: _onDragHandle, onEndDragHandle: _onEndDragHandle, ...props } = this.props;
			return /* @__PURE__ */ react.createElement("div", {
				...props,
				onMouseDown: this.onHandleMouseDown
			}, this.props.children);
		}
		componentWillUnmount() {
			this.removeListeners();
		}
		removeListeners() {
			if (this.isHoldingMouse) {
				this.isHoldingMouse = false;
				document.removeEventListener("mousemove", this.onMouseMove);
				document.removeEventListener("mouseup", this.onMouseUp);
			}
		}
	};
	//#endregion
	//#region src/graph-explorer/widgets/dialog.tsx
	var DEFAULT_WIDTH = 300;
	var DEFAULT_HEIGHT = 300;
	var MIN_WIDTH = 250;
	var MIN_HEIGHT = 250;
	var MAX_WIDTH = 800;
	var MAX_HEIGHT = 800;
	var ELEMENT_OFFSET = 40;
	var LINK_OFFSET = 20;
	var FOCUS_OFFSET = 20;
	var CLASS_NAME$19 = "graph-explorer-dialog";
	var Dialog = class extends react.Component {
		static {
			this.defaultProps = { size: {
				width: DEFAULT_WIDTH,
				height: DEFAULT_HEIGHT
			} };
		}
		constructor(props) {
			super(props);
			this.unsubscribeFromTarget = void 0;
			this.handler = new EventObserver();
			this.updateAll = () => this.forceUpdate();
			this.onStartDragging = (_e) => {
				this.preventSelection();
				const { size } = this.props;
				this.startSize = {
					x: this.state.width || size.width,
					y: this.state.height || size.height
				};
			};
			this.onDragHandleBottom = (e, dx, dy) => {
				const height = this.calculateHeight(this.startSize.y + dy);
				this.setState({ height });
			};
			this.onDragHandleRight = (e, dx) => {
				const width = this.calculateWidth(this.startSize.x + dx);
				this.setState({ width });
			};
			this.onDragHandleBottomRight = (e, dx, dy) => {
				const width = this.calculateWidth(this.startSize.x + dx);
				const height = this.calculateHeight(this.startSize.y + dy);
				this.setState({
					width,
					height
				});
			};
			this.preventSelection = () => {
				const onMouseUp = () => {
					document.body.classList.remove("graph-explorer--unselectable");
					document.removeEventListener("mouseup", onMouseUp);
				};
				document.addEventListener("mouseup", onMouseUp);
				document.body.classList.add("graph-explorer--unselectable");
			};
			this.state = {};
		}
		componentDidMount() {
			this.listenToTarget(this.props.target);
			this.focusOn();
		}
		componentDidUpdate(nextProps) {
			if (nextProps.target !== this.props.target) this.listenToTarget(nextProps.target);
		}
		componentWillUnmount() {
			this.listenToTarget(void 0);
		}
		listenToTarget(target) {
			if (this.unsubscribeFromTarget) {
				this.unsubscribeFromTarget();
				this.unsubscribeFromTarget = void 0;
			}
			if (target) {
				const { view } = this.props;
				if (target instanceof Element$1) this.listenToElement(target);
				else if (target instanceof Link) this.listenToLink(target);
				this.handler.listen(view.events, "changeLanguage", this.updateAll);
				this.unsubscribeFromTarget = () => {
					this.handler.stopListening();
				};
			}
		}
		listenToElement(element) {
			this.handler.listen(element.events, "changePosition", this.updateAll);
			this.handler.listen(element.events, "changeSize", this.updateAll);
		}
		listenToLink(link) {
			const { view } = this.props;
			const source = view.model.getElement(link.sourceId);
			const target = view.model.getElement(link.targetId);
			this.listenToElement(source);
			this.listenToElement(target);
			this.handler.listen(link.events, "changeVertices", this.updateAll);
			this.handler.listen(link.events, "changeLabelBounds", this.updateAll);
		}
		calculatePositionForElement(element) {
			const { paperArea, size } = this.props;
			const bbox = boundsOf(element);
			const { y: y0 } = paperArea.paperToScrollablePaneCoords(bbox.x, bbox.y);
			const { x: x1, y: y1 } = paperArea.paperToScrollablePaneCoords(bbox.x + bbox.width, bbox.y + bbox.height);
			return {
				x: x1 + ELEMENT_OFFSET,
				y: (y0 + y1) / 2 - size.height / 2
			};
		}
		calculatePositionForLink(link) {
			const { view, paperArea } = this.props;
			const source = view.model.getElement(link.sourceId);
			const target = view.model.getElement(link.targetId);
			if (!source || !target) throw new Error("Source and target are not specified");
			const route = view.getRouting(link.id);
			const verticesDefinedByUser = link.vertices || [];
			const polyline = computePolyline(source, target, route ? route.vertices : verticesDefinedByUser);
			const targetPoint = getPointAlongPolyline(polyline, computePolylineLength(polyline) / 2);
			const { x, y } = paperArea.paperToScrollablePaneCoords(targetPoint.x, targetPoint.y);
			return {
				y: y + LINK_OFFSET,
				x: x + LINK_OFFSET
			};
		}
		calculatePosition() {
			const { target, paperArea, offset = {
				x: 0,
				y: 0
			}, calculatePosition } = this.props;
			if (calculatePosition) {
				const pos = calculatePosition();
				const { x, y } = paperArea.paperToScrollablePaneCoords(pos.x, pos.y);
				return {
					x: x + offset.x,
					y: y + offset.y
				};
			}
			if (target instanceof Element$1) return this.calculatePositionForElement(target);
			else if (target instanceof Link) return this.calculatePositionForLink(target);
			throw new Error("Unknown target type");
		}
		getViewPortScrollablePoints() {
			const { paperArea } = this.props;
			const paperAreaMetrix = paperArea.getAreaMetrics();
			return {
				min: paperArea.clientToScrollablePaneCoords(0, 0),
				max: paperArea.clientToScrollablePaneCoords(paperAreaMetrix.clientWidth, paperAreaMetrix.clientHeight)
			};
		}
		getDialogScrollablePoints() {
			const { size } = this.props;
			const { x, y } = this.calculatePosition();
			const min = {
				x: x - FOCUS_OFFSET,
				y: y - FOCUS_OFFSET
			};
			return {
				min,
				max: {
					x: min.x + size.width + FOCUS_OFFSET * 2,
					y: min.y + size.height + FOCUS_OFFSET * 2
				}
			};
		}
		focusOn() {
			const { paperArea } = this.props;
			const { min: viewPortMin, max: viewPortMax } = this.getViewPortScrollablePoints();
			const { min, max } = this.getDialogScrollablePoints();
			let xOffset = 0;
			if (min.x < viewPortMin.x) xOffset = min.x - viewPortMin.x;
			else if (max.x > viewPortMax.x) xOffset = max.x - viewPortMax.x;
			let yOffset = 0;
			if (min.y < viewPortMin.y) yOffset = min.y - viewPortMin.y;
			else if (max.y > viewPortMax.y) yOffset = max.y - viewPortMax.y;
			const curScrollableCenter = {
				x: viewPortMin.x + (viewPortMax.x - viewPortMin.x) / 2,
				y: viewPortMin.y + (viewPortMax.y - viewPortMin.y) / 2
			};
			const newScrollabalCenter = {
				x: curScrollableCenter.x + xOffset,
				y: curScrollableCenter.y + yOffset
			};
			const paperCenter = paperArea.scrollablePaneToPaperCoords(newScrollabalCenter.x, newScrollabalCenter.y);
			paperArea.centerTo(paperCenter);
		}
		calculateHeight(height) {
			const { size } = this.props;
			const minHeight = Math.min(size.height, MIN_HEIGHT);
			const maxHeight = Math.max(size.height, MAX_HEIGHT);
			return Math.max(minHeight, Math.min(maxHeight, height));
		}
		calculateWidth(width) {
			const { size } = this.props;
			const minWidth = Math.min(size.width, MIN_WIDTH);
			const maxWidth = Math.max(size.width, MAX_WIDTH);
			return Math.max(minWidth, Math.min(maxWidth, width));
		}
		render() {
			const { size, caption } = this.props;
			const { x, y } = this.calculatePosition();
			const style = {
				top: y,
				left: x,
				width: this.state.width || size.width,
				height: this.state.height || size.height
			};
			return /* @__PURE__ */ react.createElement("div", {
				className: CLASS_NAME$19,
				style
			}, /* @__PURE__ */ react.createElement("button", {
				className: `${CLASS_NAME$19}__close-button`,
				onClick: () => this.props.onClose()
			}), caption ? /* @__PURE__ */ react.createElement("div", { className: "graph-explorer-dialog__caption" }, caption) : null, this.props.children, /* @__PURE__ */ react.createElement(DraggableHandle, {
				className: `${CLASS_NAME$19}__bottom-handle`,
				onBeginDragHandle: this.onStartDragging,
				onDragHandle: this.onDragHandleBottom
			}), /* @__PURE__ */ react.createElement(DraggableHandle, {
				className: `${CLASS_NAME$19}__right-handle`,
				onBeginDragHandle: this.onStartDragging,
				onDragHandle: this.onDragHandleRight
			}), /* @__PURE__ */ react.createElement(DraggableHandle, {
				className: `${CLASS_NAME$19}__bottom-right-handle`,
				onBeginDragHandle: this.onStartDragging,
				onDragHandle: this.onDragHandleBottomRight
			}));
		}
	};
	//#endregion
	//#region src/graph-explorer/widgets/progressBar.tsx
	var ProgressState = /* @__PURE__ */ function(ProgressState) {
		ProgressState["none"] = "none";
		ProgressState["loading"] = "loading";
		ProgressState["error"] = "error";
		ProgressState["completed"] = "completed";
		return ProgressState;
	}({});
	var CLASS_NAME$18 = "graph-explorer-progress-bar";
	var ProgressBar = class extends react.Component {
		render() {
			const { state, percent = 100, height = 20 } = this.props;
			const className = `${CLASS_NAME$18} ${CLASS_NAME$18}--${state}`;
			const showBar = state === "loading" || state === "error";
			return /* @__PURE__ */ react.createElement("div", {
				className,
				style: { height: showBar ? height : 0 }
			}, /* @__PURE__ */ react.createElement("div", {
				className: `${CLASS_NAME$18}__bar`,
				role: "progressbar",
				style: { width: `${percent}%` },
				"aria-valuemin": 0,
				"aria-valuemax": 100,
				"aria-valuenow": percent
			}));
		}
	};
	//#endregion
	//#region src/graph-explorer/widgets/listElementView.tsx
	var CLASS_NAME$17 = "graph-explorer-list-element-view";
	var ListElementView = class extends react.Component {
		constructor(..._args) {
			super(..._args);
			this.onClick = (event) => {
				const { disabled, model, onClick } = this.props;
				if (!disabled && onClick) {
					event.persist();
					onClick(event, model);
				}
			};
		}
		render() {
			const { className, view, model, highlightText, disabled, selected, onDragStart } = this.props;
			const { h, c, l } = view.getTypeStyle(model.types).color;
			const frontColor = selected && !disabled ? (0, d3_color.hcl)(h, c, l * 1.2) : (0, d3_color.hcl)("white");
			let classNames = `${CLASS_NAME$17}`;
			classNames += disabled ? ` ${CLASS_NAME$17}--disabled` : "";
			classNames += className ? ` ${className}` : "";
			const localizedText = view.formatLabel(model.label.values, model.id);
			const classesString = model.types.length > 0 ? `\nClasses: ${view.getElementTypeString(model)}` : "";
			return /* @__PURE__ */ react.createElement("li", {
				className: classNames,
				draggable: !disabled && Boolean(onDragStart),
				title: `${localizedText} ${view.formatIri(model.id)}${classesString}`,
				style: { background: (0, d3_color.hcl)(h, c, l).toString() },
				onClick: this.onClick,
				onDragStart
			}, /* @__PURE__ */ react.createElement("div", {
				className: `${CLASS_NAME$17}__label`,
				style: { background: frontColor.toString() }
			}, highlightSubstring(localizedText, highlightText)));
		}
	};
	function startDragElements(e, iris) {
		try {
			e.dataTransfer.setData("application/x-graph-explorer-elements", JSON.stringify(iris));
		} catch (_ex) {
			e.dataTransfer.setData("text", JSON.stringify(iris));
		}
		return false;
	}
	var DEFAULT_HIGHLIGHT_PROPS = { className: `graph-explorer-text-highlight` };
	function highlightSubstring(text, substring, highlightProps = DEFAULT_HIGHLIGHT_PROPS) {
		if (!substring) return /* @__PURE__ */ react.createElement("span", null, text);
		const start = text.toLowerCase().indexOf(substring.toLowerCase());
		if (start < 0) return /* @__PURE__ */ react.createElement("span", null, text);
		const end = start + substring.length;
		const before = text.substring(0, start);
		const highlighted = text.substring(start, end);
		const after = text.substring(end);
		return /* @__PURE__ */ react.createElement("span", null, before, /* @__PURE__ */ react.createElement("span", highlightProps, highlighted), after);
	}
	//#endregion
	//#region src/graph-explorer/widgets/searchResults.tsx
	var CLASS_NAME$16 = "graph-explorer-search-results";
	var SearchResults = class extends react.Component {
		static {
			this.defaultProps = { useDragAndDrop: true };
		}
		constructor(props) {
			super(props);
			this.listener = new EventObserver();
			this.delayedChangeCells = new Debouncer();
			this.startSelection = 0;
			this.endSelection = 0;
			this.onRootMount = (root) => {
				this.root = root;
			};
			this.renderResultItem = (model) => {
				const { useDragAndDrop } = this.props;
				const canBeSelected = this.canBeSelected(model);
				return /* @__PURE__ */ react.createElement(ListElementView, {
					key: model.id,
					model,
					view: this.props.view,
					highlightText: this.props.highlightText,
					disabled: !canBeSelected,
					selected: this.props.selection.has(model.id),
					onClick: canBeSelected ? this.onItemClick : void 0,
					onDragStart: useDragAndDrop ? (e) => {
						const { selection } = this.props;
						const iris = [];
						selection.forEach((iri) => iris.push(iri));
						if (!selection.has(model.id)) iris.push(model.id);
						return startDragElements(e, iris);
					} : void 0
				});
			};
			this.onChangeCells = () => {
				const { items, selection } = this.props;
				if (selection.size === 0) {
					if (items && items.length > 0) this.forceUpdate();
				} else {
					const newSelection = cloneSet(selection);
					for (const element of this.props.view.model.elements) if (element.group === void 0 && selection.has(element.iri)) newSelection.delete(element.iri);
					this.updateSelection(newSelection);
				}
			};
			this.addKeyListener = () => {
				document.addEventListener("keydown", this.onKeyUp);
			};
			this.removeKeyListener = () => {
				document.removeEventListener("keydown", this.onKeyUp);
			};
			this.onKeyUp = (event) => {
				const { items } = this.props;
				const isPressedUp = event.keyCode === 38 || event.which === 38;
				const isPressDown = event.keyCode === 40 || event.which === 40;
				if (isPressedUp || isPressDown) if (event.shiftKey) {
					if (isPressedUp) this.endSelection = this.getNextIndex(this.endSelection, 0);
					else if (isPressDown) this.endSelection = this.getNextIndex(this.endSelection, 1);
					const startIndex = Math.min(this.startSelection, this.endSelection);
					const finishIndex = Math.max(this.startSelection, this.endSelection);
					const selection = this.selectRange(startIndex, finishIndex);
					this.updateSelection(selection);
					this.focusOn(this.endSelection);
				} else {
					const startIndex = Math.min(this.startSelection, this.endSelection);
					const finishIndex = Math.max(this.startSelection, this.endSelection);
					if (isPressedUp) this.startSelection = this.getNextIndex(startIndex, 0);
					else if (isPressDown) this.startSelection = this.getNextIndex(finishIndex, 1);
					this.endSelection = this.startSelection;
					const focusElement = items[this.startSelection];
					const newSelection = /* @__PURE__ */ new Set();
					newSelection.add(focusElement.id);
					this.updateSelection(newSelection);
					this.focusOn(this.startSelection);
				}
				event.preventDefault();
			};
			this.onItemClick = (event, model) => {
				event.preventDefault();
				const { items, selection, onSelectionChanged } = this.props;
				const modelIndex = items.indexOf(model);
				let newSelection;
				if (event.shiftKey && this.startSelection !== -1) {
					const start = Math.min(this.startSelection, modelIndex);
					const end = Math.max(this.startSelection, modelIndex);
					newSelection = this.selectRange(start, end);
				} else {
					this.endSelection = this.startSelection = modelIndex;
					if (event.ctrlKey || event.metaKey) {
						newSelection = cloneSet(selection);
						if (selection.has(model.id)) newSelection.delete(model.id);
						else newSelection.add(model.id);
					} else {
						newSelection = /* @__PURE__ */ new Set();
						newSelection.add(model.id);
					}
				}
				onSelectionChanged(newSelection);
			};
			this.state = { selection: props.selection || {} };
		}
		render() {
			const items = this.props.items || [];
			return /* @__PURE__ */ react.createElement("ul", {
				className: CLASS_NAME$16,
				ref: this.onRootMount,
				tabIndex: -1,
				onFocus: this.addKeyListener,
				onBlur: this.removeKeyListener
			}, items.map(this.renderResultItem));
		}
		componentDidMount() {
			this.listener.listen(this.props.view.model.events, "changeCells", () => {
				this.delayedChangeCells.call(this.onChangeCells);
			});
		}
		UNSAFE_componentWillReceiveProps(props) {
			this.setState({ selection: props.selection || {} });
		}
		componentWillUnmount() {
			this.removeKeyListener();
			this.listener.stopListening();
			this.delayedChangeCells.dispose();
		}
		updateSelection(selection) {
			const { onSelectionChanged } = this.props;
			onSelectionChanged(selection);
		}
		selectRange(start, end) {
			const { items } = this.props;
			const selection = /* @__PURE__ */ new Set();
			for (let i = start; i <= end; i++) {
				const selectedModel = items[i];
				if (this.canBeSelected(selectedModel)) selection.add(selectedModel.id);
			}
			return selection;
		}
		getNextIndex(startIndex, direction) {
			const { items } = this.props;
			if (items.length === 0) return startIndex;
			const indexDelta = direction === 0 ? -1 : 1;
			for (let step = 1; step < items.length; step++) {
				let nextIndex = startIndex + step * indexDelta;
				if (nextIndex < 0) nextIndex += items.length;
				if (nextIndex >= items.length) nextIndex -= items.length;
				if (this.canBeSelected(items[nextIndex])) return nextIndex;
			}
			return startIndex;
		}
		canBeSelected(model) {
			const alreadyOnDiagram = this.props.view.model.elements.findIndex((element) => element.iri === model.id && element.group === void 0) >= 0;
			return !this.props.useDragAndDrop || !alreadyOnDiagram;
		}
		focusOn(index) {
			const scrollableContainer = this.root.parentElement;
			const containerBounds = scrollableContainer.getBoundingClientRect();
			const item = this.root.children.item(index);
			const itemBounds = item.getBoundingClientRect();
			const itemTop = itemBounds.top - containerBounds.top;
			const itemBottom = itemBounds.bottom - containerBounds.top;
			if (itemTop < 0) scrollableContainer.scrollTop += itemTop;
			else if (itemBottom > containerBounds.height) scrollableContainer.scrollTop += itemBottom - containerBounds.height;
			item.focus();
		}
	};
	//#endregion
	//#region src/graph-explorer/widgets/connectionsMenu.tsx
	var MAX_LINK_COUNT = 100;
	var ALL_RELATED_ELEMENTS_LINK = new FatLinkType({
		id: "allRelatedElements",
		label: [{
			value: "All",
			language: ""
		}]
	});
	var ConnectionsMenu = class extends react.Component {
		constructor(..._args) {
			super(..._args);
			this.handler = new EventObserver();
			this.linkTypesListener = new EventObserver();
			this.loadingState = ProgressState.none;
			this.updateAll = () => this.forceUpdate();
			this.addSelectedElements = (selectedObjects) => {
				const { onClose, onAddElements } = this.props;
				const addedElementsIris = selectedObjects.map((item) => item.model.id);
				const linkType = this.linkDataChunk ? this.linkDataChunk.link : void 0;
				onAddElements(addedElementsIris, this.linkDataChunk && linkType !== ALL_RELATED_ELEMENTS_LINK ? linkType : void 0);
				onClose();
			};
			this.onExpandLink = (linkDataChunk) => {
				if (!(this.objects && this.linkDataChunk && this.linkDataChunk.link === linkDataChunk.link && this.linkDataChunk.direction === linkDataChunk.direction)) this.loadObjects(linkDataChunk);
				this.updateAll();
				this.context.workspace.triggerWorkspaceEvent(WorkspaceEventKey.connectionsExpandLink);
			};
			this.onMoveToFilter = (linkDataChunk) => {
				const { view, target } = this.props;
				const { link, direction } = linkDataChunk;
				if (link === ALL_RELATED_ELEMENTS_LINK) target.addToFilter();
				else view.model.getElement(target.id).addToFilter(link, direction);
			};
		}
		static {
			this.contextType = WorkspaceContext;
		}
		componentDidMount() {
			const { view } = this.props;
			this.handler.listen(view.events, "changeLanguage", this.updateAll);
			this.loadLinks();
		}
		componentWillUnmount() {
			this.handler.stopListening();
			this.linkTypesListener.stopListening();
		}
		resubscribeOnLinkTypeEvents(linkTypesOfElement) {
			this.linkTypesListener.stopListening();
			for (const linkType of linkTypesOfElement) {
				this.linkTypesListener.listen(linkType.events, "changeLabel", this.updateAll);
				this.linkTypesListener.listen(linkType.events, "changeVisibility", this.updateAll);
			}
		}
		loadLinks() {
			const { view, editor, target } = this.props;
			this.loadingState = ProgressState.loading;
			this.links = [];
			this.countMap = {};
			editor.model.dataProvider.linkTypesOf({ elementId: target.iri }).then((linkTypes) => {
				this.loadingState = ProgressState.completed;
				const countMap = {};
				const links = [];
				for (const { id: linkTypeId, inCount, outCount } of linkTypes) {
					countMap[linkTypeId] = {
						inCount,
						outCount
					};
					links.push(view.model.createLinkType(linkTypeId));
				}
				countMap[ALL_RELATED_ELEMENTS_LINK.id] = Object.keys(countMap).map((key) => countMap[key]).reduce((a, b) => {
					return {
						inCount: a.inCount + b.inCount,
						outCount: a.outCount + b.outCount
					};
				}, {
					inCount: 0,
					outCount: 0
				});
				this.countMap = countMap;
				this.links = links;
				this.resubscribeOnLinkTypeEvents(this.links);
				this.updateAll();
				this.context.workspace.triggerWorkspaceEvent(WorkspaceEventKey.connectionsLoadLinks);
			}).catch((err) => {
				console.error(err);
				this.loadingState = ProgressState.error;
				this.updateAll();
			});
			this.updateAll();
		}
		loadObjects(linkDataChunk) {
			const { view, editor, target } = this.props;
			const { link, direction } = linkDataChunk;
			const offset = linkDataChunk.offset || 0;
			this.loadingState = ProgressState.loading;
			this.linkDataChunk = linkDataChunk;
			this.objects = [];
			editor.model.dataProvider.linkElements({
				elementId: target.iri,
				linkId: link === ALL_RELATED_ELEMENTS_LINK ? void 0 : link.id,
				limit: offset + MAX_LINK_COUNT,
				offset,
				direction
			}).then((elements) => {
				this.loadingState = ProgressState.completed;
				this.objects = Object.keys(elements).map((iri) => ({
					model: elements[iri],
					presentOnDiagram: view.model.elements.findIndex((element) => element.iri === iri && element.group === void 0) >= 0
				}));
				this.updateAll();
				this.context.workspace.triggerWorkspaceEvent(WorkspaceEventKey.connectionsLoadElements);
			}).catch((err) => {
				console.error(err);
				this.loadingState = ProgressState.error;
				this.updateAll();
			});
		}
		render() {
			const connectionsData = {
				links: this.links || [],
				countMap: this.countMap || {}
			};
			let objectsData = null;
			if (this.linkDataChunk && this.objects) objectsData = {
				linkDataChunk: this.linkDataChunk,
				objects: this.objects
			};
			const { view, target, suggestProperties } = this.props;
			return /* @__PURE__ */ react.createElement(ConnectionsMenuMarkup, {
				target,
				connectionsData,
				objectsData,
				state: this.loadingState,
				view,
				onExpandLink: this.onExpandLink,
				onPressAddSelected: this.addSelectedElements,
				onMoveToFilter: this.onMoveToFilter,
				propertySuggestionCall: suggestProperties
			});
		}
	};
	var ConnectionsMenuMarkup = class extends react.Component {
		constructor(props) {
			super(props);
			this.onChangeFilter = (e) => {
				const filterKey = e.currentTarget.value;
				this.setState({ filterKey });
			};
			this.getTitle = () => {
				if (this.props.objectsData && this.state.panel === "objects") return "Objects";
				else if (this.props.connectionsData && this.state.panel === "connections") return "Connections";
				return "Error";
			};
			this.onExpandLink = (linkDataChunk) => {
				this.setState({
					filterKey: "",
					panel: "objects"
				});
				this.props.onExpandLink(linkDataChunk);
			};
			this.onCollapseLink = () => {
				this.setState({
					filterKey: "",
					panel: "connections"
				});
			};
			this.getBreadCrumbs = () => {
				if (this.props.objectsData && this.state.panel === "objects") {
					const { link, direction } = this.props.objectsData.linkDataChunk;
					const localizedText = this.props.view.formatLabel(link.label, link.id);
					return /* @__PURE__ */ react.createElement("span", { className: "graph-explorer-connections-menu_bread-crumbs" }, /* @__PURE__ */ react.createElement("a", {
						className: "graph-explorer-connections-menu__link",
						onClick: this.onCollapseLink
					}, "Connections"), "\xA0/\xA0", localizedText, " ", direction ? `(${direction})` : null);
				} else return null;
			};
			this.getBody = () => {
				if (this.props.state === "error") return /* @__PURE__ */ react.createElement("label", { className: "graph-explorer-label graph-explorer-connections-menu__error" }, "Error");
				else if (this.props.objectsData && this.state.panel === "objects") return /* @__PURE__ */ react.createElement(ObjectsPanel, {
					data: this.props.objectsData,
					onMoveToFilter: this.props.onMoveToFilter,
					view: this.props.view,
					filterKey: this.state.filterKey,
					loading: this.props.state === ProgressState.loading,
					onPressAddSelected: this.props.onPressAddSelected
				});
				else if (this.props.connectionsData && this.state.panel === "connections") {
					if (this.props.state === ProgressState.loading) return /* @__PURE__ */ react.createElement("label", { className: "graph-explorer-label graph-explorer-connections-menu__loading" }, "Loading...");
					return /* @__PURE__ */ react.createElement(ConnectionsList, {
						id: this.props.target.id,
						data: this.props.connectionsData,
						view: this.props.view,
						filterKey: this.state.filterKey,
						onExpandLink: this.onExpandLink,
						onMoveToFilter: this.props.onMoveToFilter,
						propertySuggestionCall: this.props.propertySuggestionCall,
						sortMode: this.state.sortMode
					});
				} else return /* @__PURE__ */ react.createElement("div", null);
			};
			this.onSortChange = (e) => {
				const value = e.target.value;
				if (this.state.sortMode === value) return;
				this.setState({ sortMode: value });
			};
			this.renderSortSwitch = (id, icon, title) => {
				return /* @__PURE__ */ react.createElement("div", null, /* @__PURE__ */ react.createElement("input", {
					type: "radio",
					name: "sort",
					id,
					value: id,
					className: "graph-explorer-connections-menu__sort-switch",
					onChange: this.onSortChange,
					checked: this.state.sortMode === id
				}), /* @__PURE__ */ react.createElement("label", {
					htmlFor: id,
					className: "graph-explorer-connections-menu__sort-switch-label",
					title
				}, /* @__PURE__ */ react.createElement("i", { className: `fa ${icon}` })));
			};
			this.renderSortSwitches = () => {
				if (this.state.panel !== "connections" || !this.props.propertySuggestionCall) return null;
				return /* @__PURE__ */ react.createElement("div", { className: "graph-explorer-connections-menu_search-line-sort-switches" }, this.renderSortSwitch("alphabet", "fa-sort-alpha-asc", "Sort alphabetically"), this.renderSortSwitch("smart", "fa-lightbulb-o", "Smart sort"));
			};
			this.state = {
				filterKey: "",
				panel: "connections",
				sortMode: "alphabet"
			};
		}
		render() {
			return /* @__PURE__ */ react.createElement("div", { className: "graph-explorer-connections-menu" }, /* @__PURE__ */ react.createElement("label", { className: "graph-explorer-label graph-explorer-connections-menu__title-label" }, this.getTitle()), this.getBreadCrumbs(), /* @__PURE__ */ react.createElement("div", { className: "graph-explorer-connections-menu_search-line" }, /* @__PURE__ */ react.createElement("input", {
				type: "text",
				className: "search-input graph-explorer-form-control graph-explorer-connections-menu__search-line-input",
				value: this.state.filterKey,
				onChange: this.onChangeFilter,
				placeholder: "Search for..."
			}), this.renderSortSwitches()), /* @__PURE__ */ react.createElement(ProgressBar, {
				state: this.props.state,
				height: 10
			}), this.getBody());
		}
	};
	var ConnectionsList = class extends react.Component {
		constructor(props) {
			super(props);
			this.updateScores = (props) => {
				if (props.propertySuggestionCall && (props.filterKey || props.sortMode === "smart")) {
					const { id, data, view, filterKey } = props;
					const lang = view.getLanguage();
					const token = filterKey.trim();
					const properties = data.links.map((l) => l.id);
					props.propertySuggestionCall({
						elementId: id,
						token,
						properties,
						lang
					}).then((scores) => this.setState({ scores }));
				}
			};
			this.compareLinks = (a, b) => {
				const { view } = this.props;
				const aText = view.formatLabel(a.label, a.id);
				const bText = view.formatLabel(b.label, b.id);
				return aText.localeCompare(bText);
			};
			this.compareLinksByWeight = (a, b) => {
				const { view } = this.props;
				const aText = view.formatLabel(a.label, a.id);
				const bText = view.formatLabel(b.label, b.id);
				const aWeight = this.state.scores[a.id] ? this.state.scores[a.id].score : 0;
				const bWeight = this.state.scores[b.id] ? this.state.scores[b.id].score : 0;
				return aWeight > bWeight ? -1 : aWeight < bWeight ? 1 : aText.localeCompare(bText);
			};
			this.getLinks = () => {
				const { view, data, filterKey } = this.props;
				return (data.links || []).filter((link) => {
					const text = view.formatLabel(link.label, link.id).toLowerCase();
					return !filterKey || text.indexOf(filterKey.toLowerCase()) >= 0;
				}).sort(this.compareLinks);
			};
			this.getProbableLinks = () => {
				const isSmartMode = this.isSmartMode();
				return (this.props.data.links || []).filter((link) => {
					return this.state.scores[link.id] && (this.state.scores[link.id].score > 0 || isSmartMode);
				}).sort(this.compareLinksByWeight);
			};
			this.getViews = (links, notSure) => {
				const { view } = this.props;
				const countMap = this.props.data.countMap || {};
				const views = [];
				const addView = (link, direction) => {
					const count = direction === "in" ? countMap[link.id].inCount : countMap[link.id].outCount;
					if (count === 0) return;
					const postfix = notSure ? "-probable" : "";
					views.push(/* @__PURE__ */ react.createElement(LinkInPopupMenu, {
						key: `${direction}-${link.id}-${postfix}`,
						link,
						onExpandLink: this.props.onExpandLink,
						view,
						count,
						direction,
						filterKey: notSure ? "" : this.props.filterKey,
						onMoveToFilter: this.props.onMoveToFilter,
						probability: this.state.scores[link.id] && notSure ? this.state.scores[link.id].score : 0
					}));
				};
				for (const link of links) {
					addView(link, "in");
					addView(link, "out");
				}
				return views;
			};
			this.state = { scores: {} };
			this.updateScores(props);
		}
		componentDidUpdate(newProps) {
			this.updateScores(newProps);
		}
		isSmartMode() {
			return this.props.sortMode === "smart" && !this.props.filterKey;
		}
		render() {
			const { view } = this.props;
			const isSmartMode = this.isSmartMode();
			const links = isSmartMode ? [] : this.getLinks();
			const probableLinks = this.getProbableLinks().filter((link) => links.indexOf(link) === -1);
			const views = this.getViews(links);
			const probableViews = this.getViews(probableLinks, true);
			let viewList;
			if (views.length === 0 && probableViews.length === 0) viewList = /* @__PURE__ */ react.createElement("label", { className: "graph-explorer-label graph-explorer-connections-menu_links-list__empty" }, "List empty");
			else {
				viewList = views;
				if (views.length > 1 || isSmartMode && probableViews.length > 1) {
					const allRelatedElements = (this.props.data.countMap || {})[ALL_RELATED_ELEMENTS_LINK.id];
					viewList = [/* @__PURE__ */ react.createElement(LinkInPopupMenu, {
						key: ALL_RELATED_ELEMENTS_LINK.id,
						link: ALL_RELATED_ELEMENTS_LINK,
						onExpandLink: this.props.onExpandLink,
						view,
						count: allRelatedElements.inCount + allRelatedElements.outCount,
						onMoveToFilter: this.props.onMoveToFilter
					}), /* @__PURE__ */ react.createElement("hr", {
						key: "graph-explorer-hr-line",
						className: "graph-explorer-connections-menu_links-list__hr"
					})].concat(viewList);
				}
			}
			let probablePart = null;
			if (probableViews.length !== 0) probablePart = [isSmartMode ? null : /* @__PURE__ */ react.createElement("li", { key: "probable-links" }, /* @__PURE__ */ react.createElement("span", { className: "graph-explorer-label" }, "Probably, you‘re looking for..")), probableViews];
			return /* @__PURE__ */ react.createElement("ul", { className: "graph-explorer-connections-menu_links-list " + (views.length === 0 && probableViews.length === 0 ? "ocm_links-list-empty" : "") }, viewList, probablePart);
		}
	};
	var LinkInPopupMenu = class extends react.Component {
		constructor(..._args2) {
			super(..._args2);
			this.onExpandLink = (expectedCount, direction) => {
				this.props.onExpandLink({
					link: this.props.link,
					direction,
					expectedCount
				});
			};
			this.onMoveToFilter = (evt) => {
				evt.stopPropagation();
				this.props.onMoveToFilter({
					link: this.props.link,
					direction: this.props.direction,
					expectedCount: this.props.count
				});
			};
		}
		render() {
			const { view, link } = this.props;
			const fullText = view.formatLabel(link.label, link.id);
			const probability = Math.round(this.props.probability * 100);
			const textLine = highlightSubstring(fullText + (probability > 0 ? " (" + probability + "%)" : ""), this.props.filterKey);
			const directionName = this.props.direction === "in" ? "source" : this.props.direction === "out" ? "target" : "all connected";
			return /* @__PURE__ */ react.createElement("li", {
				"data-linktypeid": this.props.link.id,
				className: "link-in-popup-menu",
				title: `${directionName} of "${fullText}" ${view.formatIri(link.id)}`,
				onClick: () => this.onExpandLink(this.props.count, this.props.direction)
			}, this.props.direction === "in" || this.props.direction === "out" ? /* @__PURE__ */ react.createElement("div", { className: "link-in-popup-menu_direction" }, this.props.direction === "in" && /* @__PURE__ */ react.createElement("div", { className: "link-in-popup-menu_direction__in-direction" }), this.props.direction === "out" && /* @__PURE__ */ react.createElement("div", { className: "link-in-popup-menu_direction__out-direction" })) : null, /* @__PURE__ */ react.createElement("div", { className: "link-in-popup-menu__link-title" }, textLine), /* @__PURE__ */ react.createElement("span", { className: "graph-explorer-badge link-in-popup-menu__count" }, this.props.count <= MAX_LINK_COUNT ? this.props.count : "100+"), /* @__PURE__ */ react.createElement("div", {
				className: "link-in-popup-menu__filter-button",
				onClick: this.onMoveToFilter,
				title: "Set as filter in the Instances panel"
			}), /* @__PURE__ */ react.createElement("div", {
				className: "link-in-popup-menu__navigate-button",
				title: `Navigate to ${directionName} "${fullText}" elements`
			}));
		}
	};
	var ObjectsPanel = class extends react.Component {
		constructor(props) {
			super(props);
			this.onSelectAll = () => {
				const objects = this.props.data.objects;
				if (objects.length === 0) return;
				const newSelection = allNonPresentedAreSelected(objects, this.state.selection) ? /* @__PURE__ */ new Set() : selectNonPresented(this.props.data.objects);
				this.updateSelection(newSelection);
			};
			this.updateSelection = (newSelection) => {
				this.setState({ selection: newSelection });
			};
			this.counter = (activeObjCount) => {
				const countString = `${activeObjCount}\u00A0of\u00A0${this.props.data.objects.length}`;
				const wrongNodes = Math.min(MAX_LINK_COUNT, this.props.data.linkDataChunk.expectedCount) - this.props.data.objects.length;
				const wrongNodesString = Math.abs(wrongNodes) > MAX_LINK_COUNT ? `${MAX_LINK_COUNT}+` : Math.abs(wrongNodes).toString();
				const wrongNodesCount = wrongNodes === 0 ? "" : wrongNodes < 0 ? `\u00A0(${wrongNodesString})` : `\u00A0(${wrongNodesString})`;
				const wrongNodesTitle = wrongNodes === 0 ? "" : wrongNodes > 0 ? "Unavailable nodes" : "Extra nodes";
				return /* @__PURE__ */ react.createElement("div", { className: "graph-explorer-label graph-explorer-connections-menu_objects-panel_bottom-panel__count-label" }, /* @__PURE__ */ react.createElement("span", null, countString), /* @__PURE__ */ react.createElement("span", {
					className: "graph-explorer-connections-menu_objects-panel_bottom-panel__extra-elements",
					title: wrongNodesTitle
				}, wrongNodesCount));
			};
			this.state = { selection: /* @__PURE__ */ new Set() };
		}
		componentDidUpdate(nextProps) {
			if (this.props.data.objects.length < nextProps.data.objects.length) this.setState({ selection: /* @__PURE__ */ new Set() });
		}
		getFilteredObjects() {
			if (!this.props.filterKey) return this.props.data.objects;
			const filterKey = this.props.filterKey.toLowerCase();
			return this.props.data.objects.filter((element) => {
				const text = this.props.view.formatLabel(element.model.label.values, element.model.id).toLowerCase();
				return text && text.indexOf(filterKey) >= 0;
			});
		}
		getItems(list) {
			const added = {};
			const result = [];
			for (const obj of list) {
				if (added[obj.model.id]) continue;
				added[obj.model.id] = true;
				result.push(obj.model);
			}
			return result;
		}
		render() {
			const { onPressAddSelected, filterKey } = this.props;
			const { selection } = this.state;
			const objects = this.getFilteredObjects();
			const isAllSelected = allNonPresentedAreSelected(objects, selection);
			const nonPresented = objects.filter((el) => !el.presentOnDiagram);
			const active = nonPresented.filter((el) => selection.has(el.model.id));
			return /* @__PURE__ */ react.createElement("div", { className: "graph-explorer-connections-menu_objects-panel" }, /* @__PURE__ */ react.createElement("div", { className: "graph-explorer-connections-menu_objects-panel__select-all" }, /* @__PURE__ */ react.createElement("label", null, /* @__PURE__ */ react.createElement("input", {
				type: "checkbox",
				checked: isAllSelected && nonPresented.length > 0,
				onChange: this.onSelectAll,
				disabled: nonPresented.length === 0
			}), "Select All")), this.props.loading ? /* @__PURE__ */ react.createElement("label", { className: "graph-explorer-label graph-explorer-connections-menu__loading-objects" }, "Loading...") : objects.length === 0 ? /* @__PURE__ */ react.createElement("label", { className: "graph-explorer-label graph-explorer-connections-menu__loading-objects" }, "No available nodes") : /* @__PURE__ */ react.createElement("div", { className: "graph-explorer-connections-menu_objects-panel_objects-list" }, /* @__PURE__ */ react.createElement(SearchResults, {
				view: this.props.view,
				items: this.getItems(objects),
				selection: this.state.selection,
				onSelectionChanged: this.updateSelection,
				highlightText: filterKey
			}), this.props.data.linkDataChunk.expectedCount > MAX_LINK_COUNT ? /* @__PURE__ */ react.createElement("div", {
				className: "graph-explorer-connections-menu__move-to-filter",
				onClick: () => this.props.onMoveToFilter(this.props.data.linkDataChunk)
			}, "The list was truncated, for more data click here to use the filter panel") : null), /* @__PURE__ */ react.createElement("div", { className: "graph-explorer-connections-menu_objects-panel_bottom-panel" }, this.counter(active.length), /* @__PURE__ */ react.createElement("button", {
				className: "graph-explorer-btn graph-explorer-btn-primary pull-right graph-explorer-connections-menu_objects-panel_bottom-panel__add-button",
				disabled: this.props.loading || nonPresented.length === 0,
				onClick: () => onPressAddSelected(active.length > 0 ? active : nonPresented)
			}, active.length > 0 ? "Add selected" : "Add all")));
		}
	};
	function selectNonPresented(objects) {
		const selection = /* @__PURE__ */ new Set();
		for (const object of objects) {
			if (object.presentOnDiagram) continue;
			selection.add(object.model.id);
		}
		return selection;
	}
	function allNonPresentedAreSelected(objects, selection) {
		let allSelected = true;
		for (const object of objects) {
			if (object.presentOnDiagram) continue;
			allSelected = allSelected && selection.has(object.model.id);
		}
		return allSelected;
	}
	//#endregion
	//#region src/graph-explorer/forms/editEntityForm.tsx
	var CLASS_NAME$15 = "graph-explorer-edit-form";
	var EditEntityForm = class extends react.Component {
		constructor(props) {
			super(props);
			this.renderProperty = (key, property) => {
				const { view } = this.props;
				const richProperty = view.model.getProperty(key);
				const label = view.formatLabel(richProperty.label, key);
				let values = [];
				if (isLiteralProperty(property)) values = property.values.map(({ value, language }) => {
					return {
						value,
						language
					};
				});
				return /* @__PURE__ */ react.createElement("div", {
					key,
					className: `${CLASS_NAME$15}__form-row`
				}, /* @__PURE__ */ react.createElement("label", null, label, values.map((value, index) => /* @__PURE__ */ react.createElement("input", {
					key: index,
					className: "graph-explorer-form-control",
					defaultValue: value.value,
					lang: value.language,
					onChange: this.onChangeProp,
					"data-iri": key
				}))));
			};
			this.onChangeIri = (e) => {
				const iri = e.target.value;
				this.setState((prevState) => {
					return { elementModel: {
						...prevState.elementModel,
						id: iri
					} };
				});
			};
			this.onChangeLabel = (e) => {
				const target = e.target;
				const labels = target.value.length > 0 ? [{
					value: target.value,
					language: ""
				}] : [];
				this.setState({ elementModel: {
					...this.state.elementModel,
					label: { values: labels }
				} });
			};
			this.onChangeProp = (e) => {
				const target = e.target;
				const values = [];
				target.parentElement.querySelectorAll("[data-iri=\"" + target.dataset["iri"] + "\"]").forEach((Element) => {
					const typedElement = Element;
					values.push({
						value: typedElement.value,
						language: typedElement.lang
					});
				});
				this.setState({ elementModel: {
					...this.state.elementModel,
					properties: {
						...this.state.elementModel.properties,
						[target.dataset["iri"]]: {
							type: "string",
							values
						}
					}
				} });
			};
			this.state = { elementModel: props.entity };
		}
		componentDidUpdate(nextProps) {
			if (this.props.entity !== nextProps.entity) this.setState({ elementModel: nextProps.entity });
		}
		renderProperties() {
			const { properties } = this.props.entity;
			const propertyIris = Object.keys(properties);
			return /* @__PURE__ */ react.createElement("div", null, propertyIris.map((iri) => {
				return this.renderProperty(iri, properties[iri]);
			}));
		}
		renderType() {
			const { view } = this.props;
			const { elementModel } = this.state;
			const label = view.getElementTypeString(elementModel);
			return /* @__PURE__ */ react.createElement("label", null, "Type", /* @__PURE__ */ react.createElement("input", {
				className: "graph-explorer-form-control",
				value: label,
				disabled: true
			}));
		}
		renderIri() {
			const { elementModel } = this.state;
			return /* @__PURE__ */ react.createElement("label", null, "IRI", /* @__PURE__ */ react.createElement("input", {
				className: "graph-explorer-form-control",
				defaultValue: elementModel.id,
				onChange: this.onChangeIri
			}));
		}
		renderLabel() {
			const { view } = this.props;
			const label = view.selectLabel(this.state.elementModel.label.values);
			const text = label ? label.value : "";
			return /* @__PURE__ */ react.createElement("label", null, "Label", /* @__PURE__ */ react.createElement("input", {
				className: "graph-explorer-form-control",
				value: text,
				onChange: this.onChangeLabel
			}));
		}
		render() {
			return /* @__PURE__ */ react.createElement("div", { className: CLASS_NAME$15 }, /* @__PURE__ */ react.createElement("div", { className: `${CLASS_NAME$15}__body` }, /* @__PURE__ */ react.createElement("div", { className: `${CLASS_NAME$15}__form-row` }, this.renderIri()), /* @__PURE__ */ react.createElement("div", { className: `${CLASS_NAME$15}__form-row` }, this.renderType()), /* @__PURE__ */ react.createElement("div", { className: `${CLASS_NAME$15}__form-row` }, this.renderLabel()), this.renderProperties()), /* @__PURE__ */ react.createElement("div", { className: `${CLASS_NAME$15}__controls` }, /* @__PURE__ */ react.createElement("button", {
				className: `graph-explorer-btn graph-explorer-btn-success ${CLASS_NAME$15}__apply-button`,
				onClick: () => this.props.onApply(this.state.elementModel)
			}, "Apply"), /* @__PURE__ */ react.createElement("button", {
				className: "graph-explorer-btn graph-explorer-btn-danger",
				onClick: this.props.onCancel
			}, "Cancel")));
		}
	};
	//#endregion
	//#region src/graph-explorer/widgets/instancesSearch.tsx
	var CLASS_NAME$14 = "graph-explorer-instances-search";
	var InstancesSearch = class extends react.Component {
		static {
			this.contextType = WorkspaceContext;
		}
		constructor(props) {
			super(props);
			this.listener = new EventObserver();
			this.onSelectionChanged = (newSelection) => {
				this.setState({ selection: newSelection });
			};
			this.state = {
				resultId: 0,
				selection: /* @__PURE__ */ new Set()
			};
		}
		render() {
			const ENTER_KEY_CODE = 13;
			const className = `${CLASS_NAME$14} ${this.props.className || ""}`;
			const progressState = this.state.quering ? ProgressState.loading : this.state.error ? ProgressState.error : this.state.items ? ProgressState.completed : ProgressState.none;
			const searchTerm = this.state.inputText === void 0 ? this.props.criteria.text : this.state.inputText;
			return /* @__PURE__ */ react.createElement("div", { className }, /* @__PURE__ */ react.createElement(ProgressBar, { state: progressState }), /* @__PURE__ */ react.createElement("div", { className: `${CLASS_NAME$14}__criteria` }, this.renderCriteria(), /* @__PURE__ */ react.createElement("div", { className: `${CLASS_NAME$14}__text-criteria graph-explorer-input-group` }, /* @__PURE__ */ react.createElement("input", {
				type: "text",
				className: "graph-explorer-form-control",
				placeholder: "Search for...",
				value: searchTerm || "",
				onChange: (e) => this.setState({ inputText: e.currentTarget.value }),
				onKeyUp: (e) => {
					if (e.keyCode === ENTER_KEY_CODE) this.submitCriteriaUpdate();
				}
			}), /* @__PURE__ */ react.createElement("span", { className: "graph-explorer-input-group-btn" }, /* @__PURE__ */ react.createElement("button", {
				className: "graph-explorer-btn graph-explorer-btn-default",
				type: "button",
				title: "Search",
				onClick: () => this.submitCriteriaUpdate()
			}, /* @__PURE__ */ react.createElement("span", {
				className: "fa fa-search",
				"aria-hidden": "true"
			}))))), /* @__PURE__ */ react.createElement("div", {
				className: `${CLASS_NAME$14}__rest graph-explorer-scrollable`,
				key: this.state.resultId
			}, /* @__PURE__ */ react.createElement(SearchResults, {
				view: this.props.view,
				items: this.state.items,
				highlightText: this.props.criteria.text,
				selection: this.state.selection,
				onSelectionChanged: this.onSelectionChanged
			}), /* @__PURE__ */ react.createElement("div", { className: `${CLASS_NAME$14}__rest-end` }, /* @__PURE__ */ react.createElement("button", {
				type: "button",
				className: `${CLASS_NAME$14}__load-more graph-explorer-btn graph-explorer-btn-primary`,
				disabled: this.state.quering,
				style: { display: this.state.moreItemsAvailable ? void 0 : "none" },
				onClick: () => this.queryItems(true)
			}, /* @__PURE__ */ react.createElement("span", {
				className: "fa fa-chevron-down",
				"aria-hidden": "true"
			}), "\xA0Show more"))));
		}
		renderCriteria() {
			const { criteria = {}, view } = this.props;
			const criterions = [];
			if (criteria.elementType) {
				const classInfo = criteria.elementType;
				const classLabel = view.formatLabel(classInfo.label, classInfo.id);
				criterions.push(/* @__PURE__ */ react.createElement("div", {
					key: "hasType",
					className: `${CLASS_NAME$14}__criterion`
				}, this.renderRemoveCriterionButtons(() => this.props.onCriteriaChanged({
					...this.props.criteria,
					elementType: void 0
				})), "Has type", " ", /* @__PURE__ */ react.createElement("span", {
					className: `${CLASS_NAME$14}__criterion-class`,
					title: classInfo.id
				}, classLabel)));
			} else if (criteria.refElement) {
				const element = criteria.refElement;
				const elementLabel = view.formatLabel(element.data.label.values, element.iri);
				const linkType = criteria.refElementLink;
				const linkTypeLabel = linkType ? view.formatLabel(linkType.label, linkType.id) : void 0;
				criterions.push(/* @__PURE__ */ react.createElement("div", {
					key: "hasLinkedElement",
					className: `${CLASS_NAME$14}__criterion`
				}, this.renderRemoveCriterionButtons(() => this.props.onCriteriaChanged({
					...this.props.criteria,
					refElement: void 0,
					refElementLink: void 0
				})), "Connected to", " ", /* @__PURE__ */ react.createElement("span", {
					className: `${CLASS_NAME$14}__criterion-element`,
					title: element ? element.iri : void 0
				}, elementLabel), linkType && /* @__PURE__ */ react.createElement("span", null, " through ", /* @__PURE__ */ react.createElement("span", {
					className: `${CLASS_NAME$14}__criterion-link-type`,
					title: linkType ? linkType.id : void 0
				}, linkTypeLabel), criteria.linkDirection === "in" && /* @__PURE__ */ react.createElement("span", null, " as ", /* @__PURE__ */ react.createElement("img", {
					className: `${CLASS_NAME$14}__link-direction`,
					src: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAbCAYAAAAOEM1uAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAZEQAAGREBkIelaAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAG2SURBVFiFzde9axRRFMbhJ3Hjx0YRgkWElGIRGyVgaaG9XQpBrNIETJHKjxBSJCA2NiIWdhYKgoqCIELq/AU2tiJpAiliDMHEWEyKZfdO5szHrr4wzcx77vnNnXPnnktcK9jBwYCuLcwNBeHGsIGovyltDweNbYOHg9Eo4D9Tq0bsGj40BXKoO5isEjiht4ifHuE/qVpJvO/O049PvIxN/MBMH8ZP6pzeGVxK+C4kfAsl8vTMYBnI1x1Bv3E54bmWSHCAx2KfvBbgKGbxJAfOIcS7HMjnKCqpWoBRtfE5B/IVRsoAtnAGd3GlQchd/NE7Y7dwCtPYiw72xuD216KFk/zN3Ii+SYOajhqHZUU9aK1GjS3M4xumFK+yMuPexLHEsy9YbChPJR3HW+na+yjbBvNU+zdzHbcxfoTnUw7cS8XNSS3AFx1B6zif8FzKgXsmVj6VAduyFrwzcCUHcL/L9yiaJAUYXRRjON1172zC9xX3ZS+ziTk8KAFYWWX7wRGcqJAnudVV1RTu1YhP6WL3jWjXO4HvzbLE9N8fmqKAv/SpNyvQdmorSmlHVvhX1TsJltFPPPwL/+nTC6wUIf8AAAAASUVORK5CYII="
				}), "\xA0source"), criteria.linkDirection === "out" && /* @__PURE__ */ react.createElement("span", null, " as ", /* @__PURE__ */ react.createElement("img", {
					className: `${CLASS_NAME$14}__link-direction`,
					src: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAbCAYAAAAOEM1uAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAZEQAAGREBkIelaAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAGCSURBVFiFzdi9ShxRFAfwn+uiaAoRVBQbbfMEFqIoFja+QCoLLQQr8R0sbdIJgTQiSgT1AcTKzkdIQhpTaOlX0GyK2WJ2c8d1Pt0/XBjOnTnnP+eerxnYxj0aJa9nfEOvlLirgFx8zaQhV8Ng2jfKiVT2amWxKAr1gOwElwXpH8NWXiXtMbKZV2EMHwP6F2P7dR1O8T2PeBW/8EMHp5TpwWGtJewF06JEuWmzu4ueqgnC55juw6ZsHE8B218F8qJsgkS1b0Grh74EbDdwioGqCYbQj6MEkhcYIlxm3opZrGEyh47eJqH22JvDOZbJ5sEJ4Rgqeh1nLTMr6Mv4bBpMZSV4hj9FMknA96wxeC3qCOvyxWAd88L17wobdHkWV0VwxP+e3ksgd6LiOrgtyvhn7DRlo3gM2K68kwziNqb7QTSC9eN3m9136cWvjVuf8FOHaSZPJ8mLfRw0r/8m3RQiuIQPBZEY67CfSCyOsttV0hG/CV3/0VQTTbxVIrW9rv6z8A+8NRQ5z9bcwQAAAABJRU5ErkJggg=="
				}), "\xA0target"))));
			}
			return /* @__PURE__ */ react.createElement("div", { className: `${CLASS_NAME$14}__criterions` }, criterions);
		}
		renderRemoveCriterionButtons(onClick) {
			return /* @__PURE__ */ react.createElement("div", { className: `${CLASS_NAME$14}__criterion-remove ontoidia-btn-group graph-explorer-btn-group-xs` }, /* @__PURE__ */ react.createElement("button", {
				type: "button",
				className: "graph-explorer-btn graph-explorer-btn-default",
				title: "Remove criteria",
				onClick
			}, /* @__PURE__ */ react.createElement("span", {
				className: "fa fa-times",
				"aria-hidden": "true"
			})));
		}
		submitCriteriaUpdate() {
			let text = this.state.inputText === void 0 ? this.props.criteria.text : this.state.inputText;
			text = text === "" ? void 0 : text;
			this.props.onCriteriaChanged({
				...this.props.criteria,
				text
			});
		}
		componentDidMount() {
			this.listener.listen(this.props.view.events, "changeLanguage", () => this.forceUpdate());
			this.queryItems(false);
		}
		componentDidUpdate(nextProps) {
			const languageChanged = this.currentRequest ? this.currentRequest.languageCode !== nextProps.view.getLanguage() : false;
			if (this.props.criteria !== nextProps.criteria || languageChanged) this.setState({ inputText: void 0 }, () => this.queryItems(false));
		}
		componentWillUnmount() {
			this.listener.stopListening();
			this.currentRequest = void 0;
		}
		queryItems(loadMoreItems) {
			let request;
			if (loadMoreItems) {
				if (!this.currentRequest) throw new Error("Cannot request more items without initial request.");
				const { offset, limit } = this.currentRequest;
				request = {
					...this.currentRequest,
					offset: offset + limit
				};
			} else request = createRequest(this.props.criteria, this.props.view.getLanguage());
			if (!(request.text || request.elementTypeId || request.refElementId || request.refElementLinkId)) {
				this.setState({
					quering: false,
					error: void 0,
					items: void 0,
					selection: /* @__PURE__ */ new Set(),
					moreItemsAvailable: false
				});
				return;
			}
			this.currentRequest = request;
			this.setState({
				quering: true,
				error: void 0,
				moreItemsAvailable: false
			});
			this.props.model.dataProvider.filter(request).then((elements) => {
				if (this.currentRequest !== request) return;
				this.processFilterData(elements);
				this.context.workspace.triggerWorkspaceEvent(WorkspaceEventKey.searchQueryItem);
			}).catch((error) => {
				if (this.currentRequest !== request) return;
				console.error(error);
				this.setState({
					quering: false,
					error
				});
			});
		}
		processFilterData(elements) {
			const requestedAdditionalItems = this.currentRequest.offset > 0;
			const existingIris = {};
			if (requestedAdditionalItems) this.state.items.forEach((item) => existingIris[item.id] = true);
			const items = requestedAdditionalItems ? [...this.state.items] : [];
			for (const iri in elements) {
				if (!Object.prototype.hasOwnProperty.call(elements, iri)) continue;
				if (existingIris[iri]) continue;
				items.push(elements[iri]);
			}
			const moreItemsAvailable = Object.keys(elements).length >= this.currentRequest.limit;
			if (requestedAdditionalItems) this.setState({
				quering: false,
				items,
				error: void 0,
				moreItemsAvailable
			});
			else this.setState({
				quering: false,
				resultId: this.state.resultId + 1,
				items,
				selection: /* @__PURE__ */ new Set(),
				error: void 0,
				moreItemsAvailable
			});
		}
	};
	function createRequest(criteria, language) {
		const { text, elementType, refElement, refElementLink, linkDirection } = criteria;
		return {
			text,
			elementTypeId: elementType ? elementType.id : void 0,
			refElementId: refElement ? refElement.iri : void 0,
			refElementLinkId: refElementLink ? refElementLink.id : void 0,
			linkDirection,
			offset: 0,
			limit: 100,
			languageCode: language || "en"
		};
	}
	//#endregion
	//#region src/graph-explorer/forms/elementTypeSelector.tsx
	var CLASS_NAME$13 = "graph-explorer-edit-form";
	var ElementTypeSelector = class extends react.Component {
		constructor(props) {
			super(props);
			this.cancellation = new Cancellation();
			this.filterCancellation = new Cancellation();
			this.loadingItemCancellation = new Cancellation();
			this.onElementTypeChange = async (e) => {
				this.setState({ isLoading: true });
				this.loadingItemCancellation.abort();
				this.loadingItemCancellation = new Cancellation();
				const signal = this.loadingItemCancellation.signal;
				const { onChange, metadataApi } = this.props;
				const classId = e.target.value;
				const elementModel = await CancellationToken.mapCancelledToNull(signal, metadataApi.generateNewElement([classId], signal));
				if (elementModel === null) return;
				this.setState({ isLoading: false });
				onChange({
					value: elementModel,
					isNew: true,
					loading: false
				});
			};
			this.renderPossibleElementType = (elementType) => {
				const { view } = this.props;
				const type = view.model.createClass(elementType);
				const label = view.formatLabel(type.label, type.id);
				return /* @__PURE__ */ react.createElement("option", {
					key: elementType,
					value: elementType
				}, label);
			};
			this.state = {
				searchString: "",
				existingElements: []
			};
		}
		componentDidMount() {
			this.fetchPossibleElementTypes();
		}
		componentDidUpdate(prevProps, prevState) {
			const { searchString } = this.state;
			if (searchString !== prevState.searchString) this.searchExistingElements();
		}
		componentWillUnmount() {
			this.cancellation.abort();
			this.filterCancellation.abort();
			this.loadingItemCancellation.abort();
		}
		async fetchPossibleElementTypes() {
			const { view, metadataApi, source } = this.props;
			if (!metadataApi) return;
			const elementTypes = await CancellationToken.mapCancelledToNull(this.cancellation.signal, metadataApi.typesOfElementsDraggedFrom(source, this.cancellation.signal));
			if (elementTypes === null) return;
			elementTypes.sort(makeElementTypeComparatorByLabel(view));
			this.setState({ elementTypes });
		}
		searchExistingElements() {
			const { editor, view } = this.props;
			const { searchString } = this.state;
			this.setState({ existingElements: [] });
			if (searchString.length > 0) {
				this.setState({ isLoading: true });
				this.filterCancellation.abort();
				this.filterCancellation = new Cancellation();
				const signal = this.filterCancellation.signal;
				const request = createRequest({ text: searchString }, view.getLanguage());
				editor.model.dataProvider.filter(request).then((elements) => {
					if (signal.aborted) return;
					const existingElements = Object.keys(elements).map((key) => elements[key]);
					this.setState({
						existingElements,
						isLoading: false
					});
				});
			}
		}
		renderElementTypeSelector() {
			const { elementValue } = this.props;
			const { elementTypes, isLoading } = this.state;
			const value = elementValue.value.types.length ? elementValue.value.types[0] : "";
			if (isLoading) return /* @__PURE__ */ react.createElement(HtmlSpinner, {
				width: 20,
				height: 20
			});
			return /* @__PURE__ */ react.createElement("div", { className: `${CLASS_NAME$13}__control-row` }, /* @__PURE__ */ react.createElement("label", null, "Entity Type"), elementTypes ? /* @__PURE__ */ react.createElement("select", {
				className: "graph-explorer-form-control",
				value,
				onChange: this.onElementTypeChange
			}, /* @__PURE__ */ react.createElement("option", {
				value: PLACEHOLDER_ELEMENT_TYPE,
				disabled: true
			}, "Select entity type"), elementTypes.map(this.renderPossibleElementType)) : /* @__PURE__ */ react.createElement("div", null, /* @__PURE__ */ react.createElement(HtmlSpinner, {
				width: 20,
				height: 20
			})), elementValue.error ? /* @__PURE__ */ react.createElement("span", { className: `${CLASS_NAME$13}__control-error` }, elementValue.error) : "");
		}
		renderExistingElementsList() {
			const { view, editor, elementValue } = this.props;
			const { elementTypes, isLoading, existingElements } = this.state;
			if (isLoading) return /* @__PURE__ */ react.createElement(HtmlSpinner, {
				width: 20,
				height: 20
			});
			if (existingElements.length > 0) return existingElements.map((element) => {
				const isAlreadyOnDiagram = !editor.temporaryState.elements.has(element.id) && Boolean(editor.model.elements.find(({ iri, group }) => iri === element.id && group === void 0));
				const hasAppropriateType = Boolean(elementTypes.find((type) => element.types.indexOf(type) >= 0));
				return /* @__PURE__ */ react.createElement(ListElementView, {
					key: element.id,
					view,
					model: element,
					disabled: isAlreadyOnDiagram || !hasAppropriateType,
					selected: element.id === elementValue.value.id,
					onClick: (e, model) => this.onSelectExistingItem(model)
				});
			});
			return /* @__PURE__ */ react.createElement("span", null, "No results");
		}
		async onSelectExistingItem(model) {
			const { editor, onChange } = this.props;
			this.loadingItemCancellation.abort();
			this.loadingItemCancellation = new Cancellation();
			const signal = this.loadingItemCancellation.signal;
			onChange({
				value: model,
				isNew: false,
				loading: true
			});
			const result = await editor.model.dataProvider.elementInfo({ elementIds: [model.id] });
			if (signal.aborted) return;
			const loadedModel = result[model.id];
			onChange({
				value: loadedModel,
				isNew: false,
				loading: false
			});
		}
		render() {
			const { searchString } = this.state;
			return /* @__PURE__ */ react.createElement("div", { className: `${CLASS_NAME$13}__form-row ${CLASS_NAME$13}__element-selector` }, /* @__PURE__ */ react.createElement("div", { className: `${CLASS_NAME$13}__search` }, /* @__PURE__ */ react.createElement("i", { className: `fa fa-search ${CLASS_NAME$13}__search-icon` }), /* @__PURE__ */ react.createElement("input", {
				value: searchString,
				onChange: (e) => this.setState({ searchString: e.target.value }),
				className: `graph-explorer-form-control ${CLASS_NAME$13}__search-input`,
				placeholder: "Search for...",
				autoFocus: true
			})), searchString.length > 0 ? /* @__PURE__ */ react.createElement("div", { className: `${CLASS_NAME$13}__existing-elements-list` }, this.renderExistingElementsList()) : /* @__PURE__ */ react.createElement("div", null, /* @__PURE__ */ react.createElement("div", { className: `${CLASS_NAME$13}__separator` }, /* @__PURE__ */ react.createElement("i", { className: `${CLASS_NAME$13}__separator-text` }, "or create new entity")), this.renderElementTypeSelector()));
		}
	};
	function makeElementTypeComparatorByLabel(view) {
		return (a, b) => {
			const typeA = view.model.createClass(a);
			const typeB = view.model.createClass(b);
			const labelA = view.formatLabel(typeA.label, typeA.id);
			const labelB = view.formatLabel(typeB.label, typeB.id);
			return labelA.localeCompare(labelB);
		};
	}
	function validateElementType(element) {
		const error = !(element.types.indexOf("http://graph-explorer.org/NewEntity") < 0) ? "Required." : void 0;
		return Promise.resolve({
			error,
			allowChange: true
		});
	}
	//#endregion
	//#region src/graph-explorer/forms/linkTypeSelector.tsx
	var CLASS_NAME$12 = "graph-explorer-edit-form";
	var LinkTypeSelector = class extends react.Component {
		constructor(props) {
			super(props);
			this.listener = new EventObserver();
			this.cancellation = new Cancellation();
			this.updateAll = () => this.forceUpdate();
			this.onChangeType = (e) => {
				const { link: originalLink, direction: originalDirection } = this.props.linkValue.value;
				const index = parseInt(e.currentTarget.value, 10);
				const { fatLinkType, direction } = this.state.fatLinkTypes[index];
				const link = {
					...originalLink,
					linkTypeId: fatLinkType.id
				};
				if (originalDirection !== direction) {
					link.sourceId = originalLink.targetId;
					link.targetId = originalLink.sourceId;
				}
				this.props.onChange({
					link,
					direction
				});
			};
			this.renderPossibleLinkType = ({ fatLinkType, direction }, index) => {
				const { view, source, target } = this.props;
				const label = view.formatLabel(fatLinkType.label, fatLinkType.id);
				let [sourceLabel, targetLabel] = [source, target].map((element) => view.formatLabel(element.label.values, element.id));
				if (direction === LinkDirection.in) [sourceLabel, targetLabel] = [targetLabel, sourceLabel];
				return /* @__PURE__ */ react.createElement("option", {
					key: index,
					value: index
				}, label, " [", sourceLabel, " → ", targetLabel, "]");
			};
			this.state = { fatLinkTypes: [] };
		}
		componentDidMount() {
			this.fetchPossibleLinkTypes();
		}
		componentDidUpdate(prevProps) {
			const { source, target } = this.props;
			if (prevProps.source !== source || prevProps.target !== target) {
				this.setState({ fatLinkTypes: void 0 });
				this.fetchPossibleLinkTypes();
			}
		}
		componentWillUnmount() {
			this.listener.stopListening();
			this.cancellation.abort();
		}
		async fetchPossibleLinkTypes() {
			const { view, metadataApi, source, target } = this.props;
			if (!metadataApi) return;
			const linkTypes = await CancellationToken.mapCancelledToNull(this.cancellation.signal, metadataApi.possibleLinkTypes(source, target, this.cancellation.signal));
			if (linkTypes === null) return;
			const fatLinkTypes = [];
			linkTypes.forEach(({ linkTypeIri, direction }) => {
				const fatLinkType = view.model.createLinkType(linkTypeIri);
				fatLinkTypes.push({
					fatLinkType,
					direction
				});
			});
			fatLinkTypes.sort(makeLinkTypeComparatorByLabelAndDirection(view));
			this.setState({ fatLinkTypes });
			this.listenToLinkLabels(fatLinkTypes);
		}
		listenToLinkLabels(fatLinkTypes) {
			fatLinkTypes.forEach(({ fatLinkType }) => this.listener.listen(fatLinkType.events, "changeLabel", this.updateAll));
		}
		render() {
			const { linkValue, disabled } = this.props;
			const { fatLinkTypes } = this.state;
			const value = (fatLinkTypes || []).findIndex(({ fatLinkType, direction }) => fatLinkType.id === linkValue.value.link.linkTypeId && direction === linkValue.value.direction);
			return /* @__PURE__ */ react.createElement("div", { className: `${CLASS_NAME$12}__control-row` }, /* @__PURE__ */ react.createElement("label", null, "Link Type"), fatLinkTypes ? /* @__PURE__ */ react.createElement("select", {
				className: "graph-explorer-form-control",
				value,
				onChange: this.onChangeType,
				disabled
			}, /* @__PURE__ */ react.createElement("option", {
				value: -1,
				disabled: true
			}, "Select link type"), fatLinkTypes.map(this.renderPossibleLinkType)) : /* @__PURE__ */ react.createElement("div", null, /* @__PURE__ */ react.createElement(HtmlSpinner, {
				width: 20,
				height: 20
			})), linkValue.error ? /* @__PURE__ */ react.createElement("span", { className: `${CLASS_NAME$12}__control-error` }, linkValue.error) : "");
		}
	};
	function makeLinkTypeComparatorByLabelAndDirection(view) {
		return (a, b) => {
			const labelA = view.formatLabel(a.fatLinkType.label, a.fatLinkType.id);
			const labelB = view.formatLabel(b.fatLinkType.label, b.fatLinkType.id);
			const labelCompareResult = labelA.localeCompare(labelB);
			if (labelCompareResult !== 0) return labelCompareResult;
			if (a.direction === LinkDirection.out && b.direction === LinkDirection.in) return -1;
			if (a.direction === LinkDirection.in && b.direction === LinkDirection.out) return 1;
			return 0;
		};
	}
	function validateLinkType(editor, currentLink, originalLink) {
		if (currentLink.linkTypeId === "http://graph-explorer.org/NewLink") return Promise.resolve({
			error: "Required.",
			allowChange: true
		});
		if (sameLink(currentLink, originalLink)) return Promise.resolve({
			error: void 0,
			allowChange: true
		});
		if (editor.model.links.find(({ data: { linkTypeId, sourceId, targetId } }) => linkTypeId === currentLink.linkTypeId && sourceId === currentLink.sourceId && targetId === currentLink.targetId && !editor.temporaryState.links.has(currentLink))) return Promise.resolve({
			error: "The link already exists.",
			allowChange: false
		});
		return editor.model.dataProvider.linksInfo({
			elementIds: [currentLink.sourceId, currentLink.targetId],
			linkTypeIds: [currentLink.linkTypeId]
		}).then((links) => {
			return links.some((link) => sameLink(link, currentLink)) ? {
				error: "The link already exists.",
				allowChange: false
			} : {
				error: void 0,
				allowChange: true
			};
		});
	}
	//#endregion
	//#region src/graph-explorer/forms/editElementTypeForm.tsx
	var CLASS_NAME$11 = "graph-explorer-edit-form";
	var EditElementTypeForm = class extends react.Component {
		constructor(props) {
			super(props);
			this.validationCancellation = new Cancellation();
			const { target, link } = this.props;
			this.state = {
				elementValue: {
					value: target.value,
					isNew: target.isNew,
					loading: false,
					validated: true,
					allowChange: true
				},
				linkValue: {
					value: {
						link,
						direction: LinkDirection.out
					},
					validated: true,
					allowChange: true
				}
			};
		}
		componentDidMount() {
			this.validate();
		}
		componentWillUnmount() {
			this.validationCancellation.abort();
		}
		setElementOrLink({ elementValue, linkValue }) {
			this.setState((state) => ({
				elementValue: elementValue || state.elementValue,
				linkValue: linkValue || state.linkValue
			}), () => {
				if (elementValue && !elementValue.validated || linkValue && !linkValue.validated) this.validate();
				if (elementValue && elementValue.validated && elementValue.allowChange) this.props.onChangeElement(elementValue.value);
				if (linkValue && linkValue.validated && linkValue.allowChange) this.props.onChangeLink(linkValue.value.link);
			});
		}
		validate() {
			const { editor, link: originalLink } = this.props;
			const { elementValue, linkValue } = this.state;
			this.setState({ isValidating: true });
			this.validationCancellation.abort();
			this.validationCancellation = new Cancellation();
			const signal = this.validationCancellation.signal;
			const validateElement = validateElementType(elementValue.value);
			const validateLink = validateLinkType(editor, linkValue.value.link, originalLink);
			Promise.all([validateElement, validateLink]).then(([elementError, linkError]) => {
				if (signal.aborted) return;
				this.setState({ isValidating: false });
				this.setElementOrLink({
					elementValue: {
						...elementValue,
						...elementError,
						validated: true
					},
					linkValue: {
						...linkValue,
						...linkError,
						validated: true
					}
				});
			});
		}
		render() {
			const { editor, view, metadataApi, source, link: originalLink } = this.props;
			const { elementValue, linkValue, isValidating } = this.state;
			const isValid = !elementValue.error && !linkValue.error;
			return /* @__PURE__ */ react.createElement("div", { className: CLASS_NAME$11 }, /* @__PURE__ */ react.createElement("div", { className: `${CLASS_NAME$11}__body` }, /* @__PURE__ */ react.createElement(ElementTypeSelector, {
				editor,
				view,
				metadataApi,
				source,
				elementValue,
				onChange: (newState) => {
					this.setElementOrLink({
						elementValue: {
							value: newState.value,
							isNew: newState.isNew,
							loading: newState.loading,
							error: void 0,
							validated: false,
							allowChange: false
						},
						linkValue: {
							value: {
								link: {
									...originalLink,
									targetId: newState.value.id
								},
								direction: LinkDirection.out
							},
							validated: false,
							allowChange: false
						}
					});
				}
			}), elementValue.loading ? /* @__PURE__ */ react.createElement("div", { style: { display: "flex" } }, /* @__PURE__ */ react.createElement(HtmlSpinner, {
				width: 20,
				height: 20
			}), "\xA0Loading entity...") : /* @__PURE__ */ react.createElement(LinkTypeSelector, {
				editor,
				view,
				metadataApi,
				linkValue,
				source,
				target: elementValue.value,
				onChange: (value) => this.setElementOrLink({ linkValue: {
					value,
					error: void 0,
					validated: false,
					allowChange: false
				} }),
				disabled: elementValue.error !== void 0
			}), isValidating ? /* @__PURE__ */ react.createElement("div", { className: `${CLASS_NAME$11}__progress` }, /* @__PURE__ */ react.createElement(ProgressBar, {
				state: ProgressState.loading,
				height: 10
			})) : null), /* @__PURE__ */ react.createElement("div", { className: `${CLASS_NAME$11}__controls` }, /* @__PURE__ */ react.createElement("button", {
				className: `graph-explorer-btn graph-explorer-btn-success ${CLASS_NAME$11}__apply-button`,
				onClick: () => this.props.onApply(elementValue.value, elementValue.isNew, linkValue.value.link),
				disabled: elementValue.loading || !isValid || isValidating
			}, "Apply"), /* @__PURE__ */ react.createElement("button", {
				className: "graph-explorer-btn graph-explorer-btn-danger",
				onClick: this.props.onCancel
			}, "Cancel")));
		}
	};
	//#endregion
	//#region src/graph-explorer/forms/editLinkForm.tsx
	var CLASS_NAME$10 = "graph-explorer-edit-form";
	var EditLinkForm = class extends react.Component {
		constructor(props) {
			super(props);
			this.validationCancellation = new Cancellation();
			this.state = { linkValue: {
				value: {
					link: props.link,
					direction: LinkDirection.out
				},
				validated: true,
				allowChange: true
			} };
		}
		componentDidMount() {
			this.validate();
		}
		componentDidUpdate(prevProps, prevState) {
			const { linkValue } = this.state;
			if (!sameLink(linkValue.value.link, prevState.linkValue.value.link)) this.validate();
			if (linkValue !== prevState.linkValue && linkValue.validated && linkValue.allowChange) this.props.onChange(linkValue.value.link);
		}
		componentWillUnmount() {
			this.validationCancellation.abort();
		}
		validate() {
			const { editor, link: originalLink } = this.props;
			const { linkValue: { value } } = this.state;
			this.setState({ isValidating: true });
			this.validationCancellation.abort();
			this.validationCancellation = new Cancellation();
			const signal = this.validationCancellation.signal;
			validateLinkType(editor, value.link, originalLink).then((error) => {
				if (signal.aborted) return;
				this.setState(({ linkValue }) => ({
					linkValue: {
						...linkValue,
						...error,
						validated: true
					},
					isValidating: false
				}));
			});
		}
		render() {
			const { editor, view, metadataApi, source, target } = this.props;
			const { linkValue, isValidating } = this.state;
			const isValid = !linkValue.error;
			return /* @__PURE__ */ react.createElement("div", { className: CLASS_NAME$10 }, /* @__PURE__ */ react.createElement("div", { className: `${CLASS_NAME$10}__body` }, /* @__PURE__ */ react.createElement(LinkTypeSelector, {
				editor,
				view,
				metadataApi,
				linkValue,
				source,
				target,
				onChange: (value) => this.setState({ linkValue: {
					value,
					error: void 0,
					validated: false,
					allowChange: false
				} })
			}), isValidating ? /* @__PURE__ */ react.createElement("div", { className: `${CLASS_NAME$10}__progress` }, /* @__PURE__ */ react.createElement(ProgressBar, {
				state: ProgressState.loading,
				height: 10
			})) : null), /* @__PURE__ */ react.createElement("div", { className: `${CLASS_NAME$10}__controls` }, /* @__PURE__ */ react.createElement("button", {
				className: `graph-explorer-btn graph-explorer-btn-success ${CLASS_NAME$10}__apply-button`,
				onClick: () => this.props.onApply(linkValue.value.link),
				disabled: !isValid || isValidating
			}, "Apply"), /* @__PURE__ */ react.createElement("button", {
				className: "graph-explorer-btn graph-explorer-btn-danger",
				onClick: this.props.onCancel
			}, "Cancel")));
		}
	};
	//#endregion
	//#region src/graph-explorer/forms/editLinkLabelForm.tsx
	var CLASS_NAME$9 = "graph-explorer-edit-form";
	var EditLinkLabelForm = class extends react.Component {
		constructor(props) {
			super(props);
			const label = this.computeLabel();
			this.state = { label };
		}
		componentDidUpdate(prevProps) {
			if (this.props.link.typeId !== prevProps.link.typeId) {
				const label = this.computeLabel();
				this.setState({ label });
			}
		}
		computeLabel() {
			const { view, link } = this.props;
			const linkType = view.model.getLinkType(link.typeId);
			const { label = {} } = view.createLinkTemplate(linkType).renderLink(link);
			const labelTexts = label.attrs && label.attrs.text ? label.attrs.text.text : void 0;
			return labelTexts && labelTexts.length > 0 ? view.selectLabel(labelTexts).value : view.formatLabel(linkType.label, linkType.id);
		}
		render() {
			const { onApply, onCancel } = this.props;
			const { label } = this.state;
			return /* @__PURE__ */ react.createElement("div", { className: CLASS_NAME$9 }, /* @__PURE__ */ react.createElement("div", { className: `${CLASS_NAME$9}__body` }, /* @__PURE__ */ react.createElement("div", { className: `${CLASS_NAME$9}__form-row` }, /* @__PURE__ */ react.createElement("label", null, "Link Label"), /* @__PURE__ */ react.createElement("input", {
				className: "graph-explorer-form-control",
				value: label,
				onChange: (e) => this.setState({ label: e.target.value })
			}))), /* @__PURE__ */ react.createElement("div", { className: `${CLASS_NAME$9}__controls` }, /* @__PURE__ */ react.createElement("button", {
				className: `graph-explorer-btn graph-explorer-btn-success ${CLASS_NAME$9}__apply-button`,
				onClick: () => onApply(label)
			}, "Apply"), /* @__PURE__ */ react.createElement("button", {
				className: "graph-explorer-btn graph-explorer-btn-danger",
				onClick: () => onCancel()
			}, "Cancel")));
		}
	};
	//#endregion
	//#region src/graph-explorer/widgets/halo.tsx
	var CLASS_NAME$8 = "graph-explorer-halo";
	var Halo = class extends react.Component {
		constructor(props) {
			super(props);
			this.listener = new EventObserver();
			this.targetListener = new EventObserver();
			this.queryDebouncer = new Debouncer();
			this.queryCancellation = new Cancellation();
			this.onElementEvent = (data) => {
				if (data.changePosition || data.changeSize || data.changeExpanded) this.forceUpdate();
				if (data.changeData) this.queryAllowedActions();
			};
			this.onEstablishNewLink = (e) => {
				const point = this.props.paperArea.pageToPaperCoords(e.pageX, e.pageY);
				this.props.onEstablishNewLink(point);
			};
			this.state = {};
		}
		componentDidMount() {
			const { editor, target } = this.props;
			this.listener.listen(editor.events, "changeAuthoringState", () => {
				this.queryAllowedActions();
			});
			this.listenToElement(target);
			this.queryAllowedActions();
		}
		componentDidUpdate(prevProps) {
			if (prevProps.target !== this.props.target) {
				this.listenToElement(this.props.target);
				this.queryAllowedActions();
			}
		}
		componentWillUnmount() {
			this.listener.stopListening();
			this.listenToElement(void 0);
			this.queryDebouncer.dispose();
			this.queryCancellation.abort();
		}
		listenToElement(element) {
			this.targetListener.stopListening();
			if (element) this.targetListener.listenAny(element.events, this.onElementEvent);
		}
		queryAllowedActions() {
			this.queryDebouncer.call(() => {
				this.queryCancellation.abort();
				this.queryCancellation = new Cancellation();
				this.canLink(this.props.target);
			});
		}
		canLink(target) {
			const { metadataApi, editor } = this.props;
			if (!metadataApi) {
				this.setState({ canLink: false });
				return;
			}
			const event = editor.authoringState.elements.get(target.iri);
			if (event && event.deleted) this.setState({ canLink: false });
			else {
				this.setState({ canLink: void 0 });
				const signal = this.queryCancellation.signal;
				CancellationToken.mapCancelledToNull(signal, metadataApi.canLinkElement(target.data, signal)).then((canLink) => {
					if (canLink === null) return;
					if (this.props.target.iri === target.iri) this.setState({ canLink });
				});
			}
		}
		render() {
			const { paperArea, editor, target, navigationMenuOpened, onToggleNavigationMenu, onAddToFilter, onExpand, onFollowLink } = this.props;
			if (!target) return /* @__PURE__ */ react.createElement("div", {
				className: CLASS_NAME$8,
				style: { display: "none" }
			});
			const bbox = boundsOf(target);
			const { x: x0, y: y0 } = paperArea.paperToScrollablePaneCoords(bbox.x, bbox.y);
			const { x: x1, y: y1 } = paperArea.paperToScrollablePaneCoords(bbox.x + bbox.width, bbox.y + bbox.height);
			const MARGIN = 5;
			const style = {
				left: x0 - MARGIN,
				top: y0 - MARGIN,
				width: x1 - x0 + MARGIN * 2,
				height: y1 - y0 + MARGIN * 2
			};
			return /* @__PURE__ */ react.createElement("div", {
				className: CLASS_NAME$8,
				style
			}, this.renderRemoveOrDeleteButton(), onToggleNavigationMenu && /* @__PURE__ */ react.createElement("div", {
				className: `${CLASS_NAME$8}__navigate ${CLASS_NAME$8}__navigate--${navigationMenuOpened ? "closed" : "open"}`,
				role: "button",
				title: "Open a dialog to navigate to connected elements",
				onClick: onToggleNavigationMenu
			}), onFollowLink && /* @__PURE__ */ react.createElement("a", {
				className: `${CLASS_NAME$8}__folow`,
				href: target.iri,
				role: "button",
				title: "Jump to resource",
				onClick: (e) => onFollowLink(target, e)
			}), onAddToFilter && /* @__PURE__ */ react.createElement("div", {
				className: `${CLASS_NAME$8}__add-to-filter`,
				role: "button",
				title: "Search for connected elements",
				onClick: onAddToFilter
			}), onExpand && /* @__PURE__ */ react.createElement("div", {
				className: `${CLASS_NAME$8}__expand ${CLASS_NAME$8}__expand--${target.isExpanded ? "closed" : "open"}`,
				role: "button",
				title: `Expand an element to reveal additional properties`,
				onClick: onExpand
			}), editor.inAuthoringMode ? this.renderEstablishNewLinkButton() : null);
		}
		renderRemoveOrDeleteButton() {
			const { editor, target, onRemove } = this.props;
			if (!onRemove) return null;
			const isNewElement = AuthoringState.isNewElement(editor.authoringState, target.iri);
			return /* @__PURE__ */ react.createElement("div", {
				className: isNewElement ? `${CLASS_NAME$8}__delete` : `${CLASS_NAME$8}__remove`,
				role: "button",
				title: isNewElement ? "Delete new element" : "Remove an element from the diagram",
				onClick: onRemove
			});
		}
		renderEstablishNewLinkButton() {
			const { onEstablishNewLink } = this.props;
			const { canLink } = this.state;
			if (!onEstablishNewLink) return null;
			if (canLink === void 0) return /* @__PURE__ */ react.createElement("div", { className: `${CLASS_NAME$8}__establish-connection-spinner` }, /* @__PURE__ */ react.createElement(HtmlSpinner, {
				width: 20,
				height: 20
			}));
			const title = canLink ? "Establish connection" : "Establishing connection is unavailable for the selected element";
			return /* @__PURE__ */ react.createElement("button", {
				className: `${CLASS_NAME$8}__establish-connection`,
				title,
				onMouseDown: this.onEstablishNewLink,
				disabled: !canLink
			});
		}
	};
	//#endregion
	//#region src/graph-explorer/widgets/haloLink.tsx
	var CLASS_NAME$7 = "graph-explorer-halo-link";
	var BUTTON_SIZE = 20;
	var HaloLink = class extends react.Component {
		constructor(props) {
			super(props);
			this.listener = new EventObserver();
			this.targetListener = new EventObserver();
			this.queryDebouncer = new Debouncer();
			this.queryCancellation = new Cancellation();
			this.updateAll = () => this.forceUpdate();
			this.onSourceMove = (e) => {
				const point = this.props.paperArea.pageToPaperCoords(e.pageX, e.pageY);
				this.props.onSourceMove(point);
			};
			this.onTargetMove = (e) => {
				const point = this.props.paperArea.pageToPaperCoords(e.pageX, e.pageY);
				this.props.onTargetMove(point);
			};
			this.state = {};
		}
		componentDidMount() {
			const { target, editor } = this.props;
			this.listener.listen(editor.events, "changeAuthoringState", () => {
				this.queryAllowedActions();
			});
			this.listenToTarget(target);
			this.queryAllowedActions();
		}
		componentDidUpdate(prevProps) {
			if (prevProps.target !== this.props.target) {
				this.listenToTarget(this.props.target);
				this.queryAllowedActions();
			}
		}
		componentWillUnmount() {
			this.listener.stopListening();
			this.listenToTarget(void 0);
			this.queryDebouncer.dispose();
			this.queryCancellation.abort();
		}
		queryAllowedActions() {
			this.queryDebouncer.call(() => {
				this.queryCancellation.abort();
				this.queryCancellation = new Cancellation();
				this.queryCanDelete(this.props.target);
				this.queryCanEdit(this.props.target);
			});
		}
		queryCanDelete(link) {
			const { metadataApi, editor, view } = this.props;
			if (!metadataApi) {
				this.setState({ canDelete: false });
				return;
			}
			if (isSourceOrTargetDeleted(editor.authoringState, link)) this.setState({ canDelete: false });
			else {
				this.setState({ canDelete: void 0 });
				const source = view.model.getElement(link.sourceId);
				const target = view.model.getElement(link.targetId);
				const signal = this.queryCancellation.signal;
				CancellationToken.mapCancelledToNull(signal, metadataApi.canDeleteLink(link.data, source.data, target.data, signal)).then((canDelete) => {
					if (canDelete === null) return;
					if (this.props.target.id === link.id) this.setState({ canDelete });
				});
			}
		}
		queryCanEdit(link) {
			const { metadataApi, editor, view } = this.props;
			if (!metadataApi) {
				this.setState({ canEdit: false });
				return;
			}
			if (isDeletedLink(editor.authoringState, link)) this.setState({ canEdit: false });
			else {
				this.setState({ canEdit: void 0 });
				const source = view.model.getElement(link.sourceId);
				const target = view.model.getElement(link.targetId);
				const signal = this.queryCancellation.signal;
				CancellationToken.mapCancelledToNull(signal, metadataApi.canEditLink(link.data, source.data, target.data, signal)).then((canEdit) => {
					if (canEdit === null) return;
					if (this.props.target.id === link.id) this.setState({ canEdit });
				});
			}
		}
		listenToTarget(link) {
			const { view } = this.props;
			this.targetListener.stopListening();
			if (link) {
				const source = view.model.getElement(link.sourceId);
				const target = view.model.getElement(link.targetId);
				const listenToElement = (element) => {
					this.targetListener.listen(element.events, "changePosition", this.updateAll);
					this.targetListener.listen(element.events, "changeSize", this.updateAll);
				};
				listenToElement(source);
				listenToElement(target);
				this.targetListener.listen(link.events, "changeVertices", this.updateAll);
				this.targetListener.listen(link.events, "changeLabelBounds", this.updateAll);
			}
		}
		paperToScrollablePaneCoords(point) {
			return this.props.paperArea.paperToScrollablePaneCoords(point.x, point.y);
		}
		computePolyline() {
			const { view, target } = this.props;
			const sourceElement = view.model.getElement(target.sourceId);
			const targetElement = view.model.getElement(target.targetId);
			if (!(sourceElement && targetElement)) return;
			const route = view.getRouting(target.id);
			const verticesDefinedByUser = target.vertices || [];
			return computePolyline(sourceElement, targetElement, route ? route.vertices : verticesDefinedByUser);
		}
		calculateDegree(source, target) {
			const x = target.x - source.x;
			const y = target.y - source.y;
			const r = Math.sqrt(x * x + y * y);
			const unit = {
				x: x / r,
				y: y / r
			};
			return Math.atan2(unit.y, unit.x) * (180 / Math.PI);
		}
		renderSourceButton(polyline) {
			const { editor, target } = this.props;
			const point = getPointAlongPolyline(polyline, 0);
			const { x, y } = this.paperToScrollablePaneCoords(point);
			const style = {
				top: y - BUTTON_SIZE / 2,
				left: x - BUTTON_SIZE / 2
			};
			return /* @__PURE__ */ react.createElement("button", {
				className: `${CLASS_NAME$7}__button`,
				style,
				disabled: isDeletedLink(editor.authoringState, target),
				onMouseDown: this.onSourceMove
			}, /* @__PURE__ */ react.createElement("svg", {
				width: BUTTON_SIZE,
				height: BUTTON_SIZE
			}, /* @__PURE__ */ react.createElement("g", { transform: `scale(${BUTTON_SIZE})` }, /* @__PURE__ */ react.createElement("circle", {
				r: .5,
				cx: .5,
				cy: .5,
				fill: "#198AD3"
			}))));
		}
		getButtonPosition(polyline, index) {
			const point = getPointAlongPolyline(polyline, computePolylineLength(polyline) - 25 * index);
			const { x, y } = this.paperToScrollablePaneCoords(point);
			return {
				top: y - BUTTON_SIZE / 2,
				left: x - BUTTON_SIZE / 2
			};
		}
		renderTargetButton(polyline) {
			const { editor, target } = this.props;
			const style = this.getButtonPosition(polyline, 0);
			const { length } = polyline;
			const degree = this.calculateDegree(polyline[length - 1], polyline[length - 2]);
			return /* @__PURE__ */ react.createElement("button", {
				className: `${CLASS_NAME$7}__button`,
				style,
				disabled: isDeletedLink(editor.authoringState, target),
				onMouseDown: this.onTargetMove
			}, /* @__PURE__ */ react.createElement("svg", {
				width: BUTTON_SIZE,
				height: BUTTON_SIZE,
				style: { transform: `rotate(${degree}deg)` }
			}, /* @__PURE__ */ react.createElement("g", { transform: `scale(${BUTTON_SIZE})` }, /* @__PURE__ */ react.createElement("polygon", {
				points: "0,0.5 1,1 1,0",
				fill: "#198AD3"
			}))));
		}
		renderEditButton(polyline) {
			const { canEdit } = this.state;
			const style = this.getButtonPosition(polyline, 1);
			if (canEdit === void 0) return /* @__PURE__ */ react.createElement("div", {
				className: `${CLASS_NAME$7}__spinner`,
				style
			}, /* @__PURE__ */ react.createElement(HtmlSpinner, {
				width: 20,
				height: 20
			}));
			const title = canEdit ? "Edit link" : "Editing is unavailable for the selected link";
			return /* @__PURE__ */ react.createElement("button", {
				className: `${CLASS_NAME$7}__button ${CLASS_NAME$7}__edit`,
				style,
				title,
				onClick: this.props.onEdit,
				disabled: !canEdit
			});
		}
		renderDeleteButton(polyline) {
			const { canDelete } = this.state;
			const style = this.getButtonPosition(polyline, 2);
			if (canDelete === void 0) return /* @__PURE__ */ react.createElement("div", {
				className: `${CLASS_NAME$7}__spinner`,
				style
			}, /* @__PURE__ */ react.createElement(HtmlSpinner, {
				width: 20,
				height: 20
			}));
			const title = canDelete ? "Delete link" : "Deletion is unavailable for the selected link";
			return /* @__PURE__ */ react.createElement("button", {
				className: `${CLASS_NAME$7}__button ${CLASS_NAME$7}__delete`,
				style,
				title,
				onClick: this.props.onDelete,
				disabled: !canDelete
			});
		}
		renderEditLabelButton() {
			const { view, target, paperArea, onEditLabel } = this.props;
			const linkType = view.model.getLinkType(target.typeId);
			if (!view.createLinkTemplate(linkType).setLinkLabel || !target.labelBounds) return null;
			const { x, y, width, height } = target.labelBounds;
			const { x: left, y: top } = paperArea.paperToScrollablePaneCoords(x + width, y + height / 2);
			const size = {
				width: 15,
				height: 17
			};
			const style = {
				width: size.width,
				height: size.height,
				top: top - size.height / 2,
				left
			};
			return /* @__PURE__ */ react.createElement("button", {
				className: `${CLASS_NAME$7}__edit-label-button`,
				style,
				onClick: () => onEditLabel(),
				title: "Edit Link Label"
			});
		}
		render() {
			const { editor, target, metadataApi } = this.props;
			const polyline = this.computePolyline();
			if (!polyline) return null;
			const isAuthoringMode = Boolean(metadataApi);
			const deleteButton = isDeletedByItself(editor.authoringState, target) || isSourceOrTargetDeleted(editor.authoringState, target) ? null : this.renderDeleteButton(polyline);
			return /* @__PURE__ */ react.createElement("div", { className: `${CLASS_NAME$7}` }, isAuthoringMode ? this.renderTargetButton(polyline) : null, isAuthoringMode ? this.renderSourceButton(polyline) : null, !isAuthoringMode || isDeletedLink(editor.authoringState, target) ? null : this.renderEditButton(polyline), isAuthoringMode ? deleteButton : null, this.renderEditLabelButton());
		}
	};
	function isDeletedLink(state, link) {
		return isDeletedByItself(state, link) || isSourceOrTargetDeleted(state, link);
	}
	function isDeletedByItself(state, link) {
		const event = state.links.get(link.data);
		return event && event.deleted;
	}
	function isSourceOrTargetDeleted(state, link) {
		const sourceEvent = state.elements.get(link.data.sourceId);
		const targetEvent = state.elements.get(link.data.targetId);
		return sourceEvent && sourceEvent.deleted || targetEvent && targetEvent.deleted;
	}
	//#endregion
	//#region src/graph-explorer/editor/linkStateWidget.tsx
	var CLASS_NAME$6 = `graph-explorer-authoring-state`;
	var LINK_LABEL_MARGIN = 5;
	var LinkStateWidget = class extends react.Component {
		constructor(..._args) {
			super(..._args);
			this.listener = new EventObserver();
			this.delayedUpdate = new Debouncer();
			this.scheduleUpdate = () => {
				this.delayedUpdate.call(this.performUpdate);
			};
			this.performUpdate = () => {
				this.forceUpdate();
			};
		}
		componentDidMount() {
			this.listenEvents();
		}
		componentDidUpdate(prevProps) {
			if (!(this.props.view === prevProps.view)) {
				this.listener.stopListening();
				this.listenEvents();
			}
		}
		componentWillUnmount() {
			this.listener.stopListening();
		}
		listenEvents() {
			const { editor, view } = this.props;
			this.listener.listen(editor.model.events, "elementEvent", ({ data }) => {
				if (data.changeSize || data.changePosition) this.scheduleUpdate();
			});
			this.listener.listen(editor.model.events, "linkEvent", ({ data }) => {
				if (data.changeVertices || data.changeLabelBounds) this.scheduleUpdate();
			});
			this.listener.listen(editor.model.events, "changeCells", this.scheduleUpdate);
			this.listener.listen(editor.events, "changeAuthoringState", this.scheduleUpdate);
			this.listener.listen(editor.events, "changeTemporaryState", this.scheduleUpdate);
			this.listener.listen(editor.events, "changeValidationState", this.scheduleUpdate);
			this.listener.listen(view.events, "syncUpdate", ({ layer }) => {
				if (layer === RenderingLayer.Editor) this.delayedUpdate.runSynchronously();
			});
		}
		calculateLinkPath(link) {
			return "M" + this.calculatePolyline(link).map(({ x, y }) => `${x},${y}`).join(" L");
		}
		calculatePolyline(link) {
			const { editor, view } = this.props;
			const source = editor.model.getElement(link.sourceId);
			const target = editor.model.getElement(link.targetId);
			const route = view.getRouting(link.id);
			const verticesDefinedByUser = link.vertices || [];
			return computePolyline(source, target, route ? route.vertices : verticesDefinedByUser);
		}
		renderLinkStateLabels() {
			const { editor } = this.props;
			return editor.model.links.map((link) => {
				let renderedState = null;
				const state = editor.authoringState.links.get(link.data);
				if (state) {
					const onCancel = () => editor.discardChange(state);
					let statusText;
					let title;
					if (state.deleted) {
						statusText = "Delete";
						title = "Revert deletion of the link";
					} else if (!state.before) {
						statusText = "New";
						title = "Revert creation of the link";
					} else {
						statusText = "Change";
						title = "Revert all changes in properties of the link";
					}
					if (statusText && title) renderedState = /* @__PURE__ */ react.createElement("span", null, /* @__PURE__ */ react.createElement("span", { className: `${CLASS_NAME$6}__state-label` }, statusText), "[", /* @__PURE__ */ react.createElement("span", {
						className: `${CLASS_NAME$6}__state-cancel`,
						onClick: onCancel,
						title
					}, "cancel"), "]");
				}
				const renderedErrors = this.renderLinkErrors(link.data);
				if (renderedState || renderedErrors) {
					const labelPosition = this.getLinkStateLabelPosition(link);
					if (!labelPosition) return null;
					const style = {
						left: labelPosition.x,
						top: labelPosition.y
					};
					return /* @__PURE__ */ react.createElement("div", {
						className: `${CLASS_NAME$6}__state-indicator`,
						key: link.id,
						style
					}, /* @__PURE__ */ react.createElement("div", { className: `${CLASS_NAME$6}__state-indicator-container` }, /* @__PURE__ */ react.createElement("div", { className: `${CLASS_NAME$6}__state-indicator-body` }, renderedState, renderedErrors)));
				} else return null;
			});
		}
		renderLinkStateHighlighting() {
			const { editor } = this.props;
			return editor.model.links.map((link) => {
				if (editor.temporaryState.links.has(link.data)) {
					const path = this.calculateLinkPath(link);
					return /* @__PURE__ */ react.createElement("path", {
						key: link.id,
						d: path,
						fill: "none",
						stroke: "grey",
						strokeWidth: 5,
						strokeOpacity: .5,
						strokeDasharray: "8 8"
					});
				}
				const event = editor.authoringState.links.get(link.data);
				const isDeletedLink = AuthoringState.isDeletedLink(editor.authoringState, link.data);
				const isUncertainLink = AuthoringState.isUncertainLink(editor.authoringState, link.data);
				if (event || isDeletedLink || isUncertainLink) {
					const path = this.calculateLinkPath(link);
					let color;
					if (isDeletedLink) color = "red";
					else if (isUncertainLink) color = "blue";
					else if (event && event.type === AuthoringKind.ChangeLink) color = event.before ? "blue" : "green";
					return /* @__PURE__ */ react.createElement("path", {
						key: link.id,
						d: path,
						fill: "none",
						stroke: color,
						strokeWidth: 5,
						strokeOpacity: .5
					});
				}
				return null;
			});
		}
		getLinkStateLabelPosition(link) {
			if (link.labelBounds) {
				const { x, y } = link.labelBounds;
				return {
					x,
					y: y - LINK_LABEL_MARGIN / 2
				};
			} else {
				const polyline = this.calculatePolyline(link);
				return getPointAlongPolyline(polyline, computePolylineLength(polyline) / 2);
			}
		}
		renderLinkErrors(linkModel) {
			const { editor } = this.props;
			const { validationState } = editor;
			const validation = validationState.links.get(linkModel);
			if (!validation) return null;
			const title = validation.errors.map((error) => error.message).join("\n");
			return this.renderErrorIcon(title, validation);
		}
		renderErrorIcon(title, validation) {
			return /* @__PURE__ */ react.createElement("div", {
				className: `${CLASS_NAME$6}__item-error`,
				title
			}, validation.loading ? /* @__PURE__ */ react.createElement(HtmlSpinner, {
				width: 15,
				height: 17
			}) : /* @__PURE__ */ react.createElement("div", { className: `${CLASS_NAME$6}__item-error-icon` }), !validation.loading && validation.errors.length > 0 ? validation.errors.length : void 0);
		}
		render() {
			const { editor, paperTransform } = this.props;
			const { scale, originX, originY } = paperTransform;
			if (!editor.inAuthoringMode) return null;
			const htmlTransformStyle = {
				position: "absolute",
				left: 0,
				top: 0,
				transform: `scale(${scale},${scale})translate(${originX}px,${originY}px)`
			};
			return /* @__PURE__ */ react.createElement("div", { className: `${CLASS_NAME$6}` }, /* @__PURE__ */ react.createElement(TransformedSvgCanvas, {
				paperTransform,
				style: {
					overflow: "visible",
					pointerEvents: "none"
				}
			}, this.renderLinkStateHighlighting()), /* @__PURE__ */ react.createElement("div", {
				className: `${CLASS_NAME$6}__validation-layer`,
				style: htmlTransformStyle
			}, this.renderLinkStateLabels()));
		}
	};
	//#endregion
	//#region src/graph-explorer/editor/elementDecorator.tsx
	var CLASS_NAME$5 = `graph-explorer-authoring-state`;
	var ElementDecorator = class extends react.Component {
		constructor(props) {
			super(props);
			this.listener = new EventObserver();
			const { model, editor } = props;
			this.state = {
				state: editor.authoringState.elements.get(model.iri),
				validation: editor.validationState.elements.get(model.iri),
				isTemporary: editor.temporaryState.elements.has(model.iri)
			};
		}
		componentDidMount() {
			const { model, editor } = this.props;
			this.listener.listen(model.events, "changeSize", () => this.forceUpdate());
			this.listener.listen(editor.events, "changeAuthoringState", (e) => {
				const state = editor.authoringState.elements.get(model.iri);
				if (state === e.previous.elements.get(model.iri)) return;
				this.setState({ state });
			});
			this.listener.listen(editor.events, "changeValidationState", (e) => {
				const validation = editor.validationState.elements.get(model.iri);
				if (validation === e.previous.elements.get(model.iri)) return;
				this.setState({ validation });
			});
			this.listener.listen(editor.events, "changeTemporaryState", (e) => {
				const isTemporary = editor.temporaryState.elements.has(model.iri);
				if (isTemporary === e.previous.elements.has(model.iri)) return;
				this.setState({ isTemporary });
			});
			this.listener.listen(model.events, "changeData", (e) => {
				if (e.previous.id !== model.iri) this.setState({
					isTemporary: editor.temporaryState.elements.has(model.iri),
					validation: editor.validationState.elements.get(model.iri),
					state: editor.authoringState.elements.get(model.iri)
				});
			});
		}
		componentWillUnmount() {
			this.listener.stopListening();
		}
		shouldComponentUpdate(nextProps, nextState) {
			return this.state.state !== nextState.state || this.state.validation !== nextState.validation || this.state.isTemporary !== nextState.isTemporary || this.props.position !== nextProps.position;
		}
		renderElementOutlines() {
			const { model } = this.props;
			const { state, isTemporary } = this.state;
			const { width, height } = model.size;
			if (isTemporary) return [/* @__PURE__ */ react.createElement("rect", {
				key: `${model.id}-opacity`,
				x: 0,
				y: 0,
				width,
				height,
				fill: "rgba(255, 255, 255, 0.5)"
			}), /* @__PURE__ */ react.createElement("rect", {
				key: `${model.id}-stripes`,
				x: 0,
				y: 0,
				width,
				height,
				fill: "url(#stripe-pattern)"
			})];
			if (state && state.deleted) {
				const right = width;
				const bottom = height;
				return /* @__PURE__ */ react.createElement("g", { key: model.id }, /* @__PURE__ */ react.createElement("rect", {
					x: 0,
					y: 0,
					width,
					height,
					fill: "white",
					fillOpacity: .5
				}), /* @__PURE__ */ react.createElement("line", {
					x1: 0,
					y1: 0,
					x2: right,
					y2: bottom,
					stroke: "red"
				}), /* @__PURE__ */ react.createElement("line", {
					x1: right,
					y1: 0,
					x2: 0,
					y2: bottom,
					stroke: "red"
				}));
			}
			return null;
		}
		renderErrorIcon(title, validation) {
			return /* @__PURE__ */ react.createElement("div", {
				className: `${CLASS_NAME$5}__item-error`,
				title
			}, validation.loading ? /* @__PURE__ */ react.createElement(HtmlSpinner, {
				width: 15,
				height: 17
			}) : /* @__PURE__ */ react.createElement("div", { className: `${CLASS_NAME$5}__item-error-icon` }), !validation.loading && validation.errors.length > 0 ? validation.errors.length : void 0);
		}
		renderElementErrors() {
			const { view } = this.props;
			const { validation } = this.state;
			if (!validation) return null;
			const title = validation.errors.map((error) => {
				if (error.propertyType) {
					const { id, label } = view.model.createProperty(error.propertyType);
					return `${view.formatLabel(label, id)}: ${error.message}`;
				} else return error.message;
			}).join("\n");
			return this.renderErrorIcon(title, validation);
		}
		renderElementState() {
			const { model, editor } = this.props;
			const { state } = this.state;
			if (state) {
				const onCancel = () => editor.discardChange(state);
				let renderedState;
				let statusText;
				let title;
				if (state.deleted) {
					statusText = "Delete";
					title = "Revert deletion of the element";
				} else if (!state.before) {
					statusText = "New";
					title = "Revert creation of the element";
				} else {
					statusText = "Change";
					title = "Revert all changes in properties of the element";
				}
				if (statusText && title) renderedState = /* @__PURE__ */ react.createElement("span", null, /* @__PURE__ */ react.createElement("span", { className: `${CLASS_NAME$5}__state-label` }, statusText), "[", /* @__PURE__ */ react.createElement("span", {
					className: `${CLASS_NAME$5}__state-cancel`,
					onClick: onCancel,
					title
				}, "cancel"), "]");
				const renderedErrors = this.renderElementErrors();
				if (renderedState || renderedErrors) return /* @__PURE__ */ react.createElement("div", {
					className: `${CLASS_NAME$5}__state-indicator`,
					key: model.id,
					style: {
						left: 0,
						top: 0
					}
				}, /* @__PURE__ */ react.createElement("div", { className: `${CLASS_NAME$5}__state-indicator-container` }, /* @__PURE__ */ react.createElement("div", { className: `${CLASS_NAME$5}__state-indicator-body` }, renderedState, renderedErrors)));
			}
			return null;
		}
		render() {
			const { position, size } = this.props.model;
			const transform = `translate(${position.x}px,${position.y}px)`;
			const outlines = this.renderElementOutlines();
			const state = this.renderElementState();
			if (!outlines && !state) return null;
			return /* @__PURE__ */ react.createElement("div", { style: {
				position: "absolute",
				transform
			} }, outlines ? /* @__PURE__ */ react.createElement("svg", {
				width: size.width,
				height: size.height,
				style: {
					position: "absolute",
					pointerEvents: "none",
					overflow: "visible"
				}
			}, /* @__PURE__ */ react.createElement("defs", null, /* @__PURE__ */ react.createElement("pattern", {
				id: "stripe-pattern",
				patternUnits: "userSpaceOnUse",
				width: 13,
				height: 13,
				patternTransform: "rotate(45)"
			}, /* @__PURE__ */ react.createElement("line", {
				x1: 0,
				y: 0,
				x2: 0,
				y2: 13,
				stroke: "#ddd",
				strokeWidth: 10,
				strokeOpacity: .2
			}))), this.renderElementOutlines()) : null, state);
		}
	};
	//#endregion
	//#region src/graph-explorer/editor/temporaryState.ts
	var TemporaryState = {
		empty: {
			elements: /* @__PURE__ */ new Map(),
			links: new HashMap(hashLink, sameLink)
		},
		addElement(state, element) {
			const elements = cloneMap(state.elements);
			elements.set(element.id, element);
			return {
				...state,
				elements
			};
		},
		deleteElement(state, element) {
			const elements = cloneMap(state.elements);
			elements.delete(element.id);
			return {
				...state,
				elements
			};
		},
		addLink(state, link) {
			const links = state.links.clone();
			links.set(link, link);
			return {
				...state,
				links
			};
		},
		deleteLink(state, link) {
			const links = state.links.clone();
			links.delete(link);
			return {
				...state,
				links
			};
		}
	};
	//#endregion
	//#region src/graph-explorer/editor/editLayer.tsx
	var EditLayerMode = /* @__PURE__ */ function(EditLayerMode) {
		EditLayerMode[EditLayerMode["establishLink"] = 0] = "establishLink";
		EditLayerMode[EditLayerMode["moveLinkSource"] = 1] = "moveLinkSource";
		EditLayerMode[EditLayerMode["moveLinkTarget"] = 2] = "moveLinkTarget";
		return EditLayerMode;
	}({});
	var EditLayer = class extends react.Component {
		constructor(props) {
			super(props);
			this.listener = new EventObserver();
			this.cancellation = new Cancellation();
			this.canDropOnElementCancellation = new Cancellation();
			this.beginCreatingLink = (params) => {
				const { editor } = this.props;
				const { sourceId, point } = params;
				const temporaryElement = this.createTemporaryElement(point);
				const linkTemplate = new Link({
					typeId: PLACEHOLDER_LINK_TYPE,
					sourceId,
					targetId: temporaryElement.id
				});
				const temporaryLink = editor.createNewLink({
					link: linkTemplate,
					temporary: true
				});
				editor.model.createLinkType(temporaryLink.typeId).setVisibility({
					visible: true,
					showLabel: false
				});
				this.temporaryElement = temporaryElement;
				this.temporaryLink = temporaryLink;
			};
			this.onMouseMove = (e) => {
				const { view, paperArea } = this.props;
				const { targetElement, waitingForMetadata } = this.state;
				e.preventDefault();
				e.stopPropagation();
				if (waitingForMetadata) return;
				const point = paperArea.pageToPaperCoords(e.pageX, e.pageY);
				this.temporaryElement.setPosition(point);
				const newTargetElement = findElementAtPoint(view.model.elements, point);
				if (newTargetElement !== targetElement) this.queryCanDropOnElement(newTargetElement);
				this.setState({ targetElement: newTargetElement });
			};
			this.onMouseUp = (e) => {
				if (this.state.waitingForMetadata) return;
				this.setState({ waitingForMetadata: true });
				const selectedPosition = this.props.paperArea.pageToPaperCoords(e.pageX, e.pageY);
				this.executeEditOperation(selectedPosition);
			};
			this.createNewElement = async (source) => {
				const { editor, metadataApi } = this.props;
				if (!metadataApi) return;
				const elementTypes = await CancellationToken.mapCancelledToNull(this.cancellation.signal, metadataApi.typesOfElementsDraggedFrom(source, this.cancellation.signal));
				if (elementTypes === null) return;
				const classId = elementTypes.length === 1 ? elementTypes[0] : PLACEHOLDER_ELEMENT_TYPE;
				const elementModel = await CancellationToken.mapCancelledToNull(this.cancellation.signal, metadataApi.generateNewElement([classId], this.cancellation.signal));
				if (elementModel === null) return;
				return editor.createNewEntity({
					elementModel,
					temporary: true
				});
			};
			this.state = {};
		}
		componentDidMount() {
			const { mode, target, point } = this.props;
			if (mode === 0) this.beginCreatingLink({
				sourceId: target.id,
				point
			});
			else if (mode === 1 || mode === 2) this.beginMovingLink(target, point);
			else throw new Error("Unknown edit mode");
			this.forceUpdate();
			this.queryCanLinkFrom();
			this.queryCanDropOnCanvas();
			document.addEventListener("mousemove", this.onMouseMove);
			document.addEventListener("mouseup", this.onMouseUp);
		}
		componentWillUnmount() {
			this.listener.stopListening();
			this.cancellation.abort();
			this.canDropOnElementCancellation.abort();
			document.removeEventListener("mousemove", this.onMouseMove);
			document.removeEventListener("mouseup", this.onMouseUp);
		}
		beginMovingLink(target, startingPoint) {
			const { editor, mode } = this.props;
			if (!(mode === 1 || mode === 2)) throw new Error("Unexpected edit mode for moving link");
			this.oldLink = target;
			editor.model.removeLink(target.id);
			const { id: _id, typeId, sourceId, targetId, ...otherProps } = target;
			const temporaryElement = this.createTemporaryElement(startingPoint);
			const linkTemplate = new Link({
				typeId,
				sourceId: mode === 1 ? temporaryElement.id : sourceId,
				targetId: mode === 2 ? temporaryElement.id : targetId,
				...otherProps
			});
			const temporaryLink = editor.createNewLink({
				link: linkTemplate,
				temporary: true
			});
			this.temporaryElement = temporaryElement;
			this.temporaryLink = temporaryLink;
		}
		createTemporaryElement(point) {
			const temporaryElement = this.props.view.model.createTemporaryElement();
			temporaryElement.setPosition(point);
			return temporaryElement;
		}
		queryCanLinkFrom() {
			const { editor, metadataApi } = this.props;
			if (!metadataApi) {
				this.setState({ canLinkFrom: false });
				return;
			}
			this.setState({ canLinkFrom: void 0 });
			const source = editor.model.getElement(this.temporaryLink.sourceId);
			CancellationToken.mapCancelledToNull(this.cancellation.signal, metadataApi.canLinkElement(source.data, this.cancellation.signal)).then((canLinkFrom) => {
				if (canLinkFrom === null) return;
				this.setState({ canLinkFrom });
			}, (error) => {
				console.error("Error calling canLinkElement:", error);
				this.setState({ canLinkFrom: false });
			});
		}
		queryCanDropOnCanvas() {
			const { mode, editor, metadataApi } = this.props;
			if (!metadataApi || mode !== 0) {
				this.setState({ canDropOnCanvas: false });
				return;
			}
			this.setState({ canDropOnCanvas: void 0 });
			const source = editor.model.getElement(this.temporaryLink.sourceId);
			CancellationToken.mapCancelledToNull(this.cancellation.signal, metadataApi.canDropOnCanvas(source.data, this.cancellation.signal)).then((canDropOnCanvas) => {
				if (canDropOnCanvas === null) return;
				this.setState({ canDropOnCanvas });
			}, (error) => {
				console.error("Error calling canDropOnCanvas:", error);
				this.setState({ canDropOnCanvas: false });
			});
		}
		queryCanDropOnElement(targetElement) {
			const { mode, editor, metadataApi } = this.props;
			this.canDropOnElementCancellation.abort();
			this.canDropOnElementCancellation = new Cancellation();
			if (!(metadataApi && targetElement)) {
				this.setState({ canDropOnElement: false });
				return;
			}
			this.setState({ canDropOnElement: void 0 });
			let source;
			let target;
			if (mode === 0 || mode === 2) {
				source = editor.model.getElement(this.temporaryLink.sourceId).data;
				target = targetElement.data;
			} else if (mode === 1) {
				source = targetElement.data;
				target = editor.model.getElement(this.temporaryLink.targetId).data;
			}
			const signal = this.canDropOnElementCancellation.signal;
			CancellationToken.mapCancelledToNull(signal, metadataApi.canDropOnElement(source, target, signal)).then((canDropOnElement) => {
				if (canDropOnElement === null) return;
				this.setState({ canDropOnElement });
			});
		}
		async executeEditOperation(selectedPosition) {
			const { view, editor, mode } = this.props;
			try {
				const { targetElement, canLinkFrom, canDropOnCanvas, canDropOnElement } = this.state;
				if (this.oldLink) editor.model.addLink(this.oldLink);
				if (canLinkFrom && (targetElement ? canDropOnElement : canDropOnCanvas)) {
					let modifiedLink;
					let createdTarget = targetElement;
					switch (mode) {
						case 0: {
							if (!createdTarget) {
								const source = editor.model.getElement(this.temporaryLink.sourceId);
								createdTarget = await this.createNewElement(source.data);
								createdTarget.setPosition(selectedPosition);
								view.performSyncUpdate();
								centerElementAtPoint(createdTarget, selectedPosition);
							}
							const sourceElement = editor.model.getElement(this.temporaryLink.sourceId);
							modifiedLink = await this.createNewLink(sourceElement, createdTarget);
							break;
						}
						case 1:
							modifiedLink = editor.moveLinkSource({
								link: this.oldLink,
								newSource: targetElement
							});
							break;
						case 2:
							modifiedLink = editor.moveLinkTarget({
								link: this.oldLink,
								newTarget: targetElement
							});
							break;
						default: throw new Error("Unknown edit mode");
					}
					if (targetElement) {
						const focusedLink = modifiedLink || this.oldLink;
						editor.setSelection([focusedLink]);
						editor.showEditLinkForm(focusedLink);
					} else if (createdTarget && modifiedLink) {
						editor.setSelection([createdTarget]);
						const source = editor.model.getElement(modifiedLink.sourceId);
						editor.showEditElementTypeForm({
							link: modifiedLink,
							source,
							target: createdTarget,
							targetIsNew: true
						});
					}
				}
			} finally {
				this.cleanupAndFinish();
			}
		}
		async createNewLink(source, target) {
			const { editor, metadataApi } = this.props;
			if (!metadataApi) return;
			const linkTypes = await CancellationToken.mapCancelledToNull(this.cancellation.signal, metadataApi.possibleLinkTypes(source.data, target.data, this.cancellation.signal));
			if (linkTypes === null) return;
			const placeholder = {
				linkTypeIri: PLACEHOLDER_LINK_TYPE,
				direction: LinkDirection.out
			};
			const { linkTypeIri: typeId, direction } = linkTypes.length === 1 ? linkTypes[0] : placeholder;
			const data = {
				linkTypeId: typeId,
				sourceId: source.iri,
				targetId: target.iri
			};
			let [sourceId, targetId] = [source.id, target.id];
			if (direction === LinkDirection.in) {
				data.sourceId = target.iri;
				data.targetId = source.iri;
				[sourceId, targetId] = [targetId, sourceId];
			}
			const link = new Link({
				typeId,
				sourceId,
				targetId,
				data
			});
			return editor.model.findLink(link.typeId, link.sourceId, link.targetId) || editor.createNewLink({
				link,
				temporary: true
			});
		}
		cleanupAndFinish() {
			const { editor, onFinishEditing } = this.props;
			const batch = editor.model.history.startBatch();
			editor.model.removeElement(this.temporaryElement.id);
			editor.model.removeLink(this.temporaryLink.id);
			editor.setTemporaryState(TemporaryState.deleteLink(editor.temporaryState, this.temporaryLink.data));
			batch.discard();
			onFinishEditing();
		}
		render() {
			const { view, paperTransform } = this.props;
			const { waitingForMetadata } = this.state;
			if (!this.temporaryLink) return null;
			return /* @__PURE__ */ react.createElement(TransformedSvgCanvas, {
				paperTransform,
				style: { overflow: "visible" }
			}, /* @__PURE__ */ react.createElement(LinkMarkers, { view }), this.renderHighlight(), this.renderCanDropIndicator(), waitingForMetadata ? null : /* @__PURE__ */ react.createElement(LinkLayer, {
				view,
				links: [this.temporaryLink]
			}));
		}
		renderHighlight() {
			const { targetElement, canLinkFrom, canDropOnElement, waitingForMetadata } = this.state;
			if (!targetElement) return null;
			const { x, y, width, height } = boundsOf(targetElement);
			if (canLinkFrom === void 0 || canDropOnElement === void 0 || waitingForMetadata) return /* @__PURE__ */ react.createElement("g", { transform: `translate(${x},${y})` }, /* @__PURE__ */ react.createElement("rect", {
				width,
				height,
				fill: "white",
				fillOpacity: .5
			}), /* @__PURE__ */ react.createElement(Spinner, {
				size: 30,
				position: {
					x: width / 2,
					y: height / 2
				}
			}));
			const stroke = canLinkFrom && canDropOnElement ? "#5cb85c" : "#c9302c";
			return /* @__PURE__ */ react.createElement("rect", {
				x,
				y,
				width,
				height,
				fill: "transparent",
				stroke,
				strokeWidth: 3
			});
		}
		renderCanDropIndicator() {
			const { targetElement, canLinkFrom, canDropOnCanvas, waitingForMetadata } = this.state;
			if (targetElement) return null;
			const { x, y } = this.temporaryElement.position;
			let indicator;
			if (canLinkFrom === void 0 || canDropOnCanvas === void 0) indicator = /* @__PURE__ */ react.createElement(Spinner, {
				size: 1.2,
				position: {
					x: .5,
					y: -.5
				}
			});
			else if (canLinkFrom && canDropOnCanvas) indicator = /* @__PURE__ */ react.createElement("path", {
				d: "M0.5,0 L0.5,-1 M0,-0.5 L1,-0.5",
				strokeWidth: .2,
				stroke: "#5cb85c"
			});
			else indicator = /* @__PURE__ */ react.createElement("g", null, /* @__PURE__ */ react.createElement("circle", {
				cx: "0.5",
				cy: "-0.5",
				r: "0.5",
				fill: "none",
				strokeWidth: .2,
				stroke: "#c9302c"
			}), /* @__PURE__ */ react.createElement("path", {
				d: "M0.5,0 L0.5,-1",
				strokeWidth: .2,
				stroke: "#c9302c",
				transform: "rotate(-45 0.5 -0.5)"
			}));
			return /* @__PURE__ */ react.createElement("g", { transform: `translate(${x} ${y})scale(40)` }, /* @__PURE__ */ react.createElement("rect", {
				x: -.5,
				y: -.5,
				width: 1,
				height: 1,
				fill: "rgba(0, 0, 0, 0.1)",
				rx: .25,
				ry: .25
			}), waitingForMetadata ? /* @__PURE__ */ react.createElement(Spinner, { size: .8 }) : /* @__PURE__ */ react.createElement("g", { transform: `translate(0.5, -0.5)scale(0.25)` }, indicator));
		}
	};
	function centerElementAtPoint(element, point) {
		element.setPosition({
			x: point.x - element.size.width / 2,
			y: point.y - element.size.height / 2
		});
	}
	//#endregion
	//#region src/graph-explorer/editor/validation.ts
	var empty = createMutable();
	var emptyElement = {
		loading: false,
		errors: []
	};
	var emptyLink = {
		loading: false,
		errors: []
	};
	function createMutable() {
		return {
			elements: /* @__PURE__ */ new Map(),
			links: new HashMap(hashLink, sameLink)
		};
	}
	function setElementErrors(state, target, errors) {
		const elements = cloneMap(state.elements);
		if (errors.length > 0) elements.set(target, {
			loading: false,
			errors
		});
		else elements.delete(target);
		return {
			...state,
			elements
		};
	}
	function setLinkErrors(state, target, errors) {
		const links = state.links.clone();
		if (errors.length > 0) links.set(target, {
			loading: false,
			errors
		});
		else links.delete(target);
		return {
			...state,
			links
		};
	}
	var ValidationState = {
		empty,
		emptyElement,
		emptyLink,
		createMutable,
		setElementErrors,
		setLinkErrors
	};
	function changedElementsToValidate(previousAuthoring, editor) {
		const currentAuthoring = editor.authoringState;
		const links = new HashMap(hashLink, sameLink);
		previousAuthoring.links.forEach((e, model) => links.set(model, true));
		currentAuthoring.links.forEach((e, model) => links.set(model, true));
		const toValidate = /* @__PURE__ */ new Set();
		links.forEach((value, linkModel) => {
			if (currentAuthoring.links.get(linkModel) !== previousAuthoring.links.get(linkModel)) toValidate.add(linkModel.sourceId);
		});
		for (const element of editor.model.elements) {
			const current = currentAuthoring.elements.get(element.iri);
			const previous = previousAuthoring.elements.get(element.iri);
			if (current !== previous) {
				toValidate.add(element.iri);
				if ((current || previous).deleted) {
					for (const link of element.links) if (link.data.sourceId !== element.iri) toValidate.add(link.data.sourceId);
				}
			}
		}
		return toValidate;
	}
	function validateElements(targets, validationApi, editor, cancellationToken) {
		const previousState = editor.validationState;
		const newState = ValidationState.createMutable();
		for (const element of editor.model.elements) {
			if (newState.elements.has(element.iri)) continue;
			const outboundLinks = element.links.reduce((acc, link) => {
				if (link.sourceId === element.id) acc.push(link.data);
				return acc;
			}, []);
			if (targets.has(element.iri)) {
				const event = {
					target: element.data,
					outboundLinks,
					state: editor.authoringState,
					model: editor.model,
					cancellation: cancellationToken
				};
				const result = CancellationToken.mapCancelledToNull(cancellationToken, validationApi.validate(event));
				const loadingElement = {
					loading: true,
					errors: []
				};
				const loadingLink = {
					loading: true,
					errors: []
				};
				newState.elements.set(element.iri, loadingElement);
				outboundLinks.forEach((link) => newState.links.set(link, loadingLink));
				processValidationResult(result, loadingElement, loadingLink, event, editor);
			} else {
				newState.elements.set(element.iri, previousState.elements.get(element.iri));
				for (const link of outboundLinks) newState.links.set(link, previousState.links.get(link));
			}
		}
		editor.setValidationState(newState);
	}
	async function processValidationResult(result, previousElement, previousLink, e, editor) {
		let allErrors;
		try {
			allErrors = await result;
			if (allErrors === null) return;
		} catch (err) {
			console.error(`Failed to validate element`, e.target, err);
			allErrors = [{
				type: "element",
				target: e.target.id,
				message: `Failed to validate element`
			}];
		}
		const elementErrors = [];
		const linkErrors = new HashMap(hashLink, sameLink);
		e.outboundLinks.forEach((link) => linkErrors.set(link, []));
		for (const error of allErrors) if (error.type === "element" && error.target === e.target.id) elementErrors.push(error);
		else if (error.type === "link" && linkErrors.has(error.target)) linkErrors.get(error.target).push(error);
		let state = editor.validationState;
		if (state.elements.get(e.target.id) === previousElement) state = ValidationState.setElementErrors(state, e.target.id, elementErrors);
		linkErrors.forEach((errors, link) => {
			if (state.links.get(link) === previousLink) state = ValidationState.setLinkErrors(state, link, errors);
		});
		editor.setValidationState(state);
	}
	//#endregion
	//#region src/graph-explorer/editor/editorController.tsx
	var EditorController = class {
		constructor(props) {
			this.listener = new EventObserver();
			this.source = new EventSource();
			this.events = this.source;
			this._authoringState = AuthoringState.empty;
			this._validationState = ValidationState.empty;
			this._temporaryState = TemporaryState.empty;
			this._selection = [];
			this.cancellation = new Cancellation();
			this.onKeyUp = (e) => {
				if (e.keyCode === 46 && document.activeElement.localName !== "input") this.removeSelectedElements();
			};
			const { model, view, ...options } = props;
			this.model = model;
			this.view = view;
			this.options = options;
			this.listener.listen(this.events, "changeValidationState", (e) => {
				for (const element of this.model.elements) {
					const previous = e.previous.elements.get(element.iri);
					if (this.validationState.elements.get(element.iri) !== previous) element.redraw();
				}
			});
			this.listener.listen(this.events, "changeAuthoringState", (e) => {
				if (this.options.validationApi) validateElements(changedElementsToValidate(e.previous, this), this.options.validationApi, this, this.cancellation.signal);
			});
			this.view._setElementDecorator((element) => /* @__PURE__ */ react.createElement(ElementDecorator, {
				model: element,
				view: this.view,
				editor: this,
				position: element.position
			}));
		}
		_initializePaperComponents(paperArea) {
			this.listener.listen(paperArea.events, "pointerUp", (e) => this.onPaperPointerUp(e));
			this.listener.listen(this.model.events, "changeCells", () => this.onCellsChanged());
			this.listener.listen(this.model.events, "elementEvent", (e) => {
				if (e.key === "requestedGroupContent") this.loadGroupContent(e.data.requestedGroupContent.source);
			});
			this.listener.listen(this.model.events, "loadingStart", () => this.setSpinner({}));
			this.listener.listen(this.model.events, "loadingSuccess", () => {
				this.setSpinner(void 0);
				const widget = /* @__PURE__ */ react.createElement(LinkStateWidget, {
					view: this.view,
					editor: this
				});
				this.view.setPaperWidget({
					key: "states",
					widget,
					attachment: WidgetAttachment.OverLinks
				});
			});
			this.listener.listen(this.model.events, "loadingError", ({ error }) => {
				const statusText = error ? error.message : void 0;
				this.setSpinner({
					statusText,
					errorOccured: true
				});
			});
			if (!this.options.disableHalo) {
				this.configureHalo();
				document.addEventListener("keyup", this.onKeyUp);
				this.listener.listen(this.view.events, "dispose", () => {
					document.removeEventListener("keyup", this.onKeyUp);
				});
			}
		}
		get inAuthoringMode() {
			return Boolean(this._metadataApi);
		}
		get metadataApi() {
			return this._metadataApi;
		}
		setMetadataApi(value) {
			const previous = this._metadataApi;
			if (value === previous) return;
			this._metadataApi = value;
			if (Boolean(value) !== Boolean(previous)) this.source.trigger("changeMode", { source: this });
		}
		get authoringState() {
			return this._authoringState;
		}
		setAuthoringState(value) {
			if (this._authoringState === value) return;
			this.model.history.execute(this.updateAuthoringState(value));
		}
		updateAuthoringState(state) {
			const previous = this._authoringState;
			return Command.create("Create or delete entities and links", () => {
				this._authoringState = state;
				this.source.trigger("changeAuthoringState", {
					source: this,
					previous
				});
				return this.updateAuthoringState(previous);
			});
		}
		get validationState() {
			return this._validationState;
		}
		setValidationState(value) {
			const previous = this._validationState;
			if (value === previous) return;
			this._validationState = value;
			this.source.trigger("changeValidationState", {
				source: this,
				previous
			});
		}
		get temporaryState() {
			return this._temporaryState;
		}
		setTemporaryState(value) {
			const previous = this._temporaryState;
			if (value === previous) return;
			this._temporaryState = value;
			this.source.trigger("changeTemporaryState", {
				source: this,
				previous
			});
		}
		get selection() {
			return this._selection;
		}
		setSelection(value) {
			const previous = this._selection;
			if (previous === value) return;
			this._selection = value;
			this.source.trigger("changeSelection", {
				source: this,
				previous
			});
		}
		cancelSelection() {
			this.setSelection([]);
		}
		removeSelectedElements() {
			const itemsToRemove = this.selection;
			if (itemsToRemove.length === 0) return;
			this.cancelSelection();
			this.removeItems(itemsToRemove);
		}
		removeItems(items) {
			const batch = this.model.history.startBatch();
			const deletedElementIris = /* @__PURE__ */ new Set();
			for (const item of items) if (item instanceof Element$1) {
				const event = this.authoringState.elements.get(item.iri);
				if (event) this.discardChange(event);
				this.model.removeElement(item.id);
				deletedElementIris.add(item.iri);
			} else if (item instanceof Link) {
				if (AuthoringState.isNewLink(this.authoringState, item.data)) this.deleteLink(item.data);
			}
			if (deletedElementIris.size > 0) {
				const newState = AuthoringState.deleteNewLinksConnectedToElements(this.authoringState, deletedElementIris);
				this.setAuthoringState(newState);
			}
			batch.store();
		}
		onPaperPointerUp(event) {
			if (this.options.disableHalo) return;
			const { sourceEvent, target, triggerAsClick } = event;
			if (sourceEvent.ctrlKey || sourceEvent.shiftKey || sourceEvent.metaKey) return;
			if (this.dialogTarget && this.dialogType === 1) return;
			if (target instanceof Element$1) {
				this.setSelection([target]);
				target.focus();
			} else if (target instanceof Link) this.setSelection([target]);
			else if (target instanceof LinkVertex) this.setSelection([target.link]);
			else if (!target && triggerAsClick) {
				this.setSelection([]);
				this.hideDialog();
				if (document.activeElement) document.activeElement.blur();
			}
		}
		onCellsChanged() {
			if (this.selection.length === 0) return;
			const newSelection = this.selection.filter((item) => item instanceof Element$1 ? this.model.getElement(item.id) : item instanceof Link ? this.model.getLinkById(item.id) : false);
			if (newSelection.length < this.selection.length) this.setSelection(newSelection);
		}
		setSpinner(props) {
			const widget = props ? /* @__PURE__ */ react.createElement(LoadingWidget, { spinnerProps: props }) : void 0;
			this.view.setPaperWidget({
				key: LoadingWidget.Key,
				widget,
				attachment: WidgetAttachment.Viewport
			});
		}
		configureHalo() {
			if (this.options.disableHalo) return;
			this.listener.listen(this.events, "changeSelection", () => {
				const selected = this.selection.length === 1 ? this.selection[0] : void 0;
				if (this.dialogTarget && selected !== this.dialogTarget) this.hideDialog();
				this.bringSelectedElementsToFront();
				this.renderDefaultHalo();
			});
			this.listener.listen(this.events, "toggleDialog", ({ isOpened: _isOpened }) => {
				this.renderDefaultHalo();
			});
			this.renderDefaultHalo();
		}
		bringSelectedElementsToFront() {
			if (this.selection.length === 0) return;
			this.model.reorderElements(makeMoveComparator(this.model.elements, this.selection.filter((item) => item instanceof Element$1), MoveDirection.ToEnd));
		}
		renderDefaultHalo() {
			const selected = this.selection.length === 1 ? this.selection[0] : void 0;
			let halo;
			if (selected instanceof Element$1) halo = /* @__PURE__ */ react.createElement(Halo, {
				editor: this,
				metadataApi: this.metadataApi,
				target: selected,
				onRemove: () => this.removeSelectedElements(),
				onExpand: () => {
					this.model.history.execute(setElementExpanded(selected, !selected.isExpanded));
				},
				navigationMenuOpened: this.dialogType === 0,
				onToggleNavigationMenu: () => {
					if (this.dialogTarget && this.dialogType === 0) this.hideDialog();
					else this.showConnectionsMenu(selected);
					this.renderDefaultHalo();
				},
				onAddToFilter: () => selected.addToFilter(),
				onEstablishNewLink: (point) => this.startEditing({
					target: selected,
					mode: EditLayerMode.establishLink,
					point
				}),
				onFollowLink: (element, e) => this.view.onIriClick(element.iri, element, IriClickIntent.JumpToEntity, e)
			});
			else if (selected instanceof Link) halo = /* @__PURE__ */ react.createElement(HaloLink, {
				view: this.view,
				editor: this,
				metadataApi: this.metadataApi,
				target: selected,
				onEdit: () => this.showEditLinkForm(selected),
				onDelete: () => this.deleteLink(selected.data),
				onSourceMove: (point) => this.startEditing({
					target: selected,
					mode: EditLayerMode.moveLinkSource,
					point
				}),
				onTargetMove: (point) => this.startEditing({
					target: selected,
					mode: EditLayerMode.moveLinkTarget,
					point
				}),
				onEditLabel: () => this.showEditLinkLabelForm(selected)
			});
			this.view.setPaperWidget({
				key: "halo",
				widget: halo,
				attachment: WidgetAttachment.OverElements
			});
		}
		showConnectionsMenu(target) {
			const dialogType = 0;
			const onClose = () => this.hideDialog();
			const content = /* @__PURE__ */ react.createElement(ConnectionsMenu, {
				view: this.view,
				editor: this,
				target,
				onAddElements: (iris, linkType) => this.onAddElementsInConnectionMenu(iris, target, linkType),
				onClose,
				suggestProperties: this.options.suggestProperties
			});
			this.showDialog({
				target,
				dialogType,
				content,
				onClose
			});
		}
		showEditEntityForm(target) {
			const { propertyEditor } = this.options;
			const dialogType = 1;
			const onSubmit = (newData) => {
				this.hideDialog();
				this.changeEntityData(target.data.id, newData);
			};
			const isIriModified = AuthoringState.isElementWithModifiedIri(this.authoringState, target.data.id);
			let modelToEdit;
			if (isIriModified) {
				const relatedEvent = this.authoringState.elements.get(target.data.id);
				modelToEdit = {
					...target.data,
					id: relatedEvent.newIri
				};
			} else modelToEdit = target.data;
			const onCancel = () => this.hideDialog();
			const content = propertyEditor ? propertyEditor({
				elementData: target.data,
				onSubmit,
				onCancel
			}) : /* @__PURE__ */ react.createElement(EditEntityForm, {
				view: this.view,
				entity: modelToEdit,
				onApply: onSubmit,
				onCancel
			});
			this.showDialog({
				target,
				dialogType,
				content,
				onClose: onCancel
			});
		}
		showEditElementTypeForm({ link, source, target, targetIsNew }) {
			const dialogType = 3;
			const onCancel = () => {
				this.removeTemporaryElement(target);
				this.removeTemporaryLink(link);
				this.hideDialog();
			};
			const content = /* @__PURE__ */ react.createElement(EditElementTypeForm, {
				editor: this,
				view: this.view,
				metadataApi: this.metadataApi,
				link: link.data,
				source: source.data,
				target: {
					value: target.data,
					isNew: targetIsNew
				},
				onChangeElement: (data) => {
					const previous = target.data;
					this.setTemporaryState(TemporaryState.deleteElement(this.temporaryState, previous));
					target.setData(data);
					this.setTemporaryState(TemporaryState.addElement(this.temporaryState, data));
				},
				onChangeLink: (data) => {
					this.removeTemporaryLink(link);
					const newLink = makeLinkWithDirection(new Link({
						typeId: data.linkTypeId,
						sourceId: source.id,
						targetId: target.id,
						data: {
							...data,
							sourceId: source.iri,
							targetId: target.iri
						}
					}), data);
					link = this.createNewLink({
						link: newLink,
						temporary: true
					});
				},
				onApply: (elementData, isNewElement, linkData) => {
					this.removeTemporaryElement(target);
					this.removeTemporaryLink(link);
					const batch = this.model.history.startBatch(isNewElement ? "Create new entity" : "Link to entity");
					this.model.addElement(target);
					if (isNewElement) {
						target.setExpanded(true);
						this.setAuthoringState(AuthoringState.addElement(this._authoringState, target.data));
					} else this.model.requestLinksOfType();
					const newLink = makeLinkWithDirection(new Link({
						typeId: link.typeId,
						sourceId: source.id,
						targetId: target.id,
						data: {
							...link.data,
							sourceId: source.iri,
							targetId: target.iri
						}
					}), linkData);
					this.createNewLink({ link: newLink });
					batch.store();
					this.hideDialog();
					if (isNewElement) this.showEditEntityForm(target);
				},
				onCancel
			});
			this.showDialog({
				target,
				dialogType,
				content,
				caption: "Establish New Connection",
				onClose: onCancel
			});
		}
		showEditLinkForm(link) {
			const dialogType = 2;
			const source = this.model.getElement(link.sourceId).data;
			const target = this.model.getElement(link.targetId).data;
			const onCancel = () => {
				if (this.temporaryState.links.has(link.data)) this.removeTemporaryLink(link);
				this.hideDialog();
			};
			const content = /* @__PURE__ */ react.createElement(EditLinkForm, {
				editor: this,
				view: this.view,
				metadataApi: this.metadataApi,
				link: link.data,
				source,
				target,
				onChange: (data) => {
					if (this.temporaryState.links.has(link.data)) {
						this.removeTemporaryLink(link);
						const newLink = makeLinkWithDirection(link, data);
						this.showEditLinkForm(this.createNewLink({
							link: newLink,
							temporary: true
						}));
					}
				},
				onApply: (data) => {
					if (this.temporaryState.links.has(link.data)) {
						this.removeTemporaryLink(link);
						const newLink = makeLinkWithDirection(link, data);
						this.createNewLink({ link: newLink });
					} else this.changeLink(link.data, data);
					this.hideDialog();
				},
				onCancel
			});
			const caption = this.temporaryState.links.has(link.data) ? "Establish New Connection" : "Edit Connection";
			this.showDialog({
				target: link,
				dialogType,
				content,
				size: {
					width: 300,
					height: 160
				},
				caption,
				onClose: onCancel
			});
		}
		showEditLinkLabelForm(link) {
			const linkType = this.view.model.getLinkType(link.typeId);
			const template = this.view.createLinkTemplate(linkType);
			const size = {
				width: 300,
				height: 145
			};
			const onCancel = () => this.hideDialog();
			this.showDialog({
				target: link,
				dialogType: 4,
				content: /* @__PURE__ */ react.createElement(EditLinkLabelForm, {
					view: this.view,
					link,
					onApply: (label) => {
						template.setLinkLabel(link, label);
						this.hideDialog();
					},
					onCancel
				}),
				size,
				caption: "Edit Link Label",
				offset: {
					x: 25,
					y: -size.height / 2
				},
				calculatePosition: () => {
					const { x, y, width, height } = link.labelBounds;
					return {
						x: x + width,
						y: y + height / 2
					};
				},
				onClose: onCancel
			});
		}
		showDialog(params) {
			const { target, dialogType, content, size, caption, offset, calculatePosition, onClose } = params;
			this.dialogTarget = target;
			this.dialogType = dialogType;
			const dialog = /* @__PURE__ */ react.createElement(Dialog, {
				view: this.view,
				target,
				size,
				caption,
				offset,
				calculatePosition,
				onClose
			}, content);
			this.view.setPaperWidget({
				key: "dialog",
				widget: dialog,
				attachment: WidgetAttachment.OverElements
			});
			this.source.trigger("toggleDialog", { isOpened: true });
		}
		hideDialog() {
			if (this.dialogTarget) {
				const isTemporaryElement = this.dialogTarget instanceof Element$1 && this.temporaryState.elements.has(this.dialogTarget.iri);
				const isTemporaryLink = this.dialogTarget instanceof Link && this.temporaryState.links.has(this.dialogTarget.data);
				if (isTemporaryElement || isTemporaryLink) this.resetTemporaryState();
				this.dialogType = void 0;
				this.dialogTarget = void 0;
				this.view.setPaperWidget({
					key: "dialog",
					widget: void 0,
					attachment: WidgetAttachment.OverElements
				});
				this.source.trigger("toggleDialog", { isOpened: false });
			}
		}
		onDragDrop(dragged, paperPosition) {
			const batch = this.model.history.startBatch("Drag and drop onto diagram");
			const placedElements = placeElements(this.view, dragged, paperPosition);
			const irisToLoad = placedElements.map((elem) => elem.iri);
			batch.history.execute(requestElementData(this.model, irisToLoad));
			batch.history.execute(restoreLinksBetweenElements(this.model));
			batch.store();
			if (placedElements.length > 0) placedElements[placedElements.length - 1].focus();
			this.setSelection(placedElements);
			this.source.trigger("addElements", { elements: placedElements });
		}
		onAddElementsInConnectionMenu(elementIris, targetElement, linkType) {
			const batch = this.view.model.history.startBatch();
			const elements = elementIris.map((iri) => this.model.createElement(iri));
			this.view.performSyncUpdate();
			placeElementsAround({
				model: this.model,
				elements,
				targetElement,
				prefferedLinksLength: 300
			}).then(() => {
				this.source.trigger("addElements", { elements });
			});
			if (linkType && !linkType.visible) batch.history.execute(changeLinkTypeVisibility({
				linkType,
				visible: true,
				showLabel: true,
				preventLoading: true
			}));
			batch.history.execute(requestElementData(this.model, elementIris));
			batch.history.execute(restoreLinksBetweenElements(this.model));
			batch.store();
		}
		loadGroupContent(element) {
			return this.model.loadEmbeddedElements(element.iri).then((models) => {
				const batch = this.model.history.startBatch();
				const elementIris = Object.keys(models);
				elementIris.map((key) => this.model.createElement(models[key], element.id));
				batch.discard();
				return Promise.all([this.model.requestElementData(elementIris), this.model.requestLinksOfType()]).then(() => {
					this.view.performSyncUpdate();
					applyLayout(this.model, forceLayout({
						model: this.model,
						group: element.id
					}));
					this.model.triggerChangeGroupContent(element.id);
				});
			});
		}
		createNewEntity({ elementModel, temporary }) {
			const batch = this.model.history.startBatch("Create new entity");
			const element = this.model.createElement(elementModel);
			element.setExpanded(true);
			if (temporary) {
				this.setTemporaryState(TemporaryState.addElement(this.temporaryState, element.data));
				batch.discard();
			} else {
				this.setAuthoringState(AuthoringState.addElement(this._authoringState, element.data));
				batch.store();
			}
			return element;
		}
		changeEntityData(targetIri, newData) {
			const elements = this.model.elements.filter((el) => el.iri === targetIri);
			if (elements.length === 0) return;
			const oldData = elements[0].data;
			const batch = this.model.history.startBatch("Edit entity");
			const newState = AuthoringState.changeElement(this._authoringState, oldData, newData);
			const event = newState.elements.get(targetIri) || newState.elements.get(newData.id);
			this.model.history.execute(setElementData(this.model, targetIri, event.after));
			this.setAuthoringState(newState);
			batch.store();
		}
		deleteEntity(elementIri) {
			const state = this.authoringState;
			const elements = this.model.elements.filter((el) => el.iri === elementIri);
			if (elements.length === 0) return;
			const batch = this.model.history.startBatch("Delete entity");
			const model = elements[0].data;
			const event = state.elements.get(elementIri);
			const linksToRemove = /* @__PURE__ */ new Set();
			for (const element of elements) for (const link of element.links) if (link.data && AuthoringState.isNewLink(state, link.data)) linksToRemove.add(link.id);
			linksToRemove.forEach((linkId) => this.model.removeLink(linkId));
			if (event) this.discardChange(event);
			this.setAuthoringState(AuthoringState.deleteElement(state, model));
			batch.store();
		}
		createNewLink(params) {
			const { link: base, temporary } = params;
			if (this.model.findLink(base.typeId, base.sourceId, base.targetId)) throw Error("The link already exists");
			const batch = this.model.history.startBatch("Create new link");
			const addedLink = this.model.addLink(base);
			if (!temporary) this.model.createLinks(base.data);
			if (this.model.links.filter((link) => sameLink(link.data, base.data)).length > 0) if (temporary) {
				this.setTemporaryState(TemporaryState.addLink(this.temporaryState, base.data));
				batch.discard();
			} else {
				this.setAuthoringState(AuthoringState.addLink(this._authoringState, base.data));
				batch.store();
			}
			else batch.discard();
			return addedLink;
		}
		changeLink(oldData, newData) {
			const batch = this.model.history.startBatch("Change link");
			if (sameLink(oldData, newData)) {
				this.model.history.execute(setLinkData(this.model, oldData, newData));
				this.setAuthoringState(AuthoringState.changeLink(this._authoringState, oldData, newData));
			} else {
				let newState = this._authoringState;
				newState = AuthoringState.deleteLink(newState, oldData);
				newState = AuthoringState.addLink(newState, newData);
				if (AuthoringState.isNewLink(this._authoringState, oldData)) this.model.links.filter((link) => sameLink(link.data, oldData)).forEach((link) => this.model.removeLink(link.id));
				this.model.createLinks(newData);
				this.setAuthoringState(newState);
			}
			batch.store();
		}
		moveLinkSource(params) {
			const { link, newSource } = params;
			const batch = this.model.history.startBatch("Move link to another element");
			this.changeLink(link.data, {
				...link.data,
				sourceId: newSource.iri
			});
			const newLink = this.model.findLink(link.typeId, newSource.id, link.targetId);
			newLink.setVertices(link.vertices);
			batch.store();
			return newLink;
		}
		moveLinkTarget(params) {
			const { link, newTarget } = params;
			const batch = this.model.history.startBatch("Move link to another element");
			this.changeLink(link.data, {
				...link.data,
				targetId: newTarget.iri
			});
			const newLink = this.model.findLink(link.typeId, link.sourceId, newTarget.id);
			newLink.setVertices(link.vertices);
			batch.store();
			return newLink;
		}
		deleteLink(model) {
			const state = this.authoringState;
			if (AuthoringState.isDeletedLink(state, model)) return;
			const batch = this.model.history.startBatch("Delete link");
			const newState = AuthoringState.deleteLink(state, model);
			if (AuthoringState.isNewLink(state, model)) this.model.links.filter(({ data }) => sameLink(data, model)).forEach((link) => this.model.removeLink(link.id));
			this.setAuthoringState(newState);
			batch.store();
		}
		startEditing(params) {
			const { target, mode, point } = params;
			const onFinishEditing = () => {
				this.view.setPaperWidget({
					key: "editLayer",
					widget: void 0,
					attachment: WidgetAttachment.OverElements
				});
			};
			const editLayer = /* @__PURE__ */ react.createElement(EditLayer, {
				view: this.view,
				editor: this,
				metadataApi: this.metadataApi,
				mode,
				target,
				point,
				onFinishEditing
			});
			this.view.setPaperWidget({
				key: "editLayer",
				widget: editLayer,
				attachment: WidgetAttachment.OverElements
			});
		}
		resetTemporaryState() {
			if (this.temporaryState.elements.size) this.model.elements.forEach((element) => {
				if (this.temporaryState.elements.has(element.iri)) this.removeTemporaryElement(element);
			});
			if (this.temporaryState.links.size) this.model.links.forEach((link) => {
				if (this.temporaryState.links.get(link.data)) this.removeTemporaryLink(link);
			});
		}
		removeTemporaryElement(element) {
			const batch = this.model.history.startBatch();
			this.model.removeElement(element.id);
			batch.discard();
			this.setTemporaryState(TemporaryState.deleteElement(this.temporaryState, element.data));
		}
		removeTemporaryLink(link) {
			this.model.removeLink(link.id);
			this.setTemporaryState(TemporaryState.deleteLink(this.temporaryState, link.data));
		}
		discardChange(event) {
			const newState = AuthoringState.discard(this._authoringState, event);
			if (newState === this._authoringState) return;
			const batch = this.model.history.startBatch("Discard change");
			if (event.type === AuthoringKind.ChangeElement) if (event.deleted) {} else if (event.before) this.model.history.execute(setElementData(this.model, event.after.id, event.before));
			else this.model.elements.filter((el) => el.iri === event.after.id).forEach((el) => this.model.removeElement(el.id));
			else if (event.type === AuthoringKind.ChangeLink) if (event.deleted) {} else if (event.before) this.model.history.execute(setLinkData(this.model, event.after, event.before));
			else this.model.links.filter(({ data }) => sameLink(data, event.after)).forEach((link) => this.model.removeLink(link.id));
			this.setAuthoringState(newState);
			batch.store();
		}
	};
	var LoadingWidget = class extends react.Component {
		static {
			this.Key = "loadingWidget";
		}
		render() {
			const { spinnerProps, paperArea } = this.props;
			const areaMetrics = paperArea.getAreaMetrics();
			const paneWidth = areaMetrics.clientWidth;
			const paneHeight = areaMetrics.clientHeight;
			const position = {
				x: spinnerProps.statusText ? paneWidth / 3 : paneWidth / 2,
				y: paneHeight / 2
			};
			return /* @__PURE__ */ react.createElement("div", { className: "graph-explorer-loading-widget" }, /* @__PURE__ */ react.createElement("svg", {
				width: paneWidth,
				height: paneHeight
			}, /* @__PURE__ */ react.createElement(Spinner, {
				position,
				...spinnerProps
			})));
		}
	};
	function placeElements(view, dragged, position) {
		const elements = dragged.map((item) => view.model.createElement(item));
		for (const element of elements) element.setPosition(position);
		view.performSyncUpdate();
		let { x, y } = position;
		let isFirst = true;
		for (const element of elements) {
			let { width, height } = boundsOf(element);
			if (width === 0) width = 100;
			if (height === 0) height = 50;
			if (isFirst) {
				isFirst = false;
				x -= width / 2;
				y -= height / 2;
			}
			element.setPosition({
				x,
				y
			});
			y += height + 20;
		}
		return elements;
	}
	function makeLinkWithDirection(original, data) {
		if (!(data.sourceId === original.data.sourceId || data.sourceId === original.data.targetId)) throw new Error("New link source IRI is unrelated to original link");
		if (!(data.targetId === original.data.sourceId || data.targetId === original.data.targetId)) throw new Error("New link target IRI is unrelated to original link");
		const sourceId = data.sourceId === original.data.sourceId ? original.sourceId : original.targetId;
		const targetId = data.targetId === original.data.targetId ? original.targetId : original.sourceId;
		return new Link({
			typeId: data.linkTypeId,
			sourceId,
			targetId,
			data
		});
	}
	//#endregion
	//#region src/graph-explorer/workspace/toolbar.tsx
	var CLASS_NAME$4 = "graph-explorer-toolbar";
	var CLEAR_ALL_ARM_TIMEOUT = 4e3;
	var DefaultToolbar = class extends react.Component {
		constructor(..._args) {
			super(..._args);
			this.state = {};
			this.onClearAllClick = () => {
				if (this.state.clearAllArmed) {
					this.clearClearAllTimeout();
					this.setState({ clearAllArmed: false });
					this.props.onClearAll();
				} else {
					this.clearClearAllTimeout();
					this.clearAllTimeout = setTimeout(() => {
						this.setState({ clearAllArmed: false });
					}, CLEAR_ALL_ARM_TIMEOUT);
					this.setState({ clearAllArmed: true });
				}
			};
			this.onChangeLanguage = (event) => {
				const value = event.currentTarget.value;
				this.props.onChangeLanguage(value);
			};
			this.onExportSVG = () => {
				this.props.onExportSVG();
			};
			this.onExportPNG = () => {
				this.props.onExportPNG();
			};
		}
		componentWillUnmount() {
			this.clearClearAllTimeout();
		}
		clearClearAllTimeout() {
			if (this.clearAllTimeout !== void 0) {
				clearTimeout(this.clearAllTimeout);
				this.clearAllTimeout = void 0;
			}
		}
		renderSaveDiagramButton() {
			if (!this.props.onSaveDiagram) return null;
			return /* @__PURE__ */ react.createElement("button", {
				type: "button",
				className: "saveDiagramButton graph-explorer-btn graph-explorer-btn-primary",
				disabled: this.props.canSaveDiagram === false,
				onClick: this.props.onSaveDiagram
			}, /* @__PURE__ */ react.createElement("span", {
				className: "fa fa-floppy-o",
				"aria-hidden": "true"
			}), " Save diagram");
		}
		renderPersistAuthoredChangesButton() {
			if (!this.props.onPersistChanges) return null;
			return /* @__PURE__ */ react.createElement("button", {
				type: "button",
				className: "saveDiagramButton graph-explorer-btn graph-explorer-btn-success",
				disabled: this.props.canPersistChanges === false,
				onClick: this.props.onPersistChanges
			}, /* @__PURE__ */ react.createElement("span", {
				className: "fa fa-floppy-o",
				"aria-hidden": "true"
			}), " Save data");
		}
		renderLanguages() {
			const { selectedLanguage, languages } = this.props;
			if (languages.length <= 1) return null;
			return /* @__PURE__ */ react.createElement("span", { className: `graph-explorer-btn-group ${CLASS_NAME$4}__language-selector` }, /* @__PURE__ */ react.createElement("label", { className: "graph-explorer-label" }, /* @__PURE__ */ react.createElement("span", null, "Data Language")), /* @__PURE__ */ react.createElement("select", {
				value: selectedLanguage,
				onChange: this.onChangeLanguage
			}, languages.map(({ code, label }) => /* @__PURE__ */ react.createElement("option", {
				key: code,
				value: code
			}, label))));
		}
		render() {
			return /* @__PURE__ */ react.createElement("div", { className: CLASS_NAME$4 }, /* @__PURE__ */ react.createElement("div", { className: "graph-explorer-btn-group graph-explorer-btn-group-sm" }, this.renderSaveDiagramButton(), this.renderPersistAuthoredChangesButton(), this.props.onClearAll ? /* @__PURE__ */ react.createElement("button", {
				type: "button",
				className: this.state.clearAllArmed ? "graph-explorer-btn graph-explorer-btn-danger" : "graph-explorer-btn graph-explorer-btn-default",
				title: this.state.clearAllArmed ? "Click again to confirm" : "Clear All",
				onClick: this.onClearAllClick,
				onBlur: () => this.setState({ clearAllArmed: false })
			}, /* @__PURE__ */ react.createElement("span", {
				className: "fa fa-trash",
				"aria-hidden": "true"
			}), "\xA0", this.state.clearAllArmed ? "Are you sure?" : "Clear All") : null, /* @__PURE__ */ react.createElement("button", {
				type: "button",
				className: "graph-explorer-btn graph-explorer-btn-default",
				title: "Force layout",
				onClick: this.props.onForceLayout
			}, /* @__PURE__ */ react.createElement("span", {
				className: "fa fa-sitemap",
				"aria-hidden": "true"
			}), " Layout"), /* @__PURE__ */ react.createElement("button", {
				type: "button",
				className: "graph-explorer-btn graph-explorer-btn-default",
				title: "Zoom In",
				onClick: this.props.onZoomIn
			}, /* @__PURE__ */ react.createElement("span", {
				className: "fa fa-search-plus",
				"aria-hidden": "true"
			})), /* @__PURE__ */ react.createElement("button", {
				type: "button",
				className: "graph-explorer-btn graph-explorer-btn-default",
				title: "Zoom Out",
				onClick: this.props.onZoomOut
			}, /* @__PURE__ */ react.createElement("span", {
				className: "fa fa-search-minus",
				"aria-hidden": "true"
			})), /* @__PURE__ */ react.createElement("button", {
				type: "button",
				className: "graph-explorer-btn graph-explorer-btn-default",
				title: "Fit to Screen",
				onClick: this.props.onZoomToFit
			}, /* @__PURE__ */ react.createElement("span", {
				className: "fa fa-arrows-alt",
				"aria-hidden": "true"
			})), /* @__PURE__ */ react.createElement("button", {
				type: "button",
				className: "graph-explorer-btn graph-explorer-btn-default",
				title: "Export diagram as PNG",
				onClick: this.onExportPNG
			}, /* @__PURE__ */ react.createElement("span", {
				className: "fa fa-picture-o",
				"aria-hidden": "true"
			}), " PNG"), /* @__PURE__ */ react.createElement("button", {
				type: "button",
				className: "graph-explorer-btn graph-explorer-btn-default",
				title: "Export diagram as SVG",
				onClick: this.onExportSVG
			}, /* @__PURE__ */ react.createElement("span", {
				className: "fa fa-picture-o",
				"aria-hidden": "true"
			}), " SVG"), /* @__PURE__ */ react.createElement("button", {
				type: "button",
				className: "graph-explorer-btn graph-explorer-btn-default",
				title: "Print diagram",
				onClick: this.props.onPrint
			}, /* @__PURE__ */ react.createElement("span", {
				className: "fa fa-print",
				"aria-hidden": "true"
			})), this.renderLanguages()));
		}
	};
	//#endregion
	//#region src/graph-explorer/widgets/navigator.tsx
	var CLASS_NAME$3 = "graph-explorer-navigator";
	var MIN_SCALE = .25;
	var Navigator = class extends react.Component {
		static {
			this.defaultProps = {
				width: 300,
				height: 160,
				scalePadding: .2,
				expanded: true
			};
		}
		constructor(props, context) {
			super(props, context);
			this.delayedRedraw = new Debouncer();
			this.listener = new EventObserver();
			this.scheduleRedraw = () => {
				if (this.state.expanded) this.delayedRedraw.call(this.draw);
			};
			this.draw = () => {
				const { paperTransform: pt, width, height } = this.props;
				this.calculateTransform();
				const ctx = this.canvas.getContext("2d");
				ctx.fillStyle = "#EEEEEE";
				ctx.clearRect(0, 0, width, height);
				ctx.fillRect(0, 0, width, height);
				const paneStart = paneTopLeft(pt);
				const paneSize = totalPaneSize(pt);
				const paneEnd = {
					x: paneStart.x + paneSize.x,
					y: paneStart.y + paneSize.y
				};
				const start = canvasFromPaneCoords(paneStart, pt, this.transform);
				const end = canvasFromPaneCoords(paneEnd, pt, this.transform);
				ctx.fillStyle = "white";
				ctx.fillRect(start.x, start.y, end.x - start.x, end.y - start.y);
				ctx.save();
				this.drawElements(ctx);
				this.drawViewport(ctx);
				ctx.restore();
			};
			this.onDragViewport = (e) => {
				e.preventDefault();
				if (this.isDraggingViewport) {
					const paper = paperFromCanvasCoords(this.canvasFromPageCoords(e.pageX, e.pageY), this.props.paperTransform, this.transform);
					this.props.paperArea.centerTo(paper);
				}
			};
			this.onMouseUp = () => {
				this.stopDraggingViewport();
			};
			this.onWheel = (e) => {
				e.preventDefault();
				const delta = Math.max(-1, Math.min(1, e.deltaY || e.deltaX));
				this.props.paperArea.zoomBy(-delta * .1);
			};
			this.onToggleClick = () => {
				this.setState((state) => ({ expanded: !state.expanded }), this.scheduleRedraw);
			};
			this.state = { expanded: this.props.expanded };
		}
		componentDidMount() {
			const { view, paperArea } = this.props;
			this.listener.listen(view.events, "changeHighlight", this.scheduleRedraw);
			this.listener.listen(view.model.events, "changeCells", this.scheduleRedraw);
			this.listener.listen(view.model.events, "elementEvent", this.scheduleRedraw);
			this.listener.listen(paperArea.events, "pointerMove", this.scheduleRedraw);
			this.listener.listen(paperArea.events, "scroll", this.scheduleRedraw);
		}
		shouldComponentUpdate(nextProps, nextState) {
			return nextState !== this.state;
		}
		componentWillUnmount() {
			this.delayedRedraw.dispose();
			this.listener.stopListening();
			this.stopDraggingViewport();
		}
		drawElements(ctx) {
			const { view, paperTransform: pt } = this.props;
			view.model.elements.forEach((element) => {
				const { position, size } = element;
				ctx.fillStyle = this.chooseElementColor(element);
				const { x: x1, y: y1 } = canvasFromPaperCoords(position, pt, this.transform);
				const { x: x2, y: y2 } = canvasFromPaperCoords({
					x: position.x + size.width,
					y: position.y + size.height
				}, pt, this.transform);
				ctx.fillRect(x1, y1, x2 - x1, y2 - y1);
			});
		}
		chooseElementColor(element) {
			const { view } = this.props;
			if (view.highlighter && !view.highlighter(element)) return "lightgray";
			const { color: { h, c, l } } = view.getTypeStyle(element.data.types);
			return (0, d3_color.hcl)(h, c, l).toString();
		}
		drawViewport(ctx) {
			const { paperArea, paperTransform: pt, width, height } = this.props;
			ctx.strokeStyle = "#337ab7";
			ctx.lineWidth = 2;
			const { clientWidth, clientHeight } = paperArea.getAreaMetrics();
			const viewportStart = paperArea.clientToScrollablePaneCoords(0, 0);
			const viewportEnd = paperArea.clientToScrollablePaneCoords(clientWidth, clientHeight);
			const { x: x1, y: y1 } = canvasFromPaneCoords(viewportStart, pt, this.transform);
			const { x: x2, y: y2 } = canvasFromPaneCoords(viewportEnd, pt, this.transform);
			ctx.strokeRect(x1, y1, x2 - x1, y2 - y1);
			ctx.beginPath();
			if (x1 < 0) {
				ctx.moveTo(0, y1);
				ctx.lineTo(0, y2);
			}
			if (y1 < 0) {
				ctx.moveTo(x1, 0);
				ctx.lineTo(x2, 0);
			}
			if (x2 > width) {
				ctx.moveTo(width, y1);
				ctx.lineTo(width, y2);
			}
			if (y2 > height) {
				ctx.moveTo(x1, height);
				ctx.lineTo(x2, height);
			}
			ctx.lineWidth = 4;
			ctx.strokeStyle = "#a0d2ff";
			ctx.setLineDash([5, 5]);
			ctx.stroke();
		}
		calculateTransform() {
			const { paperArea, paperTransform: pt, width, height, scalePadding } = this.props;
			const box = paperArea.getContentFittingBox();
			const displayPadding = {
				x: Math.max(box.width, width / MIN_SCALE) * scalePadding,
				y: Math.max(box.height, height / MIN_SCALE) * scalePadding
			};
			const displayStart = paneFromPaperCoords({
				x: box.x - displayPadding.x,
				y: box.y - displayPadding.y
			}, pt);
			const displayEnd = paneFromPaperCoords({
				x: box.x + box.width + displayPadding.x,
				y: box.y + box.height + displayPadding.y
			}, pt);
			const displaySize = {
				x: displayEnd.x - displayStart.x,
				y: displayEnd.y - displayStart.y
			};
			const scale = Math.min(width / displaySize.x, height / displaySize.y);
			const canvasOffset = {
				x: (width - displaySize.x * scale) / 2,
				y: (height - displaySize.y * scale) / 2
			};
			this.transform = {
				scale,
				canvasOffset,
				paneOffset: displayStart
			};
		}
		canvasFromPageCoords(pageX, pageY) {
			const { top, left } = this.canvas.getBoundingClientRect();
			return {
				x: pageX - left - window.pageXOffset,
				y: pageY - top - window.pageYOffset
			};
		}
		render() {
			const { width, height } = this.props;
			const { expanded } = this.state;
			return /* @__PURE__ */ react.createElement("div", {
				className: `${CLASS_NAME$3} ${CLASS_NAME$3}--${expanded ? "expanded" : "collapsed"}`,
				style: expanded ? {
					width,
					height
				} : void 0
			}, /* @__PURE__ */ react.createElement("canvas", {
				ref: (canvas) => {
					this.canvas = canvas;
				},
				width,
				height,
				onMouseDown: (e) => {
					this.startDragginViewport();
					this.onDragViewport(e);
				},
				onWheel: this.onWheel
			}), /* @__PURE__ */ react.createElement("button", {
				className: `${CLASS_NAME$3}__toggle`,
				title: expanded ? "Collapse navigator" : "Expand navigator",
				onClick: this.onToggleClick
			}, /* @__PURE__ */ react.createElement("div", { className: `${CLASS_NAME$3}__toggle-icon` })));
		}
		startDragginViewport() {
			if (!this.isDraggingViewport) {
				this.isDraggingViewport = true;
				document.addEventListener("mousemove", this.onDragViewport);
				document.addEventListener("mouseup", this.onMouseUp);
			}
		}
		stopDraggingViewport() {
			if (this.isDraggingViewport) {
				this.isDraggingViewport = false;
				document.removeEventListener("mousemove", this.onDragViewport);
				document.removeEventListener("mouseup", this.onMouseUp);
			}
		}
	};
	function canvasFromPaneCoords(pane, pt, nt) {
		return {
			x: nt.canvasOffset.x + (pane.x - nt.paneOffset.x) * nt.scale,
			y: nt.canvasOffset.y + (pane.y - nt.paneOffset.y) * nt.scale
		};
	}
	function canvasFromPaperCoords(paper, pt, nt) {
		return canvasFromPaneCoords(paneFromPaperCoords(paper, pt), pt, nt);
	}
	function paperFromCanvasCoords(canvas, pt, nt) {
		return paperFromPaneCoords({
			x: nt.paneOffset.x + (canvas.x - nt.canvasOffset.x) / nt.scale,
			y: nt.paneOffset.y + (canvas.y - nt.canvasOffset.y) / nt.scale
		}, pt);
	}
	//#endregion
	//#region src/graph-explorer/widgets/classTree/treeModel.ts
	var TreeNode = { setDerived: (node, derived) => ({
		...node,
		derived
	}) };
	//#endregion
	//#region images/tree/expand-toggle.svg
	var expand_toggle_default = "data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20width='128'%20height='128'%20viewbox='0%200%20128%20128'%3e%3cellipse%20stroke='%23000'%20ry='60'%20rx='60'%20cy='64'%20cx='64'%20stroke-width='5'%20fill='none'/%3e%3cline%20y2='63.4375'%20x2='104.5'%20y1='63.4375'%20x1='22.5'%20stroke-width='5'%20stroke='%23000'%20fill='none'/%3e%3cline%20y2='102.444349'%20x2='63.5'%20y1='29.4375'%20x1='63.5'%20stroke-width='5'%20stroke='%23000'%20fill='none'/%3e%3c/svg%3e";
	//#endregion
	//#region images/tree/collapse-toggle.svg
	var collapse_toggle_default = "data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20width='128'%20height='128'%20viewbox='0%200%20128%20128'%3e%3cellipse%20stroke='%23000'%20ry='60'%20rx='60'%20cy='64'%20cx='64'%20stroke-width='5'%20fill='none'/%3e%3cline%20y2='63.4375'%20x2='104.5'%20y1='63.4375'%20x1='22.5'%20stroke-width='5'%20stroke='%23000'%20fill='none'/%3e%3c/svg%3e";
	//#endregion
	//#region images/tree/leaf-default.svg
	var leaf_default_default = "data:image/svg+xml,%3c?xml%20version='1.0'%20encoding='UTF-8'%20standalone='no'?%3e%3csvg%20xmlns:svg='http://www.w3.org/2000/svg'%20xmlns='http://www.w3.org/2000/svg'%20xmlns:sodipodi='http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd'%20xmlns:inkscape='http://www.inkscape.org/namespaces/inkscape'%20width='128'%20height='128'%20viewbox='0%200%20128%20128'%20version='1.1'%20id='svg4507'%20sodipodi:docname='tree-leaf.svg'%20inkscape:version='0.92.1%20r15371'%3e%3cdefs%20id='defs4511'%20/%3e%3csodipodi:namedview%20pagecolor='%23ffffff'%20bordercolor='%23666666'%20borderopacity='1'%20objecttolerance='10'%20gridtolerance='10'%20guidetolerance='10'%20inkscape:pageopacity='0'%20inkscape:pageshadow='2'%20inkscape:window-width='1920'%20inkscape:window-height='1017'%20id='namedview4509'%20showgrid='false'%20inkscape:zoom='0.90509668'%20inkscape:cx='-272.6847'%20inkscape:cy='-5.8596487'%20inkscape:window-x='-8'%20inkscape:window-y='-8'%20inkscape:window-maximized='1'%20inkscape:current-layer='svg4507'%20/%3e%3cg%20id='g4505'%3e%3ccircle%20id='svg_1'%20cy='64'%20cx='64'%20stroke-opacity='null'%20style='fill:none;stroke:%231573b0;stroke-width:5'%20r='60'%20/%3e%3ccircle%20id='svg_3'%20cy='64'%20cx='64'%20stroke-opacity='null'%20style='fill:%231573b0;stroke:%231573b0;stroke-width:5.71026325'%20r='37'%20/%3e%3c/g%3e%3c/svg%3e";
	//#endregion
	//#region images/tree/leaf-folder.svg
	var leaf_folder_default = "data:image/svg+xml,%3c?xml%20version='1.0'%20encoding='UTF-8'%20standalone='no'?%3e%3csvg%20xmlns:svg='http://www.w3.org/2000/svg'%20xmlns='http://www.w3.org/2000/svg'%20xmlns:sodipodi='http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd'%20xmlns:inkscape='http://www.inkscape.org/namespaces/inkscape'%20width='128'%20height='128'%20viewbox='0%200%20128%20128'%20version='1.1'%20id='svg5088'%20sodipodi:docname='tree-leaf-folder.svg'%20inkscape:version='0.92.1%20r15371'%3e%3cdefs%20id='defs5092'%20/%3e%3csodipodi:namedview%20pagecolor='%23ffffff'%20bordercolor='%23666666'%20borderopacity='1'%20objecttolerance='10'%20gridtolerance='10'%20guidetolerance='10'%20inkscape:pageopacity='0'%20inkscape:pageshadow='2'%20inkscape:window-width='1920'%20inkscape:window-height='1017'%20id='namedview5090'%20showgrid='false'%20inkscape:zoom='2.6074563'%20inkscape:cx='128.74614'%20inkscape:cy='30.905472'%20inkscape:window-x='-8'%20inkscape:window-y='-8'%20inkscape:window-maximized='1'%20inkscape:current-layer='svg5088'%20/%3e%3cg%20id='g5086'%3e%3ccircle%20id='svg_1'%20cy='64'%20cx='64'%20style='fill:none;stroke:%231573b0;stroke-width:5'%20r='60'%20/%3e%3ccircle%20id='svg_3'%20cy='64'%20cx='64'%20stroke-opacity='null'%20style='fill:%231573b0;stroke:%231573b0;stroke-width:5'%20r='37'%20/%3e%3cpath%20id='svg_5'%20d='m%20127.2258,86.546643%20c%20-0.0105,-5.971065%20-4.72314,-10.809034%20-10.54009,-10.817147%20v%20-0.0027%20H%2084.380152%20c%20-1.33102,-4.386353%20-5.300357,-7.593637%20-10.028771,-7.60175%20h%20-7.577587%20c%20-5.819586,0.0054%20-10.534822,4.846082%20-10.545365,10.817147%20v%2038.368417%20c%200.01054,5.96565%204.725778,10.80362%2010.545365,10.81444%20h%2049.914556%20c%205.81167,-0.0108%2010.52955,-4.84879%2010.54009,-10.81444%20V%2086.546643%20Z'%20inkscape:connector-curvature='0'%20style='fill:%230f5376'%20sodipodi:nodetypes='ccccccccccccc'%20/%3e%3c/g%3e%3c/svg%3e";
	//#endregion
	//#region src/graph-explorer/widgets/classTree/leaf.tsx
	var LEAF_CLASS = "graph-explorer-class-leaf";
	var Leaf = class extends react.Component {
		constructor(props) {
			super(props);
			this.onClick = (e) => {
				e.preventDefault();
				const { node, onSelect } = this.props;
				onSelect(node);
			};
			this.toggle = () => {
				this.setState((state) => ({ expanded: !state.expanded }));
			};
			this.onClickCreate = () => {
				this.props.onClickCreate(this.props.node);
			};
			this.onDragCreate = (e) => {
				e.dataTransfer.setData("text", "");
				this.props.onDragCreate(this.props.node);
			};
			this.state = { expanded: Boolean(this.props.searchText) };
		}
		componentDidUpdate(nextProps) {
			if (this.props.searchText !== nextProps.searchText) this.setState({ expanded: Boolean(nextProps.searchText) });
		}
		render() {
			const { node, ...otherProps } = this.props;
			const { view, selectedNode, searchText, creatableClasses } = otherProps;
			const { expanded } = this.state;
			let toggleIcon;
			if (node.derived.length > 0) toggleIcon = expanded ? collapse_toggle_default : expand_toggle_default;
			let { icon } = view.getTypeStyle([node.model.id]);
			if (!icon) icon = node.derived.length === 0 ? leaf_default_default : leaf_folder_default;
			let bodyClass = `${LEAF_CLASS}__body`;
			if (selectedNode && selectedNode.model === node.model) bodyClass += ` ${LEAF_CLASS}__body--selected`;
			const label = highlightSubstring(node.label, searchText, { className: `${LEAF_CLASS}__highlighted-term` });
			return /* @__PURE__ */ react.createElement("div", {
				className: LEAF_CLASS,
				role: "tree-item"
			}, /* @__PURE__ */ react.createElement("div", { className: `${LEAF_CLASS}__row` }, /* @__PURE__ */ react.createElement("div", {
				className: `${LEAF_CLASS}__toggle`,
				onClick: this.toggle,
				role: "button"
			}, toggleIcon ? /* @__PURE__ */ react.createElement("img", {
				className: `${LEAF_CLASS}__toggle-icon`,
				src: toggleIcon
			}) : null), /* @__PURE__ */ react.createElement("a", {
				className: bodyClass,
				href: node.model.id,
				onClick: this.onClick
			}, /* @__PURE__ */ react.createElement("div", { className: `${LEAF_CLASS}__icon-container` }, /* @__PURE__ */ react.createElement("img", {
				className: `${LEAF_CLASS}__icon`,
				src: icon
			})), /* @__PURE__ */ react.createElement("span", { className: `${LEAF_CLASS}__label` }, label), node.model.count ? /* @__PURE__ */ react.createElement("span", { className: `${LEAF_CLASS}__count graph-explorer-badge` }, node.model.count) : null), creatableClasses.get(node.model.id) ? /* @__PURE__ */ react.createElement("div", { className: `${LEAF_CLASS}__create graph-explorer-btn-group graph-explorer-btn-group-xs` }, /* @__PURE__ */ react.createElement("button", {
				className: "graph-explorer-btn graph-explorer-btn-default",
				title: "Click or drag to create new entity of this type",
				draggable: true,
				onClick: this.onClickCreate,
				onDragStart: this.onDragCreate
			}, "+")) : null), expanded && node.derived.length > 0 ? /* @__PURE__ */ react.createElement(Forest, {
				className: `${LEAF_CLASS}__children`,
				nodes: node.derived,
				...otherProps
			}) : null);
		}
	};
	var Forest = class extends react.Component {
		render() {
			const { nodes, className, ...otherProps } = this.props;
			return /* @__PURE__ */ react.createElement("div", {
				className,
				role: "tree"
			}, nodes.map((node) => /* @__PURE__ */ react.createElement(Leaf, {
				key: `node-${node.model.id}`,
				node,
				...otherProps
			})));
		}
	};
	//#endregion
	//#region src/graph-explorer/widgets/classTree/classTree.tsx
	var CLASS_NAME$2 = "graph-explorer-class-tree";
	var MIN_TERM_LENGTH = 3;
	var ClassTree = class extends react.Component {
		constructor(props) {
			super(props);
			this.listener = new EventObserver();
			this.delayedClassUpdate = new Debouncer();
			this.delayedSearch = new Debouncer(200);
			this.loadClassesOperation = new Cancellation();
			this.refreshOperation = new Cancellation();
			this.onSearchTextChange = (e) => {
				const requestedSearchText = e.currentTarget.value;
				this.setState({ requestedSearchText });
				this.delayedSearch.call(this.performSearch);
			};
			this.performSearch = () => {
				const { requestedSearchText } = this.state;
				const requested = normalizeSearchText(requestedSearchText);
				if (requested === this.state.appliedSearchText) return;
				const appliedSearchText = requested.length < MIN_TERM_LENGTH ? void 0 : requested;
				this.setState((state) => applyFilters({
					...state,
					appliedSearchText
				}));
			};
			this.onShowOnlyCreatableChange = (_e) => {
				this.setState((state) => applyFilters({
					...state,
					showOnlyConstructible: !state.showOnlyConstructible
				}));
			};
			this.onSelectNode = (node) => {
				const { onClassSelected } = this.props;
				this.setState({ selectedNode: node });
				onClassSelected(node.model.id);
			};
			this.onCreateInstance = (node) => {
				const { onCreateInstance } = this.props;
				onCreateInstance(node.model.id);
			};
			this.onDragCreate = (node) => {
				const { view, onCreateInstance } = this.props;
				view.setHandlerForNextDropOnPaper((e) => {
					onCreateInstance(node.model.id, e.paperPosition);
				});
			};
			this.refreshClassTree = () => {
				const cancellation = new Cancellation();
				const { editor } = this.props;
				this.refreshOperation.abort();
				this.refreshOperation = cancellation;
				this.setState((state, props) => {
					if (!this.classTree) return { refreshingState: ProgressState.none };
					let refreshingState = ProgressState.none;
					if (editor.inAuthoringMode) {
						const newIris = getNewClassIris(state.constructibleClasses, this.classTree);
						if (newIris.size > 0) {
							refreshingState = ProgressState.loading;
							this.queryCreatableTypes(newIris, cancellation.signal);
						}
					}
					const roots = createRoots(this.classTree, props.view);
					return applyFilters({
						...state,
						roots: sortTree(roots),
						refreshingState
					});
				});
			};
			this.state = {
				refreshingState: ProgressState.none,
				roots: [],
				filteredRoots: [],
				requestedSearchText: "",
				appliedSearchText: "",
				constructibleClasses: /* @__PURE__ */ new Map(),
				showOnlyConstructible: false
			};
		}
		render() {
			const { view, editor } = this.props;
			const { refreshingState, requestedSearchText, appliedSearchText, filteredRoots, selectedNode, constructibleClasses, showOnlyConstructible } = this.state;
			const normalizedSearchText = normalizeSearchText(requestedSearchText);
			const searchText = appliedSearchText ? normalizedSearchText : void 0;
			return /* @__PURE__ */ react.createElement("div", { className: CLASS_NAME$2 }, /* @__PURE__ */ react.createElement("div", { className: `${CLASS_NAME$2}__filter` }, /* @__PURE__ */ react.createElement("div", { className: `${CLASS_NAME$2}__filter-group` }, /* @__PURE__ */ react.createElement("input", {
				type: "text",
				className: "search-input graph-explorer-form-control",
				placeholder: "Search for...",
				value: this.state.requestedSearchText,
				onChange: this.onSearchTextChange
			}), editor.inAuthoringMode ? /* @__PURE__ */ react.createElement("label", { className: `${CLASS_NAME$2}__only-creatable` }, /* @__PURE__ */ react.createElement("input", {
				type: "checkbox",
				checked: showOnlyConstructible,
				onChange: this.onShowOnlyCreatableChange
			}), " ", "Show only constructible") : null)), /* @__PURE__ */ react.createElement(ProgressBar, { state: refreshingState }), this.classTree ? /* @__PURE__ */ react.createElement(Forest, {
				className: `${CLASS_NAME$2}__tree graph-explorer-scrollable`,
				view,
				nodes: filteredRoots,
				searchText,
				selectedNode,
				onSelect: this.onSelectNode,
				creatableClasses: constructibleClasses,
				onClickCreate: this.onCreateInstance,
				onDragCreate: this.onDragCreate
			}) : /* @__PURE__ */ react.createElement("div", { className: `${CLASS_NAME$2}__spinner` }, /* @__PURE__ */ react.createElement(HtmlSpinner, {
				width: 30,
				height: 30
			})));
		}
		componentDidMount() {
			const { view, editor } = this.props;
			this.listener.listen(view.events, "changeLanguage", () => this.refreshClassTree());
			this.listener.listen(editor.model.events, "loadingStart", () => {
				this.initClassTree();
			});
			this.listener.listen(editor.model.events, "classEvent", ({ data }) => {
				if (data.changeLabel || data.changeCount) this.delayedClassUpdate.call(this.refreshClassTree);
			});
			this.initClassTree();
		}
		componentWillUnmount() {
			this.listener.stopListening();
			this.delayedClassUpdate.dispose();
			this.delayedSearch.dispose();
			this.loadClassesOperation.abort();
			this.refreshOperation.abort();
		}
		async initClassTree() {
			if (this.dataProvider !== this.props.editor.model.dataProvider) {
				this.dataProvider = this.props.editor.model.dataProvider;
				this.classTree = void 0;
				const cancellation = new Cancellation();
				this.loadClassesOperation.abort();
				this.loadClassesOperation = cancellation;
				const classes = await this.dataProvider.classTree();
				if (cancellation.signal.aborted) return;
				this.setClassTree(classes);
			}
			this.refreshClassTree();
		}
		setClassTree(roots) {
			const diagramModel = this.props.editor.model;
			const visiting = /* @__PURE__ */ new Set();
			const reduceNonCycle = (acc, model) => {
				if (!visiting.has(model.id)) {
					visiting.add(model.id);
					const children = model.children.reduce(reduceNonCycle, []);
					acc.push({
						...model,
						children
					});
					visiting.delete(model.id);
				}
				return acc;
			};
			this.classTree = roots.reduce(reduceNonCycle, []);
			const addClass = (model) => {
				if (!diagramModel.getClass(model.id)) {
					const { id, label, count, children } = model;
					const richClass = new FatClassModel({
						id,
						label: label.values,
						count
					});
					diagramModel.addClass(richClass);
					children.forEach(addClass);
				}
			};
			this.classTree.forEach(addClass);
			this.refreshClassTree();
		}
		async queryCreatableTypes(typeIris, ct) {
			try {
				const result = await CancellationToken.mapCancelledToNull(ct, this.props.editor.metadataApi.filterConstructibleTypes(typeIris, ct));
				if (result === null) return;
				this.setState((state) => {
					const constructibleClasses = cloneMap(state.constructibleClasses);
					typeIris.forEach((type) => {
						constructibleClasses.set(type, result.has(type));
					});
					return applyFilters({
						...state,
						constructibleClasses,
						refreshingState: ProgressState.completed
					});
				});
			} catch (err) {
				console.error(err);
				if (ct.aborted) return;
				this.setState((state) => applyFilters({
					...state,
					refreshingState: ProgressState.error
				}));
			}
		}
	};
	function createRoots(classTree, view) {
		const mapClass = (model) => {
			const richClass = view.model.createClass(model.id);
			return {
				model: richClass,
				label: view.formatLabel(richClass.label, richClass.id),
				derived: model.children.map(mapClass)
			};
		};
		return classTree.map(mapClass);
	}
	function getNewClassIris(existingClasses, classTree) {
		const classIris = /* @__PURE__ */ new Set();
		const visitClass = (model) => {
			if (!existingClasses.has(model.id)) classIris.add(model.id);
			model.children.forEach(visitClass);
		};
		classTree.forEach(visitClass);
		return classIris;
	}
	function normalizeSearchText(text) {
		return text.trim().toLowerCase();
	}
	function sortTree(roots) {
		function mapNodes(nodes) {
			if (nodes.length === 0) return nodes;
			const mapped = nodes.map(mapNode);
			mapped.sort(compareByLabel);
			return mapped;
		}
		function mapNode(node) {
			return TreeNode.setDerived(node, mapNodes(node.derived));
		}
		function compareByLabel(left, right) {
			return left.label.localeCompare(right.label);
		}
		return mapNodes(roots);
	}
	function applyFilters(state) {
		let filteredRoots = state.roots;
		if (state.appliedSearchText) filteredRoots = filterByKeyword(filteredRoots, state.appliedSearchText);
		if (state.showOnlyConstructible) filteredRoots = filterOnlyCreatable(filteredRoots, state.constructibleClasses);
		return {
			...state,
			filteredRoots
		};
	}
	function filterByKeyword(roots, searchText) {
		if (roots.length === 0) return roots;
		function collectByKeyword(acc, node) {
			const derived = node.derived.reduce(collectByKeyword, []);
			if (derived.length > 0 || node.label.toLowerCase().indexOf(searchText) >= 0) acc.push(TreeNode.setDerived(node, derived));
			return acc;
		}
		return roots.reduce(collectByKeyword, []);
	}
	function filterOnlyCreatable(roots, creatableClasses) {
		function collectOnlyCreatable(acc, node) {
			const derived = node.derived.reduce(collectOnlyCreatable, []);
			if (derived.length > 0 || creatableClasses.get(node.model.id)) acc.push(TreeNode.setDerived(node, derived));
			return acc;
		}
		return roots.reduce(collectOnlyCreatable, []);
	}
	//#endregion
	//#region src/graph-explorer/widgets/linksToolbox.tsx
	var LinkInToolBox = class extends react.Component {
		constructor(..._args) {
			super(..._args);
			this.onPressFilter = () => {
				if (this.props.onPressFilter) this.props.onPressFilter(this.props.link);
			};
			this.changeState = (state) => {
				const history = this.props.view.model.history;
				changeLinkTypeState(history, state, [this.props.link]);
			};
			this.isChecked = (stateName) => {
				let curState;
				if (!this.props.link.visible) curState = "invisible";
				else if (!this.props.link.showLabel) curState = "withoutLabels";
				else curState = "allVisible";
				return stateName === curState;
			};
			this.getText = () => {
				const { link: linkType, view, filterKey } = this.props;
				return highlightSubstring(view.formatLabel(linkType.label, linkType.id), filterKey);
			};
		}
		render() {
			const newIcon = this.props.link.isNew ? /* @__PURE__ */ react.createElement("span", { className: "linkInToolBox__new-tag" }, "new") : "";
			const countIcon = this.props.count > 0 ? /* @__PURE__ */ react.createElement("span", { className: "graph-explorer-badge" }, this.props.count) : "";
			const badgeContainer = newIcon || countIcon ? /* @__PURE__ */ react.createElement("div", null, newIcon, countIcon) : "";
			return /* @__PURE__ */ react.createElement("li", {
				"data-linktypeid": this.props.link.id,
				className: "graph-explorer-list-group-item linkInToolBox clearfix"
			}, /* @__PURE__ */ react.createElement("span", {
				className: "graph-explorer-btn-group graph-explorer-btn-group-xs",
				"data-toggle": "buttons"
			}, /* @__PURE__ */ react.createElement("label", {
				className: "graph-explorer-btn graph-explorer-btn-default" + (this.isChecked("invisible") ? " active" : ""),
				id: "invisible",
				title: "Hide links and labels",
				onClick: () => this.changeState("invisible")
			}, /* @__PURE__ */ react.createElement("span", {
				className: "fa fa-times",
				"aria-hidden": "true"
			})), /* @__PURE__ */ react.createElement("label", {
				className: "graph-explorer-btn graph-explorer-btn-default" + (this.isChecked("withoutLabels") ? " active" : ""),
				id: "withoutLabels",
				title: "Show links without labels",
				onClick: () => this.changeState("withoutLabels")
			}, /* @__PURE__ */ react.createElement("span", {
				className: "fa fa-arrows-h",
				"aria-hidden": "true"
			})), /* @__PURE__ */ react.createElement("label", {
				className: "graph-explorer-btn graph-explorer-btn-default" + (this.isChecked("allVisible") ? " active" : ""),
				id: "allVisible",
				title: "Show links with labels",
				onClick: () => this.changeState("allVisible")
			}, /* @__PURE__ */ react.createElement("span", {
				className: "fa fa-text-width",
				"aria-hidden": "true"
			}))), /* @__PURE__ */ react.createElement("div", { className: "link-title" }, this.getText()), badgeContainer, /* @__PURE__ */ react.createElement("div", {
				className: "linkInToolBox__filter-button",
				onClick: this.onPressFilter
			}));
		}
	};
	var LinkTypesToolboxView = class extends react.Component {
		constructor(props) {
			super(props);
			this.compareLinks = (a, b) => {
				const { view } = this.props;
				const aText = view.formatLabel(a.label, a.id);
				const bText = view.formatLabel(b.label, b.id);
				return aText.localeCompare(bText);
			};
			this.onChangeInput = (e) => {
				this.setState({ filterKey: e.currentTarget.value });
			};
			this.onDropFilter = () => {
				this.setState({ filterKey: "" });
			};
			this.getLinks = () => {
				const { view, links = [] } = this.props;
				return links.filter((linkType) => {
					const text = view.formatLabel(linkType.label, linkType.id).toLowerCase();
					return !this.state.filterKey || text.indexOf(this.state.filterKey.toLowerCase()) >= 0;
				}).sort(this.compareLinks);
			};
			this.getViews = (links) => {
				const countMap = this.props.countMap || {};
				const views = [];
				for (const link of links) views.push(/* @__PURE__ */ react.createElement(LinkInToolBox, {
					key: link.id,
					view: this.props.view,
					link,
					onPressFilter: this.props.filterCallback,
					count: countMap[link.id] || 0,
					filterKey: this.state.filterKey
				}));
				return views;
			};
			this.state = { filterKey: "" };
		}
		render() {
			const className = "link-types-toolbox";
			const { view, dataState, selectedElement } = this.props;
			const history = view.model.history;
			const links = this.getLinks();
			const views = this.getViews(links);
			let connectedTo = null;
			if (selectedElement) {
				const selectedElementLabel = view.formatLabel(selectedElement.data.label.values, selectedElement.iri);
				connectedTo = /* @__PURE__ */ react.createElement("h4", {
					className: "links-heading",
					style: { display: "block" }
				}, "Connected to", "\xA0", /* @__PURE__ */ react.createElement("span", null, selectedElementLabel));
			}
			let dropButton = null;
			if (this.state.filterKey) dropButton = /* @__PURE__ */ react.createElement("button", {
				type: "button",
				className: `${className}__clearSearch`,
				onClick: this.onDropFilter
			}, /* @__PURE__ */ react.createElement("span", {
				className: "fa fa-times",
				"aria-hidden": "true"
			}));
			return /* @__PURE__ */ react.createElement("div", { className }, /* @__PURE__ */ react.createElement("div", { className: `${className}__heading` }, /* @__PURE__ */ react.createElement("div", { className: `${className}__searching-box` }, /* @__PURE__ */ react.createElement("input", {
				className: "search-input graph-explorer-form-control",
				type: "text",
				value: this.state.filterKey,
				onChange: this.onChangeInput,
				placeholder: "Search for..."
			}), dropButton), /* @__PURE__ */ react.createElement("div", { className: `${className}__switch-all` }, /* @__PURE__ */ react.createElement("div", { className: "graph-explorer-btn-group graph-explorer-btn-group-xs" }, /* @__PURE__ */ react.createElement("label", {
				className: "graph-explorer-btn graph-explorer-btn-default",
				title: "Hide links and labels",
				onClick: () => changeLinkTypeState(history, "invisible", links)
			}, /* @__PURE__ */ react.createElement("span", {
				className: "fa fa-times",
				"aria-hidden": "true"
			})), /* @__PURE__ */ react.createElement("label", {
				className: "graph-explorer-btn graph-explorer-btn-default",
				title: "Show links without labels",
				onClick: () => changeLinkTypeState(history, "withoutLabels", links)
			}, /* @__PURE__ */ react.createElement("span", {
				className: "fa fa-arrows-h",
				"aria-hidden": "true"
			})), /* @__PURE__ */ react.createElement("label", {
				className: "graph-explorer-btn graph-explorer-btn-default",
				title: "Show links with labels",
				onClick: () => changeLinkTypeState(history, "allVisible", links)
			}, /* @__PURE__ */ react.createElement("span", {
				className: "fa fa-text-width",
				"aria-hidden": "true"
			}))), /* @__PURE__ */ react.createElement("span", null, "\xA0Switch all"))), /* @__PURE__ */ react.createElement(ProgressBar, { state: dataState }), /* @__PURE__ */ react.createElement("div", { className: `${className}__rest` }, connectedTo, /* @__PURE__ */ react.createElement("div", { className: "graph-explorer-scrollable" }, /* @__PURE__ */ react.createElement("ul", { className: "graph-explorer-list-group connected-links" }, views))));
		}
	};
	var LinkTypesToolbox = class extends react.Component {
		constructor(props, context) {
			super(props, context);
			this.listener = new EventObserver();
			this.linkListener = new EventObserver();
			this.debounceSelection = new Debouncer(50);
			this.updateOnCurrentSelection = () => {
				const { editor } = this.props;
				const single = editor.selection.length === 1 ? editor.selection[0] : null;
				if (single !== this.state.selectedElement && single instanceof Element$1) this.requestLinksOf(single);
			};
			this.onLinkChanged = () => {
				this.forceUpdate();
			};
			this.onAddToFilter = (linkType) => {
				const { selectedElement } = this.state;
				selectedElement.addToFilter(linkType);
			};
			const { view, editor } = this.props;
			this.listener.listen(view.events, "changeLanguage", () => this.updateOnCurrentSelection());
			this.listener.listen(editor.model.events, "loadingSuccess", () => this.updateOnCurrentSelection());
			this.listener.listen(editor.events, "changeSelection", () => {
				this.debounceSelection.call(this.updateOnCurrentSelection);
			});
			this.state = { dataState: ProgressState.none };
		}
		componentDidMount() {
			this.updateOnCurrentSelection();
		}
		componentWillUnmount() {
			this.listener.stopListening();
			this.linkListener.stopListening();
			this.debounceSelection.dispose();
		}
		requestLinksOf(selectedElement) {
			if (selectedElement) {
				const request = { elementId: selectedElement.iri };
				this.currentRequest = request;
				this.setState({
					dataState: ProgressState.loading,
					selectedElement
				});
				this.props.editor.model.dataProvider.linkTypesOf(request).then((linkTypes) => {
					if (this.currentRequest !== request) return;
					const { linksOfElement, countMap } = this.computeStateFromRequestResult(linkTypes);
					this.subscribeOnLinksEvents(linksOfElement);
					this.setState({
						dataState: ProgressState.completed,
						linksOfElement,
						countMap
					});
				}).catch((error) => {
					if (this.currentRequest !== request) return;
					console.error(error);
					this.setState({
						dataState: ProgressState.error,
						linksOfElement: void 0,
						countMap: {}
					});
				});
			} else {
				this.currentRequest = null;
				this.setState({
					dataState: ProgressState.completed,
					selectedElement,
					linksOfElement: void 0,
					countMap: {}
				});
			}
		}
		computeStateFromRequestResult(linkTypes) {
			const linksOfElement = [];
			const countMap = {};
			const model = this.props.editor.model;
			for (const linkType of linkTypes) {
				const type = model.createLinkType(linkType.id);
				linksOfElement.push(type);
				countMap[linkType.id] = linkType.inCount + linkType.outCount;
			}
			return {
				linksOfElement,
				countMap
			};
		}
		subscribeOnLinksEvents(linksOfElement) {
			this.linkListener.stopListening();
			const listener = this.linkListener;
			for (const link of linksOfElement) {
				listener.listen(link.events, "changeLabel", this.onLinkChanged);
				listener.listen(link.events, "changeVisibility", this.onLinkChanged);
			}
		}
		render() {
			const { view } = this.props;
			const { selectedElement, dataState, linksOfElement, countMap } = this.state;
			return /* @__PURE__ */ react.createElement(LinkTypesToolboxView, {
				view,
				dataState,
				links: linksOfElement,
				countMap,
				filterCallback: this.onAddToFilter,
				selectedElement
			});
		}
	};
	function changeLinkTypeState(history, state, links) {
		const batch = history.startBatch();
		const { visible, showLabel } = state === "invisible" ? {
			visible: false,
			showLabel: false
		} : state === "withoutLabels" ? {
			visible: true,
			showLabel: false
		} : state === "allVisible" ? {
			visible: true,
			showLabel: true
		} : void 0;
		for (const linkType of links) history.execute(changeLinkTypeVisibility({
			linkType,
			visible,
			showLabel
		}));
		batch.store();
	}
	//#endregion
	//#region src/graph-explorer/workspace/accordion.tsx
	var CLASS_NAME$1 = "graph-explorer-accordion";
	var Accordion = class extends react.Component {
		static {
			this.defaultProps = {
				direction: "vertical",
				animationDuration: 300
			};
		}
		constructor(props) {
			super(props);
			this.items = [];
			this.isScrollable = false;
			this.updateSizes = () => {
				const { children } = this.props;
				const defaultProps = /* @__PURE__ */ new Map();
				react.Children.forEach(children, (child, index) => {
					if (typeof child !== "object") return;
					const { defaultSize, defaultCollapsed, collapsedSize, minSize } = child.props;
					if (minSize !== void 0) this.isScrollable = true;
					defaultProps.set(index, {
						defaultSize,
						defaultCollapsed,
						collapsedSize,
						minSize
					});
				});
				this.defaultProps = defaultProps;
				this.setState(({ collapsed }) => {
					const totalSize = this.clientSize(this.element.parentElement);
					let leftSize = totalSize;
					let leftChildCount = react.Children.count(children);
					const newCollapsed = [];
					this.defaultProps.forEach(({ defaultSize, defaultCollapsed = false }, index) => {
						let itemCollapsed = collapsed[index] === void 0 ? defaultCollapsed : collapsed[index];
						const isLastItem = index === this.defaultProps.size - 1;
						const noExpandedItems = newCollapsed.findIndex((c) => !c) < 0;
						if (isLastItem && noExpandedItems) itemCollapsed = false;
						const size = itemCollapsed ? this.sizeWhenCollapsed(index) : defaultSize;
						if (size) {
							leftSize = leftSize - size;
							leftChildCount = leftChildCount - 1;
						}
						newCollapsed.push(itemCollapsed);
					});
					const newSizes = [];
					const newPercents = [];
					this.defaultProps.forEach(({ defaultSize, minSize }, index) => {
						let size = leftSize / leftChildCount;
						const collapsedSize = this.sizeWhenCollapsed(index);
						if (newCollapsed[index]) size = collapsedSize;
						else if (defaultSize !== void 0) size = defaultSize;
						else if (size < minSize) size = collapsedSize + minSize;
						if (size < collapsedSize) {
							size = collapsedSize;
							newCollapsed[index] = true;
						}
						const percent = `${100 * size / totalSize}%`;
						newSizes.push(size);
						newPercents.push(percent);
					});
					return {
						sizes: newSizes,
						percents: newPercents,
						collapsed: newCollapsed
					};
				});
			};
			this.onBeginDragHandle = (_itemIndex) => {
				this.originTotalSize = this.clientSize(this.element);
				this.originSizes = this.computeEffectiveItemSizes();
				this.originCollapsed = [...this.state.collapsed];
				this.setState({ resizing: true }, () => {
					const { direction, onStartResize } = this.props;
					if (onStartResize) onStartResize(direction);
				});
			};
			this.onEndDragHandle = () => {
				this.setState({ resizing: false });
			};
			this.sizeWhenCollapsed = (index) => {
				const item = this.items[index];
				const { collapsedSize } = this.defaultProps.get(index);
				if (collapsedSize !== void 0) return collapsedSize;
				return (item.header ? this.clientSize(item.header) : 0) + (this.offsetSize(item.element) - this.clientSize(item.element));
			};
			this.onDragHandle = (itemIndex, dx, dy) => {
				const sizes = [...this.originSizes];
				const collapsed = [...this.originCollapsed];
				new SizeDistributor(sizes, collapsed, this.originTotalSize, this.sizeWhenCollapsed).distribute(itemIndex + 1, this.isVertical ? dy : dx);
				const percents = sizes.map((size) => `${100 * size / this.originTotalSize}%`);
				this.setState({
					sizes,
					percents,
					collapsed
				});
			};
			const childCount = react.Children.count(this.props.children);
			this.state = {
				collapsed: [],
				resizing: false,
				percents: react.Children.map(this.props.children, () => `${100 / childCount}%`)
			};
		}
		componentDidMount() {
			this.updateSizes();
		}
		componentDidUpdate(prevProps, prevState) {
			const { direction, children, onResize, animationDuration } = this.props;
			if (react.Children.count(children) !== react.Children.count(prevProps.children)) this.updateSizes();
			const { sizes, resizing } = this.state;
			if (sizes !== prevState.sizes && onResize) if (resizing) onResize(direction);
			else setTimeout(() => onResize(direction), animationDuration);
		}
		get isVertical() {
			return this.props.direction === "vertical";
		}
		clientSize(element) {
			const { clientWidth, clientHeight } = element;
			return this.isVertical ? clientHeight : clientWidth;
		}
		offsetSize(element) {
			const { offsetWidth, offsetHeight } = element;
			return this.isVertical ? offsetHeight : offsetWidth;
		}
		render() {
			const { direction } = this.props;
			const { resizing } = this.state;
			const resizingClassName = resizing ? `${CLASS_NAME$1}--resizing` : "";
			const scrollableClassName = this.isScrollable ? `${CLASS_NAME$1}--scrollable` : "";
			return /* @__PURE__ */ react.createElement("div", {
				className: `${CLASS_NAME$1} ${CLASS_NAME$1}--${direction} ${resizingClassName} ${scrollableClassName}`,
				ref: (element) => {
					this.element = element;
				}
			}, this.renderItems());
		}
		renderItems() {
			const { sizes, percents, collapsed } = this.state;
			const { children, direction } = this.props;
			return react.Children.map(children, (child, index) => {
				if (typeof child !== "object") throw new Error("Accordion should have only AccordionItem elements as children");
				const lastChild = index === react.Children.count(children) - 1;
				const size = collapsed[index] ? sizes[index] : percents[index];
				const additionalProps = {
					ref: (element) => {
						this.items[index] = element;
					},
					collapsed: collapsed[index],
					size,
					direction,
					onChangeCollapsed: (itemCollapsed) => this.onItemChangeCollapsed({
						itemIndex: index,
						itemCollapsed
					}),
					onBeginDragHandle: lastChild ? void 0 : () => this.onBeginDragHandle(index),
					onDragHandle: lastChild ? void 0 : (dx, dy) => this.onDragHandle(index, dx, dy),
					onEndDragHandle: this.onEndDragHandle
				};
				return react.cloneElement(child, additionalProps);
			});
		}
		computeEffectiveItemSizes() {
			const sizes = [];
			this.items.forEach((item, index) => {
				if (!item) return;
				if (this.state.collapsed[index]) {
					const collapsedSize = this.sizeWhenCollapsed(index);
					sizes.push(collapsedSize);
				} else sizes.push(this.offsetSize(item.element));
			});
			return sizes;
		}
		onItemChangeCollapsed({ itemIndex, itemCollapsed }) {
			const totalSize = this.clientSize(this.element);
			const sizes = this.computeEffectiveItemSizes();
			if (sizes.length === 1) return;
			const collapsed = [...this.state.collapsed];
			const effectiveSize = sizes[itemIndex];
			const collapsedSize = this.sizeWhenCollapsed(itemIndex);
			const distributor = new SizeDistributor(sizes, collapsed, totalSize, this.sizeWhenCollapsed);
			if (itemCollapsed) {
				const splitShift = Math.max(effectiveSize - collapsedSize, 0);
				sizes[itemIndex] = collapsedSize;
				if (itemIndex === sizes.length - 1) distributor.expand(splitShift, itemIndex - 1);
				else distributor.expand(splitShift, itemIndex + 1);
			} else {
				const { defaultSize, minSize } = this.defaultProps.get(itemIndex);
				const shift = (defaultSize || totalSize / sizes.length) - collapsedSize;
				let freeSize;
				if (itemIndex === sizes.length - 1) freeSize = distributor.collapseForward({
					shift,
					from: itemIndex - 1,
					to: itemIndex
				});
				else freeSize = distributor.collapseForward({
					shift,
					from: itemIndex + 1,
					to: sizes.length
				});
				freeSize = Math.max(freeSize, distributor.leftoverSize());
				if (freeSize < shift) freeSize += distributor.collapseForward({
					shift: shift - freeSize,
					from: 0,
					to: itemIndex
				});
				if (freeSize < minSize) freeSize = minSize;
				sizes[itemIndex] = Math.round(collapsedSize + freeSize);
			}
			collapsed[itemIndex] = itemCollapsed;
			const percents = sizes.map((size) => `${100 * size / totalSize}%`);
			this.setState({
				sizes,
				percents,
				collapsed
			});
		}
	};
	var SizeDistributor = class {
		constructor(sizes, collapsed, totalSize, sizeWhenCollapsed) {
			this.sizes = sizes;
			this.collapsed = collapsed;
			this.totalSize = totalSize;
			this.sizeWhenCollapsed = sizeWhenCollapsed;
		}
		distribute(splitIndex, splitShift) {
			if (splitShift > 0) {
				let freeSize = this.collapseForward({
					shift: splitShift,
					from: splitIndex,
					to: this.sizes.length
				});
				freeSize = Math.max(freeSize, this.leftoverSize());
				this.expand(freeSize, splitIndex - 1);
			} else {
				let freeSize = this.collapseBackward({
					shift: -splitShift,
					from: 0,
					to: splitIndex
				});
				freeSize = Math.max(freeSize, this.leftoverSize());
				this.expand(freeSize, splitIndex);
			}
		}
		collapseForward({ shift, from, to }) {
			if (shift <= 0) return 0;
			let shiftLeft = shift;
			for (let i = from; i < to; i++) shiftLeft = this.collapse(shiftLeft, i);
			return shift - shiftLeft;
		}
		collapseBackward({ shift, from, to }) {
			if (shift <= 0) return 0;
			let shiftLeft = shift;
			for (let i = to - 1; i >= from; i--) shiftLeft = this.collapse(shiftLeft, i);
			return shift - shiftLeft;
		}
		collapse(shift, index) {
			if (this.collapsed[index]) return shift;
			const size = this.sizes[index];
			const collapsedSize = this.sizeWhenCollapsed(index);
			const newSize = Math.round(Math.max(size - shift, collapsedSize));
			this.sizes[index] = newSize;
			this.collapsed[index] = newSize <= collapsedSize;
			return shift - (size - newSize);
		}
		expand(shift, index) {
			if (shift <= 0) return 0;
			const oldSize = this.sizes[index];
			const newSize = Math.round(oldSize + shift);
			this.sizes[index] = newSize;
			this.collapsed[index] = newSize <= this.sizeWhenCollapsed(index);
			return newSize - oldSize;
		}
		leftoverSize() {
			const sizeSum = this.sizes.reduce((sum, size) => sum + size, 0);
			return Math.max(this.totalSize - sizeSum, 0);
		}
	};
	//#endregion
	//#region src/graph-explorer/workspace/accordionItem.tsx
	var DockSide = /* @__PURE__ */ function(DockSide) {
		DockSide[DockSide["Left"] = 1] = "Left";
		DockSide[DockSide["Right"] = 2] = "Right";
		return DockSide;
	}({});
	var CLASS_NAME = "graph-explorer-accordion-item";
	var AccordionItem = class extends react.Component {
		static {
			this.defaultProps = { direction: "vertical" };
		}
		constructor(props) {
			super(props);
			this.state = { resizing: false };
		}
		get element() {
			return this._element;
		}
		get header() {
			return this._header;
		}
		get isVertical() {
			return this.props.direction === "vertical";
		}
		renderToggleButton() {
			const { collapsed, dockSide, onChangeCollapsed } = this.props;
			if (!dockSide) return null;
			const side = dockSide === 1 ? "left" : "right";
			return /* @__PURE__ */ react.createElement("div", {
				className: `${CLASS_NAME}__handle-btn ${CLASS_NAME}__handle-btn-${side}`,
				onClick: () => onChangeCollapsed(!collapsed)
			});
		}
		render() {
			const { heading, bodyClassName, children, bodyRef, collapsed, size, direction, onBeginDragHandle, onDragHandle, onEndDragHandle, dockSide } = this.props;
			const { resizing } = this.state;
			const shouldRenderHandle = onBeginDragHandle && onDragHandle && onEndDragHandle;
			const style = this.isVertical ? { height: size } : { width: size };
			const isMounted = !(collapsed && dockSide);
			return /* @__PURE__ */ react.createElement("div", {
				className: `${CLASS_NAME} ${CLASS_NAME}--${collapsed ? "collapsed" : "expanded"} ${CLASS_NAME}--${direction}
                ${resizing ? `${CLASS_NAME}--resizing` : ""}`,
				ref: (element) => {
					this._element = element;
				},
				style
			}, /* @__PURE__ */ react.createElement("div", { className: `${CLASS_NAME}__inner` }, heading ? /* @__PURE__ */ react.createElement("div", {
				className: `${CLASS_NAME}__header`,
				ref: (header) => {
					this._header = header;
				},
				onClick: () => this.props.onChangeCollapsed(!collapsed)
			}, heading) : null, /* @__PURE__ */ react.createElement("div", { className: `${CLASS_NAME}__body` }, children && isMounted ? children : /* @__PURE__ */ react.createElement("div", {
				ref: bodyRef,
				className: `${bodyClassName || ""}`
			}))), shouldRenderHandle ? /* @__PURE__ */ react.createElement(DraggableHandle, {
				className: `${CLASS_NAME}__handle ${CLASS_NAME}__handle-${direction}`,
				onBeginDragHandle: (_e) => {
					this.setState({ resizing: true });
					onBeginDragHandle();
				},
				onDragHandle: (_e, x, y) => onDragHandle(x, y),
				onEndDragHandle: (_e) => {
					this.setState({ resizing: false });
					onEndDragHandle();
				}
			}) : null, this.renderToggleButton());
		}
	};
	//#endregion
	//#region src/graph-explorer/workspace/layout/layout.tsx
	var DEFAULT_HORIZONTAL_COLLAPSED_SIZE = 28;
	var WorkspaceLayoutType = /* @__PURE__ */ function(WorkspaceLayoutType) {
		WorkspaceLayoutType["Row"] = "row";
		WorkspaceLayoutType["Column"] = "column";
		WorkspaceLayoutType["Component"] = "component";
		return WorkspaceLayoutType;
	}({});
	var WorkspaceLayout = class extends react.Component {
		renderAccordion({ children, direction, animationDuration }) {
			const { _onStartResize, _onResize } = this.props;
			const items = children.map((child, index) => {
				let dockSide;
				if (direction === "horizontal" && !child.undocked) {
					if (index === 0) dockSide = DockSide.Left;
					else if (index === children.length - 1) dockSide = DockSide.Right;
				}
				let collapsedSize = child.collapsedSize;
				if (collapsedSize === void 0 && direction === "horizontal") collapsedSize = DEFAULT_HORIZONTAL_COLLAPSED_SIZE;
				return /* @__PURE__ */ react.createElement(AccordionItem, {
					key: child.type === "component" ? child.id : index,
					heading: child.type === "component" ? child.heading : void 0,
					dockSide,
					defaultSize: child.defaultSize,
					defaultCollapsed: child.defaultCollapsed,
					collapsedSize,
					minSize: child.minSize
				}, this.renderLayout(child));
			});
			return /* @__PURE__ */ react.createElement(Accordion, {
				direction,
				onStartResize: _onStartResize,
				onResize: _onResize,
				animationDuration
			}, items);
		}
		renderLayout(layout) {
			if (layout.type === "row") return this.renderAccordion({
				children: layout.children,
				direction: "horizontal",
				animationDuration: layout.animationDuration
			});
			if (layout.type === "column") return this.renderAccordion({
				children: layout.children,
				direction: "vertical",
				animationDuration: layout.animationDuration
			});
			if (layout.type === "component") return react.Children.only(layout.content);
			return null;
		}
		render() {
			const { layout } = this.props;
			return this.renderLayout(layout);
		}
	};
	//#endregion
	//#region src/graph-explorer/workspace/workspaceMarkup.tsx
	var WorkspaceMarkup = class extends react.Component {
		constructor(..._args) {
			super(..._args);
			this.untilMouseUpClasses = [];
			this.cancellation = new Cancellation();
			this.triggerWorkspaceEvent = (key) => {
				const { onWorkspaceEvent } = this.props;
				if (onWorkspaceEvent) onWorkspaceEvent(key);
			};
			this.onCreateInstance = async (classId, position) => {
				const { editor, view, model, metadataApi } = this.props;
				await forceNonReactExecutionContext();
				const batch = model.history.startBatch();
				const signal = this.cancellation.signal;
				const elementModel = await CancellationToken.mapCancelledToNull(signal, metadataApi.generateNewElement([classId], signal));
				if (elementModel === null) return;
				const element = editor.createNewEntity({ elementModel });
				const targetPosition = position || getViewportCenterInPaperCoords(this.paperArea);
				element.setPosition(targetPosition);
				view.performSyncUpdate();
				centerElementToPosition(element, targetPosition);
				batch.store();
				editor.setSelection([element]);
				editor.showEditEntityForm(element);
			};
			this.onDocumentMouseUp = () => {
				for (const className of this.untilMouseUpClasses) this.element.classList.remove(className);
				this.untilMouseUpClasses = [];
			};
			this.onDropOnPaper = (e, paperPosition) => {
				e.preventDefault();
				const event = {
					dragEvent: e,
					paperPosition
				};
				if (this.props.view._tryHandleDropOnPaper(event)) return;
				const iris = tryParseDefaultDragAndDropData(e);
				if (iris.length > 0) this.props.editor.onDragDrop(iris, paperPosition);
			};
		}
		addToolbarWidgetToPaper() {
			const { hideToolbar, view, toolbar } = this.props;
			if (!hideToolbar) view.setPaperWidget({
				key: "toolbar",
				widget: /* @__PURE__ */ react.createElement(ToolbarWidget, null, toolbar),
				attachment: WidgetAttachment.Viewport
			});
		}
		getLeftPanelLayout() {
			const { view, editor, model, searchCriteria, onSearchCriteriaChanged } = this.props;
			const classTree = /* @__PURE__ */ react.createElement(ClassTree, {
				view,
				editor,
				onClassSelected: (classId) => {
					const elementType = model.createClass(classId);
					onSearchCriteriaChanged({ elementType });
				},
				onCreateInstance: this.onCreateInstance
			});
			const instancesSearch = /* @__PURE__ */ react.createElement(InstancesSearch, {
				view,
				model,
				criteria: searchCriteria || {},
				onCriteriaChanged: onSearchCriteriaChanged
			});
			return {
				type: WorkspaceLayoutType.Column,
				children: [{
					id: "classes",
					type: WorkspaceLayoutType.Component,
					content: classTree,
					heading: "Classes"
				}, {
					id: "instances",
					type: WorkspaceLayoutType.Component,
					content: instancesSearch,
					heading: "Instances"
				}],
				defaultSize: 275,
				defaultCollapsed: !this.props.isLeftPanelOpen
			};
		}
		getRightPanelLayout() {
			const { view, editor, elementsSearchPanel } = this.props;
			const rightPanel = {
				type: WorkspaceLayoutType.Column,
				children: [{
					id: "connections",
					type: WorkspaceLayoutType.Component,
					content: /* @__PURE__ */ react.createElement(LinkTypesToolbox, {
						view,
						editor
					}),
					heading: "Connections"
				}],
				defaultSize: 275,
				defaultCollapsed: !this.props.isRightPanelOpen
			};
			if (elementsSearchPanel) rightPanel.children = [...rightPanel.children, {
				id: "search",
				type: WorkspaceLayoutType.Component,
				content: react.cloneElement(elementsSearchPanel, {
					view,
					editor
				}),
				heading: "Search in diagram"
			}];
			return rightPanel;
		}
		render() {
			const paper = {
				id: "paper",
				type: WorkspaceLayoutType.Component,
				content: /* @__PURE__ */ react.createElement("div", {
					className: "graph-explorer__main-panel",
					style: {
						flex: "1 1 0px",
						width: "100%"
					}
				}, /* @__PURE__ */ react.createElement(PaperArea, {
					ref: (el) => {
						this.paperArea = el;
					},
					view: this.props.view,
					zoomOptions: this.props.zoomOptions,
					hideScrollBars: this.props.hideScrollBars,
					watermarkSvg: this.props.watermarkSvg,
					watermarkUrl: this.props.watermarkUrl,
					onDragDrop: this.onDropOnPaper,
					onZoom: this.props.onZoom
				}))
			};
			const workspaceLayout = this.props.hidePanels ? paper : {
				type: WorkspaceLayoutType.Row,
				children: [
					this.getLeftPanelLayout(),
					paper,
					this.getRightPanelLayout()
				]
			};
			return /* @__PURE__ */ react.createElement(WorkspaceContext.Provider, { value: { workspace: {
				editor: this.props.editor,
				triggerWorkspaceEvent: this.triggerWorkspaceEvent
			} } }, /* @__PURE__ */ react.createElement("div", {
				ref: (e) => {
					this.element = e;
				},
				className: "graph-explorer"
			}, /* @__PURE__ */ react.createElement("div", { className: "graph-explorer__workspace" }, /* @__PURE__ */ react.createElement(WorkspaceLayout, {
				layout: workspaceLayout,
				_onStartResize: (direction) => this.untilMouseUp({
					preventTextSelection: true,
					verticalResizing: direction === "vertical",
					horizontalResizing: direction === "horizontal"
				})
			}))));
		}
		componentDidMount() {
			document.addEventListener("mouseup", this.onDocumentMouseUp);
			this.addToolbarWidgetToPaper();
		}
		componentWillUnmount() {
			document.removeEventListener("mouseup", this.onDocumentMouseUp);
			this.cancellation.abort();
		}
		preventTextSelection() {
			this.untilMouseUp({ preventTextSelection: true });
		}
		untilMouseUp(params) {
			this.untilMouseUpClasses = [];
			if (params.preventTextSelection) this.untilMouseUpClasses.push("graph-explorer--unselectable");
			if (params.horizontalResizing) this.untilMouseUpClasses.push("graph-explorer--horizontal-resizing");
			if (params.verticalResizing) this.untilMouseUpClasses.push("graph-explorer--vertical-resizing");
			for (const className of this.untilMouseUpClasses) this.element.classList.add(className);
		}
	};
	var ToolbarWidget = class extends react.Component {
		render() {
			return /* @__PURE__ */ react.createElement("div", { className: "graph-explorer__toolbar-widget" }, this.props.children);
		}
	};
	function forceNonReactExecutionContext() {
		return Promise.resolve();
	}
	function getViewportCenterInPaperCoords(paperArea) {
		const viewport = paperArea.getAreaMetrics();
		return paperArea.clientToPaperCoords(viewport.clientWidth / 2, viewport.clientHeight / 2);
	}
	function centerElementToPosition(element, center) {
		const position = {
			x: center.x - element.size.width / 2,
			y: center.y - element.size.height / 2
		};
		element.setPosition(position);
	}
	function tryParseDefaultDragAndDropData(e) {
		const tryGetIri = (type, decode = false) => {
			try {
				const iriString = e.dataTransfer.getData(type);
				if (!iriString) return;
				let iris;
				try {
					iris = JSON.parse(iriString);
				} catch (_e) {
					iris = [decode ? decodeURI(iriString) : iriString];
				}
				return iris.length === 0 ? void 0 : iris;
			} catch (_e) {
				return;
			}
		};
		return tryGetIri("application/x-graph-explorer-elements") || tryGetIri("text/uri-list", true) || tryGetIri("text") || [];
	}
	//#endregion
	//#region src/graph-explorer/workspace/workspace.ts
	var GRAPH_EXPLORER_WEBSITE = "https://graph-explorer.org/";
	var GRAPH_EXPLORER_LOGO_SVG = void 0;
	var Workspace = class extends react.Component {
		static {
			this.defaultProps = {
				hideTutorial: true,
				collapseNavigator: false,
				leftPanelInitiallyOpen: true,
				rightPanelInitiallyOpen: false,
				languages: [{
					code: "en",
					label: "English"
				}, {
					code: "ru",
					label: "Russian"
				}],
				language: "en"
			};
		}
		constructor(props) {
			super(props);
			this.listener = new EventObserver();
			this._watermarkSvg = GRAPH_EXPLORER_LOGO_SVG;
			this._watermarkUrl = GRAPH_EXPLORER_WEBSITE;
			this.zoomToFit = () => {
				this.markup.paperArea.zoomToFit();
			};
			this.zoomToFitRect = (bbox) => {
				this.markup.paperArea.zoomToFitRect(bbox);
			};
			this.clearAll = () => {
				this.editor.removeItems([...this.model.elements]);
			};
			this.forceLayout = () => {
				const batch = this.model.history.startBatch("Force layout");
				batch.history.registerToUndo(RestoreGeometry.capture(this.model));
				applyLayout(this.model, forceLayout({ model: this.model }));
				for (const link of this.model.links) link.setVertices([]);
				batch.store();
			};
			this.exportSvg = (fileName) => {
				this.markup.paperArea.exportSVG().then((svg) => {
					fileName = fileName || "diagram.svg";
					(0, file_saverjs.default)(new Blob(["<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + svg], { type: "image/svg+xml" }), fileName);
				});
			};
			this.exportPng = (fileName) => {
				fileName = fileName || "diagram.png";
				this.markup.paperArea.exportPNG({ backgroundColor: "white" }).then((dataUri) => {
					(0, file_saverjs.default)(dataURLToBlob(dataUri), fileName);
				});
			};
			this.undo = () => {
				this.model.history.undo();
			};
			this.redo = () => {
				this.model.history.redo();
			};
			this.zoomBy = (value) => {
				this.markup.paperArea.zoomBy(value);
			};
			this.zoomIn = () => {
				this.markup.paperArea.zoomIn();
			};
			this.zoomOut = () => {
				this.markup.paperArea.zoomOut();
			};
			this.print = () => {
				this.markup.paperArea.exportSVG().then((svg) => {
					const printWindow = window.open("", void 0, "width=1280,height=720");
					printWindow.document.write(svg);
					printWindow.document.close();
					printWindow.print();
				});
			};
			this.changeLanguage = (language) => {
				const { onLanguageChange } = this.props;
				if (onLanguageChange) onLanguageChange(language);
				else {
					this.view.setLanguage(language);
					this.forceUpdate();
				}
			};
			this.centerTo = (paperPosition) => {
				this.markup.paperArea.centerTo(paperPosition);
			};
			const { hideHalo, history, viewOptions = {}, metadataApi, validationApi, propertyEditor, elementTemplateResolver, linkTemplateResolver, typeStyleResolver, selectLabelLanguage } = this.props;
			const { linkRouter, onIriClick, disableDefaultHalo, suggestProperties, groupBy } = viewOptions;
			this.model = new AsyncModel(history || new NonRememberingHistory(), groupBy || []);
			this.view = new DiagramView(this.model, {
				elementTemplateResolver,
				linkTemplateResolver,
				typeStyleResolver,
				selectLabelLanguage,
				linkRouter,
				onIriClick
			});
			this.editor = new EditorController({
				model: this.model,
				view: this.view,
				disableHalo: hideHalo || disableDefaultHalo,
				suggestProperties,
				validationApi,
				propertyEditor
			});
			this.editor.setMetadataApi(metadataApi);
			this.view.setLanguage(this.props.language);
			this.state = {};
		}
		_getPaperArea() {
			return this.markup ? this.markup.paperArea : void 0;
		}
		_setWatermark(watermarkSvg, watermarkUrl) {
			this._watermarkSvg = watermarkSvg;
			this._watermarkUrl = watermarkUrl;
			this.forceUpdate();
		}
		render() {
			const { hidePanels, hideToolbar, metadataApi, hideScrollBars, onWorkspaceEvent, _elementsSearchPanel } = this.props;
			return (0, react.createElement)(WorkspaceMarkup, {
				ref: (markup) => {
					this.markup = markup;
				},
				hidePanels,
				hideToolbar,
				hideScrollBars,
				model: this.model,
				view: this.view,
				editor: this.editor,
				metadataApi,
				leftPanelInitiallyOpen: this.props.leftPanelInitiallyOpen,
				rightPanelInitiallyOpen: this.props.rightPanelInitiallyOpen,
				searchCriteria: this.state.criteria,
				onSearchCriteriaChanged: (criteria) => this.setState({ criteria }),
				zoomOptions: this.props.zoomOptions,
				onZoom: this.props.onZoom,
				isLeftPanelOpen: this.props.leftPanelInitiallyOpen,
				isRightPanelOpen: this.props.rightPanelInitiallyOpen,
				toolbar: (0, react.createElement)(ToolbarWrapper, { workspace: this }),
				onWorkspaceEvent,
				watermarkSvg: this._watermarkSvg,
				watermarkUrl: this._watermarkUrl,
				elementsSearchPanel: _elementsSearchPanel
			});
		}
		componentDidMount() {
			const { onWorkspaceEvent } = this.props;
			this.editor._initializePaperComponents(this.markup.paperArea);
			this.updateNavigator(!this.props.hideNavigator);
			this.listener.listen(this.model.events, "loadingSuccess", () => {
				this.view.performSyncUpdate();
				this.markup.paperArea.centerContent();
			});
			this.listener.listen(this.model.events, "elementEvent", ({ key: _key, data }) => {
				if (!data.requestedAddToFilter) return;
				const { source, linkType, direction } = data.requestedAddToFilter;
				this.setState({ criteria: {
					refElement: source,
					refElementLink: linkType,
					linkDirection: direction
				} });
				if (onWorkspaceEvent) onWorkspaceEvent(WorkspaceEventKey.searchUpdateCriteria);
			});
			this.listener.listen(this.markup.paperArea.events, "pointerUp", (e) => {
				if (this.props.onPointerUp) this.props.onPointerUp(e);
			});
			this.listener.listen(this.markup.paperArea.events, "pointerMove", (e) => {
				if (this.props.onPointerMove) this.props.onPointerMove(e);
			});
			this.listener.listen(this.markup.paperArea.events, "pointerDown", (e) => {
				if (this.props.onPointerDown) this.props.onPointerDown(e);
			});
			if (onWorkspaceEvent) {
				this.listener.listen(this.editor.events, "changeSelection", () => onWorkspaceEvent(WorkspaceEventKey.editorChangeSelection));
				this.listener.listen(this.editor.events, "toggleDialog", () => onWorkspaceEvent(WorkspaceEventKey.editorToggleDialog));
				this.listener.listen(this.editor.events, "addElements", () => onWorkspaceEvent(WorkspaceEventKey.editorAddElements));
			}
		}
		componentDidUpdate(nextProps) {
			if (Boolean(nextProps.onLanguageChange) && nextProps.language !== this.view.getLanguage()) this.view.setLanguage(nextProps.language);
			if (nextProps.metadataApi !== this.editor.metadataApi) this.editor.setMetadataApi(nextProps.metadataApi);
			if (nextProps.hideNavigator !== this.props.hideNavigator) this.updateNavigator(!nextProps.hideNavigator);
		}
		componentWillUnmount() {
			this.listener.stopListening();
			this.view.dispose();
		}
		updateNavigator(showNavigator) {
			if (showNavigator) {
				const widget = (0, react.createElement)(Navigator, {
					view: this.view,
					expanded: !this.props.collapseNavigator
				});
				this.view.setPaperWidget({
					key: "navigator",
					widget,
					attachment: WidgetAttachment.Viewport
				});
			} else this.view.setPaperWidget({
				key: "navigator",
				widget: void 0,
				attachment: WidgetAttachment.Viewport
			});
		}
		getModel() {
			return this.model;
		}
		getDiagram() {
			return this.view;
		}
		getEditor() {
			return this.editor;
		}
		preventTextSelectionUntilMouseUp() {
			this.markup.preventTextSelection();
		}
		showWaitIndicatorWhile(operation) {
			this.editor.setSpinner({});
			if (operation) operation.then(() => {
				this.editor.setSpinner(void 0);
			}).catch((error) => {
				console.error(error);
				this.editor.setSpinner({
					statusText: "Unknown error occured",
					errorOccured: true
				});
			});
		}
	};
	var ToolbarWrapper = class extends react.Component {
		constructor(..._args) {
			super(..._args);
			this.listener = new EventObserver();
		}
		render() {
			const { workspace } = this.props;
			const view = workspace.getDiagram();
			const editor = workspace.getEditor();
			const { languages, onSaveDiagram, onPersistChanges, hidePanels, toolbar } = workspace.props;
			const canPersistChanges = onPersistChanges ? !AuthoringState.isEmpty(editor.authoringState) : void 0;
			const canSaveDiagram = !canPersistChanges;
			const defaultToolbarProps = {
				onZoomIn: workspace.zoomIn,
				onZoomOut: workspace.zoomOut,
				onZoomToFit: workspace.zoomToFit,
				onPrint: workspace.print,
				onExportSVG: workspace.exportSvg,
				onExportPNG: workspace.exportPng,
				canSaveDiagram,
				onSaveDiagram: onSaveDiagram ? () => onSaveDiagram(workspace) : void 0,
				canPersistChanges,
				onPersistChanges: onPersistChanges ? () => onPersistChanges(workspace) : void 0,
				onForceLayout: () => {
					workspace.forceLayout();
					workspace.getDiagram().performSyncUpdate();
					workspace.zoomToFit();
				},
				onClearAll: workspace.clearAll,
				languages,
				selectedLanguage: view.getLanguage(),
				onChangeLanguage: workspace.changeLanguage,
				hidePanels
			};
			if (toolbar) return (0, react.cloneElement)(toolbar, {
				...defaultToolbarProps,
				...toolbar.props
			});
			else return (0, react.createElement)(DefaultToolbar, defaultToolbarProps);
		}
		componentDidMount() {
			const { workspace } = this.props;
			const editor = workspace.getEditor();
			const view = workspace.getDiagram();
			this.listener.listen(editor.events, "changeAuthoringState", () => {
				this.forceUpdate();
			});
			this.listener.listen(view.events, "changeLanguage", () => {
				this.forceUpdate();
			});
		}
		componentWillUnmount() {
			this.listener.stopListening();
		}
	};
	function renderTo(workspace, container, props) {
		(0, react_dom_client.createRoot)(container).render((0, react.createElement)(workspace, props));
	}
	//#endregion
	//#region src/graph-explorer/internalApi.ts
	var internalApi_exports = /* @__PURE__ */ __exportAll({
		BatchingScheduler: () => BatchingScheduler,
		BufferingQueue: () => BufferingQueue,
		Cancellation: () => Cancellation,
		CancellationToken: () => CancellationToken,
		CancelledError: () => CancelledError,
		Debouncer: () => Debouncer,
		HashMap: () => HashMap,
		HtmlSpinner: () => HtmlSpinner,
		KeyedObserver: () => KeyedObserver,
		LINK_SHOW_IRI: () => LINK_SHOW_IRI,
		ListElementView: () => ListElementView,
		MoveDirection: () => MoveDirection,
		OrderedMap: () => OrderedMap,
		Paper: () => Paper,
		PaperArea: () => PaperArea,
		PaperAreaContext: () => PaperAreaContext,
		SearchResults: () => SearchResults,
		Spinner: () => Spinner,
		TemplateProperties: () => TemplateProperties,
		TransformedSvgCanvas: () => TransformedSvgCanvas,
		WorkspaceContext: () => WorkspaceContext,
		animateInterval: () => animateInterval,
		biasFreePadded: () => biasFreePadded,
		cloneMap: () => cloneMap,
		cloneSet: () => cloneSet,
		delay: () => delay,
		easeInOutBezier: () => easeInOutBezier,
		getContentFittingBox: () => getContentFittingBox,
		getContentFittingBoxForLayout: () => getContentFittingBoxForLayout,
		getOrCreateArrayInMap: () => getOrCreateArrayInMap,
		getOrCreateSetInMap: () => getOrCreateSetInMap,
		groupForceLayout: () => groupForceLayout,
		groupRemoveOverlaps: () => groupRemoveOverlaps,
		highlightSubstring: () => highlightSubstring,
		isEmptyMap: () => isEmptyMap,
		makeMoveComparator: () => makeMoveComparator,
		objectValues: () => objectValues,
		observeElementTypes: () => observeElementTypes,
		observeLinkTypes: () => observeLinkTypes,
		observeProperties: () => observeProperties,
		padded: () => padded,
		paneFromPaperCoords: () => paneFromPaperCoords,
		paneTopLeft: () => paneTopLeft,
		paperFromPaneCoords: () => paperFromPaneCoords,
		startDragElements: () => startDragElements,
		totalPaneSize: () => totalPaneSize
	});
	//#endregion
	exports.AsyncModel = AsyncModel;
	exports.AuthoredEntity = AuthoredEntity;
	exports.AuthoringKind = AuthoringKind;
	exports.AuthoringState = AuthoringState;
	exports.Cancellation = Cancellation;
	exports.CancellationToken = CancellationToken;
	exports.CancelledError = CancelledError;
	exports.Command = Command;
	exports.CompositeDataProvider = CompositeDataProvider;
	exports.DBPediaSettings = DBPediaSettings;
	exports.DIAGRAM_CONTEXT_URL_V1 = DIAGRAM_CONTEXT_URL_V1;
	exports.DefaultElementTemplate = DefaultElementTemplate;
	exports.DefaultElementTemplateBundle = DefaultElementTemplateBundle;
	exports.DefaultToolbar = DefaultToolbar;
	exports.DemoDataProvider = DemoDataProvider;
	exports.DiagramModel = DiagramModel;
	exports.DiagramView = DiagramView;
	exports.DraggableHandle = DraggableHandle;
	exports.EditorController = EditorController;
	exports.Element = Element$1;
	exports.EmbeddedLayer = EmbeddedLayer;
	exports.EventObserver = EventObserver;
	exports.EventSource = EventSource;
	exports.GraphBuilder = GraphBuilder;
	exports.GroupTemplate = GroupTemplate;
	Object.defineProperty(exports, "InternalApi", {
		enumerable: true,
		get: function() {
			return internalApi_exports;
		}
	});
	exports.IriClickIntent = IriClickIntent;
	exports.Link = Link;
	exports.LinkDirection = LinkDirection;
	exports.LinkVertex = LinkVertex;
	exports.NonRememberingHistory = NonRememberingHistory;
	exports.OWLRDFSSettings = OWLRDFSSettings;
	exports.OWLRDFSSettingsOverride = OWLRDFSSettingsOverride;
	exports.OWLStatsSettings = OWLStatsSettings;
	exports.PLACEHOLDER_ELEMENT_TYPE = PLACEHOLDER_ELEMENT_TYPE;
	exports.PLACEHOLDER_LINK_TYPE = PLACEHOLDER_LINK_TYPE;
	exports.QLeverSettings = QLeverSettings;
	exports.RDFSettings = RDFSettings;
	exports.Rect = Rect;
	exports.RenderingLayer = RenderingLayer;
	exports.RestoreGeometry = RestoreGeometry;
	exports.SparqlDataProvider = SparqlDataProvider;
	exports.SparqlGraphBuilder = SparqlGraphBuilder;
	exports.SparqlQueryMethod = SparqlQueryMethod;
	exports.StandardTemplate = StandardTemplate;
	exports.ValidationState = ValidationState;
	exports.Vector = Vector;
	exports.WidgetAttachment = WidgetAttachment;
	exports.WikidataSettings = WikidataSettings;
	exports.Workspace = Workspace;
	exports.WorkspaceEventKey = WorkspaceEventKey;
	exports.WorkspaceLayout = WorkspaceLayout;
	exports.WorkspaceLayoutType = WorkspaceLayoutType;
	exports.applyLayout = applyLayout;
	exports.boundsOf = boundsOf;
	exports.calculateLayout = calculateLayout;
	exports.computeGrouping = computeGrouping;
	exports.computePolyline = computePolyline;
	exports.computePolylineLength = computePolylineLength;
	exports.convertToSerializedDiagram = convertToSerializedDiagram;
	exports.executeSparqlConstruct = executeSparqlConstruct;
	exports.executeSparqlQuery = executeSparqlQuery;
	exports.findElementAtPoint = findElementAtPoint;
	exports.findNearestSegmentIndex = findNearestSegmentIndex;
	exports.forceLayout = forceLayout;
	exports.getContentFittingBox = getContentFittingBox;
	exports.getPointAlongPolyline = getPointAlongPolyline;
	exports.hashLink = hashLink;
	exports.isIriProperty = isIriProperty;
	exports.isLinkConnectedToElement = isLinkConnectedToElement;
	exports.isLiteralProperty = isLiteralProperty;
	exports.isPolylineEqual = isPolylineEqual;
	exports.makeGraphItems = makeGraphItems;
	exports.makeLayout = makeLayout;
	exports.makeLayoutData = makeLayoutData;
	exports.makeSerializedDiagram = makeSerializedDiagram;
	exports.removeOverlaps = removeOverlaps;
	exports.renderTo = renderTo;
	exports.requestElementData = requestElementData;
	exports.restoreLinksBetweenElements = restoreLinksBetweenElements;
	exports.sameElement = sameElement;
	exports.sameLink = sameLink;
	exports.setElementData = setElementData;
	exports.setElementExpanded = setElementExpanded;
	exports.setLinkData = setLinkData;
});

//# sourceMappingURL=graph-explorer.js.map