pict-section-formeditor 1.0.6 → 1.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/form_editor_flex/FormEditorFlex-Example-Application.js +345 -0
- package/example_applications/form_editor_flex/html/index.html +65 -0
- package/example_applications/form_editor_flex/html/manifests/Complex-Table.json +974 -0
- package/example_applications/form_editor_flex/html/manifests/Distill-Example.json +200 -0
- package/example_applications/form_editor_flex/html/manifests/Gradebook-Assignment.json +38 -0
- package/example_applications/form_editor_flex/html/manifests/Gradebook-Student.json +40 -0
- package/example_applications/form_editor_flex/html/manifests/Manyfest-Editor.json +347 -0
- package/example_applications/form_editor_flex/html/manifests/Patient-Intake.json +815 -0
- package/example_applications/form_editor_flex/html/manifests/Project-Proposal.json +865 -0
- package/example_applications/form_editor_flex/html/manifests/Simple-Form.json +232 -0
- package/example_applications/form_editor_flex/html/manifests/Simple-Table.json +79 -0
- package/example_applications/form_editor_flex/package.json +50 -0
- package/package.json +3 -3
- package/source/providers/Pict-Provider-FormEditorDragDrop.js +98 -0
- package/source/providers/Pict-Provider-FormEditorRendering.js +5 -4
- package/source/views/PictView-FormEditor-InlineEditing.js +1 -1
- package/source/views/PictView-FormEditor-PropertiesPanel.js +87 -1
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
const libPict = require('pict');
|
|
2
|
+
const libPictApplication = require('pict-application');
|
|
3
|
+
const libPictSectionFormEditor = require('../../source/Pict-Section-FormEditor.js');
|
|
4
|
+
|
|
5
|
+
// The list of available manifests for the selector
|
|
6
|
+
const _ManifestList =
|
|
7
|
+
[
|
|
8
|
+
{ Name: 'New Form', File: false },
|
|
9
|
+
{ Name: 'Patient Intake (large)', File: 'manifests/Patient-Intake.json' },
|
|
10
|
+
{ Name: 'Project Proposal (large)', File: 'manifests/Project-Proposal.json' },
|
|
11
|
+
{ Name: 'Complex Table', File: 'manifests/Complex-Table.json' },
|
|
12
|
+
{ Name: 'Manyfest Editor', File: 'manifests/Manyfest-Editor.json' },
|
|
13
|
+
{ Name: 'Simple Form', File: 'manifests/Simple-Form.json' },
|
|
14
|
+
{ Name: 'Gradebook - Student', File: 'manifests/Gradebook-Student.json' },
|
|
15
|
+
{ Name: 'Gradebook - Assignment', File: 'manifests/Gradebook-Assignment.json' },
|
|
16
|
+
{ Name: 'Distill (Entity Bundles)', File: 'manifests/Distill-Example.json' }
|
|
17
|
+
];
|
|
18
|
+
|
|
19
|
+
class FormEditorFlexExampleApplication extends libPictApplication
|
|
20
|
+
{
|
|
21
|
+
constructor(pFable, pOptions, pServiceHash)
|
|
22
|
+
{
|
|
23
|
+
super(pFable, pOptions, pServiceHash);
|
|
24
|
+
|
|
25
|
+
this._ManifestList = _ManifestList;
|
|
26
|
+
this._FormEditorView = null;
|
|
27
|
+
this._DragDropEnabled = false;
|
|
28
|
+
this._ShowHashes = false;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
onAfterInitializeAsync(fCallback)
|
|
32
|
+
{
|
|
33
|
+
// Start with an empty manifest; the first sample will be loaded after render
|
|
34
|
+
this.pict.AppData.FormConfig =
|
|
35
|
+
{
|
|
36
|
+
Scope: 'NewForm',
|
|
37
|
+
Sections: [],
|
|
38
|
+
Descriptors: {}
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
// Store the manifest list for the selector template
|
|
42
|
+
this.pict.AppData.ManifestList = this._ManifestList;
|
|
43
|
+
|
|
44
|
+
// Override the default CSS to remove the fixed height and use natural flow
|
|
45
|
+
let tmpDefaultConfig = JSON.parse(JSON.stringify(libPictSectionFormEditor.default_configuration));
|
|
46
|
+
|
|
47
|
+
// Replace the fixed-height .pict-formeditor rule with a flow-friendly version
|
|
48
|
+
// The key change: remove `height: calc(100vh - 120px)` and `overflow: hidden`
|
|
49
|
+
// so the editor flows with the page. The properties panel gets `position: sticky`.
|
|
50
|
+
let tmpCSS = tmpDefaultConfig.CSS;
|
|
51
|
+
|
|
52
|
+
// Patch: .pict-formeditor — remove fixed height, allow natural flow
|
|
53
|
+
tmpCSS = tmpCSS.replace(
|
|
54
|
+
/\.pict-formeditor\s*\{[^}]*\}/,
|
|
55
|
+
`.pict-formeditor
|
|
56
|
+
{
|
|
57
|
+
position: relative;
|
|
58
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
59
|
+
font-size: 14px;
|
|
60
|
+
color: #3D3229;
|
|
61
|
+
background: #FDFCFA;
|
|
62
|
+
border: 1px solid #E8E3DA;
|
|
63
|
+
border-radius: 6px;
|
|
64
|
+
display: flex;
|
|
65
|
+
flex-direction: column;
|
|
66
|
+
}`
|
|
67
|
+
);
|
|
68
|
+
|
|
69
|
+
// Patch: .pict-fe-editor-layout — remove overflow:hidden and min-height:0
|
|
70
|
+
// so the two-column layout can grow naturally
|
|
71
|
+
tmpCSS = tmpCSS.replace(
|
|
72
|
+
/\.pict-fe-editor-layout\s*\{[^}]*\}/,
|
|
73
|
+
`.pict-fe-editor-layout
|
|
74
|
+
{
|
|
75
|
+
display: flex;
|
|
76
|
+
gap: 0;
|
|
77
|
+
flex: 1;
|
|
78
|
+
position: relative;
|
|
79
|
+
}`
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
// Patch: .pict-fe-editor-content — let it grow naturally
|
|
83
|
+
tmpCSS = tmpCSS.replace(
|
|
84
|
+
/\.pict-fe-editor-content\s*\{[^}]*\}/,
|
|
85
|
+
`.pict-fe-editor-content
|
|
86
|
+
{
|
|
87
|
+
flex: 1;
|
|
88
|
+
min-width: 300px;
|
|
89
|
+
display: flex;
|
|
90
|
+
flex-direction: column;
|
|
91
|
+
}`
|
|
92
|
+
);
|
|
93
|
+
|
|
94
|
+
// Patch: .pict-fe-tabcontent — remove min-height:0 and overflow:auto
|
|
95
|
+
// so content flows naturally instead of scrolling internally
|
|
96
|
+
tmpCSS = tmpCSS.replace(
|
|
97
|
+
/\.pict-fe-tabcontent\s*\{[^}]*\}/,
|
|
98
|
+
`.pict-fe-tabcontent
|
|
99
|
+
{
|
|
100
|
+
display: none;
|
|
101
|
+
padding: 16px;
|
|
102
|
+
flex: 1;
|
|
103
|
+
}`
|
|
104
|
+
);
|
|
105
|
+
|
|
106
|
+
// Add sticky properties panel CSS
|
|
107
|
+
tmpCSS += `
|
|
108
|
+
|
|
109
|
+
/* === Flex-height sticky panel overrides === */
|
|
110
|
+
.pict-fe-properties-panel-open
|
|
111
|
+
{
|
|
112
|
+
position: sticky;
|
|
113
|
+
top: 0;
|
|
114
|
+
align-self: flex-start;
|
|
115
|
+
max-height: 100vh;
|
|
116
|
+
overflow-y: auto;
|
|
117
|
+
}
|
|
118
|
+
`;
|
|
119
|
+
|
|
120
|
+
tmpDefaultConfig.CSS = tmpCSS;
|
|
121
|
+
|
|
122
|
+
// Add the FormEditor view with our patched configuration
|
|
123
|
+
this._FormEditorView = this.pict.addView('FormEditor',
|
|
124
|
+
Object.assign({}, tmpDefaultConfig,
|
|
125
|
+
{
|
|
126
|
+
ViewIdentifier: 'FormEditor',
|
|
127
|
+
ManifestDataAddress: 'AppData.FormConfig',
|
|
128
|
+
DefaultDestinationAddress: '#FormEditor-Container',
|
|
129
|
+
ActiveTab: 'visual',
|
|
130
|
+
Renderables:
|
|
131
|
+
[
|
|
132
|
+
{
|
|
133
|
+
RenderableHash: 'FormEditor-Container',
|
|
134
|
+
TemplateHash: 'FormEditor-Container-Template',
|
|
135
|
+
DestinationAddress: '#FormEditor-Container',
|
|
136
|
+
RenderMethod: 'replace'
|
|
137
|
+
}
|
|
138
|
+
]
|
|
139
|
+
}), libPictSectionFormEditor);
|
|
140
|
+
|
|
141
|
+
this._FormEditorView.initialize();
|
|
142
|
+
this._FormEditorView.render();
|
|
143
|
+
|
|
144
|
+
// Wire up the import event
|
|
145
|
+
let tmpSelf = this;
|
|
146
|
+
this._FormEditorView.onImport = function(pManifests, pFileName)
|
|
147
|
+
{
|
|
148
|
+
tmpSelf._handleImportedManifests(pManifests, pFileName);
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
// Render the selector bar
|
|
152
|
+
this.renderSelector();
|
|
153
|
+
|
|
154
|
+
// Load the first file-based sample by default
|
|
155
|
+
let tmpDefaultIndex = 1;
|
|
156
|
+
let tmpSelect = document.getElementById('FormEditor-ManifestSelect');
|
|
157
|
+
if (tmpSelect)
|
|
158
|
+
{
|
|
159
|
+
tmpSelect.value = String(tmpDefaultIndex);
|
|
160
|
+
}
|
|
161
|
+
this.loadManifest(tmpDefaultIndex);
|
|
162
|
+
|
|
163
|
+
return super.onAfterInitializeAsync(fCallback);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
renderSelector()
|
|
167
|
+
{
|
|
168
|
+
let tmpHTML = '';
|
|
169
|
+
tmpHTML += '<div class="pict-fe-selector-bar">';
|
|
170
|
+
tmpHTML += '<label class="pict-fe-selector-label" for="FormEditor-ManifestSelect">Load Configuration:</label>';
|
|
171
|
+
tmpHTML += '<select class="pict-fe-selector-select" id="FormEditor-ManifestSelect">';
|
|
172
|
+
for (let i = 0; i < this._ManifestList.length; i++)
|
|
173
|
+
{
|
|
174
|
+
tmpHTML += `<option value="${i}">${this._escapeHTML(this._ManifestList[i].Name)}</option>`;
|
|
175
|
+
}
|
|
176
|
+
tmpHTML += '</select>';
|
|
177
|
+
tmpHTML += `<button class="pict-fe-selector-btn" onclick="${this.pict.browserAddress}.PictApplication.loadSelectedManifest()">Load</button>`;
|
|
178
|
+
tmpHTML += `<button class="pict-fe-selector-btn" id="FormEditor-DragDropToggle" onclick="${this.pict.browserAddress}.PictApplication.toggleDragAndDrop()" style="margin-left:auto; background:#8A7F72;">Enable Drag & Drop</button>`;
|
|
179
|
+
tmpHTML += `<button class="pict-fe-selector-btn" id="FormEditor-DisplayModeToggle" onclick="${this.pict.browserAddress}.PictApplication.toggleDisplayMode()" style="background:#8A7F72;">Show Hashes</button>`;
|
|
180
|
+
tmpHTML += '</div>';
|
|
181
|
+
|
|
182
|
+
this.pict.ContentAssignment.assignContent('#FormEditor-Selector', tmpHTML);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
toggleDragAndDrop()
|
|
186
|
+
{
|
|
187
|
+
this._DragDropEnabled = !this._DragDropEnabled;
|
|
188
|
+
|
|
189
|
+
if (this._FormEditorView)
|
|
190
|
+
{
|
|
191
|
+
this._FormEditorView._DragDropProvider.setDragAndDropEnabled(this._DragDropEnabled);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
let tmpToggleBtn = document.getElementById('FormEditor-DragDropToggle');
|
|
195
|
+
if (tmpToggleBtn)
|
|
196
|
+
{
|
|
197
|
+
tmpToggleBtn.textContent = this._DragDropEnabled ? 'Disable Drag & Drop' : 'Enable Drag & Drop';
|
|
198
|
+
tmpToggleBtn.style.background = this._DragDropEnabled ? '#E76F51' : '#8A7F72';
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
toggleDisplayMode()
|
|
203
|
+
{
|
|
204
|
+
this._ShowHashes = !this._ShowHashes;
|
|
205
|
+
|
|
206
|
+
if (this._FormEditorView)
|
|
207
|
+
{
|
|
208
|
+
this._FormEditorView._UtilitiesProvider.setInputDisplayMode(this._ShowHashes ? 'hash' : 'name');
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
let tmpToggleBtn = document.getElementById('FormEditor-DisplayModeToggle');
|
|
212
|
+
if (tmpToggleBtn)
|
|
213
|
+
{
|
|
214
|
+
tmpToggleBtn.textContent = this._ShowHashes ? 'Show Names' : 'Show Hashes';
|
|
215
|
+
tmpToggleBtn.style.background = this._ShowHashes ? '#5B6E5D' : '#8A7F72';
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
loadSelectedManifest()
|
|
220
|
+
{
|
|
221
|
+
let tmpSelect = document.getElementById('FormEditor-ManifestSelect');
|
|
222
|
+
if (tmpSelect)
|
|
223
|
+
{
|
|
224
|
+
this.loadManifest(parseInt(tmpSelect.value, 10));
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
loadManifest(pIndex)
|
|
229
|
+
{
|
|
230
|
+
if (pIndex < 0 || pIndex >= this._ManifestList.length)
|
|
231
|
+
{
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
let tmpEntry = this._ManifestList[pIndex];
|
|
236
|
+
|
|
237
|
+
if (tmpEntry.ManifestData)
|
|
238
|
+
{
|
|
239
|
+
this.pict.AppData.FormConfig = tmpEntry.ManifestData;
|
|
240
|
+
this._refreshEditor();
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
if (!tmpEntry.File)
|
|
245
|
+
{
|
|
246
|
+
this.pict.AppData.FormConfig =
|
|
247
|
+
{
|
|
248
|
+
Scope: 'NewForm',
|
|
249
|
+
Sections: [],
|
|
250
|
+
Descriptors: {}
|
|
251
|
+
};
|
|
252
|
+
this._refreshEditor();
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
let tmpXHR = new XMLHttpRequest();
|
|
257
|
+
tmpXHR.open('GET', tmpEntry.File, true);
|
|
258
|
+
tmpXHR.onreadystatechange = () =>
|
|
259
|
+
{
|
|
260
|
+
if (tmpXHR.readyState === 4)
|
|
261
|
+
{
|
|
262
|
+
if (tmpXHR.status === 200)
|
|
263
|
+
{
|
|
264
|
+
try
|
|
265
|
+
{
|
|
266
|
+
this.pict.AppData.FormConfig = JSON.parse(tmpXHR.responseText);
|
|
267
|
+
this._refreshEditor();
|
|
268
|
+
}
|
|
269
|
+
catch (pError)
|
|
270
|
+
{
|
|
271
|
+
this.log.error(`Error parsing manifest JSON from ${tmpEntry.File}: ${pError.message}`);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
else
|
|
275
|
+
{
|
|
276
|
+
this.log.error(`Error loading manifest from ${tmpEntry.File}: HTTP ${tmpXHR.status}`);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
};
|
|
280
|
+
tmpXHR.send();
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
_handleImportedManifests(pManifests, pFileName)
|
|
284
|
+
{
|
|
285
|
+
let tmpManifestKeys = Object.keys(pManifests);
|
|
286
|
+
if (tmpManifestKeys.length <= 1)
|
|
287
|
+
{
|
|
288
|
+
return;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
let tmpSourceLabel = pFileName.toLowerCase().endsWith('.json') ? 'JSON' : 'CSV';
|
|
292
|
+
|
|
293
|
+
for (let i = 1; i < tmpManifestKeys.length; i++)
|
|
294
|
+
{
|
|
295
|
+
let tmpKey = tmpManifestKeys[i];
|
|
296
|
+
let tmpFormName = pManifests[tmpKey].FormName || tmpKey;
|
|
297
|
+
let tmpEntry = { Name: `${tmpSourceLabel}: ${tmpFormName}`, File: false, ManifestData: pManifests[tmpKey] };
|
|
298
|
+
this._ManifestList.push(tmpEntry);
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
this.renderSelector();
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
loadManifestDirect(pManifestData)
|
|
305
|
+
{
|
|
306
|
+
this.pict.AppData.FormConfig = pManifestData;
|
|
307
|
+
this._refreshEditor();
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
_refreshEditor()
|
|
311
|
+
{
|
|
312
|
+
if (this._FormEditorView)
|
|
313
|
+
{
|
|
314
|
+
this._FormEditorView.render();
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
_escapeHTML(pString)
|
|
319
|
+
{
|
|
320
|
+
if (typeof pString !== 'string')
|
|
321
|
+
{
|
|
322
|
+
return '';
|
|
323
|
+
}
|
|
324
|
+
return pString
|
|
325
|
+
.replace(/&/g, '&')
|
|
326
|
+
.replace(/</g, '<')
|
|
327
|
+
.replace(/>/g, '>')
|
|
328
|
+
.replace(/"/g, '"');
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
module.exports = FormEditorFlexExampleApplication;
|
|
333
|
+
|
|
334
|
+
module.exports.default_configuration = (
|
|
335
|
+
{
|
|
336
|
+
Name: 'FormEditorFlexExample',
|
|
337
|
+
Hash: 'FormEditorFlexExample',
|
|
338
|
+
MainViewportViewIdentifier: 'FormEditor',
|
|
339
|
+
AutoSolveAfterInitialize: false,
|
|
340
|
+
AutoRenderMainViewportViewAfterInitialize: false,
|
|
341
|
+
pict_configuration:
|
|
342
|
+
{
|
|
343
|
+
Product: 'FormEditorFlexExample'
|
|
344
|
+
}
|
|
345
|
+
});
|
|
@@ -0,0 +1,65 @@
|
|
|
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>Form Editor - Flex Height Reference</title>
|
|
7
|
+
<!-- PICT Dynamic View CSS Container -->
|
|
8
|
+
<style id="PICT-CSS"></style>
|
|
9
|
+
<!-- Red Rock Mesa Theme — Flex Height Reference App -->
|
|
10
|
+
<style>
|
|
11
|
+
*, *::before, *::after { box-sizing: border-box; }
|
|
12
|
+
html { margin: 0; padding: 0; }
|
|
13
|
+
body { margin: 0; padding: 0; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif; background: #FAEDCD; color: #264653; }
|
|
14
|
+
|
|
15
|
+
/* --- Header Bar (sticky at top of page) --- */
|
|
16
|
+
.pict-example-header { position: sticky; top: 0; z-index: 100; display: flex; align-items: stretch; background: #264653; border-bottom: 3px solid #E76F51; }
|
|
17
|
+
.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; }
|
|
18
|
+
.pict-example-badge svg { width: 14px; height: 14px; fill: #fff; flex-shrink: 0; }
|
|
19
|
+
.pict-example-app-name { padding: 0.6rem 1rem; color: #FAEDCD; font-size: 1.1rem; font-weight: 600; display: flex; align-items: center; }
|
|
20
|
+
.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; }
|
|
21
|
+
|
|
22
|
+
/* --- Content Area — flows naturally, no fixed height --- */
|
|
23
|
+
.pict-example-content { padding: 1.5rem; }
|
|
24
|
+
|
|
25
|
+
/* --- Selector Bar --- */
|
|
26
|
+
.pict-fe-selector-bar { display: flex; align-items: center; gap: 0.75rem; padding: 0.75rem 1rem; background: #fff; border: 1px solid #D4A373; border-radius: 6px; margin-bottom: 1rem; }
|
|
27
|
+
.pict-fe-selector-label { font-size: 0.85rem; font-weight: 600; color: #264653; white-space: nowrap; }
|
|
28
|
+
.pict-fe-selector-select { flex: 1; max-width: 320px; padding: 0.4rem 0.6rem; border: 1px solid #D4C4A8; border-radius: 4px; font-size: 0.9rem; color: #264653; background: #FFFCF7; }
|
|
29
|
+
.pict-fe-selector-select:focus { outline: none; border-color: #E76F51; box-shadow: 0 0 0 2px rgba(231,111,81,0.15); }
|
|
30
|
+
.pict-fe-selector-btn { padding: 0.4rem 1rem; border: none; border-radius: 4px; font-size: 0.85rem; font-weight: 600; color: #fff; background: #E76F51; cursor: pointer; white-space: nowrap; }
|
|
31
|
+
.pict-fe-selector-btn:hover { background: #C45A3E; }
|
|
32
|
+
|
|
33
|
+
/* --- Info Banner --- */
|
|
34
|
+
.pict-example-info { background: #fff; border: 1px solid #D4A373; border-radius: 6px; padding: 1rem 1.25rem; margin-bottom: 1rem; font-size: 0.85rem; line-height: 1.6; color: #3D3229; }
|
|
35
|
+
.pict-example-info h3 { margin: 0 0 0.5rem 0; font-size: 0.95rem; color: #9E6B47; }
|
|
36
|
+
.pict-example-info code { background: #F5F0E8; padding: 0.15em 0.4em; border-radius: 3px; font-size: 0.8rem; }
|
|
37
|
+
</style>
|
|
38
|
+
<script src="./pict.js" type="text/javascript"></script>
|
|
39
|
+
<script src="./codejar.js" type="text/javascript"></script>
|
|
40
|
+
<script type="text/javascript">Pict.safeOnDocumentReady(() => { Pict.safeLoadPictApplication(FormEditorFlexExample, 1)});</script>
|
|
41
|
+
</head>
|
|
42
|
+
<body>
|
|
43
|
+
<div class="pict-example-header">
|
|
44
|
+
<div class="pict-example-badge">
|
|
45
|
+
<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>
|
|
46
|
+
Pict Example
|
|
47
|
+
</div>
|
|
48
|
+
<div class="pict-example-app-name">Form Editor — Flex Height</div>
|
|
49
|
+
<div class="pict-example-module">pict-section-formeditor (sticky panel reference)</div>
|
|
50
|
+
</div>
|
|
51
|
+
<div class="pict-example-content">
|
|
52
|
+
<div class="pict-example-info">
|
|
53
|
+
<h3>Flex-Height Layout with Sticky Properties Panel</h3>
|
|
54
|
+
This reference app demonstrates the form editor embedded in a page that scrolls
|
|
55
|
+
naturally (no fixed viewport height). The properties panel on the right uses
|
|
56
|
+
<code>position: sticky</code> so it stays visible as you scroll through long
|
|
57
|
+
manifests. Load the <strong>Patient Intake</strong> or <strong>Project Proposal</strong>
|
|
58
|
+
manifests for large forms that exercise vertical scrolling.
|
|
59
|
+
</div>
|
|
60
|
+
<div id="FormEditor-Selector"></div>
|
|
61
|
+
<div id="FormEditor-Container"></div>
|
|
62
|
+
</div>
|
|
63
|
+
<script src="./form_editor_flex_example.js" type="text/javascript"></script>
|
|
64
|
+
</body>
|
|
65
|
+
</html>
|