@v1nt1248/3nclient-lib 0.4.0 → 0.4.2

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 (28) hide show
  1. package/README.md +2 -0
  2. package/dist/chunks/{plugins-keys-DdadrIAg.js → plugins-keys-DY2USp8H.js} +550 -536
  3. package/dist/chunks/ui3n-tooltip-6Z-sRX7U.js +409 -0
  4. package/dist/src/components/ui3n-tooltip/types.d.ts +8 -2
  5. package/dist/src/components/ui3n-tooltip/ui3n-tooltip-container.d.ts +16 -0
  6. package/dist/src/components/ui3n-tooltip/ui3n-tooltip.d.ts +1 -2
  7. package/dist/src/constants/plugins-keys.d.ts +2 -0
  8. package/dist/src/index.d.ts +3 -0
  9. package/dist/src/plugins/index.d.ts +4 -1
  10. package/dist/src/plugins/tooltips/store-tooltips.d.ts +4 -0
  11. package/dist/src/plugins/tooltips/tooltips.d.ts +8 -0
  12. package/dist/src/plugins/tooltips/types.d.ts +34 -0
  13. package/dist/src/ui3n-plugins.d.ts +5 -3
  14. package/dist/src/utils/ui/has-slot-content.d.ts +8 -2
  15. package/dist/src/utils/ui/mark-search.d.ts +8 -0
  16. package/dist/style.css +1 -1
  17. package/dist/ui3n-components.js +1345 -1466
  18. package/dist/ui3n-plugins.js +168 -50
  19. package/dist/ui3n-utils.js +4 -4
  20. package/package.json +1 -1
  21. package/src/components/ui3n-autocomplete/ui3n-autocomplete.vue +24 -8
  22. package/src/components/ui3n-breadcrumbs/ui3n-breadcrumb.vue +3 -1
  23. package/src/components/ui3n-editable/useContentEditable.ts +5 -1
  24. package/src/components/ui3n-tooltip/types.ts +8 -2
  25. package/src/components/ui3n-tooltip/ui3n-tooltip-container.vue +79 -0
  26. package/src/components/ui3n-tooltip/ui3n-tooltip.vue +112 -62
  27. package/dist/chunks/ui3n-notification-CTYQV3nR.js +0 -273
  28. package/src/components/ui3n-tooltip/ui3n-tooltip-old.vue +0 -201
@@ -1,12 +1,12 @@
1
- import { H as e, i as t, n, r, t as i } from "./chunks/plugins-keys-DdadrIAg.js";
2
- import { i as a, t as o } from "./chunks/ui3n-notification-CTYQV3nR.js";
3
- import { Fragment as s, createApp as c, createBlock as l, createElementBlock as u, defineComponent as d, markRaw as f, mergeProps as p, normalizeClass as m, openBlock as h, ref as g, renderList as _ } from "vue";
1
+ import { U as e, a as t, i as n, n as r, r as i, t as a } from "./chunks/plugins-keys-DY2USp8H.js";
2
+ import { a as o, n as s, t as c } from "./chunks/ui3n-tooltip-6Z-sRX7U.js";
3
+ import { Fragment as l, createApp as u, createBlock as d, createElementBlock as f, defineComponent as p, markRaw as m, mergeProps as h, normalizeClass as g, openBlock as _, ref as v, renderList as y } from "vue";
4
4
  import "pinia";
5
- import v from "mitt";
6
- var y = /* @__PURE__ */ a(/* @__PURE__ */ d({
5
+ import b from "mitt";
6
+ var x = /* @__PURE__ */ o(/* @__PURE__ */ p({
7
7
  __name: "ui3n-notification-container",
8
8
  setup(e, { expose: t }) {
9
- let n = g([]);
9
+ let n = v([]);
10
10
  function r(e) {
11
11
  n.value.push(e);
12
12
  }
@@ -19,19 +19,19 @@ var y = /* @__PURE__ */ a(/* @__PURE__ */ d({
19
19
  return t({
20
20
  add: r,
21
21
  remove: i
22
- }), (e, t) => (h(), u("div", {
22
+ }), (e, t) => (_(), f("div", {
23
23
  id: "ui3n-notifications-container",
24
24
  "data-ui3n": "notification-container",
25
- class: m(e.$style.ui3nNotificationsWrapper)
26
- }, [(h(!0), u(s, null, _(n.value, (e) => (h(), l(o, p({ key: e.id }, { ref_for: !0 }, e, { "on-close": () => a(e) }), null, 16, ["on-close"]))), 128))], 2));
25
+ class: g(e.$style.ui3nNotificationsWrapper)
26
+ }, [(_(!0), f(l, null, y(n.value, (e) => (_(), d(s, h({ key: e.id }, { ref_for: !0 }, e, { "on-close": () => a(e) }), null, 16, ["on-close"]))), 128))], 2));
27
27
  }
28
- }), [["__cssModules", { $style: { ui3nNotificationsWrapper: "_ui3nNotificationsWrapper_n58wk_1" } }]]), b = { install: (t) => {
28
+ }), [["__cssModules", { $style: { ui3nNotificationsWrapper: "_ui3nNotificationsWrapper_n58wk_1" } }]]), S = { install: (t) => {
29
29
  if (typeof window > "u") return;
30
- let r = document.createElement("div");
31
- document.body.appendChild(r);
32
- let i = c(y);
30
+ let n = document.createElement("div");
31
+ document.body.appendChild(n);
32
+ let i = u(x);
33
33
  i._context.provides = t._context.provides;
34
- let a = i.mount(r), o = (t) => {
34
+ let a = i.mount(n), o = (t) => {
35
35
  let n = t.id || e(6), r = t.duration === void 0 ? 1500 : t.duration;
36
36
  a.add({
37
37
  ...t,
@@ -39,33 +39,33 @@ var y = /* @__PURE__ */ a(/* @__PURE__ */ d({
39
39
  duration: r
40
40
  });
41
41
  };
42
- t.config.globalProperties.$createNotice = o, t.provide(n, { $createNotice: o });
43
- } }, x = v(), S = {
44
- on: x.on.bind(x),
42
+ t.config.globalProperties.$createNotice = o, t.provide(r, { $createNotice: o });
43
+ } }, C = b(), w = {
44
+ on: C.on.bind(C),
45
45
  once: (e, t) => {
46
46
  function n() {
47
- x.off(e, n), t.apply(null, arguments);
47
+ C.off(e, n), t.apply(null, arguments);
48
48
  }
49
- x.on(e, n);
49
+ C.on(e, n);
50
50
  },
51
- off: x.off.bind(x),
52
- emit: x.emit.bind(x),
53
- clear: x.all.clear.bind(x)
54
- }, C = { install: (e) => {
55
- e.config.globalProperties.$emitter = S, e.provide(t, { $emitter: S });
56
- } }, w = { install(t) {
57
- let n = g([]);
51
+ off: C.off.bind(C),
52
+ emit: C.emit.bind(C),
53
+ clear: C.all.clear.bind(C.all)
54
+ }, T = { install: (e) => {
55
+ e.config.globalProperties.$emitter = w, e.provide(t, { $emitter: w });
56
+ } }, E = { install(t) {
57
+ let n = v([]);
58
58
  function r(t, r) {
59
59
  return new Promise((i) => {
60
60
  n.value.push({
61
61
  id: e(5),
62
- component: f(t),
62
+ component: m(t),
63
63
  props: r,
64
64
  resolve: i
65
65
  });
66
66
  });
67
67
  }
68
- function a(e, t) {
68
+ function i(e, t) {
69
69
  let r = n.value.findIndex((t) => t.id === e);
70
70
  r !== -1 && (n.value[r].resolve(t), n.value.splice(r, 1));
71
71
  }
@@ -75,30 +75,30 @@ var y = /* @__PURE__ */ a(/* @__PURE__ */ d({
75
75
  t.config.globalProperties.$dialog = {
76
76
  dialogStack: n,
77
77
  $openDialog: r,
78
- $closeDialog: a,
78
+ $closeDialog: i,
79
79
  $closeDialogs: o
80
- }, t.provide(i, {
80
+ }, t.provide(a, {
81
81
  dialogStack: n,
82
82
  $openDialog: r,
83
- $closeDialog: a,
83
+ $closeDialog: i,
84
84
  $closeDialogs: o
85
85
  });
86
86
  } };
87
87
  //#endregion
88
88
  //#region src/plugins/notifications/store-notifications.ts
89
- function T(e) {
89
+ function D(e) {
90
90
  let { app: t = {} } = e, { config: n = {} } = t, { globalProperties: r = {} } = n, { $createNotice: i } = r;
91
91
  return { $createNotice: i };
92
92
  }
93
93
  //#endregion
94
94
  //#region src/plugins/vue-bus/store-vue-bus.ts
95
- function E(e) {
95
+ function O(e) {
96
96
  let { app: t = {} } = e, { config: n = {} } = t, { globalProperties: r = {} } = n, { $emitter: i } = r;
97
97
  return { $emitter: i };
98
98
  }
99
99
  //#endregion
100
100
  //#region src/plugins/dialogs/store-dialog.ts
101
- function D(e) {
101
+ function k(e) {
102
102
  let { app: t = {} } = e, { config: n = {} } = t, { globalProperties: r = {} } = n, { $dialog: i } = r;
103
103
  return { $dialogs: {
104
104
  open: i.$openDialog,
@@ -109,38 +109,38 @@ function D(e) {
109
109
  }
110
110
  //#endregion
111
111
  //#region src/plugins/theme/theme.ts
112
- var O = [
112
+ var A = [
113
113
  "light",
114
114
  "dark",
115
115
  "midnight"
116
- ], k = [
116
+ ], j = [
117
117
  "light-theme",
118
118
  "dark-theme",
119
119
  "midnight-theme"
120
120
  ];
121
- function A(e) {
122
- return typeof e == "string" && O.includes(e);
121
+ function M(e) {
122
+ return typeof e == "string" && A.includes(e);
123
123
  }
124
- function j(e, t) {
124
+ function N(e, t) {
125
125
  e.classList.add("colors");
126
- for (let t of k) e.classList.remove(t);
126
+ for (let t of j) e.classList.remove(t);
127
127
  e.classList.add(`${t}-theme`);
128
128
  }
129
- function M(e) {
129
+ function P(e) {
130
130
  if (e.persist) {
131
131
  let t = e.storageKey ?? "ui3n-theme";
132
132
  try {
133
133
  let e = localStorage.getItem(t);
134
- if (A(e)) return e;
134
+ if (M(e)) return e;
135
135
  } catch {}
136
136
  }
137
- return A(e.theme) ? e.theme : "light";
137
+ return M(e.theme) ? e.theme : "light";
138
138
  }
139
- var N = { install(e, t = {}) {
140
- let n = t.persist ?? !1, i = t.storageKey ?? "ui3n-theme", a = g(typeof document > "u" ? t.theme ?? "light" : M(t));
139
+ var F = { install(e, t = {}) {
140
+ let n = t.persist ?? !1, r = t.storageKey ?? "ui3n-theme", a = v(typeof document > "u" ? t.theme ?? "light" : P(t));
141
141
  function o(e) {
142
- if (A(e) && (a.value = e, !(typeof document > "u") && (j(t.target ?? document.documentElement, e), n))) try {
143
- localStorage.setItem(i, e);
142
+ if (M(e) && (a.value = e, !(typeof document > "u") && (N(t.target ?? document.documentElement, e), n))) try {
143
+ localStorage.setItem(r, e);
144
144
  } catch {}
145
145
  }
146
146
  typeof document < "u" && o(a.value);
@@ -148,13 +148,131 @@ var N = { install(e, t = {}) {
148
148
  theme: a,
149
149
  setTheme: o
150
150
  };
151
- e.provide(r, s), e.config.globalProperties.$theme = s;
151
+ e.provide(i, s), e.config.globalProperties.$theme = s;
152
152
  } };
153
153
  //#endregion
154
154
  //#region src/plugins/theme/store-theme.ts
155
- function P(e) {
155
+ function I(e) {
156
156
  let { app: t = {} } = e, { config: n = {} } = t, { globalProperties: r = {} } = n, { $theme: i } = r;
157
157
  return { $theme: i };
158
158
  }
159
+ var L = /* @__PURE__ */ o(/* @__PURE__ */ p({
160
+ __name: "ui3n-tooltip-container",
161
+ setup(e, { expose: t }) {
162
+ let n = v([]);
163
+ function r(e) {
164
+ n.value.push(e);
165
+ }
166
+ function i(e) {
167
+ n.value = n.value.filter((t) => t.id !== e);
168
+ }
169
+ function a(e) {
170
+ n.value = n.value.filter((t) => t.kind !== e);
171
+ }
172
+ function o(e) {
173
+ n.value = n.value.filter((t) => !(t.kind === "attach" && t.target === e));
174
+ }
175
+ function s(e, t) {
176
+ let r = n.value.find((t) => t.id === e);
177
+ r && Object.assign(r, t);
178
+ }
179
+ function u() {
180
+ n.value = [];
181
+ }
182
+ function p(e) {
183
+ return {
184
+ id: e.id,
185
+ content: e.content,
186
+ maxContentWidth: e.maxContentWidth,
187
+ color: e.color,
188
+ textColor: e.textColor,
189
+ placement: e.placement,
190
+ positionStrategy: e.positionStrategy ?? "fixed",
191
+ offsetX: e.offsetX,
192
+ offsetY: e.offsetY,
193
+ trigger: e.trigger,
194
+ modelValue: e.modelValue,
195
+ disabled: e.disabled,
196
+ triggerElement: e.target
197
+ };
198
+ }
199
+ return t({
200
+ add: r,
201
+ remove: i,
202
+ removeByKind: a,
203
+ removeByTarget: o,
204
+ update: s,
205
+ clearAll: u
206
+ }), (e, t) => (_(), f("div", {
207
+ id: "ui3n-tooltips-container",
208
+ "data-ui3n": "tooltip-container",
209
+ class: g(e.$style.container)
210
+ }, [(_(!0), f(l, null, y(n.value, (e) => (_(), d(c, h({ key: e.id }, { ref_for: !0 }, p(e)), null, 16))), 128))], 2));
211
+ }
212
+ }), [["__cssModules", { $style: { container: "_container_zxf3h_1" } }]]), R = { install: (t) => {
213
+ if (typeof window > "u") return;
214
+ let r = document.createElement("div");
215
+ document.body.appendChild(r);
216
+ let i = u(L);
217
+ i._context.provides = t._context.provides;
218
+ let a = i.mount(r);
219
+ function o(e, t) {
220
+ return {
221
+ id: e,
222
+ close: () => {
223
+ t === "show" ? l() : d(e);
224
+ },
225
+ update: (t) => a.update(e, t)
226
+ };
227
+ }
228
+ function s(t, n) {
229
+ a.removeByKind("show");
230
+ let r = e(6);
231
+ return a.add({
232
+ ...n,
233
+ id: r,
234
+ kind: "show",
235
+ target: m(t),
236
+ trigger: "manual",
237
+ modelValue: !0,
238
+ positionStrategy: n.positionStrategy ?? "fixed"
239
+ }), o(r, "show");
240
+ }
241
+ function c(t, n) {
242
+ t instanceof HTMLElement && a.removeByTarget(t);
243
+ let r = e(6);
244
+ return a.add({
245
+ ...n,
246
+ id: r,
247
+ kind: "attach",
248
+ target: m(t),
249
+ trigger: n.trigger ?? "hover",
250
+ positionStrategy: n.positionStrategy ?? "fixed"
251
+ }), o(r, "attach");
252
+ }
253
+ function l() {
254
+ a.removeByKind("show");
255
+ }
256
+ function d(e) {
257
+ typeof e == "string" ? a.remove(e) : a.removeByTarget(e);
258
+ }
259
+ function f() {
260
+ a.clearAll();
261
+ }
262
+ let p = {
263
+ show: s,
264
+ attach: c,
265
+ hide: l,
266
+ detach: d,
267
+ detachAll: f
268
+ };
269
+ t.config.globalProperties.$tooltip = p, t.provide(n, p);
270
+ } };
271
+ //#endregion
272
+ //#region src/plugins/tooltips/store-tooltips.ts
273
+ function z(e) {
274
+ let { app: t = {} } = e, { config: n = {} } = t, { globalProperties: r = {} } = n, { $tooltip: i } = r;
275
+ return { $tooltip: i };
276
+ }
159
277
  //#endregion
160
- export { i as DIALOGS_KEY, n as NOTIFICATIONS_KEY, r as THEME_KEY, t as VUEBUS_KEY, w as dialogs, b as notifications, D as storeDialogs, T as storeNotifications, P as storeTheme, E as storeVueBus, N as theme, C as vueBus };
278
+ export { a as DIALOGS_KEY, r as NOTIFICATIONS_KEY, i as THEME_KEY, n as TOOLTIPS_KEY, t as VUEBUS_KEY, E as dialogs, S as notifications, k as storeDialogs, D as storeNotifications, I as storeTheme, z as storeTooltips, O as storeVueBus, F as theme, R as tooltips, T as vueBus };
@@ -1,6 +1,6 @@
1
- import { A as e, C as t, D as n, E as r, F as i, G as a, H as o, I as s, J as c, K as l, L as u, M as d, N as f, O as p, P as m, R as h, S as g, T as _, U as v, V as y, W as b, X as x, Y as S, Z as C, _ as w, a as T, b as E, c as D, d as O, f as k, g as A, h as j, i as M, j as N, k as P, l as F, m as I, n as L, o as R, p as z, q as B, r as V, s as H, t as U, u as W, v as G, w as K, x as q, y as J, z as Y } from "./chunks/plugins-keys-DdadrIAg.js";
2
- import { t as X } from "./chunks/emoticons-DMgiBINj.js";
1
+ import { A as e, B as t, C as n, D as r, E as i, F as a, G as o, H as s, I as c, J as l, K as u, L as d, M as f, N as p, O as m, P as h, Q as g, R as _, S as v, T as y, U as b, W as x, X as S, Y as C, Z as w, _ as T, a as E, b as D, c as O, d as k, f as A, g as j, h as M, i as N, j as P, k as F, l as I, m as L, n as R, o as z, p as B, q as V, r as H, s as U, t as W, u as G, v as K, w as q, x as J, y as Y, z as X } from "./chunks/plugins-keys-DY2USp8H.js";
2
+ import { t as Z } from "./chunks/emoticons-DMgiBINj.js";
3
3
  //#region src/constants/general.ts
4
- var Z = /[^@]+@[^@]+\.[^@]+/iu;
4
+ var Q = /[^@]+@[^@]+\.[^@]+/iu;
5
5
  //#endregion
6
- export { U as DIALOGS_KEY, L as NOTIFICATIONS_KEY, l as NamedProcs, T as SQLiteOn3NStorage, B as SingleCyclicProc, c as SingleProc, V as THEME_KEY, b as TaskRunner, M as VUEBUS_KEY, z as b64ToBlob, k as blobFromDataURL, I as blobToB64, q as capitalize, m as copyToClipboard, D as createVideoThumbnail, N as debounce, C as defer, X as emoticons, f as executeFunc, F as fileToUint8Array, J as formatFileSize, _ as generateColor, i as getDeliveryErrors, Y as getFileExtension, o as getRandomId, r as hasSlotContent, t as html2text, K as invertColor, j as isFileArchive, A as isFileAudio, G as isFileImage, w as isFileVideo, Z as mailReg, S as makeSyncedFunc, n as markSearch, h as mimeTypes, y as patchTextareaMaxRowsSupport, g as prepareDateAsSting, d as removeWhitespaceInString, W as resizeImage, v as round, a as schedulerYield, p as selectAll, P as selectEnd, e as selectStart, x as sleep, E as toCssLength, s as transformFileToWeb3NFile, u as transformWeb3nFileToFile, R as tryOnScopeDispose, O as uint8ToDataURL, H as unrefElement };
6
+ export { W as DIALOGS_KEY, R as NOTIFICATIONS_KEY, V as NamedProcs, z as SQLiteOn3NStorage, l as SingleCyclicProc, C as SingleProc, H as THEME_KEY, N as TOOLTIPS_KEY, o as TaskRunner, E as VUEBUS_KEY, L as b64ToBlob, B as blobFromDataURL, M as blobToB64, v as capitalize, a as copyToClipboard, I as createVideoThumbnail, f as debounce, g as defer, Z as emoticons, h as executeFunc, G as fileToUint8Array, D as formatFileSize, i as generateColor, c as getDeliveryErrors, t as getFileExtension, b as getRandomId, r as hasSlotContent, q as html2text, y as invertColor, j as isFileArchive, T as isFileAudio, Y as isFileImage, K as isFileVideo, Q as mailReg, S as makeSyncedFunc, m as markSearch, X as mimeTypes, s as patchTextareaMaxRowsSupport, n as prepareDateAsSting, p as removeWhitespaceInString, k as resizeImage, x as round, u as schedulerYield, F as selectAll, e as selectEnd, P as selectStart, w as sleep, J as toCssLength, d as transformFileToWeb3NFile, _ as transformWeb3nFileToFile, U as tryOnScopeDispose, A as uint8ToDataURL, O as unrefElement };
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@v1nt1248/3nclient-lib",
3
3
  "license": "AGPL-3.0-or-later",
4
4
  "author": "v1nt1248",
5
- "version": "0.4.0",
5
+ "version": "0.4.2",
6
6
  "description": "Library for 3NWeb clients",
7
7
  "type": "module",
8
8
  "files": [
@@ -48,7 +48,9 @@
48
48
  );
49
49
 
50
50
  const displayValue = computed(() => {
51
- if (props.chips) return '';
51
+ if (props.chips) {
52
+ return '';
53
+ }
52
54
 
53
55
  if (props.returnObject) {
54
56
  return (props.modelValue as T[]).map(v => v[props.itemTitle] || '?').join(', ');
@@ -62,7 +64,9 @@
62
64
  return props.items
63
65
  .filter(item => props.customFilter!(item, query.value))
64
66
  .filter(item => {
65
- if (!props.hideSelected) return true;
67
+ if (!props.hideSelected) {
68
+ return true;
69
+ }
66
70
 
67
71
  return props.returnObject
68
72
  ? !(ids.value as string[]).includes(item.id as string)
@@ -73,7 +77,9 @@
73
77
  return props.items
74
78
  .filter(item => (item[props.itemTitle] as string).toLowerCase().includes(query.value.toLowerCase()))
75
79
  .filter(item => {
76
- if (!props.hideSelected) return true;
80
+ if (!props.hideSelected) {
81
+ return true;
82
+ }
77
83
 
78
84
  return props.returnObject
79
85
  ? !(ids.value as string[]).includes(item.id as string)
@@ -130,14 +136,20 @@
130
136
  }
131
137
 
132
138
  function tryAddNewValue(): boolean {
133
- if (!props.addNewValue || props.disabled) return false;
139
+ if (!props.addNewValue || props.disabled) {
140
+ return false;
141
+ }
134
142
 
135
143
  const text = query.value.trim();
136
- if (!text) return false;
144
+ if (!text) {
145
+ return false;
146
+ }
137
147
 
138
148
  isNewValueValid.value = !props.newValueValidator ? true : props.newValueValidator(text);
139
149
  emits('valid:new-value', isNewValueValid.value);
140
- if (!isNewValueValid.value) return false;
150
+ if (!isNewValueValid.value) {
151
+ return false;
152
+ }
141
153
 
142
154
  const item = {
143
155
  id: getRandomId(6),
@@ -173,7 +185,9 @@
173
185
  }
174
186
 
175
187
  function onItemClick(item: T) {
176
- if (props.disabled || isItemDisabled(item)) return;
188
+ if (props.disabled || isItemDisabled(item)) {
189
+ return;
190
+ }
177
191
 
178
192
  if (!props.multiple) {
179
193
  const newValue = props.returnObject ? [item] : [item[props.itemValue]];
@@ -198,7 +212,9 @@
198
212
  }
199
213
 
200
214
  function onChipClose(item: T | T[keyof T]) {
201
- if (props.disabled) return;
215
+ if (props.disabled) {
216
+ return;
217
+ }
202
218
 
203
219
  const index = props.returnObject
204
220
  ? (props.modelValue as T[]).findIndex(v => v.id === (item as T).id)
@@ -18,7 +18,9 @@
18
18
  const parentContext = inject<any>('ui3n-breadcrumbs-context', null);
19
19
 
20
20
  const separatorValue = computed(() => {
21
- if (props.separator) return props.separator;
21
+ if (props.separator) {
22
+ return props.separator;
23
+ }
22
24
  return parentContext ? parentContext.separator() : '/';
23
25
  });
24
26
 
@@ -24,8 +24,12 @@ export function useContentEditable(props: Ui3nContentEditableProps, emits: Ui3nC
24
24
  }
25
25
 
26
26
  function setHtmlFromValue(value: string): void {
27
+ if (!el.value) {
28
+ return;
29
+ }
30
+
27
31
  const sanitizedValue = value ? sanitizeHtml(value) : value;
28
- el.value!.innerText = convertValueToHtml(sanitizedValue);
32
+ el.value.innerText = convertValueToHtml(sanitizedValue);
29
33
  }
30
34
 
31
35
  function getContent(ev: Event): Nullable<string> {
@@ -1,4 +1,5 @@
1
1
  import { VNode } from 'vue';
2
+ import type { Ui3nVirtualElement } from '../ui3n-menu/types';
2
3
 
3
4
  /**
4
5
  * Tooltip placement types
@@ -49,9 +50,14 @@ export interface Ui3nTooltipProps {
49
50
  * Tooltip placement
50
51
  */
51
52
  placement?: Ui3nTooltipPlacement;
53
+ /**
54
+ * External element the tooltip is positioned against.
55
+ * When set, this node is the floating-ui reference and receives hover/click listeners.
56
+ */
57
+ triggerElement?: HTMLElement | Ui3nVirtualElement;
52
58
  /**
53
59
  * Position strategy
54
- * @default 'absolute'
60
+ * @default 'absolute' (or 'fixed' when triggerElement is set)
55
61
  */
56
62
  positionStrategy?: 'absolute' | 'fixed';
57
63
  /**
@@ -107,7 +113,7 @@ export interface Ui3nTooltipSlots {
107
113
  /**
108
114
  * Default slot
109
115
  */
110
- default: () => VNode;
116
+ default?: () => VNode;
111
117
  /**
112
118
  * Content slot
113
119
  */
@@ -0,0 +1,79 @@
1
+ <script lang="ts" setup>
2
+ import { ref } from 'vue';
3
+ import Ui3nTooltip from './ui3n-tooltip.vue';
4
+ import type { TooltipInstance, Ui3nTooltipShowOptions } from '../../plugins/tooltips/types';
5
+
6
+ const items = ref<TooltipInstance[]>([]);
7
+
8
+ function add(item: TooltipInstance) {
9
+ items.value.push(item);
10
+ }
11
+
12
+ function remove(id: string) {
13
+ items.value = items.value.filter(item => item.id !== id);
14
+ }
15
+
16
+ function removeByKind(kind: 'show' | 'attach') {
17
+ items.value = items.value.filter(item => item.kind !== kind);
18
+ }
19
+
20
+ function removeByTarget(target: HTMLElement) {
21
+ items.value = items.value.filter(item => !(item.kind === 'attach' && item.target === target));
22
+ }
23
+
24
+ function update(id: string, patch: Partial<Ui3nTooltipShowOptions>) {
25
+ const item = items.value.find(entry => entry.id === id);
26
+ if (item) {
27
+ Object.assign(item, patch);
28
+ }
29
+ }
30
+
31
+ function clearAll() {
32
+ items.value = [];
33
+ }
34
+
35
+ function tooltipBind(item: TooltipInstance) {
36
+ return {
37
+ id: item.id,
38
+ content: item.content,
39
+ maxContentWidth: item.maxContentWidth,
40
+ color: item.color,
41
+ textColor: item.textColor,
42
+ placement: item.placement,
43
+ positionStrategy: item.positionStrategy ?? 'fixed',
44
+ offsetX: item.offsetX,
45
+ offsetY: item.offsetY,
46
+ trigger: item.trigger,
47
+ modelValue: item.modelValue,
48
+ disabled: item.disabled,
49
+ triggerElement: item.target,
50
+ };
51
+ }
52
+
53
+ defineExpose({ add, remove, removeByKind, removeByTarget, update, clearAll });
54
+ </script>
55
+
56
+ <template>
57
+ <div
58
+ id="ui3n-tooltips-container"
59
+ data-ui3n="tooltip-container"
60
+ :class="$style.container"
61
+ >
62
+ <ui3n-tooltip
63
+ v-for="item in items"
64
+ :key="item.id"
65
+ v-bind="tooltipBind(item)"
66
+ />
67
+ </div>
68
+ </template>
69
+
70
+ <style lang="scss" module>
71
+ .container {
72
+ position: absolute;
73
+ width: 0;
74
+ height: 0;
75
+ overflow: visible;
76
+ pointer-events: none;
77
+ z-index: 2000;
78
+ }
79
+ </style>