@luscii-healthtech/web-ui 54.4.4 → 54.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.development.js +160 -5
- package/dist/index.development.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/src/components/TextEditor/MentionList.d.ts +30 -0
- package/dist/src/components/TextEditor/MentionView.d.ts +13 -0
- package/dist/src/components/TextEditor/TextEditor.d.ts +21 -0
- package/dist/src/components/TextEditor/TextEditorToolbar.d.ts +1 -1
- package/dist/src/components/TextEditor/mentionSuggestion.d.ts +10 -0
- package/dist/src/components/TextEditor/textEditorTranslations.d.ts +1 -0
- package/dist/src/generated/components/TextEditor/MentionList.d.ts +30 -0
- package/dist/src/generated/components/TextEditor/MentionView.d.ts +13 -0
- package/dist/src/generated/components/TextEditor/TextEditor.d.ts +21 -0
- package/dist/src/generated/components/TextEditor/TextEditorToolbar.d.ts +1 -1
- package/dist/src/generated/components/TextEditor/mentionSuggestion.d.ts +10 -0
- package/dist/src/generated/components/TextEditor/textEditorTranslations.d.ts +1 -0
- package/dist/src/generated/index.d.ts +1 -1
- package/dist/src/index.d.ts +1 -1
- package/dist/stories/TextEditor.stories.d.ts +18 -0
- package/dist/web-ui-tailwind.css +9 -0
- package/dist/web-ui.esm.js +1 -1
- package/dist/web-ui.esm.js.map +1 -1
- package/package.json +3 -1
|
@@ -29,6 +29,7 @@ var Creatable = require('react-select/creatable');
|
|
|
29
29
|
var RadixSwitch = require('@radix-ui/react-switch');
|
|
30
30
|
var react = require('@tiptap/react');
|
|
31
31
|
var StarterKit = require('@tiptap/starter-kit');
|
|
32
|
+
var extensionMention = require('@tiptap/extension-mention');
|
|
32
33
|
var solid = require('@heroicons/react/20/solid');
|
|
33
34
|
var react$1 = require('@headlessui/react');
|
|
34
35
|
var ToggleGroup = require('@radix-ui/react-toggle-group');
|
|
@@ -5189,6 +5190,15 @@ const TextEditorToolbarButton = ({ option, hasTextSelected, editor, translations
|
|
|
5189
5190
|
editor.chain().focus().extendMarkRange("link").setLink({ href: url }).run();
|
|
5190
5191
|
}
|
|
5191
5192
|
}, "aria-pressed": editor.isActive("link"), children: jsxRuntime.jsx(solid.LinkIcon, { width: 16 }) });
|
|
5193
|
+
case "tag":
|
|
5194
|
+
if (!editor.schema.nodes.mention) {
|
|
5195
|
+
return null;
|
|
5196
|
+
}
|
|
5197
|
+
return jsxRuntime.jsx(TertiaryIconButton, { label: translations.tagLabel, className: buttonClasses, onClick: () => {
|
|
5198
|
+
const before = editor.state.selection.$from.nodeBefore;
|
|
5199
|
+
const needsSpace = Boolean((before === null || before === void 0 ? void 0 : before.isText) && before.text && !/\s$/.test(before.text));
|
|
5200
|
+
editor.chain().focus().insertContent(needsSpace ? " @" : "@").run();
|
|
5201
|
+
}, children: jsxRuntime.jsx(solid.AtSymbolIcon, { width: 16 }) });
|
|
5192
5202
|
default:
|
|
5193
5203
|
return null;
|
|
5194
5204
|
}
|
|
@@ -5224,6 +5234,123 @@ const TextEditorToolbar = ({ toolbarId, toolbar, hasTextSelected, editor, transl
|
|
|
5224
5234
|
return jsxRuntime.jsx(Stack, { axis: "x", gap: "m", _px: "xs", id: toolbarId, children: toolbar.map((group) => jsxRuntime.jsx(Stack, { axis: "x", _gap: "xs", children: group.map((option, optionIndex) => jsxRuntime.jsx(TextEditorToolbarButton, { option, hasTextSelected, editor, translations }, getOptionKey(option, optionIndex))) }, getGroupKey(group))) });
|
|
5225
5235
|
};
|
|
5226
5236
|
|
|
5237
|
+
const MentionList = React.forwardRef(({ items, command }, ref) => {
|
|
5238
|
+
const [selectedIndex, setSelectedIndex] = React.useState(0);
|
|
5239
|
+
React.useEffect(() => {
|
|
5240
|
+
setSelectedIndex(0);
|
|
5241
|
+
}, [items]);
|
|
5242
|
+
const selectItem = (index) => {
|
|
5243
|
+
const item = items[index];
|
|
5244
|
+
if (item) {
|
|
5245
|
+
command({ id: item.id, label: item.label });
|
|
5246
|
+
}
|
|
5247
|
+
};
|
|
5248
|
+
React.useImperativeHandle(ref, () => ({
|
|
5249
|
+
onKeyDown: ({ event }) => {
|
|
5250
|
+
if (items.length === 0) {
|
|
5251
|
+
return false;
|
|
5252
|
+
}
|
|
5253
|
+
if (event.key === "ArrowUp") {
|
|
5254
|
+
setSelectedIndex((selectedIndex + items.length - 1) % items.length);
|
|
5255
|
+
return true;
|
|
5256
|
+
}
|
|
5257
|
+
if (event.key === "ArrowDown") {
|
|
5258
|
+
setSelectedIndex((selectedIndex + 1) % items.length);
|
|
5259
|
+
return true;
|
|
5260
|
+
}
|
|
5261
|
+
if (event.key === "Enter") {
|
|
5262
|
+
selectItem(selectedIndex);
|
|
5263
|
+
return true;
|
|
5264
|
+
}
|
|
5265
|
+
return false;
|
|
5266
|
+
}
|
|
5267
|
+
}));
|
|
5268
|
+
if (items.length === 0) {
|
|
5269
|
+
return null;
|
|
5270
|
+
}
|
|
5271
|
+
return jsxRuntime.jsx(Card, { borderRadius: "s", elevation: "large", padding: false, border: true, className: "ui:max-w-80 ui:overflow-hidden", children: jsxRuntime.jsx(Stack, { width: "full", align: "stretch", className: "ui:p-1", children: items.map((item, index) => jsxRuntime.jsx(Box, {
|
|
5272
|
+
as: "button",
|
|
5273
|
+
type: "button",
|
|
5274
|
+
// Use mousedown so selection happens before the editor loses focus.
|
|
5275
|
+
onMouseDown: (event) => {
|
|
5276
|
+
event.preventDefault();
|
|
5277
|
+
selectItem(index);
|
|
5278
|
+
},
|
|
5279
|
+
onMouseEnter: () => setSelectedIndex(index),
|
|
5280
|
+
borderRadius: "xs",
|
|
5281
|
+
className: classNames__default.default("ui:w-full ui:text-left ui:cursor-pointer ui:px-2 ui:py-1.5", {
|
|
5282
|
+
"ui:bg-background-neutral-secondary-hovered": index === selectedIndex
|
|
5283
|
+
}),
|
|
5284
|
+
children: jsxRuntime.jsx(Text, { truncate: true, children: item.label })
|
|
5285
|
+
}, item.id)) }) });
|
|
5286
|
+
});
|
|
5287
|
+
MentionList.displayName = "MentionList";
|
|
5288
|
+
|
|
5289
|
+
const MAX_RESULTS = 8;
|
|
5290
|
+
const createMentionSuggestion = (getTags) => ({
|
|
5291
|
+
items: ({ query }) => {
|
|
5292
|
+
const normalizedQuery = query.toLowerCase();
|
|
5293
|
+
return getTags().filter((tag) => tag.label.toLowerCase().includes(normalizedQuery)).slice(0, MAX_RESULTS);
|
|
5294
|
+
},
|
|
5295
|
+
render: () => {
|
|
5296
|
+
let component = null;
|
|
5297
|
+
let popup = null;
|
|
5298
|
+
const reposition = (clientRect) => {
|
|
5299
|
+
if (!popup || !clientRect) {
|
|
5300
|
+
return;
|
|
5301
|
+
}
|
|
5302
|
+
const rect = clientRect();
|
|
5303
|
+
if (!rect) {
|
|
5304
|
+
return;
|
|
5305
|
+
}
|
|
5306
|
+
popup.style.top = `${rect.bottom + 4}px`;
|
|
5307
|
+
popup.style.left = `${rect.left}px`;
|
|
5308
|
+
};
|
|
5309
|
+
return {
|
|
5310
|
+
onStart: (props) => {
|
|
5311
|
+
component = new react.ReactRenderer(MentionList, {
|
|
5312
|
+
props,
|
|
5313
|
+
editor: props.editor
|
|
5314
|
+
});
|
|
5315
|
+
if (!props.clientRect) {
|
|
5316
|
+
return;
|
|
5317
|
+
}
|
|
5318
|
+
popup = document.createElement("div");
|
|
5319
|
+
popup.style.position = "fixed";
|
|
5320
|
+
popup.style.zIndex = "1000";
|
|
5321
|
+
popup.appendChild(component.element);
|
|
5322
|
+
document.body.appendChild(popup);
|
|
5323
|
+
reposition(props.clientRect);
|
|
5324
|
+
},
|
|
5325
|
+
onUpdate: (props) => {
|
|
5326
|
+
component === null || component === void 0 ? void 0 : component.updateProps(props);
|
|
5327
|
+
reposition(props.clientRect);
|
|
5328
|
+
},
|
|
5329
|
+
onKeyDown: (props) => {
|
|
5330
|
+
var _a, _b;
|
|
5331
|
+
return (_b = (_a = component === null || component === void 0 ? void 0 : component.ref) === null || _a === void 0 ? void 0 : _a.onKeyDown(props)) !== null && _b !== void 0 ? _b : false;
|
|
5332
|
+
},
|
|
5333
|
+
onExit: () => {
|
|
5334
|
+
popup === null || popup === void 0 ? void 0 : popup.remove();
|
|
5335
|
+
popup = null;
|
|
5336
|
+
component === null || component === void 0 ? void 0 : component.destroy();
|
|
5337
|
+
component = null;
|
|
5338
|
+
}
|
|
5339
|
+
};
|
|
5340
|
+
}
|
|
5341
|
+
});
|
|
5342
|
+
|
|
5343
|
+
const MentionView = ({ node }) => {
|
|
5344
|
+
var _a, _b;
|
|
5345
|
+
const id = node.attrs.id;
|
|
5346
|
+
const label = (_a = node.attrs.label) !== null && _a !== void 0 ? _a : id;
|
|
5347
|
+
const char = (_b = node.attrs.mentionSuggestionChar) !== null && _b !== void 0 ? _b : "@";
|
|
5348
|
+
const display = `${char}${label}`;
|
|
5349
|
+
const tooltipText = id && id !== label ? id : null;
|
|
5350
|
+
const pill = jsxRuntime.jsx("span", { className: "web-ui-mention", children: display });
|
|
5351
|
+
return jsxRuntime.jsx(react.NodeViewWrapper, { as: "span", children: tooltipText ? jsxRuntime.jsx(Tooltip$1.Provider, { children: jsxRuntime.jsxs(Tooltip.Root, { children: [jsxRuntime.jsx(Tooltip.Trigger, { asChild: true, children: pill }), jsxRuntime.jsx(Tooltip.Content, { children: jsxRuntime.jsx(Tooltip.Text, { children: tooltipText }) })] }) }) : pill });
|
|
5352
|
+
};
|
|
5353
|
+
|
|
5227
5354
|
const TEXT_EDITOR_TRANSLATIONS = {
|
|
5228
5355
|
"en-GB": {
|
|
5229
5356
|
boldLabel: "bold",
|
|
@@ -5231,6 +5358,7 @@ const TEXT_EDITOR_TRANSLATIONS = {
|
|
|
5231
5358
|
underlineLabel: "underline",
|
|
5232
5359
|
strikeLabel: "strike",
|
|
5233
5360
|
linkLabel: "link",
|
|
5361
|
+
tagLabel: "insert tag",
|
|
5234
5362
|
orderedListLabel: "ordered list",
|
|
5235
5363
|
bulletListLabel: "bullet list",
|
|
5236
5364
|
enterUrlPrompt: "Enter URL:",
|
|
@@ -5246,6 +5374,7 @@ const TEXT_EDITOR_TRANSLATIONS = {
|
|
|
5246
5374
|
underlineLabel: "onderstreept",
|
|
5247
5375
|
strikeLabel: "doorgestreept",
|
|
5248
5376
|
linkLabel: "link",
|
|
5377
|
+
tagLabel: "tag invoegen",
|
|
5249
5378
|
orderedListLabel: "genummerde lijst",
|
|
5250
5379
|
bulletListLabel: "opsommingslijst",
|
|
5251
5380
|
enterUrlPrompt: "Voer URL in:",
|
|
@@ -5261,6 +5390,7 @@ const TEXT_EDITOR_TRANSLATIONS = {
|
|
|
5261
5390
|
underlineLabel: "unterstrichen",
|
|
5262
5391
|
strikeLabel: "durchgestrichen",
|
|
5263
5392
|
linkLabel: "Link",
|
|
5393
|
+
tagLabel: "Tag einf\xFCgen",
|
|
5264
5394
|
orderedListLabel: "nummerierte Liste",
|
|
5265
5395
|
bulletListLabel: "Aufz\xE4hlungsliste",
|
|
5266
5396
|
enterUrlPrompt: "URL eingeben:",
|
|
@@ -5276,6 +5406,7 @@ const TEXT_EDITOR_TRANSLATIONS = {
|
|
|
5276
5406
|
underlineLabel: "soulign\xE9",
|
|
5277
5407
|
strikeLabel: "barr\xE9",
|
|
5278
5408
|
linkLabel: "lien",
|
|
5409
|
+
tagLabel: "ins\xE9rer une balise",
|
|
5279
5410
|
orderedListLabel: "liste num\xE9rot\xE9e",
|
|
5280
5411
|
bulletListLabel: "liste \xE0 puces",
|
|
5281
5412
|
enterUrlPrompt: "Entrer l'URL :",
|
|
@@ -5291,6 +5422,7 @@ const TEXT_EDITOR_TRANSLATIONS = {
|
|
|
5291
5422
|
underlineLabel: "sublinhado",
|
|
5292
5423
|
strikeLabel: "riscado",
|
|
5293
5424
|
linkLabel: "liga\xE7\xE3o",
|
|
5425
|
+
tagLabel: "inserir etiqueta",
|
|
5294
5426
|
orderedListLabel: "lista numerada",
|
|
5295
5427
|
bulletListLabel: "lista com marcadores",
|
|
5296
5428
|
enterUrlPrompt: "Introduzir URL:",
|
|
@@ -5305,29 +5437,46 @@ const getTextEditorTranslations = (locale) => {
|
|
|
5305
5437
|
return TEXT_EDITOR_TRANSLATIONS[locale] || TEXT_EDITOR_TRANSLATIONS["en-GB"];
|
|
5306
5438
|
};
|
|
5307
5439
|
|
|
5308
|
-
var css_248z$1 = "/**\n * --- DEPRECATED ---\n * DON'T USE ANYTHING FROM THIS FILE IN FUTURE CHANGES. WE SHOULD BE\n * USING TAILWIND CLASSES DIRECTLY IN OUR COMPONENTS.\n */\n.web-ui-text-editor {\n resize: vertical;\n min-height: 10rem;\n padding: 1rem;\n font-size: 0.8rem;\n line-height: 1.5;\n outline: none;\n}\n.web-ui-text-editor.tiptap.ProseMirror p.is-editor-empty:first-child::before {\n color: var(--ui-color-text-neutral-primary-disabled);\n content: attr(data-placeholder);\n float: left;\n height: 0;\n pointer-events: none;\n}\n.web-ui-text-editor a {\n color: var(--ui-color-text-brand-primary-default);\n text-decoration: underline;\n cursor: pointer;\n}\n.web-ui-text-editor ul,\n.web-ui-text-editor ol {\n padding-left: 1.5rem;\n}\n.web-ui-text-editor ul {\n list-style-type: disc;\n}\n.web-ui-text-editor ol {\n list-style-type: decimal;\n}\n.web-ui-text-editor li {\n margin-bottom: 0.25rem;\n}\n.web-ui-text-editor strong {\n font-weight: 600;\n}\n.web-ui-text-editor em {\n font-style: italic;\n}\n.web-ui-text-editor u {\n text-decoration: underline;\n}\n.web-ui-text-editor s {\n text-decoration: line-through;\n}\n.web-ui-text-editor h1,\n.web-ui-text-editor h2,\n.web-ui-text-editor h3,\n.web-ui-text-editor h4,\n.web-ui-text-editor h5,\n.web-ui-text-editor h6 {\n font-weight: 600;\n margin-bottom: 0.75rem;\n margin-top: 1rem;\n}\n.web-ui-text-editor h1:first-child,\n.web-ui-text-editor h2:first-child,\n.web-ui-text-editor h3:first-child,\n.web-ui-text-editor h4:first-child,\n.web-ui-text-editor h5:first-child,\n.web-ui-text-editor h6:first-child {\n margin-top: 0;\n}\n.web-ui-text-editor h1 {\n font-size: 2rem;\n}\n.web-ui-text-editor h2 {\n font-size: 1.5rem;\n}\n.web-ui-text-editor h3 {\n font-size: 1.25rem;\n}\n.web-ui-text-editor h4 {\n font-size: 1.125rem;\n}\n.web-ui-text-editor h5,\n.web-ui-text-editor h6 {\n font-size: 1rem;\n}";
|
|
5440
|
+
var css_248z$1 = "/**\n * --- DEPRECATED ---\n * DON'T USE ANYTHING FROM THIS FILE IN FUTURE CHANGES. WE SHOULD BE\n * USING TAILWIND CLASSES DIRECTLY IN OUR COMPONENTS.\n */\n.web-ui-text-editor {\n resize: vertical;\n min-height: 10rem;\n padding: 1rem;\n font-size: 0.8rem;\n line-height: 1.5;\n outline: none;\n}\n.web-ui-text-editor.tiptap.ProseMirror p.is-editor-empty:first-child::before {\n color: var(--ui-color-text-neutral-primary-disabled);\n content: attr(data-placeholder);\n float: left;\n height: 0;\n pointer-events: none;\n}\n.web-ui-text-editor a {\n color: var(--ui-color-text-brand-primary-default);\n text-decoration: underline;\n cursor: pointer;\n}\n.web-ui-text-editor .web-ui-mention {\n display: inline-block;\n padding: 0.125rem 0.375rem;\n border-radius: 0.25rem;\n background-color: var(--ui-primitive-color-pink-100);\n color: var(--ui-primitive-color-pink-700);\n font-weight: 500;\n white-space: nowrap;\n}\n.web-ui-text-editor ul,\n.web-ui-text-editor ol {\n padding-left: 1.5rem;\n}\n.web-ui-text-editor ul {\n list-style-type: disc;\n}\n.web-ui-text-editor ol {\n list-style-type: decimal;\n}\n.web-ui-text-editor li {\n margin-bottom: 0.25rem;\n}\n.web-ui-text-editor strong {\n font-weight: 600;\n}\n.web-ui-text-editor em {\n font-style: italic;\n}\n.web-ui-text-editor u {\n text-decoration: underline;\n}\n.web-ui-text-editor s {\n text-decoration: line-through;\n}\n.web-ui-text-editor h1,\n.web-ui-text-editor h2,\n.web-ui-text-editor h3,\n.web-ui-text-editor h4,\n.web-ui-text-editor h5,\n.web-ui-text-editor h6 {\n font-weight: 600;\n margin-bottom: 0.75rem;\n margin-top: 1rem;\n}\n.web-ui-text-editor h1:first-child,\n.web-ui-text-editor h2:first-child,\n.web-ui-text-editor h3:first-child,\n.web-ui-text-editor h4:first-child,\n.web-ui-text-editor h5:first-child,\n.web-ui-text-editor h6:first-child {\n margin-top: 0;\n}\n.web-ui-text-editor h1 {\n font-size: 2rem;\n}\n.web-ui-text-editor h2 {\n font-size: 1.5rem;\n}\n.web-ui-text-editor h3 {\n font-size: 1.25rem;\n}\n.web-ui-text-editor h4 {\n font-size: 1.125rem;\n}\n.web-ui-text-editor h5,\n.web-ui-text-editor h6 {\n font-size: 1rem;\n}";
|
|
5309
5441
|
styleInject(css_248z$1);
|
|
5310
5442
|
|
|
5443
|
+
const MentionWithTooltip = extensionMention.Mention.extend({
|
|
5444
|
+
addNodeView() {
|
|
5445
|
+
return react.ReactNodeViewRenderer(MentionView);
|
|
5446
|
+
}
|
|
5447
|
+
});
|
|
5311
5448
|
const sanitize = (html) => DOMPurify__default.default.sanitize(html, {
|
|
5312
|
-
ALLOWED_TAGS: ["u", "a", "s", "ul", "ol", "li", "p", "strong", "em"],
|
|
5313
|
-
ALLOWED_ATTR: [
|
|
5449
|
+
ALLOWED_TAGS: ["u", "a", "s", "ul", "ol", "li", "p", "strong", "em", "span"],
|
|
5450
|
+
ALLOWED_ATTR: [
|
|
5451
|
+
"href",
|
|
5452
|
+
"target",
|
|
5453
|
+
// Mention/tag nodes render as a span carrying these attributes.
|
|
5454
|
+
"class",
|
|
5455
|
+
"data-type",
|
|
5456
|
+
"data-id",
|
|
5457
|
+
"data-label",
|
|
5458
|
+
"data-mention-suggestion-char"
|
|
5459
|
+
]
|
|
5314
5460
|
});
|
|
5315
5461
|
const TextEditor = (_a) => {
|
|
5316
5462
|
var { defaultValue, formats = ["bold", "italic", "underline", "strike", "list", "link"], toolbar = [
|
|
5317
5463
|
["bold", "italic", "underline", "strike"],
|
|
5318
5464
|
[{ list: "ordered" }, { list: "bullet" }],
|
|
5319
5465
|
["link"]
|
|
5320
|
-
], placeholder, onValueChange } = _a, attrs = __rest(_a, ["defaultValue", "formats", "toolbar", "placeholder", "onValueChange"]);
|
|
5466
|
+
], placeholder, tags, onValueChange } = _a, attrs = __rest(_a, ["defaultValue", "formats", "toolbar", "placeholder", "tags", "onValueChange"]);
|
|
5321
5467
|
const rawId = React.useId();
|
|
5322
5468
|
const toolbarId = `toolbar-${rawId.replace(/:/g, "")}`;
|
|
5323
5469
|
const defaultValueRef = React.useRef(sanitize(defaultValue !== null && defaultValue !== void 0 ? defaultValue : ""));
|
|
5324
5470
|
const onTextChangeRef = React.useRef(onValueChange);
|
|
5471
|
+
const tagsRef = React.useRef(tags !== null && tags !== void 0 ? tags : []);
|
|
5472
|
+
const mentionsEnabled = tags !== void 0;
|
|
5325
5473
|
const [linkTooltip, setLinkTooltip] = React.useState(null);
|
|
5326
5474
|
const [hasTextSelected, setHasTextSelected] = React.useState(false);
|
|
5327
5475
|
const locale = useLocaleContext();
|
|
5328
5476
|
const translations = getTextEditorTranslations(locale);
|
|
5329
5477
|
React.useLayoutEffect(() => {
|
|
5330
5478
|
onTextChangeRef.current = onValueChange;
|
|
5479
|
+
tagsRef.current = tags !== null && tags !== void 0 ? tags : [];
|
|
5331
5480
|
});
|
|
5332
5481
|
const editor = react.useEditor({
|
|
5333
5482
|
extensions: [
|
|
@@ -5354,7 +5503,13 @@ const TextEditor = (_a) => {
|
|
|
5354
5503
|
}
|
|
5355
5504
|
} : false,
|
|
5356
5505
|
codeBlock: (formats === null || formats === void 0 ? void 0 : formats.includes("code")) ? {} : false
|
|
5357
|
-
})
|
|
5506
|
+
}),
|
|
5507
|
+
...mentionsEnabled ? [
|
|
5508
|
+
MentionWithTooltip.configure({
|
|
5509
|
+
HTMLAttributes: { class: "web-ui-mention" },
|
|
5510
|
+
suggestion: createMentionSuggestion(() => tagsRef.current)
|
|
5511
|
+
})
|
|
5512
|
+
] : []
|
|
5358
5513
|
],
|
|
5359
5514
|
content: defaultValueRef.current,
|
|
5360
5515
|
editorProps: {
|