@aceshooting/lyra-ui 11.2.0 → 12.1.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 +407 -0
- package/README.md +11 -8
- package/custom-elements.json +1 -1
- package/dist/all.d.ts +1 -0
- package/dist/all.js +1 -1
- package/dist/autoloader.js +1 -1
- package/dist/components/agent-tools/tool-param-form/tool-param-form.class.d.ts +0 -1
- package/dist/components/agent-tools/tool-param-form/tool-param-form.class.js +1 -1
- package/dist/components/charts/chart/chart.class.d.ts +13 -1
- package/dist/components/charts/chart/histogram-bin.d.ts +0 -1
- package/dist/components/charts/chart/histogram-bin.js +1 -1
- package/dist/components/charts/chart/lite-chart.class.d.ts +22 -9
- package/dist/components/charts/chart/lite-chart.class.js +6 -6
- package/dist/components/conversation/code-block/code-block-shared.d.ts +4 -54
- package/dist/components/conversation/code-block/code-block-shared.js +1 -1
- package/dist/components/conversation/code-block/shiki-types.d.ts +2 -1
- package/dist/components/conversation/generation-metrics/generation-metrics.class.js +1 -1
- package/dist/components/conversation/model-select/model-select.class.d.ts +0 -3
- package/dist/components/conversation/model-select/model-select.class.js +1 -1
- package/dist/components/conversation/selection-toolbar/selection-toolbar.class.js +1 -1
- package/dist/components/conversation/voice-picker/voice-picker.class.d.ts +0 -1
- package/dist/components/conversation/voice-picker/voice-picker.class.js +1 -1
- package/dist/components/data/data-grid/data-grid.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 +0 -1
- package/dist/components/data/graph-query-builder/graph-query-builder.class.js +1 -1
- package/dist/components/data/heatmap/heatmap.class.d.ts +199 -14
- 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.d.ts +18 -4
- package/dist/components/data/table/table.class.js +2 -2
- package/dist/components/data/table/table.styles.js +2 -1
- package/dist/components/data/timeline/timeline-cluster.d.ts +1 -0
- package/dist/components/data/timeline/timeline-cluster.js +1 -0
- package/dist/components/data/timeline/timeline-item.class.d.ts +17 -2
- package/dist/components/data/timeline/timeline-item.class.js +13 -2
- package/dist/components/data/timeline/timeline-item.styles.js +65 -0
- package/dist/components/data/timeline/timeline.class.d.ts +83 -27
- package/dist/components/data/timeline/timeline.class.js +3 -3
- package/dist/components/data/timeline/timeline.d.ts +1 -0
- package/dist/components/data/timeline/timeline.js +1 -1
- package/dist/components/data/timeline/timeline.styles.js +14 -0
- package/dist/components/forms/button/button.class.js +1 -1
- package/dist/components/forms/checkbox/checkbox.class.d.ts +0 -1
- package/dist/components/forms/checkbox/checkbox.class.js +1 -1
- package/dist/components/forms/checkbox-group/checkbox-group.class.d.ts +0 -1
- package/dist/components/forms/checkbox-group/checkbox-group.class.js +1 -1
- package/dist/components/forms/code-editor/code-editor.class.js +1 -1
- package/dist/components/forms/color-picker/color-picker.class.js +1 -1
- package/dist/components/forms/combobox/combobox.class.d.ts +7 -1
- package/dist/components/forms/combobox/combobox.class.js +3 -2
- package/dist/components/forms/combobox/combobox.styles.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/emoji-picker/emoji-data-loader.d.ts +0 -1
- package/dist/components/forms/input/native-time-input.class.js +1 -1
- package/dist/components/forms/input/time-input-shared.d.ts +2 -1
- package/dist/components/forms/input/time-input.class.js +1 -1
- package/dist/components/forms/locale-picker/locale-picker.class.d.ts +0 -1
- package/dist/components/forms/locale-picker/locale-picker.class.js +1 -1
- package/dist/components/forms/radio/radio-button.styles.d.ts +0 -1
- package/dist/components/forms/radio/radio-button.styles.js +1 -1
- package/dist/components/forms/radio/radio-group.class.d.ts +0 -1
- package/dist/components/forms/radio/radio-group.class.js +1 -1
- package/dist/components/forms/radio/radio.class.d.ts +0 -1
- package/dist/components/forms/radio/radio.class.js +1 -1
- package/dist/components/forms/rubric-form/rubric-form.class.d.ts +0 -1
- package/dist/components/forms/rubric-form/rubric-form.class.js +1 -1
- package/dist/components/forms/select/select.class.d.ts +0 -1
- package/dist/components/forms/select/select.class.js +1 -1
- package/dist/components/forms/slider/slider.class.d.ts +0 -1
- package/dist/components/forms/slider/slider.class.js +1 -1
- package/dist/components/forms/switch/switch.class.d.ts +0 -1
- package/dist/components/forms/switch/switch.class.js +1 -1
- package/dist/components/forms/time-range/time-range.class.d.ts +0 -1
- package/dist/components/forms/time-range/time-range.class.js +1 -1
- package/dist/components/forms/token-input/token-input.class.d.ts +0 -1
- 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/dashboard-grid/layout-internal.d.ts +0 -1
- package/dist/components/layout/dashboard-grid/layout-internal.js +1 -1
- package/dist/components/layout/details/accordion-owner.d.ts +1 -1
- 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/menu/menu-item.class.js +1 -1
- package/dist/components/layout/virtual-list/virtual-list.class.js +1 -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/av-player/av-metadata.d.ts +0 -2
- package/dist/components/media/av-player/av-metadata.js +1 -1
- package/dist/components/media/file-input/file-input.class.d.ts +0 -1
- 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.class.d.ts +8 -0
- package/dist/components/media/flag/flag.class.js +1 -1
- package/dist/components/media/map/map-loader.d.ts +4 -1
- package/dist/components/media/map/map.class.d.ts +242 -23
- package/dist/components/media/map/map.class.js +2 -2
- 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/overlays/overlay/popover.class.d.ts +7 -1
- package/dist/components/overlays/overlay/popover.class.js +1 -1
- package/dist/components/overlays/overlay/tooltip.class.d.ts +1 -0
- package/dist/components/overlays/overlay/tooltip.class.js +1 -1
- package/dist/components/overlays/progress/progress-shared.d.ts +0 -2
- package/dist/components/overlays/progress/progress-shared.js +1 -1
- package/dist/components/overlays/rating/rating.class.js +1 -1
- package/dist/components/retrieval/graph/graph-canvas.d.ts +10 -9
- package/dist/components/retrieval/mind-map/mind-map-layout.d.ts +0 -4
- package/dist/components/retrieval/mind-map/mind-map-layout.js +1 -1
- package/dist/components/utility/format/format-options.d.ts +0 -2
- package/dist/components/utility/format/format-options.js +1 -1
- package/dist/components/utility/icon/icon-resource.d.ts +0 -2
- package/dist/components/utility/icon/icon-resource.js +1 -1
- package/dist/components/viewers/archive-viewer/zip-resource-guard.d.ts +2 -1
- package/dist/components/viewers/docx-viewer/docx-resource-guard.d.ts +0 -3
- package/dist/components/viewers/docx-viewer/docx-resource-guard.js +1 -1
- package/dist/components/viewers/ebook-viewer/ebook-loader.d.ts +2 -1
- package/dist/components/viewers/ebook-viewer/epub-resource-guard.d.ts +0 -3
- package/dist/components/viewers/ebook-viewer/epub-resource-guard.js +1 -1
- package/dist/components/viewers/pdf-viewer/pdf-loader.d.ts +2 -2
- package/dist/components/viewers/pdf-viewer/pdf-viewer.class.js +2 -2
- package/dist/components/viewers/pptx-viewer/pptx-resource-guard.d.ts +0 -2
- package/dist/components/viewers/pptx-viewer/pptx-resource-guard.js +1 -1
- package/dist/components/viewers/spreadsheet-viewer/xlsx-resource-guard.d.ts +0 -5
- package/dist/components/viewers/spreadsheet-viewer/xlsx-resource-guard.js +1 -1
- package/dist/custom-elements-jsx.d.ts +16 -8
- package/dist/events.d.ts +15 -0
- package/dist/internal/accessibility-visibility.d.ts +1 -1
- package/dist/internal/anchor-target.d.ts +1 -3
- package/dist/internal/anchor-target.js +2 -2
- package/dist/internal/anchored-overlay-runtime.d.ts +7 -0
- package/dist/internal/anchored-overlay-runtime.js +1 -0
- package/dist/internal/announcement-text.d.ts +1 -1
- package/dist/internal/ansi.d.ts +0 -4
- package/dist/internal/ansi.js +1 -1
- package/dist/internal/aria-ownership.d.ts +2 -1
- 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/default-strings.generated.d.ts +1 -0
- package/dist/internal/default-strings.generated.js +1 -1
- package/dist/internal/focus-navigation.d.ts +3 -2
- package/dist/internal/form-associated.d.ts +0 -1
- package/dist/internal/form-associated.js +1 -1
- package/dist/internal/form-control-labels.d.ts +0 -3
- package/dist/internal/form-control-labels.js +1 -1
- package/dist/internal/localization-runtime.js +1 -1
- package/dist/internal/localization-types.d.ts +1 -1
- package/dist/internal/localization.js +1 -1
- package/dist/internal/lyra-element.d.ts +7 -14
- package/dist/internal/lyra-element.js +1 -1
- package/dist/internal/nonmodal-overlay-manager.d.ts +9 -0
- package/dist/internal/nonmodal-overlay-manager.js +1 -0
- package/dist/internal/overlay-manager.d.ts +4 -20
- package/dist/internal/overlay-manager.js +1 -1
- package/dist/internal/overlay-stack.d.ts +66 -0
- package/dist/internal/overlay-stack.js +1 -0
- package/dist/internal/package-metadata.d.ts +1 -1
- package/dist/internal/package-metadata.js +1 -1
- package/dist/internal/positioner.js +1 -1
- package/dist/internal/root-registration-allowlist.d.ts +1 -1
- package/dist/internal/root-registration-allowlist.js +1 -1
- package/dist/internal/text-quote.d.ts +1 -1
- package/dist/lyra.d.ts +5 -4
- 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 +17 -8
- package/dist/translations/ar.js +1 -1
- package/dist/translations/de.js +1 -1
- package/dist/translations/es.js +1 -1
- package/dist/translations/fa.js +1 -1
- package/dist/translations/fr.js +1 -1
- package/dist/translations/he.js +1 -1
- package/dist/translations/ja.js +1 -1
- package/dist/translations/pt-BR.js +1 -1
- package/dist/translations/ru.js +1 -1
- package/dist/translations/zh-CN.js +1 -1
- package/dist/utilities/localization.js +1 -1
- package/dist/vue.d.ts +16 -8
- 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-combobox.md +42 -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 +14 -0
- package/llms/components/lr-funnel.md +122 -0
- package/llms/components/lr-heatmap.md +55 -8
- package/llms/components/lr-lite-chart.md +20 -8
- package/llms/components/lr-map.md +109 -22
- package/llms/components/lr-option.md +42 -0
- package/llms/components/lr-popover.md +39 -0
- package/llms/components/lr-table.md +7 -3
- package/llms/components/lr-timeline-item.md +49 -24
- package/llms/components/lr-timeline.md +49 -24
- package/llms/components/lr-widget.md +7 -1
- package/llms/index.md +3 -2
- package/llms/peers.md +1 -1
- package/llms/shared.md +110 -1
- package/llms-full.txt +681 -67
- package/llms.txt +1 -1
- package/package.json +26 -8
- package/vscode-css-data.json +63 -0
- package/vscode-html-data.json +108 -23
- package/web-types.json +32738 -310
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import{css}from"lit";const styles=css`
|
|
2
|
+
:host {
|
|
3
|
+
display: block;
|
|
4
|
+
font-family: var(--lr-font);
|
|
5
|
+
color: var(--lr-color-text);
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
[part='base'] {
|
|
9
|
+
min-inline-size: 0;
|
|
10
|
+
container-type: inline-size;
|
|
11
|
+
contain-intrinsic-inline-size: var(--lr-size-16rem);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
[part='stages'] {
|
|
15
|
+
list-style: none;
|
|
16
|
+
margin: 0;
|
|
17
|
+
padding: 0;
|
|
18
|
+
display: flex;
|
|
19
|
+
flex-direction: column;
|
|
20
|
+
gap: var(--lr-space-s);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
[part='stage'] {
|
|
24
|
+
display: flex;
|
|
25
|
+
flex-direction: column;
|
|
26
|
+
gap: var(--lr-space-2xs);
|
|
27
|
+
min-inline-size: 0;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
[part='dropoff'] {
|
|
31
|
+
font-size: var(--lr-font-size-xs);
|
|
32
|
+
color: var(--lr-color-text-quiet);
|
|
33
|
+
align-self: flex-start;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
[part='stage-header'] {
|
|
37
|
+
display: flex;
|
|
38
|
+
flex-wrap: wrap;
|
|
39
|
+
align-items: baseline;
|
|
40
|
+
gap: var(--lr-space-2xs) var(--lr-space-xs);
|
|
41
|
+
min-inline-size: 0;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
[part='stage-label'] {
|
|
45
|
+
flex: 1 1 auto;
|
|
46
|
+
min-inline-size: 0;
|
|
47
|
+
font-size: var(--lr-font-size-sm);
|
|
48
|
+
overflow-wrap: anywhere;
|
|
49
|
+
text-align: start;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
[part='stage-value'] {
|
|
53
|
+
font-size: var(--lr-font-size-sm);
|
|
54
|
+
font-weight: var(--lr-font-weight-semibold);
|
|
55
|
+
font-variant-numeric: tabular-nums;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
[part='stage-share'] {
|
|
59
|
+
font-size: var(--lr-font-size-sm);
|
|
60
|
+
color: var(--lr-color-text-quiet);
|
|
61
|
+
font-variant-numeric: tabular-nums;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
[part='comparison-value'] {
|
|
65
|
+
flex-basis: 100%;
|
|
66
|
+
font-size: var(--lr-font-size-xs);
|
|
67
|
+
color: var(--lr-color-text-quiet);
|
|
68
|
+
text-align: start;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
[part='track'] {
|
|
72
|
+
position: relative;
|
|
73
|
+
display: block;
|
|
74
|
+
inline-size: 100%;
|
|
75
|
+
block-size: var(--lr-funnel-bar-size, var(--lr-size-1-5rem));
|
|
76
|
+
background: var(--lr-funnel-track-color, var(--lr-color-surface-raised));
|
|
77
|
+
border-radius: var(--lr-radius-xs);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
[part~='bar'],
|
|
81
|
+
[part='comparison-bar'] {
|
|
82
|
+
position: absolute;
|
|
83
|
+
inset-inline-start: 0;
|
|
84
|
+
border-radius: inherit;
|
|
85
|
+
transition: inline-size var(--lr-transition-base);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
[part='comparison-bar'] {
|
|
89
|
+
inset-block: 0;
|
|
90
|
+
border: var(--lr-size-1px) dashed
|
|
91
|
+
var(--lr-funnel-comparison-color, var(--lr-color-border-strong));
|
|
92
|
+
background: none;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
[part~='bar'] {
|
|
96
|
+
inset-block: 0;
|
|
97
|
+
background: var(--lr-funnel-bar-color, var(--lr-color-brand));
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
[part='comparison-bar'] ~ [part~='bar'] {
|
|
101
|
+
inset-block: var(--lr-size-0-25rem);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
[part~='bar-overflow'] {
|
|
105
|
+
border-inline-end: var(--lr-size-3px) solid var(--lr-color-text);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
[part='empty'] {
|
|
109
|
+
margin: 0;
|
|
110
|
+
font-size: var(--lr-font-size-sm);
|
|
111
|
+
color: var(--lr-color-text-quiet);
|
|
112
|
+
text-align: start;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
@container (max-inline-size: 18rem) {
|
|
116
|
+
[part='stage-label'] {
|
|
117
|
+
flex-basis: 100%;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
@media (prefers-reduced-motion: reduce) {
|
|
122
|
+
[part~='bar'],
|
|
123
|
+
[part='comparison-bar'] {
|
|
124
|
+
transition: none;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
`;export{styles};
|
|
@@ -1,7 +1,6 @@
|
|
|
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';
|
|
5
4
|
import { type FormOwnerValue } from '../../../internal/form-associated.js';
|
|
6
5
|
/** Traversal direction relative to the matched node(s): `'out'` (outgoing edges), `'in'`
|
|
7
6
|
* (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"../../../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`
|
|
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{installFormControlLabelSupport}from"../../../internal/form-control-labels.js";installFormControlLabelSupport();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
|
|
@@ -227,6 +239,22 @@ export interface LyraHeatmapEventMap {
|
|
|
227
239
|
* focus, its semantic matrix coordinate or calendar date remains the sole roving stop; removal
|
|
228
240
|
* clamps to the nearest survivor, or to the stable heatmap base when no interactive cells remain.
|
|
229
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
|
+
*
|
|
230
258
|
* Calendar `data.columnX` overrides the x-origin computed for each
|
|
231
259
|
* week column — drawing, hit-testing, the focus ring, and month-label
|
|
232
260
|
* positioning all consult it consistently, so a consumer can pixel-align a
|
|
@@ -271,9 +299,14 @@ export interface LyraHeatmapEventMap {
|
|
|
271
299
|
* resize. `detail` is the same object `matrixGeometry` returns. Never fired in calendar mode.
|
|
272
300
|
* @csspart base - The heatmap wrapper.
|
|
273
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`.
|
|
274
305
|
* @csspart cells - The opt-in per-cell accessibility overlay.
|
|
275
306
|
* @csspart cell - An opt-in native button for one matrix or calendar cell.
|
|
276
|
-
* @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.
|
|
277
310
|
* @csspart live-region - An aria-hidden shadow mirror of the keyboard announcement; the actual
|
|
278
311
|
* announcement uses the shared light-DOM polite sink.
|
|
279
312
|
* @csspart projection-limit - Localized assistive disclosure for bounded projections.
|
|
@@ -294,6 +327,8 @@ export interface LyraHeatmapEventMap {
|
|
|
294
327
|
* @cssprop [--lr-heatmap-focus-ring-color=var(--lr-focus-ring-color)] - Focus ring around a focused cell.
|
|
295
328
|
* @cssprop [--lr-heatmap-annotation-color=var(--lr-color-danger)] - Border color for an annotated cell.
|
|
296
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.
|
|
297
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.
|
|
298
333
|
* @status stable
|
|
299
334
|
* @since 4.0.0
|
|
@@ -357,6 +392,46 @@ export declare class LyraHeatmap extends LyraElement<LyraHeatmapEventMap> {
|
|
|
357
392
|
* would be incoherent.
|
|
358
393
|
*/
|
|
359
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();
|
|
360
435
|
/** Column band resolved during the last draw, mirroring `resolvedRowLabelWidth`. */
|
|
361
436
|
private resolvedColLabelHeight;
|
|
362
437
|
/** Normalized rotation in degrees: finite, clamped to `[0, 90]`. */
|
|
@@ -370,17 +445,26 @@ export declare class LyraHeatmap extends LyraElement<LyraHeatmapEventMap> {
|
|
|
370
445
|
* `{ padLeft, padTop, cellSize }`, all in CSS pixels -- so a light-DOM consumer (e.g. a sticky
|
|
371
446
|
* header mirror) can line up with the canvas without hardcoding the same numbers `row-label-width`
|
|
372
447
|
* or `col-label-height`'s `"auto"` resolution would otherwise keep private. `undefined` in
|
|
373
|
-
* calendar mode, and before the first matrix draw.
|
|
374
|
-
*
|
|
375
|
-
* `lr-matrix-geometry-change`
|
|
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.
|
|
376
460
|
*/
|
|
377
461
|
get matrixGeometry(): Readonly<LyraHeatmapMatrixGeometryChangeDetail> | undefined;
|
|
378
|
-
/**
|
|
379
|
-
*
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
*
|
|
383
|
-
private
|
|
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?;
|
|
384
468
|
private get matrixPadTop();
|
|
385
469
|
/** Tallest rotated column label plus inset, floored at the built-in band and capped so labels can
|
|
386
470
|
* never crowd out the matrix. The column mirror of `measureRowLabelWidth()`. */
|
|
@@ -537,7 +621,10 @@ export declare class LyraHeatmap extends LyraElement<LyraHeatmapEventMap> {
|
|
|
537
621
|
* Strictly presentation: the stops are never consulted by the color ramp, the bucket math, the
|
|
538
622
|
* tooltip, or the accessible name — supplying them changes nothing a cell renders. Any
|
|
539
623
|
* `annotations` with a `label` still render their `[part="legend-annotation"]` entries after
|
|
540
|
-
* the stops.
|
|
624
|
+
* the stops. Reassigning stops whose supported fields are unchanged does not schedule a redraw;
|
|
625
|
+
* every assignment is still clone-owned, so mutating and reassigning the caller's array is
|
|
626
|
+
* detected without exposing that mutation in place. Unset (the default) or an empty array
|
|
627
|
+
* reproduces today's exact gradient legend.
|
|
541
628
|
*/
|
|
542
629
|
legendStops?: readonly HeatmapLegendStop[];
|
|
543
630
|
/**
|
|
@@ -768,6 +855,10 @@ export declare class LyraHeatmap extends LyraElement<LyraHeatmapEventMap> {
|
|
|
768
855
|
private labelColor;
|
|
769
856
|
/** Reads the customizable canvas axis/label font off the host's computed style. */
|
|
770
857
|
private labelFont;
|
|
858
|
+
/** Reads the customizable frozen-label-band backdrop off the host's computed style, resolved to a
|
|
859
|
+
* concrete color: canvas silently keeps its previous `fillStyle` for anything it cannot parse,
|
|
860
|
+
* and a `var()` chain is exactly that. */
|
|
861
|
+
private stickyLabelBg;
|
|
771
862
|
/** Reads the customizable no-data cell fill off the host's computed style. */
|
|
772
863
|
private noDataFill;
|
|
773
864
|
/** Reads the customizable canvas-drawn keyboard-focus-ring stroke color off the host's computed style. */
|
|
@@ -898,6 +989,32 @@ export declare class LyraHeatmap extends LyraElement<LyraHeatmapEventMap> {
|
|
|
898
989
|
private paintCalendarFocusOverlays;
|
|
899
990
|
private repaintCalendarFocusCell;
|
|
900
991
|
private drawMatrix;
|
|
992
|
+
/** Paints the row-label gutter at `x = 0 .. padLeft`. Extracted so the cell canvas and a frozen
|
|
993
|
+
* `[part="row-labels"]` band paint from one routine and one set of geometry arguments — the
|
|
994
|
+
* band's own canvas shares the cell canvas's origin, so "aligned" is what the same coordinates
|
|
995
|
+
* mean, rather than something a second implementation has to keep agreeing about. */
|
|
996
|
+
private paintMatrixRowLabels;
|
|
997
|
+
/** The column-label band at `y = 0 .. padTop`, rotation included. The mirror of
|
|
998
|
+
* `paintMatrixRowLabels()`, shared with a frozen `[part="col-labels"]` band the same way. */
|
|
999
|
+
private paintMatrixColLabels;
|
|
1000
|
+
/**
|
|
1001
|
+
* Repaints whichever label bands `stickyLabels` freezes, from the geometry this very draw pass
|
|
1002
|
+
* painted the cells with. Each band is a canvas sharing the cell canvas's origin (both sit in the
|
|
1003
|
+
* same single-area grid), sized to the band it owns and offset on one axis only by
|
|
1004
|
+
* `position: sticky`, so it slides along the axis it is not frozen on and stays put on the one it
|
|
1005
|
+
* is. Nothing here recomputes geometry, which is what keeps a band aligned across a resize, a DPR
|
|
1006
|
+
* change, and a `row-label-width`/`col-label-height` `"auto"` re-resolution alike.
|
|
1007
|
+
*
|
|
1008
|
+
* The cell canvas keeps painting its own labels underneath: leaving that pass untouched is what
|
|
1009
|
+
* makes the default `'none'` byte-identical, and the band's opaque backdrop covers the duplicate
|
|
1010
|
+
* once it scrolls out from under the frozen copy.
|
|
1011
|
+
*/
|
|
1012
|
+
private paintFrozenLabelBands;
|
|
1013
|
+
private frozenBandCanvas;
|
|
1014
|
+
/** Sizes one band's backing store to the same DPR the cell canvas uses, fills the opaque backdrop,
|
|
1015
|
+
* then hands the caller a context already in CSS-pixel coordinates identical to the cell
|
|
1016
|
+
* canvas's — so a label lands on the same physical pixel in both. */
|
|
1017
|
+
private paintFrozenBand;
|
|
901
1018
|
/**
|
|
902
1019
|
* Maps a pointer position, in canvas-local CSS px (e.g.
|
|
903
1020
|
* `PointerEvent.offsetX/offsetY`), to the cell underneath it — or `null`
|
|
@@ -940,7 +1057,7 @@ export declare class LyraHeatmap extends LyraElement<LyraHeatmapEventMap> {
|
|
|
940
1057
|
* `CalendarCellPos` in this component goes through here, so no call site can forget the date. */
|
|
941
1058
|
private calendarPos;
|
|
942
1059
|
/**
|
|
943
|
-
* Pixel rect (canvas-local CSS px) of a cell — shared by `
|
|
1060
|
+
* Pixel rect (canvas-local CSS px) of a cell — shared by `tooltipAnchor()`
|
|
944
1061
|
* so the tooltip's position always agrees with the same geometry
|
|
945
1062
|
* `drawMatrix()`/`drawCalendar()`/`hitTest*()` use.
|
|
946
1063
|
*/
|
|
@@ -968,8 +1085,53 @@ export declare class LyraHeatmap extends LyraElement<LyraHeatmapEventMap> {
|
|
|
968
1085
|
* wording anywhere around the cell text instead of it being appended. */
|
|
969
1086
|
private announce;
|
|
970
1087
|
private emitCellClick;
|
|
971
|
-
/**
|
|
972
|
-
private
|
|
1088
|
+
/** The `stickyLabels` scrollport, or `null` in the default unfrozen render, which has none. */
|
|
1089
|
+
private get gridScrollport();
|
|
1090
|
+
/** The tooltip's own rendered box in CSS px, recorded by `measureTooltip()`: `inline` is its
|
|
1091
|
+
* border box, `block` that box plus the token-sized gap it keeps from the cell. Only read while
|
|
1092
|
+
* a scrollport can clip it; zero until the first measurement, which degrades to the unclamped
|
|
1093
|
+
* placement rather than to a wrong one. */
|
|
1094
|
+
private tooltipSize;
|
|
1095
|
+
/**
|
|
1096
|
+
* Records the tooltip's rendered size, so the next paint can keep it inside the `stickyLabels`
|
|
1097
|
+
* scrollport. Measured rather than derived: the box is sized by caller text, and the gap it
|
|
1098
|
+
* keeps from the cell is a design token whose value belongs in the stylesheet.
|
|
1099
|
+
*
|
|
1100
|
+
* Repositioning can never resize it (`white-space: nowrap`, no inline-size constraint), so the
|
|
1101
|
+
* re-render scheduled here always settles in one step. It runs from `scheduleAfterUpdate()`
|
|
1102
|
+
* rather than straight out of `updated()` on purpose: that keeps the `requestUpdate()` outside
|
|
1103
|
+
* Lit's own update cycle, and its microtask still flushes before paint, so the corrected
|
|
1104
|
+
* position is the first one the user ever sees.
|
|
1105
|
+
*/
|
|
1106
|
+
private measureTooltip;
|
|
1107
|
+
/**
|
|
1108
|
+
* Inline `style` for `[part="tooltip"]` — centered on the given cell — plus whether it had to be
|
|
1109
|
+
* flipped below that cell.
|
|
1110
|
+
*
|
|
1111
|
+
* With no `stickyLabels` scrollport this is the original unconditional "centered above the cell"
|
|
1112
|
+
* placement, in the canvas-local coordinates `cellRect()` returns. With one, the tooltip renders
|
|
1113
|
+
* *inside* that scrollport, which is what keeps it pinned to the cell it describes through a
|
|
1114
|
+
* scroll — and there `overflow: auto` clips whatever leaves the scrollport, while an opaque
|
|
1115
|
+
* frozen band hides whatever is drawn under it. So the placement is additionally kept inside the
|
|
1116
|
+
* band-free part of the visible window: still centered on the cell but clamped to that window,
|
|
1117
|
+
* and flipped to below the cell when there is no room above it and there is room below. Flipping
|
|
1118
|
+
* is conditional on both, deliberately: an unconditional flip at the block end would push the
|
|
1119
|
+
* tooltip past the content box and grow the scrollable area under the pointer.
|
|
1120
|
+
*/
|
|
1121
|
+
private tooltipAnchor;
|
|
1122
|
+
/**
|
|
1123
|
+
* Keeps the keyboard-focused cell inside the `stickyLabels` scrollport, clear of the frozen
|
|
1124
|
+
* bands' own boxes.
|
|
1125
|
+
*
|
|
1126
|
+
* Without this the feature is an accessibility regression: the default (unset `accessibleCells`)
|
|
1127
|
+
* roving stop is the canvas itself, its focus ring is painted into the canvas bitmap rather than
|
|
1128
|
+
* carried by a focusable element the browser would scroll to, and `onMatrixKeyDown()` calls
|
|
1129
|
+
* `preventDefault()` on every arrow — so the browser's own scrolling never happens either, and
|
|
1130
|
+
* arrowing far enough leaves the focus indicator off-screen with no keyboard way to reveal it.
|
|
1131
|
+
* A minimal scroll (never re-centering a cell that is already fully visible) keeps the scroll
|
|
1132
|
+
* position stable while arrowing around inside the visible window.
|
|
1133
|
+
*/
|
|
1134
|
+
private scrollCellIntoView;
|
|
973
1135
|
/**
|
|
974
1136
|
* Value-equality check for a `CellPos`, since `hoverCell` is assigned a
|
|
975
1137
|
* fresh object literal on every `pointermove` — Lit's `@state()`
|
|
@@ -1016,6 +1178,29 @@ export declare class LyraHeatmap extends LyraElement<LyraHeatmapEventMap> {
|
|
|
1016
1178
|
* unset (or empty) `legendStops` therefore reproduces the pre-`legendStops` markup exactly.
|
|
1017
1179
|
*/
|
|
1018
1180
|
private renderLegendScale;
|
|
1181
|
+
/**
|
|
1182
|
+
* The cell canvas, the opt-in per-cell overlay, and — while `stickyLabels` freezes an axis — the
|
|
1183
|
+
* frozen label bands, wrapped in the scrollport those bands stick to.
|
|
1184
|
+
*
|
|
1185
|
+
* Both branches emit the same canvas and overlay from one template, so the unfrozen default keeps
|
|
1186
|
+
* rendering exactly the elements it always did (no wrapper, no scrollport, no second canvas) with
|
|
1187
|
+
* no second copy of the canvas's attribute/listener surface to drift. The bands are decorative
|
|
1188
|
+
* duplicates of pixels the cell canvas already painted, so they carry `aria-hidden` and no role:
|
|
1189
|
+
* the accessible representation stays the canvas's own `role="application"` name, or the
|
|
1190
|
+
* `[part="cells"]` grid under `accessibleCells` — which moves inside the scrollport so the cells
|
|
1191
|
+
* scroll with the canvas they overlay.
|
|
1192
|
+
*/
|
|
1193
|
+
private renderGridSurface;
|
|
1194
|
+
/**
|
|
1195
|
+
* The hover tooltip, rendered once: inside the `stickyLabels` scrollport's stack when an axis is
|
|
1196
|
+
* frozen (see `renderGridSurface()`), and as the `[part="base"]` sibling it has always been
|
|
1197
|
+
* otherwise, where the canvas's origin already *is* the base's.
|
|
1198
|
+
*
|
|
1199
|
+
* `dir` is carried explicitly because the scrollport pins `direction: ltr` for the physically
|
|
1200
|
+
* non-mirrored grid geometry, and the tooltip is the one thing in there that is prose rather
|
|
1201
|
+
* than geometry -- it keeps the host's own direction it inherited before the scrollport existed.
|
|
1202
|
+
*/
|
|
1203
|
+
private renderTooltip;
|
|
1019
1204
|
render(): TemplateResult;
|
|
1020
1205
|
/** `localize()` interpolates with a bare `String(value)`, so a number handed to it renders in
|
|
1021
1206
|
* ASCII digits no matter the locale -- mixing two numbering systems inside one translated
|