@floegence/floe-webapp-core 0.35.44 → 0.35.46

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.
@@ -7,6 +7,8 @@ export interface Command {
7
7
  class?: string;
8
8
  }>;
9
9
  keybind?: string;
10
+ /** Allow this keybind even while the user is typing in an input/editor. */
11
+ allowWhileTyping?: boolean;
10
12
  category?: string;
11
13
  execute: () => void | Promise<void>;
12
14
  }
@@ -1,60 +1,58 @@
1
- import { createSignal as c, onCleanup as D, createEffect as L } from "solid-js";
2
- import { createSimpleContext as P } from "./createSimpleContext.js";
3
- import { useResolvedFloeConfig as S } from "./FloeConfigContext.js";
4
- import { formatKeybind as E, parseKeybind as k, matchKeybind as p } from "../utils/keybind.js";
1
+ import { createSignal as c, onCleanup as L, createEffect as P } from "solid-js";
2
+ import { createSimpleContext as S } from "./createSimpleContext.js";
3
+ import { useResolvedFloeConfig as E } from "./FloeConfigContext.js";
4
+ import { formatKeybind as T, parseKeybind as W, matchKeybind as u } from "../utils/keybind.js";
5
5
  import { deferAfterPaint as F, deferNonBlocking as m } from "../utils/defer.js";
6
6
  import { shouldIgnoreHotkeys as I } from "../utils/dom.js";
7
- function T() {
8
- const x = S(), y = () => x.config.commands, r = /* @__PURE__ */ new Map(), i = /* @__PURE__ */ new Map(), [v, s] = c(!1), [g, f] = c(""), [K, h] = c(""), [b, W] = c([]), a = () => {
9
- W(Array.from(r.values()));
7
+ function M() {
8
+ const x = E(), y = () => x.config.commands, r = /* @__PURE__ */ new Map(), i = /* @__PURE__ */ new Map(), [v, s] = c(!1), [g, f] = c(""), [K, h] = c(""), [b, A] = c([]), l = () => {
9
+ A(Array.from(r.values()));
10
10
  };
11
11
  if (typeof window < "u" && y().enableGlobalKeybinds) {
12
12
  const t = (e) => {
13
- const n = y();
14
- if (n.save.enabled && p(e, n.save.keybind)) {
13
+ const n = y(), k = I(e, {
14
+ ignoreWhenTyping: n.ignoreWhenTyping,
15
+ allowWhenTypingWithin: n.allowWhenTypingWithin
16
+ });
17
+ if (n.save.enabled && u(e, n.save.keybind)) {
15
18
  const o = r.get(n.save.commandId);
16
19
  o ? (e.preventDefault(), m(() => {
17
20
  Promise.resolve(o.execute()).catch((d) => console.error(d));
18
21
  })) : n.save.preventDefaultWhenNoHandler && e.preventDefault();
19
22
  return;
20
23
  }
21
- if (!I(e, {
22
- ignoreWhenTyping: n.ignoreWhenTyping,
23
- allowWhenTypingWithin: n.allowWhenTypingWithin
24
- })) {
25
- if (n.palette.enabled && p(e, n.palette.keybind)) {
26
- e.preventDefault(), s((o) => !o);
27
- return;
28
- }
29
- if (!v())
30
- for (const o of r.values()) {
31
- if (!o.keybind) continue;
32
- const d = i.get(o.id);
33
- if (d && p(e, d)) {
34
- e.preventDefault(), m(() => {
35
- Promise.resolve(o.execute()).catch((A) => console.error(A));
36
- });
37
- return;
38
- }
39
- }
24
+ if (!k && n.palette.enabled && u(e, n.palette.keybind)) {
25
+ e.preventDefault(), s((o) => !o);
26
+ return;
40
27
  }
28
+ if (!v())
29
+ for (const o of r.values()) {
30
+ if (!o.keybind || k && !o.allowWhileTyping) continue;
31
+ const d = i.get(o.id);
32
+ if (d && u(e, d)) {
33
+ e.preventDefault(), m(() => {
34
+ Promise.resolve(o.execute()).catch((D) => console.error(D));
35
+ });
36
+ return;
37
+ }
38
+ }
41
39
  };
42
- window.addEventListener("keydown", t), D(() => window.removeEventListener("keydown", t));
40
+ window.addEventListener("keydown", t), L(() => window.removeEventListener("keydown", t));
43
41
  }
44
- let u = 0;
45
- L(() => {
42
+ let p = 0;
43
+ P(() => {
46
44
  const t = g().trim();
47
- u += 1;
48
- const e = u;
45
+ p += 1;
46
+ const e = p;
49
47
  if (!t) {
50
48
  h("");
51
49
  return;
52
50
  }
53
51
  F(() => {
54
- e === u && h(t.toLowerCase());
52
+ e === p && h(t.toLowerCase());
55
53
  });
56
54
  });
57
- let w = "", C = null, l = [];
55
+ let w = "", C = null, a = [];
58
56
  return {
59
57
  // State
60
58
  isOpen: v,
@@ -62,7 +60,7 @@ function T() {
62
60
  commands: b,
63
61
  filteredCommands: () => {
64
62
  const t = b(), e = K();
65
- return t === C && e === w ? l : (C = t, w = e, e ? (l = t.filter((n) => n.title.toLowerCase().includes(e) || n.description?.toLowerCase().includes(e) || n.category?.toLowerCase().includes(e)), l) : (l = t, t));
63
+ return t === C && e === w ? a : (C = t, w = e, e ? (a = t.filter((n) => n.title.toLowerCase().includes(e) || n.description?.toLowerCase().includes(e) || n.category?.toLowerCase().includes(e)), a) : (a = t, t));
66
64
  },
67
65
  // Actions
68
66
  open: () => s(!0),
@@ -71,15 +69,15 @@ function T() {
71
69
  },
72
70
  toggle: () => s((t) => !t),
73
71
  setSearch: (t) => f(t),
74
- register: (t) => (r.set(t.id, t), t.keybind && i.set(t.id, k(t.keybind)), a(), () => {
75
- r.delete(t.id), i.delete(t.id), a();
72
+ register: (t) => (r.set(t.id, t), t.keybind && i.set(t.id, W(t.keybind)), l(), () => {
73
+ r.delete(t.id), i.delete(t.id), l();
76
74
  }),
77
75
  registerAll: (t) => (t.forEach((e) => {
78
- r.set(e.id, e), e.keybind && i.set(e.id, k(e.keybind));
79
- }), a(), () => {
76
+ r.set(e.id, e), e.keybind && i.set(e.id, W(e.keybind));
77
+ }), l(), () => {
80
78
  t.forEach((e) => {
81
79
  r.delete(e.id), i.delete(e.id);
82
- }), a();
80
+ }), l();
83
81
  }),
84
82
  execute: (t) => {
85
83
  const e = r.get(t);
@@ -87,18 +85,18 @@ function T() {
87
85
  Promise.resolve(e.execute()).catch((n) => console.error(n));
88
86
  }));
89
87
  },
90
- getKeybindDisplay: E
88
+ getKeybindDisplay: T
91
89
  };
92
90
  }
93
91
  const {
94
- Provider: B,
95
- use: G
96
- } = P({
92
+ Provider: G,
93
+ use: J
94
+ } = S({
97
95
  name: "Command",
98
- init: T
96
+ init: M
99
97
  });
100
98
  export {
101
- B as CommandProvider,
102
- T as createCommandService,
103
- G as useCommand
99
+ G as CommandProvider,
100
+ M as createCommandService,
101
+ J as useCommand
104
102
  };
@@ -36,6 +36,7 @@ export interface CommandContribution<TProtocol = unknown> {
36
36
  class?: string;
37
37
  }>;
38
38
  keybind?: string;
39
+ allowWhileTyping?: boolean;
39
40
  category?: string;
40
41
  execute: (ctx: ComponentContext<TProtocol>) => void | Promise<void>;
41
42
  }
@@ -7,16 +7,16 @@ import { useCommand as b } from "./CommandContext.js";
7
7
  import { useNotification as R } from "./NotificationContext.js";
8
8
  import { deferNonBlocking as M } from "../utils/defer.js";
9
9
  function S(r) {
10
- const s = `[${r}]`;
10
+ const i = `[${r}]`;
11
11
  return {
12
- debug: (...n) => console.debug(s, ...n),
13
- info: (...n) => console.info(s, ...n),
14
- warn: (...n) => console.warn(s, ...n),
15
- error: (...n) => console.error(s, ...n)
12
+ debug: (...n) => console.debug(i, ...n),
13
+ info: (...n) => console.info(i, ...n),
14
+ warn: (...n) => console.warn(i, ...n),
15
+ error: (...n) => console.error(i, ...n)
16
16
  };
17
17
  }
18
- function A(r, s) {
19
- const n = `component:${s}:`;
18
+ function A(r, i) {
19
+ const n = `component:${i}:`;
20
20
  return {
21
21
  get: (a, m) => r.load(n + a, m),
22
22
  set: (a, m) => r.debouncedSave(n + a, m),
@@ -24,36 +24,36 @@ function A(r, s) {
24
24
  };
25
25
  }
26
26
  function D() {
27
- const r = x(), s = v(), n = b(), a = R(), m = w();
28
- return (f, p) => ({
27
+ const r = x(), i = v(), n = b(), a = R(), m = w();
28
+ return (l, p) => ({
29
29
  protocol: p?.protocol,
30
30
  theme: r,
31
- layout: s,
31
+ layout: i,
32
32
  commands: n,
33
33
  notifications: a,
34
- storage: A(m.persist, f),
35
- logger: S(f)
34
+ storage: A(m.persist, l),
35
+ logger: S(l)
36
36
  });
37
37
  }
38
- const l = h({
38
+ const f = h({
39
39
  name: "ComponentRegistry",
40
40
  init: B
41
- }), G = l.Provider;
41
+ }), G = f.Provider;
42
42
  function H() {
43
- return l.use();
43
+ return f.use();
44
44
  }
45
45
  function J() {
46
- return l.useOptional();
46
+ return f.useOptional();
47
47
  }
48
48
  function K() {
49
- return l.has();
49
+ return f.has();
50
50
  }
51
51
  function B() {
52
- const [r, s] = C(/* @__PURE__ */ new Map()), [n, a] = C(/* @__PURE__ */ new Set()), m = /* @__PURE__ */ new Map(), f = (t) => {
53
- s((e) => new Map(e).set(t.id, t));
52
+ const [r, i] = C(/* @__PURE__ */ new Map()), [n, a] = C(/* @__PURE__ */ new Set()), m = /* @__PURE__ */ new Map(), l = (t) => {
53
+ i((e) => new Map(e).set(t.id, t));
54
54
  }, p = (t) => {
55
55
  const e = t.map((o) => o.id).filter((o) => !!o);
56
- return s((o) => {
56
+ return i((o) => {
57
57
  const c = new Map(o);
58
58
  return t.forEach((u) => c.set(u.id, u)), c;
59
59
  }), () => {
@@ -61,31 +61,32 @@ function B() {
61
61
  y(o);
62
62
  });
63
63
  };
64
- }, g = async (t, e) => {
64
+ }, d = async (t, e) => {
65
65
  const o = r().get(t);
66
66
  if (!o || n().has(t)) return;
67
67
  const c = [];
68
68
  try {
69
69
  if (o.commands?.length) {
70
- const u = o.commands.map((i) => ({
71
- id: i.id,
72
- title: i.title,
73
- description: i.description,
74
- icon: i.icon,
75
- keybind: i.keybind,
76
- category: i.category,
77
- execute: () => i.execute(e)
70
+ const u = o.commands.map((s) => ({
71
+ id: s.id,
72
+ title: s.title,
73
+ description: s.description,
74
+ icon: s.icon,
75
+ keybind: s.keybind,
76
+ allowWhileTyping: s.allowWhileTyping,
77
+ category: s.category,
78
+ execute: () => s.execute(e)
78
79
  }));
79
80
  c.push(e.commands.registerAll(u));
80
81
  }
81
82
  await o.onMount?.(e), c.length && m.set(t, () => c.forEach((u) => u())), a((u) => {
82
- const i = new Set(u);
83
- return i.add(t), i;
83
+ const s = new Set(u);
84
+ return s.add(t), s;
84
85
  });
85
86
  } catch (u) {
86
- throw c.forEach((i) => i()), u;
87
+ throw c.forEach((s) => s()), u;
87
88
  }
88
- }, d = async (t) => {
89
+ }, g = async (t) => {
89
90
  const e = r().get(t);
90
91
  if (e && n().has(t))
91
92
  try {
@@ -97,24 +98,24 @@ function B() {
97
98
  });
98
99
  }
99
100
  }, y = async (t) => {
100
- await d(t), s((e) => {
101
+ await g(t), i((e) => {
101
102
  const o = new Map(e);
102
103
  return o.delete(t), o;
103
104
  });
104
105
  };
105
106
  return {
106
- register: f,
107
+ register: l,
107
108
  registerAll: p,
108
109
  unregister: y,
109
- mount: g,
110
- unmount: d,
110
+ mount: d,
111
+ unmount: g,
111
112
  mountAll: async (t) => {
112
113
  for (const e of r().keys())
113
- await g(e, t(e));
114
+ await d(e, t(e));
114
115
  },
115
116
  unmountAll: async () => {
116
117
  for (const t of n())
117
- await d(t);
118
+ await g(t);
118
119
  },
119
120
  components: r,
120
121
  mountedComponents: n,
@@ -5,6 +5,10 @@ export interface UseOverlayMaskOptions {
5
5
  open: Accessor<boolean>;
6
6
  root: Accessor<HTMLElement | undefined>;
7
7
  onClose?: () => void;
8
+ /** Treat additional nodes as part of the overlay surface (e.g. portaled layers). */
9
+ containsTarget?: (target: EventTarget | null) => boolean;
10
+ /** Optional alternate close path for Escape pressed outside the overlay surface. */
11
+ onEscapeOutside?: () => void;
8
12
  /** Lock `document.body` scroll while the overlay is open (default: true). */
9
13
  lockBodyScroll?: boolean;
10
14
  /** Prevent scroll via wheel events (default: none). */
@@ -1,26 +1,29 @@
1
- import { createEffect as L, onCleanup as M } from "solid-js";
2
- import { lockBodyStyle as O } from "../utils/bodyStyleLock.js";
3
- import { deferAfterPaint as k } from "../utils/defer.js";
4
- import { getFocusableElements as T, getFirstFocusableElement as B } from "../utils/focus.js";
5
- function i(t) {
1
+ import { createEffect as T, onCleanup as O } from "solid-js";
2
+ import { lockBodyStyle as M } from "../utils/bodyStyleLock.js";
3
+ import { deferAfterPaint as p } from "../utils/defer.js";
4
+ import { getFocusableElements as B, getFirstFocusableElement as D } from "../utils/focus.js";
5
+ function b(t) {
6
6
  return typeof Node < "u" && t instanceof Node;
7
7
  }
8
- function p(t, u, c) {
9
- return c === "none" ? !1 : c === "all" || !t || !i(u) ? !0 : !t.contains(u);
8
+ function i(t, c, r) {
9
+ return r ? r(c) : !t || !b(c) ? !1 : t.contains(c);
10
+ }
11
+ function k(t, c, r, u) {
12
+ return r === "none" ? !1 : r === "all" ? !0 : !i(t, c, u);
10
13
  }
11
14
  function H(t) {
12
- const u = () => t.lockBodyScroll !== !1, c = () => t.trapFocus !== !1, s = () => t.closeOnEscape === !1 ? "none" : t.closeOnEscape === "inside" ? "inside" : t.closeOnEscape === "none" ? "none" : "always", b = () => t.blockHotkeys !== !1, w = () => t.restoreFocus !== !1;
13
- L(() => {
15
+ const c = () => t.lockBodyScroll !== !1, r = () => t.trapFocus !== !1, u = () => t.closeOnEscape === !1 ? "none" : t.closeOnEscape === "inside" ? "inside" : t.closeOnEscape === "none" ? "none" : "always", g = () => t.blockHotkeys !== !1, w = () => t.restoreFocus !== !1;
16
+ T(() => {
14
17
  if (!t.open() || typeof document > "u") return;
15
- const f = document.activeElement instanceof HTMLElement ? document.activeElement : null, g = u() ? O({ overflow: "hidden" }) : null;
16
- k(() => {
18
+ const f = document.activeElement instanceof HTMLElement ? document.activeElement : null, L = c() ? M({ overflow: "hidden" }) : null;
19
+ p(() => {
17
20
  const e = t.root();
18
21
  if (!e) return;
19
22
  const n = t.autoFocus;
20
23
  if (n === !1) return;
21
- const o = typeof n == "object" ? n.selector : void 0, a = (o ? e.querySelector(o) : null) ?? e.querySelector("[data-floe-autofocus]") ?? B(e) ?? e;
24
+ const o = typeof n == "object" ? n.selector : void 0, l = (o ? e.querySelector(o) : null) ?? e.querySelector("[data-floe-autofocus]") ?? D(e) ?? e;
22
25
  try {
23
- a.focus();
26
+ l.focus();
24
27
  } catch {
25
28
  }
26
29
  });
@@ -28,7 +31,7 @@ function H(t) {
28
31
  if (e.key !== "Tab") return;
29
32
  const n = t.root();
30
33
  if (!n) return;
31
- const o = T(n);
34
+ const o = B(n);
32
35
  if (!o.length) {
33
36
  e.preventDefault();
34
37
  try {
@@ -37,48 +40,50 @@ function H(t) {
37
40
  }
38
41
  return;
39
42
  }
40
- const r = o[0], a = o[o.length - 1], l = document.activeElement instanceof HTMLElement ? document.activeElement : null;
43
+ const a = o[0], l = o[o.length - 1], s = document.activeElement instanceof HTMLElement ? document.activeElement : null;
41
44
  if (e.shiftKey) {
42
- if (l === r || !l || !n.contains(l)) {
45
+ if (s === a || !s || !n.contains(s)) {
43
46
  e.preventDefault();
44
47
  try {
45
- a.focus();
48
+ l.focus();
46
49
  } catch {
47
50
  }
48
51
  }
49
- } else if (l === a) {
52
+ } else if (s === l) {
50
53
  e.preventDefault();
51
54
  try {
52
- r.focus();
55
+ a.focus();
53
56
  } catch {
54
57
  }
55
58
  }
56
59
  }, m = (e) => {
57
60
  if (e.key !== "Escape") return;
58
- const n = s();
59
- if (n !== "none") {
60
- if (n === "inside") {
61
- const o = t.root();
62
- if (!o) return;
63
- const r = i(e.target) ? e.target : document.activeElement;
64
- if (!r || !o.contains(r)) return;
61
+ const n = u();
62
+ if (n === "none") return;
63
+ const o = t.root(), a = i(o, b(e.target) ? e.target : document.activeElement, t.containsTarget);
64
+ if (n === "inside") {
65
+ if (a) {
66
+ e.preventDefault(), e.stopImmediatePropagation(), t.onClose?.();
67
+ return;
65
68
  }
66
- e.preventDefault(), e.stopImmediatePropagation(), t.onClose?.();
69
+ t.onEscapeOutside && (e.preventDefault(), e.stopImmediatePropagation(), t.onEscapeOutside());
70
+ return;
67
71
  }
72
+ e.preventDefault(), e.stopImmediatePropagation(), t.onClose?.();
68
73
  }, v = (e) => {
69
74
  const n = t.root();
70
- n && b() && i(e.target) && n.contains(e.target) && e.stopPropagation();
75
+ n && g() && i(n, e.target, t.containsTarget) && e.stopPropagation();
71
76
  }, y = (e) => {
72
77
  const n = t.blockWheel ?? "none", o = t.root();
73
- p(o, e.target, n) && e.cancelable && e.preventDefault();
78
+ k(o, e.target, n, t.containsTarget) && e.cancelable && e.preventDefault();
74
79
  }, h = (e) => {
75
80
  e.stopPropagation();
76
81
  }, E = (e) => {
77
82
  const n = t.blockTouchMove ?? "none", o = t.root();
78
- p(o, e.target, n) && e.cancelable && e.preventDefault();
83
+ k(o, e.target, n, t.containsTarget) && e.cancelable && e.preventDefault();
79
84
  };
80
- c() && document.addEventListener("keydown", d, !0), s() !== "none" && window.addEventListener("keydown", m, !0), document.addEventListener("keydown", v), (t.blockWheel ?? "none") !== "none" && (document.addEventListener("wheel", y, { capture: !0, passive: !1 }), document.addEventListener("wheel", h)), (t.blockTouchMove ?? "none") !== "none" && document.addEventListener("touchmove", E, { capture: !0, passive: !1 }), M(() => {
81
- c() && document.removeEventListener("keydown", d, !0), s() !== "none" && window.removeEventListener("keydown", m, !0), document.removeEventListener("keydown", v), (t.blockWheel ?? "none") !== "none" && (document.removeEventListener("wheel", y, !0), document.removeEventListener("wheel", h)), (t.blockTouchMove ?? "none") !== "none" && document.removeEventListener("touchmove", E, !0), g?.(), w() && f && f.isConnected && k(() => {
85
+ r() && document.addEventListener("keydown", d, !0), u() !== "none" && window.addEventListener("keydown", m, !0), document.addEventListener("keydown", v), (t.blockWheel ?? "none") !== "none" && (document.addEventListener("wheel", y, { capture: !0, passive: !1 }), document.addEventListener("wheel", h)), (t.blockTouchMove ?? "none") !== "none" && document.addEventListener("touchmove", E, { capture: !0, passive: !1 }), O(() => {
86
+ r() && document.removeEventListener("keydown", d, !0), u() !== "none" && window.removeEventListener("keydown", m, !0), document.removeEventListener("keydown", v), (t.blockWheel ?? "none") !== "none" && (document.removeEventListener("wheel", y, !0), document.removeEventListener("wheel", h)), (t.blockTouchMove ?? "none") !== "none" && document.removeEventListener("touchmove", E, !0), L?.(), w() && f && f.isConnected && p(() => {
82
87
  if (typeof document > "u") return;
83
88
  const e = document.activeElement;
84
89
  if (!(e && e !== document.body && e !== document.documentElement))
@@ -1209,12 +1209,16 @@
1209
1209
  }
1210
1210
 
1211
1211
  .notes-trash-note__body {
1212
- flex: 1;
1212
+ display: flex;
1213
+ flex: 1 1 auto;
1214
+ min-height: 0;
1215
+ overflow: hidden;
1213
1216
  padding: 0.18rem 0.78rem 0.65rem;
1214
1217
  }
1215
1218
 
1216
1219
  .notes-trash-note__body span {
1217
1220
  display: -webkit-box;
1221
+ width: 100%;
1218
1222
  overflow: hidden;
1219
1223
  color: color-mix(in srgb, var(--notes-ink) 92%, black 8%);
1220
1224
  font-size: 0.83rem;
@@ -1239,6 +1243,7 @@
1239
1243
 
1240
1244
  .notes-trash-note__actions {
1241
1245
  display: flex;
1246
+ flex-shrink: 0;
1242
1247
  gap: 0.35rem;
1243
1248
  padding: 0 0.72rem 0.72rem;
1244
1249
  margin-top: auto;
@@ -1246,6 +1251,9 @@
1246
1251
 
1247
1252
  .notes-trash-note__actions button {
1248
1253
  flex: 1;
1254
+ display: inline-flex;
1255
+ align-items: center;
1256
+ justify-content: center;
1249
1257
  min-width: 0;
1250
1258
  padding: 0.44rem 0.1rem;
1251
1259
  cursor: pointer;
@@ -1253,6 +1261,7 @@
1253
1261
  color: color-mix(in srgb, var(--foreground) 84%, var(--muted-foreground));
1254
1262
  font-size: 0.68rem;
1255
1263
  font-weight: 650;
1264
+ white-space: nowrap;
1256
1265
  transition:
1257
1266
  transform 140ms ease,
1258
1267
  color 140ms ease,