diff --git a/flavours/classic/config/flavour_assets/components.css b/flavours/classic/config/flavour_assets/components.css index 1cd9eb4860..443a336fc5 100644 --- a/flavours/classic/config/flavour_assets/components.css +++ b/flavours/classic/config/flavour_assets/components.css @@ -1,3 +1,812 @@ /* This file was generated by the Surface compiler. */ + +/* Bonfire.Editor.Milkdown (jlrhi) */ + +.milkdown[s-jlrhi] { + width: 100%; +} + +.milkdown[s-jlrhi] img[s-jlrhi][title^=":"] { + height: 1em; + width: 1em; + margin: 0 1px 0 1.5px; + vertical-align: -1.5px; + display: inline; +} + +.milkdown[s-jlrhi] .emoji[s-jlrhi] { + height: 1em; + width: 1em; + margin: 0 1px 0 1.5px; + vertical-align: -1.5px; + display: inline; +} + +/* Bonfire.UI.Social.Activity.ActionsLive (sabiy) */ + + +/* Bonfire.UI.Social.Activity.MediaLive (bdjtg) */ + + +/* Bonfire.UI.Social.Activity.MoreActionsLive (ms2gq) */ + +div[s-ms2gq][data-id="more_menu"][data-rendered="widget"] { + @apply dropdown-top dropdown-end; +} + +/* Bonfire.UI.Social.Activity.NoteLive (sicz3) */ + +div[s-sicz3][data-rendered="widget"] { + @apply !mt-2; +} + +div[s-sicz3][data-rendered="smart_input"] { + @apply !my-0 !ml-0; +} + +div[s-sicz3][data-rendered="notifications"] { + @apply opacity-60; +} + +div[s-sicz3][data-rendered="thread"] { + @apply cursor-default; +} + +div[s-sicz3][data-id="object_body"][data-rendered="smart_input"] { + @apply !my-0 !text-sm !font-normal; +} + +div[s-sicz3][data-id="object_body"][data-main-object] { + @apply md:prose-base md:prose-p:my-0; +} + +/* Bonfire.UI.Social.Activity.SubjectLive (au77b) */ + +.mfm[s-au77b] { + display: inline-block; +} + +._mfm_tada_[s-au77b] { + font-size: 150%; + animation: mfm-tada 1s linear infinite both; +} + +._mfm_jelly_[s-au77b] { + animation: mfm-jelly 1s linear infinite both; +} + +._mfm_twitch_[s-au77b] { + animation: mfm-twitch 0.5s ease infinite; +} + +._mfm_shake_[s-au77b] { + animation: mfm-shake 0.5s ease infinite; +} + +._mfm_spin_[s-au77b] { + animation: mfm-spin 0.5s linear infinite; +} + +._mfm_spin_[s-au77b][data-x] { + animation-name: mfm-spinX; +} +._mfm_spin_[s-au77b][data-y] { + animation-name: mfm-spinY; +} +._mfm_spin_[s-au77b][left] { + animation-direction: reverse; +} +._mfm_spin_[s-au77b][alternate] { + animation-direction: alternate; +} + +._mfm_jump_[s-au77b] { + animation: mfm-jump 0.75s linear infinite; +} + +._mfm_bounce_[s-au77b] { + animation: mfm-bounce 0.75s linear infinite; + transform-origin: center bottom; +} + +._mfm_flip_[s-au77b][data-h][data-v] { + transform: scale(-1, -1); +} +._mfm_flip_[s-au77b][data-v] { + transform: scaleY(-1); +} +._mfm_flip_[s-au77b]:not([data-v]) { + transform: scaleX(-1); +} + +._mfm_x2_[s-au77b] { + font-size: 200%; +} + +._mfm_x3_[s-au77b] { + font-size: 400%; +} + +._mfm_x4_[s-au77b] { + font-size: 600%; +} + +._mfm_blur_[s-au77b] { + filter: blur(6px); + transition: filter 0.3s; +} +._mfm_blur_[s-au77b]:hover { + filter: blur(0px); +} + +._mfm_rainbow_[s-au77b] { + animation: mfm-rainbow 1s linear infinite; +} + +._mfm_rotate_[s-au77b] { + transform: rotate(90deg); + transform-origin: center center; +} + +/* sparkle */ + +@keyframes mfm-tada { + from[s-au77b] { + transform: scale3d(1, 1, 1); + } + + 10%, + 20% { + transform: scale3d(0.9, 0.9, 0.9) rotate3d(0, 0, 1, -3deg); + } + + 30%, + 50%, + 70%, + 90% { + transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg); + } + + 40%, + 60%, + 80% { + transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg); + } + + to[s-au77b] { + transform: scale3d(1, 1, 1); + } +} + +@keyframes bounce { + 0% { + transform: scaleX(0.9) scaleY(0.9); + } + + 19% { + transform: scaleX(1.1) scaleY(1.1); + } + + 48% { + transform: scaleX(0.95) scaleY(0.95); + } + + 100% { + transform: scaleX(1) scaleY(1); + } +} + +@keyframes mfm-spin { + 0% { + transform: rotate(0deg); + } + 100% { + transform: rotate(360deg); + } +} + +@keyframes mfm-spinX { + 0% { + transform: perspective(128px) rotateX(0deg); + } + 100% { + transform: perspective(128px) rotateX(360deg); + } +} + +@keyframes mfm-spinY { + 0% { + transform: perspective(128px) rotateY(0deg); + } + 100% { + transform: perspective(128px) rotateY(360deg); + } +} + +@keyframes mfm-jump { + 0% { + transform: translateY(0); + } + 25% { + transform: translateY(-16px); + } + 50% { + transform: translateY(0); + } + 75% { + transform: translateY(-8px); + } + 100% { + transform: translateY(0); + } +} + +@keyframes mfm-bounce { + 0% { + transform: translateY(0) scale(1, 1); + } + 25% { + transform: translateY(-16px) scale(1, 1); + } + 50% { + transform: translateY(0) scale(1, 1); + } + 75% { + transform: translateY(0) scale(1.5, 0.75); + } + 100% { + transform: translateY(0) scale(1, 1); + } +} + +@keyframes mfm-twitch { + 0% { + transform: translate(7px, -2px); + } + 5% { + transform: translate(-3px, 1px); + } + 10% { + transform: translate(-7px, -1px); + } + 15% { + transform: translate(0, -1px); + } + 20% { + transform: translate(-8px, 6px); + } + 25% { + transform: translate(-4px, -3px); + } + 30% { + transform: translate(-4px, -6px); + } + 35% { + transform: translate(-8px, -8px); + } + 40% { + transform: translate(4px, 6px); + } + 45% { + transform: translate(-3px, 1px); + } + 50% { + transform: translate(2px, -10px); + } + 55% { + transform: translate(-7px, 0); + } + 60% { + transform: translate(-2px, 4px); + } + 65% { + transform: translate(3px, -8px); + } + 70% { + transform: translate(6px, 7px); + } + 75% { + transform: translate(-7px, -2px); + } + 80% { + transform: translate(-7px, -8px); + } + 85% { + transform: translate(9px, 3px); + } + 90% { + transform: translate(-3px, -2px); + } + 95% { + transform: translate(-10px, 2px); + } + 100% { + transform: translate(-2px, -6px); + } +} + +@keyframes mfm-shake { + 0% { + transform: translate(-3px, -1px) rotate(-8deg); + } + 5% { + transform: translate(0, -1px) rotate(-10deg); + } + 10% { + transform: translate(1px, -3px) rotate(0deg); + } + 15% { + transform: translate(1px, 1px) rotate(11deg); + } + 20% { + transform: translate(-2px, 1px) rotate(1deg); + } + 25% { + transform: translate(-1px, -2px) rotate(-2deg); + } + 30% { + transform: translate(-1px, 2px) rotate(-3deg); + } + 35% { + transform: translate(2px, 1px) rotate(6deg); + } + 40% { + transform: translate(-2px, -3px) rotate(-9deg); + } + 45% { + transform: translate(0, -1px) rotate(-12deg); + } + 50% { + transform: translate(1px, 2px) rotate(10deg); + } + 55% { + transform: translate(0, -3px) rotate(8deg); + } + 60% { + transform: translate(1px, -1px) rotate(8deg); + } + 65% { + transform: translate(0, -1px) rotate(-7deg); + } + 70% { + transform: translate(-1px, -3px) rotate(6deg); + } + 75% { + transform: translate(0, -2px) rotate(4deg); + } + 80% { + transform: translate(-2px, -1px) rotate(3deg); + } + 85% { + transform: translate(1px, -3px) rotate(-10deg); + } + 90% { + transform: translate(1px, 0) rotate(3deg); + } + 95% { + transform: translate(-2px, 0) rotate(-3deg); + } + 100% { + transform: translate(2px, 1px) rotate(2deg); + } +} + +@keyframes mfm-jelly { + from[s-au77b] { + transform: scale3d(1, 1, 1); + } + 30% { + transform: scale3d(1.25, 0.75, 1); + } + 40% { + transform: scale3d(0.75, 1.25, 1); + } + 50% { + transform: scale3d(1.15, 0.85, 1); + } + 65% { + transform: scale3d(0.95, 1.05, 1); + } + 75% { + transform: scale3d(1.05, 0.95, 1); + } + to[s-au77b] { + transform: scale3d(1, 1, 1); + } +} + +@keyframes mfm-rainbow { + 0% { + filter: hue-rotate(0deg) contrast(150%) saturate(150%); + } + 100% { + filter: hue-rotate(360deg) contrast(150%) saturate(150%); + } +} + +/* Bonfire.UI.Social.ActivityLive (xsoi6) */ + +.mfm[s-xsoi6] { + display: inline-block; +} + +._mfm_tada_[s-xsoi6] { + font-size: 150%; + animation: mfm-tada 1s linear infinite both; +} + +._mfm_jelly_[s-xsoi6] { + animation: mfm-jelly 1s linear infinite both; +} + +._mfm_twitch_[s-xsoi6] { + animation: mfm-twitch 0.5s ease infinite; +} + +._mfm_shake_[s-xsoi6] { + animation: mfm-shake 0.5s ease infinite; +} + +._mfm_spin_[s-xsoi6] { + animation: mfm-spin 0.5s linear infinite; +} + +._mfm_spin_[s-xsoi6][data-x] { + animation-name: mfm-spinX; +} +._mfm_spin_[s-xsoi6][data-y] { + animation-name: mfm-spinY; +} +._mfm_spin_[s-xsoi6][left] { + animation-direction: reverse; +} +._mfm_spin_[s-xsoi6][alternate] { + animation-direction: alternate; +} + +._mfm_jump_[s-xsoi6] { + animation: mfm-jump 0.75s linear infinite; +} + +._mfm_bounce_[s-xsoi6] { + animation: mfm-bounce 0.75s linear infinite; + transform-origin: center bottom; +} + +._mfm_flip_[s-xsoi6][data-h][data-v] { + transform: scale(-1, -1); +} +._mfm_flip_[s-xsoi6][data-v] { + transform: scaleY(-1); +} +._mfm_flip_[s-xsoi6]:not([data-v]) { + transform: scaleX(-1); +} + +._mfm_x2_[s-xsoi6] { + font-size: 200%; +} + +._mfm_x3_[s-xsoi6] { + font-size: 400%; +} + +._mfm_x4_[s-xsoi6] { + font-size: 600%; +} + +._mfm_blur_[s-xsoi6] { + filter: blur(6px); + transition: filter 0.3s; +} +._mfm_blur_[s-xsoi6]:hover { + filter: blur(0px); +} + +._mfm_rainbow_[s-xsoi6] { + animation: mfm-rainbow 1s linear infinite; +} + +._mfm_rotate_[s-xsoi6] { + transform: rotate(90deg); + transform-origin: center center; +} + +/* sparkle */ + +@keyframes mfm-tada { + from[s-xsoi6] { + transform: scale3d(1, 1, 1); + } + + 10%, + 20% { + transform: scale3d(0.9, 0.9, 0.9) rotate3d(0, 0, 1, -3deg); + } + + 30%, + 50%, + 70%, + 90% { + transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg); + } + + 40%, + 60%, + 80% { + transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg); + } + + to[s-xsoi6] { + transform: scale3d(1, 1, 1); + } +} + +@keyframes bounce { + 0% { + transform: scaleX(0.9) scaleY(0.9); + } + + 19% { + transform: scaleX(1.1) scaleY(1.1); + } + + 48% { + transform: scaleX(0.95) scaleY(0.95); + } + + 100% { + transform: scaleX(1) scaleY(1); + } +} + +@keyframes mfm-spin { + 0% { + transform: rotate(0deg); + } + 100% { + transform: rotate(360deg); + } +} + +@keyframes mfm-spinX { + 0% { + transform: perspective(128px) rotateX(0deg); + } + 100% { + transform: perspective(128px) rotateX(360deg); + } +} + +@keyframes mfm-spinY { + 0% { + transform: perspective(128px) rotateY(0deg); + } + 100% { + transform: perspective(128px) rotateY(360deg); + } +} + +@keyframes mfm-jump { + 0% { + transform: translateY(0); + } + 25% { + transform: translateY(-16px); + } + 50% { + transform: translateY(0); + } + 75% { + transform: translateY(-8px); + } + 100% { + transform: translateY(0); + } +} + +@keyframes mfm-bounce { + 0% { + transform: translateY(0) scale(1, 1); + } + 25% { + transform: translateY(-16px) scale(1, 1); + } + 50% { + transform: translateY(0) scale(1, 1); + } + 75% { + transform: translateY(0) scale(1.5, 0.75); + } + 100% { + transform: translateY(0) scale(1, 1); + } +} + +@keyframes mfm-twitch { + 0% { + transform: translate(7px, -2px); + } + 5% { + transform: translate(-3px, 1px); + } + 10% { + transform: translate(-7px, -1px); + } + 15% { + transform: translate(0, -1px); + } + 20% { + transform: translate(-8px, 6px); + } + 25% { + transform: translate(-4px, -3px); + } + 30% { + transform: translate(-4px, -6px); + } + 35% { + transform: translate(-8px, -8px); + } + 40% { + transform: translate(4px, 6px); + } + 45% { + transform: translate(-3px, 1px); + } + 50% { + transform: translate(2px, -10px); + } + 55% { + transform: translate(-7px, 0); + } + 60% { + transform: translate(-2px, 4px); + } + 65% { + transform: translate(3px, -8px); + } + 70% { + transform: translate(6px, 7px); + } + 75% { + transform: translate(-7px, -2px); + } + 80% { + transform: translate(-7px, -8px); + } + 85% { + transform: translate(9px, 3px); + } + 90% { + transform: translate(-3px, -2px); + } + 95% { + transform: translate(-10px, 2px); + } + 100% { + transform: translate(-2px, -6px); + } +} + +@keyframes mfm-shake { + 0% { + transform: translate(-3px, -1px) rotate(-8deg); + } + 5% { + transform: translate(0, -1px) rotate(-10deg); + } + 10% { + transform: translate(1px, -3px) rotate(0deg); + } + 15% { + transform: translate(1px, 1px) rotate(11deg); + } + 20% { + transform: translate(-2px, 1px) rotate(1deg); + } + 25% { + transform: translate(-1px, -2px) rotate(-2deg); + } + 30% { + transform: translate(-1px, 2px) rotate(-3deg); + } + 35% { + transform: translate(2px, 1px) rotate(6deg); + } + 40% { + transform: translate(-2px, -3px) rotate(-9deg); + } + 45% { + transform: translate(0, -1px) rotate(-12deg); + } + 50% { + transform: translate(1px, 2px) rotate(10deg); + } + 55% { + transform: translate(0, -3px) rotate(8deg); + } + 60% { + transform: translate(1px, -1px) rotate(8deg); + } + 65% { + transform: translate(0, -1px) rotate(-7deg); + } + 70% { + transform: translate(-1px, -3px) rotate(6deg); + } + 75% { + transform: translate(0, -2px) rotate(4deg); + } + 80% { + transform: translate(-2px, -1px) rotate(3deg); + } + 85% { + transform: translate(1px, -3px) rotate(-10deg); + } + 90% { + transform: translate(1px, 0) rotate(3deg); + } + 95% { + transform: translate(-2px, 0) rotate(-3deg); + } + 100% { + transform: translate(2px, 1px) rotate(2deg); + } +} + +@keyframes mfm-jelly { + from[s-xsoi6] { + transform: scale3d(1, 1, 1); + } + 30% { + transform: scale3d(1.25, 0.75, 1); + } + 40% { + transform: scale3d(0.75, 1.25, 1); + } + 50% { + transform: scale3d(1.15, 0.85, 1); + } + 65% { + transform: scale3d(0.95, 1.05, 1); + } + 75% { + transform: scale3d(1.05, 0.95, 1); + } + to[s-xsoi6] { + transform: scale3d(1, 1, 1); + } +} + +@keyframes mfm-rainbow { + 0% { + filter: hue-rotate(0deg) contrast(150%) saturate(150%); + } + 100% { + filter: hue-rotate(360deg) contrast(150%) saturate(150%); + } +} + +.p_line_clamp_4[s-xsoi6], +.p_line_clamp_6[s-xsoi6] { + overflow: hidden; + text-overflow: ellipsis; + white-space: initial; + display: -webkit-box; + -webkit-box-orient: vertical; +} +.p_line_clamp_4[s-xsoi6] { + -webkit-line-clamp: 4; + line-clamp: 4; +} +.p_line_clamp_6[s-xsoi6] { + -webkit-line-clamp: 6; + line-clamp: 6; +} +.p_line_clamp_4[s-xsoi6] p[s-xsoi6], +.p_line_clamp_6[s-xsoi6] p[s-xsoi6] { + display: contents; +} diff --git a/flavours/classic/config/flavour_assets/hooks/Bonfire.Editor.Milkdown.hooks.js b/flavours/classic/config/flavour_assets/hooks/Bonfire.Editor.Milkdown.hooks.js new file mode 100644 index 0000000000..494678c339 --- /dev/null +++ b/flavours/classic/config/flavour_assets/hooks/Bonfire.Editor.Milkdown.hooks.js @@ -0,0 +1,578 @@ +/* +This file was generated by the Surface compiler. +*/ + +import { + defaultValueCtx, + editorViewOptionsCtx, + Editor, + editorViewCtx, + commandsCtx, + rootCtx, +} from "@milkdown/kit/core"; +import { $prose, replaceAll, insert } from "@milkdown/utils"; +import { + commonmark, + toggleStrongCommand, + toggleEmphasisCommand, +} from "@milkdown/kit/preset/commonmark"; +import { gfm } from "@milkdown/kit/preset/gfm"; +import { emoji } from "@milkdown/plugin-emoji"; +import { listener, listenerCtx } from "@milkdown/kit/plugin/listener"; +import { SlashProvider, slashFactory } from "@milkdown/kit/plugin/slash"; +import { gemoji } from "gemoji"; +import { clipboard } from "@milkdown/kit/plugin/clipboard"; +import { createPopup } from "@picmo/popup-picker"; +import { Plugin, PluginKey } from "@milkdown/kit/prose/state"; +import { Decoration, DecorationSet } from "@milkdown/kit/prose/view"; + +const PlaceholderPlugin = new Plugin({ + key: new PluginKey("milkdown-placeholder"), + props: { + decorations: (state) => { + const element = document.createElement("span"); + + element.classList.add("milkdown-placeholder"); + element.style.position = "absolute"; + element.style.opacity = "0.5"; + element.innerText = "Write something..."; + + const placeholderDecoration = Decoration.widget(0, element, { + key: "milkdown-placeholder", + side: 0, + }); + if (state.doc.textContent.trim().length === 0) { + return DecorationSet.create(state.doc, [placeholderDecoration]); + } + }, + }, +}); +const placeholder = $prose(() => PlaceholderPlugin); + +const MIN_PREFIX_LENGTH = 2; +const VALID_CHARS = "[\\w\\+_\\-:]"; +const MENTION_PREFIX = "(?:@)"; +const EMOJI_PREFIX = "(?::)"; +const MENTION_REGEX = new RegExp( + `(?:\\s|^)(${MENTION_PREFIX}${VALID_CHARS}{${MIN_PREFIX_LENGTH},})$`, +); +const EMOJI_REGEX = new RegExp( + `(?:\\s|^)(${EMOJI_PREFIX}${VALID_CHARS}{${MIN_PREFIX_LENGTH},})$`, +); + +import "@milkdown/theme-nord/style.css"; + +const markdown = ``; + +function mentionsPluginView(view) { + const content = document.createElement("ul"); + content.tabIndex = 1; + + content.className = + "milkdown-menu absolute m-0 p-0 menu left-menu bg-base-200 border border-base-content/10 shadow-xl border-lg"; + let list = ""; + + const provider = new SlashProvider({ + content, + shouldShow: (view, prevState) => { + // get the current content of the editor + const { state } = view; + const { doc } = state; + const currentText = doc.textContent; + + if (currentText === "") { + return false; + } + + const mentions = currentText.match(MENTION_REGEX); + // Display the menu if the last character is `@` followed by 2 chars. + if (mentions) { + // get the characters that follows the `@` in currentText + const text = mentions[1].split("@").pop(); + + return getFeedItems(text, "@").then((res) => { + list = ""; + if (res.length > 0) { + // Add max 4 items to the menu + let maxItems = 4; + for (let i = 0; i < res.length && i < maxItems; i++) { + list += mentionItemRenderer(res[i], text); + } + content.innerHTML = list; + return true; + } else { + content.innerHTML = ""; + return false; + } + }); + } + + return false; + }, + trigger: "@", + }); + + return { + update: (updatedView, prevState) => { + provider.update(updatedView, prevState); + }, + destroy: () => { + provider.destroy(); + content.remove(); + }, + }; +} + +function emojisPluginView() { + const content = document.createElement("ul"); + content.tabIndex = 1; + + content.className = + "milkdown-menu absolute m-0 p-0 menu w-72 bg-base-100 border border-base-content/10 shadow-lg"; + let list = ""; + + const provider = new SlashProvider({ + content, + shouldShow: (view, prevState) => { + // get the current content of the editor + const { state } = view; + const { doc } = state; + const currentText = doc.textContent; + + if (currentText === "") { + return false; + } + + const emojis = currentText.match(EMOJI_REGEX); + // Display the menu if the last character is `@` followed by 2 chars. + if (emojis) { + // get the characters that follows the `@` in currentText + const text = emojis[1].split(":").pop(); + const index = gemoji.findIndex((emoji) => { + return emoji.names.some((name) => name.includes(text)); + }); + list = ""; + if (index > 0) { + // Add max 4 items to the menu + gemoji + .filter((emoji) => { + return emoji.names.some((name) => name.includes(text)); + }) + .slice(0, 6) + .map((emoji) => { + list += emojiItemRenderer(emoji, text); + }); + + content.innerHTML = list; + return true; + } else { + content.innerHTML = ""; + return false; + } + } + return false; + }, + trigger: ":", + }); + + return { + update: (updatedView, prevState) => { + provider.update(updatedView, prevState); + }, + destroy: () => { + provider.destroy(); + content.remove(); + }, + }; +} + +// function slashPluginView(view) { +// const content = document.createElement('ul'); +// content.tabIndex = 1; + +// content.className = 'm-0 p-0 menu w-72 bg-base-100 shadow-lg ring-2'; +// let list = slashItemRenderer() +// content.innerHTML = list + +// const provider = new SlashProvider({ +// content, +// trigger: '/', +// }); + +// return { +// update: (updatedView, prevState) => { +// provider.update(updatedView, prevState); +// }, +// destroy: () => { +// provider.destroy(); +// content.remove(); +// } +// } +// } + +function getFeedItems(queryText, prefix) { + // console.log(prefix) + if (queryText && queryText.length > 0) { + return new Promise((resolve) => { + // this requires the bonfire_tag extension + fetch("/api/tag/autocomplete/ck5/" + prefix + "/" + queryText) + .then((response) => response.json()) + .then((data) => { + console.log("data"); + console.log(data); + let values = data.map((item) => ({ + id: item.id, + value: item.name, + icon: item.icon, + })); + resolve(values); + }) + .catch((error) => { + console.error("There has been a problem with the tag search:", error); + resolve([]); + }); + }); + } else return []; +} + +const mentionItemRenderer = (item, text) => { + return ` +