@aceshooting/lyra-ui 11.1.0 → 12.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +456 -0
- package/README.md +19 -8
- package/custom-elements.json +1 -1
- package/dist/all.d.ts +1 -0
- package/dist/all.js +1 -1
- package/dist/components/agent-tools/activity-feed/activity-feed.class.js +1 -1
- package/dist/components/agent-tools/agent-eval-dashboard/agent-eval-dashboard.class.js +1 -1
- package/dist/components/agent-tools/agent-run/agent-run.class.js +1 -1
- package/dist/components/agent-tools/agent-trace/agent-trace.class.js +1 -1
- package/dist/components/agent-tools/browser-frame/browser-frame.class.js +1 -1
- package/dist/components/agent-tools/commit-card/commit-card.class.js +1 -1
- package/dist/components/agent-tools/span-waterfall/span-waterfall.class.js +1 -1
- package/dist/components/agent-tools/task-list/task-list.class.js +2 -2
- package/dist/components/agent-tools/test-results/test-results.class.js +1 -1
- package/dist/components/agent-tools/thinking-panel/thinking-panel.class.js +1 -1
- package/dist/components/agent-tools/tool-call-chip/tool-call-chip.class.js +2 -2
- package/dist/components/agent-tools/tool-param-form/tool-param-form.class.d.ts +1 -0
- package/dist/components/agent-tools/tool-param-form/tool-param-form.class.js +1 -1
- package/dist/components/agent-tools/tool-result-dialog/tool-result-dialog.class.js +2 -2
- package/dist/components/agent-tools/trace-tree/trace-tree.class.js +2 -2
- package/dist/components/charts/chart/bar-chart.class.js +1 -1
- package/dist/components/charts/chart/bubble-chart.class.js +1 -1
- package/dist/components/charts/chart/chart.class.d.ts +13 -1
- package/dist/components/charts/chart/chart.class.js +1 -1
- package/dist/components/charts/chart/doughnut-chart.class.js +1 -1
- package/dist/components/charts/chart/histogram.class.js +1 -1
- package/dist/components/charts/chart/line-chart.class.js +1 -1
- package/dist/components/charts/chart/pie-chart.class.js +1 -1
- package/dist/components/charts/chart/polar-area-chart.class.js +1 -1
- package/dist/components/charts/chart/radar-chart.class.js +1 -1
- package/dist/components/charts/chart/scatter-chart.class.js +1 -1
- package/dist/components/conversation/chat-message/chat-message.class.js +2 -2
- package/dist/components/conversation/chat-viewport/chat-viewport.class.js +1 -1
- package/dist/components/conversation/model-select/model-select.class.d.ts +1 -0
- package/dist/components/conversation/model-select/model-select.class.js +1 -1
- package/dist/components/conversation/usage-badge/usage-badge.class.js +1 -1
- package/dist/components/conversation/voice-picker/voice-picker.class.d.ts +1 -0
- package/dist/components/conversation/voice-picker/voice-picker.class.js +1 -1
- package/dist/components/data/funnel/funnel.class.d.ts +92 -0
- package/dist/components/data/funnel/funnel.class.js +25 -0
- package/dist/components/data/funnel/funnel.d.ts +1 -0
- package/dist/components/data/funnel/funnel.js +1 -0
- package/dist/components/data/funnel/funnel.styles.d.ts +1 -0
- package/dist/components/data/funnel/funnel.styles.js +127 -0
- package/dist/components/data/graph-query-builder/graph-query-builder.class.d.ts +1 -0
- package/dist/components/data/graph-query-builder/graph-query-builder.class.js +1 -1
- package/dist/components/data/heatmap/heatmap.class.d.ts +222 -5
- package/dist/components/data/heatmap/heatmap.class.js +30 -22
- package/dist/components/data/heatmap/heatmap.styles.js +36 -0
- package/dist/components/data/index.d.ts +1 -0
- package/dist/components/data/index.js +1 -1
- package/dist/components/data/table/table.class.js +1 -1
- package/dist/components/forms/checkbox/checkbox.class.d.ts +1 -0
- package/dist/components/forms/checkbox/checkbox.class.js +1 -1
- package/dist/components/forms/checkbox-group/checkbox-group.class.d.ts +1 -0
- package/dist/components/forms/checkbox-group/checkbox-group.class.js +1 -1
- package/dist/components/forms/combobox/combobox.class.d.ts +1 -0
- package/dist/components/forms/combobox/combobox.class.js +1 -1
- package/dist/components/forms/date-picker/date-input.class.d.ts +23 -0
- package/dist/components/forms/date-picker/date-input.class.js +1 -1
- package/dist/components/forms/locale-picker/locale-picker.class.d.ts +1 -0
- package/dist/components/forms/locale-picker/locale-picker.class.js +1 -1
- package/dist/components/forms/radio/radio-group.class.d.ts +1 -0
- package/dist/components/forms/radio/radio-group.class.js +1 -1
- package/dist/components/forms/radio/radio.class.d.ts +1 -0
- package/dist/components/forms/radio/radio.class.js +1 -1
- package/dist/components/forms/rubric-form/rubric-form.class.d.ts +1 -0
- package/dist/components/forms/rubric-form/rubric-form.class.js +1 -1
- package/dist/components/forms/select/select.class.d.ts +1 -0
- package/dist/components/forms/select/select.class.js +1 -1
- package/dist/components/forms/slider/slider.class.d.ts +1 -0
- package/dist/components/forms/slider/slider.class.js +1 -1
- package/dist/components/forms/switch/switch.class.d.ts +1 -0
- package/dist/components/forms/switch/switch.class.js +1 -1
- package/dist/components/forms/time-range/time-range.class.d.ts +1 -0
- package/dist/components/forms/time-range/time-range.class.js +1 -1
- package/dist/components/forms/token-input/token-input.class.d.ts +1 -0
- package/dist/components/forms/token-input/token-input.class.js +1 -1
- package/dist/components/layout/app-rail/app-rail-item.class.d.ts +16 -0
- package/dist/components/layout/app-rail/app-rail-item.class.js +4 -4
- package/dist/components/layout/filter-bar/filter-bar.class.d.ts +32 -3
- package/dist/components/layout/filter-bar/filter-bar.class.js +2 -1
- package/dist/components/layout/widget/widget.class.d.ts +16 -0
- package/dist/components/layout/widget/widget.class.js +2 -2
- package/dist/components/lr-funnel.d.ts +1 -0
- package/dist/components/lr-funnel.js +1 -0
- package/dist/components/media/attachment-chip/attachment-chip.class.js +2 -2
- package/dist/components/media/attachment-trigger/attachment-trigger.class.js +2 -2
- package/dist/components/media/file-icon/file-icon.class.js +1 -1
- package/dist/components/media/file-input/file-input.class.d.ts +1 -0
- package/dist/components/media/file-input/file-input.class.js +1 -1
- package/dist/components/media/flag/flag-peer-bulk-standard.d.ts +25 -0
- package/dist/components/media/flag/flag-peer-bulk-standard.js +1 -0
- package/dist/components/media/flag/flag-peer-bulk.d.ts +12 -0
- package/dist/components/media/flag/flag-peer-bulk.js +1 -0
- package/dist/components/media/flag/flag.class.d.ts +36 -0
- package/dist/components/media/flag/flag.class.js +2 -2
- package/dist/components/media/map/map.class.d.ts +196 -15
- package/dist/components/media/map/map.class.js +1 -1
- package/dist/components/overlays/chip/chip-group.class.d.ts +16 -0
- package/dist/components/overlays/chip/chip-group.class.js +10 -3
- package/dist/components/retrieval/citation-badge/citation-badge.class.js +1 -1
- package/dist/components/retrieval/claim-evidence/claim-evidence.class.js +1 -1
- package/dist/components/retrieval/grounding-summary/grounding-summary.class.js +2 -2
- package/dist/components/retrieval/retrieval-trace/retrieval-trace.class.js +1 -1
- package/dist/components/viewers/archive-viewer/archive-viewer.class.js +1 -1
- package/dist/components/viewers/contact-viewer/contact-viewer.class.js +1 -1
- package/dist/components/viewers/document-compare/document-compare.class.js +1 -1
- package/dist/components/viewers/ebook-viewer/ebook-viewer.class.js +1 -1
- package/dist/components/viewers/email-viewer/email-viewer.class.js +2 -2
- package/dist/custom-elements-jsx.d.ts +12 -4
- package/dist/events.d.ts +7 -0
- package/dist/internal/autoloader-manifest.js +1 -1
- package/dist/internal/autoloader-tags.d.ts +1 -1
- package/dist/internal/autoloader-tags.js +1 -1
- package/dist/internal/form-associated.d.ts +1 -0
- package/dist/internal/form-associated.js +1 -1
- package/dist/internal/form-control-labels.js +1 -1
- package/dist/internal/lyra-element.d.ts +7 -1
- package/dist/internal/lyra-element.js +1 -1
- package/dist/internal/package-metadata.d.ts +1 -1
- package/dist/internal/package-metadata.js +1 -1
- package/dist/internal/root-registration-allowlist.d.ts +1 -1
- package/dist/internal/root-registration-allowlist.js +1 -1
- package/dist/lyra.d.ts +4 -2
- package/dist/lyra.js +1 -1
- package/dist/ssr/all.d.ts +1 -0
- package/dist/ssr/all.js +1 -1
- package/dist/ssr.d.ts +4 -4
- package/dist/styles/tokens-root.css +488 -0
- package/dist/svelte.d.ts +13 -4
- package/dist/vue.d.ts +12 -4
- package/llms/components/lr-app-rail-item.md +8 -1
- package/llms/components/lr-app-rail.md +6 -0
- package/llms/components/lr-chip-group.md +7 -0
- package/llms/components/lr-chip.md +7 -0
- package/llms/components/lr-date-input.md +19 -1
- package/llms/components/lr-date-picker.md +19 -1
- package/llms/components/lr-filter-bar.md +50 -1
- package/llms/components/lr-flag.md +38 -1
- package/llms/components/lr-funnel.md +122 -0
- package/llms/components/lr-heatmap.md +64 -8
- package/llms/components/lr-map.md +65 -8
- package/llms/components/lr-widget.md +7 -1
- package/llms/index.md +3 -2
- package/llms/peers.md +2 -2
- package/llms/shared.md +129 -1
- package/llms-full.txt +526 -20
- package/llms.txt +1 -1
- package/package.json +28 -9
- package/vscode-css-data.json +42 -0
- package/vscode-html-data.json +96 -17
- package/web-types.json +32714 -317
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { LyraEventDetailSnapshot } from '../../../internal/lyra-element.js';
|
|
2
2
|
import { type TemplateResult, type PropertyValues } from 'lit';
|
|
3
3
|
import { LyraElement } from '../../../internal/lyra-element.js';
|
|
4
|
+
import '../../../internal/form-control-labels.js';
|
|
4
5
|
import { type FormOwnerValue } from '../../../internal/form-associated.js';
|
|
5
6
|
/** Traversal direction relative to the matched node(s): `'out'` (outgoing edges), `'in'`
|
|
6
7
|
* (incoming edges), or `'both'`. */
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var __decorate=function(decorators,target,key,desc){var c=arguments.length,r=c<3?target:desc===null?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;i>=0;i--)(d=decorators[i])&&(r=(c<3?d(r):c>3?d(target,key,r):d(target,key))||r);return c>3&&r&&Object.defineProperty(target,key,r),r};import{html,nothing}from"lit";import{property,state}from"lit/decorators.js";import{LyraElement}from"../../../internal/lyra-element.js";import{closeIcon}from"../../../internal/icons.js";import{AnchoredValidityController,VALIDITY_ANCHOR}from"../../../internal/anchored-validity.js";import{syncValidityStates}from"../../../internal/custom-states.js";import{finiteInteger}from"../../../internal/numbers.js";import{getNumberFormat}from"../../../internal/intl-cache.js";import{nextId}from"../../../internal/a11y.js";import{deepActiveElementIn}from"../../../internal/active-element.js";import{styles}from"./graph-query-builder.styles.js";import{attachInternalsSafely}from"../../../internal/element-internals.js";import{getFormOwner,installCustomErrorProperty,isBarredFromValidation,setFormOwner}from"../../../internal/form-associated.js";import{installInvalidEventAlias}from"../../../internal/invalid-event-alias.js";import{LYRA_DEFAULT_fieldRequired,LYRA_DEFAULT_graphQueryBuilderLabel,LYRA_DEFAULT_graphQueryDeleteWithContext,LYRA_DEFAULT_graphQueryDirectionLabel,LYRA_DEFAULT_graphQueryEndLabel,LYRA_DEFAULT_graphQueryHopRangeInvalid,LYRA_DEFAULT_graphQueryLoadWithContext,LYRA_DEFAULT_graphQueryMaxHopsLabel,LYRA_DEFAULT_graphQueryMinHopsLabel,LYRA_DEFAULT_graphQueryNodeTypeLabel,LYRA_DEFAULT_graphQueryRelationshipTypeLabel,LYRA_DEFAULT_graphQueryRun,LYRA_DEFAULT_graphQuerySaveButton,LYRA_DEFAULT_graphQuerySaveNameLabel,LYRA_DEFAULT_graphQuerySavedQueriesLabel,LYRA_DEFAULT_graphQueryStartLabel,LYRA_DEFAULT_neighborDirectionBoth,LYRA_DEFAULT_neighborDirectionIn,LYRA_DEFAULT_neighborDirectionOut,LYRA_DEFAULT_noData,LYRA_DEFAULT_select}from"../../../internal/default-strings.generated.js";const MAX_TYPES=500,MAX_SAVED_QUERIES=200,MAX_TEXT=256,EMPTY_STRINGS=Object.freeze([]),EMPTY_VALUE=Object.freeze({startId:"",endId:"",relationshipTypes:EMPTY_STRINGS,nodeTypes:EMPTY_STRINGS,direction:"both",minHops:1,maxHops:1}),EMPTY_OPTIONS=Object.freeze([]),EMPTY_SAVED=Object.freeze([]);function ownValue(record,key){try{const descriptor=Object.getOwnPropertyDescriptor(record,key);return descriptor&&"value"in descriptor?descriptor.value:void 0}catch{return}}function boundedString(value){return typeof value=="string"?value.slice(0,MAX_TEXT):""}function stringArray(value){return Array.isArray(value)?Object.freeze([...new Set(value.slice(0,MAX_TYPES).filter(entry=>typeof entry=="string").map(entry=>boundedString(entry)).filter(Boolean))]):EMPTY_STRINGS}function normalizeGraphQuery(value){const record=value!==null&&typeof value=="object"&&!Array.isArray(value)?value:EMPTY_VALUE,direction=ownValue(record,"direction");return Object.freeze({startId:boundedString(ownValue(record,"startId")),endId:boundedString(ownValue(record,"endId")),relationshipTypes:stringArray(ownValue(record,"relationshipTypes")),nodeTypes:stringArray(ownValue(record,"nodeTypes")),direction:direction==="out"||direction==="in"||direction==="both"?direction:"both",minHops:finiteInteger(typeof ownValue(record,"minHops")=="number"?ownValue(record,"minHops"):EMPTY_VALUE.minHops,EMPTY_VALUE.minHops,1,20),maxHops:finiteInteger(typeof ownValue(record,"maxHops")=="number"?ownValue(record,"maxHops"):EMPTY_VALUE.maxHops,EMPTY_VALUE.maxHops,1,20)})}function normalizeTypeOptions(value){if(!Array.isArray(value))return EMPTY_OPTIONS;const values=new Set,result=[];for(const candidate of value.slice(0,MAX_TYPES)){if(candidate===null||typeof candidate!="object"||Array.isArray(candidate))continue;const optionValue=boundedString(ownValue(candidate,"value"));if(optionValue.trim().length===0||values.has(optionValue))continue;values.add(optionValue);const label=boundedString(ownValue(candidate,"label"));result.push(Object.freeze({value:optionValue,...label?{label}:{}}))}return Object.freeze(result)}function normalizeSavedQueries(value){if(!Array.isArray(value))return EMPTY_SAVED;const ids=new Set,result=[];for(const candidate of value.slice(0,MAX_SAVED_QUERIES)){if(candidate===null||typeof candidate!="object"||Array.isArray(candidate))continue;const id=boundedString(ownValue(candidate,"id"));id.trim().length===0||ids.has(id)||(ids.add(id),result.push(Object.freeze({id,name:boundedString(ownValue(candidate,"name")),query:normalizeGraphQuery(ownValue(candidate,"query"))})))}return Object.freeze(result)}class LyraGraphQueryBuilder extends LyraElement{static{this.defaultStrings={...super.defaultStrings,fieldRequired:LYRA_DEFAULT_fieldRequired,graphQueryBuilderLabel:LYRA_DEFAULT_graphQueryBuilderLabel,graphQueryDeleteWithContext:LYRA_DEFAULT_graphQueryDeleteWithContext,graphQueryDirectionLabel:LYRA_DEFAULT_graphQueryDirectionLabel,graphQueryEndLabel:LYRA_DEFAULT_graphQueryEndLabel,graphQueryHopRangeInvalid:LYRA_DEFAULT_graphQueryHopRangeInvalid,graphQueryLoadWithContext:LYRA_DEFAULT_graphQueryLoadWithContext,graphQueryMaxHopsLabel:LYRA_DEFAULT_graphQueryMaxHopsLabel,graphQueryMinHopsLabel:LYRA_DEFAULT_graphQueryMinHopsLabel,graphQueryNodeTypeLabel:LYRA_DEFAULT_graphQueryNodeTypeLabel,graphQueryRelationshipTypeLabel:LYRA_DEFAULT_graphQueryRelationshipTypeLabel,graphQueryRun:LYRA_DEFAULT_graphQueryRun,graphQuerySaveButton:LYRA_DEFAULT_graphQuerySaveButton,graphQuerySaveNameLabel:LYRA_DEFAULT_graphQuerySaveNameLabel,graphQuerySavedQueriesLabel:LYRA_DEFAULT_graphQuerySavedQueriesLabel,graphQueryStartLabel:LYRA_DEFAULT_graphQueryStartLabel,neighborDirectionBoth:LYRA_DEFAULT_neighborDirectionBoth,neighborDirectionIn:LYRA_DEFAULT_neighborDirectionIn,neighborDirectionOut:LYRA_DEFAULT_neighborDirectionOut,noData:LYRA_DEFAULT_noData,select:LYRA_DEFAULT_select}}static{this.formAssociated=!0}static{this.styles=[LyraElement.styles,styles]}static{this.immutableEventDetails=Object.freeze(["lr-input","lr-before-query-run","lr-query-run","lr-before-query-save","lr-query-save","lr-before-query-load","lr-query-load"])}static{this.properties={customError:{attribute:"custom-error",reflect:!0,noAccessor:!0},name:{reflect:!0,noAccessor:!0},value:{attribute:!1,noAccessor:!0},disabled:{type:Boolean,reflect:!0,noAccessor:!0}}}get relationshipTypeOptions(){return this._relationshipTypeOptions}set relationshipTypeOptions(value){const previous=this._relationshipTypeOptions;this._relationshipTypeOptions=normalizeTypeOptions(value),this.requestUpdate("relationshipTypeOptions",previous)}get nodeTypeOptions(){return this._nodeTypeOptions}set nodeTypeOptions(value){const previous=this._nodeTypeOptions;this._nodeTypeOptions=normalizeTypeOptions(value),this.requestUpdate("nodeTypeOptions",previous)}get savedQueries(){return this._savedQueries}set savedQueries(value){const previous=this._savedQueries;this._savedQueries=normalizeSavedQueries(value),this.requestUpdate("savedQueries",previous)}constructor(){super(),this._relationshipTypeOptions=EMPTY_OPTIONS,this._nodeTypeOptions=EMPTY_OPTIONS,this._savedQueries=EMPTY_SAVED,this.hopLimit=6,this.label="",this.hint="",this.errorText="",this._errors={},this.touchedFields=new Set,this.saveName="",this.hasHintSlot=!1,this.hasErrorSlot=!1,this.labelId=nextId("graph-query-builder-label"),this.hintId=nextId("graph-query-builder-hint"),this.errorId=nextId("graph-query-builder-error"),this._fieldsetDisabled=!1,this._name="",this._value=EMPTY_VALUE,this.defaultValue=normalizeGraphQuery(EMPTY_VALUE),this.defaultValueCaptured=!1,this._disabled=!1,this.hasInteracted=!1,this.removalFocusGeneration=0,this.onChromeSlotChange=event=>{const slot=event.currentTarget,hasContent=slot.assignedNodes({flatten:!0}).some(node=>node.nodeType===Node.TEXT_NODE?!!node.textContent?.trim():!0);slot.name==="hint"?this.hasHintSlot=hasContent:slot.name==="error"&&(this.hasErrorSlot=hasContent)},this.internals=attachInternalsSafely(this),this.validityController=new AnchoredValidityController(this,this.internals,()=>this[VALIDITY_ANCHOR]()),installCustomErrorProperty(this,()=>this.validityController.customValidityMessage),installInvalidEventAlias(this,init=>this.emit("lr-invalid",null,init)),this.syncFormState()}disconnectedCallback(){this.removalFocusGeneration++,this.pendingRemovalFocus=void 0,super.disconnectedCallback()}get form(){return getFormOwner(this.internals)}set form(owner){setFormOwner(this,owner)}getForm(){return getFormOwner(this.internals)}get labels(){return this.internals.labels}get validity(){return this.internals.validity}get validationMessage(){return this.internals.validationMessage}get willValidate(){return this.internals.willValidate}get value(){return this._value}set value(next){const old=this._value;this._value=normalizeGraphQuery(next),this.syncFormState(),this.requestUpdate("value",old)}get name(){return this._name}set name(next){const old=this._name;this._name=next??"",this._name?this.setAttribute("name",this._name):this.removeAttribute("name"),this.requestUpdate("name",old)}get disabled(){return this._disabled}set disabled(next){const old=this._disabled;this._disabled=!!next,this.toggleAttribute("disabled",this._disabled),this.validityController&&this.syncFormState(),this.requestUpdate("disabled",old)}get effectiveDisabled(){return this.disabled||this._fieldsetDisabled}get errors(){return this.publicValidityErrors()}publicValidityErrors(){const errors={...this._errors};return this.willValidate&&this.validity.customError&&(errors.base=this.validationMessage),Object.freeze(errors)}publishValiditySnapshot(){if(!this.isConnected)return;const valid=!this.willValidate||this.validity.valid,errors=valid?Object.freeze({}):this.publicValidityErrors(),key=JSON.stringify({valid,errors});key!==this.lastValidityKey&&(this.lastValidityKey=key,this.emit("lr-validity-change",Object.freeze({valid,errors})))}[VALIDITY_ANCHOR](){const firstInvalidPart=Object.keys(this._errors)[0];if(!(!firstInvalidPart||!this.renderRoot))return this.renderRoot.querySelector(`[part="${firstInvalidPart}"]`)??void 0}computeValidation(){const errors={},flags={};return this._value.startId.trim()||(errors["start-input"]=this.localize("fieldRequired"),flags.valueMissing=!0),this._value.minHops>this._value.maxHops&&(errors["max-hops"]=this.localize("graphQueryHopRangeInvalid"),flags.rangeUnderflow=!0),{errors,flags}}syncFormState(){const{errors,flags}=this.computeValidation();this._errors=errors;let formValue=null;try{formValue=JSON.stringify(this._value)}catch{formValue=null}if(this.internals.setFormValue(formValue,formValue),this.barredFromValidation||Object.keys(flags).length===0)this.validityController.setValidity({});else{const message=Object.values(errors)[0]??"";this.validityController.setValidity(flags,message)}this.syncValidityCustomStates(),this.publishValiditySnapshot()}get barredFromValidation(){return isBarredFromValidation(this,this.internals)}syncValidityCustomStates(){syncValidityStates(this.internals,{required:!0,hasInteracted:this.hasInteracted,barred:this.barredFromValidation})}checkValidity(){return this.syncFormState(),this.internals.checkValidity()}reportValidity(){return this.hasInteracted=!0,this.syncFormState(),Object.keys(this._errors).length>0&&(this.touchedFields=new Set([...this.touchedFields,...Object.keys(this._errors)])),this.internals.reportValidity()}setCustomValidity(message){this.validityController.setCustomValidity(message??""),this.syncValidityCustomStates(),this.publishValiditySnapshot()}formResetCallback(){this.hasInteracted=!1,this.captureDefaultValue(),this.value=this.defaultValue,this.touchedFields=new Set,this.saveName=""}captureDefaultValue(){this.defaultValueCaptured||(this.defaultValue=normalizeGraphQuery(this._value),this.defaultValueCaptured=!0)}formStateRestoreCallback(state2,_mode){let restored=EMPTY_VALUE;if(typeof state2=="string")try{const parsed=JSON.parse(state2);parsed!==null&&typeof parsed=="object"&&!Array.isArray(parsed)&&(restored=normalizeGraphQuery(parsed))}catch{}this.value=restored}formDisabledCallback(disabled){this._fieldsetDisabled=disabled,this.syncFormState(),this.requestUpdate()}get liveDisabled(){return this.effectiveDisabled||this.matches(":disabled")}focusFirstControl(options){if(!this.renderRoot||this.liveDisabled)return;(this.renderRoot.querySelector('[part="start-input"]')||this.renderRoot.querySelector('[part="end-input"]')||this.renderRoot.querySelector('[part="min-hops"]')||this.renderRoot.querySelector('[part="max-hops"]')||this.renderRoot.querySelector('[part="direction"]')||this.renderRoot.querySelector('[part="save-name-input"]'))?.focus(options)}focus(options){this.focusFirstControl(options)}blur(){const active=deepActiveElementIn(this.shadowRoot);active&&typeof active.blur=="function"&&active.blur()}click(){this.focusFirstControl()}setValue(next){this.effectiveDisabled||(this.hasInteracted=!0,this.value=next,this.emit("lr-input",Object.freeze({value:this._value})))}addRelationshipType(type){!type||this._value.relationshipTypes.includes(type)||this.setValue({...this._value,relationshipTypes:[...this._value.relationshipTypes,type]})}removeRelationshipType(type){this.captureChipRemovalFocus("relationship",type,this._value.relationshipTypes),this.setValue({...this._value,relationshipTypes:this._value.relationshipTypes.filter(t=>t!==type)})}addNodeType(type){!type||this._value.nodeTypes.includes(type)||this.setValue({...this._value,nodeTypes:[...this._value.nodeTypes,type]})}removeNodeType(type){this.captureChipRemovalFocus("node-type",type,this._value.nodeTypes),this.setValue({...this._value,nodeTypes:this._value.nodeTypes.filter(t=>t!==type)})}captureChipRemovalFocus(group,value,selected){const active=this.shadowRoot?.activeElement,expectedPart=group==="relationship"?"relationship-chips":"node-type-chips";if(active?.localName!=="lr-chip"||active.getAttribute("value")!==value||active.closest("lr-chip-group")?.getAttribute("part")!==expectedPart)return;const index=selected.indexOf(value),survivors=selected.filter(candidate=>candidate!==value),targetValue=survivors[Math.min(Math.max(index,0),survivors.length-1)];this.pendingRemovalFocus={kind:"chip",group,targetValue},this.removalFocusGeneration++}markTouched(part){this.hasInteracted=!0,this.syncValidityCustomStates(),!this.touchedFields.has(part)&&(this.touchedFields=new Set(this.touchedFields).add(part))}runQuery(){if(this.effectiveDisabled||!this.reportValidity())return;const detail=()=>Object.freeze({query:normalizeGraphQuery(this._value)});this.emit("lr-before-query-run",detail(),{cancelable:!0}).defaultPrevented||this.emit("lr-query-run",detail())}saveQuery(){if(this.effectiveDisabled)return;const name=this.saveName.trim();if(!name)return;const detail=()=>Object.freeze({name,query:normalizeGraphQuery(this._value)});this.emit("lr-before-query-save",detail(),{cancelable:!0}).defaultPrevented||(this.saveName="",this.emit("lr-query-save",detail()))}loadQuery(item){if(this.effectiveDisabled)return;const detail=()=>Object.freeze({queryId:item.id,query:normalizeGraphQuery(item.query)});this.emit("lr-before-query-load",detail(),{cancelable:!0}).defaultPrevented||(this.setValue({...EMPTY_VALUE,...item.query}),this.emit("lr-query-load",detail()))}deleteQuery(item){if(this.effectiveDisabled)return;const detail=()=>Object.freeze({queryId:item.id});this.emit("lr-before-query-delete",detail(),{cancelable:!0}).defaultPrevented||this.emit("lr-query-delete",detail())}willUpdate(changed){if(super.willUpdate(changed),this.hasUpdated||this.captureDefaultValue(),!changed.has("savedQueries"))return;const active=this.shadowRoot?.activeElement;if(active?.getAttribute("part")!=="saved-delete-button")return;const focusedId=active.closest("[data-query-id]")?.dataset.queryId;if(!focusedId||this.savedQueries.some(item=>item.id===focusedId))return;const index=(changed.get("savedQueries")??[]).findIndex(item=>item.id===focusedId),target=this.savedQueries[Math.min(Math.max(index,0),this.savedQueries.length-1)];this.pendingRemovalFocus={kind:"saved",targetId:target?.id},this.removalFocusGeneration++}updated(changed){super.updated(changed),this.publishValiditySnapshot();const pending=this.pendingRemovalFocus;if(!pending)return;this.pendingRemovalFocus=void 0;const generation=this.removalFocusGeneration;this.scheduleAfterUpdate(()=>{if(!(generation!==this.removalFocusGeneration||!this.isConnected)){if(pending.kind==="chip"){if(pending.targetValue){const part=pending.group==="relationship"?"relationship-chips":"node-type-chips",chip=[...this.shadowRoot?.querySelectorAll(`[part="${part}"] lr-chip`)??[]].find(candidate=>candidate.getAttribute("value")===pending.targetValue);if(chip){chip.focus();return}}const pickerPart=pending.group==="relationship"?"relationship-picker":"node-type-picker";this.shadowRoot?.querySelector(`[part="${pickerPart}"]`)?.focus();return}if(pending.targetId){const action=[...this.shadowRoot?.querySelectorAll("[data-query-id]")??[]].find(candidate=>candidate.dataset.queryId===pending.targetId)?.querySelector('[part="saved-delete-button"]');if(action){action.focus();return}}this.shadowRoot?.querySelector('[part="save-name-input"]')?.focus()}},"graph-query-removal-focus")}hopOptions(){const limit=finiteInteger(this.hopLimit,6,1,20),options=new Set(Array.from({length:limit},(_,i)=>i+1));return options.add(this._value.minHops),options.add(this._value.maxHops),[...options].sort((a,b)=>a-b)}labelForType(options,value){return options.find(o=>o.value===value)?.label??value}renderTypeFilter(kind,options,selected,add,remove,disabled){const pickerPart=kind==="relationship"?"relationship-picker":"node-type-picker",chipsPart=kind==="relationship"?"relationship-chips":"node-type-chips",pickerLabel=kind==="relationship"?this.localize("graphQueryRelationshipTypeLabel"):this.localize("graphQueryNodeTypeLabel"),available=options.filter(o=>!selected.includes(o.value));return html`
|
|
1
|
+
var __decorate=function(decorators,target,key,desc){var c=arguments.length,r=c<3?target:desc===null?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;i>=0;i--)(d=decorators[i])&&(r=(c<3?d(r):c>3?d(target,key,r):d(target,key))||r);return c>3&&r&&Object.defineProperty(target,key,r),r};import{html,nothing}from"lit";import{property,state}from"lit/decorators.js";import{LyraElement}from"../../../internal/lyra-element.js";import"../../../internal/form-control-labels.js";import{closeIcon}from"../../../internal/icons.js";import{AnchoredValidityController,VALIDITY_ANCHOR}from"../../../internal/anchored-validity.js";import{syncValidityStates}from"../../../internal/custom-states.js";import{finiteInteger}from"../../../internal/numbers.js";import{getNumberFormat}from"../../../internal/intl-cache.js";import{nextId}from"../../../internal/a11y.js";import{deepActiveElementIn}from"../../../internal/active-element.js";import{styles}from"./graph-query-builder.styles.js";import{attachInternalsSafely}from"../../../internal/element-internals.js";import{getFormOwner,installCustomErrorProperty,isBarredFromValidation,setFormOwner}from"../../../internal/form-associated.js";import{installInvalidEventAlias}from"../../../internal/invalid-event-alias.js";import{LYRA_DEFAULT_fieldRequired,LYRA_DEFAULT_graphQueryBuilderLabel,LYRA_DEFAULT_graphQueryDeleteWithContext,LYRA_DEFAULT_graphQueryDirectionLabel,LYRA_DEFAULT_graphQueryEndLabel,LYRA_DEFAULT_graphQueryHopRangeInvalid,LYRA_DEFAULT_graphQueryLoadWithContext,LYRA_DEFAULT_graphQueryMaxHopsLabel,LYRA_DEFAULT_graphQueryMinHopsLabel,LYRA_DEFAULT_graphQueryNodeTypeLabel,LYRA_DEFAULT_graphQueryRelationshipTypeLabel,LYRA_DEFAULT_graphQueryRun,LYRA_DEFAULT_graphQuerySaveButton,LYRA_DEFAULT_graphQuerySaveNameLabel,LYRA_DEFAULT_graphQuerySavedQueriesLabel,LYRA_DEFAULT_graphQueryStartLabel,LYRA_DEFAULT_neighborDirectionBoth,LYRA_DEFAULT_neighborDirectionIn,LYRA_DEFAULT_neighborDirectionOut,LYRA_DEFAULT_noData,LYRA_DEFAULT_select}from"../../../internal/default-strings.generated.js";const MAX_TYPES=500,MAX_SAVED_QUERIES=200,MAX_TEXT=256,EMPTY_STRINGS=Object.freeze([]),EMPTY_VALUE=Object.freeze({startId:"",endId:"",relationshipTypes:EMPTY_STRINGS,nodeTypes:EMPTY_STRINGS,direction:"both",minHops:1,maxHops:1}),EMPTY_OPTIONS=Object.freeze([]),EMPTY_SAVED=Object.freeze([]);function ownValue(record,key){try{const descriptor=Object.getOwnPropertyDescriptor(record,key);return descriptor&&"value"in descriptor?descriptor.value:void 0}catch{return}}function boundedString(value){return typeof value=="string"?value.slice(0,MAX_TEXT):""}function stringArray(value){return Array.isArray(value)?Object.freeze([...new Set(value.slice(0,MAX_TYPES).filter(entry=>typeof entry=="string").map(entry=>boundedString(entry)).filter(Boolean))]):EMPTY_STRINGS}function normalizeGraphQuery(value){const record=value!==null&&typeof value=="object"&&!Array.isArray(value)?value:EMPTY_VALUE,direction=ownValue(record,"direction");return Object.freeze({startId:boundedString(ownValue(record,"startId")),endId:boundedString(ownValue(record,"endId")),relationshipTypes:stringArray(ownValue(record,"relationshipTypes")),nodeTypes:stringArray(ownValue(record,"nodeTypes")),direction:direction==="out"||direction==="in"||direction==="both"?direction:"both",minHops:finiteInteger(typeof ownValue(record,"minHops")=="number"?ownValue(record,"minHops"):EMPTY_VALUE.minHops,EMPTY_VALUE.minHops,1,20),maxHops:finiteInteger(typeof ownValue(record,"maxHops")=="number"?ownValue(record,"maxHops"):EMPTY_VALUE.maxHops,EMPTY_VALUE.maxHops,1,20)})}function normalizeTypeOptions(value){if(!Array.isArray(value))return EMPTY_OPTIONS;const values=new Set,result=[];for(const candidate of value.slice(0,MAX_TYPES)){if(candidate===null||typeof candidate!="object"||Array.isArray(candidate))continue;const optionValue=boundedString(ownValue(candidate,"value"));if(optionValue.trim().length===0||values.has(optionValue))continue;values.add(optionValue);const label=boundedString(ownValue(candidate,"label"));result.push(Object.freeze({value:optionValue,...label?{label}:{}}))}return Object.freeze(result)}function normalizeSavedQueries(value){if(!Array.isArray(value))return EMPTY_SAVED;const ids=new Set,result=[];for(const candidate of value.slice(0,MAX_SAVED_QUERIES)){if(candidate===null||typeof candidate!="object"||Array.isArray(candidate))continue;const id=boundedString(ownValue(candidate,"id"));id.trim().length===0||ids.has(id)||(ids.add(id),result.push(Object.freeze({id,name:boundedString(ownValue(candidate,"name")),query:normalizeGraphQuery(ownValue(candidate,"query"))})))}return Object.freeze(result)}class LyraGraphQueryBuilder extends LyraElement{static{this.defaultStrings={...super.defaultStrings,fieldRequired:LYRA_DEFAULT_fieldRequired,graphQueryBuilderLabel:LYRA_DEFAULT_graphQueryBuilderLabel,graphQueryDeleteWithContext:LYRA_DEFAULT_graphQueryDeleteWithContext,graphQueryDirectionLabel:LYRA_DEFAULT_graphQueryDirectionLabel,graphQueryEndLabel:LYRA_DEFAULT_graphQueryEndLabel,graphQueryHopRangeInvalid:LYRA_DEFAULT_graphQueryHopRangeInvalid,graphQueryLoadWithContext:LYRA_DEFAULT_graphQueryLoadWithContext,graphQueryMaxHopsLabel:LYRA_DEFAULT_graphQueryMaxHopsLabel,graphQueryMinHopsLabel:LYRA_DEFAULT_graphQueryMinHopsLabel,graphQueryNodeTypeLabel:LYRA_DEFAULT_graphQueryNodeTypeLabel,graphQueryRelationshipTypeLabel:LYRA_DEFAULT_graphQueryRelationshipTypeLabel,graphQueryRun:LYRA_DEFAULT_graphQueryRun,graphQuerySaveButton:LYRA_DEFAULT_graphQuerySaveButton,graphQuerySaveNameLabel:LYRA_DEFAULT_graphQuerySaveNameLabel,graphQuerySavedQueriesLabel:LYRA_DEFAULT_graphQuerySavedQueriesLabel,graphQueryStartLabel:LYRA_DEFAULT_graphQueryStartLabel,neighborDirectionBoth:LYRA_DEFAULT_neighborDirectionBoth,neighborDirectionIn:LYRA_DEFAULT_neighborDirectionIn,neighborDirectionOut:LYRA_DEFAULT_neighborDirectionOut,noData:LYRA_DEFAULT_noData,select:LYRA_DEFAULT_select}}static{this.formAssociated=!0}static{this.styles=[LyraElement.styles,styles]}static{this.immutableEventDetails=Object.freeze(["lr-input","lr-before-query-run","lr-query-run","lr-before-query-save","lr-query-save","lr-before-query-load","lr-query-load"])}static{this.properties={customError:{attribute:"custom-error",reflect:!0,noAccessor:!0},name:{reflect:!0,noAccessor:!0},value:{attribute:!1,noAccessor:!0},disabled:{type:Boolean,reflect:!0,noAccessor:!0}}}get relationshipTypeOptions(){return this._relationshipTypeOptions}set relationshipTypeOptions(value){const previous=this._relationshipTypeOptions;this._relationshipTypeOptions=normalizeTypeOptions(value),this.requestUpdate("relationshipTypeOptions",previous)}get nodeTypeOptions(){return this._nodeTypeOptions}set nodeTypeOptions(value){const previous=this._nodeTypeOptions;this._nodeTypeOptions=normalizeTypeOptions(value),this.requestUpdate("nodeTypeOptions",previous)}get savedQueries(){return this._savedQueries}set savedQueries(value){const previous=this._savedQueries;this._savedQueries=normalizeSavedQueries(value),this.requestUpdate("savedQueries",previous)}constructor(){super(),this._relationshipTypeOptions=EMPTY_OPTIONS,this._nodeTypeOptions=EMPTY_OPTIONS,this._savedQueries=EMPTY_SAVED,this.hopLimit=6,this.label="",this.hint="",this.errorText="",this._errors={},this.touchedFields=new Set,this.saveName="",this.hasHintSlot=!1,this.hasErrorSlot=!1,this.labelId=nextId("graph-query-builder-label"),this.hintId=nextId("graph-query-builder-hint"),this.errorId=nextId("graph-query-builder-error"),this._fieldsetDisabled=!1,this._name="",this._value=EMPTY_VALUE,this.defaultValue=normalizeGraphQuery(EMPTY_VALUE),this.defaultValueCaptured=!1,this._disabled=!1,this.hasInteracted=!1,this.removalFocusGeneration=0,this.onChromeSlotChange=event=>{const slot=event.currentTarget,hasContent=slot.assignedNodes({flatten:!0}).some(node=>node.nodeType===Node.TEXT_NODE?!!node.textContent?.trim():!0);slot.name==="hint"?this.hasHintSlot=hasContent:slot.name==="error"&&(this.hasErrorSlot=hasContent)},this.internals=attachInternalsSafely(this),this.validityController=new AnchoredValidityController(this,this.internals,()=>this[VALIDITY_ANCHOR]()),installCustomErrorProperty(this,()=>this.validityController.customValidityMessage),installInvalidEventAlias(this,init=>this.emit("lr-invalid",null,init)),this.syncFormState()}disconnectedCallback(){this.removalFocusGeneration++,this.pendingRemovalFocus=void 0,super.disconnectedCallback()}get form(){return getFormOwner(this.internals)}set form(owner){setFormOwner(this,owner)}getForm(){return getFormOwner(this.internals)}get labels(){return this.internals.labels}get validity(){return this.internals.validity}get validationMessage(){return this.internals.validationMessage}get willValidate(){return this.internals.willValidate}get value(){return this._value}set value(next){const old=this._value;this._value=normalizeGraphQuery(next),this.syncFormState(),this.requestUpdate("value",old)}get name(){return this._name}set name(next){const old=this._name;this._name=next??"",this._name?this.setAttribute("name",this._name):this.removeAttribute("name"),this.requestUpdate("name",old)}get disabled(){return this._disabled}set disabled(next){const old=this._disabled;this._disabled=!!next,this.toggleAttribute("disabled",this._disabled),this.validityController&&this.syncFormState(),this.requestUpdate("disabled",old)}get effectiveDisabled(){return this.disabled||this._fieldsetDisabled}get errors(){return this.publicValidityErrors()}publicValidityErrors(){const errors={...this._errors};return this.willValidate&&this.validity.customError&&(errors.base=this.validationMessage),Object.freeze(errors)}publishValiditySnapshot(){if(!this.isConnected)return;const valid=!this.willValidate||this.validity.valid,errors=valid?Object.freeze({}):this.publicValidityErrors(),key=JSON.stringify({valid,errors});key!==this.lastValidityKey&&(this.lastValidityKey=key,this.emit("lr-validity-change",Object.freeze({valid,errors})))}[VALIDITY_ANCHOR](){const firstInvalidPart=Object.keys(this._errors)[0];if(!(!firstInvalidPart||!this.renderRoot))return this.renderRoot.querySelector(`[part="${firstInvalidPart}"]`)??void 0}computeValidation(){const errors={},flags={};return this._value.startId.trim()||(errors["start-input"]=this.localize("fieldRequired"),flags.valueMissing=!0),this._value.minHops>this._value.maxHops&&(errors["max-hops"]=this.localize("graphQueryHopRangeInvalid"),flags.rangeUnderflow=!0),{errors,flags}}syncFormState(){const{errors,flags}=this.computeValidation();this._errors=errors;let formValue=null;try{formValue=JSON.stringify(this._value)}catch{formValue=null}if(this.internals.setFormValue(formValue,formValue),this.barredFromValidation||Object.keys(flags).length===0)this.validityController.setValidity({});else{const message=Object.values(errors)[0]??"";this.validityController.setValidity(flags,message)}this.syncValidityCustomStates(),this.publishValiditySnapshot()}get barredFromValidation(){return isBarredFromValidation(this,this.internals)}syncValidityCustomStates(){syncValidityStates(this.internals,{required:!0,hasInteracted:this.hasInteracted,barred:this.barredFromValidation})}checkValidity(){return this.syncFormState(),this.internals.checkValidity()}reportValidity(){return this.hasInteracted=!0,this.syncFormState(),Object.keys(this._errors).length>0&&(this.touchedFields=new Set([...this.touchedFields,...Object.keys(this._errors)])),this.internals.reportValidity()}setCustomValidity(message){this.validityController.setCustomValidity(message??""),this.syncValidityCustomStates(),this.publishValiditySnapshot()}formResetCallback(){this.hasInteracted=!1,this.captureDefaultValue(),this.value=this.defaultValue,this.touchedFields=new Set,this.saveName=""}captureDefaultValue(){this.defaultValueCaptured||(this.defaultValue=normalizeGraphQuery(this._value),this.defaultValueCaptured=!0)}formStateRestoreCallback(state2,_mode){let restored=EMPTY_VALUE;if(typeof state2=="string")try{const parsed=JSON.parse(state2);parsed!==null&&typeof parsed=="object"&&!Array.isArray(parsed)&&(restored=normalizeGraphQuery(parsed))}catch{}this.value=restored}formDisabledCallback(disabled){this._fieldsetDisabled=disabled,this.syncFormState(),this.requestUpdate()}get liveDisabled(){return this.effectiveDisabled||this.matches(":disabled")}focusFirstControl(options){if(!this.renderRoot||this.liveDisabled)return;(this.renderRoot.querySelector('[part="start-input"]')||this.renderRoot.querySelector('[part="end-input"]')||this.renderRoot.querySelector('[part="min-hops"]')||this.renderRoot.querySelector('[part="max-hops"]')||this.renderRoot.querySelector('[part="direction"]')||this.renderRoot.querySelector('[part="save-name-input"]'))?.focus(options)}focus(options){this.focusFirstControl(options)}blur(){const active=deepActiveElementIn(this.shadowRoot);active&&typeof active.blur=="function"&&active.blur()}click(){this.focusFirstControl()}setValue(next){this.effectiveDisabled||(this.hasInteracted=!0,this.value=next,this.emit("lr-input",Object.freeze({value:this._value})))}addRelationshipType(type){!type||this._value.relationshipTypes.includes(type)||this.setValue({...this._value,relationshipTypes:[...this._value.relationshipTypes,type]})}removeRelationshipType(type){this.captureChipRemovalFocus("relationship",type,this._value.relationshipTypes),this.setValue({...this._value,relationshipTypes:this._value.relationshipTypes.filter(t=>t!==type)})}addNodeType(type){!type||this._value.nodeTypes.includes(type)||this.setValue({...this._value,nodeTypes:[...this._value.nodeTypes,type]})}removeNodeType(type){this.captureChipRemovalFocus("node-type",type,this._value.nodeTypes),this.setValue({...this._value,nodeTypes:this._value.nodeTypes.filter(t=>t!==type)})}captureChipRemovalFocus(group,value,selected){const active=this.shadowRoot?.activeElement,expectedPart=group==="relationship"?"relationship-chips":"node-type-chips";if(active?.localName!=="lr-chip"||active.getAttribute("value")!==value||active.closest("lr-chip-group")?.getAttribute("part")!==expectedPart)return;const index=selected.indexOf(value),survivors=selected.filter(candidate=>candidate!==value),targetValue=survivors[Math.min(Math.max(index,0),survivors.length-1)];this.pendingRemovalFocus={kind:"chip",group,targetValue},this.removalFocusGeneration++}markTouched(part){this.hasInteracted=!0,this.syncValidityCustomStates(),!this.touchedFields.has(part)&&(this.touchedFields=new Set(this.touchedFields).add(part))}runQuery(){if(this.effectiveDisabled||!this.reportValidity())return;const detail=()=>Object.freeze({query:normalizeGraphQuery(this._value)});this.emit("lr-before-query-run",detail(),{cancelable:!0}).defaultPrevented||this.emit("lr-query-run",detail())}saveQuery(){if(this.effectiveDisabled)return;const name=this.saveName.trim();if(!name)return;const detail=()=>Object.freeze({name,query:normalizeGraphQuery(this._value)});this.emit("lr-before-query-save",detail(),{cancelable:!0}).defaultPrevented||(this.saveName="",this.emit("lr-query-save",detail()))}loadQuery(item){if(this.effectiveDisabled)return;const detail=()=>Object.freeze({queryId:item.id,query:normalizeGraphQuery(item.query)});this.emit("lr-before-query-load",detail(),{cancelable:!0}).defaultPrevented||(this.setValue({...EMPTY_VALUE,...item.query}),this.emit("lr-query-load",detail()))}deleteQuery(item){if(this.effectiveDisabled)return;const detail=()=>Object.freeze({queryId:item.id});this.emit("lr-before-query-delete",detail(),{cancelable:!0}).defaultPrevented||this.emit("lr-query-delete",detail())}willUpdate(changed){if(super.willUpdate(changed),this.hasUpdated||this.captureDefaultValue(),!changed.has("savedQueries"))return;const active=this.shadowRoot?.activeElement;if(active?.getAttribute("part")!=="saved-delete-button")return;const focusedId=active.closest("[data-query-id]")?.dataset.queryId;if(!focusedId||this.savedQueries.some(item=>item.id===focusedId))return;const index=(changed.get("savedQueries")??[]).findIndex(item=>item.id===focusedId),target=this.savedQueries[Math.min(Math.max(index,0),this.savedQueries.length-1)];this.pendingRemovalFocus={kind:"saved",targetId:target?.id},this.removalFocusGeneration++}updated(changed){super.updated(changed),this.publishValiditySnapshot();const pending=this.pendingRemovalFocus;if(!pending)return;this.pendingRemovalFocus=void 0;const generation=this.removalFocusGeneration;this.scheduleAfterUpdate(()=>{if(!(generation!==this.removalFocusGeneration||!this.isConnected)){if(pending.kind==="chip"){if(pending.targetValue){const part=pending.group==="relationship"?"relationship-chips":"node-type-chips",chip=[...this.shadowRoot?.querySelectorAll(`[part="${part}"] lr-chip`)??[]].find(candidate=>candidate.getAttribute("value")===pending.targetValue);if(chip){chip.focus();return}}const pickerPart=pending.group==="relationship"?"relationship-picker":"node-type-picker";this.shadowRoot?.querySelector(`[part="${pickerPart}"]`)?.focus();return}if(pending.targetId){const action=[...this.shadowRoot?.querySelectorAll("[data-query-id]")??[]].find(candidate=>candidate.dataset.queryId===pending.targetId)?.querySelector('[part="saved-delete-button"]');if(action){action.focus();return}}this.shadowRoot?.querySelector('[part="save-name-input"]')?.focus()}},"graph-query-removal-focus")}hopOptions(){const limit=finiteInteger(this.hopLimit,6,1,20),options=new Set(Array.from({length:limit},(_,i)=>i+1));return options.add(this._value.minHops),options.add(this._value.maxHops),[...options].sort((a,b)=>a-b)}labelForType(options,value){return options.find(o=>o.value===value)?.label??value}renderTypeFilter(kind,options,selected,add,remove,disabled){const pickerPart=kind==="relationship"?"relationship-picker":"node-type-picker",chipsPart=kind==="relationship"?"relationship-chips":"node-type-chips",pickerLabel=kind==="relationship"?this.localize("graphQueryRelationshipTypeLabel"):this.localize("graphQueryNodeTypeLabel"),available=options.filter(o=>!selected.includes(o.value));return html`
|
|
2
2
|
<div part="filter-group" data-kind=${kind}>
|
|
3
3
|
<lr-select
|
|
4
4
|
part=${pickerPart}
|
|
@@ -1,6 +1,18 @@
|
|
|
1
1
|
import { type PropertyValues, type TemplateResult } from 'lit';
|
|
2
2
|
import { LyraElement } from '../../../internal/lyra-element.js';
|
|
3
3
|
import { type CalendarDay } from './calendar-grid.js';
|
|
4
|
+
/**
|
|
5
|
+
* Which matrix label band, if any, is frozen while the grid scrolls.
|
|
6
|
+
*
|
|
7
|
+
* One closed set rather than a boolean or a pair of booleans, because freezing one axis is a real
|
|
8
|
+
* request on its own: a wide matrix needs the row gutter to survive horizontal scrolling, a tall one
|
|
9
|
+
* needs the column band to survive vertical scrolling, and the two are independent. A boolean cannot
|
|
10
|
+
* express that at all, and a `sticky-row-labels`/`sticky-col-labels` pair spends two attributes and
|
|
11
|
+
* four states on it while leaving no single reflected value to select on in CSS. The `rows`/`cols`
|
|
12
|
+
* spelling matches the vocabulary the rest of this component already uses (`rowLabels`,
|
|
13
|
+
* `row-label-width`, `colLabels`, `col-label-height`) rather than introducing axis letters.
|
|
14
|
+
*/
|
|
15
|
+
export type LyraHeatmapStickyLabels = 'none' | 'rows' | 'cols' | 'both';
|
|
4
16
|
/**
|
|
5
17
|
* A linear RGB ramp cannot contain more than 256 visually distinct integer
|
|
6
18
|
* steps on any channel. Keeping the bucket count within that bound avoids an
|
|
@@ -88,6 +100,14 @@ export interface HeatmapLegendStop {
|
|
|
88
100
|
color?: string;
|
|
89
101
|
/** Optional label override; defaults to the component's own numeric formatting of `value`. */
|
|
90
102
|
label?: string;
|
|
103
|
+
/**
|
|
104
|
+
* Set to `false` to exclude this stop from `warnOnLegendRampMismatch()`'s `colorSteps` agreement
|
|
105
|
+
* check, for a real, distinctly-colored swatch that is intentionally not part of the sequential
|
|
106
|
+
* ramp -- e.g. a calendar heatmap's fixed neutral "no data" color shown alongside an N-step
|
|
107
|
+
* ramp. Defaults to `true`. A caption-only stop (no `color`) is already excluded regardless of
|
|
108
|
+
* this flag, since it describes no color to compare.
|
|
109
|
+
*/
|
|
110
|
+
partOfRamp?: boolean;
|
|
91
111
|
}
|
|
92
112
|
/** A single cell to mark as persistently selected -- `row`/`col` in matrix mode, `date` in
|
|
93
113
|
* calendar mode (whichever pair matches the active `mode`; the other field is ignored),
|
|
@@ -139,8 +159,14 @@ export type LyraHeatmapCellClickDetail = {
|
|
|
139
159
|
col: number;
|
|
140
160
|
value: number;
|
|
141
161
|
};
|
|
162
|
+
export type LyraHeatmapMatrixGeometryChangeDetail = {
|
|
163
|
+
padLeft: number;
|
|
164
|
+
padTop: number;
|
|
165
|
+
cellSize: number;
|
|
166
|
+
};
|
|
142
167
|
export interface LyraHeatmapEventMap {
|
|
143
168
|
'lr-cell-click': CustomEvent<LyraHeatmapCellClickDetail>;
|
|
169
|
+
'lr-matrix-geometry-change': CustomEvent<LyraHeatmapMatrixGeometryChangeDetail>;
|
|
144
170
|
}
|
|
145
171
|
/**
|
|
146
172
|
* `<lr-heatmap>` — a Canvas heatmap with a DPR-aware, resize-aware redraw
|
|
@@ -213,6 +239,22 @@ export interface LyraHeatmapEventMap {
|
|
|
213
239
|
* focus, its semantic matrix coordinate or calendar date remains the sole roving stop; removal
|
|
214
240
|
* clamps to the nearest survivor, or to the stable heatmap base when no interactive cells remain.
|
|
215
241
|
*
|
|
242
|
+
* `stickyLabels` freezes a matrix label band against the grid's own scrolling — `'rows'` pins the
|
|
243
|
+
* row-label gutter through horizontal scrolling, `'cols'` pins the column-label band through
|
|
244
|
+
* vertical scrolling, `'both'` pins both. The frozen band is repainted into its own layer from the
|
|
245
|
+
* same `matrixGeometry` the cells were painted with in the same pass, so it tracks a
|
|
246
|
+
* `row-label-width`/`col-label-height` `"auto"` re-resolution instead of hardcoding it. The default
|
|
247
|
+
* `'none'` renders exactly what it always did: one canvas, no scrollport.
|
|
248
|
+
*
|
|
249
|
+
* Everything positioned in canvas coordinates moves into that scrollport with the cells. The hover
|
|
250
|
+
* tooltip renders inside it, so it stays on the cell it describes through a scroll instead of
|
|
251
|
+
* drifting by the scroll offset; since `overflow: auto` there clips whatever leaves the
|
|
252
|
+
* scrollport, it is also kept inside the visible window — clamped along the inline axis, and
|
|
253
|
+
* flipped to below its cell when a frozen band leaves no room above. Arrow-key navigation scrolls
|
|
254
|
+
* the focused cell into that window, clear of the frozen bands: the canvas is the roving tab stop,
|
|
255
|
+
* its focus ring is painted into the bitmap, and it calls `preventDefault()` on the arrows, so
|
|
256
|
+
* without that scroll a keyboard user has no way at all to bring the focused cell back into view.
|
|
257
|
+
*
|
|
216
258
|
* Calendar `data.columnX` overrides the x-origin computed for each
|
|
217
259
|
* week column — drawing, hit-testing, the focus ring, and month-label
|
|
218
260
|
* positioning all consult it consistently, so a consumer can pixel-align a
|
|
@@ -251,11 +293,20 @@ export interface LyraHeatmapEventMap {
|
|
|
251
293
|
* tooltip and the keyboard live-region announcement. Use the callback for application-specific
|
|
252
294
|
* wording that is not represented by the locale catalog.
|
|
253
295
|
* `cellColor` overrides a cell's ramp-computed color entirely for an exact value.
|
|
296
|
+
* @event lr-matrix-geometry-change - Fired after a matrix-mode draw pass whose resolved
|
|
297
|
+
* `matrixGeometry` (`padLeft`/`padTop`/`cellSize`) differs from the previous draw -- e.g. after
|
|
298
|
+
* `row-label-width="auto"`/`col-label-height="auto"` resolves against new label content or a
|
|
299
|
+
* resize. `detail` is the same object `matrixGeometry` returns. Never fired in calendar mode.
|
|
254
300
|
* @csspart base - The heatmap wrapper.
|
|
255
301
|
* @csspart canvas - The heatmap canvas.
|
|
302
|
+
* @csspart grid - The scrollport wrapping the canvas while `stickyLabels` freezes an axis; absent otherwise.
|
|
303
|
+
* @csspart row-labels - The frozen row-label gutter, rendered while `stickyLabels` is `rows` or `both`.
|
|
304
|
+
* @csspart col-labels - The frozen column-label band, rendered while `stickyLabels` is `cols` or `both`.
|
|
256
305
|
* @csspart cells - The opt-in per-cell accessibility overlay.
|
|
257
306
|
* @csspart cell - An opt-in native button for one matrix or calendar cell.
|
|
258
|
-
* @csspart tooltip - The hover tooltip.
|
|
307
|
+
* @csspart tooltip - The hover tooltip, positioned over the hovered cell. It renders inside
|
|
308
|
+
* `[part="grid"]` while `stickyLabels` freezes an axis (so it scrolls with the cells) and as a
|
|
309
|
+
* `[part="base"]` child otherwise.
|
|
259
310
|
* @csspart live-region - An aria-hidden shadow mirror of the keyboard announcement; the actual
|
|
260
311
|
* announcement uses the shared light-DOM polite sink.
|
|
261
312
|
* @csspart projection-limit - Localized assistive disclosure for bounded projections.
|
|
@@ -276,6 +327,8 @@ export interface LyraHeatmapEventMap {
|
|
|
276
327
|
* @cssprop [--lr-heatmap-focus-ring-color=var(--lr-focus-ring-color)] - Focus ring around a focused cell.
|
|
277
328
|
* @cssprop [--lr-heatmap-annotation-color=var(--lr-color-danger)] - Border color for an annotated cell.
|
|
278
329
|
* @cssprop [--lr-heatmap-selected-color=var(--lr-color-success)] - Border color for the selected cell.
|
|
330
|
+
* @cssprop [--lr-heatmap-sticky-label-bg=var(--lr-color-surface)] - Backdrop painted under a frozen `stickyLabels` band. Must be opaque: it covers the same labels the scrolling canvas painted underneath it.
|
|
331
|
+
* @cssprop [--lr-heatmap-grid-max-block-size=none] - Block-size ceiling of the `stickyLabels` scrollport. A frozen column band only stays behind once the grid actually scrolls vertically.
|
|
279
332
|
* @cssprop [--lr-heatmap-color-steps-gradient=linear-gradient(to right, var(--lr-heatmap-scale-lo), var(--lr-heatmap-scale-hi))] - Gradient painted on the continuous legend bar. Set on the host by the component itself while `colorSteps` is supplied, and removed again when it is not; the fallback is the two-endpoint scale ramp.
|
|
280
333
|
* @status stable
|
|
281
334
|
* @since 4.0.0
|
|
@@ -339,6 +392,46 @@ export declare class LyraHeatmap extends LyraElement<LyraHeatmapEventMap> {
|
|
|
339
392
|
* would be incoherent.
|
|
340
393
|
*/
|
|
341
394
|
colLabelRotation?: number;
|
|
395
|
+
private _stickyLabels;
|
|
396
|
+
/**
|
|
397
|
+
* Freezes a matrix label band against the grid's own scrolling, instead of leaving it baked into
|
|
398
|
+
* the scrolling bitmap. `'rows'` pins the row-label gutter so it survives horizontal scrolling,
|
|
399
|
+
* `'cols'` pins the column-label band so it survives vertical scrolling, `'both'` pins both, and
|
|
400
|
+
* the default `'none'` renders exactly what this component rendered before the option existed:
|
|
401
|
+
* one canvas, no scrollport, no extra elements.
|
|
402
|
+
*
|
|
403
|
+
* Labels and cells share one bitmap, so a band cannot be `position: sticky` on its own; a tall
|
|
404
|
+
* matrix therefore scrolled its column header away and left the columns unidentifiable. Setting
|
|
405
|
+
* this repaints the requested band into its own layer, in the same draw pass and from the same
|
|
406
|
+
* resolved `matrixGeometry` the cells were painted with, so the two cannot drift under scroll, a
|
|
407
|
+
* resize, a DPR change, or a `rowLabelWidth`/`colLabelHeight` `"auto"` re-resolution. That last
|
|
408
|
+
* one is the point: a hand-rolled light-DOM mirror had to hardcode the gutter width, which made
|
|
409
|
+
* it mutually exclusive with `row-label-width="auto"`.
|
|
410
|
+
*
|
|
411
|
+
* Freezing needs something to scroll, so the frozen modes wrap the grid in a `[part="grid"]`
|
|
412
|
+
* scrollport. It is bounded inline by the host's own allocation (a matrix wider than a 320px host
|
|
413
|
+
* scrolls inside the component rather than overflowing it) and unbounded in block by default; set
|
|
414
|
+
* `--lr-heatmap-grid-max-block-size` to bound it, since a column band can only stay behind while
|
|
415
|
+
* the grid actually scrolls vertically.
|
|
416
|
+
*
|
|
417
|
+
* Matrix mode only, like `matrixGeometry` and `lr-matrix-geometry-change`: calendar mode's axes
|
|
418
|
+
* are a different geometry (a fixed weekday gutter, a month band, and the optional `columnX`/
|
|
419
|
+
* `rowY` overrides), so this property is read but has no effect there.
|
|
420
|
+
*
|
|
421
|
+
* Under `dir="rtl"` the grid keeps this component's documented physical LTR geometry, so the
|
|
422
|
+
* scrollport is direction-pinned like the canvas already is and the bands then freeze against the
|
|
423
|
+
* logical inline-start/block-start edges of that pinned box — which is to say the physical left
|
|
424
|
+
* and top, where the labels they duplicate are actually painted.
|
|
425
|
+
*
|
|
426
|
+
* See `LyraHeatmapStickyLabels` for why this is one closed set rather than a boolean or a pair.
|
|
427
|
+
*/
|
|
428
|
+
get stickyLabels(): LyraHeatmapStickyLabels;
|
|
429
|
+
set stickyLabels(next: LyraHeatmapStickyLabels);
|
|
430
|
+
/** `stickyLabels` restricted to the mode it applies to. One gate for render and paint alike, so
|
|
431
|
+
* switching `data` to a calendar can never leave a frozen band or a scrollport behind. */
|
|
432
|
+
private get effectiveStickyLabels();
|
|
433
|
+
private get freezesRowLabels();
|
|
434
|
+
private get freezesColLabels();
|
|
342
435
|
/** Column band resolved during the last draw, mirroring `resolvedRowLabelWidth`. */
|
|
343
436
|
private resolvedColLabelHeight;
|
|
344
437
|
/** Normalized rotation in degrees: finite, clamped to `[0, 90]`. */
|
|
@@ -347,6 +440,31 @@ export declare class LyraHeatmap extends LyraElement<LyraHeatmapEventMap> {
|
|
|
347
440
|
* painted. Only ever differs from the default while `rowLabelWidth="auto"`. */
|
|
348
441
|
private resolvedRowLabelWidth;
|
|
349
442
|
private get matrixPadLeft();
|
|
443
|
+
/**
|
|
444
|
+
* The gutter/cell geometry the last matrix-mode draw actually painted with --
|
|
445
|
+
* `{ padLeft, padTop, cellSize }`, all in CSS pixels -- so a light-DOM consumer (e.g. a sticky
|
|
446
|
+
* header mirror) can line up with the canvas without hardcoding the same numbers `row-label-width`
|
|
447
|
+
* or `col-label-height`'s `"auto"` resolution would otherwise keep private. `undefined` in
|
|
448
|
+
* calendar mode, and before the first matrix draw.
|
|
449
|
+
*
|
|
450
|
+
* This returns the frozen object `drawMatrix()` stored (and `lr-matrix-geometry-change` carried)
|
|
451
|
+
* on the last draw -- not a fresh computation. That distinction is the whole contract. Computing
|
|
452
|
+
* it on read from the same internal getters `drawMatrix()` uses looks equivalent and is not:
|
|
453
|
+
* those getters read CURRENT layout, so any interval where layout has moved but no draw has
|
|
454
|
+
* happened yet makes the getter describe a canvas that does not exist. Two such intervals are
|
|
455
|
+
* routine -- full redraws pause while the host is outside the viewport (documented behaviour of
|
|
456
|
+
* this component), and `rowLabelWidth`/`colLabelHeight` are not redraw-triggering properties at
|
|
457
|
+
* all -- and both land hardest on the tall, partly-scrolled matrix this getter exists to serve.
|
|
458
|
+
* Returning the stored object also makes the getter and the event the same value by
|
|
459
|
+
* construction rather than by coincidence.
|
|
460
|
+
*/
|
|
461
|
+
get matrixGeometry(): Readonly<LyraHeatmapMatrixGeometryChangeDetail> | undefined;
|
|
462
|
+
/** The geometry the last `drawMatrix()` pass painted with, frozen and shared with the
|
|
463
|
+
* `lr-matrix-geometry-change` detail. `undefined` until the first draw, which is what gates
|
|
464
|
+
* `matrixGeometry` returning a real value only once there is a draw to describe. Also backs the
|
|
465
|
+
* event's change detection, so a same-valued redraw (a color-only update, an unrelated data
|
|
466
|
+
* change) does not refire it. */
|
|
467
|
+
private lastPaintedMatrixGeometry?;
|
|
350
468
|
private get matrixPadTop();
|
|
351
469
|
/** Tallest rotated column label plus inset, floored at the built-in band and capped so labels can
|
|
352
470
|
* never crowd out the matrix. The column mirror of `measureRowLabelWidth()`. */
|
|
@@ -644,7 +762,8 @@ export declare class LyraHeatmap extends LyraElement<LyraHeatmapEventMap> {
|
|
|
644
762
|
* Warning rather than deriving one from the other: deriving would silently change what an
|
|
645
763
|
* existing `colorSteps`-only consumer sees, and would also break the deliberate `cellColor`
|
|
646
764
|
* escape hatch. This keeps every current behavior and only makes the disagreement audible.
|
|
647
|
-
* Compares only the stops that carry a color -- a caption-only stop describes no color at all
|
|
765
|
+
* Compares only the stops that carry a color -- a caption-only stop describes no color at all --
|
|
766
|
+
* and, among those, only the ones that did not opt out via `partOfRamp: false`.
|
|
648
767
|
*/
|
|
649
768
|
private warnOnLegendRampMismatch;
|
|
650
769
|
private cachedLegendStops;
|
|
@@ -733,6 +852,10 @@ export declare class LyraHeatmap extends LyraElement<LyraHeatmapEventMap> {
|
|
|
733
852
|
private labelColor;
|
|
734
853
|
/** Reads the customizable canvas axis/label font off the host's computed style. */
|
|
735
854
|
private labelFont;
|
|
855
|
+
/** Reads the customizable frozen-label-band backdrop off the host's computed style, resolved to a
|
|
856
|
+
* concrete color: canvas silently keeps its previous `fillStyle` for anything it cannot parse,
|
|
857
|
+
* and a `var()` chain is exactly that. */
|
|
858
|
+
private stickyLabelBg;
|
|
736
859
|
/** Reads the customizable no-data cell fill off the host's computed style. */
|
|
737
860
|
private noDataFill;
|
|
738
861
|
/** Reads the customizable canvas-drawn keyboard-focus-ring stroke color off the host's computed style. */
|
|
@@ -863,6 +986,32 @@ export declare class LyraHeatmap extends LyraElement<LyraHeatmapEventMap> {
|
|
|
863
986
|
private paintCalendarFocusOverlays;
|
|
864
987
|
private repaintCalendarFocusCell;
|
|
865
988
|
private drawMatrix;
|
|
989
|
+
/** Paints the row-label gutter at `x = 0 .. padLeft`. Extracted so the cell canvas and a frozen
|
|
990
|
+
* `[part="row-labels"]` band paint from one routine and one set of geometry arguments — the
|
|
991
|
+
* band's own canvas shares the cell canvas's origin, so "aligned" is what the same coordinates
|
|
992
|
+
* mean, rather than something a second implementation has to keep agreeing about. */
|
|
993
|
+
private paintMatrixRowLabels;
|
|
994
|
+
/** The column-label band at `y = 0 .. padTop`, rotation included. The mirror of
|
|
995
|
+
* `paintMatrixRowLabels()`, shared with a frozen `[part="col-labels"]` band the same way. */
|
|
996
|
+
private paintMatrixColLabels;
|
|
997
|
+
/**
|
|
998
|
+
* Repaints whichever label bands `stickyLabels` freezes, from the geometry this very draw pass
|
|
999
|
+
* painted the cells with. Each band is a canvas sharing the cell canvas's origin (both sit in the
|
|
1000
|
+
* same single-area grid), sized to the band it owns and offset on one axis only by
|
|
1001
|
+
* `position: sticky`, so it slides along the axis it is not frozen on and stays put on the one it
|
|
1002
|
+
* is. Nothing here recomputes geometry, which is what keeps a band aligned across a resize, a DPR
|
|
1003
|
+
* change, and a `row-label-width`/`col-label-height` `"auto"` re-resolution alike.
|
|
1004
|
+
*
|
|
1005
|
+
* The cell canvas keeps painting its own labels underneath: leaving that pass untouched is what
|
|
1006
|
+
* makes the default `'none'` byte-identical, and the band's opaque backdrop covers the duplicate
|
|
1007
|
+
* once it scrolls out from under the frozen copy.
|
|
1008
|
+
*/
|
|
1009
|
+
private paintFrozenLabelBands;
|
|
1010
|
+
private frozenBandCanvas;
|
|
1011
|
+
/** Sizes one band's backing store to the same DPR the cell canvas uses, fills the opaque backdrop,
|
|
1012
|
+
* then hands the caller a context already in CSS-pixel coordinates identical to the cell
|
|
1013
|
+
* canvas's — so a label lands on the same physical pixel in both. */
|
|
1014
|
+
private paintFrozenBand;
|
|
866
1015
|
/**
|
|
867
1016
|
* Maps a pointer position, in canvas-local CSS px (e.g.
|
|
868
1017
|
* `PointerEvent.offsetX/offsetY`), to the cell underneath it — or `null`
|
|
@@ -905,7 +1054,7 @@ export declare class LyraHeatmap extends LyraElement<LyraHeatmapEventMap> {
|
|
|
905
1054
|
* `CalendarCellPos` in this component goes through here, so no call site can forget the date. */
|
|
906
1055
|
private calendarPos;
|
|
907
1056
|
/**
|
|
908
|
-
* Pixel rect (canvas-local CSS px) of a cell — shared by `
|
|
1057
|
+
* Pixel rect (canvas-local CSS px) of a cell — shared by `tooltipAnchor()`
|
|
909
1058
|
* so the tooltip's position always agrees with the same geometry
|
|
910
1059
|
* `drawMatrix()`/`drawCalendar()`/`hitTest*()` use.
|
|
911
1060
|
*/
|
|
@@ -933,8 +1082,53 @@ export declare class LyraHeatmap extends LyraElement<LyraHeatmapEventMap> {
|
|
|
933
1082
|
* wording anywhere around the cell text instead of it being appended. */
|
|
934
1083
|
private announce;
|
|
935
1084
|
private emitCellClick;
|
|
936
|
-
/**
|
|
937
|
-
private
|
|
1085
|
+
/** The `stickyLabels` scrollport, or `null` in the default unfrozen render, which has none. */
|
|
1086
|
+
private get gridScrollport();
|
|
1087
|
+
/** The tooltip's own rendered box in CSS px, recorded by `measureTooltip()`: `inline` is its
|
|
1088
|
+
* border box, `block` that box plus the token-sized gap it keeps from the cell. Only read while
|
|
1089
|
+
* a scrollport can clip it; zero until the first measurement, which degrades to the unclamped
|
|
1090
|
+
* placement rather than to a wrong one. */
|
|
1091
|
+
private tooltipSize;
|
|
1092
|
+
/**
|
|
1093
|
+
* Records the tooltip's rendered size, so the next paint can keep it inside the `stickyLabels`
|
|
1094
|
+
* scrollport. Measured rather than derived: the box is sized by caller text, and the gap it
|
|
1095
|
+
* keeps from the cell is a design token whose value belongs in the stylesheet.
|
|
1096
|
+
*
|
|
1097
|
+
* Repositioning can never resize it (`white-space: nowrap`, no inline-size constraint), so the
|
|
1098
|
+
* re-render scheduled here always settles in one step. It runs from `scheduleAfterUpdate()`
|
|
1099
|
+
* rather than straight out of `updated()` on purpose: that keeps the `requestUpdate()` outside
|
|
1100
|
+
* Lit's own update cycle, and its microtask still flushes before paint, so the corrected
|
|
1101
|
+
* position is the first one the user ever sees.
|
|
1102
|
+
*/
|
|
1103
|
+
private measureTooltip;
|
|
1104
|
+
/**
|
|
1105
|
+
* Inline `style` for `[part="tooltip"]` — centered on the given cell — plus whether it had to be
|
|
1106
|
+
* flipped below that cell.
|
|
1107
|
+
*
|
|
1108
|
+
* With no `stickyLabels` scrollport this is the original unconditional "centered above the cell"
|
|
1109
|
+
* placement, in the canvas-local coordinates `cellRect()` returns. With one, the tooltip renders
|
|
1110
|
+
* *inside* that scrollport, which is what keeps it pinned to the cell it describes through a
|
|
1111
|
+
* scroll — and there `overflow: auto` clips whatever leaves the scrollport, while an opaque
|
|
1112
|
+
* frozen band hides whatever is drawn under it. So the placement is additionally kept inside the
|
|
1113
|
+
* band-free part of the visible window: still centered on the cell but clamped to that window,
|
|
1114
|
+
* and flipped to below the cell when there is no room above it and there is room below. Flipping
|
|
1115
|
+
* is conditional on both, deliberately: an unconditional flip at the block end would push the
|
|
1116
|
+
* tooltip past the content box and grow the scrollable area under the pointer.
|
|
1117
|
+
*/
|
|
1118
|
+
private tooltipAnchor;
|
|
1119
|
+
/**
|
|
1120
|
+
* Keeps the keyboard-focused cell inside the `stickyLabels` scrollport, clear of the frozen
|
|
1121
|
+
* bands' own boxes.
|
|
1122
|
+
*
|
|
1123
|
+
* Without this the feature is an accessibility regression: the default (unset `accessibleCells`)
|
|
1124
|
+
* roving stop is the canvas itself, its focus ring is painted into the canvas bitmap rather than
|
|
1125
|
+
* carried by a focusable element the browser would scroll to, and `onMatrixKeyDown()` calls
|
|
1126
|
+
* `preventDefault()` on every arrow — so the browser's own scrolling never happens either, and
|
|
1127
|
+
* arrowing far enough leaves the focus indicator off-screen with no keyboard way to reveal it.
|
|
1128
|
+
* A minimal scroll (never re-centering a cell that is already fully visible) keeps the scroll
|
|
1129
|
+
* position stable while arrowing around inside the visible window.
|
|
1130
|
+
*/
|
|
1131
|
+
private scrollCellIntoView;
|
|
938
1132
|
/**
|
|
939
1133
|
* Value-equality check for a `CellPos`, since `hoverCell` is assigned a
|
|
940
1134
|
* fresh object literal on every `pointermove` — Lit's `@state()`
|
|
@@ -981,6 +1175,29 @@ export declare class LyraHeatmap extends LyraElement<LyraHeatmapEventMap> {
|
|
|
981
1175
|
* unset (or empty) `legendStops` therefore reproduces the pre-`legendStops` markup exactly.
|
|
982
1176
|
*/
|
|
983
1177
|
private renderLegendScale;
|
|
1178
|
+
/**
|
|
1179
|
+
* The cell canvas, the opt-in per-cell overlay, and — while `stickyLabels` freezes an axis — the
|
|
1180
|
+
* frozen label bands, wrapped in the scrollport those bands stick to.
|
|
1181
|
+
*
|
|
1182
|
+
* Both branches emit the same canvas and overlay from one template, so the unfrozen default keeps
|
|
1183
|
+
* rendering exactly the elements it always did (no wrapper, no scrollport, no second canvas) with
|
|
1184
|
+
* no second copy of the canvas's attribute/listener surface to drift. The bands are decorative
|
|
1185
|
+
* duplicates of pixels the cell canvas already painted, so they carry `aria-hidden` and no role:
|
|
1186
|
+
* the accessible representation stays the canvas's own `role="application"` name, or the
|
|
1187
|
+
* `[part="cells"]` grid under `accessibleCells` — which moves inside the scrollport so the cells
|
|
1188
|
+
* scroll with the canvas they overlay.
|
|
1189
|
+
*/
|
|
1190
|
+
private renderGridSurface;
|
|
1191
|
+
/**
|
|
1192
|
+
* The hover tooltip, rendered once: inside the `stickyLabels` scrollport's stack when an axis is
|
|
1193
|
+
* frozen (see `renderGridSurface()`), and as the `[part="base"]` sibling it has always been
|
|
1194
|
+
* otherwise, where the canvas's origin already *is* the base's.
|
|
1195
|
+
*
|
|
1196
|
+
* `dir` is carried explicitly because the scrollport pins `direction: ltr` for the physically
|
|
1197
|
+
* non-mirrored grid geometry, and the tooltip is the one thing in there that is prose rather
|
|
1198
|
+
* than geometry -- it keeps the host's own direction it inherited before the scrollport existed.
|
|
1199
|
+
*/
|
|
1200
|
+
private renderTooltip;
|
|
984
1201
|
render(): TemplateResult;
|
|
985
1202
|
/** `localize()` interpolates with a bare `String(value)`, so a number handed to it renders in
|
|
986
1203
|
* ASCII digits no matter the locale -- mixing two numbering systems inside one translated
|