pict-section-form 1.1.0 → 1.1.2
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/docs/_cover.md +3 -0
- package/docs/_sidebar.md +5 -0
- package/docs/_version.json +3 -3
- package/docs/examples/README.md +3 -0
- package/docs/examples/change_tracking/change_tracking.js +9437 -9427
- package/docs/examples/diagram_form/README.md +116 -0
- package/docs/examples/diagram_form/diagram_form_example.min.js +42 -0
- package/docs/examples/diagram_form/excalidraw-iframe-host.html +25 -0
- package/docs/examples/diagram_form/excalidraw-wrapper.css +1 -0
- package/docs/examples/diagram_form/excalidraw-wrapper.min.js +3327 -0
- package/docs/examples/diagram_form/index.html +116 -0
- package/docs/examples/diagram_form/manifest.json +13 -0
- package/docs/examples/diagram_form/react-vendor.min.js +9 -0
- package/docs/examples/dynamic_analysis/dynamic_analysis_application.js +6549 -6550
- package/docs/examples/gradebook/gradebook_application.min.js +2 -2
- package/docs/examples/ndt_field_test/ndt_field_test.js +9437 -9427
- package/docs/examples/richtext_form/README.md +132 -0
- package/docs/examples/richtext_form/index.html +82 -0
- package/docs/examples/richtext_form/richtext_form_example.min.js +42 -0
- package/docs/examples/scope_mathematics/scope_mathematics.js +9437 -9427
- package/docs/examples/simple_table/simple_tabular_application.min.js +2 -2
- package/docs/examples/superhero_studio/README.md +199 -0
- package/docs/examples/superhero_studio/excalidraw-iframe-host.html +25 -0
- package/docs/examples/superhero_studio/excalidraw-wrapper.css +1 -0
- package/docs/examples/superhero_studio/excalidraw-wrapper.min.js +3327 -0
- package/docs/examples/superhero_studio/index.html +166 -0
- package/docs/examples/superhero_studio/manifest.json +13 -0
- package/docs/examples/superhero_studio/react-vendor.min.js +9 -0
- package/docs/examples/superhero_studio/superhero_studio_example.min.js +42 -0
- package/docs/index.html +2 -2
- package/docs/retold-catalog.json +45 -1
- package/docs/retold-keyword-index.json +11843 -7677
- package/example_applications/diagram_form/DiagramForm-Example-Application.js +145 -0
- package/example_applications/diagram_form/html/index.html +116 -0
- package/example_applications/diagram_form/package.json +29 -0
- package/example_applications/richtext_form/RichTextForm-Example-Application.js +176 -0
- package/example_applications/richtext_form/html/index.html +82 -0
- package/example_applications/richtext_form/package.json +28 -0
- package/example_applications/superhero_studio/SuperheroStudio-Example-Application.js +313 -0
- package/example_applications/superhero_studio/html/index.html +166 -0
- package/example_applications/superhero_studio/package.json +29 -0
- package/example_applications/superhero_studio/superheroes/Superheroes.js +386 -0
- package/package.json +3 -9
- package/source/providers/inputs/Pict-Provider-Input-Diagram.js +1 -31
- package/source/providers/inputs/Pict-Provider-Input-RichText.js +1 -32
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
# RichText Form Input
|
|
2
|
+
|
|
3
|
+
<!-- docuserve:example-launch:start -->
|
|
4
|
+
> **[Launch the live app](examples/richtext%5Fform/index.html)** - runs in your browser, opens in a new tab.
|
|
5
|
+
<!-- docuserve:example-launch:end -->
|
|
6
|
+
|
|
7
|
+
**RichText Form Input** is the smallest demonstration of the new
|
|
8
|
+
`RichText` InputType: a pict-section-form with one field whose provider
|
|
9
|
+
pairs this module's markdown editor (edit mode) with rendered markdown
|
|
10
|
+
(view mode). Boots in view mode — no CodeMirror loaded until the first
|
|
11
|
+
toggle. Demonstrates the pluggable image-uploader hook in two flavors.
|
|
12
|
+
|
|
13
|
+
The `RichText` InputType + its provider class live in **pict-section-form**
|
|
14
|
+
(see [the Input Type doc](https://fable-retold.github.io/pict-section-form/#/page/input%5Fproviders/014-rich-text)).
|
|
15
|
+
The provider lazy-requires this module on the first edit toggle — that's why
|
|
16
|
+
the heavy CodeMirror bundle isn't fetched at boot.
|
|
17
|
+
|
|
18
|
+
For the same InputType inside a richer character-sheet form alongside
|
|
19
|
+
stock inputs and a Diagram, see
|
|
20
|
+
[Superhero Studio](../superhero%5Fstudio/README.md)
|
|
21
|
+
in the pict-section-excalidraw sister module.
|
|
22
|
+
|
|
23
|
+
## What it demonstrates
|
|
24
|
+
|
|
25
|
+
| Capability | Where you see it |
|
|
26
|
+
|------------|------------------|
|
|
27
|
+
| `Pict-Input-RichText` provider registration | One `pict.addProvider(...)` call wires the InputType into the form |
|
|
28
|
+
| Per-field runtime mode toggle | `provider.toggleMode('Body', cb)` flips view ↔ edit; the editor bundle lazy-loads on the first edit |
|
|
29
|
+
| View-mode rendered markdown | `pict-section-content` renders headings, lists, code blocks, blockquotes into the slot — no editor present |
|
|
30
|
+
| `AllowImages: false` rejection | The checkbox toggles this off live; pasting an image surfaces a rejection rather than inserting a half-baked data URI |
|
|
31
|
+
| Pluggable `ImageUploader` | Pasting with the uploader on calls `pict.PictApplication.uploadImage(file, descriptor, cb)`; turning it off falls through to default base64 inline |
|
|
32
|
+
|
|
33
|
+
## Key files
|
|
34
|
+
|
|
35
|
+
- `RichTextForm-Example-Application.js` — the app. Registers the RichText input provider, defines a one-field form manifest, stubs `uploadImage`, and exposes the mode-toggle + AllowImages-toggle controls.
|
|
36
|
+
- `html/index.html` — page chrome: the Edit/Done toggle, two checkboxes (`AllowImages` and `Use ImageUploader stub`), and the form container.
|
|
37
|
+
|
|
38
|
+
## The form descriptor
|
|
39
|
+
|
|
40
|
+
```javascript
|
|
41
|
+
'Body': {
|
|
42
|
+
Name: 'Body',
|
|
43
|
+
Hash: 'Body',
|
|
44
|
+
DataType: 'String',
|
|
45
|
+
PictForm:
|
|
46
|
+
{
|
|
47
|
+
Section: 'Article',
|
|
48
|
+
Row: 1,
|
|
49
|
+
Width: 12,
|
|
50
|
+
InputType: 'RichText',
|
|
51
|
+
RichText:
|
|
52
|
+
{
|
|
53
|
+
AllowImages: true,
|
|
54
|
+
ImageUploader: 'uploadImage', // method name on pict.PictApplication
|
|
55
|
+
Height: '320px'
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
The provider auto-injects its templates into pict-section-form's `DynamicTemplates` registry on construction, so the form's render path finds `*-Template-Input-InputType-RichText` and emits the standard hidden input + display slot.
|
|
62
|
+
|
|
63
|
+
## Feature 1 — View-by-default with lazy editor mount
|
|
64
|
+
|
|
65
|
+
On page load, the field's value is parsed as markdown and written into the slot — that's it. Inspect the DevTools Network tab: no `vendor`-side or `codemirror`-side requests fire.
|
|
66
|
+
|
|
67
|
+
The first time the user clicks Edit, `provider.setMode('Body', 'edit', cb)` runs:
|
|
68
|
+
|
|
69
|
+
1. Tear down view-mode DOM (clear the slot).
|
|
70
|
+
2. Instantiate a subclass of `Pict-Section-MarkdownEditor` with `TargetElementAddress` pointing at the slot.
|
|
71
|
+
3. Seed it with the value the provider was last holding for this hash.
|
|
72
|
+
4. Wire `onContentChange(segmentIndex, content)` so every keystroke writes through to the form's hidden `<input>` (and dispatches a `change` event so Informary updates AppData).
|
|
73
|
+
|
|
74
|
+
Clicking Done calls `setMode('Body', 'view', cb)`: the editor is destroyed, the slot is re-rendered from the latest value. The hidden input keeps the user's content across the toggle.
|
|
75
|
+
|
|
76
|
+
## Feature 2 — `AllowImages: false` rejection
|
|
77
|
+
|
|
78
|
+
The provider subclass overrides `onImageUpload(file, segmentIndex, cb)`:
|
|
79
|
+
|
|
80
|
+
```javascript
|
|
81
|
+
onImageUpload(pFile, pSegmentIndex, fImgCallback)
|
|
82
|
+
{
|
|
83
|
+
if (!tmpRichTextOpts.AllowImages)
|
|
84
|
+
{
|
|
85
|
+
fImgCallback('Image uploads are disabled for this field.');
|
|
86
|
+
return true; // claim the upload so the editor doesn't fall through
|
|
87
|
+
}
|
|
88
|
+
// ... uploader dispatch below
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Returning `true` and calling `fCallback(errMessage)` tells the editor "I handled this — and I refused it." No half-baked data URI ends up in the markdown. Toggle the page checkbox to see the live difference.
|
|
93
|
+
|
|
94
|
+
## Feature 3 — Pluggable `ImageUploader`
|
|
95
|
+
|
|
96
|
+
When `AllowImages: true` AND `ImageUploader` is set, the provider dispatches the file to `pict.PictApplication[name](pFile, pInputDescriptor, fCallback)`:
|
|
97
|
+
|
|
98
|
+
```javascript
|
|
99
|
+
uploadImage(pFile, pInputDescriptor, fCallback)
|
|
100
|
+
{
|
|
101
|
+
setTimeout(() =>
|
|
102
|
+
{
|
|
103
|
+
let tmpFakeURL = '/uploads/' + Date.now() + '-' + pFile.name.replace(/[^A-Za-z0-9._-]/g, '_');
|
|
104
|
+
fCallback(null, tmpFakeURL);
|
|
105
|
+
}, 600);
|
|
106
|
+
return true;
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
The 600 ms `setTimeout` mimics a real upload round-trip. A production app would POST the file to its storage endpoint and call back with the permanent URL. With the page checkbox set to "off", the stub returns `false`, which tells the underlying editor "fall through to default" — and the default is `FileReader` → base64 data URI inline. Toggle and confirm.
|
|
111
|
+
|
|
112
|
+
## Running the example
|
|
113
|
+
|
|
114
|
+
```sh
|
|
115
|
+
cd modules/pict/pict-section-form/example_applications/richtext_form
|
|
116
|
+
npm install
|
|
117
|
+
npx quack build && npx quack copy
|
|
118
|
+
open dist/index.html
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## Takeaways
|
|
122
|
+
|
|
123
|
+
1. **The provider is the only registration step.** Once it's added to the Pict instance, every form on the instance can use `InputType: 'RichText'`.
|
|
124
|
+
2. **Image handling is the host's contract.** Three knobs cover the realistic cases: forbid (`AllowImages: false`), accept and embed (`AllowImages: true`, no uploader), accept and store remotely (`AllowImages: true`, `ImageUploader: '<name>'`).
|
|
125
|
+
3. **View-mode performance is free.** A form full of read-only RichText fields never touches CodeMirror until the user starts editing.
|
|
126
|
+
|
|
127
|
+
## Related documentation
|
|
128
|
+
|
|
129
|
+
- [pict-section-markdowneditor API Reference ↗](https://fable-retold.github.io/pict-section-markdowneditor/#/page/api) — the markdown editor's public surface, on which the input provider depends.
|
|
130
|
+
- [pict-section-markdowneditor / Image Upload ↗](https://fable-retold.github.io/pict-section-markdowneditor/#/page/image%5Fupload) — the full `onImageUpload` contract (this is what `ImageUploader` proxies through).
|
|
131
|
+
- [Server Upload ↗](https://fable-retold.github.io/pict-section-markdowneditor/#/page/examples/server%5Fupload/README) — the editor's `onImageUpload` hook wired to a real Orator backend; useful when you want to build a real `ImageUploader` for the form provider.
|
|
132
|
+
- [Superhero Studio](../superhero%5Fstudio/README.md) — the RichText InputType inside a fuller form, alongside a Diagram InputType.
|
|
@@ -0,0 +1,82 @@
|
|
|
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>RichText Form Input — Pict Example</title>
|
|
7
|
+
|
|
8
|
+
<style id="PICT-CSS"></style>
|
|
9
|
+
<style>
|
|
10
|
+
*, *::before, *::after { box-sizing: border-box; }
|
|
11
|
+
body { margin: 0; padding: 0; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif; background: #FAF8F4; color: #2A2520; }
|
|
12
|
+
|
|
13
|
+
.pict-example-header { display: flex; align-items: stretch; background: #264653; border-bottom: 3px solid #E76F51; }
|
|
14
|
+
.pict-example-badge { background: #E76F51; color: #FAEDCD; padding: 0.6rem 1rem; font-size: 0.72rem; font-weight: 800; text-transform: uppercase; letter-spacing: 0.1em; }
|
|
15
|
+
.pict-example-app-name { padding: 0.6rem 1rem; color: #FAEDCD; font-size: 1.1rem; font-weight: 600; }
|
|
16
|
+
.pict-example-module { margin-left: auto; padding: 0.6rem 1rem; color: #D4A373; font-size: 0.75rem; letter-spacing: 0.03em; align-self: center; }
|
|
17
|
+
|
|
18
|
+
.page-content { padding: 2rem; max-width: 920px; margin: 0 auto; }
|
|
19
|
+
.intro { color: #5A4A3C; font-size: 0.9rem; line-height: 1.6; margin-bottom: 24px; }
|
|
20
|
+
.intro code { background: #F0E8DA; padding: 1px 6px; border-radius: 3px; font-family: 'SFMono-Regular', Menlo, monospace; font-size: 0.85em; }
|
|
21
|
+
|
|
22
|
+
.controls { background: #FFFFFF; border: 1px solid #D4C4A8; border-radius: 6px; padding: 14px 16px; margin-bottom: 20px; display: flex; flex-wrap: wrap; gap: 16px; align-items: center; font-size: 0.85rem; }
|
|
23
|
+
.controls label { display: flex; align-items: center; gap: 6px; cursor: pointer; }
|
|
24
|
+
.controls button { padding: 6px 14px; font-size: 0.85rem; font-weight: 600; color: #FAEDCD; background: #264653; border: none; border-radius: 4px; cursor: pointer; }
|
|
25
|
+
.controls button:hover { background: #E76F51; }
|
|
26
|
+
|
|
27
|
+
#Pict-Form-Container { background: #FFFFFF; border: 1px solid #D4C4A8; border-radius: 6px; padding: 20px; }
|
|
28
|
+
|
|
29
|
+
/* The form has one section + one input. */
|
|
30
|
+
.notes { margin-top: 24px; padding: 14px 16px; background: #FFF8E7; border-left: 3px solid #E9C46A; border-radius: 3px; font-size: 0.82rem; color: #5A4A3C; }
|
|
31
|
+
.notes strong { color: #2A2520; }
|
|
32
|
+
</style>
|
|
33
|
+
</head>
|
|
34
|
+
<body>
|
|
35
|
+
<header class="pict-example-header">
|
|
36
|
+
<span class="pict-example-badge">Pict Example</span>
|
|
37
|
+
<span class="pict-example-app-name">RichText Form Input</span>
|
|
38
|
+
<span class="pict-example-module">pict-section-markdowneditor</span>
|
|
39
|
+
</header>
|
|
40
|
+
|
|
41
|
+
<main class="page-content">
|
|
42
|
+
<p class="intro">
|
|
43
|
+
A pict-section-form field whose <code>InputType</code> is <code>RichText</code>. Boots in
|
|
44
|
+
<strong>view</strong> mode — just rendered markdown, no CodeMirror loaded. Click <em>Edit</em>
|
|
45
|
+
to flip into the editor (lazy-loads the markdown editor bundle on first toggle).
|
|
46
|
+
</p>
|
|
47
|
+
|
|
48
|
+
<div class="controls">
|
|
49
|
+
<button id="toggle-Body" onclick="_Pict.PictApplication.demo_toggleMode('Body')">Edit</button>
|
|
50
|
+
|
|
51
|
+
<label>
|
|
52
|
+
<input type="checkbox" id="allow-images" checked onchange="_Pict.PictApplication.demo_setAllowImages('Body', this.checked)">
|
|
53
|
+
Allow image paste
|
|
54
|
+
</label>
|
|
55
|
+
|
|
56
|
+
<label>
|
|
57
|
+
<input type="checkbox" id="use-uploader" checked onchange="_Pict.PictApplication.demo_setUploaderEnabled(this.checked)">
|
|
58
|
+
Use ImageUploader stub
|
|
59
|
+
<span style="color:#8A7F72; margin-left:6px; font-size:0.75rem;">(off = base64 inline)</span>
|
|
60
|
+
</label>
|
|
61
|
+
</div>
|
|
62
|
+
|
|
63
|
+
<div id="Pict-Form-Container"></div>
|
|
64
|
+
|
|
65
|
+
<div class="notes">
|
|
66
|
+
<strong>Verifying:</strong>
|
|
67
|
+
Open DevTools → Network. With <em>Edit</em> never clicked, no CodeMirror request fires. Click <em>Edit</em>
|
|
68
|
+
once and the markdown-editor bundle loads. Click <em>Done</em> to return to view mode — the editor view
|
|
69
|
+
is torn down, but its content lives in the field's hidden form input.
|
|
70
|
+
</div>
|
|
71
|
+
</main>
|
|
72
|
+
|
|
73
|
+
<script src="https://cdn.jsdelivr.net/npm/pict@1/dist/pict.min.js"></script>
|
|
74
|
+
<script src="./richtext_form_example.min.js"></script>
|
|
75
|
+
<script>
|
|
76
|
+
Pict.safeOnDocumentReady(() =>
|
|
77
|
+
{
|
|
78
|
+
Pict.safeLoadPictApplication(window.RichtextFormExample || window.RichTextFormExample, 1);
|
|
79
|
+
});
|
|
80
|
+
</script>
|
|
81
|
+
</body>
|
|
82
|
+
</html>
|