@xeplr/ui-factory 1.0.10 → 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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xeplr/ui-factory",
3
- "version": "1.0.10",
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>
@@ -133,6 +133,7 @@
133
133
  /* Back / Next, under the page. */
134
134
  .xeplr-factory-stepnav { display: flex; align-items: center; gap: 12px; padding: 10px 0; }
135
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; }
136
137
 
137
138
  /* Done — a page's way back, when the list opens records on one. */
138
139
  .xeplr-factory-done { display: flex; justify-content: flex-end; padding: 10px 0; }