pict-section-inlinedocumentation 0.0.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.
Files changed (51) hide show
  1. package/README.md +107 -0
  2. package/docs/.nojekyll +0 -0
  3. package/docs/README.md +83 -0
  4. package/docs/_cover.md +15 -0
  5. package/docs/_sidebar.md +24 -0
  6. package/docs/_topbar.md +8 -0
  7. package/docs/_version.json +7 -0
  8. package/docs/api-reference.md +185 -0
  9. package/docs/architecture.md +103 -0
  10. package/docs/css/docuserve.css +327 -0
  11. package/docs/embedding-level1-sidebar.md +92 -0
  12. package/docs/embedding-level2-routes.md +86 -0
  13. package/docs/embedding-level3-tooltips.md +97 -0
  14. package/docs/embedding-level4-autogen.md +126 -0
  15. package/docs/index.html +39 -0
  16. package/docs/overview.md +42 -0
  17. package/docs/quickstart.md +95 -0
  18. package/docs/reference.md +73 -0
  19. package/docs/retold-catalog.json +181 -0
  20. package/docs/retold-keyword-index.json +4374 -0
  21. package/example_applications/basic/docs/README.md +40 -0
  22. package/example_applications/basic/docs/_sidebar.md +4 -0
  23. package/example_applications/basic/docs/_topics.json +10 -0
  24. package/example_applications/basic/docs/advanced-topics.md +47 -0
  25. package/example_applications/basic/docs/getting-started.md +70 -0
  26. package/example_applications/basic/index.html +100 -0
  27. package/example_applications/bookshop/.quackage.json +10 -0
  28. package/example_applications/bookshop/Pict-Application-Bookshop-Configuration.json +15 -0
  29. package/example_applications/bookshop/Pict-Application-Bookshop.js +218 -0
  30. package/example_applications/bookshop/data/BookshopData.json +65 -0
  31. package/example_applications/bookshop/data/pict_documentation_topics.json +46 -0
  32. package/example_applications/bookshop/docs/_sidebar.md +6 -0
  33. package/example_applications/bookshop/docs/book-detail.md +21 -0
  34. package/example_applications/bookshop/docs/book-list.md +21 -0
  35. package/example_applications/bookshop/docs/search-filter.md +18 -0
  36. package/example_applications/bookshop/docs/store.md +29 -0
  37. package/example_applications/bookshop/docs/welcome.md +23 -0
  38. package/example_applications/bookshop/html/index.html +236 -0
  39. package/example_applications/bookshop/package.json +34 -0
  40. package/example_applications/bookshop/views/PictView-Bookshop-BookList.js +324 -0
  41. package/example_applications/bookshop/views/PictView-Bookshop-HelpToggle.js +44 -0
  42. package/example_applications/bookshop/views/PictView-Bookshop-Store.js +271 -0
  43. package/package.json +55 -0
  44. package/source/Pict-Section-InlineDocumentation.js +10 -0
  45. package/source/providers/Pict-Provider-InlineDocumentation.js +1995 -0
  46. package/source/views/Pict-View-InlineDocumentation-Content.js +542 -0
  47. package/source/views/Pict-View-InlineDocumentation-Layout.js +206 -0
  48. package/source/views/Pict-View-InlineDocumentation-Nav.js +475 -0
  49. package/source/views/Pict-View-InlineDocumentation-TopicManager.js +1623 -0
  50. package/test/Browser_Integration_tests.js +1449 -0
  51. package/test/Pict-Section-InlineDocumentation_test.js +1285 -0
@@ -0,0 +1,206 @@
1
+ const libPictView = require('pict-view');
2
+
3
+ const _ViewConfiguration =
4
+ {
5
+ ViewIdentifier: "InlineDoc-Layout",
6
+
7
+ DefaultRenderable: "InlineDoc-Layout-Container",
8
+ DefaultDestinationAddress: "#InlineDoc-Container",
9
+
10
+ AutoRender: false,
11
+
12
+ CSS: /*css*/`
13
+ .pict-inline-doc {
14
+ display: flex;
15
+ flex-direction: row;
16
+ width: 100%;
17
+ height: 100%;
18
+ min-height: 300px;
19
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
20
+ font-size: 15px;
21
+ color: #423D37;
22
+ background: #FDFCFA;
23
+ border: 1px solid #E5DED4;
24
+ border-radius: 6px;
25
+ overflow: hidden;
26
+ }
27
+ .pict-inline-doc-nav-container {
28
+ width: 240px;
29
+ min-width: 200px;
30
+ max-width: 300px;
31
+ border-right: 1px solid #E5DED4;
32
+ background: #F7F5F0;
33
+ overflow-y: auto;
34
+ flex-shrink: 0;
35
+ }
36
+ .pict-inline-doc-content-container {
37
+ flex: 1;
38
+ overflow-y: auto;
39
+ overflow-x: hidden;
40
+ min-width: 0;
41
+ }
42
+ .pict-inline-doc-nav-container.pict-inline-doc-nav-hidden {
43
+ display: none;
44
+ }
45
+ /* Compact mode: nav moves to a horizontal top bar when container is narrow */
46
+ .pict-inline-doc.pict-inline-doc-compact {
47
+ flex-direction: column;
48
+ }
49
+ .pict-inline-doc.pict-inline-doc-compact .pict-inline-doc-nav-container {
50
+ width: 100%;
51
+ min-width: 0;
52
+ max-width: none;
53
+ border-right: none;
54
+ border-bottom: 1px solid #E5DED4;
55
+ overflow-y: visible;
56
+ overflow-x: auto;
57
+ flex-shrink: 0;
58
+ max-height: none;
59
+ }
60
+ /* Compact mode: nav items flow horizontally */
61
+ .pict-inline-doc.pict-inline-doc-compact .pict-inline-doc-nav {
62
+ padding: 0.4em 0.5em;
63
+ display: flex;
64
+ flex-wrap: wrap;
65
+ align-items: center;
66
+ gap: 0.15em 0.3em;
67
+ }
68
+ .pict-inline-doc.pict-inline-doc-compact .pict-inline-doc-nav-group {
69
+ display: flex;
70
+ flex-wrap: wrap;
71
+ align-items: center;
72
+ margin-bottom: 0;
73
+ gap: 0.1em 0.2em;
74
+ }
75
+ .pict-inline-doc.pict-inline-doc-compact .pict-inline-doc-nav-group-header {
76
+ padding: 0.2em 0.5em;
77
+ font-size: 0.75em;
78
+ white-space: nowrap;
79
+ }
80
+ .pict-inline-doc.pict-inline-doc-compact .pict-inline-doc-nav-group-toggle {
81
+ display: none;
82
+ }
83
+ .pict-inline-doc.pict-inline-doc-compact .pict-inline-doc-nav-group-items {
84
+ display: flex !important;
85
+ flex-wrap: wrap;
86
+ gap: 0.1em;
87
+ }
88
+ .pict-inline-doc.pict-inline-doc-compact .pict-inline-doc-nav-item {
89
+ padding: 0.2em 0.5em;
90
+ font-size: 0.8em;
91
+ border-left: none;
92
+ border-radius: 3px;
93
+ white-space: nowrap;
94
+ }
95
+ .pict-inline-doc.pict-inline-doc-compact .pict-inline-doc-nav-item.active {
96
+ border-left: none;
97
+ background: #2E7D74;
98
+ color: #fff;
99
+ }
100
+ .pict-inline-doc.pict-inline-doc-compact .pict-inline-doc-nav-topic-badge {
101
+ margin: 0 0.3em;
102
+ padding: 0.15em 0.5em;
103
+ font-size: 0.75em;
104
+ }
105
+ `,
106
+
107
+ Templates:
108
+ [
109
+ {
110
+ Hash: "InlineDoc-Layout-Template",
111
+ Template: /*html*/`
112
+ <div class="pict-inline-doc">
113
+ <div class="pict-inline-doc-nav-container" id="InlineDoc-Nav-Container"></div>
114
+ <div class="pict-inline-doc-content-container" id="InlineDoc-Content-Container"></div>
115
+ </div>
116
+ `
117
+ }
118
+ ],
119
+
120
+ Renderables:
121
+ [
122
+ {
123
+ RenderableHash: "InlineDoc-Layout-Container",
124
+ TemplateHash: "InlineDoc-Layout-Template",
125
+ DestinationAddress: "#InlineDoc-Container",
126
+ RenderMethod: "replace"
127
+ }
128
+ ]
129
+ };
130
+
131
+ class InlineDocumentationLayoutView extends libPictView
132
+ {
133
+ constructor(pFable, pOptions, pServiceHash)
134
+ {
135
+ super(pFable, pOptions, pServiceHash);
136
+ }
137
+
138
+ onAfterRender()
139
+ {
140
+ // Inject all view CSS into the PICT-CSS style element
141
+ this.pict.CSSMap.injectCSS();
142
+
143
+ // Watch for size changes and toggle compact mode
144
+ this._setupCompactModeObserver();
145
+
146
+ return super.onAfterRender();
147
+ }
148
+
149
+ /**
150
+ * Set up a ResizeObserver to toggle compact mode when the container
151
+ * is too narrow for a side-by-side nav + content layout.
152
+ *
153
+ * Below the threshold, the nav switches to a horizontal top bar.
154
+ */
155
+ _setupCompactModeObserver()
156
+ {
157
+ if (typeof document === 'undefined' || typeof ResizeObserver === 'undefined')
158
+ {
159
+ return;
160
+ }
161
+
162
+ let tmpContainer = document.querySelector('.pict-inline-doc');
163
+ if (!tmpContainer)
164
+ {
165
+ return;
166
+ }
167
+
168
+ // Clean up any previous observer
169
+ if (this._resizeObserver)
170
+ {
171
+ this._resizeObserver.disconnect();
172
+ }
173
+
174
+ let tmpCompactThreshold = 550;
175
+
176
+ this._resizeObserver = new ResizeObserver((pEntries) =>
177
+ {
178
+ for (let i = 0; i < pEntries.length; i++)
179
+ {
180
+ let tmpWidth = pEntries[i].contentRect.width;
181
+
182
+ if (tmpWidth < tmpCompactThreshold)
183
+ {
184
+ tmpContainer.classList.add('pict-inline-doc-compact');
185
+ }
186
+ else
187
+ {
188
+ tmpContainer.classList.remove('pict-inline-doc-compact');
189
+ }
190
+ }
191
+ });
192
+
193
+ this._resizeObserver.observe(tmpContainer);
194
+
195
+ // Also do an immediate check
196
+ let tmpWidth = tmpContainer.offsetWidth;
197
+ if (tmpWidth > 0 && tmpWidth < tmpCompactThreshold)
198
+ {
199
+ tmpContainer.classList.add('pict-inline-doc-compact');
200
+ }
201
+ }
202
+ }
203
+
204
+ module.exports = InlineDocumentationLayoutView;
205
+
206
+ module.exports.default_configuration = _ViewConfiguration;
@@ -0,0 +1,475 @@
1
+ const libPictView = require('pict-view');
2
+
3
+ const _ViewConfiguration =
4
+ {
5
+ ViewIdentifier: "InlineDoc-Nav",
6
+
7
+ DefaultRenderable: "InlineDoc-Nav-Display",
8
+ DefaultDestinationAddress: "#InlineDoc-Nav-Container",
9
+
10
+ AutoRender: false,
11
+
12
+ CSS: /*css*/`
13
+ .pict-inline-doc-nav {
14
+ padding: 1em 0;
15
+ }
16
+ .pict-inline-doc-nav-group {
17
+ margin-bottom: 0.5em;
18
+ }
19
+ .pict-inline-doc-nav-group-header {
20
+ display: flex;
21
+ align-items: center;
22
+ padding: 0.4em 1em;
23
+ font-weight: 600;
24
+ font-size: 0.85em;
25
+ color: #5E5549;
26
+ text-transform: uppercase;
27
+ letter-spacing: 0.03em;
28
+ cursor: pointer;
29
+ user-select: none;
30
+ }
31
+ .pict-inline-doc-nav-group-header:hover {
32
+ color: #3D3229;
33
+ }
34
+ .pict-inline-doc-nav-group-toggle {
35
+ margin-right: 0.4em;
36
+ font-size: 0.7em;
37
+ transition: transform 0.15s ease;
38
+ }
39
+ .pict-inline-doc-nav-group.collapsed .pict-inline-doc-nav-group-toggle {
40
+ transform: rotate(-90deg);
41
+ }
42
+ .pict-inline-doc-nav-group.collapsed .pict-inline-doc-nav-group-items {
43
+ display: none;
44
+ }
45
+ .pict-inline-doc-nav-item {
46
+ display: block;
47
+ padding: 0.3em 1em 0.3em 1.8em;
48
+ color: #5E5549;
49
+ text-decoration: none;
50
+ font-size: 0.9em;
51
+ cursor: pointer;
52
+ border-left: 3px solid transparent;
53
+ transition: background 0.1s ease, border-color 0.1s ease;
54
+ }
55
+ .pict-inline-doc-nav-item:hover {
56
+ background: #EDE8DF;
57
+ color: #3D3229;
58
+ }
59
+ .pict-inline-doc-nav-item.active {
60
+ background: #E8E3D8;
61
+ color: #2E7D74;
62
+ border-left-color: #2E7D74;
63
+ font-weight: 500;
64
+ }
65
+ .pict-inline-doc-nav-topic-badge {
66
+ display: inline-block;
67
+ margin: 0.5em 1em;
68
+ padding: 0.3em 0.7em;
69
+ background: #2E7D74;
70
+ color: #fff;
71
+ border-radius: 4px;
72
+ font-size: 0.8em;
73
+ font-weight: 500;
74
+ }
75
+ .pict-inline-doc-nav-topic-clear {
76
+ margin-left: 0.5em;
77
+ cursor: pointer;
78
+ opacity: 0.8;
79
+ }
80
+ .pict-inline-doc-nav-topic-clear:hover {
81
+ opacity: 1;
82
+ }
83
+ .pict-inline-doc-nav-toolbar {
84
+ display: flex;
85
+ align-items: center;
86
+ gap: 0.3em;
87
+ padding: 0.3em 1em;
88
+ border-bottom: 1px solid #EAE3D8;
89
+ }
90
+ .pict-inline-doc-nav-toolbar-btn {
91
+ display: inline-flex;
92
+ align-items: center;
93
+ justify-content: center;
94
+ width: 28px;
95
+ height: 28px;
96
+ border: 1px solid #DDD6CA;
97
+ border-radius: 3px;
98
+ background: #fff;
99
+ color: #5E5549;
100
+ font-size: 0.9em;
101
+ cursor: pointer;
102
+ transition: background 0.1s, border-color 0.1s;
103
+ }
104
+ .pict-inline-doc-nav-toolbar-btn:hover {
105
+ background: #F0ECE4;
106
+ border-color: #C4BDB3;
107
+ }
108
+ .pict-inline-doc-nav-toolbar-btn.accent {
109
+ border-color: #2E7D74;
110
+ color: #2E7D74;
111
+ }
112
+ .pict-inline-doc-nav-toolbar-btn.accent:hover {
113
+ background: #F0F9F7;
114
+ }
115
+ .pict-inline-doc-nav-toolbar-btn.active {
116
+ background: #2E7D74;
117
+ color: #fff;
118
+ border-color: #2E7D74;
119
+ }
120
+ .pict-inline-doc-nav-toolbar-btn.active:hover {
121
+ background: #266D65;
122
+ }
123
+ .pict-inline-doc-nav-toolbar-spacer {
124
+ flex: 1;
125
+ }
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
+ `,
178
+
179
+ Templates:
180
+ [
181
+ {
182
+ Hash: "InlineDoc-Nav-Template",
183
+ Template: /*html*/`<div class="pict-inline-doc-nav" id="InlineDoc-Nav-Body"></div>`
184
+ }
185
+ ],
186
+
187
+ Renderables:
188
+ [
189
+ {
190
+ RenderableHash: "InlineDoc-Nav-Display",
191
+ TemplateHash: "InlineDoc-Nav-Template",
192
+ DestinationAddress: "#InlineDoc-Nav-Container",
193
+ RenderMethod: "replace"
194
+ }
195
+ ]
196
+ };
197
+
198
+ class InlineDocumentationNavView extends libPictView
199
+ {
200
+ constructor(pFable, pOptions, pServiceHash)
201
+ {
202
+ super(pFable, pOptions, pServiceHash);
203
+ }
204
+
205
+ onAfterRender()
206
+ {
207
+ this._renderNavigation();
208
+ return super.onAfterRender();
209
+ }
210
+
211
+ /**
212
+ * Build and inject the navigation HTML into the nav body.
213
+ */
214
+ _renderNavigation()
215
+ {
216
+ if (typeof document === 'undefined')
217
+ {
218
+ return;
219
+ }
220
+
221
+ let tmpContainer = document.getElementById('InlineDoc-Nav-Body');
222
+ if (!tmpContainer)
223
+ {
224
+ return;
225
+ }
226
+
227
+ let tmpState = this.pict.AppData.InlineDocumentation;
228
+ if (!tmpState)
229
+ {
230
+ return;
231
+ }
232
+
233
+ let tmpHTML = '';
234
+ let tmpCurrentPath = tmpState.CurrentPath || '';
235
+ let tmpActiveTopic = tmpState.Topic;
236
+ let tmpTopicDef = null;
237
+ let tmpTopicDocuments = null;
238
+
239
+ // If a topic is active, show a badge and filter documents.
240
+ // Supports both formats:
241
+ // pict_documentation_topics.json: { TopicCode, TopicTitle, TopicHelpFilePath }
242
+ // legacy: { Name, Documents: [] }
243
+ if (tmpActiveTopic && tmpState.Topics && tmpState.Topics[tmpActiveTopic])
244
+ {
245
+ tmpTopicDef = tmpState.Topics[tmpActiveTopic];
246
+
247
+ // Determine the display name (TopicTitle or Name)
248
+ let tmpTopicName = tmpTopicDef.TopicTitle || tmpTopicDef.Name || tmpActiveTopic;
249
+
250
+ // Determine matching documents
251
+ if (tmpTopicDef.TopicHelpFilePath)
252
+ {
253
+ // pict_documentation_topics.json format — single file per topic
254
+ tmpTopicDocuments = [tmpTopicDef.TopicHelpFilePath];
255
+ }
256
+ else if (tmpTopicDef.Documents)
257
+ {
258
+ // Legacy format — array of document paths
259
+ tmpTopicDocuments = tmpTopicDef.Documents;
260
+ }
261
+ else
262
+ {
263
+ tmpTopicDocuments = [];
264
+ }
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">&#x2715;</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">&#x2699;</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">&#x1F517;</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">&#x1F4AC;</button>';
283
+ tmpHTML += '<span class="pict-inline-doc-nav-toolbar-spacer"></span>';
284
+ tmpHTML += '</div>';
285
+ }
286
+
287
+ let tmpGroups = tmpState.SidebarGroups || [];
288
+
289
+ for (let i = 0; i < tmpGroups.length; i++)
290
+ {
291
+ let tmpGroup = tmpGroups[i];
292
+ let tmpGroupItems = tmpGroup.Items || [];
293
+
294
+ // If topic filter is active, only include items that match
295
+ if (tmpTopicDocuments)
296
+ {
297
+ tmpGroupItems = tmpGroupItems.filter((pItem) =>
298
+ {
299
+ return tmpTopicDocuments.indexOf(pItem.Path) >= 0;
300
+ });
301
+
302
+ // Also check if the group-level path matches
303
+ let tmpGroupMatches = tmpTopicDocuments.indexOf(tmpGroup.Path) >= 0;
304
+
305
+ if (tmpGroupItems.length < 1 && !tmpGroupMatches)
306
+ {
307
+ continue;
308
+ }
309
+ }
310
+
311
+ tmpHTML += '<div class="pict-inline-doc-nav-group" data-group="' + this._escapeHTML(tmpGroup.Key) + '">';
312
+ tmpHTML += '<div class="pict-inline-doc-nav-group-header">';
313
+ tmpHTML += '<span class="pict-inline-doc-nav-group-toggle">&#x25BC;</span>';
314
+ tmpHTML += this._escapeHTML(tmpGroup.Name);
315
+ tmpHTML += '</div>';
316
+
317
+ tmpHTML += '<div class="pict-inline-doc-nav-group-items">';
318
+
319
+ // If the group itself has a path (it's a link), show it as the first item
320
+ if (tmpGroup.Path)
321
+ {
322
+ let tmpActive = (tmpCurrentPath === tmpGroup.Path) ? ' active' : '';
323
+ tmpHTML += '<a class="pict-inline-doc-nav-item' + tmpActive
324
+ + '" data-doc-path="' + this._escapeHTML(tmpGroup.Path) + '">'
325
+ + this._escapeHTML(tmpGroup.Name)
326
+ + '</a>';
327
+ }
328
+
329
+ for (let j = 0; j < tmpGroupItems.length; j++)
330
+ {
331
+ let tmpItem = tmpGroupItems[j];
332
+ if (!tmpItem.Path)
333
+ {
334
+ tmpHTML += '<span class="pict-inline-doc-nav-item">' + this._escapeHTML(tmpItem.Name) + '</span>';
335
+ continue;
336
+ }
337
+
338
+ let tmpActive = (tmpCurrentPath === tmpItem.Path) ? ' active' : '';
339
+ tmpHTML += '<a class="pict-inline-doc-nav-item' + tmpActive
340
+ + '" data-doc-path="' + this._escapeHTML(tmpItem.Path) + '">'
341
+ + this._escapeHTML(tmpItem.Name)
342
+ + '</a>';
343
+ }
344
+
345
+ tmpHTML += '</div>';
346
+ tmpHTML += '</div>';
347
+ }
348
+
349
+ tmpContainer.innerHTML = tmpHTML;
350
+
351
+ // Wire up click handlers
352
+ this._wireClickHandlers(tmpContainer);
353
+ }
354
+
355
+ /**
356
+ * Wire click handlers on navigation items and group headers.
357
+ *
358
+ * @param {HTMLElement} pContainer - The nav container element
359
+ */
360
+ _wireClickHandlers(pContainer)
361
+ {
362
+ let tmpProvider = this.pict.providers['Pict-InlineDocumentation'];
363
+
364
+ // Document links
365
+ let tmpLinks = pContainer.querySelectorAll('.pict-inline-doc-nav-item[data-doc-path]');
366
+ for (let i = 0; i < tmpLinks.length; i++)
367
+ {
368
+ let tmpLink = tmpLinks[i];
369
+ tmpLink.addEventListener('click', (pEvent) =>
370
+ {
371
+ pEvent.preventDefault();
372
+ let tmpPath = tmpLink.getAttribute('data-doc-path');
373
+ if (tmpProvider && tmpPath)
374
+ {
375
+ tmpProvider.loadDocument(tmpPath);
376
+ }
377
+ });
378
+ }
379
+
380
+ // Group collapse toggle
381
+ let tmpHeaders = pContainer.querySelectorAll('.pict-inline-doc-nav-group-header');
382
+ for (let i = 0; i < tmpHeaders.length; i++)
383
+ {
384
+ let tmpHeader = tmpHeaders[i];
385
+ tmpHeader.addEventListener('click', () =>
386
+ {
387
+ let tmpGroup = tmpHeader.parentElement;
388
+ if (tmpGroup)
389
+ {
390
+ tmpGroup.classList.toggle('collapsed');
391
+ }
392
+ });
393
+ }
394
+
395
+ // Topic clear button
396
+ let tmpClearBtn = pContainer.querySelector('#InlineDoc-Nav-ClearTopic');
397
+ if (tmpClearBtn && tmpProvider)
398
+ {
399
+ tmpClearBtn.addEventListener('click', (pEvent) =>
400
+ {
401
+ pEvent.stopPropagation();
402
+ tmpProvider.clearTopic();
403
+ });
404
+ }
405
+
406
+ // Topic manager button
407
+ let tmpManageBtn = pContainer.querySelector('#InlineDoc-Nav-ManageTopics');
408
+ if (tmpManageBtn)
409
+ {
410
+ tmpManageBtn.addEventListener('click', (pEvent) =>
411
+ {
412
+ pEvent.stopPropagation();
413
+ let tmpTopicManagerView = this.pict.views['InlineDoc-TopicManager'];
414
+ if (tmpTopicManagerView)
415
+ {
416
+ tmpTopicManagerView.showTopicManager();
417
+ }
418
+ });
419
+ }
420
+
421
+ // Tooltip edit mode toggle
422
+ let tmpTooltipEditBtn = pContainer.querySelector('#InlineDoc-Nav-TooltipEditMode');
423
+ if (tmpTooltipEditBtn)
424
+ {
425
+ tmpTooltipEditBtn.addEventListener('click', (pEvent) =>
426
+ {
427
+ pEvent.stopPropagation();
428
+ let tmpDocProvider = this.pict.providers['Pict-InlineDocumentation'];
429
+ if (tmpDocProvider)
430
+ {
431
+ let tmpCurrentState = this.pict.AppData.InlineDocumentation;
432
+ tmpDocProvider.setTooltipEditMode(!tmpCurrentState.TooltipEditMode);
433
+ }
434
+ });
435
+ }
436
+
437
+ // Bind topic to route button
438
+ let tmpBindBtn = pContainer.querySelector('#InlineDoc-Nav-BindTopic');
439
+ if (tmpBindBtn)
440
+ {
441
+ tmpBindBtn.addEventListener('click', (pEvent) =>
442
+ {
443
+ pEvent.stopPropagation();
444
+ let tmpTopicManagerView = this.pict.views['InlineDoc-TopicManager'];
445
+ if (tmpTopicManagerView)
446
+ {
447
+ tmpTopicManagerView.showBindTopicToRoute();
448
+ }
449
+ });
450
+ }
451
+ }
452
+
453
+ /**
454
+ * Escape HTML special characters.
455
+ *
456
+ * @param {string} pText - Text to escape
457
+ * @returns {string} Escaped text
458
+ */
459
+ _escapeHTML(pText)
460
+ {
461
+ if (!pText)
462
+ {
463
+ return '';
464
+ }
465
+ return pText
466
+ .replace(/&/g, '&amp;')
467
+ .replace(/</g, '&lt;')
468
+ .replace(/>/g, '&gt;')
469
+ .replace(/"/g, '&quot;');
470
+ }
471
+ }
472
+
473
+ module.exports = InlineDocumentationNavView;
474
+
475
+ module.exports.default_configuration = _ViewConfiguration;