pict-section-inlinedocumentation 0.0.4 → 0.0.7
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/example_applications/basic/index.html +5 -5
- package/example_applications/bookshop/html/index.html +5 -5
- package/example_applications/bookshop/views/PictView-Bookshop-BookList.js +6 -6
- package/example_applications/bookshop/views/PictView-Bookshop-Store.js +3 -3
- package/package.json +9 -8
- package/source/providers/Pict-Provider-InlineDocumentation.js +293 -9
- package/source/views/Pict-View-InlineDocumentation-Content.js +114 -45
- package/source/views/Pict-View-InlineDocumentation-Layout.js +7 -54
- package/source/views/Pict-View-InlineDocumentation-Nav.js +678 -130
- package/source/views/Pict-View-InlineDocumentation-TopicManager.js +64 -64
|
@@ -11,32 +11,100 @@ const _ViewConfiguration =
|
|
|
11
11
|
|
|
12
12
|
CSS: /*css*/`
|
|
13
13
|
.pict-inline-doc-nav {
|
|
14
|
-
|
|
14
|
+
display: flex;
|
|
15
|
+
flex-direction: column;
|
|
16
|
+
height: 100%;
|
|
17
|
+
}
|
|
18
|
+
.pict-inline-doc-nav-collapsed-header {
|
|
19
|
+
display: flex;
|
|
20
|
+
align-items: center;
|
|
21
|
+
padding: 0.5em 0.8em;
|
|
22
|
+
cursor: pointer;
|
|
23
|
+
border-bottom: 1px solid var(--theme-color-border-light, #EAE3D8);
|
|
24
|
+
background: var(--theme-color-background-secondary, #F7F5F0);
|
|
25
|
+
user-select: none;
|
|
26
|
+
}
|
|
27
|
+
.pict-inline-doc-nav-collapsed-header:hover {
|
|
28
|
+
background: var(--theme-color-background-tertiary, #EDE8DF);
|
|
29
|
+
}
|
|
30
|
+
.pict-inline-doc-nav-chevron {
|
|
31
|
+
font-size: 0.6em;
|
|
32
|
+
transition: transform 0.2s ease;
|
|
33
|
+
color: var(--theme-color-text-muted, #8A7F72);
|
|
34
|
+
display: inline-flex;
|
|
35
|
+
align-items: center;
|
|
36
|
+
margin-right: 0.5em;
|
|
37
|
+
}
|
|
38
|
+
.pict-inline-doc-nav-chevron.expanded {
|
|
39
|
+
transform: rotate(90deg);
|
|
40
|
+
}
|
|
41
|
+
.pict-inline-doc-nav-current-title {
|
|
42
|
+
font-size: 0.9em;
|
|
43
|
+
font-weight: 500;
|
|
44
|
+
color: var(--theme-color-text-primary, #3D3229);
|
|
45
|
+
overflow: hidden;
|
|
46
|
+
text-overflow: ellipsis;
|
|
47
|
+
white-space: nowrap;
|
|
48
|
+
flex: 1;
|
|
49
|
+
}
|
|
50
|
+
.pict-inline-doc-nav-outline {
|
|
51
|
+
display: none;
|
|
52
|
+
overflow-y: auto;
|
|
53
|
+
}
|
|
54
|
+
.pict-inline-doc-nav-outline.expanded {
|
|
55
|
+
display: block;
|
|
56
|
+
}
|
|
57
|
+
.pict-inline-doc-nav-filter {
|
|
58
|
+
padding: 0.3em 0.6em;
|
|
59
|
+
border-bottom: 1px solid var(--theme-color-border-light, #EAE3D8);
|
|
60
|
+
}
|
|
61
|
+
.pict-inline-doc-nav-filter input {
|
|
62
|
+
width: 100%;
|
|
63
|
+
box-sizing: border-box;
|
|
64
|
+
padding: 0.3em 0.5em;
|
|
65
|
+
border: 1px solid var(--theme-color-border-default, #DDD6CA);
|
|
66
|
+
border-radius: 3px;
|
|
67
|
+
font-size: 0.85em;
|
|
68
|
+
outline: none;
|
|
69
|
+
}
|
|
70
|
+
.pict-inline-doc-nav-filter input:focus {
|
|
71
|
+
border-color: var(--theme-color-brand-primary, #2E7D74);
|
|
15
72
|
}
|
|
16
73
|
.pict-inline-doc-nav-group {
|
|
17
|
-
margin-bottom: 0
|
|
74
|
+
margin-bottom: 0;
|
|
18
75
|
}
|
|
19
76
|
.pict-inline-doc-nav-group-header {
|
|
20
77
|
display: flex;
|
|
21
78
|
align-items: center;
|
|
22
|
-
padding: 0.4em
|
|
79
|
+
padding: 0.4em 0.8em;
|
|
23
80
|
font-weight: 600;
|
|
24
|
-
font-size: 0.
|
|
25
|
-
color: #5E5549;
|
|
81
|
+
font-size: 0.7em;
|
|
82
|
+
color: var(--theme-color-text-secondary, #5E5549);
|
|
26
83
|
text-transform: uppercase;
|
|
27
84
|
letter-spacing: 0.03em;
|
|
28
85
|
cursor: pointer;
|
|
29
86
|
user-select: none;
|
|
30
87
|
}
|
|
31
88
|
.pict-inline-doc-nav-group-header:hover {
|
|
32
|
-
color: #3D3229;
|
|
89
|
+
color: var(--theme-color-text-primary, #3D3229);
|
|
90
|
+
background: var(--theme-color-background-tertiary, #F0ECE4);
|
|
33
91
|
}
|
|
34
92
|
.pict-inline-doc-nav-group-toggle {
|
|
35
|
-
margin-right: 0.
|
|
36
|
-
|
|
93
|
+
margin-right: 0.35em;
|
|
94
|
+
display: inline-flex;
|
|
95
|
+
align-items: center;
|
|
96
|
+
justify-content: center;
|
|
97
|
+
width: 0.85em;
|
|
98
|
+
height: 0.85em;
|
|
99
|
+
color: currentColor;
|
|
37
100
|
transition: transform 0.15s ease;
|
|
38
101
|
}
|
|
39
|
-
.pict-inline-doc-nav-group
|
|
102
|
+
.pict-inline-doc-nav-group-toggle svg {
|
|
103
|
+
width: 100%;
|
|
104
|
+
height: 100%;
|
|
105
|
+
display: block;
|
|
106
|
+
}
|
|
107
|
+
.pict-inline-doc-nav-group-toggle.collapsed {
|
|
40
108
|
transform: rotate(-90deg);
|
|
41
109
|
}
|
|
42
110
|
.pict-inline-doc-nav-group.collapsed .pict-inline-doc-nav-group-items {
|
|
@@ -44,30 +112,110 @@ const _ViewConfiguration =
|
|
|
44
112
|
}
|
|
45
113
|
.pict-inline-doc-nav-item {
|
|
46
114
|
display: block;
|
|
47
|
-
padding: 0.
|
|
48
|
-
color: #5E5549;
|
|
115
|
+
padding: 0.25em 0.8em 0.25em 1.6em;
|
|
116
|
+
color: var(--theme-color-text-secondary, #5E5549);
|
|
49
117
|
text-decoration: none;
|
|
50
|
-
font-size: 0.
|
|
118
|
+
font-size: 0.85em;
|
|
51
119
|
cursor: pointer;
|
|
52
120
|
border-left: 3px solid transparent;
|
|
53
121
|
transition: background 0.1s ease, border-color 0.1s ease;
|
|
54
122
|
}
|
|
55
123
|
.pict-inline-doc-nav-item:hover {
|
|
56
|
-
background: #EDE8DF;
|
|
57
|
-
color: #3D3229;
|
|
124
|
+
background: var(--theme-color-background-tertiary, #EDE8DF);
|
|
58
125
|
}
|
|
59
126
|
.pict-inline-doc-nav-item.active {
|
|
60
127
|
background: #E8E3D8;
|
|
61
|
-
color: #2E7D74;
|
|
62
|
-
border-left-color: #2E7D74;
|
|
128
|
+
color: var(--theme-color-brand-primary, #2E7D74);
|
|
129
|
+
border-left-color: var(--theme-color-brand-primary, #2E7D74);
|
|
63
130
|
font-weight: 500;
|
|
64
131
|
}
|
|
132
|
+
.pict-inline-doc-nav-heading {
|
|
133
|
+
display: block;
|
|
134
|
+
padding: 0.15em 0.8em 0.15em 2.4em;
|
|
135
|
+
color: var(--theme-color-text-muted, #8A7F72);
|
|
136
|
+
font-size: 0.78em;
|
|
137
|
+
cursor: pointer;
|
|
138
|
+
border-left: 3px solid transparent;
|
|
139
|
+
transition: background 0.1s ease, color 0.1s ease;
|
|
140
|
+
}
|
|
141
|
+
.pict-inline-doc-nav-heading:hover {
|
|
142
|
+
background: var(--theme-color-background-tertiary, #EDE8DF);
|
|
143
|
+
color: var(--theme-color-text-secondary, #5E5549);
|
|
144
|
+
}
|
|
145
|
+
.pict-inline-doc-nav-heading.h3 {
|
|
146
|
+
padding-left: 3.2em;
|
|
147
|
+
font-size: 0.72em;
|
|
148
|
+
}
|
|
149
|
+
/* Search icon in collapsed header */
|
|
150
|
+
.pict-inline-doc-nav-search-icon {
|
|
151
|
+
display: inline-flex;
|
|
152
|
+
align-items: center;
|
|
153
|
+
color: var(--theme-color-text-muted, #8A7F72);
|
|
154
|
+
opacity: 0.5;
|
|
155
|
+
transition: opacity 0.2s;
|
|
156
|
+
flex-shrink: 0;
|
|
157
|
+
margin-left: 0.3em;
|
|
158
|
+
}
|
|
159
|
+
.pict-inline-doc-nav-search-icon:hover {
|
|
160
|
+
opacity: 1;
|
|
161
|
+
color: var(--theme-color-brand-primary, #2E7D74);
|
|
162
|
+
}
|
|
163
|
+
/* Search results section */
|
|
164
|
+
.pict-inline-doc-nav-search-results {
|
|
165
|
+
border-bottom: 1px solid var(--theme-color-border-light, #EAE3D8);
|
|
166
|
+
padding: 0.3em 0;
|
|
167
|
+
}
|
|
168
|
+
.pict-inline-doc-nav-search-status {
|
|
169
|
+
padding: 0.2em 0.8em;
|
|
170
|
+
font-size: 0.7em;
|
|
171
|
+
color: var(--theme-color-text-muted, #8A7F72);
|
|
172
|
+
text-transform: uppercase;
|
|
173
|
+
letter-spacing: 0.03em;
|
|
174
|
+
}
|
|
175
|
+
.pict-inline-doc-nav-search-result {
|
|
176
|
+
display: flex;
|
|
177
|
+
align-items: baseline;
|
|
178
|
+
padding: 0.25em 0.8em 0.25em 1.2em;
|
|
179
|
+
cursor: pointer;
|
|
180
|
+
font-size: 0.82em;
|
|
181
|
+
color: var(--theme-color-text-primary, #3D3229);
|
|
182
|
+
text-decoration: none;
|
|
183
|
+
transition: background 0.1s ease;
|
|
184
|
+
gap: 0.5em;
|
|
185
|
+
}
|
|
186
|
+
.pict-inline-doc-nav-search-result:hover {
|
|
187
|
+
background: var(--theme-color-background-tertiary, #EDE8DF);
|
|
188
|
+
}
|
|
189
|
+
.pict-inline-doc-nav-search-result-title {
|
|
190
|
+
flex: 1;
|
|
191
|
+
overflow: hidden;
|
|
192
|
+
text-overflow: ellipsis;
|
|
193
|
+
white-space: nowrap;
|
|
194
|
+
}
|
|
195
|
+
.pict-inline-doc-nav-search-result-group {
|
|
196
|
+
font-size: 0.75em;
|
|
197
|
+
color: var(--theme-color-text-muted, #8A7F72);
|
|
198
|
+
white-space: nowrap;
|
|
199
|
+
}
|
|
200
|
+
/* External link indicator */
|
|
201
|
+
.pict-inline-doc-nav-item-external {
|
|
202
|
+
color: var(--theme-color-text-muted, #8A7F72);
|
|
203
|
+
}
|
|
204
|
+
.pict-inline-doc-nav-item-external:hover {
|
|
205
|
+
color: var(--theme-color-brand-primary, #2E7D74);
|
|
206
|
+
}
|
|
207
|
+
.pict-inline-doc-nav-external-icon {
|
|
208
|
+
display: inline;
|
|
209
|
+
margin-left: 0.3em;
|
|
210
|
+
opacity: 0.5;
|
|
211
|
+
vertical-align: -0.05em;
|
|
212
|
+
}
|
|
65
213
|
.pict-inline-doc-nav-topic-badge {
|
|
66
214
|
display: inline-block;
|
|
67
215
|
margin: 0.5em 1em;
|
|
68
216
|
padding: 0.3em 0.7em;
|
|
69
217
|
background: #2E7D74;
|
|
70
|
-
color: #fff;
|
|
218
|
+
color: var(--theme-color-background-panel, #fff);
|
|
71
219
|
border-radius: 4px;
|
|
72
220
|
font-size: 0.8em;
|
|
73
221
|
font-weight: 500;
|
|
@@ -85,7 +233,7 @@ const _ViewConfiguration =
|
|
|
85
233
|
align-items: center;
|
|
86
234
|
gap: 0.3em;
|
|
87
235
|
padding: 0.3em 1em;
|
|
88
|
-
border-bottom: 1px solid #EAE3D8;
|
|
236
|
+
border-bottom: 1px solid var(--theme-color-border-light, #EAE3D8);
|
|
89
237
|
}
|
|
90
238
|
.pict-inline-doc-nav-toolbar-btn {
|
|
91
239
|
display: inline-flex;
|
|
@@ -93,29 +241,29 @@ const _ViewConfiguration =
|
|
|
93
241
|
justify-content: center;
|
|
94
242
|
width: 28px;
|
|
95
243
|
height: 28px;
|
|
96
|
-
border: 1px solid #DDD6CA;
|
|
244
|
+
border: 1px solid var(--theme-color-border-default, #DDD6CA);
|
|
97
245
|
border-radius: 3px;
|
|
98
|
-
background: #fff;
|
|
99
|
-
color: #5E5549;
|
|
246
|
+
background: var(--theme-color-background-panel, #fff);
|
|
247
|
+
color: var(--theme-color-text-secondary, #5E5549);
|
|
100
248
|
font-size: 0.9em;
|
|
101
249
|
cursor: pointer;
|
|
102
250
|
transition: background 0.1s, border-color 0.1s;
|
|
103
251
|
}
|
|
104
252
|
.pict-inline-doc-nav-toolbar-btn:hover {
|
|
105
|
-
background: #F0ECE4;
|
|
106
|
-
border-color: #C4BDB3;
|
|
253
|
+
background: var(--theme-color-background-tertiary, #F0ECE4);
|
|
254
|
+
border-color: var(--theme-color-border-default, #C4BDB3);
|
|
107
255
|
}
|
|
108
256
|
.pict-inline-doc-nav-toolbar-btn.accent {
|
|
109
|
-
border-color: #2E7D74;
|
|
110
|
-
color: #2E7D74;
|
|
257
|
+
border-color: var(--theme-color-brand-primary, #2E7D74);
|
|
258
|
+
color: var(--theme-color-brand-primary, #2E7D74);
|
|
111
259
|
}
|
|
112
260
|
.pict-inline-doc-nav-toolbar-btn.accent:hover {
|
|
113
261
|
background: #F0F9F7;
|
|
114
262
|
}
|
|
115
263
|
.pict-inline-doc-nav-toolbar-btn.active {
|
|
116
264
|
background: #2E7D74;
|
|
117
|
-
color: #fff;
|
|
118
|
-
border-color: #2E7D74;
|
|
265
|
+
color: var(--theme-color-background-panel, #fff);
|
|
266
|
+
border-color: var(--theme-color-brand-primary, #2E7D74);
|
|
119
267
|
}
|
|
120
268
|
.pict-inline-doc-nav-toolbar-btn.active:hover {
|
|
121
269
|
background: #266D65;
|
|
@@ -123,57 +271,6 @@ const _ViewConfiguration =
|
|
|
123
271
|
.pict-inline-doc-nav-toolbar-spacer {
|
|
124
272
|
flex: 1;
|
|
125
273
|
}
|
|
126
|
-
/* Compact (horizontal) nav mode */
|
|
127
|
-
.pict-inline-doc-compact .pict-inline-doc-nav {
|
|
128
|
-
display: flex;
|
|
129
|
-
flex-wrap: wrap;
|
|
130
|
-
align-items: center;
|
|
131
|
-
padding: 0.4em 0.5em;
|
|
132
|
-
gap: 0.2em 0;
|
|
133
|
-
}
|
|
134
|
-
.pict-inline-doc-compact .pict-inline-doc-nav-group {
|
|
135
|
-
margin-bottom: 0;
|
|
136
|
-
display: flex;
|
|
137
|
-
align-items: center;
|
|
138
|
-
}
|
|
139
|
-
.pict-inline-doc-compact .pict-inline-doc-nav-group-header {
|
|
140
|
-
padding: 0.25em 0.5em;
|
|
141
|
-
font-size: 0.75em;
|
|
142
|
-
}
|
|
143
|
-
.pict-inline-doc-compact .pict-inline-doc-nav-group-toggle {
|
|
144
|
-
display: none;
|
|
145
|
-
}
|
|
146
|
-
.pict-inline-doc-compact .pict-inline-doc-nav-group-items {
|
|
147
|
-
display: flex !important;
|
|
148
|
-
flex-wrap: wrap;
|
|
149
|
-
gap: 0;
|
|
150
|
-
}
|
|
151
|
-
.pict-inline-doc-compact .pict-inline-doc-nav-item {
|
|
152
|
-
padding: 0.25em 0.6em;
|
|
153
|
-
font-size: 0.8em;
|
|
154
|
-
border-left: none;
|
|
155
|
-
border-bottom: 2px solid transparent;
|
|
156
|
-
white-space: nowrap;
|
|
157
|
-
}
|
|
158
|
-
.pict-inline-doc-compact .pict-inline-doc-nav-item.active {
|
|
159
|
-
border-left: none;
|
|
160
|
-
border-bottom-color: #2E7D74;
|
|
161
|
-
}
|
|
162
|
-
.pict-inline-doc-compact .pict-inline-doc-nav-topic-badge {
|
|
163
|
-
margin: 0 0.5em;
|
|
164
|
-
padding: 0.2em 0.5em;
|
|
165
|
-
font-size: 0.75em;
|
|
166
|
-
}
|
|
167
|
-
.pict-inline-doc-compact .pict-inline-doc-nav-toolbar {
|
|
168
|
-
padding: 0.2em 0.5em;
|
|
169
|
-
border-bottom: none;
|
|
170
|
-
border-right: 1px solid #EAE3D8;
|
|
171
|
-
}
|
|
172
|
-
.pict-inline-doc-compact .pict-inline-doc-nav-toolbar-btn {
|
|
173
|
-
width: 24px;
|
|
174
|
-
height: 24px;
|
|
175
|
-
font-size: 0.8em;
|
|
176
|
-
}
|
|
177
274
|
`,
|
|
178
275
|
|
|
179
276
|
Templates:
|
|
@@ -230,68 +327,234 @@ class InlineDocumentationNavView extends libPictView
|
|
|
230
327
|
return;
|
|
231
328
|
}
|
|
232
329
|
|
|
233
|
-
let
|
|
330
|
+
let tmpProvider = this.pict.providers['Pict-InlineDocumentation'];
|
|
331
|
+
let tmpHeadings = [];
|
|
332
|
+
if (tmpProvider && typeof tmpProvider._extractHeadings === 'function')
|
|
333
|
+
{
|
|
334
|
+
tmpHeadings = tmpProvider._extractHeadings();
|
|
335
|
+
}
|
|
336
|
+
|
|
234
337
|
let tmpCurrentPath = tmpState.CurrentPath || '';
|
|
235
|
-
let
|
|
236
|
-
let
|
|
237
|
-
let
|
|
338
|
+
let tmpIsCollapsed = tmpState.NavCollapsed !== false;
|
|
339
|
+
let tmpFilterText = tmpState.NavFilterText || '';
|
|
340
|
+
let tmpCurrentDocName = this._resolveCurrentDocName(tmpState, tmpCurrentPath);
|
|
341
|
+
|
|
342
|
+
let tmpHTML = '';
|
|
343
|
+
|
|
344
|
+
let tmpSearchQuery = tmpState.SearchQuery || '';
|
|
345
|
+
let tmpSearchResults = tmpState.SearchResults || [];
|
|
346
|
+
|
|
347
|
+
// 1. Collapsed header with search icon
|
|
348
|
+
let tmpChevronClass = 'pict-inline-doc-nav-chevron' + (tmpIsCollapsed ? '' : ' expanded');
|
|
349
|
+
tmpHTML += '<div class="pict-inline-doc-nav-collapsed-header">';
|
|
350
|
+
tmpHTML += '<span class="' + tmpChevronClass + '" id="InlineDoc-Nav-CollapseToggle">';
|
|
351
|
+
tmpHTML += '<svg width="1em" height="1em" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="6,3 11,8 6,13"/></svg>';
|
|
352
|
+
tmpHTML += '</span>';
|
|
353
|
+
tmpHTML += '<span class="pict-inline-doc-nav-current-title" id="InlineDoc-Nav-TitleToggle">' + this._escapeHTML(tmpCurrentDocName) + '</span>';
|
|
354
|
+
tmpHTML += '<span class="pict-inline-doc-nav-search-icon" id="InlineDoc-Nav-SearchBtn" title="Search documentation">';
|
|
355
|
+
tmpHTML += '<svg width="1em" height="1em" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><circle cx="7" cy="7" r="4.5"/><line x1="10.5" y1="10.5" x2="14" y2="14"/></svg>';
|
|
356
|
+
tmpHTML += '</span>';
|
|
357
|
+
tmpHTML += '</div>';
|
|
358
|
+
|
|
359
|
+
// 2. Outline body
|
|
360
|
+
let tmpOutlineClass = 'pict-inline-doc-nav-outline' + (tmpIsCollapsed ? '' : ' expanded');
|
|
361
|
+
tmpHTML += '<div class="' + tmpOutlineClass + '" id="InlineDoc-Nav-Outline">';
|
|
362
|
+
|
|
363
|
+
// Search / filter input
|
|
364
|
+
let tmpPlaceholder = tmpState.SearchIndexLoaded ? 'Search documentation...' : 'Filter...';
|
|
365
|
+
tmpHTML += '<div class="pict-inline-doc-nav-filter">';
|
|
366
|
+
tmpHTML += '<input type="text" id="InlineDoc-Nav-FilterInput" placeholder="' + tmpPlaceholder + '" value="' + this._escapeHTML(tmpSearchQuery || tmpFilterText) + '" />';
|
|
367
|
+
tmpHTML += '</div>';
|
|
368
|
+
|
|
369
|
+
// Search results (when full-text search is active)
|
|
370
|
+
if (tmpSearchResults.length > 0 && tmpSearchQuery)
|
|
371
|
+
{
|
|
372
|
+
tmpHTML += '<div class="pict-inline-doc-nav-search-results">';
|
|
373
|
+
tmpHTML += '<div class="pict-inline-doc-nav-search-status">' + tmpSearchResults.length + ' result' + (tmpSearchResults.length !== 1 ? 's' : '') + '</div>';
|
|
374
|
+
for (let i = 0; i < tmpSearchResults.length && i < 15; i++)
|
|
375
|
+
{
|
|
376
|
+
let tmpResult = tmpSearchResults[i];
|
|
377
|
+
tmpHTML += '<a class="pict-inline-doc-nav-search-result" data-search-path="' + this._escapeHTML(tmpResult.DocPath) + '">';
|
|
378
|
+
tmpHTML += '<span class="pict-inline-doc-nav-search-result-title">' + this._escapeHTML(tmpResult.Title) + '</span>';
|
|
379
|
+
if (tmpResult.Group)
|
|
380
|
+
{
|
|
381
|
+
tmpHTML += '<span class="pict-inline-doc-nav-search-result-group">' + this._escapeHTML(tmpResult.Group) + '</span>';
|
|
382
|
+
}
|
|
383
|
+
tmpHTML += '</a>';
|
|
384
|
+
}
|
|
385
|
+
tmpHTML += '</div>';
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
// Topic badge
|
|
389
|
+
tmpHTML += this._renderTopicBadge(tmpState);
|
|
390
|
+
|
|
391
|
+
// Toolbar
|
|
392
|
+
tmpHTML += this._renderToolbar(tmpState);
|
|
393
|
+
|
|
394
|
+
// Group tree
|
|
395
|
+
tmpHTML += this._renderGroupTree(tmpState, tmpCurrentPath, tmpHeadings, tmpFilterText);
|
|
396
|
+
|
|
397
|
+
tmpHTML += '</div>';
|
|
398
|
+
|
|
399
|
+
tmpContainer.innerHTML = tmpHTML;
|
|
400
|
+
|
|
401
|
+
// Wire up click handlers
|
|
402
|
+
this._wireClickHandlers(tmpContainer);
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
/**
|
|
406
|
+
* Resolve the display name for the currently loaded document.
|
|
407
|
+
*
|
|
408
|
+
* Searches SidebarGroups for a matching item name; falls back to the path.
|
|
409
|
+
*
|
|
410
|
+
* @param {object} pState - The InlineDocumentation state
|
|
411
|
+
* @param {string} pCurrentPath - The current document path
|
|
412
|
+
* @returns {string} The resolved document name
|
|
413
|
+
*/
|
|
414
|
+
_resolveCurrentDocName(pState, pCurrentPath)
|
|
415
|
+
{
|
|
416
|
+
if (!pCurrentPath)
|
|
417
|
+
{
|
|
418
|
+
return 'Documentation';
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
let tmpGroups = pState.SidebarGroups || [];
|
|
422
|
+
|
|
423
|
+
for (let i = 0; i < tmpGroups.length; i++)
|
|
424
|
+
{
|
|
425
|
+
let tmpGroup = tmpGroups[i];
|
|
426
|
+
|
|
427
|
+
// Check if the group itself matches
|
|
428
|
+
if (tmpGroup.Path && tmpGroup.Path === pCurrentPath)
|
|
429
|
+
{
|
|
430
|
+
return tmpGroup.Name || pCurrentPath;
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
let tmpItems = tmpGroup.Items || [];
|
|
434
|
+
for (let j = 0; j < tmpItems.length; j++)
|
|
435
|
+
{
|
|
436
|
+
if (tmpItems[j].Path === pCurrentPath)
|
|
437
|
+
{
|
|
438
|
+
return tmpItems[j].Name || pCurrentPath;
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
return pCurrentPath;
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
/**
|
|
447
|
+
* Render the topic badge HTML if a topic is active.
|
|
448
|
+
*
|
|
449
|
+
* @param {object} pState - The InlineDocumentation state
|
|
450
|
+
* @returns {string} HTML string for the topic badge, or empty string
|
|
451
|
+
*/
|
|
452
|
+
_renderTopicBadge(pState)
|
|
453
|
+
{
|
|
454
|
+
let tmpActiveTopic = pState.Topic;
|
|
455
|
+
|
|
456
|
+
if (!tmpActiveTopic || !pState.Topics || !pState.Topics[tmpActiveTopic])
|
|
457
|
+
{
|
|
458
|
+
return '';
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
let tmpTopicDef = pState.Topics[tmpActiveTopic];
|
|
462
|
+
let tmpTopicName = tmpTopicDef.TopicTitle || tmpTopicDef.Name || tmpActiveTopic;
|
|
463
|
+
|
|
464
|
+
let tmpHTML = '<div class="pict-inline-doc-nav-topic-badge">'
|
|
465
|
+
+ this._escapeHTML(tmpTopicName)
|
|
466
|
+
+ '<span class="pict-inline-doc-nav-topic-clear" id="InlineDoc-Nav-ClearTopic">'
|
|
467
|
+
+ '<svg width="1em" height="1em" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round">'
|
|
468
|
+
+ '<line x1="4" y1="4" x2="12" y2="12"/><line x1="12" y1="4" x2="4" y2="12"/>'
|
|
469
|
+
+ '</svg></span>'
|
|
470
|
+
+ '</div>';
|
|
471
|
+
|
|
472
|
+
return tmpHTML;
|
|
473
|
+
}
|
|
238
474
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
475
|
+
/**
|
|
476
|
+
* Render the topic management toolbar HTML.
|
|
477
|
+
*
|
|
478
|
+
* @param {object} pState - The InlineDocumentation state
|
|
479
|
+
* @returns {string} HTML string for the toolbar, or empty string
|
|
480
|
+
*/
|
|
481
|
+
_renderToolbar(pState)
|
|
482
|
+
{
|
|
483
|
+
if (!pState.TopicManagerEnabled)
|
|
244
484
|
{
|
|
245
|
-
|
|
485
|
+
return '';
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
let tmpHTML = '<div class="pict-inline-doc-nav-toolbar">';
|
|
489
|
+
tmpHTML += '<button class="pict-inline-doc-nav-toolbar-btn" id="InlineDoc-Nav-ManageTopics" title="Manage Topics">'
|
|
490
|
+
+ '<svg width="1em" height="1em" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">'
|
|
491
|
+
+ '<circle cx="8" cy="8" r="2.5"/>'
|
|
492
|
+
+ '<path d="M8 1v2M8 13v2M1 8h2M13 8h2M3.05 3.05l1.41 1.41M11.54 11.54l1.41 1.41M3.05 12.95l1.41-1.41M11.54 4.46l1.41-1.41"/>'
|
|
493
|
+
+ '</svg></button>';
|
|
494
|
+
|
|
495
|
+
if (pState.CurrentRoute)
|
|
496
|
+
{
|
|
497
|
+
tmpHTML += '<button class="pict-inline-doc-nav-toolbar-btn accent" id="InlineDoc-Nav-BindTopic" title="Bind topic to current route">'
|
|
498
|
+
+ '<svg width="1em" height="1em" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">'
|
|
499
|
+
+ '<path d="M6.5 9.5a3.5 3.5 0 005 0l2-2a3.5 3.5 0 00-5-5l-1 1"/>'
|
|
500
|
+
+ '<path d="M9.5 6.5a3.5 3.5 0 00-5 0l-2 2a3.5 3.5 0 005 5l1-1"/>'
|
|
501
|
+
+ '</svg></button>';
|
|
502
|
+
}
|
|
246
503
|
|
|
247
|
-
|
|
248
|
-
|
|
504
|
+
let tmpTooltipEditActive = pState.TooltipEditMode ? ' active' : '';
|
|
505
|
+
tmpHTML += '<button class="pict-inline-doc-nav-toolbar-btn' + tmpTooltipEditActive + '" id="InlineDoc-Nav-TooltipEditMode" title="Toggle tooltip edit mode">'
|
|
506
|
+
+ '<svg width="1em" height="1em" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">'
|
|
507
|
+
+ '<path d="M14 10a1.5 1.5 0 01-1.5 1.5H4l-3 3V3A1.5 1.5 0 012.5 1.5h10A1.5 1.5 0 0114 3z"/>'
|
|
508
|
+
+ '</svg></button>';
|
|
509
|
+
|
|
510
|
+
tmpHTML += '<span class="pict-inline-doc-nav-toolbar-spacer"></span>';
|
|
511
|
+
tmpHTML += '</div>';
|
|
512
|
+
|
|
513
|
+
return tmpHTML;
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
/**
|
|
517
|
+
* Build the group/item/heading tree HTML.
|
|
518
|
+
*
|
|
519
|
+
* @param {object} pState - The InlineDocumentation state
|
|
520
|
+
* @param {string} pCurrentPath - The current document path
|
|
521
|
+
* @param {Array} pHeadings - Array of { Text, Slug, Level } from _extractHeadings
|
|
522
|
+
* @param {string} pFilterText - The current filter text
|
|
523
|
+
* @returns {string} HTML string for the group tree
|
|
524
|
+
*/
|
|
525
|
+
_renderGroupTree(pState, pCurrentPath, pHeadings, pFilterText)
|
|
526
|
+
{
|
|
527
|
+
let tmpHTML = '';
|
|
528
|
+
let tmpGroups = pState.SidebarGroups || [];
|
|
529
|
+
let tmpActiveTopic = pState.Topic;
|
|
530
|
+
let tmpTopicDocuments = null;
|
|
531
|
+
let tmpFilterLower = (pFilterText || '').toLowerCase();
|
|
532
|
+
|
|
533
|
+
// Resolve topic document filter
|
|
534
|
+
if (tmpActiveTopic && pState.Topics && pState.Topics[tmpActiveTopic])
|
|
535
|
+
{
|
|
536
|
+
let tmpTopicDef = pState.Topics[tmpActiveTopic];
|
|
249
537
|
|
|
250
|
-
// Determine matching documents
|
|
251
538
|
if (tmpTopicDef.TopicHelpFilePath)
|
|
252
539
|
{
|
|
253
|
-
// pict_documentation_topics.json format — single file per topic
|
|
254
540
|
tmpTopicDocuments = [tmpTopicDef.TopicHelpFilePath];
|
|
255
541
|
}
|
|
256
542
|
else if (tmpTopicDef.Documents)
|
|
257
543
|
{
|
|
258
|
-
// Legacy format — array of document paths
|
|
259
544
|
tmpTopicDocuments = tmpTopicDef.Documents;
|
|
260
545
|
}
|
|
261
546
|
else
|
|
262
547
|
{
|
|
263
548
|
tmpTopicDocuments = [];
|
|
264
549
|
}
|
|
265
|
-
|
|
266
|
-
tmpHTML += '<div class="pict-inline-doc-nav-topic-badge">'
|
|
267
|
-
+ this._escapeHTML(tmpTopicName)
|
|
268
|
-
+ '<span class="pict-inline-doc-nav-topic-clear" id="InlineDoc-Nav-ClearTopic"><svg width="1em" height="1em" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"><line x1="4" y1="4" x2="12" y2="12"/><line x1="12" y1="4" x2="4" y2="12"/></svg></span>'
|
|
269
|
-
+ '</div>';
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
// Topic management toolbar
|
|
273
|
-
if (tmpState.TopicManagerEnabled)
|
|
274
|
-
{
|
|
275
|
-
tmpHTML += '<div class="pict-inline-doc-nav-toolbar">';
|
|
276
|
-
tmpHTML += '<button class="pict-inline-doc-nav-toolbar-btn" id="InlineDoc-Nav-ManageTopics" title="Manage Topics"><svg width="1em" height="1em" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><circle cx="8" cy="8" r="2.5"/><path d="M8 1v2M8 13v2M1 8h2M13 8h2M3.05 3.05l1.41 1.41M11.54 11.54l1.41 1.41M3.05 12.95l1.41-1.41M11.54 4.46l1.41-1.41"/></svg></button>';
|
|
277
|
-
if (tmpState.CurrentRoute)
|
|
278
|
-
{
|
|
279
|
-
tmpHTML += '<button class="pict-inline-doc-nav-toolbar-btn accent" id="InlineDoc-Nav-BindTopic" title="Bind topic to current route"><svg width="1em" height="1em" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M6.5 9.5a3.5 3.5 0 005 0l2-2a3.5 3.5 0 00-5-5l-1 1"/><path d="M9.5 6.5a3.5 3.5 0 00-5 0l-2 2a3.5 3.5 0 005 5l1-1"/></svg></button>';
|
|
280
|
-
}
|
|
281
|
-
let tmpTooltipEditActive = tmpState.TooltipEditMode ? ' active' : '';
|
|
282
|
-
tmpHTML += '<button class="pict-inline-doc-nav-toolbar-btn' + tmpTooltipEditActive + '" id="InlineDoc-Nav-TooltipEditMode" title="Toggle tooltip edit mode"><svg width="1em" height="1em" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M14 10a1.5 1.5 0 01-1.5 1.5H4l-3 3V3A1.5 1.5 0 012.5 1.5h10A1.5 1.5 0 0114 3z"/></svg></button>';
|
|
283
|
-
tmpHTML += '<span class="pict-inline-doc-nav-toolbar-spacer"></span>';
|
|
284
|
-
tmpHTML += '</div>';
|
|
285
550
|
}
|
|
286
551
|
|
|
287
|
-
let tmpGroups = tmpState.SidebarGroups || [];
|
|
288
|
-
|
|
289
552
|
for (let i = 0; i < tmpGroups.length; i++)
|
|
290
553
|
{
|
|
291
554
|
let tmpGroup = tmpGroups[i];
|
|
292
555
|
let tmpGroupItems = tmpGroup.Items || [];
|
|
293
556
|
|
|
294
|
-
//
|
|
557
|
+
// Apply topic filter
|
|
295
558
|
if (tmpTopicDocuments)
|
|
296
559
|
{
|
|
297
560
|
tmpGroupItems = tmpGroupItems.filter((pItem) =>
|
|
@@ -299,7 +562,6 @@ class InlineDocumentationNavView extends libPictView
|
|
|
299
562
|
return tmpTopicDocuments.indexOf(pItem.Path) >= 0;
|
|
300
563
|
});
|
|
301
564
|
|
|
302
|
-
// Also check if the group-level path matches
|
|
303
565
|
let tmpGroupMatches = tmpTopicDocuments.indexOf(tmpGroup.Path) >= 0;
|
|
304
566
|
|
|
305
567
|
if (tmpGroupItems.length < 1 && !tmpGroupMatches)
|
|
@@ -308,22 +570,68 @@ class InlineDocumentationNavView extends libPictView
|
|
|
308
570
|
}
|
|
309
571
|
}
|
|
310
572
|
|
|
311
|
-
|
|
573
|
+
// Apply text filter — match item names AND headings of the active document
|
|
574
|
+
if (tmpFilterLower)
|
|
575
|
+
{
|
|
576
|
+
tmpGroupItems = tmpGroupItems.filter((pItem) =>
|
|
577
|
+
{
|
|
578
|
+
if ((pItem.Name || '').toLowerCase().indexOf(tmpFilterLower) >= 0)
|
|
579
|
+
{
|
|
580
|
+
return true;
|
|
581
|
+
}
|
|
582
|
+
// For the active document, also check heading text
|
|
583
|
+
if (pItem.Path === pCurrentPath && pHeadings.length > 0)
|
|
584
|
+
{
|
|
585
|
+
for (let h = 0; h < pHeadings.length; h++)
|
|
586
|
+
{
|
|
587
|
+
if ((pHeadings[h].Text || '').toLowerCase().indexOf(tmpFilterLower) >= 0)
|
|
588
|
+
{
|
|
589
|
+
return true;
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
return false;
|
|
594
|
+
});
|
|
595
|
+
|
|
596
|
+
let tmpGroupNameMatches = (tmpGroup.Name || '').toLowerCase().indexOf(tmpFilterLower) >= 0;
|
|
597
|
+
|
|
598
|
+
if (tmpGroupItems.length < 1 && !tmpGroupNameMatches)
|
|
599
|
+
{
|
|
600
|
+
continue;
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
let tmpGroupKey = tmpGroup.Key || tmpGroup.Name || ('group-' + i);
|
|
605
|
+
let tmpIsGroupCollapsed = pState.CollapsedGroups && pState.CollapsedGroups[tmpGroupKey];
|
|
606
|
+
let tmpGroupClass = 'pict-inline-doc-nav-group' + (tmpIsGroupCollapsed ? ' collapsed' : '');
|
|
607
|
+
let tmpToggleClass = 'pict-inline-doc-nav-group-toggle' + (tmpIsGroupCollapsed ? ' collapsed' : '');
|
|
608
|
+
|
|
609
|
+
tmpHTML += '<div class="' + tmpGroupClass + '" data-group="' + this._escapeHTML(tmpGroupKey) + '">';
|
|
312
610
|
tmpHTML += '<div class="pict-inline-doc-nav-group-header">';
|
|
313
|
-
tmpHTML += '<span class="
|
|
611
|
+
tmpHTML += '<span class="' + tmpToggleClass + '" aria-hidden="true">'
|
|
612
|
+
+ '<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" '
|
|
613
|
+
+ 'stroke-linecap="round" stroke-linejoin="round">'
|
|
614
|
+
+ '<polyline points="3 6 8 11 13 6"/>'
|
|
615
|
+
+ '</svg></span>';
|
|
314
616
|
tmpHTML += this._escapeHTML(tmpGroup.Name);
|
|
315
617
|
tmpHTML += '</div>';
|
|
316
618
|
|
|
317
619
|
tmpHTML += '<div class="pict-inline-doc-nav-group-items">';
|
|
318
620
|
|
|
319
|
-
// If the group itself has a path
|
|
621
|
+
// If the group itself has a path, show it as the first item
|
|
320
622
|
if (tmpGroup.Path)
|
|
321
623
|
{
|
|
322
|
-
let tmpActive = (
|
|
624
|
+
let tmpActive = (pCurrentPath === tmpGroup.Path) ? ' active' : '';
|
|
323
625
|
tmpHTML += '<a class="pict-inline-doc-nav-item' + tmpActive
|
|
324
626
|
+ '" data-doc-path="' + this._escapeHTML(tmpGroup.Path) + '">'
|
|
325
627
|
+ this._escapeHTML(tmpGroup.Name)
|
|
326
628
|
+ '</a>';
|
|
629
|
+
|
|
630
|
+
// If this is the active item, render heading sub-items
|
|
631
|
+
if (pCurrentPath === tmpGroup.Path)
|
|
632
|
+
{
|
|
633
|
+
tmpHTML += this._renderHeadingSubItems(pHeadings, tmpFilterLower);
|
|
634
|
+
}
|
|
327
635
|
}
|
|
328
636
|
|
|
329
637
|
for (let j = 0; j < tmpGroupItems.length; j++)
|
|
@@ -335,31 +643,223 @@ class InlineDocumentationNavView extends libPictView
|
|
|
335
643
|
continue;
|
|
336
644
|
}
|
|
337
645
|
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
646
|
+
if (tmpItem.External && tmpItem.ExternalURL)
|
|
647
|
+
{
|
|
648
|
+
// External link — opens in a new tab
|
|
649
|
+
tmpHTML += '<a class="pict-inline-doc-nav-item pict-inline-doc-nav-item-external'
|
|
650
|
+
+ '" data-external-url="' + this._escapeHTML(tmpItem.ExternalURL) + '">'
|
|
651
|
+
+ this._escapeHTML(tmpItem.Name)
|
|
652
|
+
+ '<svg class="pict-inline-doc-nav-external-icon" width="0.75em" height="0.75em" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M12 9v4a1 1 0 01-1 1H3a1 1 0 01-1-1V5a1 1 0 011-1h4"/><polyline points="8,2 14,2 14,8"/><line x1="14" y1="2" x2="7" y2="9"/></svg>'
|
|
653
|
+
+ '</a>';
|
|
654
|
+
}
|
|
655
|
+
else
|
|
656
|
+
{
|
|
657
|
+
let tmpActive = (pCurrentPath === tmpItem.Path) ? ' active' : '';
|
|
658
|
+
tmpHTML += '<a class="pict-inline-doc-nav-item' + tmpActive
|
|
659
|
+
+ '" data-doc-path="' + this._escapeHTML(tmpItem.Path) + '">'
|
|
660
|
+
+ this._escapeHTML(tmpItem.Name)
|
|
661
|
+
+ '</a>';
|
|
662
|
+
|
|
663
|
+
// If this is the active item, render heading sub-items
|
|
664
|
+
if (pCurrentPath === tmpItem.Path)
|
|
665
|
+
{
|
|
666
|
+
tmpHTML += this._renderHeadingSubItems(pHeadings, tmpFilterLower);
|
|
667
|
+
}
|
|
668
|
+
}
|
|
343
669
|
}
|
|
344
670
|
|
|
345
671
|
tmpHTML += '</div>';
|
|
346
672
|
tmpHTML += '</div>';
|
|
347
673
|
}
|
|
348
674
|
|
|
349
|
-
|
|
675
|
+
return tmpHTML;
|
|
676
|
+
}
|
|
350
677
|
|
|
351
|
-
|
|
352
|
-
|
|
678
|
+
/**
|
|
679
|
+
* Render heading sub-items (h2 and h3) beneath the active nav item.
|
|
680
|
+
*
|
|
681
|
+
* @param {Array} pHeadings - Array of { Text, Slug, Level }
|
|
682
|
+
* @param {string} pFilterText - Lowercase filter text
|
|
683
|
+
* @returns {string} HTML string for heading sub-items
|
|
684
|
+
*/
|
|
685
|
+
_renderHeadingSubItems(pHeadings, pFilterText)
|
|
686
|
+
{
|
|
687
|
+
if (!pHeadings || pHeadings.length < 1)
|
|
688
|
+
{
|
|
689
|
+
return '';
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
let tmpHTML = '';
|
|
693
|
+
|
|
694
|
+
for (let i = 0; i < pHeadings.length; i++)
|
|
695
|
+
{
|
|
696
|
+
let tmpHeading = pHeadings[i];
|
|
697
|
+
let tmpText = tmpHeading.Text || '';
|
|
698
|
+
|
|
699
|
+
// Apply filter
|
|
700
|
+
if (pFilterText && tmpText.toLowerCase().indexOf(pFilterText) < 0)
|
|
701
|
+
{
|
|
702
|
+
continue;
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
let tmpLevelClass = (tmpHeading.Level === 3) ? ' h3' : '';
|
|
706
|
+
tmpHTML += '<a class="pict-inline-doc-nav-heading' + tmpLevelClass
|
|
707
|
+
+ '" data-heading-slug="' + this._escapeHTML(tmpHeading.Slug) + '">'
|
|
708
|
+
+ this._escapeHTML(tmpText)
|
|
709
|
+
+ '</a>';
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
return tmpHTML;
|
|
353
713
|
}
|
|
354
714
|
|
|
355
715
|
/**
|
|
356
|
-
* Wire click handlers on navigation items
|
|
716
|
+
* Wire click handlers on navigation items, group headers, and controls.
|
|
357
717
|
*
|
|
358
718
|
* @param {HTMLElement} pContainer - The nav container element
|
|
359
719
|
*/
|
|
360
720
|
_wireClickHandlers(pContainer)
|
|
361
721
|
{
|
|
362
722
|
let tmpProvider = this.pict.providers['Pict-InlineDocumentation'];
|
|
723
|
+
let tmpState = this.pict.AppData.InlineDocumentation;
|
|
724
|
+
|
|
725
|
+
let tmpSelf = this;
|
|
726
|
+
|
|
727
|
+
// Collapse toggle (chevron)
|
|
728
|
+
let tmpCollapseToggle = pContainer.querySelector('#InlineDoc-Nav-CollapseToggle');
|
|
729
|
+
if (tmpCollapseToggle)
|
|
730
|
+
{
|
|
731
|
+
tmpCollapseToggle.addEventListener('click', () =>
|
|
732
|
+
{
|
|
733
|
+
if (tmpState)
|
|
734
|
+
{
|
|
735
|
+
tmpState.NavCollapsed = !tmpState.NavCollapsed;
|
|
736
|
+
}
|
|
737
|
+
tmpSelf._renderNavigation();
|
|
738
|
+
});
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
// Title click also toggles
|
|
742
|
+
let tmpTitleToggle = pContainer.querySelector('#InlineDoc-Nav-TitleToggle');
|
|
743
|
+
if (tmpTitleToggle)
|
|
744
|
+
{
|
|
745
|
+
tmpTitleToggle.addEventListener('click', () =>
|
|
746
|
+
{
|
|
747
|
+
if (tmpState)
|
|
748
|
+
{
|
|
749
|
+
tmpState.NavCollapsed = !tmpState.NavCollapsed;
|
|
750
|
+
}
|
|
751
|
+
tmpSelf._renderNavigation();
|
|
752
|
+
});
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
// Search icon — expands outline and focuses search input
|
|
756
|
+
let tmpSearchBtn = pContainer.querySelector('#InlineDoc-Nav-SearchBtn');
|
|
757
|
+
if (tmpSearchBtn)
|
|
758
|
+
{
|
|
759
|
+
tmpSearchBtn.addEventListener('click', (pEvent) =>
|
|
760
|
+
{
|
|
761
|
+
pEvent.stopPropagation();
|
|
762
|
+
if (tmpState)
|
|
763
|
+
{
|
|
764
|
+
tmpState.NavCollapsed = false;
|
|
765
|
+
}
|
|
766
|
+
tmpSelf._renderNavigation();
|
|
767
|
+
|
|
768
|
+
let tmpInput = document.getElementById('InlineDoc-Nav-FilterInput');
|
|
769
|
+
if (tmpInput)
|
|
770
|
+
{
|
|
771
|
+
tmpInput.focus();
|
|
772
|
+
}
|
|
773
|
+
});
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
// Search / filter input
|
|
777
|
+
let tmpFilterInput = pContainer.querySelector('#InlineDoc-Nav-FilterInput');
|
|
778
|
+
if (tmpFilterInput)
|
|
779
|
+
{
|
|
780
|
+
let tmpDebounceTimer = null;
|
|
781
|
+
|
|
782
|
+
tmpFilterInput.addEventListener('input', (pEvent) =>
|
|
783
|
+
{
|
|
784
|
+
let tmpValue = pEvent.target.value || '';
|
|
785
|
+
|
|
786
|
+
if (tmpState)
|
|
787
|
+
{
|
|
788
|
+
tmpState.NavFilterText = tmpValue;
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
// If search index is loaded, debounce full-text search
|
|
792
|
+
if (tmpState && tmpState.SearchIndexLoaded && tmpProvider && typeof tmpProvider.search === 'function')
|
|
793
|
+
{
|
|
794
|
+
if (tmpDebounceTimer) clearTimeout(tmpDebounceTimer);
|
|
795
|
+
tmpDebounceTimer = setTimeout(() =>
|
|
796
|
+
{
|
|
797
|
+
tmpState.SearchQuery = tmpValue;
|
|
798
|
+
tmpState.SearchResults = tmpValue.trim() ? tmpProvider.search(tmpValue) : [];
|
|
799
|
+
tmpSelf._renderNavigation();
|
|
800
|
+
|
|
801
|
+
let tmpNewInput = document.getElementById('InlineDoc-Nav-FilterInput');
|
|
802
|
+
if (tmpNewInput)
|
|
803
|
+
{
|
|
804
|
+
tmpNewInput.focus();
|
|
805
|
+
let tmpLen = tmpNewInput.value.length;
|
|
806
|
+
tmpNewInput.setSelectionRange(tmpLen, tmpLen);
|
|
807
|
+
}
|
|
808
|
+
}, 250);
|
|
809
|
+
}
|
|
810
|
+
else
|
|
811
|
+
{
|
|
812
|
+
// No search index — immediate client-side filter only
|
|
813
|
+
tmpSelf._renderNavigation();
|
|
814
|
+
|
|
815
|
+
let tmpNewInput = document.getElementById('InlineDoc-Nav-FilterInput');
|
|
816
|
+
if (tmpNewInput)
|
|
817
|
+
{
|
|
818
|
+
tmpNewInput.focus();
|
|
819
|
+
let tmpLen = tmpNewInput.value.length;
|
|
820
|
+
tmpNewInput.setSelectionRange(tmpLen, tmpLen);
|
|
821
|
+
}
|
|
822
|
+
}
|
|
823
|
+
});
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
// Search result clicks
|
|
827
|
+
let tmpSearchResults = pContainer.querySelectorAll('.pict-inline-doc-nav-search-result[data-search-path]');
|
|
828
|
+
for (let i = 0; i < tmpSearchResults.length; i++)
|
|
829
|
+
{
|
|
830
|
+
let tmpResult = tmpSearchResults[i];
|
|
831
|
+
tmpResult.addEventListener('click', (pEvent) =>
|
|
832
|
+
{
|
|
833
|
+
pEvent.preventDefault();
|
|
834
|
+
let tmpPath = tmpResult.getAttribute('data-search-path');
|
|
835
|
+
if (tmpProvider && tmpPath)
|
|
836
|
+
{
|
|
837
|
+
if (tmpState)
|
|
838
|
+
{
|
|
839
|
+
tmpState.SearchQuery = '';
|
|
840
|
+
tmpState.SearchResults = [];
|
|
841
|
+
tmpState.NavFilterText = '';
|
|
842
|
+
}
|
|
843
|
+
tmpProvider.loadDocument(tmpPath);
|
|
844
|
+
}
|
|
845
|
+
});
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
// External links — open in new tab
|
|
849
|
+
let tmpExternalLinks = pContainer.querySelectorAll('[data-external-url]');
|
|
850
|
+
for (let i = 0; i < tmpExternalLinks.length; i++)
|
|
851
|
+
{
|
|
852
|
+
let tmpExtLink = tmpExternalLinks[i];
|
|
853
|
+
tmpExtLink.addEventListener('click', (pEvent) =>
|
|
854
|
+
{
|
|
855
|
+
pEvent.preventDefault();
|
|
856
|
+
let tmpURL = tmpExtLink.getAttribute('data-external-url');
|
|
857
|
+
if (tmpURL)
|
|
858
|
+
{
|
|
859
|
+
window.open(tmpURL, '_blank');
|
|
860
|
+
}
|
|
861
|
+
});
|
|
862
|
+
}
|
|
363
863
|
|
|
364
864
|
// Document links
|
|
365
865
|
let tmpLinks = pContainer.querySelectorAll('.pict-inline-doc-nav-item[data-doc-path]');
|
|
@@ -372,11 +872,32 @@ class InlineDocumentationNavView extends libPictView
|
|
|
372
872
|
let tmpPath = tmpLink.getAttribute('data-doc-path');
|
|
373
873
|
if (tmpProvider && tmpPath)
|
|
374
874
|
{
|
|
875
|
+
// Clear filter when navigating
|
|
876
|
+
if (tmpState)
|
|
877
|
+
{
|
|
878
|
+
tmpState.NavFilterText = '';
|
|
879
|
+
}
|
|
375
880
|
tmpProvider.loadDocument(tmpPath);
|
|
376
881
|
}
|
|
377
882
|
});
|
|
378
883
|
}
|
|
379
884
|
|
|
885
|
+
// Heading links
|
|
886
|
+
let tmpHeadingLinks = pContainer.querySelectorAll('.pict-inline-doc-nav-heading[data-heading-slug]');
|
|
887
|
+
for (let i = 0; i < tmpHeadingLinks.length; i++)
|
|
888
|
+
{
|
|
889
|
+
let tmpHeadingLink = tmpHeadingLinks[i];
|
|
890
|
+
tmpHeadingLink.addEventListener('click', (pEvent) =>
|
|
891
|
+
{
|
|
892
|
+
pEvent.preventDefault();
|
|
893
|
+
let tmpSlug = tmpHeadingLink.getAttribute('data-heading-slug');
|
|
894
|
+
if (tmpProvider && tmpSlug)
|
|
895
|
+
{
|
|
896
|
+
tmpProvider._scrollToAnchor(tmpSlug);
|
|
897
|
+
}
|
|
898
|
+
});
|
|
899
|
+
}
|
|
900
|
+
|
|
380
901
|
// Group collapse toggle
|
|
381
902
|
let tmpHeaders = pContainer.querySelectorAll('.pict-inline-doc-nav-group-header');
|
|
382
903
|
for (let i = 0; i < tmpHeaders.length; i++)
|
|
@@ -388,6 +909,33 @@ class InlineDocumentationNavView extends libPictView
|
|
|
388
909
|
if (tmpGroup)
|
|
389
910
|
{
|
|
390
911
|
tmpGroup.classList.toggle('collapsed');
|
|
912
|
+
|
|
913
|
+
// Persist collapse state
|
|
914
|
+
let tmpGroupKey = tmpGroup.getAttribute('data-group');
|
|
915
|
+
if (tmpState && tmpGroupKey)
|
|
916
|
+
{
|
|
917
|
+
if (!tmpState.CollapsedGroups)
|
|
918
|
+
{
|
|
919
|
+
tmpState.CollapsedGroups = {};
|
|
920
|
+
}
|
|
921
|
+
let tmpToggle = tmpGroup.querySelector('.pict-inline-doc-nav-group-toggle');
|
|
922
|
+
if (tmpGroup.classList.contains('collapsed'))
|
|
923
|
+
{
|
|
924
|
+
tmpState.CollapsedGroups[tmpGroupKey] = true;
|
|
925
|
+
if (tmpToggle)
|
|
926
|
+
{
|
|
927
|
+
tmpToggle.classList.add('collapsed');
|
|
928
|
+
}
|
|
929
|
+
}
|
|
930
|
+
else
|
|
931
|
+
{
|
|
932
|
+
delete tmpState.CollapsedGroups[tmpGroupKey];
|
|
933
|
+
if (tmpToggle)
|
|
934
|
+
{
|
|
935
|
+
tmpToggle.classList.remove('collapsed');
|
|
936
|
+
}
|
|
937
|
+
}
|
|
938
|
+
}
|
|
391
939
|
}
|
|
392
940
|
});
|
|
393
941
|
}
|