feat(form): friendly empty-state when standalone HTML opened directly
The form renderer is server-driven: zddc-server's form handler injects schema/ui/data into <script id="form-context"> on every render. Standalone form/dist/form.html opened from file:// has no context and just rendered as a blank page below the header chrome — no orientation, no submit button affordance was hidden, but nothing labelled what the user was looking at. Detect the empty-context case in form/js/main.js, render a small .form-welcome card explaining that this tool is server-driven, and hide the now-meaningless Submit button. The card uses shared tokens (--bg, --border, --font-mono, etc.) so it themes correctly. Note: the unified tables.html bundle that hosts the form via the zddcMode dispatcher is unaffected — tables always sets zddcMode='form' or 'table' before form's main.js boots, so the welcome only fires for the standalone HTML. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
81b687a2eb
commit
c58511232f
2 changed files with 65 additions and 0 deletions
|
|
@ -198,3 +198,31 @@
|
||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Standalone welcome — shown when form.html is opened directly (no server-injected #form-context). */
|
||||||
|
.form-welcome {
|
||||||
|
max-width: 36rem;
|
||||||
|
margin: 2rem auto;
|
||||||
|
padding: 1.5rem 1.75rem;
|
||||||
|
background: var(--bg);
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
border-radius: var(--radius);
|
||||||
|
}
|
||||||
|
.form-welcome h2 {
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
font-size: 1.25rem;
|
||||||
|
}
|
||||||
|
.form-welcome h3 {
|
||||||
|
margin: 1rem 0 0.35rem;
|
||||||
|
font-size: 0.95rem;
|
||||||
|
}
|
||||||
|
.form-welcome p { margin-bottom: 0.75rem; line-height: 1.5; }
|
||||||
|
.form-welcome ol { margin: 0 0 0.75rem 1.25rem; }
|
||||||
|
.form-welcome li { margin-bottom: 0.35rem; }
|
||||||
|
.form-welcome code {
|
||||||
|
font-family: var(--font-mono);
|
||||||
|
font-size: 0.85em;
|
||||||
|
background: var(--bg-secondary);
|
||||||
|
padding: 0.05em 0.3em;
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,37 @@
|
||||||
(function (app) {
|
(function (app) {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
// Friendly empty-state shown when the form is opened standalone
|
||||||
|
// (file:// or otherwise without a server-injected #form-context
|
||||||
|
// payload). The form renderer is always driven by the host —
|
||||||
|
// zddc-server's form handler injects schema+ui+data; the tool has
|
||||||
|
// no client-side picker because there's nothing it could pick from
|
||||||
|
// outside that contract.
|
||||||
|
function renderStandaloneWelcome(root) {
|
||||||
|
if (!root) return;
|
||||||
|
root.innerHTML = '';
|
||||||
|
const wrap = document.createElement('div');
|
||||||
|
wrap.className = 'form-welcome';
|
||||||
|
wrap.innerHTML = [
|
||||||
|
'<h2>ZDDC Form Renderer</h2>',
|
||||||
|
'<p>This tool renders a form spec injected by <code>zddc-server</code>',
|
||||||
|
' at <code><name>.form.html</code> URLs. There is no schema',
|
||||||
|
' to render here — most likely you opened the standalone HTML directly.</p>',
|
||||||
|
'<h3>To use it</h3>',
|
||||||
|
'<ol>',
|
||||||
|
'<li>Run <code>zddc-server</code> against an archive that contains a',
|
||||||
|
' <code><name>.form.yaml</code> spec.</li>',
|
||||||
|
'<li>Visit <code><path>/<name>.form.html</code> in the browser.</li>',
|
||||||
|
'</ol>',
|
||||||
|
'<p>See <a href="https://zddc.varasys.io/reference.html" target="_blank" rel="noopener">',
|
||||||
|
'zddc.varasys.io/reference.html</a> for the full ZDDC reference.</p>'
|
||||||
|
].join('');
|
||||||
|
root.appendChild(wrap);
|
||||||
|
|
||||||
|
const submitBtn = document.getElementById('submit-btn');
|
||||||
|
if (submitBtn) submitBtn.hidden = true;
|
||||||
|
}
|
||||||
|
|
||||||
function boot() {
|
function boot() {
|
||||||
// When this bundle is hosted by the unified tables.html, the
|
// When this bundle is hosted by the unified tables.html, the
|
||||||
// mode dispatcher decides which app paints. Skip when mode is
|
// mode dispatcher decides which app paints. Skip when mode is
|
||||||
|
|
@ -32,6 +63,12 @@
|
||||||
app.context.ui || {},
|
app.context.ui || {},
|
||||||
app.context.data
|
app.context.data
|
||||||
);
|
);
|
||||||
|
} else if (root) {
|
||||||
|
// No schema — server-injected context is empty. Most common
|
||||||
|
// when the standalone form.html is opened from file:// without
|
||||||
|
// a host. Show a friendly explanation instead of a blank page.
|
||||||
|
renderStandaloneWelcome(root);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (app.context.errors && app.context.errors.length) {
|
if (app.context.errors && app.context.errors.length) {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue