@xeplr/ui-factory 1.0.9 → 1.0.11
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/README.md +5 -0
- package/package.json +1 -1
- package/src/designs/ScreenSample.jsx +18 -9
- package/src/designs/factory.css +18 -2
package/README.md
CHANGED
|
@@ -196,6 +196,11 @@ const clean = schemaHandler.applySchema(formSchema(screen), req.body) // throw
|
|
|
196
196
|
| `label` | — | text with a heading, subheading or text preset |
|
|
197
197
|
| `list` | — | saved records, with New / Edit / Delete |
|
|
198
198
|
|
|
199
|
+
A screen is a **sheet**: it paints its own surface, so a screen designed in
|
|
200
|
+
dark ink stays readable inside a dark app. Give the screen a `background` in
|
|
201
|
+
its own style to change it, or set `--xeplr-factory-paper` on the host for all
|
|
202
|
+
of them.
|
|
203
|
+
|
|
199
204
|
Every control also takes `style` — see [AUTHORING.md](./AUTHORING.md#styles) for the keys. Sizes are pixels at the screen's design `width` (default 800): a screen is shown at that size, never stretched, and scaled down only on a narrower display.
|
|
200
205
|
|
|
201
206
|
### Steps
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xeplr/ui-factory",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.11",
|
|
4
4
|
"description": "Design data-entry screens on @xeplr/ui-canvas, save them as JSON, run them as auto-saving forms with lists of saved records — built for Claude to draft and people to refine",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.js",
|
|
@@ -27,7 +27,7 @@ const STATUS = {
|
|
|
27
27
|
* filled in — and shows why, rather than moving on and leaving a problem
|
|
28
28
|
* behind on a step nobody is looking at.
|
|
29
29
|
*/
|
|
30
|
-
function StepNav({ ctrl, node }) {
|
|
30
|
+
function StepNav({ ctrl, node, children }) {
|
|
31
31
|
const at = ctrl.steps.active(node.id)
|
|
32
32
|
const last = ctrl.steps.count(node.id) - 1
|
|
33
33
|
const unfinished = ctrl.steps.fieldsOn(node.id, at).filter((n) => ctrl.allErrors[n.props.name])
|
|
@@ -40,10 +40,21 @@ function StepNav({ ctrl, node }) {
|
|
|
40
40
|
<button type="button" className="xeplr-factory-secondary" onClick={() => go(at - 1, 'back')} disabled={at === 0}>Back</button>
|
|
41
41
|
<span className="xeplr-factory-stepnav-where">Step {at + 1} of {last + 1}</span>
|
|
42
42
|
<button type="button" className="xeplr-factory-primary" onClick={() => go(at + 1, 'next')} disabled={at === last}>Next</button>
|
|
43
|
+
{children}
|
|
43
44
|
</div>
|
|
44
45
|
)
|
|
45
46
|
}
|
|
46
47
|
|
|
48
|
+
/** Leaves the page — after whatever is still being saved has gone out. */
|
|
49
|
+
function DoneButton({ ctrl }) {
|
|
50
|
+
const saving = ctrl.status === 'pending' || ctrl.status === 'saving'
|
|
51
|
+
return (
|
|
52
|
+
<button type="button" className="xeplr-factory-secondary" onClick={() => ctrl.flush().then(ctrl.done, ctrl.done)}>
|
|
53
|
+
{saving ? 'Saving…' : 'Done'}
|
|
54
|
+
</button>
|
|
55
|
+
)
|
|
56
|
+
}
|
|
57
|
+
|
|
47
58
|
export default function ScreenSample({ ctrl, className, style, renderPopup }) {
|
|
48
59
|
const { document: doc } = ctrl
|
|
49
60
|
|
|
@@ -128,15 +139,13 @@ export default function ScreenSample({ ctrl, className, style, renderPopup }) {
|
|
|
128
139
|
</div>
|
|
129
140
|
))}
|
|
130
141
|
</form>
|
|
131
|
-
{ctrl.steps.nodes.map((node) => (
|
|
132
|
-
<StepNav key={node.id} ctrl={ctrl} node={node}
|
|
142
|
+
{ctrl.steps.nodes.map((node, i) => (
|
|
143
|
+
<StepNav key={node.id} ctrl={ctrl} node={node}>
|
|
144
|
+
{ctrl.done && i === ctrl.steps.nodes.length - 1 && <DoneButton ctrl={ctrl} />}
|
|
145
|
+
</StepNav>
|
|
133
146
|
))}
|
|
134
|
-
{ctrl.done && (
|
|
135
|
-
<div className="xeplr-factory-done">
|
|
136
|
-
<button type="button" className="xeplr-factory-primary" onClick={() => ctrl.flush().then(ctrl.done, ctrl.done)}>
|
|
137
|
-
{ctrl.status === 'pending' || ctrl.status === 'saving' ? 'Saving…' : 'Done'}
|
|
138
|
-
</button>
|
|
139
|
-
</div>
|
|
147
|
+
{ctrl.done && !ctrl.steps.nodes.length && (
|
|
148
|
+
<div className="xeplr-factory-done"><DoneButton ctrl={ctrl} /></div>
|
|
140
149
|
)}
|
|
141
150
|
{ctrl.popup && renderPopup && renderPopup(ctrl.popup, ctrl)}
|
|
142
151
|
</div>
|
package/src/designs/factory.css
CHANGED
|
@@ -19,8 +19,23 @@
|
|
|
19
19
|
--xf-danger: var(--xeplr-danger, #c2372e);
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
/* ── the screen ───────────────────────────────────────────────────────────
|
|
23
|
-
|
|
22
|
+
/* ── the screen ───────────────────────────────────────────────────────────
|
|
23
|
+
A screen is a SHEET: it paints its own surface, the way the builder's canvas
|
|
24
|
+
does. Without that it is transparent, and a screen designed in dark ink
|
|
25
|
+
disappears into a dark app — what you designed is not what you get. The
|
|
26
|
+
screen's own `background` style overrides this (screenStyle), as does the
|
|
27
|
+
host with --xeplr-factory-paper. */
|
|
28
|
+
.xeplr-factory-screen {
|
|
29
|
+
position: relative; width: 100%;
|
|
30
|
+
color: var(--xf-ink);
|
|
31
|
+
background: var(--xeplr-factory-paper, var(--xf-surface));
|
|
32
|
+
border-radius: calc(8 * var(--xf-u));
|
|
33
|
+
}
|
|
34
|
+
/* The status line and the step buttons live on the sheet, so they keep a
|
|
35
|
+
margin of their own rather than touching its edge. */
|
|
36
|
+
.xeplr-factory-screen > .xeplr-factory-status,
|
|
37
|
+
.xeplr-factory-screen > .xeplr-factory-stepnav,
|
|
38
|
+
.xeplr-factory-screen > .xeplr-factory-done { padding-inline: calc(12 * var(--xf-u)); }
|
|
24
39
|
.xeplr-factory-status {
|
|
25
40
|
display: flex; justify-content: space-between; gap: 12px; min-height: 18px;
|
|
26
41
|
padding: 4px 2px 8px; font-size: 12px; color: var(--xf-muted);
|
|
@@ -118,6 +133,7 @@
|
|
|
118
133
|
/* Back / Next, under the page. */
|
|
119
134
|
.xeplr-factory-stepnav { display: flex; align-items: center; gap: 12px; padding: 10px 0; }
|
|
120
135
|
.xeplr-factory-stepnav-where { flex: 1; text-align: center; color: var(--xf-muted); font-size: 12px; }
|
|
136
|
+
.xeplr-factory-stepnav button[disabled], .xeplr-factory-done button[disabled] { opacity: 0.45; cursor: default; }
|
|
121
137
|
|
|
122
138
|
/* Done — a page's way back, when the list opens records on one. */
|
|
123
139
|
.xeplr-factory-done { display: flex; justify-content: flex-end; padding: 10px 0; }
|