@fieldia/core 0.30.0 → 0.31.0

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 +362 -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 +337 -3
  245. package/src/lib/record/data-source.d.ts +337 -3
  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/files-part.d.mts +1 -0
  255. package/src/lib/record/files-part.d.ts +1 -0
  256. package/src/lib/record/files-part.js +7 -1
  257. package/src/lib/record/files-part.js.map +1 -1
  258. package/src/lib/record/files-part.mjs +5 -1
  259. package/src/lib/record/files-part.mjs.map +1 -1
  260. package/src/lib/record/form-approvals.d.mts +12 -17
  261. package/src/lib/record/form-approvals.d.ts +12 -17
  262. package/src/lib/record/form-approvals.js +15 -9
  263. package/src/lib/record/form-approvals.js.map +1 -1
  264. package/src/lib/record/form-approvals.mjs +14 -8
  265. package/src/lib/record/form-approvals.mjs.map +1 -1
  266. package/src/lib/record/form-limits.d.mts +4 -28
  267. package/src/lib/record/form-limits.d.ts +4 -28
  268. package/src/lib/record/form-limits.js +8 -5
  269. package/src/lib/record/form-limits.js.map +1 -1
  270. package/src/lib/record/form-limits.mjs +8 -5
  271. package/src/lib/record/form-limits.mjs.map +1 -1
  272. package/src/lib/record/form.d.mts +125 -7
  273. package/src/lib/record/form.d.ts +125 -7
  274. package/src/lib/record/form.js +277 -77
  275. package/src/lib/record/form.js.map +1 -1
  276. package/src/lib/record/form.mjs +278 -78
  277. package/src/lib/record/form.mjs.map +1 -1
  278. package/src/lib/record/history-steps.d.mts +38 -0
  279. package/src/lib/record/history-steps.d.ts +38 -0
  280. package/src/lib/record/history-steps.js +63 -0
  281. package/src/lib/record/history-steps.js.map +1 -0
  282. package/src/lib/record/history-steps.mjs +58 -0
  283. package/src/lib/record/history-steps.mjs.map +1 -0
  284. package/src/lib/record/history.d.mts +16 -0
  285. package/src/lib/record/history.d.ts +16 -0
  286. package/src/lib/record/history.js +3 -0
  287. package/src/lib/record/history.js.map +1 -0
  288. package/src/lib/record/history.mjs +2 -0
  289. package/src/lib/record/history.mjs.map +1 -0
  290. package/src/lib/record/input-rules.d.mts +2 -0
  291. package/src/lib/record/input-rules.d.ts +2 -0
  292. package/src/lib/record/input-rules.js +4 -1
  293. package/src/lib/record/input-rules.js.map +1 -1
  294. package/src/lib/record/input-rules.mjs +2 -0
  295. package/src/lib/record/input-rules.mjs.map +1 -1
  296. package/src/lib/record/joins.d.mts +143 -0
  297. package/src/lib/record/joins.d.ts +143 -0
  298. package/src/lib/record/joins.js +28 -0
  299. package/src/lib/record/joins.js.map +1 -0
  300. package/src/lib/record/joins.mjs +24 -0
  301. package/src/lib/record/joins.mjs.map +1 -0
  302. package/src/lib/record/limits.js +7 -4
  303. package/src/lib/record/limits.js.map +1 -1
  304. package/src/lib/record/limits.mjs +8 -5
  305. package/src/lib/record/limits.mjs.map +1 -1
  306. package/src/lib/record/link-values.d.mts +31 -0
  307. package/src/lib/record/link-values.d.ts +31 -0
  308. package/src/lib/record/link-values.js +132 -0
  309. package/src/lib/record/link-values.js.map +1 -0
  310. package/src/lib/record/link-values.mjs +125 -0
  311. package/src/lib/record/link-values.mjs.map +1 -0
  312. package/src/lib/record/live-later.d.mts +15 -0
  313. package/src/lib/record/live-later.d.ts +15 -0
  314. package/src/lib/record/live-later.js +10 -0
  315. package/src/lib/record/live-later.js.map +1 -0
  316. package/src/lib/record/live-later.mjs +7 -0
  317. package/src/lib/record/live-later.mjs.map +1 -0
  318. package/src/lib/record/live-part.d.mts +6 -0
  319. package/src/lib/record/live-part.d.ts +6 -0
  320. package/src/lib/record/live-part.js +12 -0
  321. package/src/lib/record/live-part.js.map +1 -0
  322. package/src/lib/record/live-part.mjs +7 -0
  323. package/src/lib/record/live-part.mjs.map +1 -0
  324. package/src/lib/record/live.d.mts +8 -0
  325. package/src/lib/record/live.d.ts +8 -0
  326. package/src/lib/record/live.js +133 -0
  327. package/src/lib/record/live.js.map +1 -0
  328. package/src/lib/record/live.mjs +129 -0
  329. package/src/lib/record/live.mjs.map +1 -0
  330. package/src/lib/record/locales/all.d.mts +5 -5
  331. package/src/lib/record/locales/all.d.ts +5 -5
  332. package/src/lib/record/locales/all.js +3 -3
  333. package/src/lib/record/locales/all.js.map +1 -1
  334. package/src/lib/record/locales/all.mjs +3 -3
  335. package/src/lib/record/locales/all.mjs.map +1 -1
  336. package/src/lib/record/locales/ar.js +11 -1
  337. package/src/lib/record/locales/ar.js.map +1 -1
  338. package/src/lib/record/locales/ar.mjs +11 -1
  339. package/src/lib/record/locales/ar.mjs.map +1 -1
  340. package/src/lib/record/locales/de.js +11 -1
  341. package/src/lib/record/locales/de.js.map +1 -1
  342. package/src/lib/record/locales/de.mjs +11 -1
  343. package/src/lib/record/locales/de.mjs.map +1 -1
  344. package/src/lib/record/locales/es.d.mts +8 -0
  345. package/src/lib/record/locales/es.d.ts +8 -0
  346. package/src/lib/record/locales/es.js +111 -0
  347. package/src/lib/record/locales/es.js.map +1 -0
  348. package/src/lib/record/locales/es.mjs +108 -0
  349. package/src/lib/record/locales/es.mjs.map +1 -0
  350. package/src/lib/record/locales/fa.d.mts +5 -0
  351. package/src/lib/record/locales/fa.d.ts +5 -0
  352. package/src/lib/record/locales/fa.js +117 -0
  353. package/src/lib/record/locales/fa.js.map +1 -0
  354. package/src/lib/record/locales/fa.mjs +114 -0
  355. package/src/lib/record/locales/fa.mjs.map +1 -0
  356. package/src/lib/record/locales/fr.js +11 -1
  357. package/src/lib/record/locales/fr.js.map +1 -1
  358. package/src/lib/record/locales/fr.mjs +11 -1
  359. package/src/lib/record/locales/fr.mjs.map +1 -1
  360. package/src/lib/record/locales/later.d.mts +8 -0
  361. package/src/lib/record/locales/later.d.ts +8 -0
  362. package/src/lib/record/locales/later.js +16 -0
  363. package/src/lib/record/locales/later.js.map +1 -0
  364. package/src/lib/record/locales/later.mjs +13 -0
  365. package/src/lib/record/locales/later.mjs.map +1 -0
  366. package/src/lib/record/locales/tr.d.mts +6 -0
  367. package/src/lib/record/locales/tr.d.ts +6 -0
  368. package/src/lib/record/locales/tr.js +118 -0
  369. package/src/lib/record/locales/tr.js.map +1 -0
  370. package/src/lib/record/locales/tr.mjs +115 -0
  371. package/src/lib/record/locales/tr.mjs.map +1 -0
  372. package/src/lib/record/locales/ur.d.mts +9 -0
  373. package/src/lib/record/locales/ur.d.ts +9 -0
  374. package/src/lib/record/locales/ur.js +118 -0
  375. package/src/lib/record/locales/ur.js.map +1 -0
  376. package/src/lib/record/locales/ur.mjs +115 -0
  377. package/src/lib/record/locales/ur.mjs.map +1 -0
  378. package/src/lib/record/memory-approvals.d.mts +7 -4
  379. package/src/lib/record/memory-approvals.d.ts +7 -4
  380. package/src/lib/record/memory-approvals.js +54 -7
  381. package/src/lib/record/memory-approvals.js.map +1 -1
  382. package/src/lib/record/memory-approvals.mjs +54 -7
  383. package/src/lib/record/memory-approvals.mjs.map +1 -1
  384. package/src/lib/record/memory-assist.d.mts +7 -2
  385. package/src/lib/record/memory-assist.d.ts +7 -2
  386. package/src/lib/record/memory-assist.js +47 -12
  387. package/src/lib/record/memory-assist.js.map +1 -1
  388. package/src/lib/record/memory-assist.mjs +46 -12
  389. package/src/lib/record/memory-assist.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 +60 -4
  397. package/src/lib/record/memory-data-source.d.ts +60 -4
  398. package/src/lib/record/memory-data-source.js +69 -1
  399. package/src/lib/record/memory-data-source.js.map +1 -1
  400. package/src/lib/record/memory-data-source.mjs +69 -1
  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 +60 -0
  423. package/src/lib/record/memory-views.js.map +1 -0
  424. package/src/lib/record/memory-views.mjs +57 -0
  425. package/src/lib/record/memory-views.mjs.map +1 -0
  426. package/src/lib/record/messages.d.mts +24 -3
  427. package/src/lib/record/messages.d.ts +24 -3
  428. package/src/lib/record/messages.js +18 -3
  429. package/src/lib/record/messages.js.map +1 -1
  430. package/src/lib/record/messages.mjs +18 -3
  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 +71 -8
  485. package/src/lib/record/run.d.ts +71 -8
  486. package/src/lib/record/run.js +40 -13
  487. package/src/lib/record/run.js.map +1 -1
  488. package/src/lib/record/run.mjs +38 -12
  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 +99 -0
  493. package/src/lib/record/survey-kit.js.map +1 -0
  494. package/src/lib/record/survey-kit.mjs +96 -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,94 @@ 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`), so a page opened again goes on
485
+ counting; the send tells `started` and `timeUp`. The clock is the browser's: a
486
+ server that must be sure keeps its own.
487
+
314
488
  ## Files stored as they are picked
315
489
 
316
490
  Give the data source `upload(file, request)` and a file or picture field sends
@@ -347,6 +521,8 @@ your words and offers no Retry; any other error offers Retry. Stop with an
347
521
  { bytesPerSecond, fails } })` is a store as slow, or as unreliable, as a real
348
522
  one. Without `upload`, files travel inside the record as base64, as before.
349
523
  See [files stored as they are picked](https://fieldia.dev/data/#upload).
524
+ `uploadTo`'s work comes in the files part (0.31), asked for as its first file
525
+ goes — a page with a file field has it already; one with none never downloads it.
350
526
 
351
527
  A photo set (`"widget": "photos"`, @fieldia/widgets' README) keeps everything in
352
528
  the field's value, so any source that keeps a file value keeps it: the photos in
@@ -686,6 +862,105 @@ import { assistStandIn, createMemoryDataSource } from '@fieldia/core';
686
862
  const dataSource = createMemoryDataSource({ records, assist: assistStandIn({ drafts: { 'enquiry.reply': (values) => `Dear ${values.partner_name},` } }) });
687
863
  ```
688
864
 
865
+ ## Fields filled from the link
866
+
867
+ A page may fill fields from the link it is opened with — a campaign's, a
868
+ broker's, a unit's — with no code of the app's:
869
+
870
+ ```json
871
+ {
872
+ "prefill": { "fromUrl": ["utm_source", "utm_campaign", { "param": "agent", "field": "agent_code" }, "unit"] },
873
+ "fields": { "utm_source": { "type": "char", "label": "Source" }, "agent_code": { "type": "char", "label": "Agent" }, "unit": { "type": "char", "label": "Unit" } }
874
+ }
875
+ ```
876
+
877
+ `https://homes.example/enquiry?utm_source=whatsapp&agent=mona&unit=B-12` starts
878
+ the form with those values: each parameter named fills the field of its name, or
879
+ the `field` it names, as a new record or response starts — and again after
880
+ Submit another. A field the page fills so and places nowhere is a hidden field:
881
+ sent with the answers (a page of responses otherwise sends only what its
882
+ questions show), seen by no one. One placed on the page shows the value, for the
883
+ person to keep or change. Words are read as the field reads them — a number as a
884
+ number, `yes`/`no`/`1`/`0` for a yes or no, a choice by one of its options'
885
+ values, a day as 2026-10-20, a day and time with its offset — and one that does
886
+ not read so, or that the field's own checks would refuse (its most characters,
887
+ its pattern, its least and most), is left out: a hidden field no one can put
888
+ right never stops a send. The link never writes over an answer: a draft opened
889
+ over it, and what the person types, are theirs; a stored record opened is never
890
+ filled. The form reads `url` (the address, its `?…` part, or the parameters by
891
+ name), else the page's own address (`location.href`) — an app rendered on a
892
+ server, or embedded, gives the one it knows (the React, Vue and Angular
893
+ wrappers' `url`) — and `linkValues(page, url)` is the reading, exported. The page's checks refuse a
894
+ field it has not, a link's field, one worked out, a choice of the app's own
895
+ list, and a field filled twice.
896
+
897
+ ## Proof of an email or a phone
898
+
899
+ A field drawn as an email or a phone may ask the person to prove it is theirs
900
+ before the answers go — `"options": { "verify": true }`, or `{ "by":
901
+ ["whatsapp", "sms"] }` for the ways a code may be sent — where the data source
902
+ has `sendCode({ pageId, model, recordId, field, value, kind, by, language })`
903
+ (answering `{ id, expiresAt, retryAfter, length, message }`) and
904
+ `checkCode({ …, value, code, id })` (answering `{ ok, proof }`, or `{ ok:
905
+ false, triesLeft, expired }`). Fieldia sends nothing and holds no keys: the app
906
+ sends the code its own way. `form.joined('verify')?.mark(field, { value, proof
907
+ })` keeps a proof while the field holds that value (`state.verified`); a send is refused
908
+ while a shown field asking for a code holds a value not proved ("Mobile is not
909
+ confirmed: send a code and type it in"), and every send carries `verified` — by
910
+ field, the value and the proof — for the server to trust.
911
+ `form.joined('verify')?.asks(field)` says whether a field asks for one: never
912
+ where the source lacks either member.
913
+ The memory source sends and checks codes as a service would (its `codes`
914
+ option), each kept in `codes`.
915
+
916
+ ## A payment the answers wait for
917
+
918
+ A page may take a payment before its answers go — a reservation fee, a deposit
919
+ — through the app's own provider: `"payment": { "label": "Reservation fee",
920
+ "amount": 10000, "currency": "EGP", "when": "visit == 'reserve'" }` (the amount
921
+ a number or a number or money field's name, the currency a code or a field's,
922
+ else a money field's own). Where the data source has `pay(request)` (answering
923
+ `{ status: 'paid' | 'failed' | 'cancelled', reference, message }`), a send
924
+ checks the answers, then waits for the payment — through the host's payment
925
+ step (the viewer's, else `ActionHost.pay`), else the source's `pay` itself — and
926
+ sends nothing unpaid; paid, the send carries `payment` (`{ amount, currency,
927
+ key, reference }`). `request.key` is the same for every try of one response's
928
+ payment: the provider's idempotency key. A send that failed after paying is
929
+ sent again without paying twice. `form.joined('pay')?.due()` says what is due
930
+ now, `state.paid` what was taken. A new payment in the designer asks 100 USD
931
+ until its amount and currency are set. Fieldia holds no keys and no provider's code. The
932
+ memory source answers paid unless its `pay` option says otherwise.
933
+
934
+ ## Sends kept without signal
935
+
936
+ A page with `"outbox": true` keeps a send that finds no network — a site
937
+ visit's report in a compound, a delivery's proof — on the device and sends it
938
+ when the signal comes back. The form goes on as though it went: a response ends
939
+ "Kept on this device" (`state.outbox.kept`), and `state.outbox` says how many
940
+ wait (`{ waiting, sending, offline, kept, refused }`). The items are kept in the browser's
941
+ IndexedDB (`indexedOutbox()`: never lost on a reload, shared by a site's tabs),
942
+ or the store given as `outbox` (`memoryOutbox()` for tests). A photo the network
943
+ could not take stays in its field as its bytes and is stored through `upload`
944
+ just before its send goes. `form.joined('outbox')` sends what waits in order —
945
+ each item claimed by one sender, sent with `queued: { key, at }` so a server
946
+ can refuse a second try — and keeps a refusal to `retry` or `discard`. Kept sends
947
+ go in the order they were kept; a send made once the signal is back goes first,
948
+ and what waited goes right after it. A new record
949
+ saved twice without signal is saved once, and the form takes its id when it
950
+ went. The memory source's `offline` option fails as a network does.
951
+
952
+ ## Parts that join a form
953
+
954
+ The four above are parts of their own, asked for as a page needs them
955
+ (`formJoins(page)`): the form knows only that its page asks for one, and each
956
+ joins it by one hook into its send (`FormJoin`) — `before` the send, once the
957
+ form's own checks ran (a field not proved added to what they found; a payment
958
+ not taken, nothing sent), `around` the send itself (what it carries added, or
959
+ kept on the device), and `reset` as another response or record starts. Their
960
+ state, their words and their checks come with them. `form.joined(name)` is a
961
+ part's side of the form once it came — null before, and on a page that asks for
962
+ none; a send made before it came waits for it.
963
+
689
964
  ## What a page's records are called
690
965
 
691
966
  A page may say what its records are, so Fieldia's own sentences name them as
@@ -737,6 +1012,61 @@ plain, locale)` says one. A language, or an app's own `messages`, that has no
737
1012
  such sentence says its plain one: a page that names no records reads as before.
738
1013
  `checkPage` and `validatePage` refuse a word for one or for more left out.
739
1014
 
1015
+ ## Undo and Redo while filling
1016
+
1017
+ A form keeps the person's changes to the record shown, for `form.undo()` and
1018
+ `form.redo()` (the viewer's Ctrl+Z and Ctrl+Shift+Z): each field written
1019
+ (`setValue`), each cell typed in (`updateLine`), each line added, taken away or
1020
+ moved — typing on in one box is one change until the box is left
1021
+ (`boxLeft`). Each returns what it took (`{ field, line? }`), or null when
1022
+ nothing is left; `form.history()` names the next of each without taking it.
1023
+ The changes are noted from the first; walking them is the undo part's
1024
+ (`pressUndoPart`), asked for with the first change — in by the time a person
1025
+ presses Ctrl+Z, and in at once where an app loads it first (`await
1026
+ pressUndoPart.load()`): until it has come, `undo` and `redo` take nothing.
1027
+
1028
+ ```ts
1029
+ form.setValue('price', 1200);
1030
+ form.boxLeft('price');
1031
+ form.undo(); // { field: 'price' }: back to what it held, as the person's own change back
1032
+ form.redo(); // { field: 'price' }: 1200 again
1033
+ ```
1034
+
1035
+ What it writes is the person's own change back: the page's `change` steps and
1036
+ the source's onchange run as for any, and what is worked out from it follows. A
1037
+ step's, a rule's or the app's writes are never a change to take back, and a
1038
+ change whose field one of them wrote since — or that is locked now — is passed
1039
+ over, never written over theirs. Another record shown, a reload, or `reset()`
1040
+ starts with nothing to take back; a form not being edited takes nothing back.
1041
+
1042
+ ## Changes pushed as they happen, and who else is here
1043
+
1044
+ Two optional data source members make an open record live. `subscribe(record,
1045
+ push) → stop` is asked as a record is shown and stopped as another is; push
1046
+ `{ type: 'record', version?, values?, by?, at? }` as someone else saves it, or
1047
+ `{ type: 'deleted', by? }`. Where the person changed nothing, their values are
1048
+ laid on the record as stored (`arrived` is told, `conflict: false`); after a
1049
+ change of theirs it waits as the conflict a save would meet (`state.conflict`,
1050
+ with Reload and Keep mine), their typing untouched. A change without `values`
1051
+ is read with `load`; one carrying this form's own version is let go.
1052
+ `presence(request, push) → stop` is asked with the form's `user` and whether
1053
+ they have changes not saved (`editing`), asked again as that turns; what it
1054
+ pushes — the others with the record open — is `state.present`. Both are the
1055
+ same call as @fieldia/chatter's `subscribe`, with types that never meet: one
1056
+ function may serve both. It comes in a part of its own (`recordLivePart`),
1057
+ asked for as a form is made where the source has either member, and never
1058
+ where it has neither. The memory source does both with `live: true`
1059
+ (`changeElsewhere`, `arrive`, `leave`), and has none of them without.
1060
+
1061
+ ## Record templates
1062
+
1063
+ A record page's `templates` (`true`, or `{ fields }`) keeps a record's values
1064
+ by a name, to start new records from. The data source's `templates`,
1065
+ `saveTemplate` and `deleteTemplate` keep them on your server
1066
+ (`RecordTemplate`: `{ id, name, values, by? }`); the viewer keeps them in its
1067
+ `preferences` without them. The memory source has them where its `templates`
1068
+ option is given (`{}` for none yet), kept by page id.
1069
+
740
1070
  ## Two people, one record
741
1071
 
742
1072
  A source that keeps versions returns each record with its version, and what this
@@ -1019,6 +1349,37 @@ onAction: async ({ action, values }) => {
1019
1349
  warning. Nothing answered means go on: an `onAction` that returns nothing
1020
1350
  works as it always did.
1021
1351
 
1352
+ ### Undo after a one-tap press
1353
+
1354
+ A button or a gear menu item with `"undo": true` offers Undo in place of
1355
+ asking first: once its press has run whole, the words it said — its last `say`,
1356
+ or the app's — are given to the host's `say` with a third argument, `{ undo }`
1357
+ (else "Done: {label}", the built-in Archive's "Archived."); the words before
1358
+ them are said plainly. `undo()` takes the press back and resolves to a
1359
+ `RunResult`: the app's own undos (an answer's `undo`, latest first, each
1360
+ answered as a call is), the record archived brought back (or the reverse), and
1361
+ the values its steps and answers wrote put back — each only while it holds what
1362
+ they left — saved again where the press saved. It is offered only where all of
1363
+ it can be taken back: a copy, a delete, a post, a page opened, an address, a
1364
+ form put back or closed, or a call answered without `undo` say plainly. Steps in
1365
+ place of `true` are what Undo runs instead. A call's answer with `undo` offers it
1366
+ by itself, for what the app did:
1367
+
1368
+ ```ts
1369
+ onAction: async ({ action, recordId }) => {
1370
+ if (action === 'mark_done') {
1371
+ await api.done(recordId);
1372
+ return { say: { message: 'Follow-up marked done', tone: 'success' }, undo: () => api.reopen(recordId).then(() => ({ reload: true })) };
1373
+ }
1374
+ },
1375
+ ```
1376
+
1377
+ Undo's run is told as `run` with the press's id and `.undo` after it
1378
+ (`b-done.undo`); a built-in Archive or Delete with `undo` asks nothing first
1379
+ unless it says `confirm`. Saying it with Undo and taking it back come in a part
1380
+ of their own (`pressUndoPart`, `fieldia.undo.js`): asked for with a page whose
1381
+ buttons offer Undo, else as an answer first brings one.
1382
+
1022
1383
  ### The moments
1023
1384
 
1024
1385
  - `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.0",
3
+ "version": "0.31.0",
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",