@zealsolutions/zeal-ui 1.0.0-alpha.330 → 1.0.0-alpha.332

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.
@@ -1,32 +1,32 @@
1
- import { openBlock as o, createElementBlock as i, createVNode as C, createElementVNode as n, createTextVNode as U, mergeModels as Z, useModel as ye, getCurrentInstance as ae, ref as b, computed as S, watch as R, nextTick as ee, onMounted as ve, onBeforeUnmount as me, createBlock as I, Teleport as be, withModifiers as A, withDirectives as K, vModelText as ge, createCommentVNode as v, normalizeClass as $, toDisplayString as m, Fragment as N, renderList as j, normalizeStyle as ke, pushScopeId as we, popScopeId as $e, Transition as se, withCtx as re, resolveDynamicComponent as ie, unref as G, vShow as ce, renderSlot as B } from "vue";
2
- import Ce from "../../HouseIcon-BxmNyxvv.js";
3
- import _e from "../../ArrowLeftIcon-Cgsy08pY.js";
4
- import ue from "../../MagnifyingGlassIcon-ChYNIA-H.js";
5
- import { _ as Me } from "../../_plugin-vue_export-helper-CHgC5LLL.js";
6
- import { o as pe } from "../../index-CedrSBIl.js";
7
- import te from "../../BellIcon-lK5EZXNf.js";
8
- import Se from "../../CircleCheckIcon-CA15yXgI.js";
9
- import Te from "../../XMarkIcon-DKJ_--uA.js";
10
- const Ie = /* @__PURE__ */ n("span", { class: "hidden whitespace-nowrap sm:inline" }, "Search", -1), Ae = /* @__PURE__ */ n("kbd", { class: "hidden items-center gap-px rounded border border-proclusteal-300 bg-proclusteal-100 px-[5px] py-0.5 font-sans text-[11px] font-bold leading-none text-proclusteal-500 sm:inline-flex" }, [
11
- /* @__PURE__ */ n("span", null, "⌘"),
12
- /* @__PURE__ */ U("K ")
13
- ], -1), Ee = {
1
+ import { openBlock as l, createElementBlock as u, createVNode as T, createElementVNode as a, createTextVNode as P, mergeModels as te, useModel as ge, getCurrentInstance as ie, ref as g, computed as $, watch as K, nextTick as ne, onMounted as ke, onBeforeUnmount as we, createBlock as E, Teleport as Ce, withModifiers as N, withDirectives as G, vModelText as $e, createCommentVNode as m, normalizeClass as M, toDisplayString as b, Fragment as H, renderList as U, normalizeStyle as q, pushScopeId as Se, popScopeId as _e, Transition as ce, withCtx as ue, resolveDynamicComponent as pe, unref as F, vShow as de, renderSlot as V } from "vue";
2
+ import Me from "../../HouseIcon-BxmNyxvv.js";
3
+ import Te from "../../ArrowLeftIcon-Cgsy08pY.js";
4
+ import fe from "../../MagnifyingGlassIcon-ChYNIA-H.js";
5
+ import { _ as Ae } from "../../_plugin-vue_export-helper-CHgC5LLL.js";
6
+ import { o as xe } from "../../index-CedrSBIl.js";
7
+ import oe from "../../BellIcon-lK5EZXNf.js";
8
+ import Ie from "../../CircleCheckIcon-CA15yXgI.js";
9
+ import Ee from "../../XMarkIcon-DKJ_--uA.js";
10
+ const Ne = /* @__PURE__ */ a("span", { class: "hidden whitespace-nowrap sm:inline" }, "Search", -1), He = /* @__PURE__ */ a("kbd", { class: "hidden items-center gap-px rounded border border-proclusteal-300 bg-proclusteal-100 px-[5px] py-0.5 font-sans text-[11px] font-bold leading-none text-proclusteal-500 sm:inline-flex" }, [
11
+ /* @__PURE__ */ a("span", null, "⌘"),
12
+ /* @__PURE__ */ P("K ")
13
+ ], -1), Oe = {
14
14
  __name: "GlobalSearchPill",
15
15
  emits: ["click"],
16
16
  setup(e) {
17
- return (u, p) => (o(), i("button", {
17
+ return (i, o) => (l(), u("button", {
18
18
  type: "button",
19
19
  class: "inline-flex h-[34px] cursor-pointer items-center justify-center gap-[7px] rounded-lg border border-proclusteal-300 bg-white pl-[11px] pr-[9px] font-sans text-[13px] font-semibold text-proclusteal-600 transition-[border-color,color,box-shadow] duration-150 hover:border-proclusteal-950 hover:text-proclusteal-800 hover:shadow-[0_1px_3px_rgba(20,40,45,0.08)] focus:border-proclusteal-950 focus:text-proclusteal-800 focus:outline-none",
20
20
  title: "Search (Ctrl K)",
21
21
  "aria-label": "Search (Ctrl K)",
22
- onClick: p[0] || (p[0] = (g) => u.$emit("click"))
22
+ onClick: o[0] || (o[0] = (y) => i.$emit("click"))
23
23
  }, [
24
- C(ue, { class: "!h-[15px] !w-[15px] flex-none text-proclusteal-950" }),
25
- Ie,
26
- Ae
24
+ T(fe, { class: "!h-[15px] !w-[15px] flex-none text-proclusteal-950" }),
25
+ Ne,
26
+ He
27
27
  ]));
28
28
  }
29
- }, Ne = {
29
+ }, j = {
30
30
  Contact: { label: "Contacts", colour: "#1a8a7d", icon: '<path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/>' },
31
31
  Incident: { label: "Incidents", colour: "#cd5c5c", icon: '<path d="M10.29 3.86 1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/>' },
32
32
  Asset: { label: "Assets", colour: "#8b4789", icon: '<path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"/><polyline points="3.27 6.96 12 12.01 20.73 6.96"/><line x1="12" y1="22.08" x2="12" y2="12"/>' },
@@ -39,60 +39,60 @@ const Ie = /* @__PURE__ */ n("span", { class: "hidden whitespace-nowrap sm:inlin
39
39
  EDS: { label: "Equipment Data", colour: "#708090", icon: '<path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"/><rect x="8" y="2" width="8" height="4" rx="1" ry="1"/><line x1="8" y1="12" x2="16" y2="12"/><line x1="8" y1="16" x2="14" y2="16"/>' },
40
40
  TIS: { label: "Training Sheets", colour: "#4682b4", icon: '<line x1="8" y1="6" x2="21" y2="6"/><line x1="8" y1="12" x2="21" y2="12"/><line x1="8" y1="18" x2="21" y2="18"/><line x1="3" y1="6" x2="3.01" y2="6"/><line x1="3" y1="12" x2="3.01" y2="12"/><line x1="3" y1="18" x2="3.01" y2="18"/>' },
41
41
  Training: { label: "Training", colour: "#3f7cac", icon: '<path d="M22 10 12 5 2 10l10 5 10-5z"/><path d="M6 12v5c0 1 2.7 3 6 3s6-2 6-3v-5"/>' }
42
- }, He = {
42
+ }, Le = {
43
43
  colour: "#9aa4ad",
44
44
  icon: '<circle cx="11" cy="11" r="7"/><line x1="21" y1="21" x2="16.65" y2="16.65"/>'
45
45
  };
46
- function De(e, u = {}) {
47
- const p = { ...Ne, ...u };
48
- return Object.prototype.hasOwnProperty.call(p, e) ? p[e] : { ...He, label: e };
46
+ function De(e, i = {}) {
47
+ const o = { ...j, ...i };
48
+ return Object.prototype.hasOwnProperty.call(o, e) ? o[e] : { ...Le, label: e };
49
49
  }
50
- function Oe(e) {
51
- return (e == null ? "" : String(e)).replace(/[&<>"']/g, (u) => ({
50
+ function je(e) {
51
+ return (e == null ? "" : String(e)).replace(/[&<>"']/g, (i) => ({
52
52
  "&": "&amp;",
53
53
  "<": "&lt;",
54
54
  ">": "&gt;",
55
55
  '"': "&quot;",
56
56
  "'": "&#39;"
57
- })[u]);
57
+ })[i]);
58
58
  }
59
- function Ue(e) {
59
+ function he(e) {
60
60
  if (!e)
61
61
  return "";
62
- const u = String(e).trim();
63
- return /^#([0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$/i.test(u) || /^(rgb|rgba|hsl|hsla)\([0-9.,%\s/]+\)$/i.test(u) || /^[a-z]{3,20}$/i.test(u) ? u : "";
62
+ const i = String(e).trim();
63
+ return /^#([0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$/i.test(i) || /^(rgb|rgba|hsl|hsla)\([0-9.,%\s/]+\)$/i.test(i) || /^[a-z]{3,20}$/i.test(i) ? i : "";
64
64
  }
65
- function H(e) {
65
+ function O(e) {
66
66
  if (!e)
67
67
  return "";
68
- const u = String(e).trim();
69
- if (u.includes("\\"))
68
+ const i = String(e).trim();
69
+ if (i.includes("\\"))
70
70
  return "";
71
- let p;
71
+ let o;
72
72
  try {
73
- p = new URL(u, "https://url-check.invalid/");
73
+ o = new URL(i, "https://url-check.invalid/");
74
74
  } catch {
75
75
  return "";
76
76
  }
77
- return p.protocol === "http:" || p.protocol === "https:" ? u : "";
77
+ return o.protocol === "http:" || o.protocol === "https:" ? i : "";
78
78
  }
79
- function je(e) {
80
- return String(e || "").toLowerCase().split(/\s+/).filter((u) => u.length >= 2);
79
+ function Pe(e) {
80
+ return String(e || "").toLowerCase().split(/\s+/).filter((i) => i.length >= 2);
81
81
  }
82
- function le(e, u) {
83
- const p = Oe(e);
84
- if (!u || !u.length)
85
- return p;
86
- const g = new RegExp(`(${u.map((d) => d.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("|")})`, "ig");
87
- return p.replace(g, "<mark>$1</mark>");
82
+ function le(e, i) {
83
+ const o = je(e);
84
+ if (!i || !i.length)
85
+ return o;
86
+ const y = new RegExp(`(${i.map((d) => d.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("|")})`, "ig");
87
+ return o.replace(y, "<mark>$1</mark>");
88
88
  }
89
- const Le = (e) => (we("data-v-b4eb0ff3"), e = e(), $e(), e), ze = { class: "flex items-center gap-2.5 border-b border-proclusteal-200 px-4 py-3.5" }, Pe = ["placeholder"], Ve = {
89
+ const Ue = (e) => (Se("data-v-b4eb0ff3"), e = e(), _e(), e), ze = { class: "flex items-center gap-2.5 border-b border-proclusteal-200 px-4 py-3.5" }, Be = ["placeholder"], Re = {
90
90
  key: 0,
91
91
  class: "px-[18px] pb-0.5 pt-3.5 text-[15px] font-extrabold text-[#1e262c]"
92
- }, Be = {
92
+ }, Ve = {
93
93
  key: 1,
94
94
  class: "border-b border-proclusteal-200 px-[18px] pb-3 pt-2.5"
95
- }, Re = ["onClick"], Ke = { class: "sticky top-0 z-[1] border-t border-proclusteal-200 bg-proclusteal-150 px-[18px] py-2 text-[12px] font-extrabold tracking-[0.3px] text-proclusteal-700" }, Ge = { class: "ml-0.5 text-[#667079]" }, qe = ["href", "data-row-idx", "onClick", "onMouseenter"], Fe = ["innerHTML"], Qe = { class: "min-w-0 flex-1" }, Xe = ["innerHTML"], Ye = ["innerHTML"], Je = /* @__PURE__ */ Le(() => /* @__PURE__ */ n("svg", {
95
+ }, Ke = ["onClick"], qe = { class: "sticky top-0 z-[1] border-t border-proclusteal-200 bg-proclusteal-150 px-[18px] py-2 text-[12px] font-extrabold tracking-[0.3px] text-proclusteal-700" }, Ge = { class: "ml-0.5 text-[#667079]" }, Fe = ["href", "data-row-idx", "onClick", "onMouseenter"], Qe = ["innerHTML"], Ye = { class: "min-w-0 flex-1" }, Xe = ["innerHTML"], Je = ["innerHTML"], We = /* @__PURE__ */ Ue(() => /* @__PURE__ */ a("svg", {
96
96
  class: "h-4 w-4 flex-none text-[#c2cad1]",
97
97
  viewBox: "0 0 24 24",
98
98
  fill: "none",
@@ -101,10 +101,10 @@ const Le = (e) => (we("data-v-b4eb0ff3"), e = e(), $e(), e), ze = { class: "flex
101
101
  "stroke-linecap": "round",
102
102
  "stroke-linejoin": "round"
103
103
  }, [
104
- /* @__PURE__ */ n("polyline", { points: "9 18 15 12 9 6" })
105
- ], -1)), oe = "mb-2 mr-2 inline-flex cursor-pointer items-center gap-[7px] rounded-[20px] border border-[#dde3e8] bg-[#f4f6f8] px-3.5 py-1.5 text-[13px] font-bold text-proclusteal-700 hover:border-proclusteal-950", ne = "!border-proclusteal-950 !bg-proclusteal-950 !text-white", V = "px-5 py-[26px] text-center text-[13px] font-medium text-[#667079]", We = {
104
+ /* @__PURE__ */ a("polyline", { points: "9 18 15 12 9 6" })
105
+ ], -1)), ae = "mb-2 mr-2 inline-flex cursor-pointer items-center gap-[7px] rounded-[20px] border border-[#dde3e8] bg-[#f4f6f8] px-3.5 py-1.5 text-[13px] font-bold text-proclusteal-700 hover:border-proclusteal-950", re = "!border-proclusteal-950 !bg-proclusteal-950 !text-white", R = "px-5 py-[26px] text-center text-[13px] font-medium text-[#667079]", Ze = {
106
106
  __name: "GlobalSearchModal",
107
- props: /* @__PURE__ */ Z({
107
+ props: /* @__PURE__ */ te({
108
108
  searchProvider: {
109
109
  type: Function,
110
110
  required: !0
@@ -129,139 +129,139 @@ const Le = (e) => (we("data-v-b4eb0ff3"), e = e(), $e(), e), ze = { class: "flex
129
129
  open: { type: Boolean, default: !1 },
130
130
  openModifiers: {}
131
131
  }),
132
- emits: /* @__PURE__ */ Z(["navigate"], ["update:open"]),
133
- setup(e, { emit: u }) {
134
- const p = e, g = u, d = ye(e, "open"), x = ae(), y = b(null), _ = b(null), M = b(null), w = b(""), c = b(""), r = b([]), l = b("all"), h = b("zero"), k = b(-1);
135
- let L = null, E = 0, D = null, T = null;
136
- const q = S(() => je(c.value)), F = (t) => De(t, p.types), Q = S(() => {
132
+ emits: /* @__PURE__ */ te(["navigate"], ["update:open"]),
133
+ setup(e, { emit: i }) {
134
+ const o = e, y = i, d = ge(e, "open"), x = ie(), w = g(null), _ = g(null), A = g(null), k = g(""), S = g(""), v = g([]), f = g("all"), n = g("zero"), c = g(-1);
135
+ let p = null, C = 0, L = null, I = null;
136
+ const Q = $(() => Pe(S.value)), Y = (t) => De(t, o.types), X = $(() => {
137
137
  let t = 0;
138
- return r.value.filter((s) => l.value === "all" || s.type === l.value).map((s) => {
139
- const a = F(s.type);
138
+ return v.value.filter((s) => f.value === "all" || s.type === f.value).map((s) => {
139
+ const r = Y(s.type);
140
140
  return {
141
141
  type: s.type,
142
- label: a.label,
143
- items: s.items.map((f) => ({
144
- url: H(f.Url),
145
- titleHtml: le(f.Title, q.value),
146
- subtitleHtml: le(f.Subtitle, q.value),
147
- tileColour: Ue(f.Colour) || a.colour,
148
- tileIcon: a.icon,
142
+ label: r.label,
143
+ items: s.items.map((h) => ({
144
+ url: O(h.Url),
145
+ titleHtml: le(h.Title, Q.value),
146
+ subtitleHtml: le(h.Subtitle, Q.value),
147
+ tileColour: he(h.Colour) || r.colour,
148
+ tileIcon: r.icon,
149
149
  flatIdx: t++
150
150
  }))
151
151
  };
152
152
  });
153
- }), X = S(() => Q.value.flatMap((t) => t.items)), de = S(() => r.value.reduce((t, s) => t + s.items.length, 0));
153
+ }), J = $(() => X.value.flatMap((t) => t.items)), ye = $(() => v.value.reduce((t, s) => t + s.items.length, 0));
154
154
  function z(t) {
155
- const s = X.value;
155
+ const s = J.value;
156
156
  if (!s.length) {
157
- k.value = -1;
157
+ c.value = -1;
158
158
  return;
159
159
  }
160
- k.value = Math.min(Math.max(t, 0), s.length - 1), ee(() => {
161
- var f;
162
- const a = (f = M.value) == null ? void 0 : f.querySelector(`[data-row-idx="${k.value}"]`);
163
- a == null || a.scrollIntoView({ block: "nearest" });
160
+ c.value = Math.min(Math.max(t, 0), s.length - 1), ne(() => {
161
+ var h;
162
+ const r = (h = A.value) == null ? void 0 : h.querySelector(`[data-row-idx="${c.value}"]`);
163
+ r == null || r.scrollIntoView({ block: "nearest" });
164
164
  });
165
165
  }
166
- function Y(t) {
166
+ function W(t) {
167
167
  var s;
168
- l.value = t, z(0), (s = y.value) == null || s.focus();
168
+ f.value = t, z(0), (s = w.value) == null || s.focus();
169
169
  }
170
- function J(t) {
171
- var s, a;
172
- t && (g("navigate", t), (a = (s = x == null ? void 0 : x.vnode) == null ? void 0 : s.props) != null && a.onNavigate || (window.location.href = t), O());
170
+ function Z(t) {
171
+ var s, r;
172
+ t && (y("navigate", t), (r = (s = x == null ? void 0 : x.vnode) == null ? void 0 : s.props) != null && r.onNavigate || (window.location.href = t), D());
173
173
  }
174
- function O() {
174
+ function D() {
175
175
  d.value = !1;
176
176
  }
177
- async function fe(t) {
178
- const s = ++E;
179
- c.value = t;
177
+ async function ve(t) {
178
+ const s = ++C;
179
+ S.value = t;
180
180
  try {
181
- const a = await p.searchProvider(t);
182
- if (s !== E || !d.value)
181
+ const r = await o.searchProvider(t);
182
+ if (s !== C || !d.value)
183
183
  return;
184
- r.value = a && a.groups || [], l.value = "all", h.value = r.value.length ? "results" : "empty", z(0);
184
+ v.value = r && r.groups || [], f.value = "all", n.value = v.value.length ? "results" : "empty", z(0);
185
185
  } catch {
186
- if (s !== E || !d.value)
186
+ if (s !== C || !d.value)
187
187
  return;
188
- r.value = [], h.value = "error", k.value = -1;
188
+ v.value = [], n.value = "error", c.value = -1;
189
189
  }
190
190
  }
191
- R(w, (t) => {
192
- clearTimeout(L);
191
+ K(k, (t) => {
192
+ clearTimeout(p);
193
193
  const s = t.trim();
194
- if (s.length < p.minChars) {
195
- E++, r.value = [], h.value = s.length ? "hint" : "zero", k.value = -1;
194
+ if (s.length < o.minChars) {
195
+ C++, v.value = [], n.value = s.length ? "hint" : "zero", c.value = -1;
196
196
  return;
197
197
  }
198
- L = setTimeout(() => fe(s), p.debounce);
199
- }), R(d, (t) => {
200
- t ? (D = document.activeElement, w.value = "", c.value = "", r.value = [], l.value = "all", h.value = "zero", k.value = -1, T = document.body.style.overflow, document.body.style.overflow = "hidden", ee(() => {
198
+ p = setTimeout(() => ve(s), o.debounce);
199
+ }), K(d, (t) => {
200
+ t ? (L = document.activeElement, k.value = "", S.value = "", v.value = [], f.value = "all", n.value = "zero", c.value = -1, I = document.body.style.overflow, document.body.style.overflow = "hidden", ne(() => {
201
201
  var s;
202
- return (s = y.value) == null ? void 0 : s.focus();
203
- })) : (clearTimeout(L), E++, T !== null && (document.body.style.overflow = T, T = null), D != null && D.focus && D.focus());
202
+ return (s = w.value) == null ? void 0 : s.focus();
203
+ })) : (clearTimeout(p), C++, I !== null && (document.body.style.overflow = I, I = null), L != null && L.focus && L.focus());
204
204
  }, { immediate: !0 });
205
- function xe(t) {
205
+ function me(t) {
206
206
  var s;
207
207
  if (t.key === "Escape") {
208
- t.preventDefault(), O();
208
+ t.preventDefault(), D();
209
209
  return;
210
210
  }
211
211
  if (t.key === "ArrowDown") {
212
- t.preventDefault(), z(k.value + 1);
212
+ t.preventDefault(), z(c.value + 1);
213
213
  return;
214
214
  }
215
215
  if (t.key === "ArrowUp") {
216
- t.preventDefault(), z(k.value - 1);
216
+ t.preventDefault(), z(c.value - 1);
217
217
  return;
218
218
  }
219
219
  if (t.key === "Enter") {
220
220
  if (t.isComposing)
221
221
  return;
222
- const a = X.value;
223
- if (!a.length)
222
+ const r = J.value;
223
+ if (!r.length)
224
224
  return;
225
- t.preventDefault(), J(a[k.value >= 0 ? k.value : 0].url);
225
+ t.preventDefault(), Z(r[c.value >= 0 ? c.value : 0].url);
226
226
  return;
227
227
  }
228
228
  if (t.key === "Tab") {
229
- const a = (s = _.value) == null ? void 0 : s.querySelectorAll('input, button, a[href], [tabindex]:not([tabindex="-1"])');
230
- if (!(a != null && a.length))
229
+ const r = (s = _.value) == null ? void 0 : s.querySelectorAll('input, button, a[href], [tabindex]:not([tabindex="-1"])');
230
+ if (!(r != null && r.length))
231
231
  return;
232
- const f = a[0], P = a[a.length - 1];
233
- t.shiftKey && document.activeElement === f ? (t.preventDefault(), P.focus()) : !t.shiftKey && document.activeElement === P && (t.preventDefault(), f.focus());
232
+ const h = r[0], B = r[r.length - 1];
233
+ t.shiftKey && document.activeElement === h ? (t.preventDefault(), B.focus()) : !t.shiftKey && document.activeElement === B && (t.preventDefault(), h.focus());
234
234
  }
235
235
  }
236
- function he(t) {
236
+ function be(t) {
237
237
  if (!t)
238
238
  return !1;
239
239
  const s = (t.tagName || "").toLowerCase();
240
240
  return s === "input" || s === "textarea" || s === "select" || t.isContentEditable;
241
241
  }
242
- function W(t) {
242
+ function ee(t) {
243
243
  if (t.key === "Escape" && d.value) {
244
- t.preventDefault(), O();
244
+ t.preventDefault(), D();
245
245
  return;
246
246
  }
247
247
  if ((t.ctrlKey || t.metaKey) && (t.key === "k" || t.key === "K")) {
248
248
  t.preventDefault(), d.value = !d.value;
249
249
  return;
250
250
  }
251
- t.key === "/" && !d.value && !he(document.activeElement) && (t.preventDefault(), d.value = !0);
251
+ t.key === "/" && !d.value && !be(document.activeElement) && (t.preventDefault(), d.value = !0);
252
252
  }
253
- return ve(() => {
254
- document.addEventListener("keydown", W);
255
- }), me(() => {
256
- document.removeEventListener("keydown", W), clearTimeout(L), E++, T !== null && (document.body.style.overflow = T, T = null);
257
- }), (t, s) => (o(), I(be, { to: "body" }, [
258
- d.value ? (o(), i("div", {
253
+ return ke(() => {
254
+ document.addEventListener("keydown", ee);
255
+ }), we(() => {
256
+ document.removeEventListener("keydown", ee), clearTimeout(p), C++, I !== null && (document.body.style.overflow = I, I = null);
257
+ }), (t, s) => (l(), E(Ce, { to: "body" }, [
258
+ d.value ? (l(), u("div", {
259
259
  key: 0,
260
260
  class: "fixed inset-0 z-[20000] flex items-start justify-center bg-[#11181c]/45",
261
- onMousedown: A(O, ["self"]),
262
- onKeydown: xe
261
+ onMousedown: N(D, ["self"]),
262
+ onKeydown: me
263
263
  }, [
264
- n("div", {
264
+ a("div", {
265
265
  ref_key: "panelEl",
266
266
  ref: _,
267
267
  class: "mt-[4vh] flex max-h-[88vh] w-[94%] max-w-[720px] flex-col overflow-hidden rounded-[14px] bg-white font-sans shadow-[0_30px_80px_rgba(0,0,0,0.3)] sm:mt-[8vh] sm:max-h-[82vh]",
@@ -269,88 +269,88 @@ const Le = (e) => (we("data-v-b4eb0ff3"), e = e(), $e(), e), ze = { class: "flex
269
269
  "aria-modal": "true",
270
270
  "aria-label": "Search"
271
271
  }, [
272
- n("div", ze, [
273
- C(ue, { class: "!h-[18px] !w-[18px] flex-none text-proclusteal-400" }),
274
- K(n("input", {
272
+ a("div", ze, [
273
+ T(fe, { class: "!h-[18px] !w-[18px] flex-none text-proclusteal-400" }),
274
+ G(a("input", {
275
275
  ref_key: "inputEl",
276
- ref: y,
277
- "onUpdate:modelValue": s[0] || (s[0] = (a) => w.value = a),
276
+ ref: w,
277
+ "onUpdate:modelValue": s[0] || (s[0] = (r) => k.value = r),
278
278
  type: "text",
279
279
  autocomplete: "off",
280
280
  placeholder: e.placeholder,
281
281
  class: "flex-1 border-0 bg-transparent p-0 text-[16px] text-[#1e262c] outline-none placeholder:text-proclusteal-400 focus:ring-0"
282
- }, null, 8, Pe), [
283
- [ge, w.value]
282
+ }, null, 8, Be), [
283
+ [$e, k.value]
284
284
  ]),
285
- n("button", {
285
+ a("button", {
286
286
  type: "button",
287
287
  class: "cursor-pointer border-0 bg-transparent px-1 text-[22px] leading-none text-proclusteal-400 hover:text-proclusteal-700",
288
288
  "aria-label": "Close search",
289
289
  title: "Close (Esc)",
290
- onClick: O
290
+ onClick: D
291
291
  }, "×")
292
292
  ]),
293
- h.value === "results" ? (o(), i("div", Ve, " Search results ")) : v("", !0),
294
- h.value === "results" ? (o(), i("div", Be, [
295
- n("button", {
293
+ n.value === "results" ? (l(), u("div", Re, " Search results ")) : m("", !0),
294
+ n.value === "results" ? (l(), u("div", Ve, [
295
+ a("button", {
296
296
  type: "button",
297
- class: $([oe, l.value === "all" ? ne : ""]),
298
- onClick: s[1] || (s[1] = (a) => Y("all"))
297
+ class: M([ae, f.value === "all" ? re : ""]),
298
+ onClick: s[1] || (s[1] = (r) => W("all"))
299
299
  }, [
300
- U(" All "),
301
- n("span", {
302
- class: $(["font-bold", l.value === "all" ? "opacity-85" : "opacity-60"])
303
- }, "(" + m(de.value) + ")", 3)
300
+ P(" All "),
301
+ a("span", {
302
+ class: M(["font-bold", f.value === "all" ? "opacity-85" : "opacity-60"])
303
+ }, "(" + b(ye.value) + ")", 3)
304
304
  ], 2),
305
- (o(!0), i(N, null, j(r.value, (a) => (o(), i("button", {
306
- key: a.type,
305
+ (l(!0), u(H, null, U(v.value, (r) => (l(), u("button", {
306
+ key: r.type,
307
307
  type: "button",
308
- class: $([oe, l.value === a.type ? ne : ""]),
309
- onClick: (f) => Y(a.type)
308
+ class: M([ae, f.value === r.type ? re : ""]),
309
+ onClick: (h) => W(r.type)
310
310
  }, [
311
- U(m(F(a.type).label) + " ", 1),
312
- n("span", {
313
- class: $(["font-bold", l.value === a.type ? "opacity-85" : "opacity-60"])
314
- }, "(" + m(a.items.length) + ")", 3)
315
- ], 10, Re))), 128))
316
- ])) : v("", !0),
317
- n("div", {
311
+ P(b(Y(r.type).label) + " ", 1),
312
+ a("span", {
313
+ class: M(["font-bold", f.value === r.type ? "opacity-85" : "opacity-60"])
314
+ }, "(" + b(r.items.length) + ")", 3)
315
+ ], 10, Ke))), 128))
316
+ ])) : m("", !0),
317
+ a("div", {
318
318
  ref_key: "resultsEl",
319
- ref: M,
319
+ ref: A,
320
320
  class: "overflow-y-auto pb-2.5"
321
321
  }, [
322
- h.value === "zero" ? (o(), i("div", {
322
+ n.value === "zero" ? (l(), u("div", {
323
323
  key: 0,
324
- class: $(V)
325
- }, " Search across SOPs, incidents, assets, people and more — you only ever see what you have access to. ")) : h.value === "hint" ? (o(), i("div", {
324
+ class: M(R)
325
+ }, " Search across SOPs, incidents, assets, people and more — you only ever see what you have access to. ")) : n.value === "hint" ? (l(), u("div", {
326
326
  key: 1,
327
- class: $(V)
328
- }, " Keep typing… enter at least " + m(e.minChars) + " characters to search. ", 1)) : h.value === "empty" ? (o(), i("div", {
327
+ class: M(R)
328
+ }, " Keep typing… enter at least " + b(e.minChars) + " characters to search. ", 1)) : n.value === "empty" ? (l(), u("div", {
329
329
  key: 2,
330
- class: $(V)
331
- }, " No results for “" + m(c.value) + "” — try a broader term or a code. ", 1)) : h.value === "error" ? (o(), i("div", {
330
+ class: M(R)
331
+ }, " No results for “" + b(S.value) + "” — try a broader term or a code. ", 1)) : n.value === "error" ? (l(), u("div", {
332
332
  key: 3,
333
- class: $(V)
334
- }, " Search is temporarily unavailable. ")) : (o(!0), i(N, { key: 4 }, j(Q.value, (a) => (o(), i("div", {
335
- key: a.type
333
+ class: M(R)
334
+ }, " Search is temporarily unavailable. ")) : (l(!0), u(H, { key: 4 }, U(X.value, (r) => (l(), u("div", {
335
+ key: r.type
336
336
  }, [
337
- n("div", Ke, [
338
- U(m(a.label) + " ", 1),
339
- n("span", Ge, "(" + m(a.items.length) + ")", 1)
337
+ a("div", qe, [
338
+ P(b(r.label) + " ", 1),
339
+ a("span", Ge, "(" + b(r.items.length) + ")", 1)
340
340
  ]),
341
- (o(!0), i(N, null, j(a.items, (f) => (o(), i("a", {
342
- key: f.flatIdx,
343
- href: f.url || null,
344
- class: $(["flex items-center gap-[13px] px-[18px] py-[11px] text-[#1e262c] no-underline", { "bg-proclusteal-50": f.flatIdx === k.value }]),
345
- "data-row-idx": f.flatIdx,
346
- onClick: A((P) => J(f.url), ["exact", "prevent"]),
347
- onMouseenter: (P) => k.value = f.flatIdx
341
+ (l(!0), u(H, null, U(r.items, (h) => (l(), u("a", {
342
+ key: h.flatIdx,
343
+ href: h.url || null,
344
+ class: M(["flex items-center gap-[13px] px-[18px] py-[11px] text-[#1e262c] no-underline", { "bg-proclusteal-50": h.flatIdx === c.value }]),
345
+ "data-row-idx": h.flatIdx,
346
+ onClick: N((B) => Z(h.url), ["exact", "prevent"]),
347
+ onMouseenter: (B) => c.value = h.flatIdx
348
348
  }, [
349
- n("span", {
349
+ a("span", {
350
350
  class: "inline-flex h-[42px] w-[42px] flex-none items-center justify-center rounded-[10px] text-white",
351
- style: ke({ background: f.tileColour })
351
+ style: q({ background: h.tileColour })
352
352
  }, [
353
- (o(), i("svg", {
353
+ (l(), u("svg", {
354
354
  class: "h-5 w-5",
355
355
  viewBox: "0 0 24 24",
356
356
  fill: "none",
@@ -358,85 +358,156 @@ const Le = (e) => (we("data-v-b4eb0ff3"), e = e(), $e(), e), ze = { class: "flex
358
358
  "stroke-width": "2",
359
359
  "stroke-linecap": "round",
360
360
  "stroke-linejoin": "round",
361
- innerHTML: f.tileIcon
362
- }, null, 8, Fe))
361
+ innerHTML: h.tileIcon
362
+ }, null, 8, Qe))
363
363
  ], 4),
364
- n("span", Qe, [
365
- n("span", {
364
+ a("span", Ye, [
365
+ a("span", {
366
366
  class: "gs-marked block truncate text-[14px] font-bold",
367
- innerHTML: f.titleHtml
367
+ innerHTML: h.titleHtml
368
368
  }, null, 8, Xe),
369
- n("span", {
369
+ a("span", {
370
370
  class: "gs-marked mt-0.5 block truncate text-[12.5px] text-[#5b6570]",
371
- innerHTML: f.subtitleHtml
372
- }, null, 8, Ye)
371
+ innerHTML: h.subtitleHtml
372
+ }, null, 8, Je)
373
373
  ]),
374
- Je
375
- ], 42, qe))), 128))
374
+ We
375
+ ], 42, Fe))), 128))
376
376
  ]))), 128))
377
377
  ], 512)
378
378
  ], 512)
379
- ], 32)) : v("", !0)
379
+ ], 32)) : m("", !0)
380
380
  ]));
381
381
  }
382
- }, Ze = /* @__PURE__ */ Me(We, [["__scopeId", "data-v-b4eb0ff3"]]), et = {
382
+ }, et = /* @__PURE__ */ Ae(Ze, [["__scopeId", "data-v-b4eb0ff3"]]), se = {
383
+ "reference library": "RefLib",
384
+ reflib: "RefLib",
385
+ repository: "RefLib",
386
+ "equipment data sheets": "EDS",
387
+ "equipment data": "EDS",
388
+ "action cards": "ActionCard",
389
+ "change management": "Change",
390
+ "safety alert": "Safety",
391
+ "safety alert system": "Safety",
392
+ "lessons identified": "LID",
393
+ "training centre": "Training",
394
+ "training sheets": "TIS",
395
+ "incident recording": "Incident",
396
+ "asset management": "Asset",
397
+ directory: "Contact",
398
+ "telephone directory": "Contact"
399
+ };
400
+ function tt(e) {
401
+ if (!e)
402
+ return "";
403
+ const i = String(e).trim();
404
+ if (!i)
405
+ return "";
406
+ let o = null;
407
+ if (Object.prototype.hasOwnProperty.call(j, i))
408
+ o = i;
409
+ else {
410
+ const y = i.toLowerCase(), d = Object.keys(j).find((x) => x.toLowerCase() === y);
411
+ d ? o = d : Object.prototype.hasOwnProperty.call(se, y) && (o = se[y]);
412
+ }
413
+ return !o || !Object.prototype.hasOwnProperty.call(j, o) ? "" : j[o].icon || "";
414
+ }
415
+ function nt(e) {
416
+ if (!e)
417
+ return "";
418
+ if (e.dateText)
419
+ return String(e.dateText);
420
+ const i = e.notifyday != null ? String(e.notifyday).replace(/^0/, "") : "", o = e.notifymonthname ? String(e.notifymonthname) : "", y = e.notifyyear != null ? String(e.notifyyear) : "";
421
+ return [i, o, y].filter(Boolean).join(" ");
422
+ }
423
+ const ot = {
383
424
  key: 0,
384
425
  class: "absolute -right-[3px] -top-[3px] h-2 w-2 rounded-full bg-[#dd3730] ring-2 ring-white"
385
- }, tt = { class: "absolute right-0 top-full z-30 mt-2 w-[400px] max-w-[90vw] origin-top-right overflow-hidden rounded-[10px] border border-proclusteal-300 bg-white shadow-zeal-md" }, lt = { class: "max-h-[420px] overflow-y-auto" }, ot = {
426
+ }, lt = { class: "absolute right-0 top-full z-30 mt-2 w-[400px] max-w-[90vw] origin-top-right overflow-hidden rounded-[10px] border border-proclusteal-300 bg-white shadow-zeal-md" }, at = { class: "max-h-[420px] overflow-y-auto" }, rt = {
386
427
  key: 0,
387
428
  class: "px-5 py-[26px] text-center text-[13px] font-medium text-[#667079]"
388
- }, nt = ["onClick"], at = { class: "inline-flex h-[42px] w-[42px] flex-none items-center justify-center rounded-[10px] bg-proclusteal-950 text-white" }, st = { class: "min-w-0 flex-1" }, rt = { class: "block truncate text-[14px] font-bold text-[#1e262c]" }, it = { class: "block truncate text-[12.5px] text-[#5b6570]" }, ct = {
429
+ }, st = {
430
+ key: 1,
431
+ class: "px-5 py-[26px] text-center text-[13px] font-medium text-[#667079]"
432
+ }, it = ["onClick"], ct = { class: "inline-flex h-[42px] w-[42px] flex-none items-center justify-center rounded-[10px] bg-proclusteal-950 text-white" }, ut = ["innerHTML"], pt = { class: "min-w-0 flex-1" }, dt = { class: "block truncate text-[14px] font-bold text-[#1e262c]" }, ft = { class: "block truncate text-[12.5px] text-[#5b6570]" }, xt = {
389
433
  key: 0,
390
434
  class: "mt-0.5 block text-[12px] text-proclusteal-500"
391
- }, ut = { class: "flex flex-none flex-col items-center gap-2 pt-0.5 text-proclusteal-600" }, pt = ["onClick"], dt = ["onClick"], ft = ["href"], xt = {
435
+ }, ht = { class: "flex flex-none flex-col items-center gap-2 pt-0.5 text-proclusteal-600" }, yt = ["onClick"], vt = ["onClick"], mt = ["href"], bt = {
392
436
  __name: "HeaderNotificationDropdown",
393
437
  props: {
438
+ // The feed as /personal/GetNotifications.ashx returns it: { data: [...] }. Null means
439
+ // "not loaded" — the dropdown shows a loading state and the app can fetch on `open`.
394
440
  notifications: {
395
441
  type: Object,
396
442
  default: null
397
443
  },
444
+ // Unread badge, decoupled from the list so an app can poll the cheap
445
+ // /personal/notifycheck.ashx ({ notifyCount }) instead of the feed. When null, falls back
446
+ // to deriving from `notifications` (what apps on the original contract already do).
447
+ unreadCount: {
448
+ type: Number,
449
+ default: null
450
+ },
398
451
  notificationsUrl: {
399
452
  type: String,
400
453
  default: "/personal/notifications.aspx"
401
454
  },
455
+ // Optional per-item icon override, keyed by VueAppTypeIcon or AppTypeName. Icons resolve
456
+ // from the shared table without it, so passing this is not required.
402
457
  iconMap: {
403
458
  type: Object,
404
459
  default: () => ({})
405
460
  }
406
461
  },
407
- emits: ["markAsRead", "deleteNotification", "navigate"],
408
- setup(e, { emit: u }) {
409
- const p = e, g = u, d = b(null), x = b(!1), y = S(() => {
410
- var c;
411
- return ((c = p.notifications) == null ? void 0 : c.data) || [];
412
- }), _ = S(() => y.value.some((c) => c.ClassRead === "unread"));
413
- pe(d, () => {
462
+ emits: ["markAsRead", "deleteNotification", "navigate", "open"],
463
+ setup(e, { emit: i }) {
464
+ const o = e, y = i, d = g(null), x = g(!1), w = $(() => {
465
+ var n;
466
+ return ((n = o.notifications) == null ? void 0 : n.data) || [];
467
+ }), _ = $(() => o.unreadCount !== null && o.unreadCount !== void 0 ? o.unreadCount > 0 : w.value.some((n) => n.ClassRead === "unread"));
468
+ xe(d, () => {
414
469
  x.value = !1;
415
470
  });
416
- function M(c) {
417
- return Object.prototype.hasOwnProperty.call(p.iconMap, c.VueAppTypeIcon) && p.iconMap[c.VueAppTypeIcon] || te;
471
+ function A() {
472
+ x.value = !x.value, x.value && y("open");
473
+ }
474
+ function k(n) {
475
+ return n && Object.prototype.hasOwnProperty.call(o.iconMap, n) && o.iconMap[n] || null;
418
476
  }
419
- function w(c) {
477
+ function S(n) {
478
+ const c = k(n.VueAppTypeIcon) || k(n.AppTypeName);
479
+ if (c)
480
+ return { component: c, path: "" };
481
+ const p = tt(n.AppTypeName);
482
+ return p ? { component: null, path: p } : { component: oe, path: "" };
483
+ }
484
+ const v = $(() => w.value.map((n) => ({
485
+ item: n,
486
+ icon: S(n),
487
+ date: nt(n),
488
+ unread: n.ClassRead === "unread"
489
+ })));
490
+ function f(n) {
420
491
  x.value = !1;
421
- const r = H(c);
422
- r && g("navigate", r);
492
+ const c = O(n);
493
+ c && y("navigate", c);
423
494
  }
424
- return (c, r) => (o(), i("div", {
495
+ return (n, c) => (l(), u("div", {
425
496
  ref_key: "rootEl",
426
497
  ref: d,
427
498
  class: "relative font-sans"
428
499
  }, [
429
- n("button", {
500
+ a("button", {
430
501
  type: "button",
431
502
  class: "relative flex cursor-pointer items-center justify-center text-proclusteal-600 transition-colors duration-150 hover:text-proclusteal-900",
432
503
  title: "View Notifications",
433
504
  "aria-label": "View Notifications",
434
- onClick: r[0] || (r[0] = (l) => x.value = !x.value)
505
+ onClick: A
435
506
  }, [
436
- C(te, { class: "!h-[21px] !w-[21px]" }),
437
- _.value ? (o(), i("span", et)) : v("", !0)
507
+ T(oe, { class: "!h-[21px] !w-[21px]" }),
508
+ _.value ? (l(), u("span", ot)) : m("", !0)
438
509
  ]),
439
- C(se, {
510
+ T(ce, {
440
511
  "enter-active-class": "transition-all ease-out duration-75",
441
512
  "enter-from-class": "scale-95 opacity-0",
442
513
  "enter-to-class": "scale-100 opacity-100",
@@ -444,66 +515,79 @@ const Le = (e) => (we("data-v-b4eb0ff3"), e = e(), $e(), e), ze = { class: "flex
444
515
  "leave-from-class": "scale-100 opacity-100",
445
516
  "leave-to-class": "scale-95 opacity-0"
446
517
  }, {
447
- default: re(() => [
448
- K(n("div", tt, [
449
- n("div", lt, [
450
- y.value.length ? v("", !0) : (o(), i("div", ot, " No notifications. ")),
451
- (o(!0), i(N, null, j(y.value, (l) => (o(), i("div", {
452
- key: l.NotifyID,
453
- class: $(["flex cursor-pointer items-start gap-3 border-b border-proclusteal-200 px-4 py-3", l.ClassRead === "unread" ? "bg-proclusteal-50" : "bg-white"]),
454
- onClick: (h) => w(l.url)
518
+ default: ue(() => [
519
+ G(a("div", lt, [
520
+ a("div", at, [
521
+ e.notifications ? w.value.length ? m("", !0) : (l(), u("div", st, " No notifications. ")) : (l(), u("div", rt, " Loading notifications… ")),
522
+ (l(!0), u(H, null, U(v.value, (p) => (l(), u("div", {
523
+ key: p.item.NotifyID,
524
+ class: M(["flex cursor-pointer items-start gap-3 border-b border-proclusteal-200 px-4 py-3", p.unread ? "bg-proclusteal-50" : "bg-white"]),
525
+ onClick: (C) => f(p.item.url)
455
526
  }, [
456
- n("span", at, [
457
- (o(), I(ie(M(l)), { class: "!h-5 !w-5" }))
527
+ a("span", ct, [
528
+ p.icon.component ? (l(), E(pe(p.icon.component), {
529
+ key: 0,
530
+ class: "!h-5 !w-5"
531
+ })) : (l(), u("svg", {
532
+ key: 1,
533
+ class: "h-5 w-5",
534
+ viewBox: "0 0 24 24",
535
+ fill: "none",
536
+ stroke: "currentColor",
537
+ "stroke-width": "2",
538
+ "stroke-linecap": "round",
539
+ "stroke-linejoin": "round",
540
+ innerHTML: p.icon.path
541
+ }, null, 8, ut))
458
542
  ]),
459
- n("span", st, [
460
- n("span", rt, m(l.notifyname), 1),
461
- n("span", it, m(l.summary), 1),
462
- l.dateText ? (o(), i("span", ct, m(l.dateText), 1)) : v("", !0)
543
+ a("span", pt, [
544
+ a("span", dt, b(p.item.notifyname), 1),
545
+ a("span", ft, b(p.item.summary), 1),
546
+ p.date ? (l(), u("span", xt, b(p.date), 1)) : m("", !0)
463
547
  ]),
464
- n("span", ut, [
465
- l.ClassRead === "unread" ? (o(), i("button", {
548
+ a("span", ht, [
549
+ p.unread ? (l(), u("button", {
466
550
  key: 0,
467
551
  type: "button",
468
552
  class: "hover:text-proclusteal-900",
469
553
  title: "Mark notification as read",
470
554
  "aria-label": "Mark notification as read",
471
- onClick: A((h) => c.$emit("markAsRead", l.NotifyID), ["stop"])
555
+ onClick: N((C) => n.$emit("markAsRead", p.item.NotifyID), ["stop"])
472
556
  }, [
473
- C(Se, { class: "!h-4 !w-4" })
474
- ], 8, pt)) : v("", !0),
475
- n("button", {
557
+ T(Ie, { class: "!h-4 !w-4" })
558
+ ], 8, yt)) : m("", !0),
559
+ a("button", {
476
560
  type: "button",
477
561
  class: "hover:text-[#dd3730]",
478
562
  title: "Delete notification",
479
563
  "aria-label": "Delete notification",
480
- onClick: A((h) => c.$emit("deleteNotification", l.NotifyID), ["stop"])
564
+ onClick: N((C) => n.$emit("deleteNotification", p.item.NotifyID), ["stop"])
481
565
  }, [
482
- C(Te, { class: "!w-3" })
483
- ], 8, dt)
566
+ T(Ee, { class: "!w-3" })
567
+ ], 8, vt)
484
568
  ])
485
- ], 10, nt))), 128))
569
+ ], 10, it))), 128))
486
570
  ]),
487
- n("a", {
488
- href: G(H)(e.notificationsUrl) || null,
571
+ a("a", {
572
+ href: F(O)(e.notificationsUrl) || null,
489
573
  class: "block border-t border-proclusteal-200 px-4 py-2.5 text-center text-[13px] font-bold text-proclusteal-700 no-underline hover:bg-proclusteal-50 hover:text-proclusteal-900",
490
- onClick: r[1] || (r[1] = A((l) => w(e.notificationsUrl), ["exact", "prevent"]))
491
- }, " See all notifications ", 8, ft)
574
+ onClick: c[0] || (c[0] = N((p) => f(e.notificationsUrl), ["exact", "prevent"]))
575
+ }, " See all notifications ", 8, mt)
492
576
  ], 512), [
493
- [ce, x.value]
577
+ [de, x.value]
494
578
  ])
495
579
  ]),
496
580
  _: 1
497
581
  })
498
582
  ], 512));
499
583
  }
500
- }, ht = ["src"], yt = {
584
+ }, gt = ["src"], kt = {
501
585
  key: 1,
502
586
  class: "inline-flex h-[34px] w-[34px] items-center justify-center rounded-full bg-proclusteal-900 text-[13px] font-bold uppercase leading-none tracking-[0.5px] text-white"
503
- }, vt = { class: "absolute right-0 top-full z-30 mt-2 w-[260px] origin-top-right rounded-[10px] border border-proclusteal-300 bg-white py-1 shadow-zeal-md" }, mt = { class: "flex max-w-[260px] flex-col gap-0.5 whitespace-normal px-[18px] pb-2.5 pt-3" }, bt = { class: "block text-[14px] font-bold text-proclusteal-800" }, gt = /* @__PURE__ */ n("span", { class: "my-1.5 block h-0.5 w-8 flex-none rounded-[1px] bg-[#cdd4da]" }, null, -1), kt = { class: "block break-words text-[12px] leading-[1.3] text-proclusteal-600" }, wt = /* @__PURE__ */ n("div", { class: "h-px bg-proclusteal-200" }, null, -1), $t = {
587
+ }, wt = { class: "absolute right-0 top-full z-30 mt-2 w-[260px] origin-top-right rounded-[10px] border border-proclusteal-300 bg-white py-1 shadow-zeal-md" }, Ct = { class: "flex max-w-[260px] flex-col gap-0.5 whitespace-normal px-[18px] pb-2.5 pt-3" }, $t = { class: "block text-[14px] font-bold text-proclusteal-800" }, St = /* @__PURE__ */ a("span", { class: "my-1.5 block h-0.5 w-8 flex-none rounded-[1px] bg-[#cdd4da]" }, null, -1), _t = { class: "block break-words text-[12px] leading-[1.3] text-proclusteal-600" }, Mt = /* @__PURE__ */ a("div", { class: "h-px bg-proclusteal-200" }, null, -1), Tt = {
504
588
  key: 0,
505
589
  class: "my-1 h-px bg-proclusteal-200"
506
- }, Ct = ["href", "onClick"], _t = {
590
+ }, At = ["href", "onClick"], It = {
507
591
  __name: "HeaderUserMenu",
508
592
  props: {
509
593
  user: {
@@ -516,39 +600,39 @@ const Le = (e) => (we("data-v-b4eb0ff3"), e = e(), $e(), e), ze = { class: "flex
516
600
  }
517
601
  },
518
602
  emits: ["select"],
519
- setup(e, { emit: u }) {
520
- const p = e, g = u, d = b(null), x = b(!1), y = b(!1);
521
- R(() => p.user.avatarUrl, () => {
522
- y.value = !1;
603
+ setup(e, { emit: i }) {
604
+ const o = e, y = i, d = g(null), x = g(!1), w = g(!1);
605
+ K(() => o.user.avatarUrl, () => {
606
+ w.value = !1;
523
607
  });
524
- const _ = S(() => `${p.user.firstName || ""} ${p.user.surname || ""}`.trim()), M = S(() => `${(p.user.firstName || "").charAt(0)}${(p.user.surname || "").charAt(0)}`.toUpperCase());
525
- pe(d, () => {
608
+ const _ = $(() => `${o.user.firstName || ""} ${o.user.surname || ""}`.trim()), A = $(() => `${(o.user.firstName || "").charAt(0)}${(o.user.surname || "").charAt(0)}`.toUpperCase());
609
+ xe(d, () => {
526
610
  x.value = !1;
527
611
  });
528
- function w(c) {
529
- x.value = !1, g("select", c);
612
+ function k(S) {
613
+ x.value = !1, y("select", S);
530
614
  }
531
- return (c, r) => (o(), i("div", {
615
+ return (S, v) => (l(), u("div", {
532
616
  ref_key: "rootEl",
533
617
  ref: d,
534
618
  class: "relative font-sans"
535
619
  }, [
536
- n("button", {
620
+ a("button", {
537
621
  type: "button",
538
622
  class: "flex cursor-pointer items-center justify-center",
539
623
  title: "View Menu Options",
540
624
  "aria-label": "View Menu Options",
541
- onClick: r[1] || (r[1] = (l) => x.value = !x.value)
625
+ onClick: v[1] || (v[1] = (f) => x.value = !x.value)
542
626
  }, [
543
- e.user.avatarUrl && !y.value ? (o(), i("img", {
627
+ e.user.avatarUrl && !w.value ? (l(), u("img", {
544
628
  key: 0,
545
629
  src: e.user.avatarUrl,
546
630
  alt: "",
547
631
  class: "h-[34px] w-[34px] rounded-full object-cover",
548
- onError: r[0] || (r[0] = (l) => y.value = !0)
549
- }, null, 40, ht)) : (o(), i("span", yt, m(M.value), 1))
632
+ onError: v[0] || (v[0] = (f) => w.value = !0)
633
+ }, null, 40, gt)) : (l(), u("span", kt, b(A.value), 1))
550
634
  ]),
551
- C(se, {
635
+ T(ce, {
552
636
  "enter-active-class": "transition-all ease-out duration-75",
553
637
  "enter-from-class": "scale-95 opacity-0",
554
638
  "enter-to-class": "scale-100 opacity-100",
@@ -556,43 +640,43 @@ const Le = (e) => (we("data-v-b4eb0ff3"), e = e(), $e(), e), ze = { class: "flex
556
640
  "leave-from-class": "scale-100 opacity-100",
557
641
  "leave-to-class": "scale-95 opacity-0"
558
642
  }, {
559
- default: re(() => [
560
- K(n("div", vt, [
561
- n("div", mt, [
562
- n("span", bt, m(_.value), 1),
563
- gt,
564
- n("span", kt, m(e.user.orgName), 1)
643
+ default: ue(() => [
644
+ G(a("div", wt, [
645
+ a("div", Ct, [
646
+ a("span", $t, b(_.value), 1),
647
+ St,
648
+ a("span", _t, b(e.user.orgName), 1)
565
649
  ]),
566
- wt,
567
- (o(!0), i(N, null, j(e.menuItems, (l, h) => (o(), i(N, { key: h }, [
568
- l.divider ? (o(), i("div", $t)) : (o(), i("a", {
650
+ Mt,
651
+ (l(!0), u(H, null, U(e.menuItems, (f, n) => (l(), u(H, { key: n }, [
652
+ f.divider ? (l(), u("div", Tt)) : (l(), u("a", {
569
653
  key: 1,
570
- href: l.href && G(H)(l.href) || null,
654
+ href: f.href && F(O)(f.href) || null,
571
655
  class: "flex items-center gap-2.5 px-[18px] py-2 text-[13px] font-semibold text-proclusteal-700 no-underline hover:bg-proclusteal-50 hover:text-proclusteal-900",
572
- onClick: A((k) => w(l), ["exact", "prevent"])
656
+ onClick: N((c) => k(f), ["exact", "prevent"])
573
657
  }, [
574
- l.icon ? (o(), I(ie(l.icon), {
658
+ f.icon ? (l(), E(pe(f.icon), {
575
659
  key: 0,
576
660
  class: "!h-4 !w-4 flex-none"
577
- })) : v("", !0),
578
- n("span", null, m(l.label), 1)
579
- ], 8, Ct))
661
+ })) : m("", !0),
662
+ a("span", null, b(f.label), 1)
663
+ ], 8, At))
580
664
  ], 64))), 128))
581
665
  ], 512), [
582
- [ce, x.value]
666
+ [de, x.value]
583
667
  ])
584
668
  ]),
585
669
  _: 1
586
670
  })
587
671
  ], 512));
588
672
  }
589
- }, Mt = { class: "flex h-[70px] shrink-0 items-center justify-between border-b border-proclusteal-300 bg-white px-[15px] font-sans shadow-[0_1px_3px_rgba(20,40,45,0.05)] sm:px-[25px]" }, St = { class: "flex min-w-0 items-center gap-[18px]" }, Tt = {
673
+ }, Et = { class: "flex h-[70px] shrink-0 items-center justify-between border-b border-proclusteal-300 bg-white px-[15px] font-sans shadow-[0_1px_3px_rgba(20,40,45,0.05)] sm:px-[25px]" }, Nt = { class: "flex min-w-0 items-center gap-[18px]" }, Ht = {
590
674
  key: 0,
591
675
  class: "hidden whitespace-nowrap text-[18px] font-semibold text-proclusteal-800 sm:inline"
592
- }, It = {
676
+ }, Ot = {
593
677
  key: 0,
594
678
  class: "font-normal text-black-800"
595
- }, At = { class: "flex items-center gap-3.5 text-proclusteal-600" }, Et = ["href", "title", "aria-label"], Nt = { class: "flex items-center gap-[18px] sm:gap-[25px]" }, Bt = {
679
+ }, Lt = ["href", "title", "aria-label"], Dt = { class: "flex items-center gap-[18px] sm:gap-[25px]" }, Gt = {
596
680
  __name: "AppHeader",
597
681
  props: {
598
682
  title: {
@@ -615,6 +699,12 @@ const Le = (e) => (we("data-v-b4eb0ff3"), e = e(), $e(), e), ze = { class: "flex
615
699
  type: Boolean,
616
700
  default: !1
617
701
  },
702
+ // Per-module accent (proclus `.top-left-part:after`): a 2x45px bar dividing the
703
+ // brand block from the header icons. Omit for no divider.
704
+ accentColour: {
705
+ type: String,
706
+ default: ""
707
+ },
618
708
  user: {
619
709
  type: Object,
620
710
  default: null
@@ -627,6 +717,13 @@ const Le = (e) => (we("data-v-b4eb0ff3"), e = e(), $e(), e), ze = { class: "flex
627
717
  type: Object,
628
718
  default: null
629
719
  },
720
+ // Drives the bell's unread dot on its own, so an app can poll the cheap
721
+ // /personal/notifycheck.ashx rather than the write-side-effecting feed. Falls back to
722
+ // deriving from `notifications` when not supplied.
723
+ unreadCount: {
724
+ type: Number,
725
+ default: null
726
+ },
630
727
  notificationsUrl: {
631
728
  type: String,
632
729
  default: "/personal/notifications.aspx"
@@ -648,96 +745,114 @@ const Le = (e) => (we("data-v-b4eb0ff3"), e = e(), $e(), e), ze = { class: "flex
648
745
  default: () => ({})
649
746
  }
650
747
  },
651
- emits: ["navigate", "home", "menu-select", "markAsRead", "deleteNotification"],
652
- setup(e, { emit: u }) {
653
- const p = e, g = u, d = ae(), x = b(!1);
654
- function y(c) {
655
- var l, h;
656
- if (!c)
748
+ emits: [
749
+ "navigate",
750
+ "home",
751
+ "menu-select",
752
+ "markAsRead",
753
+ "deleteNotification",
754
+ "notifications-open"
755
+ ],
756
+ setup(e, { emit: i }) {
757
+ const o = e, y = i, d = ie(), x = g(!1), w = $(() => !!o.notifications || o.unreadCount !== null && o.unreadCount !== void 0), _ = $(() => he(o.accentColour)), A = $(() => _.value || "#1c6f63");
758
+ function k(n) {
759
+ var p, C;
760
+ if (!n)
657
761
  return;
658
- const r = H(c);
659
- r && (g("navigate", r), (h = (l = d == null ? void 0 : d.vnode) == null ? void 0 : l.props) != null && h.onNavigate || (window.location.href = r));
762
+ const c = O(n);
763
+ c && (y("navigate", c), (C = (p = d == null ? void 0 : d.vnode) == null ? void 0 : p.props) != null && C.onNavigate || (window.location.href = c));
660
764
  }
661
- function _() {
662
- g("home"), y(p.homeUrl);
765
+ function S() {
766
+ y("home"), k(o.homeUrl);
663
767
  }
664
- function M() {
768
+ function v() {
665
769
  window.history.back();
666
770
  }
667
- function w(c) {
668
- g("menu-select", c), c.href && y(c.href);
771
+ function f(n) {
772
+ y("menu-select", n), n.href && k(n.href);
669
773
  }
670
- return (c, r) => (o(), i("header", Mt, [
671
- n("div", St, [
672
- B(c.$slots, "logo"),
673
- e.title ? (o(), i("span", Tt, [
674
- U(m(e.title), 1),
675
- e.subtitle ? (o(), i("span", It, " " + m(e.subtitle), 1)) : v("", !0)
676
- ])) : v("", !0),
677
- n("nav", At, [
678
- e.homeUrl ? (o(), i("a", {
774
+ return (n, c) => (l(), u("header", Et, [
775
+ a("div", Nt, [
776
+ V(n.$slots, "logo"),
777
+ e.title ? (l(), u("span", Ht, [
778
+ P(b(e.title), 1),
779
+ e.subtitle ? (l(), u("span", Ot, " " + b(e.subtitle), 1)) : m("", !0)
780
+ ])) : m("", !0),
781
+ _.value ? (l(), u("span", {
782
+ key: 1,
783
+ class: "h-[45px] w-[2px] shrink-0",
784
+ style: q({ background: _.value }),
785
+ "aria-hidden": "true"
786
+ }, null, 4)) : m("", !0),
787
+ a("nav", {
788
+ class: "flex items-center gap-7 text-proclusteal-600",
789
+ style: q({ "--hdr-accent": A.value })
790
+ }, [
791
+ e.homeUrl ? (l(), u("a", {
679
792
  key: 0,
680
- href: G(H)(e.homeUrl) || null,
681
- class: "hover:text-proclusteal-900",
793
+ href: F(O)(e.homeUrl) || null,
794
+ class: "hover:text-[var(--hdr-accent)]",
682
795
  title: e.homeTooltip,
683
796
  "aria-label": e.homeTooltip,
684
- onClick: A(_, ["exact", "prevent"])
797
+ onClick: N(S, ["exact", "prevent"])
685
798
  }, [
686
- C(Ce, { class: "!h-5 !w-5" })
687
- ], 8, Et)) : v("", !0),
688
- e.showBack ? (o(), i("button", {
799
+ T(Me, { class: "!h-[22px] !w-[22px]" })
800
+ ], 8, Lt)) : m("", !0),
801
+ e.showBack ? (l(), u("button", {
689
802
  key: 1,
690
803
  type: "button",
691
- class: "cursor-pointer hover:text-proclusteal-900",
804
+ class: "cursor-pointer hover:text-[var(--hdr-accent)]",
692
805
  title: "Go Back",
693
806
  "aria-label": "Go Back",
694
- onClick: M
807
+ onClick: v
695
808
  }, [
696
- C(_e, { class: "!h-5 !w-5" })
697
- ])) : v("", !0)
698
- ]),
699
- B(c.$slots, "left")
809
+ T(Te, { class: "!h-[22px] !w-[22px]" })
810
+ ])) : m("", !0)
811
+ ], 4),
812
+ V(n.$slots, "left")
700
813
  ]),
701
- n("div", Nt, [
702
- B(c.$slots, "right"),
703
- e.searchProvider ? (o(), I(Ee, {
814
+ a("div", Dt, [
815
+ V(n.$slots, "right"),
816
+ e.searchProvider ? (l(), E(Oe, {
704
817
  key: 0,
705
- onClick: r[0] || (r[0] = (l) => x.value = !0)
706
- })) : v("", !0),
707
- e.notifications ? (o(), I(xt, {
818
+ onClick: c[0] || (c[0] = (p) => x.value = !0)
819
+ })) : m("", !0),
820
+ w.value ? (l(), E(bt, {
708
821
  key: 1,
709
822
  notifications: e.notifications,
823
+ "unread-count": e.unreadCount,
710
824
  "notifications-url": e.notificationsUrl,
711
825
  "icon-map": e.notificationIconMap,
712
- onMarkAsRead: r[1] || (r[1] = (l) => c.$emit("markAsRead", l)),
713
- onDeleteNotification: r[2] || (r[2] = (l) => c.$emit("deleteNotification", l)),
714
- onNavigate: y
715
- }, null, 8, ["notifications", "notifications-url", "icon-map"])) : v("", !0),
716
- e.user ? (o(), I(_t, {
826
+ onMarkAsRead: c[1] || (c[1] = (p) => n.$emit("markAsRead", p)),
827
+ onDeleteNotification: c[2] || (c[2] = (p) => n.$emit("deleteNotification", p)),
828
+ onOpen: c[3] || (c[3] = (p) => n.$emit("notifications-open")),
829
+ onNavigate: k
830
+ }, null, 8, ["notifications", "unread-count", "notifications-url", "icon-map"])) : m("", !0),
831
+ e.user ? (l(), E(It, {
717
832
  key: 2,
718
833
  user: e.user,
719
834
  "menu-items": e.menuItems,
720
- onSelect: w
721
- }, null, 8, ["user", "menu-items"])) : v("", !0)
835
+ onSelect: f
836
+ }, null, 8, ["user", "menu-items"])) : m("", !0)
722
837
  ]),
723
- e.searchProvider ? (o(), I(Ze, {
838
+ e.searchProvider ? (l(), E(et, {
724
839
  key: 0,
725
840
  open: x.value,
726
- "onUpdate:open": r[3] || (r[3] = (l) => x.value = l),
841
+ "onUpdate:open": c[4] || (c[4] = (p) => x.value = p),
727
842
  "search-provider": e.searchProvider,
728
843
  placeholder: e.searchPlaceholder,
729
844
  types: e.searchTypes,
730
- onNavigate: y
731
- }, null, 8, ["open", "search-provider", "placeholder", "types"])) : v("", !0)
845
+ onNavigate: k
846
+ }, null, 8, ["open", "search-provider", "placeholder", "types"])) : m("", !0)
732
847
  ]));
733
848
  }
734
849
  };
735
850
  export {
736
- Bt as AppHeader,
737
- Ne as DEFAULT_SEARCH_TYPES,
738
- Ze as GlobalSearchModal,
739
- Ee as GlobalSearchPill,
740
- xt as HeaderNotificationDropdown,
741
- _t as HeaderUserMenu,
742
- H as safeUrl
851
+ Gt as AppHeader,
852
+ j as DEFAULT_SEARCH_TYPES,
853
+ et as GlobalSearchModal,
854
+ Oe as GlobalSearchPill,
855
+ bt as HeaderNotificationDropdown,
856
+ It as HeaderUserMenu,
857
+ O as safeUrl
743
858
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zealsolutions/zeal-ui",
3
- "version": "1.0.0-alpha.330",
3
+ "version": "1.0.0-alpha.332",
4
4
  "description": "UI library for Zeal Solutions",
5
5
  "author": "Zeal Solutions",
6
6
  "license": "ISC",