@teipublisher/pb-components 2.26.1-next.3 → 3.0.0-next-4.1
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/.github/workflows/docker-cypress.yml +54 -0
- package/.github/workflows/main.yml +6 -4
- package/.github/workflows/node.js.yml +56 -21
- package/.github/workflows/release.js.yml +19 -17
- package/.releaserc.json +1 -1
- package/CHANGELOG.md +346 -11
- package/Dockerfile +78 -70
- package/README.md +112 -4
- package/css/components.css +5 -5
- package/css/gridjs/mermaid.min.css +1 -1
- package/css/leaflet/Control.Geocoder.css +1 -126
- package/css/leaflet/images/layers.png +0 -0
- package/css/tify/tify.css +6 -5
- package/css/tom-select/tom-select.bootstrap4.min.css +1 -1
- package/css/tom-select/tom-select.bootstrap5.min.css +1 -1
- package/css/tom-select/tom-select.default.min.css +1 -1
- package/css/tom-select/tom-select.default.min.css.map +1 -0
- package/css/tom-select/tom-select.min.css +1 -1
- package/cypress.config.js +84 -0
- package/dist/api.html +1 -1
- package/dist/css/design-system.css +607 -0
- package/dist/demo/bundle-test.html +4 -3
- package/dist/demo/components.css +46 -1
- package/dist/demo/design-system.html +710 -0
- package/dist/demo/dts-client.html +2 -2
- package/dist/demo/pb-autocomplete.html +23 -11
- package/dist/demo/pb-autocomplete2.html +66 -55
- package/dist/demo/pb-autocomplete3.html +17 -8
- package/dist/demo/pb-blacklab-highlight.html +28 -11
- package/dist/demo/pb-blacklab-results.html +3 -2
- package/dist/demo/pb-browse-docs.html +24 -24
- package/dist/demo/pb-browse-docs2.html +3 -3
- package/dist/demo/pb-clipboard.html +32 -28
- package/dist/demo/pb-code-editor.html +6 -6
- package/dist/demo/pb-code-highlight.html +63 -63
- package/dist/demo/pb-codepen.html +1 -1
- package/dist/demo/pb-collapse.html +1 -1
- package/dist/demo/pb-collapse2.html +2 -2
- package/dist/demo/pb-combo-box.html +135 -130
- package/dist/demo/pb-custom-form.html +64 -55
- package/dist/demo/pb-dialog.html +12 -6
- package/dist/demo/pb-document.html +1 -1
- package/dist/demo/pb-download.html +68 -59
- package/dist/demo/pb-drawer.html +67 -46
- package/dist/demo/pb-drawer2.html +65 -58
- package/dist/demo/pb-edit-app.html +2 -2
- package/dist/demo/pb-edit-xml.html +1 -1
- package/dist/demo/pb-facsimile-2.html +26 -11
- package/dist/demo/pb-facsimile-3.html +25 -10
- package/dist/demo/pb-facsimile-dedup-test-2.html +48 -0
- package/dist/demo/pb-facsimile-dedup-test.html +48 -0
- package/dist/demo/pb-facsimile.html +4 -4
- package/dist/demo/pb-formula.html +1 -1
- package/dist/demo/pb-grid.html +22 -8
- package/dist/demo/pb-highlight.html +2 -2
- package/dist/demo/pb-i18n-simple.html +1 -0
- package/dist/demo/pb-i18n.html +15 -5
- package/dist/demo/pb-image-strip-standalone.html +2 -2
- package/dist/demo/pb-image-strip-view.html +2 -2
- package/dist/demo/pb-leaflet-map.html +3 -3
- package/dist/demo/pb-leaflet-map2.html +2 -2
- package/dist/demo/pb-leaflet-map3.html +3 -3
- package/dist/demo/pb-link.html +1 -1
- package/dist/demo/pb-load.html +2 -6
- package/dist/demo/pb-login.html +1 -3
- package/dist/demo/pb-manage-odds.html +9 -4
- package/dist/demo/pb-markdown.html +1 -1
- package/dist/demo/pb-media-query.html +2 -2
- package/dist/demo/pb-mei.html +2 -2
- package/dist/demo/pb-mei2.html +2 -2
- package/dist/demo/pb-message.html +2 -3
- package/dist/demo/pb-odd-editor.html +54 -52
- package/dist/demo/pb-page-header.html +27 -0
- package/dist/demo/pb-popover.html +1 -1
- package/dist/demo/pb-print-preview.html +2 -2
- package/dist/demo/pb-progress.html +4 -4
- package/dist/demo/pb-repeat.html +32 -36
- package/dist/demo/pb-search.html +16 -5
- package/dist/demo/pb-search2.html +4 -4
- package/dist/demo/pb-search3.html +3 -3
- package/dist/demo/pb-search4.html +3 -3
- package/dist/demo/pb-select-feature.html +4 -4
- package/dist/demo/pb-select-feature2.html +4 -4
- package/dist/demo/pb-select-feature3.html +2 -2
- package/dist/demo/pb-select-i18n.html +58 -53
- package/dist/demo/pb-select-odd.html +1 -1
- package/dist/demo/pb-select.html +190 -75
- package/dist/demo/pb-select2.html +91 -37
- package/dist/demo/pb-select3.html +109 -41
- package/dist/demo/pb-svg.html +1 -1
- package/dist/demo/pb-table-grid.html +26 -15
- package/dist/demo/pb-tabs.html +15 -7
- package/dist/demo/pb-tify.html +7 -7
- package/dist/demo/pb-timeline.html +1 -1
- package/dist/demo/pb-timeline2.html +1 -1
- package/dist/demo/pb-toggle-feature.html +26 -23
- package/dist/demo/pb-toggle-feature2.html +4 -4
- package/dist/demo/pb-toggle-feature3.html +2 -2
- package/dist/demo/pb-toggle-feature4.html +56 -54
- package/dist/demo/pb-version.html +2 -2
- package/dist/demo/pb-view.html +78 -40
- package/dist/demo/pb-view2.html +69 -46
- package/dist/demo/pb-view3.html +53 -48
- package/dist/demo/pb-view4.html +70 -49
- package/dist/demo/pb-zoom.html +2 -2
- package/dist/{es-global-bridge-d8ce175d.js → es-global-bridge-D8ZcUcx_.js} +0 -4
- package/dist/focus-mixin-VCsFap6b.js +768 -0
- package/dist/images/icons.svg +217 -0
- package/dist/jinn-codemirror-DETLdm08.js +1 -0
- package/dist/lib/openseadragon.min.js +80 -0
- package/dist/lib/openseadragon.min.js.map +1 -0
- package/dist/pb-code-editor.js +25 -20
- package/dist/pb-component-docs.js +414 -3225
- package/dist/pb-components-bundle.js +3046 -4402
- package/dist/pb-dialog-tklYGWfc.js +121 -0
- package/dist/pb-edit-app.js +208 -107
- package/dist/pb-elements.json +716 -249
- package/dist/pb-facsimile.js +46 -0
- package/dist/pb-i18n-C0NDma4h.js +1 -0
- package/dist/pb-leaflet-map.js +23 -23
- package/dist/pb-mei.js +152 -134
- package/dist/pb-mixin-DHoWQheB.js +1 -0
- package/dist/pb-odd-editor.js +1671 -1231
- package/dist/pb-tify.js +1 -27
- package/dist/unsafe-html-D5VGo9Oq.js +1 -0
- package/dist/urls-BEONu_g4.js +1 -0
- package/eslint.config.mjs +92 -0
- package/gh-pages.js +5 -3
- package/i18n/common/en.json +6 -0
- package/i18n/common/pl.json +2 -2
- package/images/icons.svg +217 -0
- package/index.html +0 -5
- package/lib/leaflet-src.js.map +1 -0
- package/lib/leaflet.markercluster-src.js.map +1 -0
- package/lib/openseadragon.min.js +6 -6
- package/package.json +56 -81
- package/pb-elements.json +716 -249
- package/rollup.config.mjs +312 -0
- package/src/assets/components.css +5 -5
- package/src/assets/design-system.css +607 -0
- package/src/authority/airtable.js +20 -21
- package/src/authority/anton.js +129 -129
- package/src/authority/custom.js +70 -27
- package/src/authority/geonames.js +38 -32
- package/src/authority/gnd.js +50 -42
- package/src/authority/kbga.js +136 -134
- package/src/authority/metagrid.js +44 -46
- package/src/authority/reconciliation.js +66 -68
- package/src/authority/registry.js +4 -4
- package/src/docs/demo-utils.js +91 -0
- package/src/docs/pb-component-docs.js +287 -147
- package/src/docs/pb-component-view.js +380 -273
- package/src/docs/pb-components-list.js +115 -51
- package/src/docs/pb-demo-snippet.js +199 -174
- package/src/dts-client.js +306 -303
- package/src/dts-select-endpoint.js +125 -85
- package/src/parse-date-service.js +184 -135
- package/src/pb-ajax.js +175 -173
- package/src/pb-authority-lookup.js +198 -158
- package/src/pb-autocomplete.js +731 -313
- package/src/pb-blacklab-highlight.js +266 -260
- package/src/pb-blacklab-results.js +230 -225
- package/src/pb-browse-docs.js +601 -484
- package/src/pb-browse.js +68 -65
- package/src/pb-clipboard.js +97 -76
- package/src/pb-code-editor.js +111 -103
- package/src/pb-code-highlight.js +234 -204
- package/src/pb-codepen.js +81 -73
- package/src/pb-collapse.js +265 -152
- package/src/pb-combo-box.js +191 -191
- package/src/pb-components-bundle.js +1 -7
- package/src/pb-components.js +2 -6
- package/src/pb-custom-form.js +230 -141
- package/src/pb-dialog.js +99 -63
- package/src/pb-document.js +118 -91
- package/src/pb-download.js +214 -198
- package/src/pb-drawer.js +146 -149
- package/src/pb-edit-app.js +471 -240
- package/src/pb-edit-xml.js +101 -98
- package/src/pb-events.js +126 -107
- package/src/pb-facs-link.js +130 -101
- package/src/pb-facsimile.js +494 -410
- package/src/pb-fetch.js +389 -0
- package/src/pb-formula.js +152 -154
- package/src/pb-geolocation.js +130 -132
- package/src/pb-grid-action.js +59 -56
- package/src/pb-grid.js +388 -228
- package/src/pb-highlight.js +142 -142
- package/src/pb-hotkeys.js +40 -42
- package/src/pb-i18n.js +115 -127
- package/src/pb-icon-button.js +108 -0
- package/src/pb-icon.js +283 -0
- package/src/pb-image-strip.js +85 -79
- package/src/pb-lang.js +142 -57
- package/src/pb-leaflet-map.js +551 -483
- package/src/pb-link.js +132 -126
- package/src/pb-load.js +495 -428
- package/src/pb-login.js +303 -248
- package/src/pb-manage-odds.js +384 -338
- package/src/pb-map-icon.js +90 -90
- package/src/pb-map-layer.js +86 -86
- package/src/pb-markdown.js +107 -110
- package/src/pb-media-query.js +75 -73
- package/src/pb-mei.js +523 -303
- package/src/pb-message.js +144 -98
- package/src/pb-mixin.js +268 -265
- package/src/pb-navigation.js +83 -96
- package/src/pb-observable.js +39 -39
- package/src/pb-odd-editor.js +1209 -948
- package/src/pb-odd-elementspec-editor.js +375 -310
- package/src/pb-odd-model-editor.js +1189 -941
- package/src/pb-odd-parameter-editor.js +269 -170
- package/src/pb-odd-rendition-editor.js +184 -131
- package/src/pb-page.js +451 -422
- package/src/pb-paginate.js +260 -178
- package/src/pb-panel.js +217 -183
- package/src/pb-popover-themes.js +16 -9
- package/src/pb-popover.js +297 -288
- package/src/pb-print-preview.js +128 -128
- package/src/pb-progress.js +52 -52
- package/src/pb-repeat.js +141 -108
- package/src/pb-restricted.js +85 -78
- package/src/pb-search.js +258 -230
- package/src/pb-select-feature.js +210 -126
- package/src/pb-select-odd.js +184 -118
- package/src/pb-select-template.js +113 -78
- package/src/pb-select.js +330 -229
- package/src/pb-split-list.js +181 -176
- package/src/pb-svg.js +81 -80
- package/src/pb-table-column.js +55 -55
- package/src/pb-table-grid.js +334 -205
- package/src/pb-tabs.js +238 -61
- package/src/pb-tify.js +3331 -126
- package/src/pb-timeline.js +394 -255
- package/src/pb-toggle-feature.js +196 -188
- package/src/pb-upload.js +201 -176
- package/src/pb-version.js +22 -34
- package/src/pb-view-annotate.js +138 -102
- package/src/pb-view.js +1722 -1272
- package/src/pb-zoom.js +144 -46
- package/src/search-result-service.js +256 -223
- package/src/seed-element.js +14 -22
- package/src/settings.js +4 -4
- package/src/theming.js +98 -91
- package/src/urls.js +403 -289
- package/src/utils.js +53 -51
- package/vite.config.js +86 -0
- package/css/pb-styles.css +0 -51
- package/dist/iron-form-3b8dcaa7.js +0 -210
- package/dist/jinn-codemirror-da0e2d1f.js +0 -1
- package/dist/paper-checkbox-515a5284.js +0 -1597
- package/dist/paper-icon-button-b1d31571.js +0 -398
- package/dist/paper-listbox-a3b7175c.js +0 -1265
- package/dist/pb-i18n-0611135a.js +0 -1
- package/dist/pb-mixin-b1caa22e.js +0 -158
- package/dist/polymer-hack.js +0 -1
- package/dist/vaadin-element-mixin-fe4a4883.js +0 -527
- package/lib/Control.Geocoder.min.js +0 -2
- package/lib/Control.Geocoder.min.js.map +0 -1
- package/src/assets/pb-styles.css +0 -51
- package/src/pb-light-dom.js +0 -41
- package/src/polymer-hack.js +0 -6
package/src/pb-grid.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { LitElement, html, css } from 'lit
|
|
1
|
+
import { LitElement, html, css } from 'lit';
|
|
2
|
+
import { animate } from 'animejs';
|
|
2
3
|
import { pbMixin } from './pb-mixin.js';
|
|
3
|
-
import { registry } from
|
|
4
|
+
import { registry } from './urls.js';
|
|
4
5
|
import './pb-panel.js';
|
|
5
6
|
|
|
6
7
|
/**
|
|
@@ -15,265 +16,424 @@ import './pb-panel.js';
|
|
|
15
16
|
* @cssprop --pb-grid-column-gap - Width of the gap between columns
|
|
16
17
|
*/
|
|
17
18
|
export class PbGrid extends pbMixin(LitElement) {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
19
|
+
static get properties() {
|
|
20
|
+
return {
|
|
21
|
+
...super.properties,
|
|
22
|
+
/**
|
|
23
|
+
* an array of panel items to display when the component is loaded. It should contain a
|
|
24
|
+
* number for each panel to show, indicating the ordinal position of the template within the `<pb-panel>`
|
|
25
|
+
* to initialize. For example, if you have two templates in `<pb-panel>`: "transcription" and "translation",
|
|
26
|
+
* setting `panels="[0, 1]"` will show two columns, one with the transcription, the other with the translation.
|
|
27
|
+
*
|
|
28
|
+
* Passing in a browser parameter `panels` with a comma-separated list will set this property as well.
|
|
29
|
+
*/
|
|
30
|
+
panels: {
|
|
31
|
+
type: Array,
|
|
32
|
+
},
|
|
33
|
+
direction: {
|
|
34
|
+
type: String,
|
|
35
|
+
},
|
|
36
|
+
/**
|
|
37
|
+
* the number of columns
|
|
38
|
+
*/
|
|
39
|
+
_columns: {
|
|
40
|
+
type: Number,
|
|
41
|
+
},
|
|
42
|
+
/**
|
|
43
|
+
* CSS Selektor to choose elements to animate. If not specified all 'pb-view' elements will be animated by default.
|
|
44
|
+
*/
|
|
45
|
+
animated: {
|
|
46
|
+
type: String,
|
|
47
|
+
},
|
|
48
|
+
/**
|
|
49
|
+
* wether to animate the view when new page is loaded. Defaults to 'false' meaning that no
|
|
50
|
+
* animation takes place.
|
|
51
|
+
*/
|
|
52
|
+
animation: {
|
|
53
|
+
type: Boolean,
|
|
54
|
+
},
|
|
55
|
+
};
|
|
56
|
+
}
|
|
56
57
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
58
|
+
constructor() {
|
|
59
|
+
super();
|
|
60
|
+
this.panels = [];
|
|
61
|
+
this.direction = 'ltr';
|
|
62
|
+
this.animated = 'pb-view';
|
|
63
|
+
this.animation = false;
|
|
64
|
+
this._panelsInitialized = false; // Track if panels have been initialized from registry
|
|
65
|
+
}
|
|
64
66
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
+
connectedCallback() {
|
|
68
|
+
super.connectedCallback();
|
|
67
69
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
70
|
+
this.subscribeTo('pb-panel', ev => {
|
|
71
|
+
const idx = this._getPanelIndex(ev.detail.panel);
|
|
72
|
+
if (idx < 0) {
|
|
73
|
+
return; // panel not found
|
|
74
|
+
}
|
|
75
|
+
console.log('<pb-grid> Updating panel %d to show %s', idx, ev.detail.active);
|
|
76
|
+
// Update the panel's active template index (this is for pb-panel's internal state)
|
|
77
|
+
// BUT: Do NOT commit panels to registry - panels array should only change when panels are added/removed,
|
|
78
|
+
// not when a panel switches its active view. The panels parameter in the URL should remain stable.
|
|
79
|
+
// Only update the internal state, don't commit to registry
|
|
80
|
+
const panelIdx = this.direction === 'rtl' ? this.panels.length - idx - 1 : idx;
|
|
81
|
+
// Store the active template index for this panel, but don't change the panels array structure
|
|
82
|
+
// The panels array represents which panels are visible, not which template each panel is showing
|
|
83
|
+
// We'll track active templates separately if needed, but for now just log it
|
|
84
|
+
console.log('<pb-grid> Panel %d switched to template %s (not committing to registry)', panelIdx, ev.detail.active);
|
|
85
|
+
// DO NOT commit - panels parameter should remain stable
|
|
86
|
+
});
|
|
75
87
|
|
|
76
|
-
|
|
77
|
-
|
|
88
|
+
this.subscribeTo('pb-zoom', ev => {
|
|
89
|
+
this.zoom(ev.detail.direction);
|
|
90
|
+
});
|
|
78
91
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
92
|
+
// CRITICAL: Always prioritize registry value over template attribute
|
|
93
|
+
// The template may have panels="[0,1,2]" hardcoded, but the URL parameter should override it
|
|
94
|
+
const panelsParam = registry.get('panels');
|
|
95
|
+
if (panelsParam) {
|
|
96
|
+
// Parse panels from registry, but ensure we don't concatenate
|
|
97
|
+
// Split by '.' and parse each segment as integer
|
|
98
|
+
const parsed = panelsParam.split('.').map(param => parseInt(param, 10));
|
|
99
|
+
// Only use if all segments are valid numbers and reasonable (max 10 panels)
|
|
100
|
+
if (parsed.length > 0 && parsed.length <= 10 && parsed.every(p => !isNaN(p) && p >= 0 && p < 10)) {
|
|
101
|
+
console.log('<pb-grid> connectedCallback: Using panels from registry:', parsed, 'overriding template attribute');
|
|
102
|
+
this.panels = parsed;
|
|
103
|
+
this._panelsInitialized = true;
|
|
104
|
+
}
|
|
105
|
+
} else {
|
|
106
|
+
// No registry value - check if template attribute was set (LitElement may have already parsed it)
|
|
107
|
+
// If template has panels="[0,1,2]" but we want to use that only if no registry value exists
|
|
108
|
+
// But we should still mark as initialized to prevent duplicates
|
|
109
|
+
if (this.panels && this.panels.length > 0) {
|
|
110
|
+
console.log('<pb-grid> connectedCallback: Using panels from template attribute:', this.panels, '(no registry value)');
|
|
111
|
+
this._panelsInitialized = true;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
82
114
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
115
|
+
this._isUpdatingFromRegistry = false;
|
|
116
|
+
this._lastPanelsState = null; // Track last panels state to prevent duplicate rebuilds
|
|
117
|
+
registry.subscribe(this, state => {
|
|
118
|
+
console.log(
|
|
119
|
+
'<pb-grid> Registry subscribe callback triggered, _isUpdatingFromRegistry:',
|
|
120
|
+
this._isUpdatingFromRegistry,
|
|
121
|
+
'state.panels:',
|
|
122
|
+
state.panels,
|
|
123
|
+
);
|
|
124
|
+
// Only rebuild DOM if state change came from external source (e.g., browser navigation)
|
|
125
|
+
// not from our own registry.commit() calls
|
|
126
|
+
if (this._isUpdatingFromRegistry) {
|
|
127
|
+
console.log(
|
|
128
|
+
'<pb-grid> Skipping registry subscribe callback due to _isUpdatingFromRegistry flag',
|
|
129
|
+
);
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
const newState = state.panels ? state.panels.split('.').map(p => parseInt(p, 10)).filter(p => !isNaN(p)) : [];
|
|
133
|
+
const newStateStr = newState.join('.');
|
|
134
|
+
|
|
135
|
+
// Prevent duplicate rebuilds if panels haven't actually changed
|
|
136
|
+
if (this._lastPanelsState === newStateStr) {
|
|
137
|
+
console.log(
|
|
138
|
+
'<pb-grid> Skipping registry subscribe callback - panels state unchanged:',
|
|
139
|
+
newStateStr,
|
|
140
|
+
);
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Prevent rebuild if we haven't initialized yet (firstUpdated hasn't run)
|
|
145
|
+
// This prevents the registry callback from running before firstUpdated and creating duplicates
|
|
146
|
+
if (!this._panelsInitialized && !this.template) {
|
|
147
|
+
console.log(
|
|
148
|
+
'<pb-grid> Skipping registry subscribe callback - not yet initialized (template not ready)',
|
|
149
|
+
);
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
console.log('<pb-grid> Registry subscribe callback rebuilding DOM with panels:', newState, 'current panels:', this.panels);
|
|
154
|
+
this._lastPanelsState = newStateStr;
|
|
155
|
+
this.panels = newState;
|
|
156
|
+
this._panelsInitialized = true;
|
|
157
|
+
this.innerHTML = ''; // hard reset of child DOM
|
|
158
|
+
this.panels.forEach(panelNum => this._insertPanel(panelNum));
|
|
159
|
+
this._update();
|
|
160
|
+
});
|
|
161
|
+
this._columns = this.panels.length;
|
|
162
|
+
this.template = this.querySelector('template');
|
|
163
|
+
|
|
164
|
+
// If template is ready and we have panels but haven't initialized, mark as initialized
|
|
165
|
+
// This handles the case where template attribute was parsed before registry value was read
|
|
166
|
+
if (this.template && this.panels && this.panels.length > 0 && !this._panelsInitialized) {
|
|
167
|
+
console.log('<pb-grid> connectedCallback: Template ready, panels from attribute:', this.panels);
|
|
168
|
+
this._panelsInitialized = true;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
87
171
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
172
|
+
firstUpdated() {
|
|
173
|
+
// CRITICAL: Double-check registry value one more time before creating panels
|
|
174
|
+
// LitElement may have set this.panels from the template attribute before connectedCallback ran
|
|
175
|
+
// We need to ensure we use the registry value, not the template attribute
|
|
176
|
+
const panelsParam = registry.get('panels');
|
|
177
|
+
if (panelsParam) {
|
|
178
|
+
const parsed = panelsParam.split('.').map(param => parseInt(param, 10)).filter(p => !isNaN(p) && p >= 0 && p < 10);
|
|
179
|
+
if (parsed.length > 0 && parsed.length <= 10) {
|
|
180
|
+
const parsedStr = parsed.join('.');
|
|
181
|
+
const currentStr = this.panels.join('.');
|
|
182
|
+
if (parsedStr !== currentStr) {
|
|
183
|
+
console.log('<pb-grid> firstUpdated: Overriding template panels', this.panels, 'with registry value', parsed);
|
|
184
|
+
this.panels = parsed;
|
|
185
|
+
this._panelsInitialized = true;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// Only insert panels if they haven't been inserted yet
|
|
191
|
+
// This prevents duplicates if registry subscribe callback already created them
|
|
192
|
+
const existingPanels = this.querySelectorAll('._grid_panel').length;
|
|
193
|
+
if (existingPanels === 0 && this.panels && this.panels.length > 0) {
|
|
194
|
+
console.log('<pb-grid> firstUpdated: Inserting panels:', this.panels, 'existing panels:', existingPanels);
|
|
195
|
+
this.panels.forEach(panelNum => this._insertPanel(panelNum));
|
|
196
|
+
} else {
|
|
197
|
+
console.log('<pb-grid> firstUpdated: Skipping panel insertion - already have', existingPanels, 'panels');
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// Track initial state to prevent duplicate rebuilds
|
|
201
|
+
this._lastPanelsState = this._getState().panels;
|
|
202
|
+
this._isUpdatingFromRegistry = true;
|
|
203
|
+
// Only commit if panels state differs from what's already in the registry
|
|
204
|
+
// This prevents unnecessary URL updates during initialization
|
|
205
|
+
const currentPanels = registry.get('panels');
|
|
206
|
+
const newPanels = this._getState().panels;
|
|
207
|
+
if (currentPanels !== newPanels) {
|
|
208
|
+
registry.commit(this, this._getState());
|
|
97
209
|
}
|
|
210
|
+
this._isUpdatingFromRegistry = false;
|
|
211
|
+
this._animate();
|
|
212
|
+
this._update();
|
|
98
213
|
|
|
99
|
-
|
|
214
|
+
this.addEventListener('pb-drop', ev => {
|
|
215
|
+
const draggedPanelIdx = parseInt(ev.detail.panel);
|
|
216
|
+
const targetPanelIdx = this._getPanelIndex(ev.detail.target);
|
|
100
217
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
218
|
+
console.log(
|
|
219
|
+
'<pb-grid> Insert panel %d at %d in %s',
|
|
220
|
+
draggedPanelIdx,
|
|
221
|
+
targetPanelIdx,
|
|
222
|
+
this.panels,
|
|
223
|
+
);
|
|
224
|
+
this.querySelectorAll('._grid_panel').forEach(panel => {
|
|
225
|
+
panel.classList.remove('dragover');
|
|
226
|
+
});
|
|
105
227
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
228
|
+
this.panels.splice(targetPanelIdx, 0, this.panels.splice(draggedPanelIdx, 1)[0]);
|
|
229
|
+
this.innerHTML = ''; // hard reset of child DOM
|
|
230
|
+
this.panels.forEach(panelNum => this._insertPanel(panelNum));
|
|
231
|
+
this._isUpdatingFromRegistry = true;
|
|
232
|
+
registry.commit(this, this._getState());
|
|
233
|
+
this._isUpdatingFromRegistry = false;
|
|
234
|
+
this._update();
|
|
235
|
+
});
|
|
236
|
+
}
|
|
109
237
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
238
|
+
/**
|
|
239
|
+
* slides in all panels from left to right with a slight delay between the panels. If animejs is not
|
|
240
|
+
* loaded nothing happens and content is displayed as usual.
|
|
241
|
+
*/
|
|
242
|
+
_animate() {
|
|
243
|
+
if (this.animation) {
|
|
244
|
+
// console.log('animated elements', document.querySelectorAll('pb-panel'));
|
|
245
|
+
const animated = document.querySelectorAll(this.animated);
|
|
246
|
+
|
|
247
|
+
// Animate each element with a staggered delay
|
|
248
|
+
animated.forEach((element, index) => {
|
|
249
|
+
const animation = animate(element, {
|
|
250
|
+
opacity: [0, 0.6],
|
|
251
|
+
translateX: [2000, 0],
|
|
252
|
+
duration: 400,
|
|
253
|
+
delay: 100 + index * 100,
|
|
254
|
+
ease: 'linear',
|
|
120
255
|
});
|
|
121
|
-
}
|
|
122
256
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
translateX: [2000, 0],
|
|
145
|
-
duration: 400,
|
|
146
|
-
delay: anime.stagger(100, { start: 100 })
|
|
147
|
-
});
|
|
148
|
-
anim.add({
|
|
149
|
-
targets: animated,
|
|
150
|
-
opacity: [0.6, 1],
|
|
151
|
-
duration: 200,
|
|
152
|
-
delay: anime.stagger(50)
|
|
153
|
-
});
|
|
154
|
-
anim.play();
|
|
155
|
-
}
|
|
257
|
+
// Check if animation has a finished promise
|
|
258
|
+
if (animation && animation.finished) {
|
|
259
|
+
animation.finished.then(() => {
|
|
260
|
+
// Second phase: fade to full opacity
|
|
261
|
+
animate(element, {
|
|
262
|
+
opacity: [0.6, 1],
|
|
263
|
+
duration: 200,
|
|
264
|
+
delay: index * 50,
|
|
265
|
+
ease: 'linear',
|
|
266
|
+
});
|
|
267
|
+
});
|
|
268
|
+
} else {
|
|
269
|
+
// Fallback: use setTimeout if no promise available
|
|
270
|
+
setTimeout(() => {
|
|
271
|
+
animate(element, {
|
|
272
|
+
opacity: [0.6, 1],
|
|
273
|
+
duration: 200,
|
|
274
|
+
delay: index * 50,
|
|
275
|
+
ease: 'linear',
|
|
276
|
+
});
|
|
277
|
+
}, 400 + index * 100);
|
|
156
278
|
}
|
|
279
|
+
});
|
|
157
280
|
}
|
|
281
|
+
}
|
|
158
282
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
283
|
+
/**
|
|
284
|
+
* Add a panel. Defaults to opening 'the next' panel if the `initial` parameter is omitted: if
|
|
285
|
+
* panels 1,6,3 are open, panel 7 will be added
|
|
286
|
+
*
|
|
287
|
+
* @param {number} [initial] The panel number of the panel to add.
|
|
288
|
+
*/
|
|
289
|
+
addPanel(initial) {
|
|
290
|
+
let value = initial;
|
|
291
|
+
if (initial === undefined && !this.panels.length) {
|
|
292
|
+
value = 0;
|
|
293
|
+
}
|
|
294
|
+
if (initial === undefined && this.panels.length) {
|
|
295
|
+
const max = this.panels.reduce((result, next) => Math.max(result, next), 0);
|
|
296
|
+
value = max + 1;
|
|
297
|
+
}
|
|
174
298
|
|
|
175
|
-
|
|
176
|
-
|
|
299
|
+
console.log('<pb-grid> Adding panel with value:', value);
|
|
300
|
+
console.log('<pb-grid> Current panels before add:', this.panels);
|
|
301
|
+
console.log(
|
|
302
|
+
'<pb-grid> Current panel count before add:',
|
|
303
|
+
this.querySelectorAll('._grid_panel').length,
|
|
304
|
+
);
|
|
177
305
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
this._update();
|
|
181
|
-
this.emitTo('pb-refresh');
|
|
182
|
-
}
|
|
306
|
+
this._columns += 1;
|
|
307
|
+
this.panels.push(value);
|
|
183
308
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
let idx;
|
|
191
|
-
let container;
|
|
192
|
-
if (typeof panel === 'number') {
|
|
193
|
-
idx = this.panels.indexOf(panel);
|
|
194
|
-
container = this.querySelector(`[active="${panel}"]`);
|
|
195
|
-
} else {
|
|
196
|
-
container = panel;
|
|
197
|
-
idx = this._getPanelIndex(panel);
|
|
198
|
-
}
|
|
199
|
-
console.log('<pb-grid> Removing panel %d', idx);
|
|
200
|
-
this.panels.splice(this.direction === 'rtl' ? this.panels.length - idx - 1 : idx, 1);
|
|
201
|
-
|
|
202
|
-
container.parentNode.removeChild(container);
|
|
203
|
-
this._columns -= 1;
|
|
204
|
-
registry.commit(this, this._getState());
|
|
205
|
-
this._assignPanelIds();
|
|
206
|
-
this._update();
|
|
207
|
-
}
|
|
309
|
+
this._insertPanel(value);
|
|
310
|
+
this._isUpdatingFromRegistry = true;
|
|
311
|
+
registry.commit(this, this._getState());
|
|
312
|
+
this._isUpdatingFromRegistry = false;
|
|
313
|
+
this._update();
|
|
314
|
+
this.emitTo('pb-refresh');
|
|
208
315
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
this.insertBefore(clone, this.firstElementChild);
|
|
216
|
-
}
|
|
217
|
-
clone.classList.add('_grid_panel');
|
|
218
|
-
this._assignPanelIds();
|
|
219
|
-
}
|
|
316
|
+
console.log('<pb-grid> After adding panel - panels:', this.panels);
|
|
317
|
+
console.log(
|
|
318
|
+
'<pb-grid> After adding panel - panel count:',
|
|
319
|
+
this.querySelectorAll('._grid_panel').length,
|
|
320
|
+
);
|
|
321
|
+
}
|
|
220
322
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
323
|
+
/**
|
|
324
|
+
* Remove a panel from the grid
|
|
325
|
+
*
|
|
326
|
+
* @param {HTMLElement|number} panel the pb-panel element or the panel number
|
|
327
|
+
*/
|
|
328
|
+
removePanel(panel) {
|
|
329
|
+
let idx;
|
|
330
|
+
let container;
|
|
331
|
+
if (typeof panel === 'number') {
|
|
332
|
+
idx = this.panels.indexOf(panel);
|
|
333
|
+
container = this.querySelector(`[active="${panel}"]`);
|
|
334
|
+
} else {
|
|
335
|
+
container = panel;
|
|
336
|
+
idx = this._getPanelIndex(panel);
|
|
233
337
|
}
|
|
338
|
+
console.log('<pb-grid> Removing panel %d', idx);
|
|
339
|
+
console.log('<pb-grid> Container:', container);
|
|
340
|
+
console.log('<pb-grid> Current panels:', [...this.panels]);
|
|
341
|
+
console.log('<pb-grid> Current panel count:', this.querySelectorAll('._grid_panel').length);
|
|
234
342
|
|
|
235
|
-
|
|
236
|
-
const panels = Array.from(this.querySelectorAll('._grid_panel'));
|
|
237
|
-
return panels.indexOf(panel);
|
|
238
|
-
}
|
|
343
|
+
this.panels.splice(this.direction === 'rtl' ? this.panels.length - idx - 1 : idx, 1);
|
|
239
344
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
345
|
+
container.parentNode.removeChild(container);
|
|
346
|
+
this._columns -= 1;
|
|
347
|
+
this._isUpdatingFromRegistry = true;
|
|
348
|
+
registry.commit(this, this._getState());
|
|
349
|
+
this._isUpdatingFromRegistry = false;
|
|
350
|
+
this._assignPanelIds();
|
|
351
|
+
this._update();
|
|
245
352
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
353
|
+
console.log('<pb-grid> After removal - panels:', [...this.panels]);
|
|
354
|
+
console.log(
|
|
355
|
+
'<pb-grid> After removal - panel count:',
|
|
356
|
+
this.querySelectorAll('._grid_panel').length,
|
|
357
|
+
);
|
|
358
|
+
}
|
|
249
359
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
360
|
+
_insertPanel(active) {
|
|
361
|
+
console.log('<pb-grid> _insertPanel called with active:', active);
|
|
362
|
+
console.log('<pb-grid> Template content:', this.template.content);
|
|
363
|
+
console.log('<pb-grid> Template firstElementChild:', this.template.content.firstElementChild);
|
|
364
|
+
|
|
365
|
+
const clone = document.importNode(this.template.content.firstElementChild, true);
|
|
366
|
+
console.log('<pb-grid> Cloned element:', clone);
|
|
253
367
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
grid-column-gap: var(--pb-grid-column-gap, 20px);
|
|
260
|
-
justify-content: space-between;
|
|
261
|
-
}
|
|
262
|
-
`;
|
|
368
|
+
clone.setAttribute('active', active);
|
|
369
|
+
if (this.direction === 'ltr' || this.querySelectorAll('._grid_panel').length === 0) {
|
|
370
|
+
this.appendChild(clone);
|
|
371
|
+
} else {
|
|
372
|
+
this.insertBefore(clone, this.firstElementChild);
|
|
263
373
|
}
|
|
374
|
+
clone.classList.add('_grid_panel');
|
|
375
|
+
this._assignPanelIds();
|
|
264
376
|
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
377
|
+
console.log(
|
|
378
|
+
'<pb-grid> After _insertPanel - DOM panels:',
|
|
379
|
+
this.querySelectorAll('._grid_panel').length,
|
|
380
|
+
);
|
|
381
|
+
}
|
|
268
382
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
383
|
+
_update() {
|
|
384
|
+
const widths = Array.from(this.children)
|
|
385
|
+
.filter(child => !(child instanceof HTMLTemplateElement))
|
|
386
|
+
.map(child => {
|
|
387
|
+
const styles = window.getComputedStyle(child);
|
|
388
|
+
const width = styles.getPropertyValue('max-width');
|
|
389
|
+
if (width && width !== 'none') {
|
|
390
|
+
return width;
|
|
273
391
|
}
|
|
274
|
-
|
|
392
|
+
return '1fr';
|
|
393
|
+
});
|
|
394
|
+
this.style.setProperty('--pb-computed-column-widths', widths.join(' '));
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
_getPanelIndex(panel) {
|
|
398
|
+
const panels = Array.from(this.querySelectorAll('._grid_panel'));
|
|
399
|
+
return panels.indexOf(panel);
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
_assignPanelIds() {
|
|
403
|
+
this.querySelectorAll('._grid_panel').forEach((panel, idx) => {
|
|
404
|
+
panel.position = idx;
|
|
405
|
+
});
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
_getState() {
|
|
409
|
+
// Ensure panels array is valid before joining
|
|
410
|
+
// Filter out any invalid values (NaN, undefined, null)
|
|
411
|
+
const validPanels = this.panels.filter(p => typeof p === 'number' && !isNaN(p) && p >= 0 && p < 10);
|
|
412
|
+
return { panels: validPanels.join('.') };
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
render() {
|
|
416
|
+
return html`<slot></slot>`;
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
static get styles() {
|
|
420
|
+
return css`
|
|
421
|
+
:host {
|
|
422
|
+
display: grid;
|
|
423
|
+
grid-template-columns: var(--pb-grid-column-widths, var(--pb-computed-column-widths));
|
|
424
|
+
grid-column-gap: var(--pb-grid-column-gap, 20px);
|
|
425
|
+
justify-content: space-between;
|
|
426
|
+
font-size: calc(var(--pb-content-font-size, 1rem) * var(--pb-zoom-factor, 1));
|
|
427
|
+
}
|
|
428
|
+
`;
|
|
429
|
+
}
|
|
275
430
|
|
|
431
|
+
zoom(direction) {
|
|
432
|
+
// Zoom is now handled globally by pb-zoom component using CSS custom properties
|
|
433
|
+
// This method is kept for compatibility but does nothing
|
|
434
|
+
// The component should rely on CSS: font-size: calc(var(--pb-content-font-size, 1rem) * var(--pb-zoom-factor, 1));
|
|
435
|
+
}
|
|
276
436
|
}
|
|
277
437
|
if (!customElements.get('pb-grid')) {
|
|
278
|
-
|
|
438
|
+
customElements.define('pb-grid', PbGrid);
|
|
279
439
|
}
|