@fieldia/core 0.29.0 → 0.30.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 (97) hide show
  1. package/README.md +1 -1
  2. package/package.json +1 -1
  3. package/schema/page.schema.json +17 -1
  4. package/src/lib/format/head-checks.d.mts +10 -2
  5. package/src/lib/format/head-checks.d.ts +10 -2
  6. package/src/lib/format/head-checks.js +9 -2
  7. package/src/lib/format/head-checks.js.map +1 -1
  8. package/src/lib/format/head-checks.mjs +10 -4
  9. package/src/lib/format/head-checks.mjs.map +1 -1
  10. package/src/lib/format/layout.d.mts +29 -0
  11. package/src/lib/format/layout.d.ts +29 -0
  12. package/src/lib/format/layout.js +5 -0
  13. package/src/lib/format/layout.js.map +1 -1
  14. package/src/lib/format/layout.mjs +5 -0
  15. package/src/lib/format/layout.mjs.map +1 -1
  16. package/src/lib/format/page.d.mts +5 -1
  17. package/src/lib/format/page.d.ts +5 -1
  18. package/src/lib/format/references.d.mts +3 -1
  19. package/src/lib/format/references.d.ts +3 -1
  20. package/src/lib/format/references.js +10 -13
  21. package/src/lib/format/references.js.map +1 -1
  22. package/src/lib/format/references.mjs +11 -14
  23. package/src/lib/format/references.mjs.map +1 -1
  24. package/src/lib/format/sheet-head-checks.d.mts +10 -2
  25. package/src/lib/format/sheet-head-checks.d.ts +10 -2
  26. package/src/lib/format/sheet-head-checks.js +24 -0
  27. package/src/lib/format/sheet-head-checks.js.map +1 -1
  28. package/src/lib/format/sheet-head-checks.mjs +23 -0
  29. package/src/lib/format/sheet-head-checks.mjs.map +1 -1
  30. package/src/lib/format/upgrade.d.mts +3 -1
  31. package/src/lib/format/upgrade.d.ts +3 -1
  32. package/src/lib/format/upgrade.js +3 -1
  33. package/src/lib/format/upgrade.js.map +1 -1
  34. package/src/lib/format/upgrade.mjs +3 -1
  35. package/src/lib/format/upgrade.mjs.map +1 -1
  36. package/src/lib/format/version.d.mts +2 -2
  37. package/src/lib/format/version.d.ts +2 -2
  38. package/src/lib/format/version.js +2 -2
  39. package/src/lib/format/version.js.map +1 -1
  40. package/src/lib/format/version.mjs +2 -2
  41. package/src/lib/format/version.mjs.map +1 -1
  42. package/src/lib/record/data-source.d.mts +6 -3
  43. package/src/lib/record/data-source.d.ts +6 -3
  44. package/src/lib/record/data-source.js.map +1 -1
  45. package/src/lib/record/data-source.mjs.map +1 -1
  46. package/src/lib/record/form-approvals.js +1 -1
  47. package/src/lib/record/form-approvals.js.map +1 -1
  48. package/src/lib/record/form-approvals.mjs +1 -1
  49. package/src/lib/record/form-approvals.mjs.map +1 -1
  50. package/src/lib/record/form.d.mts +10 -4
  51. package/src/lib/record/form.d.ts +10 -4
  52. package/src/lib/record/form.js +26 -22
  53. package/src/lib/record/form.js.map +1 -1
  54. package/src/lib/record/form.mjs +26 -22
  55. package/src/lib/record/form.mjs.map +1 -1
  56. package/src/lib/record/locales/ar.js +3 -1
  57. package/src/lib/record/locales/ar.js.map +1 -1
  58. package/src/lib/record/locales/ar.mjs +3 -1
  59. package/src/lib/record/locales/ar.mjs.map +1 -1
  60. package/src/lib/record/locales/de.js +3 -1
  61. package/src/lib/record/locales/de.js.map +1 -1
  62. package/src/lib/record/locales/de.mjs +3 -1
  63. package/src/lib/record/locales/de.mjs.map +1 -1
  64. package/src/lib/record/locales/fr.js +3 -1
  65. package/src/lib/record/locales/fr.js.map +1 -1
  66. package/src/lib/record/locales/fr.mjs +3 -1
  67. package/src/lib/record/locales/fr.mjs.map +1 -1
  68. package/src/lib/record/memory-approvals.d.mts +7 -4
  69. package/src/lib/record/memory-approvals.d.ts +7 -4
  70. package/src/lib/record/memory-approvals.js +54 -7
  71. package/src/lib/record/memory-approvals.js.map +1 -1
  72. package/src/lib/record/memory-approvals.mjs +54 -7
  73. package/src/lib/record/memory-approvals.mjs.map +1 -1
  74. package/src/lib/record/memory-assist.d.mts +7 -2
  75. package/src/lib/record/memory-assist.d.ts +7 -2
  76. package/src/lib/record/memory-assist.js +47 -12
  77. package/src/lib/record/memory-assist.js.map +1 -1
  78. package/src/lib/record/memory-assist.mjs +46 -12
  79. package/src/lib/record/memory-assist.mjs.map +1 -1
  80. package/src/lib/record/memory-data-source.d.mts +4 -2
  81. package/src/lib/record/memory-data-source.d.ts +4 -2
  82. package/src/lib/record/memory-data-source.js +2 -0
  83. package/src/lib/record/memory-data-source.js.map +1 -1
  84. package/src/lib/record/memory-data-source.mjs +2 -0
  85. package/src/lib/record/memory-data-source.mjs.map +1 -1
  86. package/src/lib/record/messages.d.mts +3 -0
  87. package/src/lib/record/messages.d.ts +3 -0
  88. package/src/lib/record/messages.js +3 -1
  89. package/src/lib/record/messages.js.map +1 -1
  90. package/src/lib/record/messages.mjs +3 -1
  91. package/src/lib/record/messages.mjs.map +1 -1
  92. package/src/lib/record/run.d.mts +23 -7
  93. package/src/lib/record/run.d.ts +23 -7
  94. package/src/lib/record/run.js +10 -7
  95. package/src/lib/record/run.js.map +1 -1
  96. package/src/lib/record/run.mjs +10 -7
  97. package/src/lib/record/run.mjs.map +1 -1
@@ -1857,8 +1857,8 @@ function innerForm(options, within, place, outer) {
1857
1857
  }
1858
1858
  return shown;
1859
1859
  }
1860
- async function save(chain = []) {
1861
- return (await saving(chain)) === null;
1860
+ async function save(chain = [], yes) {
1861
+ return (await saving(chain, yes)) === null;
1862
1862
  }
1863
1863
  /** Every value, for a source that saves whole records: those of fields hidden from the person, which they never had, left out. */
1864
1864
  function sentValues() {
@@ -1887,14 +1887,14 @@ function innerForm(options, within, place, outer) {
1887
1887
  * save with the version the first got back, never as someone else's. A save
1888
1888
  * the page's own beforeSave steps ask for runs inside the one that set them off.
1889
1889
  */
1890
- function saving(chain) {
1890
+ function saving(chain, yes) {
1891
1891
  if (chain.includes('on.beforeSave'))
1892
- return savingNow(chain);
1892
+ return savingNow(chain, yes);
1893
1893
  const before = saveRunning;
1894
1894
  const mine = (async () => {
1895
1895
  if (before)
1896
1896
  await before;
1897
- return savingNow(chain);
1897
+ return savingNow(chain, yes);
1898
1898
  })();
1899
1899
  const done = mine.then(() => undefined, () => undefined);
1900
1900
  saveRunning = done;
@@ -1904,7 +1904,7 @@ function innerForm(options, within, place, outer) {
1904
1904
  });
1905
1905
  return mine;
1906
1906
  }
1907
- async function savingNow(chain) {
1907
+ async function savingNow(chain, yes) {
1908
1908
  // A record its source does not let this person change is refused here, in its words or the form's: no source is asked.
1909
1909
  if (page.data.kind === 'record' && state.can?.edit === false) {
1910
1910
  const problem = { kind: 'rule', message: state.can.reason ?? named(messages.mayNotEditNoun, messages.mayNotEdit) };
@@ -1952,7 +1952,8 @@ function innerForm(options, within, place, outer) {
1952
1952
  if (page.on?.beforeSave) {
1953
1953
  // Its run stops of itself on a record shown by anything but its own steps (a `call`'s `{ record }`, a reload):
1954
1954
  // those move the save on with it.
1955
- const before = await moment('on.beforeSave', page.on.beforeSave, chain, false);
1955
+ // Its questions' Yes goes on with what set the save off: its words (Submit, a button's).
1956
+ const before = await moment('on.beforeSave', page.on.beforeSave, chain, false, yes);
1956
1957
  if (!before.done) {
1957
1958
  // A check's problems, or an inner save's, are shown already; any other stop is this save's problem.
1958
1959
  if (before.reason !== 'check' && before.reason !== 'save') {
@@ -2668,7 +2669,7 @@ function innerForm(options, within, place, outer) {
2668
2669
  });
2669
2670
  // A moment's run is on the record it was set off on: one set off again while its run goes, and run after it, is let
2670
2671
  // go when another record is shown by then (its steps were for that one).
2671
- const moment = createMoments((key, list, chain, on) => runTop(list, { id: key, chain, generation: on }), () => generation);
2672
+ const moment = createMoments((key, list, chain, on, yes) => runTop(list, { id: key, chain, generation: on, yes }), () => generation);
2672
2673
  /**
2673
2674
  * Whether steps do something before their first save — set a status, call the app, open a page — so a record's
2674
2675
  * button made of them saves first. Steps that start with the save (Save and close), or only check before it, need
@@ -2694,12 +2695,14 @@ function innerForm(options, within, place, outer) {
2694
2695
  list.push({ do: builtin });
2695
2696
  const asked = builtin === 'archive' ? named(messages.archiveConfirmNoun, messages.archiveConfirm) : builtin === 'delete' ? named(messages.deleteConfirmNoun, messages.deleteConfirm) : undefined;
2696
2697
  const confirm = 'confirm' in source && source.confirm !== undefined ? source.confirm : asked;
2698
+ // Its question's Yes, and its ask steps', say what it does: its own words, else Archive or Delete.
2699
+ scope.yes ??= source.label || (builtin === 'archive' ? messages.archiveYes : builtin === 'delete' ? messages.deleteYes : undefined);
2697
2700
  // On the record it was pressed on: another shown while its question is asked, it does nothing to that one.
2698
2701
  scope.generation ??= generation;
2699
2702
  // Pressed by the person: what is typed is read before a step reads the form or hands its values on.
2700
2703
  scope.typed ??= 'first';
2701
2704
  return track((async () => {
2702
- if (confirm && !(await runner.ask(confirm))) {
2705
+ if (confirm && !(await runner.ask(confirm, scope.yes))) {
2703
2706
  const result = { done: false, reason: 'no', message: confirm };
2704
2707
  emit('run', { id: scope.id, steps: list, result });
2705
2708
  return result;
@@ -2718,7 +2721,7 @@ function innerForm(options, within, place, outer) {
2718
2721
  }
2719
2722
  // Then the save first, then the steps.
2720
2723
  if (saveFirst && (state.recordId == null || state.dirty.length > 0 || Object.keys(state.unread ?? {}).length > 0 || state.uploads.some(uploadGoing))) {
2721
- const first = await saving(scope.chain);
2724
+ const first = await saving(scope.chain, scope.yes);
2722
2725
  if (first) {
2723
2726
  const result = { done: false, step: { do: 'save' }, reason: first.reason, ...(first.message !== undefined ? { message: first.message } : {}), ...(first.error !== undefined ? { error: first.error } : {}) };
2724
2727
  emit('run', { id: scope.id, steps: list, result });
@@ -2885,7 +2888,7 @@ function innerForm(options, within, place, outer) {
2885
2888
  set({ errors });
2886
2889
  return Object.keys(errors).length === 0;
2887
2890
  },
2888
- save: () => track(save()),
2891
+ save: (how) => track(save([], how?.yes)),
2889
2892
  canUpload: () => typeof options.dataSource?.upload === 'function',
2890
2893
  today,
2891
2894
  now: () => options.now?.() ?? new Date(),
@@ -3239,7 +3242,7 @@ function innerForm(options, within, place, outer) {
3239
3242
  lines: { field: source.field, keys: [...keys], ids: lines.flatMap((line) => (line.id === undefined ? [] : [line.id])), values: lines.map((line) => structuredCopy(line.values)) },
3240
3243
  });
3241
3244
  },
3242
- run: (list, context = {}) => track(runTop(list, { id: context.id ?? 'run', chain: [], typed: 'first', ...(context.recordIds ? { recordIds: [...context.recordIds] } : {}) })),
3245
+ run: (list, context = {}) => track(runTop(list, { id: context.id ?? 'run', chain: [], typed: 'first', ...(context.recordIds ? { recordIds: [...context.recordIds] } : {}), yes: context.yes })),
3243
3246
  shown(tab) {
3244
3247
  // A wizard's steps are told by the form itself, as they are entered.
3245
3248
  if (steps.includes(tab))
@@ -3640,7 +3643,14 @@ function indexLayout(root, functions) {
3640
3643
  ...(does.length ? { does } : {}),
3641
3644
  source,
3642
3645
  });
3643
- // A button's menu: each item a button of the record, hidden with it.
3646
+ // A menu's built-in Archive shows while the record is active, Unarchive while it is not.
3647
+ const builtin = source.builtin;
3648
+ if (builtin === 'archive' || builtin === 'unarchive') {
3649
+ const own = index.get(source.id);
3650
+ const mine = own.invisible;
3651
+ own.invisible = { ...mine, evaluate: (context, env) => (context['active'] === false) !== (builtin === 'unarchive') || mine.evaluate(context, env) };
3652
+ }
3653
+ // A button's menu, and a menu inside a menu: each item a button of the record, hidden with it.
3644
3654
  if (kind === 'button')
3645
3655
  for (const item of source.menu ?? [])
3646
3656
  add(item, source.id, 'button', { invisible: item.invisible });
@@ -3749,16 +3759,10 @@ function indexLayout(root, functions) {
3749
3759
  walk(head?.band?.children ?? [], root.id);
3750
3760
  if (root.sidePanel)
3751
3761
  add(root.sidePanel, root.id, 'other', { invisible: root.sidePanel.invisible });
3752
- // The gear menu's items are buttons of the record; Archive shows while it is active, Unarchive while it is not.
3753
- for (const item of root.toolbar?.menu ?? []) {
3762
+ // The gear menu's items are buttons of the record — those of a menu inside it too, hidden with the item that opens
3763
+ // it (add's own); Archive shows while it is active, Unarchive while it is not.
3764
+ for (const item of root.toolbar?.menu ?? [])
3754
3765
  add(item, root.id, 'button', { invisible: item.invisible });
3755
- if (item.builtin === 'archive' || item.builtin === 'unarchive') {
3756
- const own = index.get(item.id);
3757
- const mine = own.invisible;
3758
- const archived = item.builtin === 'unarchive';
3759
- own.invisible = { ...mine, evaluate: (context, env) => (context['active'] === false) !== archived || mine.evaluate(context, env) };
3760
- }
3761
- }
3762
3766
  if (root.attachmentPreview)
3763
3767
  add({ id: '#preview', ...root.attachmentPreview }, root.id, 'other', { invisible: root.attachmentPreview.invisible });
3764
3768
  }