@wssto2/vue-core 0.12.0 → 0.13.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 (122) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/README.md +4 -2
  3. package/dist/{AccessGate.vue_vue_type_script_setup_true_lang-CzQbD2Pc.js → AccessGate.vue_vue_type_script_setup_true_lang-DEzXovsY.js} +1 -1
  4. package/dist/{Activity-CdkJW68R.js → Activity-ChfxdvXf.js} +24 -23
  5. package/dist/{AdaptivePageShell.vue_vue_type_script_setup_true_lang-D5i77H6S.js → AdaptivePageShell.vue_vue_type_script_setup_true_lang-lPj9hPqV.js} +33 -33
  6. package/dist/{Changes-DxK_QfiB.js → Changes-BCa43_mO.js} +18 -17
  7. package/dist/{CollectionPage.vue_vue_type_script_setup_true_lang-x0jyJ01f.js → CollectionPage.vue_vue_type_script_setup_true_lang-C1GCvyZx.js} +6 -6
  8. package/dist/{DataTable.vue_vue_type_script_setup_true_lang-C_ZytnW-.js → DataTable.vue_vue_type_script_setup_true_lang-B9r9M5Gt.js} +1 -1
  9. package/dist/{DateField.vue_vue_type_script_setup_true_lang-CeNwBbJT.js → DateField.vue_vue_type_script_setup_true_lang-B5UUY1OO.js} +2 -2
  10. package/dist/{DeadLetters-DnA7LP1w.js → DeadLetters-wFTqhISU.js} +5 -5
  11. package/dist/{General-2matxl2Y.js → General-jW7u4MjH.js} +16 -15
  12. package/dist/{IncidentRecord-Bt3G4HlX.js → IncidentRecord-CXzgLKqI.js} +6 -6
  13. package/dist/{IncidentsList-2iwgqp9J.js → IncidentsList-D1MySyXb.js} +6 -6
  14. package/dist/{NewRolePage-DhGFwvk3.js → NewRolePage-CQ5UVaHs.js} +3 -3
  15. package/dist/{NumberField.vue_vue_type_script_setup_true_lang-B3UrXNqH.js → NumberField.vue_vue_type_script_setup_true_lang-YVgf5CP6.js} +1 -1
  16. package/dist/{PersonAccess.vue_vue_type_script_setup_true_lang-DbGZSNQc.js → PersonAccess.vue_vue_type_script_setup_true_lang-CWCt9_dM.js} +2 -2
  17. package/dist/{ProfilePage-CpuyDBAv.js → ProfilePage-Ca3x3UAH.js} +79 -77
  18. package/dist/{RecordHeader.vue_vue_type_script_setup_true_lang-DqGc3Jyo.js → RecordHeader.vue_vue_type_script_setup_true_lang-Do_ATJwT.js} +1 -1
  19. package/dist/{ResourcePage.vue_vue_type_script_setup_true_lang-DljhsTU4.js → ResourcePage.vue_vue_type_script_setup_true_lang-Coz91xht.js} +1 -1
  20. package/dist/{RoleEditor.vue_vue_type_script_setup_true_lang-C0FIotFA.js → RoleEditor.vue_vue_type_script_setup_true_lang-d_aaeXTT.js} +2 -2
  21. package/dist/{RolePage-DaNv049g.js → RolePage-BUj1w1m1.js} +5 -5
  22. package/dist/{RolesPage-6hlzJes_.js → RolesPage-NKzBUsrM.js} +3 -3
  23. package/dist/{SectionNavigator.vue_vue_type_script_setup_true_lang-Dh3sXUt_.js → SectionNavigator.vue_vue_type_script_setup_true_lang-DfKEhTFv.js} +2 -2
  24. package/dist/{ServiceAccountDialog.vue_vue_type_script_setup_true_lang-FJbWxME_.js → ServiceAccountDialog.vue_vue_type_script_setup_true_lang-4nbhEpv_.js} +10 -9
  25. package/dist/{ServiceAccountRecord-0-JF5lRx.js → ServiceAccountRecord-ClbyeLhL.js} +8 -8
  26. package/dist/{ServiceAccountsList-DcsnOcf-.js → ServiceAccountsList-B2VDnYxD.js} +5 -5
  27. package/dist/{Sessions-DgWhpk-i.js → Sessions-BjkciyHH.js} +23 -21
  28. package/dist/{SettingsPage-BXPWATYU.js → SettingsPage-Csb14qsx.js} +7 -7
  29. package/dist/{SignIn-DPoUwHZd.js → SignIn-DPFMv4C7.js} +14 -12
  30. package/dist/{SignInPage-OyrVemro.js → SignInPage-DukoFqkt.js} +2 -2
  31. package/dist/{SignIns-BMDrZVVp.js → SignIns-DvdpNkiS.js} +23 -22
  32. package/dist/{TimeField.vue_vue_type_script_setup_true_lang-D-Em4glH.js → TimeField.vue_vue_type_script_setup_true_lang-DpDXHH7u.js} +2 -2
  33. package/dist/{Timestamp.vue_vue_type_script_setup_true_lang-ClZAAUMd.js → Timestamp.vue_vue_type_script_setup_true_lang-DlEUKWra.js} +1 -1
  34. package/dist/{UserRecord-BW-gdCqi.js → UserRecord-B9SeSWQh.js} +57 -55
  35. package/dist/{UsersList-B3ZF_1Dj.js → UsersList-CREG8q3l.js} +4 -4
  36. package/dist/access/index.js +4 -4
  37. package/dist/app/application.d.ts +14 -6
  38. package/dist/app/current.d.ts +11 -0
  39. package/dist/app/environment.d.ts +8 -0
  40. package/dist/app/index.d.ts +1 -0
  41. package/dist/app/index.js +14 -12
  42. package/dist/application-DomS6sbx.js +435 -0
  43. package/dist/collection/http.d.ts +16 -1
  44. package/dist/collection/index.d.ts +1 -1
  45. package/dist/collection/index.js +34 -32
  46. package/dist/content/Money.vue.d.ts +1 -1
  47. package/dist/content/index.js +151 -158
  48. package/dist/{contributions-CeG4bszd.js → contributions-obnyn03x.js} +1 -1
  49. package/dist/current-B0lHKTWr.js +17 -0
  50. package/dist/form/DateField.vue.d.ts +2 -2
  51. package/dist/form/DateTimeField.vue.d.ts +2 -2
  52. package/dist/form/MoneyField.vue.d.ts +1 -1
  53. package/dist/form/NumberField.vue.d.ts +1 -1
  54. package/dist/form/date/MonthYearPanel.vue.d.ts +1 -1
  55. package/dist/form/date/days.d.ts +3 -3
  56. package/dist/form/index.d.ts +2 -0
  57. package/dist/form/index.js +1111 -1081
  58. package/dist/form/zodErrorMap.d.ts +35 -0
  59. package/dist/format/format.d.ts +51 -6
  60. package/dist/format/index.d.ts +1 -1
  61. package/dist/format/index.js +1 -1
  62. package/dist/format-DoKs29bZ.js +118 -0
  63. package/dist/{guards-Biv_SlGn.js → guards-DGcSfTEh.js} +1 -1
  64. package/dist/http-DOEfFCDA.js +107 -0
  65. package/dist/i18n/index.js +15 -15
  66. package/dist/identity/index.d.ts +2 -0
  67. package/dist/identity/index.js +43 -40
  68. package/dist/identity/usePreferences.d.ts +19 -0
  69. package/dist/incidents/clientErrorReporter.d.ts +2 -1
  70. package/dist/incidents/index.js +1 -1
  71. package/dist/{index-kEHY7hcG.js → index-CRxU_Wh2.js} +61 -61
  72. package/dist/{index-Cq9TuOqH.js → index-DZikGJ8L.js} +457 -511
  73. package/dist/{index-ClJeyW3F.js → index-D_yyd4C2.js} +4 -4
  74. package/dist/index.d.ts +1 -1
  75. package/dist/index.js +1 -1
  76. package/dist/internal/intlLocale.d.ts +5 -2
  77. package/dist/modules/identity/entities.d.ts +7 -2
  78. package/dist/modules/identity/routes.d.ts +5 -2
  79. package/dist/modules/identity/schemas.d.ts +6 -2
  80. package/dist/{navigation-TnVFYRaX.js → navigation-CctcxT51.js} +1 -1
  81. package/dist/{neighbors-OyvGi233.js → neighbors-Csfan8Ho.js} +1 -1
  82. package/dist/notifications/index.js +1 -1
  83. package/dist/onboarding/Tip.vue.d.ts +41 -0
  84. package/dist/onboarding/index.d.ts +1 -0
  85. package/dist/onboarding/index.js +145 -0
  86. package/dist/onboarding/tips.d.ts +5 -0
  87. package/dist/page/index.js +3 -3
  88. package/dist/phone/index.js +74 -74
  89. package/dist/phone/phone.d.ts +3 -3
  90. package/dist/platform/httpSession.d.ts +1 -1
  91. package/dist/platform/index.d.ts +2 -0
  92. package/dist/platform/index.js +16 -13
  93. package/dist/platform/preferences.d.ts +35 -0
  94. package/dist/platform/session.d.ts +6 -1
  95. package/dist/platform-DtISOEt7.js +284 -0
  96. package/dist/playwright/session.d.ts +7 -11
  97. package/dist/preferences-hYhrw8Uy.js +91 -0
  98. package/dist/resource/index.d.ts +1 -0
  99. package/dist/resource/index.js +24 -8
  100. package/dist/resource/read.d.ts +16 -0
  101. package/dist/router/index.js +3 -3
  102. package/dist/{rowLayout-BsKEzEME.js → rowLayout-y1IB_h2r.js} +2 -2
  103. package/dist/{sections-CvUwZ-S1.js → sections-fkW_IJLc.js} +1 -1
  104. package/dist/{serverMessages-B6GHgi40.js → serverMessages-Ddghrewh.js} +1 -1
  105. package/dist/shell/darkMode.d.ts +13 -8
  106. package/dist/shell/index.js +396 -384
  107. package/dist/{state-6KSYsVw0.js → state-CXMexi0l.js} +1 -1
  108. package/dist/styles.css +1 -1
  109. package/dist/testing/app.d.ts +11 -0
  110. package/dist/testing/format.d.ts +4 -2
  111. package/dist/testing/index.d.ts +1 -1
  112. package/dist/testing/index.js +96 -89
  113. package/dist/testing/platform.d.ts +2 -0
  114. package/dist/usePreferences-B8LIZp_f.js +47 -0
  115. package/dist/{useTypedEntry-C_Bk4sI0.js → useTypedEntry-DKs8I1yP.js} +279 -280
  116. package/package.json +6 -2
  117. package/src/styles/components.css +17 -0
  118. package/dist/application-CuzT-0vW.js +0 -420
  119. package/dist/format-D8KUBmbS.js +0 -87
  120. package/dist/http-Dm0uXY9O.js +0 -95
  121. package/dist/intlLocale-CeRU44qJ.js +0 -4
  122. package/dist/platform-BQOX_Ntw.js +0 -283
@@ -1,21 +1,21 @@
1
- import { defineComponent as fe, useModel as me, useTemplateRef as F, ref as E, computed as g, watch as ne, nextTick as A, openBlock as w, createElementBlock as $, createElementVNode as f, normalizeClass as P, unref as s, createVNode as M, toDisplayString as T, normalizeStyle as xe, Fragment as ee, renderList as le, createCommentVNode as J, withModifiers as we, withDirectives as _e, vModelText as ke, mergeModels as ae, inject as Ce, shallowRef as $e, onBeforeUnmount as De, createBlock as Me, mergeProps as Te, createSlots as Se, withCtx as ie, createTextVNode as Ne, renderSlot as Ie, mergeDefaults as Pe } from "vue";
1
+ import { defineComponent as fe, useModel as me, useTemplateRef as F, ref as E, computed as g, watch as ne, nextTick as q, openBlock as w, createElementBlock as $, createElementVNode as f, normalizeClass as P, unref as i, createVNode as M, toDisplayString as T, normalizeStyle as xe, Fragment as ee, renderList as le, createCommentVNode as J, withModifiers as we, withDirectives as _e, vModelText as ke, mergeModels as ae, inject as Ce, shallowRef as $e, onBeforeUnmount as De, createBlock as Me, mergeProps as Te, createSlots as Se, withCtx as se, createTextVNode as Ne, renderSlot as Ie, mergeDefaults as Pe } from "vue";
2
2
  import { useI18n as pe } from "vue-i18n";
3
+ import { u as ve } from "../format-DoKs29bZ.js";
3
4
  import { b as Ve } from "../controlSurface-t7OEFESJ.js";
4
- import { c as se, a as Oe, e as Re, _ as Be, f as Ee, b as ze } from "../options-B48UiYsG.js";
5
- import { _ as q } from "../Icon.vue_vue_type_script_lang-BhhsFYwp.js";
5
+ import { c as ie, a as Oe, e as Re, _ as Be, f as Ee, b as Le } from "../options-B48UiYsG.js";
6
+ import { _ as z } from "../Icon.vue_vue_type_script_lang-BhhsFYwp.js";
6
7
  import { _ as ue } from "../CountryFlag.vue_vue_type_script_setup_true_lang-Kry_vPPZ.js";
7
8
  import { u as Fe } from "../anchored-DpuUwf-9.js";
8
- import { i as ve } from "../intlLocale-CeRU44qJ.js";
9
- import { AsYouType as L, validatePhoneNumberLength as qe, parsePhoneNumberFromString as he, getCountries as Ae, getCountryCallingCode as Le } from "libphonenumber-js/max";
9
+ import { AsYouType as A, validatePhoneNumberLength as ze, parsePhoneNumberFromString as he, getCountries as qe, getCountryCallingCode as Ae } from "libphonenumber-js/max";
10
10
  import We from "libphonenumber-js/max/metadata";
11
11
  const ce = ["HR", "BA", "SI", "RS"], Ke = 15;
12
12
  function ye(t) {
13
13
  return We.country_calling_codes[t]?.[0];
14
14
  }
15
- const W = (t) => Le(t), de = (t) => `+${W(t)}`, te = () => Ae();
15
+ const W = (t) => Ae(t), de = (t) => `+${W(t)}`, te = () => qe();
16
16
  function Ue(t, a) {
17
17
  const o = `+${t}`;
18
- return new L().input(`${o}${a}`).slice(o.length).trim();
18
+ return new A().input(`${o}${a}`).slice(o.length).trim();
19
19
  }
20
20
  function re(t, a, o) {
21
21
  const r = o.slice(0, Math.max(0, Ke - a.length));
@@ -24,21 +24,21 @@ function re(t, a, o) {
24
24
  function oe(t, a) {
25
25
  const o = t.trim().replace(/^00(?=\d)/, "+");
26
26
  if (o.startsWith("+")) {
27
- const l = new L();
27
+ const l = new A();
28
28
  l.input(o);
29
29
  const x = l.getCallingCode();
30
30
  if (!x) return { country: a, e164: "", text: o.replace(/[^\d+]/g, "") };
31
31
  const p = l.getCountry() ?? (W(a) === x ? a : ye(x) ?? a);
32
32
  return re(p, x, l.getNumber()?.nationalNumber ?? "");
33
33
  }
34
- const r = new L(a);
34
+ const r = new A(a);
35
35
  return r.input(o.replace(/\D/g, "")), re(a, W(a), r.getNumber()?.nationalNumber ?? "");
36
36
  }
37
37
  function je(t, a) {
38
38
  return re(a, W(a), t.text.replace(/\D/g, ""));
39
39
  }
40
40
  function He(t) {
41
- return t.startsWith("+") ? new L().input(t) : t;
41
+ return t.startsWith("+") ? new A().input(t) : t;
42
42
  }
43
43
  const Ge = { MOBILE: "mobile", FIXED_LINE: "landline", TOLL_FREE: "toll_free", PREMIUM_RATE: "premium_rate", VOIP: "voip" };
44
44
  function Xe(t) {
@@ -46,28 +46,28 @@ function Xe(t) {
46
46
  return o ? Ge[o] : void 0;
47
47
  }
48
48
  function Ye(t) {
49
- const a = new L();
49
+ const a = new A();
50
50
  a.input(t);
51
51
  const o = a.getCallingCode();
52
52
  return a.getCountry() ?? (o ? ye(o) : void 0);
53
53
  }
54
54
  function be(t) {
55
55
  if (t === "") return null;
56
- const a = Ye(t), o = qe(t);
56
+ const a = Ye(t), o = ze(t);
57
57
  return o === "TOO_SHORT" ? { kind: "too_short", country: a } : o === "TOO_LONG" ? { kind: "too_long", country: a } : o !== void 0 ? { kind: "invalid", country: a } : he(t)?.isValid() ? null : { kind: "invalid", country: a };
58
58
  }
59
59
  const Dt = (t) => be(t) === null;
60
60
  function ge(t, a) {
61
61
  try {
62
- return new Intl.DisplayNames([ve(a)], { type: "region" }).of(t) ?? t;
62
+ return new Intl.DisplayNames([a], { type: "region" }).of(t) ?? t;
63
63
  } catch {
64
64
  return t;
65
65
  }
66
66
  }
67
67
  function Je(t, a, o) {
68
- const r = se(t.trim());
68
+ const r = ie(t.trim());
69
69
  if (r === "") return o;
70
- const l = r.replace(/\D/g, ""), x = new Intl.DisplayNames([ve(a)], { type: "region" }), p = (h) => se(x.of(h) ?? h), _ = r.startsWith("+") || /^\d+$/.test(r);
70
+ const l = r.replace(/\D/g, ""), x = new Intl.DisplayNames([a], { type: "region" }), p = (h) => ie(x.of(h) ?? h), _ = r.startsWith("+") || /^\d+$/.test(r);
71
71
  return o.filter((h) => _ ? W(h).startsWith(l) : p(h).includes(r) || h.toLowerCase() === r);
72
72
  }
73
73
  const Qe = ["id", "disabled", "aria-label", "aria-expanded"], Ze = { class: "tabular-nums" }, et = ["id", "aria-label"], tt = {
@@ -78,7 +78,7 @@ const Qe = ["id", "disabled", "aria-label", "aria-expanded"], Ze = { class: "tab
78
78
  key: 0,
79
79
  class: "px-3 py-2 text-footnote text-content-muted",
80
80
  role: "status"
81
- }, rt = { class: "border-t border-border-separator px-3 py-2" }, lt = ["aria-controls", "aria-activedescendant", "aria-label", "placeholder"], it = /* @__PURE__ */ fe({
81
+ }, rt = { class: "border-t border-border-separator px-3 py-2" }, lt = ["aria-controls", "aria-activedescendant", "aria-label", "placeholder"], st = /* @__PURE__ */ fe({
82
82
  __name: "CountryPicker",
83
83
  props: /* @__PURE__ */ ae({
84
84
  id: {},
@@ -91,29 +91,29 @@ const Qe = ["id", "disabled", "aria-label", "aria-expanded"], Ze = { class: "tab
91
91
  }),
92
92
  emits: /* @__PURE__ */ ae(["picked"], ["update:modelValue"]),
93
93
  setup(t, { expose: a, emit: o }) {
94
- const r = t, l = me(t, "modelValue"), x = o, { t: p, locale: _ } = pe(), h = F("root"), V = F("trigger"), k = F("panel"), K = F("search"), C = E(!1), v = E(""), d = E(0), O = g(() => {
94
+ const r = t, l = me(t, "modelValue"), x = o, { t: p } = pe(), _ = ve(), h = F("root"), V = F("trigger"), k = F("panel"), K = F("search"), C = E(!1), v = E(""), d = E(0), O = g(() => {
95
95
  const e = /* @__PURE__ */ new Map();
96
- for (const i of te()) e.set(i, ge(i, _.value));
96
+ for (const s of te()) e.set(s, ge(s, _.intlLocale));
97
97
  return e;
98
98
  }), S = (e) => O.value.get(e) ?? e, D = g(() => {
99
99
  const e = r.common.filter((c) => O.value.has(c));
100
100
  if (v.value.trim() !== "") {
101
- const c = Je(v.value, _.value, te());
101
+ const c = Je(v.value, _.intlLocale, te());
102
102
  return [{ title: null, countries: [...c.filter((n) => e.includes(n)), ...c.filter((n) => !e.includes(n))] }];
103
103
  }
104
- const i = te().filter((c) => !e.includes(c)).sort((c, n) => S(c).localeCompare(S(n), _.value));
105
- return [{ title: p("core.form.phone.common"), countries: e }, { title: p("core.form.phone.all"), countries: i }].filter((c) => c.countries.length > 0);
106
- }), y = g(() => D.value.flatMap((e) => e.countries)), z = g(() => D.value.map((e, i) => D.value.slice(0, i).reduce((c, n) => c + n.countries.length, 0))), U = (e) => `${r.id}-country-${e}`, { style: Q } = Fe(k, {
104
+ const s = te().filter((c) => !e.includes(c)).sort((c, n) => S(c).localeCompare(S(n), _.intlLocale));
105
+ return [{ title: p("core.form.phone.common"), countries: e }, { title: p("core.form.phone.all"), countries: s }].filter((c) => c.countries.length > 0);
106
+ }), y = g(() => D.value.flatMap((e) => e.countries)), L = g(() => D.value.map((e, s) => D.value.slice(0, s).reduce((c, n) => c + n.countries.length, 0))), U = (e) => `${r.id}-country-${e}`, { style: Q } = Fe(k, {
107
107
  reference: () => V.value,
108
108
  placement: () => "bottom-start",
109
109
  offset: 4,
110
110
  padding: 8,
111
- fit: (e, i) => {
112
- e.style.width = "min(20rem, calc(100vw - 1rem))", e.style.maxHeight = `${Math.max(200, Math.min(380, i.height))}px`;
111
+ fit: (e, s) => {
112
+ e.style.width = "min(20rem, calc(100vw - 1rem))", e.style.maxHeight = `${Math.max(200, Math.min(380, s.height))}px`;
113
113
  }
114
114
  });
115
115
  async function j() {
116
- r.disabled || C.value || (v.value = "", d.value = Math.max(0, y.value.indexOf(l.value)), C.value = !0, await A(), K.value?.focus());
116
+ r.disabled || C.value || (v.value = "", d.value = Math.max(0, y.value.indexOf(l.value)), C.value = !0, await q(), K.value?.focus());
117
117
  }
118
118
  function N(e) {
119
119
  C.value = !1, e && V.value?.focus();
@@ -121,7 +121,7 @@ const Qe = ["id", "disabled", "aria-label", "aria-expanded"], Ze = { class: "tab
121
121
  function R(e) {
122
122
  l.value = e, x("picked", e), N(!1);
123
123
  }
124
- ne(v, () => d.value = 0), ne(d, () => void A(() => k.value?.querySelector("[aria-selected='true']")?.scrollIntoView?.({ block: "nearest" })));
124
+ ne(v, () => d.value = 0), ne(d, () => void q(() => k.value?.querySelector("[aria-selected='true']")?.scrollIntoView?.({ block: "nearest" })));
125
125
  function H(e) {
126
126
  C.value && !h.value?.contains(e.relatedTarget) && N(!1);
127
127
  }
@@ -132,14 +132,14 @@ const Qe = ["id", "disabled", "aria-label", "aria-expanded"], Ze = { class: "tab
132
132
  e.preventDefault(), d.value = Math.min(Math.max(d.value + (e.key === "ArrowDown" ? 1 : -1), 0), y.value.length - 1);
133
133
  else if (e.key === "Enter") {
134
134
  e.preventDefault();
135
- const i = y.value[d.value];
136
- i && R(i);
135
+ const s = y.value[d.value];
136
+ s && R(s);
137
137
  }
138
138
  }
139
139
  function B(e) {
140
140
  (e.key === "ArrowDown" || e.key === "ArrowUp") && (e.preventDefault(), j());
141
141
  }
142
- return a({ focus: () => V.value?.focus() }), (e, i) => (w(), $("div", {
142
+ return a({ focus: () => V.value?.focus() }), (e, s) => (w(), $("div", {
143
143
  ref_key: "root",
144
144
  ref: h,
145
145
  class: "shrink-0",
@@ -151,17 +151,17 @@ const Qe = ["id", "disabled", "aria-label", "aria-expanded"], Ze = { class: "tab
151
151
  ref: V,
152
152
  type: "button",
153
153
  disabled: r.disabled,
154
- "aria-label": s(p)("core.form.phone.country", { country: S(l.value) }),
154
+ "aria-label": i(p)("core.form.phone.country", { country: S(l.value) }),
155
155
  "aria-haspopup": "listbox",
156
156
  "aria-expanded": C.value,
157
157
  "data-test": "country-button",
158
158
  class: P(["flex h-full min-h-8 cursor-pointer items-center gap-1.5 whitespace-nowrap text-body font-medium text-content-strong focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-border-focus disabled:cursor-not-allowed compact:border-r compact:border-border-separator", r.surface]),
159
- onClick: i[0] || (i[0] = (c) => C.value ? N(!0) : j()),
159
+ onClick: s[0] || (s[0] = (c) => C.value ? N(!0) : j()),
160
160
  onKeydown: B
161
161
  }, [
162
162
  M(ue, { country: l.value }, null, 8, ["country"]),
163
- f("span", Ze, T(s(de)(l.value)), 1),
164
- M(s(q), {
163
+ f("span", Ze, T(i(de)(l.value)), 1),
164
+ M(i(z), {
165
165
  name: "arrowDownSLine",
166
166
  size: 14,
167
167
  class: "text-content-muted"
@@ -171,14 +171,14 @@ const Qe = ["id", "disabled", "aria-label", "aria-expanded"], Ze = { class: "tab
171
171
  key: 0,
172
172
  ref_key: "panel",
173
173
  ref: k,
174
- style: xe(s(Q)),
174
+ style: xe(i(Q)),
175
175
  "data-test": "country-list",
176
176
  class: "z-1000 flex flex-col overflow-hidden rounded-menu bg-surface-overlay shadow-float"
177
177
  }, [
178
178
  f("div", {
179
179
  id: `${r.id}-countries`,
180
180
  role: "listbox",
181
- "aria-label": s(p)("core.form.phone.countries"),
181
+ "aria-label": i(p)("core.form.phone.countries"),
182
182
  class: "min-h-0 flex-1 overflow-y-auto p-2"
183
183
  }, [
184
184
  (w(!0), $(ee, null, le(D.value, (c, n) => (w(), $(ee, {
@@ -189,29 +189,29 @@ const Qe = ["id", "disabled", "aria-label", "aria-expanded"], Ze = { class: "tab
189
189
  id: U(u),
190
190
  key: u,
191
191
  role: "option",
192
- "aria-selected": (z.value[n] ?? 0) + b === d.value,
192
+ "aria-selected": (L.value[n] ?? 0) + b === d.value,
193
193
  "data-test": "country-option",
194
194
  "data-country": u,
195
- class: P(["flex cursor-pointer items-center gap-2.5 rounded-control px-2 py-2 text-body", (z.value[n] ?? 0) + b === d.value ? "bg-tint-soft" : "hover:bg-fill"]),
196
- onMousedown: i[1] || (i[1] = we(() => {
195
+ class: P(["flex cursor-pointer items-center gap-2.5 rounded-control px-2 py-2 text-body", (L.value[n] ?? 0) + b === d.value ? "bg-tint-soft" : "hover:bg-fill"]),
196
+ onMousedown: s[1] || (s[1] = we(() => {
197
197
  }, ["prevent"])),
198
- onMouseenter: (m) => d.value = (z.value[n] ?? 0) + b,
198
+ onMouseenter: (m) => d.value = (L.value[n] ?? 0) + b,
199
199
  onClick: (m) => R(u)
200
200
  }, [
201
201
  M(ue, { country: u }, null, 8, ["country"]),
202
202
  f("span", {
203
203
  class: P(["min-w-0 flex-1 truncate text-content-strong", u === l.value ? "font-semibold" : ""])
204
204
  }, T(S(u)), 3),
205
- f("span", nt, T(s(de)(u)), 1)
205
+ f("span", nt, T(i(de)(u)), 1)
206
206
  ], 42, ot))), 128))
207
207
  ], 64))), 128)),
208
- y.value.length === 0 ? (w(), $("p", at, T(s(p)("core.form.phone.no_match")), 1)) : J("", !0)
208
+ y.value.length === 0 ? (w(), $("p", at, T(i(p)("core.form.phone.no_match")), 1)) : J("", !0)
209
209
  ], 8, et),
210
210
  f("div", rt, [
211
211
  _e(f("input", {
212
212
  ref_key: "search",
213
213
  ref: K,
214
- "onUpdate:modelValue": i[2] || (i[2] = (c) => v.value = c),
214
+ "onUpdate:modelValue": s[2] || (s[2] = (c) => v.value = c),
215
215
  type: "text",
216
216
  role: "combobox",
217
217
  autocomplete: "off",
@@ -219,8 +219,8 @@ const Qe = ["id", "disabled", "aria-label", "aria-expanded"], Ze = { class: "tab
219
219
  "aria-expanded": "true",
220
220
  "aria-controls": `${r.id}-countries`,
221
221
  "aria-activedescendant": y.value[d.value] ? U(y.value[d.value]) : void 0,
222
- "aria-label": s(p)("core.form.phone.search"),
223
- placeholder: s(p)("core.form.phone.search"),
222
+ "aria-label": i(p)("core.form.phone.search"),
223
+ placeholder: i(p)("core.form.phone.search"),
224
224
  "data-test": "country-search",
225
225
  class: "block w-full border-0 bg-transparent p-0 text-body text-content-strong placeholder:text-content-muted focus:outline-none focus:ring-0",
226
226
  onKeydown: G
@@ -231,7 +231,7 @@ const Qe = ["id", "disabled", "aria-label", "aria-expanded"], Ze = { class: "tab
231
231
  ], 4)) : J("", !0)
232
232
  ], 544));
233
233
  }
234
- }), st = Symbol("vue-core.phoneDefaults"), ut = { class: "w-full min-w-0" }, ct = ["id", "value", "name", "placeholder", "disabled", "required", "aria-required", "aria-invalid", "aria-describedby"], dt = {
234
+ }), it = Symbol("vue-core.phoneDefaults"), ut = { class: "w-full min-w-0" }, ct = ["id", "value", "name", "placeholder", "disabled", "required", "aria-required", "aria-invalid", "aria-describedby"], dt = {
235
235
  key: 0,
236
236
  class: "mt-1.5 flex items-center gap-1.5 text-footnote text-status-success-content",
237
237
  "data-test": "phone-kind"
@@ -255,13 +255,13 @@ const Qe = ["id", "disabled", "aria-label", "aria-expanded"], Ze = { class: "tab
255
255
  commonCountries: {},
256
256
  placeholder: {},
257
257
  width: {}
258
- }, { ...ze, defaultCountry: void 0, commonCountries: void 0, placeholder: void 0, width: "lg" }), {
258
+ }, { ...Le, defaultCountry: void 0, commonCountries: void 0, placeholder: void 0, width: "lg" }), {
259
259
  modelValue: { default: "" },
260
260
  modelModifiers: {}
261
261
  }),
262
262
  emits: ["update:modelValue"],
263
263
  setup(t, { expose: a }) {
264
- const o = t, r = me(t, "modelValue"), { t: l, locale: x } = pe(), p = Ce(st, {}), _ = !!Oe(), h = Re("text", () => o.error || R.value ? "error" : o.disabled ? "locked" : "rest"), V = g(() => _ ? Ve(o.width) : "w-full"), k = F("input"), K = g(() => o.defaultCountry ?? p.defaultCountry ?? (o.commonCountries ?? p.commonCountries ?? ce)[0] ?? "HR"), C = g(() => o.commonCountries ?? p.commonCountries ?? ce), v = $e(K.value), d = E("");
264
+ const o = t, r = me(t, "modelValue"), { t: l } = pe(), x = ve(), p = Ce(it, {}), _ = !!Oe(), h = Re("text", () => o.error || R.value ? "error" : o.disabled ? "locked" : "rest"), V = g(() => _ ? Ve(o.width) : "w-full"), k = F("input"), K = g(() => o.defaultCountry ?? p.defaultCountry ?? (o.commonCountries ?? p.commonCountries ?? ce)[0] ?? "HR"), C = g(() => o.commonCountries ?? p.commonCountries ?? ce), v = $e(K.value), d = E("");
265
265
  let O = null;
266
266
  function S(n) {
267
267
  v.value = n.country, d.value = n.text;
@@ -273,8 +273,8 @@ const Qe = ["id", "disabled", "aria-label", "aria-expanded"], Ze = { class: "tab
273
273
  S(n), O = n.e164, r.value = n.e164;
274
274
  }
275
275
  const y = (n) => n.replace(/\D/g, "").length;
276
- async function z(n) {
277
- await A();
276
+ async function L(n) {
277
+ await q();
278
278
  const u = k.value;
279
279
  if (!u || document.activeElement !== u) return;
280
280
  u.value = d.value;
@@ -290,48 +290,48 @@ const Qe = ["id", "disabled", "aria-label", "aria-expanded"], Ze = { class: "tab
290
290
  const Z = m.replace(/\D/g, ""), Y = X === "deleteContentForward" ? I : I - 1;
291
291
  Y >= 0 && Y < Z.length && (m = (m.trimStart().startsWith("+") ? "+" : "") + Z.slice(0, Y) + Z.slice(Y + 1), I = Math.max(0, I - (X === "deleteContentForward" ? 0 : 1)));
292
292
  }
293
- D(oe(m, v.value)), z(I);
293
+ D(oe(m, v.value)), L(I);
294
294
  }
295
295
  function Q(n) {
296
296
  const u = n.clipboardData?.getData("text")?.trim() ?? "";
297
- /^(\+|00)\d/.test(u) && (n.preventDefault(), D(oe(u, v.value)), A(() => k.value?.setSelectionRange(d.value.length, d.value.length)));
297
+ /^(\+|00)\d/.test(u) && (n.preventDefault(), D(oe(u, v.value)), q(() => k.value?.setSelectionRange(d.value.length, d.value.length)));
298
298
  }
299
299
  function j(n) {
300
- D(je({ country: v.value, e164: r.value, text: d.value }, n)), A(() => k.value?.focus());
300
+ D(je({ country: v.value, e164: r.value, text: d.value }, n)), q(() => k.value?.focus());
301
301
  }
302
302
  const N = E(!1), R = g(() => N.value && r.value !== "" ? be(r.value) : null), H = g(() => {
303
303
  const n = R.value;
304
304
  if (n)
305
- return n.country ? l(`core.form.phone.${n.kind}`, { country: ge(n.country, x.value) }) : l("core.form.phone.invalid_any");
305
+ return n.country ? l(`core.form.phone.${n.kind}`, { country: ge(n.country, x.intlLocale) }) : l("core.form.phone.invalid_any");
306
306
  }), G = g(() => r.value !== "" && !R.value ? Xe(r.value) : void 0), B = g(() => He(r.value)), e = E(!1);
307
- let i = null;
307
+ let s = null;
308
308
  async function c() {
309
309
  try {
310
310
  await navigator.clipboard.writeText(B.value);
311
311
  } catch {
312
312
  return;
313
313
  }
314
- e.value = !0, i && clearTimeout(i), i = setTimeout(() => e.value = !1, 1800);
314
+ e.value = !0, s && clearTimeout(s), s = setTimeout(() => e.value = !1, 1800);
315
315
  }
316
- return De(() => i && clearTimeout(i)), a({ focus: () => k.value?.focus() }), (n, u) => (w(), Me(Be, Te({ ...s(Ee)(o), error: o.error ?? H.value }, {
316
+ return De(() => s && clearTimeout(s)), a({ focus: () => k.value?.focus() }), (n, u) => (w(), Me(Be, Te({ ...i(Ee)(o), error: o.error ?? H.value }, {
317
317
  value: r.value === "" ? null : B.value,
318
318
  "value-style": "numeric"
319
319
  }), Se({
320
- default: ie(({ id: b, describedby: m, invalid: I }) => [
320
+ default: se(({ id: b, describedby: m, invalid: I }) => [
321
321
  f("div", ut, [
322
322
  f("div", {
323
323
  class: P(["flex items-stretch gap-1.5", V.value])
324
324
  }, [
325
- M(it, {
325
+ M(st, {
326
326
  id: b,
327
327
  "model-value": v.value,
328
328
  common: C.value,
329
329
  disabled: o.disabled,
330
- surface: `${s(h)} px-2.5`,
330
+ surface: `${i(h)} px-2.5`,
331
331
  onPicked: j
332
332
  }, null, 8, ["id", "model-value", "common", "disabled", "surface"]),
333
333
  f("div", {
334
- class: P(["min-w-0 flex-1", s(h)])
334
+ class: P(["min-w-0 flex-1", i(h)])
335
335
  }, [
336
336
  f("input", {
337
337
  id: b,
@@ -357,12 +357,12 @@ const Qe = ["id", "disabled", "aria-label", "aria-expanded"], Ze = { class: "tab
357
357
  ], 2)
358
358
  ], 2),
359
359
  G.value && !(o.error ?? H.value) ? (w(), $("p", dt, [
360
- M(s(q), {
360
+ M(i(z), {
361
361
  name: "checkCustom",
362
362
  size: 14,
363
363
  class: "shrink-0"
364
364
  }),
365
- Ne(" " + T(s(l)(`core.form.phone.kind_${G.value}`)), 1)
365
+ Ne(" " + T(i(l)(`core.form.phone.kind_${G.value}`)), 1)
366
366
  ])) : J("", !0)
367
367
  ])
368
368
  ]),
@@ -370,7 +370,7 @@ const Qe = ["id", "disabled", "aria-label", "aria-expanded"], Ze = { class: "tab
370
370
  }, [
371
371
  r.value !== "" ? {
372
372
  name: "readonly",
373
- fn: ie(() => [
373
+ fn: se(() => [
374
374
  f("div", {
375
375
  class: P(["flex w-full min-w-0 flex-wrap items-center gap-x-2 gap-y-1.5", _ ? "justify-end" : ""]),
376
376
  "data-test": "phone-read"
@@ -380,24 +380,24 @@ const Qe = ["id", "disabled", "aria-label", "aria-expanded"], Ze = { class: "tab
380
380
  }, T(B.value), 3),
381
381
  f("a", {
382
382
  href: `tel:${r.value}`,
383
- "aria-label": s(l)("core.form.phone.call"),
384
- title: s(l)("core.form.phone.call"),
383
+ "aria-label": i(l)("core.form.phone.call"),
384
+ title: i(l)("core.form.phone.call"),
385
385
  "data-test": "phone-call",
386
386
  class: "flex size-9 shrink-0 items-center justify-center rounded-full bg-tint-soft text-content-link transition-colors duration-motion-fast hover:bg-fill focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-border-focus"
387
387
  }, [
388
- M(s(q), {
388
+ M(i(z), {
389
389
  name: "phone",
390
390
  size: 18
391
391
  })
392
392
  ], 8, ft),
393
393
  f("a", {
394
394
  href: `sms:${r.value}`,
395
- "aria-label": s(l)("core.form.phone.message"),
396
- title: s(l)("core.form.phone.message"),
395
+ "aria-label": i(l)("core.form.phone.message"),
396
+ title: i(l)("core.form.phone.message"),
397
397
  "data-test": "phone-message",
398
398
  class: "flex size-9 shrink-0 items-center justify-center rounded-full bg-tint-soft text-content-link transition-colors duration-motion-fast hover:bg-fill focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-border-focus"
399
399
  }, [
400
- M(s(q), {
400
+ M(i(z), {
401
401
  name: "message",
402
402
  size: 18
403
403
  })
@@ -408,18 +408,18 @@ const Qe = ["id", "disabled", "aria-label", "aria-expanded"], Ze = { class: "tab
408
408
  }),
409
409
  f("button", {
410
410
  type: "button",
411
- "aria-label": s(l)("core.form.phone.copy"),
412
- title: s(l)("core.form.phone.copy"),
411
+ "aria-label": i(l)("core.form.phone.copy"),
412
+ title: i(l)("core.form.phone.copy"),
413
413
  "data-test": "phone-copy",
414
414
  class: "flex size-9 shrink-0 cursor-pointer items-center justify-center rounded-full bg-fill text-content-strong transition-colors duration-motion-fast hover:bg-fill-strong focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-border-focus",
415
415
  onClick: c
416
416
  }, [
417
- M(s(q), {
417
+ M(i(z), {
418
418
  name: e.value ? "checkCustom" : "copy",
419
419
  size: 18
420
420
  }, null, 8, ["name"])
421
421
  ], 8, pt),
422
- f("span", vt, T(e.value ? s(l)("core.form.phone.copied") : ""), 1)
422
+ f("span", vt, T(e.value ? i(l)("core.form.phone.copied") : ""), 1)
423
423
  ], 2)
424
424
  ]),
425
425
  key: "0"
@@ -435,7 +435,7 @@ export {
435
435
  He as formatInternational,
436
436
  Dt as isValidPhone,
437
437
  Ye as phoneCountry,
438
- st as phoneDefaultsKey,
438
+ it as phoneDefaultsKey,
439
439
  Xe as phoneKind,
440
440
  be as phoneProblem
441
441
  };
@@ -41,7 +41,7 @@ export declare function phoneCountry(value: string): PhoneCountry | undefined;
41
41
  export declare function phoneProblem(value: string): PhoneProblem | null;
42
42
  /** True when the value is empty or a valid number: for a validator that does not need the reason. */
43
43
  export declare const isValidPhone: (value: string) => boolean;
44
- /** The country's name in a language ("Bosna i Hercegovina"); the code itself when the browser does not know it. */
45
- export declare function countryName(country: PhoneCountry, locale: string): string;
44
+ /** The country's name in a language ("Bosna i Hercegovina"); the code itself when the browser does not know it. `tag` is the BCP 47 tag `Intl` is given: `useFormat().intlLocale`. */
45
+ export declare function countryName(country: PhoneCountry, tag: string): string;
46
46
  /** The countries that match what was typed in the picker: by name, by code ("ba"), or by dial code ("387", "+387"). */
47
- export declare function searchCountries(query: string, locale: string, countries: readonly PhoneCountry[]): readonly PhoneCountry[];
47
+ export declare function searchCountries(query: string, tag: string, countries: readonly PhoneCountry[]): readonly PhoneCountry[];
@@ -10,7 +10,7 @@ export type UserParser<U extends SessionUser> = (raw: unknown) => U;
10
10
  /** The default projection: the user's id, nothing else. Applications that need a name or roles pass their own parser. */
11
11
  export declare const parseSessionUser: UserParser<SessionUser>;
12
12
  /**
13
- * Reads go-core's session payload `{ user, expires_at?, access, navigation? }` (the answer of `/auth/me`, and of a login).
13
+ * Reads go-core's session payload `{ user, expires_at?, access, navigation?, preferences? }` (the answer of `/auth/me`, and of a login).
14
14
  * Throws an `ApiError` of kind `malformed` naming what is wrong.
15
15
  */
16
16
  export declare function parseSessionPayload<U extends SessionUser = SessionUser>(raw: unknown, parseUser?: UserParser<U>): SessionSnapshot<U>;
@@ -11,6 +11,8 @@ export { httpSessionAdapter, parseSessionPayload } from "./httpSession";
11
11
  export type { HttpSessionOptions, UserParser } from "./httpSession";
12
12
  export { createPlatform, installPlatform, platformKey, usePlatform } from "./platform";
13
13
  export type { Platform, PlatformOptions } from "./platform";
14
+ export { mergePatch, preferencesOf } from "./preferences";
15
+ export type { Preferences, PreferencesPatch } from "./preferences";
14
16
  export { useSessionUser } from "./sessionUser";
15
17
  export { beforeSignOutTimeout, createSession, heldSession } from "./session";
16
18
  export type { BeforeSignOutHook, Session, SessionAdapter, SessionEnd, SessionImpersonator, SessionOptions, SessionPatch, SessionSnapshot, SessionState, SessionUser } from "./session";
@@ -2,14 +2,15 @@ var N = Object.defineProperty;
2
2
  var S = (s) => {
3
3
  throw TypeError(s);
4
4
  };
5
- var v = (s, t, e) => t in s ? N(s, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : s[t] = e;
6
- var $ = (s, t, e) => v(s, typeof t != "symbol" ? t + "" : t, e), w = (s, t, e) => t.has(s) || S("Cannot " + e);
5
+ var O = (s, t, e) => t in s ? N(s, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : s[t] = e;
6
+ var $ = (s, t, e) => O(s, typeof t != "symbol" ? t + "" : t, e), w = (s, t, e) => t.has(s) || S("Cannot " + e);
7
7
  var o = (s, t, e) => (w(s, t, "read from private field"), e ? e.call(s) : t.get(s)), l = (s, t, e) => t.has(s) ? S("Cannot add the same private member more than once") : t instanceof WeakSet ? t.add(s) : t.set(s, e), f = (s, t, e, r) => (w(s, t, "write to private field"), r ? r.call(s, e) : t.set(s, e), e), h = (s, t, e) => (w(s, t, "access private method"), e);
8
- import { u as E } from "../platform-BQOX_Ntw.js";
9
- import { b as F, c as G, a as K, d as U, h as _, e as z, i as D, p as H, f as Q, g as R } from "../platform-BQOX_Ntw.js";
8
+ import { u as v } from "../platform-DtISOEt7.js";
9
+ import { b as F, c as G, a as K, d as U, h as _, e as z, i as D, p as H, f as Q, g as R } from "../platform-DtISOEt7.js";
10
10
  import { M as W, d as X } from "../context-Ch1r4fdN.js";
11
- import { computed as O } from "vue";
12
- import { _ as Z } from "../AccessGate.vue_vue_type_script_setup_true_lang-CzQbD2Pc.js";
11
+ import { m as Z, p as k } from "../preferences-hYhrw8Uy.js";
12
+ import { computed as E } from "vue";
13
+ import { _ as et } from "../AccessGate.vue_vue_type_script_setup_true_lang-DEzXovsY.js";
13
14
  class m extends Error {
14
15
  constructor(e, r = [], n) {
15
16
  super(r.length > 0 ? `${e}: ${r.join("; ")}` : e);
@@ -61,7 +62,7 @@ a = new WeakMap(), c = new WeakMap(), p = new WeakMap(), d = new WeakMap(), u =
61
62
  return i === void 0 && n.length > 0 ? n[0] : r(i) ? i : (this.fail(t, `expected ${e}, got ${i === void 0 ? "nothing (missing)" : x(i)}`), null);
62
63
  };
63
64
  let A = b;
64
- function C(s, t) {
65
+ function P(s, t) {
65
66
  if (!B(s))
66
67
  throw new m("Invalid bootstrap config", [`expected a JSON object, got ${x(s)}`]);
67
68
  const e = [], r = new A(s, "", e), n = r.string("locale");
@@ -89,17 +90,17 @@ function L(s = {}) {
89
90
  } catch (j) {
90
91
  throw new m(`Bootstrap config in ${n} is not valid JSON`, [], { cause: j });
91
92
  }
92
- return C(y, e);
93
+ return P(y, e);
93
94
  }
94
95
  function M() {
95
- const { session: s } = E();
96
- return O(() => {
96
+ const { session: s } = v();
97
+ return E(() => {
97
98
  const t = s.state.value;
98
99
  return t.status === "authenticated" ? t.user : null;
99
100
  });
100
101
  }
101
102
  export {
102
- Z as AccessGate,
103
+ et as AccessGate,
103
104
  m as BootstrapError,
104
105
  A as BootstrapFields,
105
106
  W as MissingContextError,
@@ -111,11 +112,13 @@ export {
111
112
  _ as heldSession,
112
113
  z as httpSessionAdapter,
113
114
  D as installPlatform,
114
- C as parseBootstrap,
115
+ Z as mergePatch,
116
+ P as parseBootstrap,
115
117
  H as parseNavigation,
116
118
  Q as parseSessionPayload,
117
119
  R as platformKey,
120
+ k as preferencesOf,
118
121
  L as readBootstrap,
119
- E as usePlatform,
122
+ v as usePlatform,
120
123
  M as useSessionUser
121
124
  };
@@ -0,0 +1,35 @@
1
+ import { type ComputedRef } from "vue";
2
+ import type { Platform } from "./platform";
3
+ import type { SessionUser } from "./session";
4
+ /** A patch of `T` (RFC 7396): any member may be left out; `null` deletes a key; an object merges into the stored one; an array replaces it. */
5
+ export type PreferencesPatch<T> = {
6
+ [K in keyof T]?: T[K] extends readonly unknown[] ? T[K] | null : T[K] extends object ? PreferencesPatch<T[K]> | null : T[K] | null;
7
+ };
8
+ /** The signed-in person's stored preferences. See `preferencesOf`. */
9
+ export interface Preferences<T extends object> {
10
+ /** What is stored for the person, with the saves still on their way already applied; `{}` when nothing is stored or nobody is signed in. */
11
+ readonly value: Readonly<ComputedRef<Readonly<PreferencesPatch<T>>>>;
12
+ /**
13
+ * Applies `patch` to `value` at once, sends it (`PUT /v1/auth/preferences`), then replaces `value` by the server's merged
14
+ * answer. Saves go one after another, in the order they were made. When the server refuses, only this patch is taken back
15
+ * and the promise rejects with the failure; `usePreferences` reports it instead. Resolves at once, doing nothing, when nobody is signed in.
16
+ */
17
+ save(patch: PreferencesPatch<T>): Promise<void>;
18
+ }
19
+ type Bag = Record<string, unknown>;
20
+ /**
21
+ * `target` with `patch` merged in as JSON Merge Patch (RFC 7396), which is also what the server does by default: objects
22
+ * merge, `null` deletes a key, everything else (arrays included) replaces. Neither argument is changed.
23
+ */
24
+ export declare function mergePatch(target: unknown, patch: unknown): unknown;
25
+ /**
26
+ * The preferences of one platform's signed-in person: read from the session, saved through go-core identity's
27
+ * `PUT /v1/auth/preferences`. One service per platform, so every reader sees the same value and every save joins one queue.
28
+ *
29
+ * const preferences = preferencesOf<{ dark_mode: boolean }>(platform);
30
+ * await preferences.save({ dark_mode: true });
31
+ *
32
+ * In a component use `usePreferences`, which also reports a refused save.
33
+ */
34
+ export declare function preferencesOf<T extends object = Bag>(platform: Platform<SessionUser>): Preferences<T>;
35
+ export {};
@@ -20,6 +20,11 @@ export interface SessionSnapshot<U extends SessionUser = SessionUser> {
20
20
  readonly access: AccessSnapshot;
21
21
  /** The menu the server built for this user; absent when the adapter's backend has none. */
22
22
  readonly navigation?: readonly NavigationNode[];
23
+ /**
24
+ * The person's own settings the server keeps for them (dark mode, tips they closed): a JSON object of the application's shape,
25
+ * `{}` when nothing is stored, absent when the backend has none. Read and saved with `usePreferences`.
26
+ */
27
+ readonly preferences?: Readonly<Record<string, unknown>>;
23
28
  }
24
29
  /**
25
30
  * Why nobody is signed in: `none` (the server has no session for this browser), `expired` (a request was
@@ -52,7 +57,7 @@ export type SessionState<U extends SessionUser = SessionUser> =
52
57
  */
53
58
  export declare function heldSession<U extends SessionUser>(state: SessionState<U>): SessionSnapshot<U> | null;
54
59
  /** The parts of a signed-in session `Session.update` may replace. */
55
- export type SessionPatch<U extends SessionUser = SessionUser> = Partial<Pick<SessionSnapshot<U>, "user" | "access" | "navigation">>;
60
+ export type SessionPatch<U extends SessionUser = SessionUser> = Partial<Pick<SessionSnapshot<U>, "user" | "access" | "navigation" | "preferences">>;
56
61
  /** The seam to a backend: how to ask who is signed in and how to end the session. */
57
62
  export interface SessionAdapter<U extends SessionUser = SessionUser> {
58
63
  /** The current session, or null when there is none (not signed in). Reject for failures; honour `signal`. */