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,18 @@
1
+ # Searching & Filtering
2
+
3
+ The bookshop provides a genre filter to help you find books in specific categories.
4
+
5
+ ## Genre Filter
6
+
7
+ The dropdown at the top of the book catalog lets you filter by genre:
8
+
9
+ - **All Genres** — Shows every book in the catalog
10
+ - **Software Engineering** — Books about coding practices and software design
11
+ - **Distributed Systems** — Books about scalable system architecture
12
+ - **Computer Science** — Foundational CS theory and algorithms
13
+
14
+ ## How It Works
15
+
16
+ When you select a genre, the book list instantly updates to show only books in that category. The filter selection is preserved when you navigate to a book detail page and back.
17
+
18
+ > Future versions will include full-text search across titles, authors, and descriptions.
@@ -0,0 +1,29 @@
1
+ # The Store Page
2
+
3
+ The store page is the detail view for a specific book. It provides all the information you need to make a purchase decision.
4
+
5
+ ## Layout
6
+
7
+ The store page uses a two-column layout:
8
+
9
+ 1. **Left column** — Book cover image
10
+ 2. **Right column** — Book metadata, description, and action buttons
11
+
12
+ ## Pricing
13
+
14
+ All prices are displayed in **USD** and include applicable tax. The price shown on the store page is the final price — no hidden fees at checkout.
15
+
16
+ ## Availability
17
+
18
+ Books can have one of two statuses:
19
+
20
+ | Status | Meaning |
21
+ |--------|---------|
22
+ | **In Stock** | The book is available for purchase |
23
+ | **Out of Stock** | The book is currently unavailable |
24
+
25
+ Out of stock titles may be restocked periodically. Check back later or browse similar titles in the catalog.
26
+
27
+ ## Returning to the Catalog
28
+
29
+ Click the **Back to Catalog** button at the top of the store page to return to the full book list. Your genre filter selection will be preserved.
@@ -0,0 +1,23 @@
1
+ # Welcome to the Bookshop
2
+
3
+ Welcome to the Pict Bookshop example application. This app demonstrates how inline documentation can be embedded alongside your application views to provide contextual help.
4
+
5
+ ## Getting Around
6
+
7
+ - **Book Catalog** — Browse the full list of available titles
8
+ - **Store Page** — Click on any book to see details and purchase options
9
+ - **Help** — Press **F1** or click the circled **?** icons to get contextual help
10
+
11
+ ## Quick Tips
12
+
13
+ > Press **F1** at any time to toggle the help panel. The help content changes based on which part of the application you are viewing.
14
+
15
+ Each section of the application has a small **?** button next to its header. Clicking it opens the help panel with documentation specific to that section.
16
+
17
+ ## Navigation
18
+
19
+ | Key | Action |
20
+ |-----|--------|
21
+ | F1 | Toggle help panel |
22
+ | Click ? | Open contextual help for that section |
23
+ | Click book | View book details and store page |
@@ -0,0 +1,236 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1">
6
+ <title>Bookshop - Pict Example</title>
7
+ <!-- PICT Dynamic View CSS Container -->
8
+ <style id="PICT-CSS"></style>
9
+ <!-- Red Rock Mesa Theme -->
10
+ <style>
11
+ *, *::before, *::after { box-sizing: border-box; }
12
+ body { margin: 0; padding: 0; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif; background: #FAEDCD; color: #264653; }
13
+
14
+ /* --- Header Bar --- */
15
+ .pict-example-header { display: flex; align-items: stretch; background: #264653; border-bottom: 3px solid #E76F51; position: fixed; top: 0; left: 0; right: 0; z-index: 100; }
16
+ .pict-example-badge { background: #E76F51; color: #fff; padding: 0.6rem 1rem; font-size: 0.7rem; font-weight: 800; text-transform: uppercase; letter-spacing: 0.1em; display: flex; align-items: center; gap: 0.5rem; }
17
+ .pict-example-badge svg { width: 14px; height: 14px; fill: #fff; flex-shrink: 0; }
18
+ .pict-example-app-name { padding: 0.6rem 1rem; color: #FAEDCD; font-size: 1.1rem; font-weight: 600; display: flex; align-items: center; }
19
+ .pict-example-module { margin-left: auto; padding: 0.6rem 1rem; color: #D4A373; font-size: 0.75rem; display: flex; align-items: center; letter-spacing: 0.03em; }
20
+ .pict-example-header-help-btn {
21
+ display: flex; align-items: center; justify-content: center;
22
+ padding: 0 1rem; cursor: pointer; color: #D4A373;
23
+ font-size: 0.85rem; font-weight: 600; gap: 0.4em;
24
+ transition: color 0.15s; border: none; background: transparent;
25
+ }
26
+ .pict-example-header-help-btn:hover { color: #FAEDCD; }
27
+ .pict-example-header-help-btn .help-icon {
28
+ display: inline-flex; align-items: center; justify-content: center;
29
+ width: 20px; height: 20px; border-radius: 50%;
30
+ border: 2px solid currentColor; font-size: 0.75em; font-weight: 800;
31
+ }
32
+
33
+ /* --- Layout --- */
34
+ .pict-example-layout { display: flex; margin-top: 44px; min-height: calc(100vh - 44px); }
35
+
36
+ /* --- Content Area --- */
37
+ .pict-example-content {
38
+ flex: 1; padding: 1.5rem; transition: margin-right 0.25s ease;
39
+ }
40
+ .pict-example-content.help-open {
41
+ margin-right: 380px;
42
+ }
43
+ #Bookshop-Content-Container {
44
+ background: #fff;
45
+ border: 1px solid #D4A373;
46
+ border-top: 4px solid #E76F51;
47
+ border-radius: 6px;
48
+ padding: 1.25rem;
49
+ box-shadow: 0 2px 8px rgba(38,70,83,0.08);
50
+ }
51
+
52
+ /* --- Help Panel (slide-in from right) --- */
53
+ #Bookshop-Help-Panel {
54
+ position: fixed;
55
+ top: 44px;
56
+ right: 0;
57
+ bottom: 0;
58
+ width: 380px;
59
+ min-width: 320px;
60
+ background: #FDFCFA;
61
+ border-left: 1px solid #D4A373;
62
+ box-shadow: -2px 0 12px rgba(38,70,83,0.08);
63
+ transform: translateX(100%);
64
+ transition: transform 0.25s ease;
65
+ z-index: 50;
66
+ display: flex;
67
+ flex-direction: column;
68
+ overflow: hidden;
69
+ }
70
+ #Bookshop-Help-Panel.visible {
71
+ transform: translateX(0);
72
+ }
73
+ .bookshop-help-panel-header {
74
+ display: flex;
75
+ align-items: center;
76
+ padding: 0.6em 1em;
77
+ background: #264653;
78
+ color: #FAEDCD;
79
+ font-weight: 600;
80
+ font-size: 0.9em;
81
+ flex-shrink: 0;
82
+ }
83
+ .bookshop-help-panel-header span { flex: 1; }
84
+ .bookshop-help-panel-close {
85
+ background: transparent;
86
+ border: none;
87
+ color: #D4A373;
88
+ font-size: 1.2em;
89
+ cursor: pointer;
90
+ padding: 0 0.3em;
91
+ line-height: 1;
92
+ }
93
+ .bookshop-help-panel-close:hover { color: #FAEDCD; }
94
+ #InlineDoc-Container {
95
+ flex: 1;
96
+ overflow: hidden;
97
+ min-height: 0;
98
+ }
99
+ /* Override the inline doc border/background within the help panel */
100
+ #Bookshop-Help-Panel .pict-inline-doc {
101
+ border: none;
102
+ border-radius: 0;
103
+ height: 100%;
104
+ }
105
+ /* Force compact (horizontal nav) mode inside the narrow help panel */
106
+ #Bookshop-Help-Panel .pict-inline-doc {
107
+ flex-direction: column;
108
+ }
109
+ #Bookshop-Help-Panel .pict-inline-doc-nav-container {
110
+ width: 100%;
111
+ min-width: 0;
112
+ max-width: none;
113
+ border-right: none;
114
+ border-bottom: 1px solid #E5DED4;
115
+ overflow-y: visible;
116
+ overflow-x: auto;
117
+ max-height: none;
118
+ }
119
+ #Bookshop-Help-Panel .pict-inline-doc-nav {
120
+ padding: 0.4em 0.5em;
121
+ display: flex;
122
+ flex-wrap: wrap;
123
+ align-items: center;
124
+ gap: 0.15em 0.3em;
125
+ }
126
+ #Bookshop-Help-Panel .pict-inline-doc-nav-group {
127
+ display: flex;
128
+ flex-wrap: wrap;
129
+ align-items: center;
130
+ margin-bottom: 0;
131
+ gap: 0.1em 0.2em;
132
+ }
133
+ #Bookshop-Help-Panel .pict-inline-doc-nav-group-header {
134
+ padding: 0.2em 0.5em;
135
+ font-size: 0.75em;
136
+ white-space: nowrap;
137
+ }
138
+ #Bookshop-Help-Panel .pict-inline-doc-nav-group-toggle {
139
+ display: none;
140
+ }
141
+ #Bookshop-Help-Panel .pict-inline-doc-nav-group-items {
142
+ display: flex !important;
143
+ flex-wrap: wrap;
144
+ gap: 0.1em;
145
+ }
146
+ #Bookshop-Help-Panel .pict-inline-doc-nav-item {
147
+ padding: 0.2em 0.5em;
148
+ font-size: 0.8em;
149
+ border-left: none;
150
+ border-radius: 3px;
151
+ white-space: nowrap;
152
+ }
153
+ #Bookshop-Help-Panel .pict-inline-doc-nav-item.active {
154
+ border-left: none;
155
+ background: #2E7D74;
156
+ color: #fff;
157
+ }
158
+ #Bookshop-Help-Panel .pict-inline-doc-nav-topic-badge {
159
+ margin: 0 0.3em;
160
+ padding: 0.15em 0.5em;
161
+ font-size: 0.75em;
162
+ }
163
+
164
+ /* --- F1 hint --- */
165
+ .bookshop-f1-hint {
166
+ position: fixed;
167
+ bottom: 1em;
168
+ right: 1em;
169
+ background: #264653;
170
+ color: #D4A373;
171
+ padding: 0.3em 0.7em;
172
+ border-radius: 4px;
173
+ font-size: 0.75em;
174
+ opacity: 0.7;
175
+ z-index: 10;
176
+ }
177
+ </style>
178
+ <script src="./pict.js" type="text/javascript"></script>
179
+ <script type="text/javascript">Pict.safeOnDocumentReady(() => { Pict.safeLoadPictApplication(BookshopExample, 2)});</script>
180
+ </head>
181
+ <body>
182
+ <!-- Header Bar -->
183
+ <div class="pict-example-header">
184
+ <div class="pict-example-badge">
185
+ <svg viewBox="0 0 16 16"><polygon points="8,1 10,6 16,6 11,9.5 13,15 8,11.5 3,15 5,9.5 0,6 6,6"/></svg>
186
+ Pict Example
187
+ </div>
188
+ <div class="pict-example-app-name">Bookshop</div>
189
+ <div class="pict-example-module">pict-section-inlinedocumentation</div>
190
+ <button class="pict-example-header-help-btn" id="Bookshop-Header-HelpBtn">
191
+ <span class="help-icon">?</span>
192
+ Help
193
+ </button>
194
+ </div>
195
+
196
+ <!-- Layout -->
197
+ <div class="pict-example-layout">
198
+ <div class="pict-example-content" id="Bookshop-Content-Area">
199
+ <div id="Bookshop-Content-Container"></div>
200
+ </div>
201
+ </div>
202
+
203
+ <!-- Help Panel (slide-in from right) -->
204
+ <div id="Bookshop-Help-Panel">
205
+ <div class="bookshop-help-panel-header">
206
+ <span>Help</span>
207
+ <button class="bookshop-help-panel-close" id="Bookshop-Help-CloseBtn">&#x2715;</button>
208
+ </div>
209
+ <div id="InlineDoc-Container"></div>
210
+ </div>
211
+
212
+ <!-- F1 hint -->
213
+ <div class="bookshop-f1-hint">Press F1 for help</div>
214
+
215
+ <!-- Load the Application -->
216
+ <script src="./bookshop_example.js" type="text/javascript"></script>
217
+
218
+ <!-- Wire header help button and close button -->
219
+ <script>
220
+ document.getElementById('Bookshop-Header-HelpBtn').addEventListener('click', function ()
221
+ {
222
+ if (window._Pict && window._Pict.PictApplication)
223
+ {
224
+ window._Pict.PictApplication.toggleHelp();
225
+ }
226
+ });
227
+ document.getElementById('Bookshop-Help-CloseBtn').addEventListener('click', function ()
228
+ {
229
+ if (window._Pict && window._Pict.PictApplication)
230
+ {
231
+ window._Pict.PictApplication.toggleHelp();
232
+ }
233
+ });
234
+ </script>
235
+ </body>
236
+ </html>
@@ -0,0 +1,34 @@
1
+ {
2
+ "name": "bookshop_example",
3
+ "version": "1.0.0",
4
+ "description": "Bookshop example demonstrating inline contextual documentation with pict-section-inlinedocumentation",
5
+ "main": "Pict-Application-Bookshop.js",
6
+ "scripts": {
7
+ "start": "node Pict-Application-Bookshop.js",
8
+ "build": "npx quack build && npx quack copy"
9
+ },
10
+ "author": "steven",
11
+ "license": "MIT",
12
+ "devDependencies": {},
13
+ "copyFilesSettings": {
14
+ "whenFileExists": "overwrite"
15
+ },
16
+ "copyFiles": [
17
+ {
18
+ "from": "./html/*",
19
+ "to": "./dist/"
20
+ },
21
+ {
22
+ "from": "../../node_modules/pict/dist/*",
23
+ "to": "./dist/"
24
+ },
25
+ {
26
+ "from": "./docs/*",
27
+ "to": "./dist/docs/"
28
+ },
29
+ {
30
+ "from": "./data/pict_documentation_topics.json",
31
+ "to": "./dist/docs/"
32
+ }
33
+ ]
34
+ }
@@ -0,0 +1,324 @@
1
+ const libPictView = require('pict-view');
2
+
3
+ const _ViewConfiguration =
4
+ {
5
+ ViewIdentifier: "Bookshop-BookList",
6
+
7
+ DefaultRenderable: "Bookshop-BookList-Display",
8
+ DefaultDestinationAddress: "#Bookshop-Content-Container",
9
+
10
+ AutoRender: false,
11
+
12
+ CSS: /*css*/`
13
+ .bookshop-section-header {
14
+ display: flex;
15
+ align-items: center;
16
+ gap: 0.5em;
17
+ margin-bottom: 1em;
18
+ }
19
+ .bookshop-section-title {
20
+ font-size: 1.5em;
21
+ font-weight: 700;
22
+ color: #264653;
23
+ margin: 0;
24
+ }
25
+ .bookshop-help-btn {
26
+ display: inline-flex;
27
+ align-items: center;
28
+ justify-content: center;
29
+ width: 22px;
30
+ height: 22px;
31
+ border-radius: 50%;
32
+ border: 2px solid #D4A373;
33
+ background: transparent;
34
+ color: #D4A373;
35
+ font-size: 0.75em;
36
+ font-weight: 700;
37
+ cursor: pointer;
38
+ line-height: 1;
39
+ padding: 0;
40
+ transition: background 0.15s, color 0.15s;
41
+ flex-shrink: 0;
42
+ }
43
+ .bookshop-help-btn:hover {
44
+ background: #D4A373;
45
+ color: #fff;
46
+ }
47
+ .bookshop-filter-bar {
48
+ margin-bottom: 1.25em;
49
+ display: flex;
50
+ align-items: center;
51
+ gap: 0.75em;
52
+ }
53
+ .bookshop-filter-bar label {
54
+ font-size: 0.85em;
55
+ font-weight: 600;
56
+ color: #5E5549;
57
+ }
58
+ .bookshop-filter-bar select {
59
+ padding: 0.35em 0.7em;
60
+ border: 1px solid #D4A373;
61
+ border-radius: 4px;
62
+ font-size: 0.85em;
63
+ background: #fff;
64
+ color: #264653;
65
+ }
66
+ .bookshop-book-grid {
67
+ display: grid;
68
+ grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
69
+ gap: 1.25em;
70
+ }
71
+ .bookshop-book-card {
72
+ display: flex;
73
+ gap: 1em;
74
+ padding: 1em;
75
+ background: #fff;
76
+ border: 1px solid #E5DED4;
77
+ border-radius: 6px;
78
+ cursor: pointer;
79
+ transition: box-shadow 0.15s, border-color 0.15s;
80
+ }
81
+ .bookshop-book-card:hover {
82
+ border-color: #D4A373;
83
+ box-shadow: 0 2px 8px rgba(38,70,83,0.1);
84
+ }
85
+ .bookshop-book-cover {
86
+ width: 80px;
87
+ height: 120px;
88
+ border-radius: 4px;
89
+ object-fit: cover;
90
+ flex-shrink: 0;
91
+ background: #F0ECE4;
92
+ }
93
+ .bookshop-book-info {
94
+ flex: 1;
95
+ min-width: 0;
96
+ }
97
+ .bookshop-book-title {
98
+ font-weight: 600;
99
+ font-size: 1em;
100
+ color: #264653;
101
+ margin: 0 0 0.2em;
102
+ }
103
+ .bookshop-book-author {
104
+ font-size: 0.85em;
105
+ color: #8A7F72;
106
+ margin: 0 0 0.4em;
107
+ }
108
+ .bookshop-book-genre {
109
+ display: inline-block;
110
+ font-size: 0.7em;
111
+ padding: 0.15em 0.5em;
112
+ background: #E8E3D8;
113
+ color: #5E5549;
114
+ border-radius: 3px;
115
+ margin-bottom: 0.4em;
116
+ }
117
+ .bookshop-book-price {
118
+ font-weight: 700;
119
+ color: #2E7D74;
120
+ font-size: 1.05em;
121
+ }
122
+ .bookshop-book-stock {
123
+ font-size: 0.75em;
124
+ margin-left: 0.5em;
125
+ }
126
+ .bookshop-book-stock.in-stock {
127
+ color: #2E7D74;
128
+ }
129
+ .bookshop-book-stock.out-of-stock {
130
+ color: #E76F51;
131
+ }
132
+ `,
133
+
134
+ Templates:
135
+ [
136
+ {
137
+ Hash: "Bookshop-BookList-Template",
138
+ Template: /*html*/`<div id="Bookshop-BookList-Body"></div>`
139
+ }
140
+ ],
141
+
142
+ Renderables:
143
+ [
144
+ {
145
+ RenderableHash: "Bookshop-BookList-Display",
146
+ TemplateHash: "Bookshop-BookList-Template",
147
+ DestinationAddress: "#Bookshop-Content-Container",
148
+ RenderMethod: "replace"
149
+ }
150
+ ]
151
+ };
152
+
153
+ class BookshopBookListView extends libPictView
154
+ {
155
+ constructor(pFable, pOptions, pServiceHash)
156
+ {
157
+ super(pFable, pOptions, pServiceHash);
158
+ }
159
+
160
+ onAfterRender()
161
+ {
162
+ this._renderBookList();
163
+ return super.onAfterRender();
164
+ }
165
+
166
+ _renderBookList()
167
+ {
168
+ if (typeof document === 'undefined')
169
+ {
170
+ return;
171
+ }
172
+
173
+ let tmpContainer = document.getElementById('Bookshop-BookList-Body');
174
+ if (!tmpContainer)
175
+ {
176
+ return;
177
+ }
178
+
179
+ let tmpState = this.pict.AppData.Bookshop;
180
+ let tmpBooks = tmpState.Books || [];
181
+ let tmpGenreFilter = tmpState.GenreFilter || '';
182
+
183
+ // Collect unique genres
184
+ let tmpGenres = [];
185
+ for (let i = 0; i < tmpBooks.length; i++)
186
+ {
187
+ if (tmpGenres.indexOf(tmpBooks[i].Genre) < 0)
188
+ {
189
+ tmpGenres.push(tmpBooks[i].Genre);
190
+ }
191
+ }
192
+ tmpGenres.sort();
193
+
194
+ // Filter books by genre
195
+ let tmpFilteredBooks = tmpBooks;
196
+ if (tmpGenreFilter)
197
+ {
198
+ tmpFilteredBooks = tmpBooks.filter((pBook) => { return pBook.Genre === tmpGenreFilter; });
199
+ }
200
+
201
+ let tmpHTML = '';
202
+
203
+ // Section header with help button
204
+ tmpHTML += '<div class="bookshop-section-header">';
205
+ tmpHTML += '<h2 class="bookshop-section-title" data-d-tooltip="catalog-title">Book Catalog</h2>';
206
+ tmpHTML += '<span data-d-tooltip="catalog-info" data-d-tooltip-icon></span>';
207
+ tmpHTML += '<button class="bookshop-help-btn" id="Bookshop-Help-BookList" title="Help: Book Catalog">?</button>';
208
+ tmpHTML += '</div>';
209
+
210
+ // Filter bar with help button
211
+ tmpHTML += '<div class="bookshop-filter-bar">';
212
+ tmpHTML += '<label data-d-tooltip="genre-filter">Genre:</label>';
213
+ tmpHTML += '<select id="Bookshop-GenreFilter">';
214
+ tmpHTML += '<option value="">All Genres</option>';
215
+ for (let g = 0; g < tmpGenres.length; g++)
216
+ {
217
+ let tmpSelected = (tmpGenreFilter === tmpGenres[g]) ? ' selected' : '';
218
+ tmpHTML += '<option value="' + tmpGenres[g] + '"' + tmpSelected + '>' + tmpGenres[g] + '</option>';
219
+ }
220
+ tmpHTML += '</select>';
221
+ tmpHTML += '<span data-d-tooltip="filter-info" data-d-tooltip-icon></span>';
222
+ tmpHTML += '<button class="bookshop-help-btn" id="Bookshop-Help-Search" title="Help: Search & Filter">?</button>';
223
+ tmpHTML += '</div>';
224
+
225
+ // Book grid
226
+ tmpHTML += '<div class="bookshop-book-grid">';
227
+ for (let i = 0; i < tmpFilteredBooks.length; i++)
228
+ {
229
+ let tmpBook = tmpFilteredBooks[i];
230
+ let tmpStockClass = tmpBook.InStock ? 'in-stock' : 'out-of-stock';
231
+ let tmpStockText = tmpBook.InStock ? 'In Stock' : 'Out of Stock';
232
+
233
+ tmpHTML += '<div class="bookshop-book-card" data-book-id="' + tmpBook.IDBook + '">';
234
+ tmpHTML += '<img class="bookshop-book-cover" src="' + tmpBook.Cover + '" alt="' + tmpBook.Title + '">';
235
+ tmpHTML += '<div class="bookshop-book-info">';
236
+ tmpHTML += '<p class="bookshop-book-title">' + tmpBook.Title + '</p>';
237
+ tmpHTML += '<p class="bookshop-book-author">' + tmpBook.Author + '</p>';
238
+ tmpHTML += '<span class="bookshop-book-genre" data-d-tooltip="book-genre">' + tmpBook.Genre + '</span>';
239
+ tmpHTML += '<div>';
240
+ tmpHTML += '<span class="bookshop-book-price" data-d-tooltip="book-price">$' + tmpBook.Price.toFixed(2) + '</span>';
241
+ tmpHTML += '<span class="bookshop-book-stock ' + tmpStockClass + '" data-d-tooltip="stock-status">' + tmpStockText + '</span>';
242
+ tmpHTML += '</div>';
243
+ tmpHTML += '</div>';
244
+ tmpHTML += '</div>';
245
+ }
246
+ tmpHTML += '</div>';
247
+
248
+ tmpContainer.innerHTML = tmpHTML;
249
+
250
+ // Wire click handlers
251
+ this._wireHandlers(tmpContainer);
252
+
253
+ // Scan for tooltip placeholders
254
+ let tmpDocProvider = this.pict.providers['Pict-InlineDocumentation'];
255
+ if (tmpDocProvider)
256
+ {
257
+ tmpDocProvider.scanTooltips();
258
+ }
259
+ }
260
+
261
+ _wireHandlers(pContainer)
262
+ {
263
+ let tmpApp = this.pict.PictApplication;
264
+
265
+ // Book cards
266
+ let tmpCards = pContainer.querySelectorAll('.bookshop-book-card');
267
+ for (let i = 0; i < tmpCards.length; i++)
268
+ {
269
+ let tmpCard = tmpCards[i];
270
+ tmpCard.addEventListener('click', () =>
271
+ {
272
+ let tmpID = parseInt(tmpCard.getAttribute('data-book-id'));
273
+ if (tmpApp)
274
+ {
275
+ tmpApp.showBook(tmpID);
276
+ }
277
+ });
278
+ }
279
+
280
+ // Genre filter
281
+ let tmpSelect = pContainer.querySelector('#Bookshop-GenreFilter');
282
+ if (tmpSelect)
283
+ {
284
+ tmpSelect.addEventListener('change', () =>
285
+ {
286
+ if (tmpApp)
287
+ {
288
+ tmpApp.filterByGenre(tmpSelect.value);
289
+ }
290
+ });
291
+ }
292
+
293
+ // Help buttons
294
+ let tmpHelpBookList = pContainer.querySelector('#Bookshop-Help-BookList');
295
+ if (tmpHelpBookList)
296
+ {
297
+ tmpHelpBookList.addEventListener('click', (pEvent) =>
298
+ {
299
+ pEvent.stopPropagation();
300
+ if (tmpApp)
301
+ {
302
+ tmpApp.showHelp('BOOKSHOP-BOOKLIST');
303
+ }
304
+ });
305
+ }
306
+
307
+ let tmpHelpSearch = pContainer.querySelector('#Bookshop-Help-Search');
308
+ if (tmpHelpSearch)
309
+ {
310
+ tmpHelpSearch.addEventListener('click', (pEvent) =>
311
+ {
312
+ pEvent.stopPropagation();
313
+ if (tmpApp)
314
+ {
315
+ tmpApp.showHelp('BOOKSHOP-SEARCH');
316
+ }
317
+ });
318
+ }
319
+ }
320
+ }
321
+
322
+ module.exports = BookshopBookListView;
323
+
324
+ module.exports.default_configuration = _ViewConfiguration;