payload-intl 0.0.2 → 0.0.4

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 (69) hide show
  1. package/dist/components/MessageController.js +29 -28
  2. package/dist/components/MessageController.js.map +1 -1
  3. package/dist/components/MessagesForm.js +92 -76
  4. package/dist/components/MessagesForm.js.map +1 -1
  5. package/dist/components/actions/JsonImport.d.ts +1 -1
  6. package/dist/components/actions/JsonImport.js +63 -0
  7. package/dist/components/actions/JsonImport.js.map +1 -0
  8. package/dist/components/actions/Move.d.ts +1 -1
  9. package/dist/components/inputs/InputWrapper.d.ts +1 -1
  10. package/dist/components/inputs/InputWrapper.js +24 -18
  11. package/dist/components/inputs/InputWrapper.js.map +1 -1
  12. package/dist/components/inputs/MessageInput.d.ts +1 -1
  13. package/dist/components/inputs/MessageInput.js +27 -41
  14. package/dist/components/inputs/MessageInput.js.map +1 -1
  15. package/dist/components/inputs/RichTextInput.js +62 -58
  16. package/dist/components/inputs/RichTextInput.js.map +1 -1
  17. package/dist/components/inputs/toolbar/AlignmentControls.d.ts +1 -1
  18. package/dist/components/inputs/toolbar/AlignmentControls.js +47 -44
  19. package/dist/components/inputs/toolbar/AlignmentControls.js.map +1 -1
  20. package/dist/components/inputs/toolbar/BlockElementSelect.d.ts +1 -1
  21. package/dist/components/inputs/toolbar/BlockElementSelect.js +60 -54
  22. package/dist/components/inputs/toolbar/BlockElementSelect.js.map +1 -1
  23. package/dist/components/inputs/toolbar/LinkEditor.d.ts +1 -1
  24. package/dist/components/inputs/toolbar/LinkEditor.js +182 -170
  25. package/dist/components/inputs/toolbar/LinkEditor.js.map +1 -1
  26. package/dist/components/inputs/toolbar/MarkControls.d.ts +1 -1
  27. package/dist/components/inputs/toolbar/MarkControls.js +29 -28
  28. package/dist/components/inputs/toolbar/MarkControls.js.map +1 -1
  29. package/dist/components/inputs/toolbar/RichTextToolbar.d.ts +1 -1
  30. package/dist/components/inputs/toolbar/RichTextToolbar.js +29 -26
  31. package/dist/components/inputs/toolbar/RichTextToolbar.js.map +1 -1
  32. package/dist/components/inputs/variables/VariableChip.d.ts +1 -1
  33. package/dist/components/inputs/variables/VariableChip.js +55 -49
  34. package/dist/components/inputs/variables/VariableChip.js.map +1 -1
  35. package/dist/components/inputs/variables/VariableSuggestion.d.ts +1 -1
  36. package/dist/components/inputs/variables/VariableSuggestion.js +24 -23
  37. package/dist/components/inputs/variables/VariableSuggestion.js.map +1 -1
  38. package/dist/components/inputs/variables/editors/DateVariableEditor.d.ts +1 -1
  39. package/dist/components/inputs/variables/editors/PluralVariableEditor.d.ts +1 -1
  40. package/dist/components/inputs/variables/editors/PluralVariableEditor.js +151 -122
  41. package/dist/components/inputs/variables/editors/PluralVariableEditor.js.map +1 -1
  42. package/dist/components/inputs/variables/editors/SelectVariableEditor.d.ts +1 -1
  43. package/dist/components/inputs/variables/editors/SelectVariableEditor.js +33 -29
  44. package/dist/components/inputs/variables/editors/SelectVariableEditor.js.map +1 -1
  45. package/dist/components/inputs/variables/editors/TagVariableEditor.d.ts +1 -1
  46. package/dist/components/inputs/variables/editors/TagVariableEditor.js +13 -12
  47. package/dist/components/inputs/variables/editors/TagVariableEditor.js.map +1 -1
  48. package/dist/components/inputs/variables/editors/TimeVariableEditor.d.ts +1 -1
  49. package/dist/components/inputs/variables/pickers/NumericVariablePicker.d.ts +1 -1
  50. package/dist/components/inputs/variables/pickers/NumericVariablePicker.js +40 -36
  51. package/dist/components/inputs/variables/pickers/NumericVariablePicker.js.map +1 -1
  52. package/dist/components/inputs/variables/pickers/TemporalElementEditor.d.ts +1 -1
  53. package/dist/components/layout/MessageField.js +42 -38
  54. package/dist/components/layout/MessageField.js.map +1 -1
  55. package/dist/components/layout/MessagesTabs.js +31 -30
  56. package/dist/components/layout/MessagesTabs.js.map +1 -1
  57. package/dist/components/layout/MessagesTree.js +52 -51
  58. package/dist/components/layout/MessagesTree.js.map +1 -1
  59. package/dist/context/messages-form.d.ts +1 -1
  60. package/dist/context/messages-form.js +12 -11
  61. package/dist/context/messages-form.js.map +1 -1
  62. package/dist/exports/link.d.ts +1 -1
  63. package/dist/exports/link.js +11 -10
  64. package/dist/exports/link.js.map +1 -1
  65. package/dist/exports/view.d.ts +1 -1
  66. package/dist/exports/view.js +43 -40
  67. package/dist/exports/view.js.map +1 -1
  68. package/dist/types.d.ts +2 -2
  69. package/package.json +1 -2
@@ -1,205 +1,217 @@
1
- import { IconLink as A, IconCornerDownLeft as I, IconExternalLink as N, IconLinkOff as P } from "@tabler/icons-react";
2
- import { useEditorState as W } from "@tiptap/react";
3
- import { Popover as k, Toolbar as p } from "radix-ui";
4
- import { useState as v, useCallback as d, useEffect as h } from "react";
5
- import { cn as B } from "../../../utils/cn.js";
6
- function q({
1
+ import { jsxs as v, jsx as l } from "react/jsx-runtime";
2
+ import { IconLink as N, IconCornerDownLeft as j, IconExternalLink as P, IconLinkOff as W } from "@tabler/icons-react";
3
+ import { useEditorState as B } from "@tiptap/react";
4
+ import { Popover as g, Toolbar as m } from "radix-ui";
5
+ import { useState as L, useCallback as p, useEffect as k } from "react";
6
+ import { cn as M } from "../../../utils/cn.js";
7
+ function Q({
7
8
  editor: e,
8
- hideWhenUnavailable: t = !1,
9
- onSetLink: n,
10
- onOpenChange: a,
11
- autoOpenOnLinkActive: c = !0,
12
- onClick: u,
13
- className: f,
14
- ...r
9
+ hideWhenUnavailable: n = !1,
10
+ onSetLink: t,
11
+ onOpenChange: i,
12
+ autoOpenOnLinkActive: u = !0,
13
+ onClick: f,
14
+ className: d,
15
+ ...o
15
16
  }) {
16
- const [o, i] = v(!0), { canSet: l, isActive: m, url: b, setUrl: w, setLink: E, removeLink: g, openLink: y } = M({
17
+ const [r, s] = L(!0), { canSet: a, isActive: h, url: b, setUrl: C, setLink: x, removeLink: w, openLink: z } = T({
17
18
  editor: e,
18
- hideWhenUnavailable: t,
19
- onSetLink: n
20
- }), S = d(
21
- (s) => {
22
- i(s), a?.(s);
19
+ hideWhenUnavailable: n,
20
+ onSetLink: t
21
+ }), A = p(
22
+ (c) => {
23
+ s(c), i?.(c);
23
24
  },
24
- [a]
25
- ), R = d(() => {
26
- E(), i(!1);
27
- }, [E]), U = d(() => {
28
- g(), i(!1);
29
- }, [g]), C = d(
30
- (s) => {
31
- u?.(s), !s.defaultPrevented && i(!o);
25
+ [i]
26
+ ), y = p(() => {
27
+ x(), s(!1);
28
+ }, [x]), E = p(() => {
29
+ w(), s(!1);
30
+ }, [w]), I = p(
31
+ (c) => {
32
+ f?.(c), !c.defaultPrevented && s(!r);
32
33
  },
33
- [u, o]
34
- ), z = (s) => {
35
- s.key === "Enter" && (s.preventDefault(), R());
34
+ [f, r]
35
+ ), R = (c) => {
36
+ c.key === "Enter" && (c.preventDefault(), y());
36
37
  };
37
- return h(() => {
38
- c && m && i(!0);
39
- }, [c, m]), /* @__PURE__ */ React.createElement(k.Root, { open: o, onOpenChange: S }, /* @__PURE__ */ React.createElement(k.Trigger, { asChild: !0 }, /* @__PURE__ */ React.createElement(
40
- p.Button,
41
- {
42
- className: B(f, {
43
- "bg-elevation-600 text-elevation-0": m
44
- }),
45
- disabled: !l,
46
- onClick: C,
47
- "aria-label": "Link",
48
- ...r
49
- },
50
- /* @__PURE__ */ React.createElement(A, { size: 16 })
51
- )), /* @__PURE__ */ React.createElement(
52
- k.Content,
53
- {
54
- className: "z-50 rounded-md border border-border bg-elevation-100 p-2 shadow-md",
55
- sideOffset: 8,
56
- align: "end"
57
- },
58
- /* @__PURE__ */ React.createElement(p.Root, { className: "flex items-center gap-2" }, /* @__PURE__ */ React.createElement("div", { className: "flex items-center overflow-hidden rounded-md border border-border focus-within:border-elevation-600" }, /* @__PURE__ */ React.createElement(
59
- "input",
38
+ return k(() => {
39
+ u && h && s(!0);
40
+ }, [u, h]), /* @__PURE__ */ v(g.Root, { open: r, onOpenChange: A, children: [
41
+ /* @__PURE__ */ l(g.Trigger, { asChild: !0, children: /* @__PURE__ */ l(
42
+ m.Button,
60
43
  {
61
- type: "url",
62
- placeholder: "Paste a link...",
63
- autoComplete: "off",
64
- autoCorrect: "off",
65
- autoCapitalize: "off",
66
- value: b,
67
- onChange: (s) => w(s.target.value),
68
- onKeyDown: z,
69
- className: "h-10 flex-1 border-none bg-input px-2 py-1 focus:outline-none",
70
- "aria-label": "Link URL",
71
- style: { minWidth: "200px" }
44
+ className: M(d, {
45
+ "bg-elevation-600 text-elevation-0": h
46
+ }),
47
+ disabled: !a,
48
+ onClick: I,
49
+ "aria-label": "Link",
50
+ ...o,
51
+ children: /* @__PURE__ */ l(N, { size: 16 })
72
52
  }
73
- ), /* @__PURE__ */ React.createElement(
74
- p.Button,
75
- {
76
- type: "button",
77
- title: "Apply link",
78
- disabled: !b && !m,
79
- className: "flex size-10 items-center justify-center !rounded-none border-none bg-elevation-800 p-0 text-elevation-0 hover:bg-elevation-600 disabled:bg-transparent disabled:text-elevation-250",
80
- onClick: R
81
- },
82
- /* @__PURE__ */ React.createElement(I, { size: 16 })
83
- )), /* @__PURE__ */ React.createElement(p.Separator, { className: "mx-1 h-10 w-px bg-border" }), /* @__PURE__ */ React.createElement(
84
- p.Button,
85
- {
86
- type: "button",
87
- className: "flex size-10 items-center justify-center rounded-md border-none bg-transparent p-0 hover:bg-elevation-250",
88
- title: "Open in new window",
89
- disabled: !b && !m,
90
- onClick: () => y()
91
- },
92
- /* @__PURE__ */ React.createElement(N, { size: 16 })
93
- ), /* @__PURE__ */ React.createElement(
94
- p.Button,
53
+ ) }),
54
+ /* @__PURE__ */ l(
55
+ g.Content,
95
56
  {
96
- type: "button",
97
- title: "Remove link",
98
- className: "flex size-10 items-center justify-center rounded-md border-none bg-transparent p-0 hover:bg-elevation-250",
99
- disabled: !b && !m,
100
- onClick: U
101
- },
102
- /* @__PURE__ */ React.createElement(P, { size: 16 })
103
- ))
104
- ));
57
+ className: "z-50 rounded-md border border-border bg-elevation-100 p-2 shadow-md",
58
+ sideOffset: 8,
59
+ align: "end",
60
+ children: /* @__PURE__ */ v(m.Root, { className: "flex items-center gap-2", children: [
61
+ /* @__PURE__ */ v("div", { className: "flex items-center overflow-hidden rounded-md border border-border focus-within:border-elevation-600", children: [
62
+ /* @__PURE__ */ l(
63
+ "input",
64
+ {
65
+ type: "url",
66
+ placeholder: "Paste a link...",
67
+ autoComplete: "off",
68
+ autoCorrect: "off",
69
+ autoCapitalize: "off",
70
+ value: b,
71
+ onChange: (c) => C(c.target.value),
72
+ onKeyDown: R,
73
+ className: "h-10 flex-1 border-none bg-input px-2 py-1 focus:outline-none",
74
+ "aria-label": "Link URL",
75
+ style: { minWidth: "200px" }
76
+ }
77
+ ),
78
+ /* @__PURE__ */ l(
79
+ m.Button,
80
+ {
81
+ type: "button",
82
+ title: "Apply link",
83
+ disabled: !b && !h,
84
+ className: "flex size-10 items-center justify-center !rounded-none border-none bg-elevation-800 p-0 text-elevation-0 hover:bg-elevation-600 disabled:bg-transparent disabled:text-elevation-250",
85
+ onClick: y,
86
+ children: /* @__PURE__ */ l(j, { size: 16 })
87
+ }
88
+ )
89
+ ] }),
90
+ /* @__PURE__ */ l(m.Separator, { className: "mx-1 h-10 w-px bg-border" }),
91
+ /* @__PURE__ */ l(
92
+ m.Button,
93
+ {
94
+ type: "button",
95
+ className: "flex size-10 items-center justify-center rounded-md border-none bg-transparent p-0 hover:bg-elevation-250",
96
+ title: "Open in new window",
97
+ disabled: !b && !h,
98
+ onClick: () => z(),
99
+ children: /* @__PURE__ */ l(P, { size: 16 })
100
+ }
101
+ ),
102
+ /* @__PURE__ */ l(
103
+ m.Button,
104
+ {
105
+ type: "button",
106
+ title: "Remove link",
107
+ className: "flex size-10 items-center justify-center rounded-md border-none bg-transparent p-0 hover:bg-elevation-250",
108
+ disabled: !b && !h,
109
+ onClick: E,
110
+ children: /* @__PURE__ */ l(W, { size: 16 })
111
+ }
112
+ )
113
+ ] })
114
+ }
115
+ )
116
+ ] });
105
117
  }
106
- function M(e) {
107
- const { editor: t, hideWhenUnavailable: n = !1, onSetLink: a } = e || {}, { isVisible: c, canSet: u, isActive: f } = L({
108
- editor: t || null,
109
- hideWhenUnavailable: n
110
- }), r = D({
111
- editor: t || null,
112
- onSetLink: a
118
+ function T(e) {
119
+ const { editor: n, hideWhenUnavailable: t = !1, onSetLink: i } = e || {}, { isVisible: u, canSet: f, isActive: d } = S({
120
+ editor: n || null,
121
+ hideWhenUnavailable: t
122
+ }), o = H({
123
+ editor: n || null,
124
+ onSetLink: i
113
125
  });
114
126
  return {
115
- isVisible: c,
116
- canSet: u,
117
- isActive: f,
118
- ...r
127
+ isVisible: u,
128
+ canSet: f,
129
+ isActive: d,
130
+ ...o
119
131
  };
120
132
  }
121
- function L(e) {
122
- const { editor: t, hideWhenUnavailable: n = !1 } = e, a = x(t), c = W({
123
- editor: t,
124
- selector: (r) => r.editor?.isEditable && r?.editor?.isActive("link")
125
- }) ?? !1, [u, f] = v(!1);
126
- return h(() => {
127
- if (!t) return;
128
- const r = () => {
129
- f(
130
- T({
131
- editor: t,
132
- hideWhenUnavailable: n
133
+ function S(e) {
134
+ const { editor: n, hideWhenUnavailable: t = !1 } = e, i = U(n), u = B({
135
+ editor: n,
136
+ selector: (o) => o.editor?.isEditable && o?.editor?.isActive("link")
137
+ }) ?? !1, [f, d] = L(!1);
138
+ return k(() => {
139
+ if (!n) return;
140
+ const o = () => {
141
+ d(
142
+ D({
143
+ editor: n,
144
+ hideWhenUnavailable: t
133
145
  })
134
146
  );
135
147
  };
136
- return r(), t.on("selectionUpdate", r), () => {
137
- t.off("selectionUpdate", r);
148
+ return o(), n.on("selectionUpdate", o), () => {
149
+ n.off("selectionUpdate", o);
138
150
  };
139
- }, [t, n]), {
140
- isVisible: u,
141
- canSet: a,
142
- isActive: c
151
+ }, [n, t]), {
152
+ isVisible: f,
153
+ canSet: i,
154
+ isActive: u
143
155
  };
144
156
  }
145
- function x(e) {
157
+ function U(e) {
146
158
  return !e || !e.isEditable ? !1 : e.can().setMark("link");
147
159
  }
148
- function T(e) {
149
- const { editor: t, hideWhenUnavailable: n } = e;
150
- return !j("link", t) || !t ? !1 : n && !t.isActive("code") ? x(t) : !0;
160
+ function D(e) {
161
+ const { editor: n, hideWhenUnavailable: t } = e;
162
+ return !O("link", n) || !n ? !1 : t && !n.isActive("code") ? U(n) : !0;
151
163
  }
152
- const j = (e, t) => t?.schema ? t.schema.spec.marks.get(e) !== void 0 : !1;
153
- function D({ editor: e, onSetLink: t }) {
154
- const [n, a] = v(null), { isActive: c } = L({ editor: e, hideWhenUnavailable: !1 });
155
- h(() => {
164
+ const O = (e, n) => n?.schema ? n.schema.spec.marks.get(e) !== void 0 : !1;
165
+ function H({ editor: e, onSetLink: n }) {
166
+ const [t, i] = L(null), { isActive: u } = S({ editor: e, hideWhenUnavailable: !1 });
167
+ k(() => {
156
168
  if (!e) return;
157
- const { href: o } = e.getAttributes("link");
158
- c && n === null && a(o || "");
159
- }, [e, n, c]), h(() => {
169
+ const { href: r } = e.getAttributes("link");
170
+ u && t === null && i(r || "");
171
+ }, [e, t, u]), k(() => {
160
172
  if (!e) return;
161
- const o = () => {
162
- const { href: i } = e.getAttributes("link");
163
- a(i || "");
173
+ const r = () => {
174
+ const { href: s } = e.getAttributes("link");
175
+ i(s || "");
164
176
  };
165
- return e.on("selectionUpdate", o), () => {
166
- e.off("selectionUpdate", o);
177
+ return e.on("selectionUpdate", r), () => {
178
+ e.off("selectionUpdate", r);
167
179
  };
168
180
  }, [e]);
169
- const u = d(() => {
170
- if (!n || !e) return;
171
- const { selection: o } = e.state, i = o.empty;
172
- let l = e.chain().focus();
173
- l = l.extendMarkRange("link").setLink({ href: n }), i && (l = l.insertContent({ type: "text", text: n })), l.run(), a(null), t?.();
174
- }, [e, t, n]), f = d(() => {
175
- e && (e.chain().focus().extendMarkRange("link").unsetLink().setMeta("preventAutolink", !0).run(), a(""));
176
- }, [e]), r = d(
177
- (o = "_blank", i = "noopener,noreferrer") => {
178
- if (!n) return;
179
- const l = O(n, window.location.href);
180
- l !== "#" && window.open(l, o, i);
181
+ const f = p(() => {
182
+ if (!t || !e) return;
183
+ const { selection: r } = e.state, s = r.empty;
184
+ let a = e.chain().focus();
185
+ a = a.extendMarkRange("link").setLink({ href: t }), s && (a = a.insertContent({ type: "text", text: t })), a.run(), i(null), n?.();
186
+ }, [e, n, t]), d = p(() => {
187
+ e && (e.chain().focus().extendMarkRange("link").unsetLink().setMeta("preventAutolink", !0).run(), i(""));
188
+ }, [e]), o = p(
189
+ (r = "_blank", s = "noopener,noreferrer") => {
190
+ if (!t) return;
191
+ const a = V(t, window.location.href);
192
+ a !== "#" && window.open(a, r, s);
181
193
  },
182
- [n]
194
+ [t]
183
195
  );
184
196
  return {
185
- url: n || "",
186
- setUrl: a,
187
- setLink: u,
188
- removeLink: f,
189
- openLink: r
197
+ url: t || "",
198
+ setUrl: i,
199
+ setLink: f,
200
+ removeLink: d,
201
+ openLink: o
190
202
  };
191
203
  }
192
- function O(e, t, n) {
204
+ function V(e, n, t) {
193
205
  try {
194
- const a = new URL(e, t);
195
- if (H(a.href, n))
196
- return a.href;
206
+ const i = new URL(e, n);
207
+ if (K(i.href, t))
208
+ return i.href;
197
209
  } catch {
198
210
  }
199
211
  return "#";
200
212
  }
201
- function H(e, t) {
202
- const n = [
213
+ function K(e, n) {
214
+ const t = [
203
215
  "http",
204
216
  "https",
205
217
  "ftp",
@@ -210,21 +222,21 @@ function H(e, t) {
210
222
  "sms",
211
223
  "cid",
212
224
  "xmpp"
213
- ], a = (
225
+ ], i = (
214
226
  // eslint-disable-next-line no-control-regex
215
227
  /[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g
216
228
  );
217
- return !e || e.replace(a, "").match(
229
+ return !e || e.replace(i, "").match(
218
230
  new RegExp(
219
231
  // eslint-disable-next-line no-useless-escape, regexp/no-obscure-range
220
- `^(?:(?:${n.join("|")}):|[^a-z]|[a-z0-9+.-]+(?:[^a-z+.-:]|$))`,
232
+ `^(?:(?:${t.join("|")}):|[^a-z]|[a-z0-9+.-]+(?:[^a-z+.-:]|$))`,
221
233
  "i"
222
234
  )
223
235
  );
224
236
  }
225
237
  export {
226
- q as LinkEditor,
227
- j as isMarkInSchema,
228
- D as useLinkHandler
238
+ Q as LinkEditor,
239
+ O as isMarkInSchema,
240
+ H as useLinkHandler
229
241
  };
230
242
  //# sourceMappingURL=LinkEditor.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"LinkEditor.js","sources":["../../../../src/components/inputs/toolbar/LinkEditor.tsx"],"sourcesContent":["import type { Editor } from \"@tiptap/react\";\nimport {\n IconCornerDownLeft,\n IconExternalLink,\n IconLink,\n IconLinkOff,\n} from \"@tabler/icons-react\";\nimport { useEditorState } from \"@tiptap/react\";\nimport { Popover, Toolbar } from \"radix-ui\";\nimport { useCallback, useEffect, useState } from \"react\";\n\nimport { cn } from \"@/utils/cn\";\n\nexport interface LinkEditorProps\n extends Omit<React.HTMLAttributes<HTMLButtonElement>, \"type\" | \"children\">,\n UseLinkPopoverConfig {\n /**\n * Callback for when the popover opens or closes.\n */\n onOpenChange?: (isOpen: boolean) => void;\n /**\n * Whether to automatically open the popover when a link is active.\n * @default true\n */\n autoOpenOnLinkActive?: boolean;\n}\n\nexport function LinkEditor({\n editor,\n hideWhenUnavailable = false,\n onSetLink,\n onOpenChange,\n autoOpenOnLinkActive = true,\n onClick,\n className,\n ...buttonProps\n}: LinkEditorProps) {\n const [isOpen, setIsOpen] = useState(true);\n\n const { canSet, isActive, url, setUrl, setLink, removeLink, openLink } =\n useLinkPopover({\n editor,\n hideWhenUnavailable,\n onSetLink,\n });\n\n const handleOnOpenChange = useCallback(\n (nextIsOpen: boolean) => {\n setIsOpen(nextIsOpen);\n onOpenChange?.(nextIsOpen);\n },\n [onOpenChange],\n );\n\n const handleSetLink = useCallback(() => {\n setLink();\n setIsOpen(false);\n }, [setLink]);\n\n const handleRemoveLink = useCallback(() => {\n removeLink();\n setIsOpen(false);\n }, [removeLink]);\n\n const handleClick = useCallback(\n (event: React.MouseEvent<HTMLButtonElement>) => {\n onClick?.(event);\n if (event.defaultPrevented) return;\n setIsOpen(!isOpen);\n },\n [onClick, isOpen],\n );\n\n const handleIputKeyDown = (event: React.KeyboardEvent) => {\n if (event.key === \"Enter\") {\n event.preventDefault();\n handleSetLink();\n }\n };\n\n useEffect(() => {\n if (autoOpenOnLinkActive && isActive) {\n setIsOpen(true);\n }\n }, [autoOpenOnLinkActive, isActive]);\n\n return (\n <Popover.Root open={isOpen} onOpenChange={handleOnOpenChange}>\n <Popover.Trigger asChild>\n <Toolbar.Button\n className={cn(className, {\n \"bg-elevation-600 text-elevation-0\": isActive,\n })}\n disabled={!canSet}\n onClick={handleClick}\n aria-label=\"Link\"\n {...buttonProps}\n >\n <IconLink size={16} />\n </Toolbar.Button>\n </Popover.Trigger>\n\n <Popover.Content\n className=\"z-50 rounded-md border border-border bg-elevation-100 p-2 shadow-md\"\n sideOffset={8}\n align=\"end\"\n >\n <Toolbar.Root className=\"flex items-center gap-2\">\n <div className=\"flex items-center overflow-hidden rounded-md border border-border focus-within:border-elevation-600\">\n <input\n type=\"url\"\n placeholder=\"Paste a link...\"\n autoComplete=\"off\"\n autoCorrect=\"off\"\n autoCapitalize=\"off\"\n value={url}\n onChange={(e) => setUrl(e.target.value)}\n onKeyDown={handleIputKeyDown}\n className=\"h-10 flex-1 border-none bg-input px-2 py-1 focus:outline-none\"\n aria-label=\"Link URL\"\n style={{ minWidth: \"200px\" }}\n />\n\n <Toolbar.Button\n type=\"button\"\n title=\"Apply link\"\n disabled={!url && !isActive}\n className=\"flex size-10 items-center justify-center !rounded-none border-none bg-elevation-800 p-0 text-elevation-0 hover:bg-elevation-600 disabled:bg-transparent disabled:text-elevation-250\"\n onClick={handleSetLink}\n >\n <IconCornerDownLeft size={16} />\n </Toolbar.Button>\n </div>\n\n <Toolbar.Separator className=\"mx-1 h-10 w-px bg-border\" />\n\n <Toolbar.Button\n type=\"button\"\n className=\"flex size-10 items-center justify-center rounded-md border-none bg-transparent p-0 hover:bg-elevation-250\"\n title=\"Open in new window\"\n disabled={!url && !isActive}\n onClick={() => openLink()}\n >\n <IconExternalLink size={16} />\n </Toolbar.Button>\n\n <Toolbar.Button\n type=\"button\"\n title=\"Remove link\"\n className=\"flex size-10 items-center justify-center rounded-md border-none bg-transparent p-0 hover:bg-elevation-250\"\n disabled={!url && !isActive}\n onClick={handleRemoveLink}\n >\n <IconLinkOff size={16} />\n </Toolbar.Button>\n </Toolbar.Root>\n </Popover.Content>\n </Popover.Root>\n );\n}\n\n// TODO this was mostly copied from the tiptap starter template, pretty sure it can be simplified\n\n/**\n * Configuration for the link popover functionality\n */\nexport interface UseLinkPopoverConfig {\n /**\n * The Tiptap editor instance.\n */\n editor?: Editor | null;\n /**\n * Whether to hide the link popover when not available.\n * @default false\n */\n hideWhenUnavailable?: boolean;\n /**\n * Callback function called when the link is set.\n */\n onSetLink?: () => void;\n}\n\n/**\n * Main hook that provides link popover functionality for Tiptap editor\n */\nfunction useLinkPopover(config?: UseLinkPopoverConfig) {\n const { editor, hideWhenUnavailable = false, onSetLink } = config || {};\n\n const { isVisible, canSet, isActive } = useLinkState({\n editor: editor || null,\n hideWhenUnavailable,\n });\n\n const linkHandler = useLinkHandler({\n editor: editor || null,\n onSetLink,\n });\n\n return {\n isVisible,\n canSet,\n isActive,\n ...linkHandler,\n };\n}\n\nfunction useLinkState(props: {\n editor: Editor | null;\n hideWhenUnavailable: boolean;\n}) {\n const { editor, hideWhenUnavailable = false } = props;\n\n const canSet = canSetLink(editor);\n const isActive =\n useEditorState({\n editor,\n selector: (state) =>\n state.editor?.isEditable && state?.editor?.isActive(\"link\"),\n }) ?? false;\n\n const [isVisible, setIsVisible] = useState(false);\n\n useEffect(() => {\n if (!editor) return;\n\n const handleSelectionUpdate = () => {\n setIsVisible(\n shouldShowLinkButton({\n editor,\n hideWhenUnavailable,\n }),\n );\n };\n\n handleSelectionUpdate();\n\n editor.on(\"selectionUpdate\", handleSelectionUpdate);\n\n return () => {\n editor.off(\"selectionUpdate\", handleSelectionUpdate);\n };\n }, [editor, hideWhenUnavailable]);\n\n return {\n isVisible,\n canSet,\n isActive,\n };\n}\n\n/**\n * Checks if a link can be set in the current editor state\n */\nfunction canSetLink(editor: Editor | null): boolean {\n if (!editor || !editor.isEditable) return false;\n return editor.can().setMark(\"link\");\n}\n\n/**\n * Determines if the link button should be shown\n */\nfunction shouldShowLinkButton(props: {\n editor: Editor | null;\n hideWhenUnavailable: boolean;\n}): boolean {\n const { editor, hideWhenUnavailable } = props;\n\n const linkInSchema = isMarkInSchema(\"link\", editor);\n\n if (!linkInSchema || !editor) {\n return false;\n }\n\n if (hideWhenUnavailable && !editor.isActive(\"code\")) {\n return canSetLink(editor);\n }\n\n return true;\n}\n\n/**\n * Checks if a mark exists in the editor schema\n */\nexport const isMarkInSchema = (\n markName: string,\n editor: Editor | null,\n): boolean => {\n if (!editor?.schema) return false;\n return editor.schema.spec.marks.get(markName) !== undefined;\n};\n\n/**\n * Configuration for the link handler functionality\n */\nexport interface LinkHandlerProps {\n /**\n * The Tiptap editor instance.\n */\n editor: Editor | null;\n /**\n * Callback function called when the link is set.\n */\n onSetLink?: () => void;\n}\n\n/**\n * Custom hook for handling link operations in a Tiptap editor\n */\nexport function useLinkHandler({ editor, onSetLink }: LinkHandlerProps) {\n const [url, setUrl] = useState<string | null>(null);\n const { isActive } = useLinkState({ editor, hideWhenUnavailable: false });\n\n useEffect(() => {\n if (!editor) return;\n\n // Get URL immediately on mount\n const { href } = editor.getAttributes(\"link\");\n\n if (isActive && url === null) {\n setUrl(href || \"\");\n }\n }, [editor, url, isActive]);\n\n useEffect(() => {\n if (!editor) return;\n\n const updateLinkState = () => {\n const { href } = editor.getAttributes(\"link\");\n setUrl(href || \"\");\n };\n\n editor.on(\"selectionUpdate\", updateLinkState);\n return () => {\n editor.off(\"selectionUpdate\", updateLinkState);\n };\n }, [editor]);\n\n const setLink = useCallback(() => {\n if (!url || !editor) return;\n\n const { selection } = editor.state;\n const isEmpty = selection.empty;\n\n let chain = editor.chain().focus();\n\n chain = chain.extendMarkRange(\"link\").setLink({ href: url });\n\n if (isEmpty) {\n chain = chain.insertContent({ type: \"text\", text: url });\n }\n\n chain.run();\n\n setUrl(null);\n\n onSetLink?.();\n }, [editor, onSetLink, url]);\n\n const removeLink = useCallback(() => {\n if (!editor) return;\n editor\n .chain()\n .focus()\n .extendMarkRange(\"link\")\n .unsetLink()\n .setMeta(\"preventAutolink\", true)\n .run();\n setUrl(\"\");\n }, [editor]);\n\n const openLink = useCallback(\n (target: string = \"_blank\", features: string = \"noopener,noreferrer\") => {\n if (!url) return;\n\n const safeUrl = sanitizeUrl(url, window.location.href);\n if (safeUrl !== \"#\") {\n window.open(safeUrl, target, features);\n }\n },\n [url],\n );\n\n return {\n url: url || \"\",\n setUrl,\n setLink,\n removeLink,\n openLink,\n };\n}\n\ntype ProtocolOptions = {\n /**\n * The protocol scheme to be registered.\n * @default '''\n * @example 'ftp'\n * @example 'git'\n */\n scheme: string;\n\n /**\n * If enabled, it allows optional slashes after the protocol.\n * @default false\n * @example true\n */\n optionalSlashes?: boolean;\n};\n\ntype ProtocolConfig = Array<ProtocolOptions | string>;\n\nfunction sanitizeUrl(\n inputUrl: string,\n baseUrl: string,\n protocols?: ProtocolConfig,\n): string {\n try {\n const url = new URL(inputUrl, baseUrl);\n\n if (isAllowedUri(url.href, protocols)) {\n return url.href;\n }\n } catch {\n // If URL creation fails, it's considered invalid\n }\n return \"#\";\n}\n\nfunction isAllowedUri(uri: string | undefined, protocols?: ProtocolConfig) {\n const allowedProtocols: string[] = [\n \"http\",\n \"https\",\n \"ftp\",\n \"ftps\",\n \"mailto\",\n \"tel\",\n \"callto\",\n \"sms\",\n \"cid\",\n \"xmpp\",\n ];\n\n if (protocols) {\n protocols.forEach((protocol) => {\n const nextProtocol =\n typeof protocol === \"string\" ? protocol : protocol.scheme;\n\n if (nextProtocol) {\n allowedProtocols.push(nextProtocol);\n }\n });\n }\n\n const ATTR_WHITESPACE =\n // eslint-disable-next-line no-control-regex\n /[\\u0000-\\u0020\\u00A0\\u1680\\u180E\\u2000-\\u2029\\u205F\\u3000]/g;\n\n return (\n !uri ||\n uri.replace(ATTR_WHITESPACE, \"\").match(\n new RegExp(\n // eslint-disable-next-line no-useless-escape, regexp/no-obscure-range\n `^(?:(?:${allowedProtocols.join(\"|\")}):|[^a-z]|[a-z0-9+.\\-]+(?:[^a-z+.\\-:]|$))`,\n \"i\",\n ),\n )\n );\n}\n"],"names":["LinkEditor","editor","hideWhenUnavailable","onSetLink","onOpenChange","autoOpenOnLinkActive","onClick","className","buttonProps","isOpen","setIsOpen","useState","canSet","isActive","url","setUrl","setLink","removeLink","openLink","useLinkPopover","handleOnOpenChange","useCallback","nextIsOpen","handleSetLink","handleRemoveLink","handleClick","event","handleIputKeyDown","useEffect","Popover","Toolbar","cn","IconLink","e","IconCornerDownLeft","IconExternalLink","IconLinkOff","config","isVisible","useLinkState","linkHandler","useLinkHandler","props","canSetLink","useEditorState","state","setIsVisible","handleSelectionUpdate","shouldShowLinkButton","isMarkInSchema","markName","href","updateLinkState","selection","isEmpty","chain","target","features","safeUrl","sanitizeUrl","inputUrl","baseUrl","protocols","isAllowedUri","uri","allowedProtocols","ATTR_WHITESPACE"],"mappings":"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"}
1
+ {"version":3,"file":"LinkEditor.js","sources":["../../../../src/components/inputs/toolbar/LinkEditor.tsx"],"sourcesContent":["import type { Editor } from \"@tiptap/react\";\nimport {\n IconCornerDownLeft,\n IconExternalLink,\n IconLink,\n IconLinkOff,\n} from \"@tabler/icons-react\";\nimport { useEditorState } from \"@tiptap/react\";\nimport { Popover, Toolbar } from \"radix-ui\";\nimport { useCallback, useEffect, useState } from \"react\";\n\nimport { cn } from \"@/utils/cn\";\n\nexport interface LinkEditorProps\n extends Omit<React.HTMLAttributes<HTMLButtonElement>, \"type\" | \"children\">,\n UseLinkPopoverConfig {\n /**\n * Callback for when the popover opens or closes.\n */\n onOpenChange?: (isOpen: boolean) => void;\n /**\n * Whether to automatically open the popover when a link is active.\n * @default true\n */\n autoOpenOnLinkActive?: boolean;\n}\n\nexport function LinkEditor({\n editor,\n hideWhenUnavailable = false,\n onSetLink,\n onOpenChange,\n autoOpenOnLinkActive = true,\n onClick,\n className,\n ...buttonProps\n}: LinkEditorProps) {\n const [isOpen, setIsOpen] = useState(true);\n\n const { canSet, isActive, url, setUrl, setLink, removeLink, openLink } =\n useLinkPopover({\n editor,\n hideWhenUnavailable,\n onSetLink,\n });\n\n const handleOnOpenChange = useCallback(\n (nextIsOpen: boolean) => {\n setIsOpen(nextIsOpen);\n onOpenChange?.(nextIsOpen);\n },\n [onOpenChange],\n );\n\n const handleSetLink = useCallback(() => {\n setLink();\n setIsOpen(false);\n }, [setLink]);\n\n const handleRemoveLink = useCallback(() => {\n removeLink();\n setIsOpen(false);\n }, [removeLink]);\n\n const handleClick = useCallback(\n (event: React.MouseEvent<HTMLButtonElement>) => {\n onClick?.(event);\n if (event.defaultPrevented) return;\n setIsOpen(!isOpen);\n },\n [onClick, isOpen],\n );\n\n const handleIputKeyDown = (event: React.KeyboardEvent) => {\n if (event.key === \"Enter\") {\n event.preventDefault();\n handleSetLink();\n }\n };\n\n useEffect(() => {\n if (autoOpenOnLinkActive && isActive) {\n setIsOpen(true);\n }\n }, [autoOpenOnLinkActive, isActive]);\n\n return (\n <Popover.Root open={isOpen} onOpenChange={handleOnOpenChange}>\n <Popover.Trigger asChild>\n <Toolbar.Button\n className={cn(className, {\n \"bg-elevation-600 text-elevation-0\": isActive,\n })}\n disabled={!canSet}\n onClick={handleClick}\n aria-label=\"Link\"\n {...buttonProps}\n >\n <IconLink size={16} />\n </Toolbar.Button>\n </Popover.Trigger>\n\n <Popover.Content\n className=\"z-50 rounded-md border border-border bg-elevation-100 p-2 shadow-md\"\n sideOffset={8}\n align=\"end\"\n >\n <Toolbar.Root className=\"flex items-center gap-2\">\n <div className=\"flex items-center overflow-hidden rounded-md border border-border focus-within:border-elevation-600\">\n <input\n type=\"url\"\n placeholder=\"Paste a link...\"\n autoComplete=\"off\"\n autoCorrect=\"off\"\n autoCapitalize=\"off\"\n value={url}\n onChange={(e) => setUrl(e.target.value)}\n onKeyDown={handleIputKeyDown}\n className=\"h-10 flex-1 border-none bg-input px-2 py-1 focus:outline-none\"\n aria-label=\"Link URL\"\n style={{ minWidth: \"200px\" }}\n />\n\n <Toolbar.Button\n type=\"button\"\n title=\"Apply link\"\n disabled={!url && !isActive}\n className=\"flex size-10 items-center justify-center !rounded-none border-none bg-elevation-800 p-0 text-elevation-0 hover:bg-elevation-600 disabled:bg-transparent disabled:text-elevation-250\"\n onClick={handleSetLink}\n >\n <IconCornerDownLeft size={16} />\n </Toolbar.Button>\n </div>\n\n <Toolbar.Separator className=\"mx-1 h-10 w-px bg-border\" />\n\n <Toolbar.Button\n type=\"button\"\n className=\"flex size-10 items-center justify-center rounded-md border-none bg-transparent p-0 hover:bg-elevation-250\"\n title=\"Open in new window\"\n disabled={!url && !isActive}\n onClick={() => openLink()}\n >\n <IconExternalLink size={16} />\n </Toolbar.Button>\n\n <Toolbar.Button\n type=\"button\"\n title=\"Remove link\"\n className=\"flex size-10 items-center justify-center rounded-md border-none bg-transparent p-0 hover:bg-elevation-250\"\n disabled={!url && !isActive}\n onClick={handleRemoveLink}\n >\n <IconLinkOff size={16} />\n </Toolbar.Button>\n </Toolbar.Root>\n </Popover.Content>\n </Popover.Root>\n );\n}\n\n// TODO this was mostly copied from the tiptap starter template, pretty sure it can be simplified\n\n/**\n * Configuration for the link popover functionality\n */\nexport interface UseLinkPopoverConfig {\n /**\n * The Tiptap editor instance.\n */\n editor?: Editor | null;\n /**\n * Whether to hide the link popover when not available.\n * @default false\n */\n hideWhenUnavailable?: boolean;\n /**\n * Callback function called when the link is set.\n */\n onSetLink?: () => void;\n}\n\n/**\n * Main hook that provides link popover functionality for Tiptap editor\n */\nfunction useLinkPopover(config?: UseLinkPopoverConfig) {\n const { editor, hideWhenUnavailable = false, onSetLink } = config || {};\n\n const { isVisible, canSet, isActive } = useLinkState({\n editor: editor || null,\n hideWhenUnavailable,\n });\n\n const linkHandler = useLinkHandler({\n editor: editor || null,\n onSetLink,\n });\n\n return {\n isVisible,\n canSet,\n isActive,\n ...linkHandler,\n };\n}\n\nfunction useLinkState(props: {\n editor: Editor | null;\n hideWhenUnavailable: boolean;\n}) {\n const { editor, hideWhenUnavailable = false } = props;\n\n const canSet = canSetLink(editor);\n const isActive =\n useEditorState({\n editor,\n selector: (state) =>\n state.editor?.isEditable && state?.editor?.isActive(\"link\"),\n }) ?? false;\n\n const [isVisible, setIsVisible] = useState(false);\n\n useEffect(() => {\n if (!editor) return;\n\n const handleSelectionUpdate = () => {\n setIsVisible(\n shouldShowLinkButton({\n editor,\n hideWhenUnavailable,\n }),\n );\n };\n\n handleSelectionUpdate();\n\n editor.on(\"selectionUpdate\", handleSelectionUpdate);\n\n return () => {\n editor.off(\"selectionUpdate\", handleSelectionUpdate);\n };\n }, [editor, hideWhenUnavailable]);\n\n return {\n isVisible,\n canSet,\n isActive,\n };\n}\n\n/**\n * Checks if a link can be set in the current editor state\n */\nfunction canSetLink(editor: Editor | null): boolean {\n if (!editor || !editor.isEditable) return false;\n return editor.can().setMark(\"link\");\n}\n\n/**\n * Determines if the link button should be shown\n */\nfunction shouldShowLinkButton(props: {\n editor: Editor | null;\n hideWhenUnavailable: boolean;\n}): boolean {\n const { editor, hideWhenUnavailable } = props;\n\n const linkInSchema = isMarkInSchema(\"link\", editor);\n\n if (!linkInSchema || !editor) {\n return false;\n }\n\n if (hideWhenUnavailable && !editor.isActive(\"code\")) {\n return canSetLink(editor);\n }\n\n return true;\n}\n\n/**\n * Checks if a mark exists in the editor schema\n */\nexport const isMarkInSchema = (\n markName: string,\n editor: Editor | null,\n): boolean => {\n if (!editor?.schema) return false;\n return editor.schema.spec.marks.get(markName) !== undefined;\n};\n\n/**\n * Configuration for the link handler functionality\n */\nexport interface LinkHandlerProps {\n /**\n * The Tiptap editor instance.\n */\n editor: Editor | null;\n /**\n * Callback function called when the link is set.\n */\n onSetLink?: () => void;\n}\n\n/**\n * Custom hook for handling link operations in a Tiptap editor\n */\nexport function useLinkHandler({ editor, onSetLink }: LinkHandlerProps) {\n const [url, setUrl] = useState<string | null>(null);\n const { isActive } = useLinkState({ editor, hideWhenUnavailable: false });\n\n useEffect(() => {\n if (!editor) return;\n\n // Get URL immediately on mount\n const { href } = editor.getAttributes(\"link\");\n\n if (isActive && url === null) {\n setUrl(href || \"\");\n }\n }, [editor, url, isActive]);\n\n useEffect(() => {\n if (!editor) return;\n\n const updateLinkState = () => {\n const { href } = editor.getAttributes(\"link\");\n setUrl(href || \"\");\n };\n\n editor.on(\"selectionUpdate\", updateLinkState);\n return () => {\n editor.off(\"selectionUpdate\", updateLinkState);\n };\n }, [editor]);\n\n const setLink = useCallback(() => {\n if (!url || !editor) return;\n\n const { selection } = editor.state;\n const isEmpty = selection.empty;\n\n let chain = editor.chain().focus();\n\n chain = chain.extendMarkRange(\"link\").setLink({ href: url });\n\n if (isEmpty) {\n chain = chain.insertContent({ type: \"text\", text: url });\n }\n\n chain.run();\n\n setUrl(null);\n\n onSetLink?.();\n }, [editor, onSetLink, url]);\n\n const removeLink = useCallback(() => {\n if (!editor) return;\n editor\n .chain()\n .focus()\n .extendMarkRange(\"link\")\n .unsetLink()\n .setMeta(\"preventAutolink\", true)\n .run();\n setUrl(\"\");\n }, [editor]);\n\n const openLink = useCallback(\n (target: string = \"_blank\", features: string = \"noopener,noreferrer\") => {\n if (!url) return;\n\n const safeUrl = sanitizeUrl(url, window.location.href);\n if (safeUrl !== \"#\") {\n window.open(safeUrl, target, features);\n }\n },\n [url],\n );\n\n return {\n url: url || \"\",\n setUrl,\n setLink,\n removeLink,\n openLink,\n };\n}\n\ntype ProtocolOptions = {\n /**\n * The protocol scheme to be registered.\n * @default '''\n * @example 'ftp'\n * @example 'git'\n */\n scheme: string;\n\n /**\n * If enabled, it allows optional slashes after the protocol.\n * @default false\n * @example true\n */\n optionalSlashes?: boolean;\n};\n\ntype ProtocolConfig = Array<ProtocolOptions | string>;\n\nfunction sanitizeUrl(\n inputUrl: string,\n baseUrl: string,\n protocols?: ProtocolConfig,\n): string {\n try {\n const url = new URL(inputUrl, baseUrl);\n\n if (isAllowedUri(url.href, protocols)) {\n return url.href;\n }\n } catch {\n // If URL creation fails, it's considered invalid\n }\n return \"#\";\n}\n\nfunction isAllowedUri(uri: string | undefined, protocols?: ProtocolConfig) {\n const allowedProtocols: string[] = [\n \"http\",\n \"https\",\n \"ftp\",\n \"ftps\",\n \"mailto\",\n \"tel\",\n \"callto\",\n \"sms\",\n \"cid\",\n \"xmpp\",\n ];\n\n if (protocols) {\n protocols.forEach((protocol) => {\n const nextProtocol =\n typeof protocol === \"string\" ? protocol : protocol.scheme;\n\n if (nextProtocol) {\n allowedProtocols.push(nextProtocol);\n }\n });\n }\n\n const ATTR_WHITESPACE =\n // eslint-disable-next-line no-control-regex\n /[\\u0000-\\u0020\\u00A0\\u1680\\u180E\\u2000-\\u2029\\u205F\\u3000]/g;\n\n return (\n !uri ||\n uri.replace(ATTR_WHITESPACE, \"\").match(\n new RegExp(\n // eslint-disable-next-line no-useless-escape, regexp/no-obscure-range\n `^(?:(?:${allowedProtocols.join(\"|\")}):|[^a-z]|[a-z0-9+.\\-]+(?:[^a-z+.\\-:]|$))`,\n \"i\",\n ),\n )\n );\n}\n"],"names":["LinkEditor","editor","hideWhenUnavailable","onSetLink","onOpenChange","autoOpenOnLinkActive","onClick","className","buttonProps","isOpen","setIsOpen","useState","canSet","isActive","url","setUrl","setLink","removeLink","openLink","useLinkPopover","handleOnOpenChange","useCallback","nextIsOpen","handleSetLink","handleRemoveLink","handleClick","event","handleIputKeyDown","useEffect","Popover","jsx","Toolbar","cn","IconLink","jsxs","e","IconCornerDownLeft","IconExternalLink","IconLinkOff","config","isVisible","useLinkState","linkHandler","useLinkHandler","props","canSetLink","useEditorState","state","setIsVisible","handleSelectionUpdate","shouldShowLinkButton","isMarkInSchema","markName","href","updateLinkState","selection","isEmpty","chain","target","features","safeUrl","sanitizeUrl","inputUrl","baseUrl","protocols","isAllowedUri","uri","allowedProtocols","ATTR_WHITESPACE"],"mappings":"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"}
@@ -2,4 +2,4 @@ import { Editor } from '@tiptap/react';
2
2
  export interface MarkControlsProps {
3
3
  editor: Editor | null;
4
4
  }
5
- export declare function MarkControls({ editor }: MarkControlsProps): import("react").JSX.Element;
5
+ export declare function MarkControls({ editor }: MarkControlsProps): import("react/jsx-runtime").JSX.Element;
@@ -1,47 +1,48 @@
1
- import { IconBold as r, IconItalic as c, IconStrikethrough as u, IconUnderline as s, IconHighlight as h } from "@tabler/icons-react";
2
- import { useEditorState as g } from "@tiptap/react";
3
- import { Toolbar as t } from "radix-ui";
4
- function b({ editor: l }) {
5
- const n = g({
1
+ import { jsx as t } from "react/jsx-runtime";
2
+ import { IconBold as u, IconItalic as c, IconStrikethrough as s, IconUnderline as h, IconHighlight as g } from "@tabler/icons-react";
3
+ import { useEditorState as d } from "@tiptap/react";
4
+ import { Toolbar as n } from "radix-ui";
5
+ function p({ editor: l }) {
6
+ const r = d({
6
7
  editor: l,
7
8
  selector: (e) => {
8
9
  const i = new Array();
9
10
  return e.editor?.isActive("bold") && i.push("bold"), e.editor?.isActive("italic") && i.push("italic"), e.editor?.isActive("strike") && i.push("strikethrough"), e.editor?.isActive("underline") && i.push("underline"), e.editor?.isActive("highlight") && i.push("highlight"), i;
10
11
  }
11
- }), o = (e) => {
12
+ }), a = (e) => {
12
13
  if (l)
13
- for (const i of a)
14
+ for (const i of o)
14
15
  e.includes(i.value) ? l.chain().focus().setMark(i.value).run() : l.chain().focus().unsetMark(i.value).run();
15
16
  };
16
- return /* @__PURE__ */ React.createElement(
17
- t.ToggleGroup,
17
+ return /* @__PURE__ */ t(
18
+ n.ToggleGroup,
18
19
  {
19
20
  type: "multiple",
20
21
  className: "flex items-center gap-0.5",
21
22
  "aria-label": "Text formatting",
22
- value: n ?? [],
23
- onValueChange: o
24
- },
25
- a.map((e) => /* @__PURE__ */ React.createElement(
26
- t.ToggleItem,
27
- {
28
- key: e.value,
29
- className: "inline-flex h-7 flex-shrink-0 flex-grow-0 basis-auto cursor-pointer items-center justify-center rounded border-none bg-transparent px-2 leading-none hover:bg-elevation-250 focus:relative focus:outline data-[state=on]:bg-elevation-600 data-[state=on]:text-elevation-0",
30
- value: e.value,
31
- "aria-label": e.label
32
- },
33
- /* @__PURE__ */ React.createElement(e.icon, { size: 16 })
34
- ))
23
+ value: r ?? [],
24
+ onValueChange: a,
25
+ children: o.map((e) => /* @__PURE__ */ t(
26
+ n.ToggleItem,
27
+ {
28
+ className: "inline-flex h-7 flex-shrink-0 flex-grow-0 basis-auto cursor-pointer items-center justify-center rounded border-none bg-transparent px-2 leading-none hover:bg-elevation-250 focus:relative focus:outline data-[state=on]:bg-elevation-600 data-[state=on]:text-elevation-0",
29
+ value: e.value,
30
+ "aria-label": e.label,
31
+ children: /* @__PURE__ */ t(e.icon, { size: 16 })
32
+ },
33
+ e.value
34
+ ))
35
+ }
35
36
  );
36
37
  }
37
- const a = [
38
- { value: "bold", label: "Bold", icon: r },
38
+ const o = [
39
+ { value: "bold", label: "Bold", icon: u },
39
40
  { value: "italic", label: "Italic", icon: c },
40
- { value: "strike", label: "Strikethrough", icon: u },
41
- { value: "underline", label: "Underline", icon: s },
42
- { value: "highlight", label: "Highlight", icon: h }
41
+ { value: "strike", label: "Strikethrough", icon: s },
42
+ { value: "underline", label: "Underline", icon: h },
43
+ { value: "highlight", label: "Highlight", icon: g }
43
44
  ];
44
45
  export {
45
- b as MarkControls
46
+ p as MarkControls
46
47
  };
47
48
  //# sourceMappingURL=MarkControls.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"MarkControls.js","sources":["../../../../src/components/inputs/toolbar/MarkControls.tsx"],"sourcesContent":["import type { IconProps } from \"@tabler/icons-react\";\nimport type { Editor } from \"@tiptap/react\";\nimport {\n IconBold,\n IconHighlight,\n IconItalic,\n IconStrikethrough,\n IconUnderline,\n} from \"@tabler/icons-react\";\nimport { useEditorState } from \"@tiptap/react\";\nimport { Toolbar } from \"radix-ui\";\n\nexport interface MarkControlsProps {\n editor: Editor | null;\n}\n\nexport function MarkControls({ editor }: MarkControlsProps) {\n const value = useEditorState<string[]>({\n editor,\n selector: (state) => {\n const selected = new Array<string>();\n\n if (state.editor?.isActive(\"bold\")) selected.push(\"bold\");\n if (state.editor?.isActive(\"italic\")) selected.push(\"italic\");\n if (state.editor?.isActive(\"strike\")) selected.push(\"strikethrough\");\n if (state.editor?.isActive(\"underline\")) selected.push(\"underline\");\n if (state.editor?.isActive(\"highlight\")) selected.push(\"highlight\");\n return selected;\n },\n });\n\n const handleChange = (value: string[]) => {\n if (!editor) return;\n for (const option of FORMAT_OPTIONS) {\n if (value.includes(option.value)) {\n editor.chain().focus().setMark(option.value).run();\n } else {\n editor.chain().focus().unsetMark(option.value).run();\n }\n }\n };\n\n return (\n <Toolbar.ToggleGroup\n type=\"multiple\"\n className=\"flex items-center gap-0.5\"\n aria-label=\"Text formatting\"\n value={value ?? []}\n onValueChange={handleChange}\n >\n {FORMAT_OPTIONS.map((option) => (\n <Toolbar.ToggleItem\n key={option.value}\n className=\"inline-flex h-7 flex-shrink-0 flex-grow-0 basis-auto cursor-pointer items-center justify-center rounded border-none bg-transparent px-2 leading-none hover:bg-elevation-250 focus:relative focus:outline data-[state=on]:bg-elevation-600 data-[state=on]:text-elevation-0\"\n value={option.value}\n aria-label={option.label}\n >\n <option.icon size={16} />\n </Toolbar.ToggleItem>\n ))}\n </Toolbar.ToggleGroup>\n );\n}\n\n// MARK: Options\n\ntype FormatType = \"bold\" | \"italic\" | \"strike\" | \"underline\" | \"highlight\";\nconst FORMAT_OPTIONS: {\n value: FormatType;\n label: string;\n icon: React.FunctionComponent<IconProps>;\n}[] = [\n { value: \"bold\", label: \"Bold\", icon: IconBold },\n { value: \"italic\", label: \"Italic\", icon: IconItalic },\n { value: \"strike\", label: \"Strikethrough\", icon: IconStrikethrough },\n { value: \"underline\", label: \"Underline\", icon: IconUnderline },\n { value: \"highlight\", label: \"Highlight\", icon: IconHighlight },\n];\n"],"names":["MarkControls","editor","value","useEditorState","state","selected","handleChange","option","FORMAT_OPTIONS","Toolbar","IconBold","IconItalic","IconStrikethrough","IconUnderline","IconHighlight"],"mappings":";;;AAgBO,SAASA,EAAa,EAAE,QAAAC,KAA6B;AAC1D,QAAMC,IAAQC,EAAyB;AAAA,IACrC,QAAAF;AAAA,IACA,UAAU,CAACG,MAAU;AACnB,YAAMC,IAAW,IAAI,MAAA;AAErB,aAAID,EAAM,QAAQ,SAAS,MAAM,KAAGC,EAAS,KAAK,MAAM,GACpDD,EAAM,QAAQ,SAAS,QAAQ,KAAGC,EAAS,KAAK,QAAQ,GACxDD,EAAM,QAAQ,SAAS,QAAQ,KAAGC,EAAS,KAAK,eAAe,GAC/DD,EAAM,QAAQ,SAAS,WAAW,KAAGC,EAAS,KAAK,WAAW,GAC9DD,EAAM,QAAQ,SAAS,WAAW,KAAGC,EAAS,KAAK,WAAW,GAC3DA;AAAA,IACT;AAAA,EAAA,CACD,GAEKC,IAAe,CAACJ,MAAoB;AACxC,QAAKD;AACL,iBAAWM,KAAUC;AACnB,QAAIN,EAAM,SAASK,EAAO,KAAK,IAC7BN,EAAO,MAAA,EAAQ,MAAA,EAAQ,QAAQM,EAAO,KAAK,EAAE,IAAA,IAE7CN,EAAO,MAAA,EAAQ,MAAA,EAAQ,UAAUM,EAAO,KAAK,EAAE,IAAA;AAAA,EAGrD;AAEA,SACE,sBAAA;AAAA,IAACE,EAAQ;AAAA,IAAR;AAAA,MACC,MAAK;AAAA,MACL,WAAU;AAAA,MACV,cAAW;AAAA,MACX,OAAOP,KAAS,CAAA;AAAA,MAChB,eAAeI;AAAA,IAAA;AAAA,IAEdE,EAAe,IAAI,CAACD,MACnB,sBAAA;AAAA,MAACE,EAAQ;AAAA,MAAR;AAAA,QACC,KAAKF,EAAO;AAAA,QACZ,WAAU;AAAA,QACV,OAAOA,EAAO;AAAA,QACd,cAAYA,EAAO;AAAA,MAAA;AAAA,MAEnB,sBAAA,cAACA,EAAO,MAAP,EAAY,MAAM,GAAA,CAAI;AAAA,IAAA,CAE1B;AAAA,EAAA;AAGP;AAKA,MAAMC,IAIA;AAAA,EACJ,EAAE,OAAO,QAAQ,OAAO,QAAQ,MAAME,EAAA;AAAA,EACtC,EAAE,OAAO,UAAU,OAAO,UAAU,MAAMC,EAAA;AAAA,EAC1C,EAAE,OAAO,UAAU,OAAO,iBAAiB,MAAMC,EAAA;AAAA,EACjD,EAAE,OAAO,aAAa,OAAO,aAAa,MAAMC,EAAA;AAAA,EAChD,EAAE,OAAO,aAAa,OAAO,aAAa,MAAMC,EAAA;AAClD;"}
1
+ {"version":3,"file":"MarkControls.js","sources":["../../../../src/components/inputs/toolbar/MarkControls.tsx"],"sourcesContent":["import type { IconProps } from \"@tabler/icons-react\";\nimport type { Editor } from \"@tiptap/react\";\nimport {\n IconBold,\n IconHighlight,\n IconItalic,\n IconStrikethrough,\n IconUnderline,\n} from \"@tabler/icons-react\";\nimport { useEditorState } from \"@tiptap/react\";\nimport { Toolbar } from \"radix-ui\";\n\nexport interface MarkControlsProps {\n editor: Editor | null;\n}\n\nexport function MarkControls({ editor }: MarkControlsProps) {\n const value = useEditorState<string[]>({\n editor,\n selector: (state) => {\n const selected = new Array<string>();\n\n if (state.editor?.isActive(\"bold\")) selected.push(\"bold\");\n if (state.editor?.isActive(\"italic\")) selected.push(\"italic\");\n if (state.editor?.isActive(\"strike\")) selected.push(\"strikethrough\");\n if (state.editor?.isActive(\"underline\")) selected.push(\"underline\");\n if (state.editor?.isActive(\"highlight\")) selected.push(\"highlight\");\n return selected;\n },\n });\n\n const handleChange = (value: string[]) => {\n if (!editor) return;\n for (const option of FORMAT_OPTIONS) {\n if (value.includes(option.value)) {\n editor.chain().focus().setMark(option.value).run();\n } else {\n editor.chain().focus().unsetMark(option.value).run();\n }\n }\n };\n\n return (\n <Toolbar.ToggleGroup\n type=\"multiple\"\n className=\"flex items-center gap-0.5\"\n aria-label=\"Text formatting\"\n value={value ?? []}\n onValueChange={handleChange}\n >\n {FORMAT_OPTIONS.map((option) => (\n <Toolbar.ToggleItem\n key={option.value}\n className=\"inline-flex h-7 flex-shrink-0 flex-grow-0 basis-auto cursor-pointer items-center justify-center rounded border-none bg-transparent px-2 leading-none hover:bg-elevation-250 focus:relative focus:outline data-[state=on]:bg-elevation-600 data-[state=on]:text-elevation-0\"\n value={option.value}\n aria-label={option.label}\n >\n <option.icon size={16} />\n </Toolbar.ToggleItem>\n ))}\n </Toolbar.ToggleGroup>\n );\n}\n\n// MARK: Options\n\ntype FormatType = \"bold\" | \"italic\" | \"strike\" | \"underline\" | \"highlight\";\nconst FORMAT_OPTIONS: {\n value: FormatType;\n label: string;\n icon: React.FunctionComponent<IconProps>;\n}[] = [\n { value: \"bold\", label: \"Bold\", icon: IconBold },\n { value: \"italic\", label: \"Italic\", icon: IconItalic },\n { value: \"strike\", label: \"Strikethrough\", icon: IconStrikethrough },\n { value: \"underline\", label: \"Underline\", icon: IconUnderline },\n { value: \"highlight\", label: \"Highlight\", icon: IconHighlight },\n];\n"],"names":["MarkControls","editor","value","useEditorState","state","selected","handleChange","option","FORMAT_OPTIONS","jsx","Toolbar","IconBold","IconItalic","IconStrikethrough","IconUnderline","IconHighlight"],"mappings":";;;;AAgBO,SAASA,EAAa,EAAE,QAAAC,KAA6B;AAC1D,QAAMC,IAAQC,EAAyB;AAAA,IACrC,QAAAF;AAAA,IACA,UAAU,CAACG,MAAU;AACnB,YAAMC,IAAW,IAAI,MAAA;AAErB,aAAID,EAAM,QAAQ,SAAS,MAAM,KAAGC,EAAS,KAAK,MAAM,GACpDD,EAAM,QAAQ,SAAS,QAAQ,KAAGC,EAAS,KAAK,QAAQ,GACxDD,EAAM,QAAQ,SAAS,QAAQ,KAAGC,EAAS,KAAK,eAAe,GAC/DD,EAAM,QAAQ,SAAS,WAAW,KAAGC,EAAS,KAAK,WAAW,GAC9DD,EAAM,QAAQ,SAAS,WAAW,KAAGC,EAAS,KAAK,WAAW,GAC3DA;AAAA,IACT;AAAA,EAAA,CACD,GAEKC,IAAe,CAACJ,MAAoB;AACxC,QAAKD;AACL,iBAAWM,KAAUC;AACnB,QAAIN,EAAM,SAASK,EAAO,KAAK,IAC7BN,EAAO,MAAA,EAAQ,MAAA,EAAQ,QAAQM,EAAO,KAAK,EAAE,IAAA,IAE7CN,EAAO,MAAA,EAAQ,MAAA,EAAQ,UAAUM,EAAO,KAAK,EAAE,IAAA;AAAA,EAGrD;AAEA,SACE,gBAAAE;AAAA,IAACC,EAAQ;AAAA,IAAR;AAAA,MACC,MAAK;AAAA,MACL,WAAU;AAAA,MACV,cAAW;AAAA,MACX,OAAOR,KAAS,CAAA;AAAA,MAChB,eAAeI;AAAA,MAEd,UAAAE,EAAe,IAAI,CAACD,MACnB,gBAAAE;AAAA,QAACC,EAAQ;AAAA,QAAR;AAAA,UAEC,WAAU;AAAA,UACV,OAAOH,EAAO;AAAA,UACd,cAAYA,EAAO;AAAA,UAEnB,UAAA,gBAAAE,EAACF,EAAO,MAAP,EAAY,MAAM,GAAA,CAAI;AAAA,QAAA;AAAA,QALlBA,EAAO;AAAA,MAAA,CAOf;AAAA,IAAA;AAAA,EAAA;AAGP;AAKA,MAAMC,IAIA;AAAA,EACJ,EAAE,OAAO,QAAQ,OAAO,QAAQ,MAAMG,EAAA;AAAA,EACtC,EAAE,OAAO,UAAU,OAAO,UAAU,MAAMC,EAAA;AAAA,EAC1C,EAAE,OAAO,UAAU,OAAO,iBAAiB,MAAMC,EAAA;AAAA,EACjD,EAAE,OAAO,aAAa,OAAO,aAAa,MAAMC,EAAA;AAAA,EAChD,EAAE,OAAO,aAAa,OAAO,aAAa,MAAMC,EAAA;AAClD;"}
@@ -3,4 +3,4 @@ export interface RichTextToolbarProps {
3
3
  editor: Editor | null;
4
4
  className?: string;
5
5
  }
6
- export declare function RichTextToolbar({ editor, className }: RichTextToolbarProps): import("react").JSX.Element;
6
+ export declare function RichTextToolbar({ editor, className }: RichTextToolbarProps): import("react/jsx-runtime").JSX.Element;