@fieldia/core 0.30.1 → 0.31.1

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.
Files changed (563) hide show
  1. package/README.md +373 -1
  2. package/package.json +1 -1
  3. package/schema/page.schema.json +758 -1
  4. package/src/index.d.mts +13 -2
  5. package/src/index.d.ts +13 -2
  6. package/src/index.js +45 -2
  7. package/src/index.js.map +1 -1
  8. package/src/index.mjs +18 -2
  9. package/src/index.mjs.map +1 -1
  10. package/src/lib/format/actions.d.mts +16 -16
  11. package/src/lib/format/actions.d.ts +16 -16
  12. package/src/lib/format/actions.js +3 -0
  13. package/src/lib/format/actions.js.map +1 -1
  14. package/src/lib/format/actions.mjs +3 -0
  15. package/src/lib/format/actions.mjs.map +1 -1
  16. package/src/lib/format/address-search.js +3 -0
  17. package/src/lib/format/address-search.js.map +1 -1
  18. package/src/lib/format/address-search.mjs +3 -0
  19. package/src/lib/format/address-search.mjs.map +1 -1
  20. package/src/lib/format/duplicates.js +3 -0
  21. package/src/lib/format/duplicates.js.map +1 -1
  22. package/src/lib/format/duplicates.mjs +3 -0
  23. package/src/lib/format/duplicates.mjs.map +1 -1
  24. package/src/lib/format/endings.js +3 -0
  25. package/src/lib/format/endings.js.map +1 -1
  26. package/src/lib/format/endings.mjs +3 -0
  27. package/src/lib/format/endings.mjs.map +1 -1
  28. package/src/lib/format/field.d.mts +669 -0
  29. package/src/lib/format/field.d.ts +669 -0
  30. package/src/lib/format/field.js +42 -4
  31. package/src/lib/format/field.js.map +1 -1
  32. package/src/lib/format/field.mjs +42 -4
  33. package/src/lib/format/field.mjs.map +1 -1
  34. package/src/lib/format/flow-checks.d.mts +14 -0
  35. package/src/lib/format/flow-checks.d.ts +14 -0
  36. package/src/lib/format/flow-checks.js +61 -0
  37. package/src/lib/format/flow-checks.js.map +1 -0
  38. package/src/lib/format/flow-checks.mjs +58 -0
  39. package/src/lib/format/flow-checks.mjs.map +1 -0
  40. package/src/lib/format/flow.d.mts +43 -0
  41. package/src/lib/format/flow.d.ts +43 -0
  42. package/src/lib/format/flow.js +22 -0
  43. package/src/lib/format/flow.js.map +1 -0
  44. package/src/lib/format/flow.mjs +19 -0
  45. package/src/lib/format/flow.mjs.map +1 -0
  46. package/src/lib/format/from-schema.d.mts +70 -0
  47. package/src/lib/format/from-schema.d.ts +70 -0
  48. package/src/lib/format/from-schema.js +599 -0
  49. package/src/lib/format/from-schema.js.map +1 -0
  50. package/src/lib/format/from-schema.mjs +591 -0
  51. package/src/lib/format/from-schema.mjs.map +1 -0
  52. package/src/lib/format/jitless.d.mts +1 -0
  53. package/src/lib/format/jitless.d.ts +1 -0
  54. package/src/lib/format/jitless.js +27 -0
  55. package/src/lib/format/jitless.js.map +1 -0
  56. package/src/lib/format/jitless.mjs +24 -0
  57. package/src/lib/format/jitless.mjs.map +1 -0
  58. package/src/lib/format/json-schema.js +3 -0
  59. package/src/lib/format/json-schema.js.map +1 -1
  60. package/src/lib/format/json-schema.mjs +3 -0
  61. package/src/lib/format/json-schema.mjs.map +1 -1
  62. package/src/lib/format/json.js +3 -0
  63. package/src/lib/format/json.js.map +1 -1
  64. package/src/lib/format/json.mjs +3 -0
  65. package/src/lib/format/json.mjs.map +1 -1
  66. package/src/lib/format/languages-checks.d.mts +2 -1
  67. package/src/lib/format/languages-checks.d.ts +2 -1
  68. package/src/lib/format/languages-checks.js +8 -2
  69. package/src/lib/format/languages-checks.js.map +1 -1
  70. package/src/lib/format/languages-checks.mjs +8 -2
  71. package/src/lib/format/languages-checks.mjs.map +1 -1
  72. package/src/lib/format/later-checks.d.mts +3 -1
  73. package/src/lib/format/later-checks.d.ts +3 -1
  74. package/src/lib/format/later-checks.js +3 -1
  75. package/src/lib/format/later-checks.js.map +1 -1
  76. package/src/lib/format/later-checks.mjs +3 -1
  77. package/src/lib/format/later-checks.mjs.map +1 -1
  78. package/src/lib/format/layout.d.mts +13192 -7550
  79. package/src/lib/format/layout.d.ts +13192 -7550
  80. package/src/lib/format/layout.js +61 -3
  81. package/src/lib/format/layout.js.map +1 -1
  82. package/src/lib/format/layout.mjs +59 -1
  83. package/src/lib/format/layout.mjs.map +1 -1
  84. package/src/lib/format/layout.types.d.mts +3 -1
  85. package/src/lib/format/layout.types.d.ts +3 -1
  86. package/src/lib/format/limits.js +3 -0
  87. package/src/lib/format/limits.js.map +1 -1
  88. package/src/lib/format/limits.mjs +3 -0
  89. package/src/lib/format/limits.mjs.map +1 -1
  90. package/src/lib/format/list-checks.d.mts +1 -1
  91. package/src/lib/format/list-checks.d.ts +1 -1
  92. package/src/lib/format/list-checks.js +67 -22
  93. package/src/lib/format/list-checks.js.map +1 -1
  94. package/src/lib/format/list-checks.mjs +67 -22
  95. package/src/lib/format/list-checks.mjs.map +1 -1
  96. package/src/lib/format/list-rows-checks.d.mts +11 -0
  97. package/src/lib/format/list-rows-checks.d.ts +11 -0
  98. package/src/lib/format/list-rows-checks.js +62 -0
  99. package/src/lib/format/list-rows-checks.js.map +1 -0
  100. package/src/lib/format/list-rows-checks.mjs +59 -0
  101. package/src/lib/format/list-rows-checks.mjs.map +1 -0
  102. package/src/lib/format/media-options.d.mts +84 -0
  103. package/src/lib/format/media-options.d.ts +84 -0
  104. package/src/lib/format/media-options.js +86 -0
  105. package/src/lib/format/media-options.js.map +1 -0
  106. package/src/lib/format/media-options.mjs +80 -0
  107. package/src/lib/format/media-options.mjs.map +1 -0
  108. package/src/lib/format/outbox-checks.d.mts +11 -0
  109. package/src/lib/format/outbox-checks.d.ts +11 -0
  110. package/src/lib/format/outbox-checks.js +12 -0
  111. package/src/lib/format/outbox-checks.js.map +1 -0
  112. package/src/lib/format/outbox-checks.mjs +9 -0
  113. package/src/lib/format/outbox-checks.mjs.map +1 -0
  114. package/src/lib/format/page.d.mts +3057 -966
  115. package/src/lib/format/page.d.ts +3057 -966
  116. package/src/lib/format/page.js +15 -0
  117. package/src/lib/format/page.js.map +1 -1
  118. package/src/lib/format/page.mjs +15 -0
  119. package/src/lib/format/page.mjs.map +1 -1
  120. package/src/lib/format/part-checks.d.mts +3 -0
  121. package/src/lib/format/part-checks.d.ts +3 -0
  122. package/src/lib/format/payment-checks.d.mts +13 -0
  123. package/src/lib/format/payment-checks.d.ts +13 -0
  124. package/src/lib/format/payment-checks.js +30 -0
  125. package/src/lib/format/payment-checks.js.map +1 -0
  126. package/src/lib/format/payment-checks.mjs +27 -0
  127. package/src/lib/format/payment-checks.mjs.map +1 -0
  128. package/src/lib/format/payment.d.mts +37 -0
  129. package/src/lib/format/payment.d.ts +37 -0
  130. package/src/lib/format/payment.js +15 -0
  131. package/src/lib/format/payment.js.map +1 -0
  132. package/src/lib/format/payment.mjs +12 -0
  133. package/src/lib/format/payment.mjs.map +1 -0
  134. package/src/lib/format/phone.js +3 -0
  135. package/src/lib/format/phone.js.map +1 -1
  136. package/src/lib/format/phone.mjs +3 -0
  137. package/src/lib/format/phone.mjs.map +1 -1
  138. package/src/lib/format/picker-options.d.mts +12 -0
  139. package/src/lib/format/picker-options.d.ts +12 -0
  140. package/src/lib/format/picker-options.js +21 -3
  141. package/src/lib/format/picker-options.js.map +1 -1
  142. package/src/lib/format/picker-options.mjs +20 -2
  143. package/src/lib/format/picker-options.mjs.map +1 -1
  144. package/src/lib/format/prefill-checks.d.mts +13 -0
  145. package/src/lib/format/prefill-checks.d.ts +13 -0
  146. package/src/lib/format/prefill-checks.js +35 -0
  147. package/src/lib/format/prefill-checks.js.map +1 -0
  148. package/src/lib/format/prefill-checks.mjs +32 -0
  149. package/src/lib/format/prefill-checks.mjs.map +1 -0
  150. package/src/lib/format/prefill.d.mts +33 -0
  151. package/src/lib/format/prefill.d.ts +33 -0
  152. package/src/lib/format/prefill.js +20 -0
  153. package/src/lib/format/prefill.js.map +1 -0
  154. package/src/lib/format/prefill.mjs +17 -0
  155. package/src/lib/format/prefill.mjs.map +1 -0
  156. package/src/lib/format/quiz.d.mts +58 -0
  157. package/src/lib/format/quiz.d.ts +58 -0
  158. package/src/lib/format/quiz.js +24 -0
  159. package/src/lib/format/quiz.js.map +1 -0
  160. package/src/lib/format/quiz.mjs +21 -0
  161. package/src/lib/format/quiz.mjs.map +1 -0
  162. package/src/lib/format/records.js +3 -0
  163. package/src/lib/format/records.js.map +1 -1
  164. package/src/lib/format/records.mjs +3 -0
  165. package/src/lib/format/records.mjs.map +1 -1
  166. package/src/lib/format/references.d.mts +1 -1
  167. package/src/lib/format/references.d.ts +1 -1
  168. package/src/lib/format/references.js +56 -7
  169. package/src/lib/format/references.js.map +1 -1
  170. package/src/lib/format/references.mjs +57 -8
  171. package/src/lib/format/references.mjs.map +1 -1
  172. package/src/lib/format/schedule-checks.d.mts +8 -0
  173. package/src/lib/format/schedule-checks.d.ts +8 -0
  174. package/src/lib/format/schedule-checks.js +16 -0
  175. package/src/lib/format/schedule-checks.js.map +1 -0
  176. package/src/lib/format/schedule-checks.mjs +13 -0
  177. package/src/lib/format/schedule-checks.mjs.map +1 -0
  178. package/src/lib/format/signature-checks.d.mts +8 -0
  179. package/src/lib/format/signature-checks.d.ts +8 -0
  180. package/src/lib/format/signature-checks.js +21 -0
  181. package/src/lib/format/signature-checks.js.map +1 -1
  182. package/src/lib/format/signature-checks.mjs +20 -0
  183. package/src/lib/format/signature-checks.mjs.map +1 -1
  184. package/src/lib/format/signature-options.js +3 -0
  185. package/src/lib/format/signature-options.js.map +1 -1
  186. package/src/lib/format/signature-options.mjs +3 -0
  187. package/src/lib/format/signature-options.mjs.map +1 -1
  188. package/src/lib/format/slots-options.js +3 -0
  189. package/src/lib/format/slots-options.js.map +1 -1
  190. package/src/lib/format/slots-options.mjs +3 -0
  191. package/src/lib/format/slots-options.mjs.map +1 -1
  192. package/src/lib/format/templates-checks.d.mts +6 -0
  193. package/src/lib/format/templates-checks.d.ts +6 -0
  194. package/src/lib/format/templates-checks.js +16 -0
  195. package/src/lib/format/templates-checks.js.map +1 -0
  196. package/src/lib/format/templates-checks.mjs +13 -0
  197. package/src/lib/format/templates-checks.mjs.map +1 -0
  198. package/src/lib/format/translate.d.mts +2 -0
  199. package/src/lib/format/translate.d.ts +2 -0
  200. package/src/lib/format/translate.js +6 -2
  201. package/src/lib/format/translate.js.map +1 -1
  202. package/src/lib/format/translate.mjs +4 -2
  203. package/src/lib/format/translate.mjs.map +1 -1
  204. package/src/lib/format/typed-options.d.mts +43 -0
  205. package/src/lib/format/typed-options.d.ts +43 -0
  206. package/src/lib/format/typed-options.js +50 -0
  207. package/src/lib/format/typed-options.js.map +1 -0
  208. package/src/lib/format/typed-options.mjs +46 -0
  209. package/src/lib/format/typed-options.mjs.map +1 -0
  210. package/src/lib/format/upgrade.d.mts +5 -1
  211. package/src/lib/format/upgrade.d.ts +5 -1
  212. package/src/lib/format/upgrade.js +5 -1
  213. package/src/lib/format/upgrade.js.map +1 -1
  214. package/src/lib/format/upgrade.mjs +5 -1
  215. package/src/lib/format/upgrade.mjs.map +1 -1
  216. package/src/lib/format/validate.js +3 -0
  217. package/src/lib/format/validate.js.map +1 -1
  218. package/src/lib/format/validate.mjs +3 -0
  219. package/src/lib/format/validate.mjs.map +1 -1
  220. package/src/lib/format/verify-checks.d.mts +10 -0
  221. package/src/lib/format/verify-checks.d.ts +10 -0
  222. package/src/lib/format/verify-checks.js +44 -0
  223. package/src/lib/format/verify-checks.js.map +1 -0
  224. package/src/lib/format/verify-checks.mjs +41 -0
  225. package/src/lib/format/verify-checks.mjs.map +1 -0
  226. package/src/lib/format/version.d.mts +2 -2
  227. package/src/lib/format/version.d.ts +2 -2
  228. package/src/lib/format/version.js +2 -2
  229. package/src/lib/format/version.js.map +1 -1
  230. package/src/lib/format/version.mjs +2 -2
  231. package/src/lib/format/version.mjs.map +1 -1
  232. package/src/lib/format/week.d.mts +18 -0
  233. package/src/lib/format/week.d.ts +18 -0
  234. package/src/lib/format/week.js +58 -0
  235. package/src/lib/format/week.js.map +1 -0
  236. package/src/lib/format/week.mjs +55 -0
  237. package/src/lib/format/week.mjs.map +1 -0
  238. package/src/lib/record/approvals-part.d.mts +1 -1
  239. package/src/lib/record/approvals-part.d.ts +1 -1
  240. package/src/lib/record/approvals-part.js +2 -2
  241. package/src/lib/record/approvals-part.js.map +1 -1
  242. package/src/lib/record/approvals-part.mjs +1 -1
  243. package/src/lib/record/approvals-part.mjs.map +1 -1
  244. package/src/lib/record/data-source.d.mts +348 -5
  245. package/src/lib/record/data-source.d.ts +348 -5
  246. package/src/lib/record/data-source.js.map +1 -1
  247. package/src/lib/record/data-source.mjs.map +1 -1
  248. package/src/lib/record/day-words.d.mts +22 -1
  249. package/src/lib/record/day-words.d.ts +22 -1
  250. package/src/lib/record/day-words.js +29 -2
  251. package/src/lib/record/day-words.js.map +1 -1
  252. package/src/lib/record/day-words.mjs +24 -2
  253. package/src/lib/record/day-words.mjs.map +1 -1
  254. package/src/lib/record/drafts.d.mts +9 -0
  255. package/src/lib/record/drafts.d.ts +9 -0
  256. package/src/lib/record/drafts.js +20 -0
  257. package/src/lib/record/drafts.js.map +1 -1
  258. package/src/lib/record/drafts.mjs +19 -0
  259. package/src/lib/record/drafts.mjs.map +1 -1
  260. package/src/lib/record/files-part.d.mts +1 -0
  261. package/src/lib/record/files-part.d.ts +1 -0
  262. package/src/lib/record/files-part.js +7 -1
  263. package/src/lib/record/files-part.js.map +1 -1
  264. package/src/lib/record/files-part.mjs +5 -1
  265. package/src/lib/record/files-part.mjs.map +1 -1
  266. package/src/lib/record/form-approvals.d.mts +12 -17
  267. package/src/lib/record/form-approvals.d.ts +12 -17
  268. package/src/lib/record/form-approvals.js +19 -9
  269. package/src/lib/record/form-approvals.js.map +1 -1
  270. package/src/lib/record/form-approvals.mjs +18 -8
  271. package/src/lib/record/form-approvals.mjs.map +1 -1
  272. package/src/lib/record/form-limits.d.mts +4 -28
  273. package/src/lib/record/form-limits.d.ts +4 -28
  274. package/src/lib/record/form-limits.js +8 -5
  275. package/src/lib/record/form-limits.js.map +1 -1
  276. package/src/lib/record/form-limits.mjs +8 -5
  277. package/src/lib/record/form-limits.mjs.map +1 -1
  278. package/src/lib/record/form.d.mts +118 -3
  279. package/src/lib/record/form.d.ts +118 -3
  280. package/src/lib/record/form.js +283 -75
  281. package/src/lib/record/form.js.map +1 -1
  282. package/src/lib/record/form.mjs +285 -77
  283. package/src/lib/record/form.mjs.map +1 -1
  284. package/src/lib/record/history-steps.d.mts +38 -0
  285. package/src/lib/record/history-steps.d.ts +38 -0
  286. package/src/lib/record/history-steps.js +63 -0
  287. package/src/lib/record/history-steps.js.map +1 -0
  288. package/src/lib/record/history-steps.mjs +58 -0
  289. package/src/lib/record/history-steps.mjs.map +1 -0
  290. package/src/lib/record/history.d.mts +16 -0
  291. package/src/lib/record/history.d.ts +16 -0
  292. package/src/lib/record/history.js +3 -0
  293. package/src/lib/record/history.js.map +1 -0
  294. package/src/lib/record/history.mjs +2 -0
  295. package/src/lib/record/history.mjs.map +1 -0
  296. package/src/lib/record/input-rules.d.mts +2 -0
  297. package/src/lib/record/input-rules.d.ts +2 -0
  298. package/src/lib/record/input-rules.js +4 -1
  299. package/src/lib/record/input-rules.js.map +1 -1
  300. package/src/lib/record/input-rules.mjs +2 -0
  301. package/src/lib/record/input-rules.mjs.map +1 -1
  302. package/src/lib/record/joins.d.mts +143 -0
  303. package/src/lib/record/joins.d.ts +143 -0
  304. package/src/lib/record/joins.js +28 -0
  305. package/src/lib/record/joins.js.map +1 -0
  306. package/src/lib/record/joins.mjs +24 -0
  307. package/src/lib/record/joins.mjs.map +1 -0
  308. package/src/lib/record/limits.js +7 -4
  309. package/src/lib/record/limits.js.map +1 -1
  310. package/src/lib/record/limits.mjs +8 -5
  311. package/src/lib/record/limits.mjs.map +1 -1
  312. package/src/lib/record/link-values.d.mts +31 -0
  313. package/src/lib/record/link-values.d.ts +31 -0
  314. package/src/lib/record/link-values.js +132 -0
  315. package/src/lib/record/link-values.js.map +1 -0
  316. package/src/lib/record/link-values.mjs +125 -0
  317. package/src/lib/record/link-values.mjs.map +1 -0
  318. package/src/lib/record/live-later.d.mts +15 -0
  319. package/src/lib/record/live-later.d.ts +15 -0
  320. package/src/lib/record/live-later.js +10 -0
  321. package/src/lib/record/live-later.js.map +1 -0
  322. package/src/lib/record/live-later.mjs +7 -0
  323. package/src/lib/record/live-later.mjs.map +1 -0
  324. package/src/lib/record/live-part.d.mts +6 -0
  325. package/src/lib/record/live-part.d.ts +6 -0
  326. package/src/lib/record/live-part.js +12 -0
  327. package/src/lib/record/live-part.js.map +1 -0
  328. package/src/lib/record/live-part.mjs +7 -0
  329. package/src/lib/record/live-part.mjs.map +1 -0
  330. package/src/lib/record/live.d.mts +8 -0
  331. package/src/lib/record/live.d.ts +8 -0
  332. package/src/lib/record/live.js +133 -0
  333. package/src/lib/record/live.js.map +1 -0
  334. package/src/lib/record/live.mjs +129 -0
  335. package/src/lib/record/live.mjs.map +1 -0
  336. package/src/lib/record/locales/all.d.mts +5 -5
  337. package/src/lib/record/locales/all.d.ts +5 -5
  338. package/src/lib/record/locales/all.js +3 -3
  339. package/src/lib/record/locales/all.js.map +1 -1
  340. package/src/lib/record/locales/all.mjs +3 -3
  341. package/src/lib/record/locales/all.mjs.map +1 -1
  342. package/src/lib/record/locales/ar.js +8 -0
  343. package/src/lib/record/locales/ar.js.map +1 -1
  344. package/src/lib/record/locales/ar.mjs +8 -0
  345. package/src/lib/record/locales/ar.mjs.map +1 -1
  346. package/src/lib/record/locales/de.js +8 -0
  347. package/src/lib/record/locales/de.js.map +1 -1
  348. package/src/lib/record/locales/de.mjs +8 -0
  349. package/src/lib/record/locales/de.mjs.map +1 -1
  350. package/src/lib/record/locales/es.d.mts +8 -0
  351. package/src/lib/record/locales/es.d.ts +8 -0
  352. package/src/lib/record/locales/es.js +111 -0
  353. package/src/lib/record/locales/es.js.map +1 -0
  354. package/src/lib/record/locales/es.mjs +108 -0
  355. package/src/lib/record/locales/es.mjs.map +1 -0
  356. package/src/lib/record/locales/fa.d.mts +5 -0
  357. package/src/lib/record/locales/fa.d.ts +5 -0
  358. package/src/lib/record/locales/fa.js +117 -0
  359. package/src/lib/record/locales/fa.js.map +1 -0
  360. package/src/lib/record/locales/fa.mjs +114 -0
  361. package/src/lib/record/locales/fa.mjs.map +1 -0
  362. package/src/lib/record/locales/fr.js +8 -0
  363. package/src/lib/record/locales/fr.js.map +1 -1
  364. package/src/lib/record/locales/fr.mjs +8 -0
  365. package/src/lib/record/locales/fr.mjs.map +1 -1
  366. package/src/lib/record/locales/later.d.mts +8 -0
  367. package/src/lib/record/locales/later.d.ts +8 -0
  368. package/src/lib/record/locales/later.js +16 -0
  369. package/src/lib/record/locales/later.js.map +1 -0
  370. package/src/lib/record/locales/later.mjs +13 -0
  371. package/src/lib/record/locales/later.mjs.map +1 -0
  372. package/src/lib/record/locales/tr.d.mts +6 -0
  373. package/src/lib/record/locales/tr.d.ts +6 -0
  374. package/src/lib/record/locales/tr.js +118 -0
  375. package/src/lib/record/locales/tr.js.map +1 -0
  376. package/src/lib/record/locales/tr.mjs +115 -0
  377. package/src/lib/record/locales/tr.mjs.map +1 -0
  378. package/src/lib/record/locales/ur.d.mts +9 -0
  379. package/src/lib/record/locales/ur.d.ts +9 -0
  380. package/src/lib/record/locales/ur.js +118 -0
  381. package/src/lib/record/locales/ur.js.map +1 -0
  382. package/src/lib/record/locales/ur.mjs +115 -0
  383. package/src/lib/record/locales/ur.mjs.map +1 -0
  384. package/src/lib/record/memory-approvals.d.mts +4 -1
  385. package/src/lib/record/memory-approvals.d.ts +4 -1
  386. package/src/lib/record/memory-approvals.js +29 -0
  387. package/src/lib/record/memory-approvals.js.map +1 -1
  388. package/src/lib/record/memory-approvals.mjs +29 -0
  389. package/src/lib/record/memory-approvals.mjs.map +1 -1
  390. package/src/lib/record/memory-codes.d.mts +37 -0
  391. package/src/lib/record/memory-codes.d.ts +37 -0
  392. package/src/lib/record/memory-codes.js +50 -0
  393. package/src/lib/record/memory-codes.js.map +1 -0
  394. package/src/lib/record/memory-codes.mjs +47 -0
  395. package/src/lib/record/memory-codes.mjs.map +1 -0
  396. package/src/lib/record/memory-data-source.d.mts +56 -2
  397. package/src/lib/record/memory-data-source.d.ts +56 -2
  398. package/src/lib/record/memory-data-source.js +80 -2
  399. package/src/lib/record/memory-data-source.js.map +1 -1
  400. package/src/lib/record/memory-data-source.mjs +80 -2
  401. package/src/lib/record/memory-data-source.mjs.map +1 -1
  402. package/src/lib/record/memory-kept.d.mts +3 -1
  403. package/src/lib/record/memory-kept.d.ts +3 -1
  404. package/src/lib/record/memory-kept.js +7 -2
  405. package/src/lib/record/memory-kept.js.map +1 -1
  406. package/src/lib/record/memory-kept.mjs +7 -2
  407. package/src/lib/record/memory-kept.mjs.map +1 -1
  408. package/src/lib/record/memory-later.d.mts +3 -1
  409. package/src/lib/record/memory-later.d.ts +3 -1
  410. package/src/lib/record/memory-later.js +9 -5
  411. package/src/lib/record/memory-later.js.map +1 -1
  412. package/src/lib/record/memory-later.mjs +8 -4
  413. package/src/lib/record/memory-later.mjs.map +1 -1
  414. package/src/lib/record/memory-live.d.mts +8 -0
  415. package/src/lib/record/memory-live.d.ts +8 -0
  416. package/src/lib/record/memory-live.js +70 -0
  417. package/src/lib/record/memory-live.js.map +1 -0
  418. package/src/lib/record/memory-live.mjs +67 -0
  419. package/src/lib/record/memory-live.mjs.map +1 -0
  420. package/src/lib/record/memory-views.d.mts +11 -0
  421. package/src/lib/record/memory-views.d.ts +11 -0
  422. package/src/lib/record/memory-views.js +68 -0
  423. package/src/lib/record/memory-views.js.map +1 -0
  424. package/src/lib/record/memory-views.mjs +65 -0
  425. package/src/lib/record/memory-views.mjs.map +1 -0
  426. package/src/lib/record/messages.d.mts +21 -3
  427. package/src/lib/record/messages.d.ts +21 -3
  428. package/src/lib/record/messages.js +15 -2
  429. package/src/lib/record/messages.js.map +1 -1
  430. package/src/lib/record/messages.mjs +15 -2
  431. package/src/lib/record/messages.mjs.map +1 -1
  432. package/src/lib/record/order.d.mts +21 -0
  433. package/src/lib/record/order.d.ts +21 -0
  434. package/src/lib/record/order.js +129 -0
  435. package/src/lib/record/order.js.map +1 -0
  436. package/src/lib/record/order.mjs +122 -0
  437. package/src/lib/record/order.mjs.map +1 -0
  438. package/src/lib/record/outbox-form.d.mts +79 -0
  439. package/src/lib/record/outbox-form.d.ts +79 -0
  440. package/src/lib/record/outbox-form.js +291 -0
  441. package/src/lib/record/outbox-form.js.map +1 -0
  442. package/src/lib/record/outbox-form.mjs +286 -0
  443. package/src/lib/record/outbox-form.mjs.map +1 -0
  444. package/src/lib/record/outbox-part.d.mts +6 -0
  445. package/src/lib/record/outbox-part.d.ts +6 -0
  446. package/src/lib/record/outbox-part.js +13 -0
  447. package/src/lib/record/outbox-part.js.map +1 -0
  448. package/src/lib/record/outbox-part.mjs +7 -0
  449. package/src/lib/record/outbox-part.mjs.map +1 -0
  450. package/src/lib/record/pay-part.d.mts +6 -0
  451. package/src/lib/record/pay-part.d.ts +6 -0
  452. package/src/lib/record/pay-part.js +11 -0
  453. package/src/lib/record/pay-part.js.map +1 -0
  454. package/src/lib/record/pay-part.mjs +7 -0
  455. package/src/lib/record/pay-part.mjs.map +1 -0
  456. package/src/lib/record/payment-form.d.mts +25 -0
  457. package/src/lib/record/payment-form.d.ts +25 -0
  458. package/src/lib/record/payment-form.js +98 -0
  459. package/src/lib/record/payment-form.js.map +1 -0
  460. package/src/lib/record/payment-form.mjs +95 -0
  461. package/src/lib/record/payment-form.mjs.map +1 -0
  462. package/src/lib/record/prefill-part.d.mts +7 -0
  463. package/src/lib/record/prefill-part.d.ts +7 -0
  464. package/src/lib/record/prefill-part.js +15 -0
  465. package/src/lib/record/prefill-part.js.map +1 -0
  466. package/src/lib/record/prefill-part.mjs +8 -0
  467. package/src/lib/record/prefill-part.mjs.map +1 -0
  468. package/src/lib/record/press-undo.d.mts +42 -0
  469. package/src/lib/record/press-undo.d.ts +42 -0
  470. package/src/lib/record/press-undo.js +115 -0
  471. package/src/lib/record/press-undo.js.map +1 -0
  472. package/src/lib/record/press-undo.mjs +110 -0
  473. package/src/lib/record/press-undo.mjs.map +1 -0
  474. package/src/lib/record/quiz.d.mts +36 -0
  475. package/src/lib/record/quiz.d.ts +36 -0
  476. package/src/lib/record/quiz.js +90 -0
  477. package/src/lib/record/quiz.js.map +1 -0
  478. package/src/lib/record/quiz.mjs +87 -0
  479. package/src/lib/record/quiz.mjs.map +1 -0
  480. package/src/lib/record/record-words.js +1 -1
  481. package/src/lib/record/record-words.js.map +1 -1
  482. package/src/lib/record/record-words.mjs +1 -1
  483. package/src/lib/record/record-words.mjs.map +1 -1
  484. package/src/lib/record/run.d.mts +54 -2
  485. package/src/lib/record/run.d.ts +54 -2
  486. package/src/lib/record/run.js +30 -6
  487. package/src/lib/record/run.js.map +1 -1
  488. package/src/lib/record/run.mjs +28 -5
  489. package/src/lib/record/run.mjs.map +1 -1
  490. package/src/lib/record/survey-kit.d.mts +37 -0
  491. package/src/lib/record/survey-kit.d.ts +37 -0
  492. package/src/lib/record/survey-kit.js +110 -0
  493. package/src/lib/record/survey-kit.js.map +1 -0
  494. package/src/lib/record/survey-kit.mjs +107 -0
  495. package/src/lib/record/survey-kit.mjs.map +1 -0
  496. package/src/lib/record/survey.d.mts +16 -0
  497. package/src/lib/record/survey.d.ts +16 -0
  498. package/src/lib/record/survey.js +17 -0
  499. package/src/lib/record/survey.js.map +1 -0
  500. package/src/lib/record/survey.mjs +13 -0
  501. package/src/lib/record/survey.mjs.map +1 -0
  502. package/src/lib/record/surveyflow-part.d.mts +9 -0
  503. package/src/lib/record/surveyflow-part.d.ts +9 -0
  504. package/src/lib/record/surveyflow-part.js +20 -0
  505. package/src/lib/record/surveyflow-part.js.map +1 -0
  506. package/src/lib/record/surveyflow-part.mjs +10 -0
  507. package/src/lib/record/surveyflow-part.mjs.map +1 -0
  508. package/src/lib/record/timing.d.mts +76 -0
  509. package/src/lib/record/timing.d.ts +76 -0
  510. package/src/lib/record/timing.js +112 -0
  511. package/src/lib/record/timing.js.map +1 -0
  512. package/src/lib/record/timing.mjs +104 -0
  513. package/src/lib/record/timing.mjs.map +1 -0
  514. package/src/lib/record/undo-later.d.mts +9 -0
  515. package/src/lib/record/undo-later.d.ts +9 -0
  516. package/src/lib/record/undo-later.js +10 -0
  517. package/src/lib/record/undo-later.js.map +1 -0
  518. package/src/lib/record/undo-later.mjs +7 -0
  519. package/src/lib/record/undo-later.mjs.map +1 -0
  520. package/src/lib/record/undo-part.d.mts +8 -0
  521. package/src/lib/record/undo-part.d.ts +8 -0
  522. package/src/lib/record/undo-part.js +17 -0
  523. package/src/lib/record/undo-part.js.map +1 -0
  524. package/src/lib/record/undo-part.mjs +9 -0
  525. package/src/lib/record/undo-part.mjs.map +1 -0
  526. package/src/lib/record/upload-to-later.d.mts +10 -0
  527. package/src/lib/record/upload-to-later.d.ts +10 -0
  528. package/src/lib/record/upload-to-later.js +15 -0
  529. package/src/lib/record/upload-to-later.js.map +1 -0
  530. package/src/lib/record/upload-to-later.mjs +12 -0
  531. package/src/lib/record/upload-to-later.mjs.map +1 -0
  532. package/src/lib/record/uploads.d.mts +5 -0
  533. package/src/lib/record/uploads.d.ts +5 -0
  534. package/src/lib/record/uploads.js.map +1 -1
  535. package/src/lib/record/uploads.mjs.map +1 -1
  536. package/src/lib/record/values.d.mts +6 -0
  537. package/src/lib/record/values.d.ts +6 -0
  538. package/src/lib/record/values.js.map +1 -1
  539. package/src/lib/record/values.mjs.map +1 -1
  540. package/src/lib/record/verify-form.d.mts +24 -0
  541. package/src/lib/record/verify-form.d.ts +24 -0
  542. package/src/lib/record/verify-form.js +65 -0
  543. package/src/lib/record/verify-form.js.map +1 -0
  544. package/src/lib/record/verify-form.mjs +62 -0
  545. package/src/lib/record/verify-form.mjs.map +1 -0
  546. package/src/lib/record/verify-part.d.mts +6 -0
  547. package/src/lib/record/verify-part.d.ts +6 -0
  548. package/src/lib/record/verify-part.js +11 -0
  549. package/src/lib/record/verify-part.js.map +1 -0
  550. package/src/lib/record/verify-part.mjs +7 -0
  551. package/src/lib/record/verify-part.mjs.map +1 -0
  552. package/src/lib/record/words-chunks.d.mts +37 -0
  553. package/src/lib/record/words-chunks.d.ts +37 -0
  554. package/src/lib/record/words-chunks.js +94 -0
  555. package/src/lib/record/words-chunks.js.map +1 -0
  556. package/src/lib/record/words-chunks.mjs +86 -0
  557. package/src/lib/record/words-chunks.mjs.map +1 -0
  558. package/src/runtime.d.mts +28 -6
  559. package/src/runtime.d.ts +28 -6
  560. package/src/runtime.js +35 -6
  561. package/src/runtime.js.map +1 -1
  562. package/src/runtime.mjs +15 -3
  563. package/src/runtime.mjs.map +1 -1
package/README.md CHANGED
@@ -28,7 +28,7 @@ list of records — that your app implements;
28
28
  The page format is also a JSON Schema, for editors and other languages:
29
29
  `@fieldia/core/page.schema.json`.
30
30
 
31
- A page says which format it is written in (`"fieldia": "0.9"`, `FORMAT_VERSION`; a page in 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7 or 0.8 is read as it is).
31
+ A page says which format it is written in (`"fieldia": "0.10"`, `FORMAT_VERSION`; a page in 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8 or 0.9 is read as it is).
32
32
  One in an older format is brought up to date as it is read — by `checkPage`,
33
33
  `validatePage` and `createForm`, so by the viewer and the designer too — and
34
34
  `upgradePage` does it for the pages your app keeps. One newer than this Fieldia
@@ -63,6 +63,92 @@ settings each kind has are `PART_LOOKS`:
63
63
  }
64
64
  ```
65
65
 
66
+ The validation messages (`MESSAGES`) come in English, Arabic, German and French,
67
+ and in Turkish (`tr`), Persian (`fa`), Urdu (`ur`) and Spanish (`es`) —
68
+ **machine-assisted, not yet reviewed by a native speaker**: every message
69
+ English has, with its blanks, not yet read by a native speaker (corrections
70
+ welcome). Persian and Urdu are written right to left; `readNumber` reads their
71
+ digits (۰–۹) and marks (٫ ٬) as it reads Arabic-Indic ones; a day a message
72
+ names is written by Intl on the Gregorian calendar a value is kept in
73
+ (`dayTag`: Intl's own for Persian is the Solar Hijri — Fieldia shows the
74
+ Gregorian day, in Latin digits, in Persian too, for now). `listComma` gives the
75
+ Arabic comma in Arabic, Persian and Urdu.
76
+
77
+ `firstWeekday(language, page?)` is the week's first day, `0` Sunday to `6`
78
+ Saturday — the one every week Fieldia draws starts on: a list's "this week" and
79
+ its weeks, a calendar's and a timeline's, a date's and a range's month, booking
80
+ slots' month, a week's hours, a repeat's days, a chatter's history. CLDR's day
81
+ for a region, which is decided in this order:
82
+
83
+ 1. the region of the language's own tag: the page's (`"language": "en-GB"`,
84
+ where the page is shown in its own language) or the one given (`en-GB`);
85
+ 2. else the reader's, where the browser asks for the same language with a
86
+ region (`navigator.languages`, the first that does): an `en` page read in
87
+ `en-EG` starts on Saturday, in `en-GB` on Monday, in `en-US` on Sunday;
88
+ 3. else the region CLDR has the language most spoken in: the United States'
89
+ for `en` (Sunday), Egypt's for `ar` and Iran's for `fa` (Saturday),
90
+ Pakistan's for `ur` (Sunday), Germany's, France's, Turkey's and Spain's
91
+ (Monday).
92
+
93
+ The day is the engine's own `Intl.Locale` week info, else CLDR's table (Firefox
94
+ has none). A third argument gives the reader's languages instead of the
95
+ browser's, for a server or a test. In the one-tag script it comes with the parts
96
+ that draw a week (`fieldia.list.js`, `fieldia.date.js`), not with `fieldia.js`:
97
+ `Fieldia.firstWeekday` answers once one has come — `await
98
+ Fieldia.datePart.load()` first where your own code calls it on a page that has
99
+ drawn no week.
100
+
101
+ Those four come in a chunk each of their own, so an app never carries the words
102
+ of a language it does not show: each package says how it fetches its words
103
+ (`wordsInChunks(tableInChunks(table, { tr: () => import('./tr') … }))`), and
104
+ `wordsReady(tag)` fetches every package's for a language, once — the viewer, a
105
+ map and a chatter wait for it before they draw. Asked for, a package's table for
106
+ the language is there at once, English's words, and filled in place as its chunk
107
+ comes; `wordsComing(tag)` says whether it has yet. Something that reads them
108
+ without waiting gets English, and the console says once what to await.
109
+
110
+ ```ts
111
+ import { wordsReady, createForm, MESSAGES } from '@fieldia/core';
112
+ await wordsReady('tr');
113
+ const form = createForm({ page, messages: MESSAGES.tr });
114
+ ```
115
+
116
+ ## A starting page from a schema
117
+
118
+ `pageFromSchema(input, options)` makes a page from what an app already has: a
119
+ **JSON Schema**, an **OpenAPI** document (a component's schema, or an
120
+ operation's request body and parameters — `schema: 'POST /enquiries'`, an
121
+ `operationId`, or a component's name; `schemaChoices(doc)` lists them), or a
122
+ **model's fields** — Fieldia's own, or a backend's field list such as
123
+ Flectra's `fields_get` (`string`, `selection` pairs, `relation`). Each property
124
+ becomes a field of its kind, with its label (`title`, else its name in words),
125
+ help (`description`), required, read-only, limits (`minimum`, `maximum`,
126
+ `maxLength`, `multipleOf` as decimals), pattern (found anywhere, as JSON Schema
127
+ reads it), choices (`enum`, a union of `const`s) and default; `format` picks the
128
+ box (`date`, `date-time`, `email`, `uri`, `time`, a phone, a password, a
129
+ colour, a file); a list of choices is several picked, a list of files several
130
+ files, a list of objects a table of lines; an object's properties are fields of
131
+ their own in a section of its name. `$ref`s inside the document are followed,
132
+ `allOf` merged, `null` set aside.
133
+
134
+ ```ts
135
+ import { pageFromSchema, validatePage } from '@fieldia/core';
136
+
137
+ const { page, notes, unmapped } = pageFromSchema(openApi, { schema: 'POST /enquiries', kind: 'screen' });
138
+ validatePage(page).ok; // true: a page Fieldia reads, to edit in the designer
139
+ ```
140
+
141
+ Nothing is dropped quietly: what is kept with a change is in `notes` (a name a
142
+ field cannot have, renamed; an object's properties flattened; a value of a kind
143
+ no field holds — a list of text, a union of kinds — kept as JSON; a limit no
144
+ setting holds, such as `minLength`, left to your server), and what is left out
145
+ in `unmapped` (a `$ref` outside the document, a property of no kind). Each has a
146
+ `code` and the property's path; `schemaNoteWords(note)` says it in English. A
147
+ survey (`kind: 'survey'`) is a step for the page and one for each object, sent
148
+ as responses; a screen keeps a record of `model` (its title's words joined by
149
+ dots unless given). A schema that gives no page throws `SchemaRefused`, its
150
+ `code` saying why. In the designer: **Start from a schema…** on a blank page.
151
+
66
152
  ## Values that wait for a line
67
153
 
68
154
  A value worked out from others waits while one of them holds text that does
@@ -311,6 +397,103 @@ refused by the page check. `createMemoryDataSource`
311
397
  answers each response as a server would with ``submitted: (request, count) =>
312
398
  ({ id: `B-${1042 + count}` })``.
313
399
 
400
+ ## A quiz's results
401
+
402
+ A page of responses with `quiz` shows the person their results once the answers
403
+ are sent: their score, each question marked right or wrong, the right answer to
404
+ one missed and the question's own feedback. A choice's right answers are its
405
+ options marked `correct`; a question typed — a word, a number — names the
406
+ answers it takes (`quiz.answers`: words whatever their case and spaces, a number
407
+ by its value). A right answer earns its question's `quiz.points`, else the
408
+ page's, else 1; a choice whose options carry points (`score`) earns those, as
409
+ before, marked neither right nor wrong. With several answers, right is exactly
410
+ the right ones.
411
+
412
+ ```json
413
+ "quiz": { "results": "now", "points": 1, "rightAnswers": true },
414
+ "fields": {
415
+ "reversible": { "type": "selection", "label": "Which filler can be dissolved?",
416
+ "options": [{ "value": "ha", "label": "Hyaluronic acid", "correct": true }, { "value": "caha", "label": "Calcium hydroxylapatite" }],
417
+ "quiz": { "feedback": { "right": "Yes: hyaluronidase dissolves it.", "wrong": "Only hyaluronic acid can be dissolved." } } },
418
+ "enzyme": { "type": "char", "label": "Which enzyme dissolves it?", "quiz": { "answers": ["Hyaluronidase"] } }
419
+ }
420
+ ```
421
+
422
+ The form marks the answers as they go — `form.getState().sent.quiz` is
423
+ `{ score, max, questions: [{ field, points, max, right, answered, rightAnswer?,
424
+ feedback? }] }`, in the order they were asked — with the survey flow's part
425
+ (`formSurveyPart`, asked for as the form opens). `results: "later"` says the
426
+ results come once you have reviewed them, and shows none; `rightAnswers: false`
427
+ keeps the right answers back. The right answers travel in the page, where
428
+ anyone who reads its JSON finds them: a test where that matters keeps them out
429
+ of the page, marks the answers on your server and answers the send with them —
430
+ `submit` returns `{ quiz: { score, max, questions } }`, shown in place of the
431
+ page's. `quizResults(page, values, asked?)` marks answers the page's way for
432
+ your own code. A quiz has no pass mark of its own yet: your server may answer
433
+ the send with a value of its own (`values: { passed: true }`), which an
434
+ ending's `when` reads.
435
+
436
+ ## A review before sending
437
+
438
+ `review` on a page of responses shows every answer before it is sent — by step
439
+ on a wizard, by titled group on a page of sections — each with Edit back to its
440
+ question, then Send: `true` in Fieldia's words ("Check your answers"), or
441
+ `{ "title": "Before you send", "text": "Press Edit to change one." }` in the
442
+ page's. The viewer draws it (the survey flow's part); the answers are checked as a
443
+ step's are before they show. `form.validate(within)` checks the answers inside
444
+ one part alone — a step, a question — as the review and one question at a time
445
+ do.
446
+
447
+ ## One question at a time
448
+
449
+ `"flow": "one"` on a page of responses asks one question at a time (the
450
+ viewer's survey part draws it): each question on a screen of its own, Enter or
451
+ OK going on once its answer is checked (`form.validate(within)`, the question's
452
+ part alone), a choice picked going on by itself. A wizard's steps are entered,
453
+ checked and kept as ever. A record's sheet, and a list, are refused it.
454
+
455
+ ## Questions in an order drawn, and N of M
456
+
457
+ On a page of responses, a wizard's `"order": "random"` shows its steps in an
458
+ order drawn for each respondent — a step `"fixed": true` keeps its place (a
459
+ welcome first, a page about you last) — and a step's or a group's shows its
460
+ questions so: words and pictures, and a question `fixed`, keep their places.
461
+ `"draw": 5` asks 5 of its questions, drawn, the rest never asked (nor
462
+ required, nor sent). The draw is seeded — `createForm`'s `seed` (an
463
+ invitation's code, a candidate's id), else the person's `user.id`, else one of
464
+ the browser's for each response — so the same seed draws the same in every
465
+ engine. The form keeps it as `state.order` (by part, its parts' ids in the
466
+ order shown), in its drafts — a page opened again shows the same questions —
467
+ and sends it with the answers (`SubmitRequest.order`). A quiz's results follow
468
+ the order shown. The draw comes in the survey flow's part (`formSurveyPart`, asked for
469
+ as the form opens; a form made before it came draws once it has).
470
+
471
+ ## A time limit
472
+
473
+ `"timeLimit": { "minutes": 20, "warn": 2, "then": "send" }` on a page of
474
+ responses, or on one of its steps. A page's clock starts with
475
+ `form.startTimer()` (the viewer's Start), a step's as it is first entered; each
476
+ runs on the form's clock (`now`, `scheduler`) and runs out on time
477
+ (`state.timeUp`, by scope: `#form`, or the step's id). Its answers are then
478
+ locked, and their checks refuse nothing: they go as they stood — a required
479
+ answer not given goes empty. `then: "send"` (a page's default) leaves the send
480
+ to the viewer, at once; a headless app calls `form.save()` as `timeUp` changes.
481
+ `lock` (a step's default) keeps them for the person to send; a step's that
482
+ locks gives way to the next step. `form.countdown()` is the countdown showing
483
+ now (`{ scope, left, ends, stage: 'running' | 'warning' | 'up', … }`). Their
484
+ starts are kept in drafts (`StoredDraft.timers`) with the answers, so a page
485
+ opened again goes on counting: a reload is never a way round a limit. A clock's
486
+ start is kept the moment it starts, and a draft whose clock started is laid at
487
+ once — never offered to be let go, even with `drafts.restore: "ask"`. Where the
488
+ app keeps no drafts (no `drafts`, no `saveDraft`), a timed page keeps them in
489
+ the tab's own store (`sessionStorage`): a reload goes on with the time left, or
490
+ — past its end — says the time is up and sends or locks as the page says. Sent,
491
+ or started again (`form.reset()`), the draft is let go: the next response is a
492
+ new one, with its own clock. The send tells `started` and `timeUp`. The clock is
493
+ the browser's, and another tab or device starts afresh: a server that must be
494
+ sure keeps its own (it has `started`), and takes one response per person
495
+ (`limits.onePerPerson`).
496
+
314
497
  ## Files stored as they are picked
315
498
 
316
499
  Give the data source `upload(file, request)` and a file or picture field sends
@@ -347,6 +530,8 @@ your words and offers no Retry; any other error offers Retry. Stop with an
347
530
  { bytesPerSecond, fails } })` is a store as slow, or as unreliable, as a real
348
531
  one. Without `upload`, files travel inside the record as base64, as before.
349
532
  See [files stored as they are picked](https://fieldia.dev/data/#upload).
533
+ `uploadTo`'s work comes in the files part (0.31), asked for as its first file
534
+ goes — a page with a file field has it already; one with none never downloads it.
350
535
 
351
536
  A photo set (`"widget": "photos"`, @fieldia/widgets' README) keeps everything in
352
537
  the field's value, so any source that keeps a file value keeps it: the photos in
@@ -686,6 +871,105 @@ import { assistStandIn, createMemoryDataSource } from '@fieldia/core';
686
871
  const dataSource = createMemoryDataSource({ records, assist: assistStandIn({ drafts: { 'enquiry.reply': (values) => `Dear ${values.partner_name},` } }) });
687
872
  ```
688
873
 
874
+ ## Fields filled from the link
875
+
876
+ A page may fill fields from the link it is opened with — a campaign's, a
877
+ broker's, a unit's — with no code of the app's:
878
+
879
+ ```json
880
+ {
881
+ "prefill": { "fromUrl": ["utm_source", "utm_campaign", { "param": "agent", "field": "agent_code" }, "unit"] },
882
+ "fields": { "utm_source": { "type": "char", "label": "Source" }, "agent_code": { "type": "char", "label": "Agent" }, "unit": { "type": "char", "label": "Unit" } }
883
+ }
884
+ ```
885
+
886
+ `https://homes.example/enquiry?utm_source=whatsapp&agent=mona&unit=B-12` starts
887
+ the form with those values: each parameter named fills the field of its name, or
888
+ the `field` it names, as a new record or response starts — and again after
889
+ Submit another. A field the page fills so and places nowhere is a hidden field:
890
+ sent with the answers (a page of responses otherwise sends only what its
891
+ questions show), seen by no one. One placed on the page shows the value, for the
892
+ person to keep or change. Words are read as the field reads them — a number as a
893
+ number, `yes`/`no`/`1`/`0` for a yes or no, a choice by one of its options'
894
+ values, a day as 2026-10-20, a day and time with its offset — and one that does
895
+ not read so, or that the field's own checks would refuse (its most characters,
896
+ its pattern, its least and most), is left out: a hidden field no one can put
897
+ right never stops a send. The link never writes over an answer: a draft opened
898
+ over it, and what the person types, are theirs; a stored record opened is never
899
+ filled. The form reads `url` (the address, its `?…` part, or the parameters by
900
+ name), else the page's own address (`location.href`) — an app rendered on a
901
+ server, or embedded, gives the one it knows (the React, Vue and Angular
902
+ wrappers' `url`) — and `linkValues(page, url)` is the reading, exported. The page's checks refuse a
903
+ field it has not, a link's field, one worked out, a choice of the app's own
904
+ list, and a field filled twice.
905
+
906
+ ## Proof of an email or a phone
907
+
908
+ A field drawn as an email or a phone may ask the person to prove it is theirs
909
+ before the answers go — `"options": { "verify": true }`, or `{ "by":
910
+ ["whatsapp", "sms"] }` for the ways a code may be sent — where the data source
911
+ has `sendCode({ pageId, model, recordId, field, value, kind, by, language })`
912
+ (answering `{ id, expiresAt, retryAfter, length, message }`) and
913
+ `checkCode({ …, value, code, id })` (answering `{ ok, proof }`, or `{ ok:
914
+ false, triesLeft, expired }`). Fieldia sends nothing and holds no keys: the app
915
+ sends the code its own way. `form.joined('verify')?.mark(field, { value, proof
916
+ })` keeps a proof while the field holds that value (`state.verified`); a send is refused
917
+ while a shown field asking for a code holds a value not proved ("Mobile is not
918
+ confirmed: send a code and type it in"), and every send carries `verified` — by
919
+ field, the value and the proof — for the server to trust.
920
+ `form.joined('verify')?.asks(field)` says whether a field asks for one: never
921
+ where the source lacks either member.
922
+ The memory source sends and checks codes as a service would (its `codes`
923
+ option), each kept in `codes`.
924
+
925
+ ## A payment the answers wait for
926
+
927
+ A page may take a payment before its answers go — a reservation fee, a deposit
928
+ — through the app's own provider: `"payment": { "label": "Reservation fee",
929
+ "amount": 10000, "currency": "EGP", "when": "visit == 'reserve'" }` (the amount
930
+ a number or a number or money field's name, the currency a code or a field's,
931
+ else a money field's own). Where the data source has `pay(request)` (answering
932
+ `{ status: 'paid' | 'failed' | 'cancelled', reference, message }`), a send
933
+ checks the answers, then waits for the payment — through the host's payment
934
+ step (the viewer's, else `ActionHost.pay`), else the source's `pay` itself — and
935
+ sends nothing unpaid; paid, the send carries `payment` (`{ amount, currency,
936
+ key, reference }`). `request.key` is the same for every try of one response's
937
+ payment: the provider's idempotency key. A send that failed after paying is
938
+ sent again without paying twice. `form.joined('pay')?.due()` says what is due
939
+ now, `state.paid` what was taken. A new payment in the designer asks 100 USD
940
+ until its amount and currency are set. Fieldia holds no keys and no provider's code. The
941
+ memory source answers paid unless its `pay` option says otherwise.
942
+
943
+ ## Sends kept without signal
944
+
945
+ A page with `"outbox": true` keeps a send that finds no network — a site
946
+ visit's report in a compound, a delivery's proof — on the device and sends it
947
+ when the signal comes back. The form goes on as though it went: a response ends
948
+ "Kept on this device" (`state.outbox.kept`), and `state.outbox` says how many
949
+ wait (`{ waiting, sending, offline, kept, refused }`). The items are kept in the browser's
950
+ IndexedDB (`indexedOutbox()`: never lost on a reload, shared by a site's tabs),
951
+ or the store given as `outbox` (`memoryOutbox()` for tests). A photo the network
952
+ could not take stays in its field as its bytes and is stored through `upload`
953
+ just before its send goes. `form.joined('outbox')` sends what waits in order —
954
+ each item claimed by one sender, sent with `queued: { key, at }` so a server
955
+ can refuse a second try — and keeps a refusal to `retry` or `discard`. Kept sends
956
+ go in the order they were kept; a send made once the signal is back goes first,
957
+ and what waited goes right after it. A new record
958
+ saved twice without signal is saved once, and the form takes its id when it
959
+ went. The memory source's `offline` option fails as a network does.
960
+
961
+ ## Parts that join a form
962
+
963
+ The four above are parts of their own, asked for as a page needs them
964
+ (`formJoins(page)`): the form knows only that its page asks for one, and each
965
+ joins it by one hook into its send (`FormJoin`) — `before` the send, once the
966
+ form's own checks ran (a field not proved added to what they found; a payment
967
+ not taken, nothing sent), `around` the send itself (what it carries added, or
968
+ kept on the device), and `reset` as another response or record starts. Their
969
+ state, their words and their checks come with them. `form.joined(name)` is a
970
+ part's side of the form once it came — null before, and on a page that asks for
971
+ none; a send made before it came waits for it.
972
+
689
973
  ## What a page's records are called
690
974
 
691
975
  A page may say what its records are, so Fieldia's own sentences name them as
@@ -737,6 +1021,63 @@ plain, locale)` says one. A language, or an app's own `messages`, that has no
737
1021
  such sentence says its plain one: a page that names no records reads as before.
738
1022
  `checkPage` and `validatePage` refuse a word for one or for more left out.
739
1023
 
1024
+ ## Undo and Redo while filling
1025
+
1026
+ A form keeps the person's changes to the record shown, for `form.undo()` and
1027
+ `form.redo()` (the viewer's Ctrl+Z and Ctrl+Shift+Z): each field written
1028
+ (`setValue`), each cell typed in (`updateLine`), each line added, taken away or
1029
+ moved — typing on in one box is one change until the box is left
1030
+ (`boxLeft`). Each returns what it took (`{ field, line? }`), or null when
1031
+ nothing is left; `form.history()` names the next of each without taking it.
1032
+ A save starts them afresh, as a change saved is none to take back — but on a
1033
+ page with `autosave`, whose changes are taken back across its saves, and where
1034
+ a change made while it saved goes on past it. The changes are noted from the first; walking them is the undo part's
1035
+ (`pressUndoPart`), asked for with the first change — in by the time a person
1036
+ presses Ctrl+Z, and in at once where an app loads it first (`await
1037
+ pressUndoPart.load()`): until it has come, `undo` and `redo` take nothing.
1038
+
1039
+ ```ts
1040
+ form.setValue('price', 1200);
1041
+ form.boxLeft('price');
1042
+ form.undo(); // { field: 'price' }: back to what it held, as the person's own change back
1043
+ form.redo(); // { field: 'price' }: 1200 again
1044
+ ```
1045
+
1046
+ What it writes is the person's own change back: the page's `change` steps and
1047
+ the source's onchange run as for any, and what is worked out from it follows. A
1048
+ step's, a rule's or the app's writes are never a change to take back, and a
1049
+ change whose field one of them wrote since — or that is locked now — is passed
1050
+ over, never written over theirs. Another record shown, a reload, or `reset()`
1051
+ starts with nothing to take back; a form not being edited takes nothing back.
1052
+
1053
+ ## Changes pushed as they happen, and who else is here
1054
+
1055
+ Two optional data source members make an open record live. `subscribe(record,
1056
+ push) → stop` is asked as a record is shown and stopped as another is; push
1057
+ `{ type: 'record', version?, values?, by?, at? }` as someone else saves it, or
1058
+ `{ type: 'deleted', by? }`. Where the person changed nothing, their values are
1059
+ laid on the record as stored (`arrived` is told, `conflict: false`); after a
1060
+ change of theirs it waits as the conflict a save would meet (`state.conflict`,
1061
+ with Reload and Keep mine), their typing untouched. A change without `values`
1062
+ is read with `load`; one carrying this form's own version is let go.
1063
+ `presence(request, push) → stop` is asked with the form's `user` and whether
1064
+ they have changes not saved (`editing`), asked again as that turns; what it
1065
+ pushes — the others with the record open — is `state.present`. Both are the
1066
+ same call as @fieldia/chatter's `subscribe`, with types that never meet: one
1067
+ function may serve both. It comes in a part of its own (`recordLivePart`),
1068
+ asked for as a form is made where the source has either member, and never
1069
+ where it has neither. The memory source does both with `live: true`
1070
+ (`changeElsewhere`, `arrive`, `leave`), and has none of them without.
1071
+
1072
+ ## Record templates
1073
+
1074
+ A record page's `templates` (`true`, or `{ fields }`) keeps a record's values
1075
+ by a name, to start new records from. The data source's `templates`,
1076
+ `saveTemplate` and `deleteTemplate` keep them on your server
1077
+ (`RecordTemplate`: `{ id, name, values, by? }`); the viewer keeps them in its
1078
+ `preferences` without them. The memory source has them where its `templates`
1079
+ option is given (`{}` for none yet), kept by page id.
1080
+
740
1081
  ## Two people, one record
741
1082
 
742
1083
  A source that keeps versions returns each record with its version, and what this
@@ -1019,6 +1360,37 @@ onAction: async ({ action, values }) => {
1019
1360
  warning. Nothing answered means go on: an `onAction` that returns nothing
1020
1361
  works as it always did.
1021
1362
 
1363
+ ### Undo after a one-tap press
1364
+
1365
+ A button or a gear menu item with `"undo": true` offers Undo in place of
1366
+ asking first: once its press has run whole, the words it said — its last `say`,
1367
+ or the app's — are given to the host's `say` with a third argument, `{ undo }`
1368
+ (else "Done: {label}", the built-in Archive's "Archived."); the words before
1369
+ them are said plainly. `undo()` takes the press back and resolves to a
1370
+ `RunResult`: the app's own undos (an answer's `undo`, latest first, each
1371
+ answered as a call is), the record archived brought back (or the reverse), and
1372
+ the values its steps and answers wrote put back — each only while it holds what
1373
+ they left — saved again where the press saved. It is offered only where all of
1374
+ it can be taken back: a copy, a delete, a post, a page opened, an address, a
1375
+ form put back or closed, or a call answered without `undo` say plainly. Steps in
1376
+ place of `true` are what Undo runs instead. A call's answer with `undo` offers it
1377
+ by itself, for what the app did:
1378
+
1379
+ ```ts
1380
+ onAction: async ({ action, recordId }) => {
1381
+ if (action === 'mark_done') {
1382
+ await api.done(recordId);
1383
+ return { say: { message: 'Follow-up marked done', tone: 'success' }, undo: () => api.reopen(recordId).then(() => ({ reload: true })) };
1384
+ }
1385
+ },
1386
+ ```
1387
+
1388
+ Undo's run is told as `run` with the press's id and `.undo` after it
1389
+ (`b-done.undo`); a built-in Archive or Delete with `undo` asks nothing first
1390
+ unless it says `confirm`. Saying it with Undo and taking it back come in a part
1391
+ of their own (`pressUndoPart`, `fieldia.undo.js`): asked for with a page whose
1392
+ buttons offer Undo, else as an answer first brings one.
1393
+
1022
1394
  ### The moments
1023
1395
 
1024
1396
  - `open` runs once the form has its values: as soon as a new one is made, and
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fieldia/core",
3
- "version": "0.30.1",
3
+ "version": "0.31.1",
4
4
  "description": "Headless form model for Fieldia: the page format, modifiers, validation and record state. No DOM.",
5
5
  "license": "MIT",
6
6
  "homepage": "https://fieldia.dev",