UNPKG

letsjam

Version:
1,499 lines (1,284 loc) 209 kB
function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } var React = require('react'); var React__default = _interopDefault(React); var emotion = require('emotion'); var Mousetrap = _interopDefault(require('mousetrap')); var jsBase64 = require('js-base64'); var moment = _interopDefault(require('moment')); var draftJs = require('draft-js'); var ReactTooltip = _interopDefault(require('react-tooltip')); var Editor = _interopDefault(require('draft-js-plugins-editor')); var createMentionPlugin = require('draft-js-mention-plugin'); var createMentionPlugin__default = _interopDefault(createMentionPlugin); var createLinkifyPlugin = _interopDefault(require('draft-js-linkify-plugin')); var createToolbarPlugin = _interopDefault(require('draft-js-static-toolbar-plugin')); var emojiMart = require('emoji-mart'); var tooltip = require('@reach/tooltip'); var reactSpring = require('react-spring'); var DeviceDetector = _interopDefault(require('device-detector-js')); var io = _interopDefault(require('socket.io-client')); var optimalSelect = require('optimal-select'); var ChipInput = _interopDefault(require('material-ui-chip-input')); var MutationObserver = _interopDefault(require('react-mutation-observer')); function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; } function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; } function _taggedTemplateLiteralLoose(strings, raw) { if (!raw) { raw = strings.slice(0); } strings.raw = raw; return strings; } function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; } function _createForOfIteratorHelperLoose(o) { var i = 0; if (typeof Symbol === "undefined" || o[Symbol.iterator] == null) { if (Array.isArray(o) || (o = _unsupportedIterableToArray(o))) return function () { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }; throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } i = o[Symbol.iterator](); return i.next.bind(i); } function _templateObject3() { var data = _taggedTemplateLiteralLoose(["\n\t\t\t\t\twidth: 30px;\n\t\t\t\t\theight: 30px;\n\t\t\t\t"]); _templateObject3 = function _templateObject3() { return data; }; return data; } function _templateObject2() { var data = _taggedTemplateLiteralLoose(["\n\t\t\t\t\tbackground: linear-gradient(\n\t\t\t\t\t\t\t0deg,\n\t\t\t\t\t\t\trgba(115, 229, 191, 0.2),\n\t\t\t\t\t\t\trgba(115, 229, 191, 0.2)\n\t\t\t\t\t\t),\n\t\t\t\t\t\t#ffffff;\n\t\t\t\t"]); _templateObject2 = function _templateObject2() { return data; }; return data; } function _templateObject() { var data = _taggedTemplateLiteralLoose(["\n\t\t\t\twidth: 60px;\n\t\t\t\theight: 60px;\n\t\t\t\tborder-radius: 50px;\n\t\t\t\tposition: fixed;\n\t\t\t\tbottom: 2rem;\n\t\t\t\tright: 2rem;\n\t\t\t\tbox-shadow: 0px 4px 10px rgba(0, 0, 0, 0.15);\n\t\t\t\tdisplay: flex;\n\t\t\t\talign-items: center;\n\t\t\t\tjustify-content: center;\n\t\t\t\tz-index: 1;\n\t\t\t\ttransition: all 0.4s ease-in-out;\n\t\t\t\tbackground: #f8f9fb;\n\t\t\t\tcursor: pointer;\n\t\t\t\tfont-size: 14px;\n\t\t\t\tz-index: 1000000;\n\n\t\t\t\t", "\n\t\t\t"]); _templateObject = function _templateObject() { return data; }; return data; } function JamButton(props) { return React__default.createElement("div", { onClick: props.toggleJamMode, className: emotion.css(_templateObject(), props.jamTime && emotion.css(_templateObject2())) }, React__default.createElement("img", { src: "https://strawberryjam.nyc3.cdn.digitaloceanspaces.com/icon.png", className: emotion.css(_templateObject3()) })); } function useKeyBinding(keys, callback) { var callbackRef = React.useRef(); React.useEffect(function () { callbackRef.current = callback; }, [callback]); React.useEffect(function () { Mousetrap.bind(keys, function () { if (callbackRef.current) { callbackRef.current(); } }); return function () { Mousetrap.unbind(keys); }; }, [keys, callbackRef]); } function KeyboardShortcuts(props) { useKeyBinding("j a m", function () { props.onToggleJamMode(); }); useKeyBinding("p a m", function () { console.log("missing the office"); }); return null; } function SuperShortcuts(props) { useKeyBinding("shift+u", function () { props.onToggleUpdates(); }); useKeyBinding("shift+right", function () { var nextThread = props.currentOpenThread + 1; if (nextThread === props.threads.length) { nextThread = 0; } props.onChangeOpenThread(nextThread); if (props.threads[nextThread] !== undefined && props.threads[nextThread].y !== undefined) { window.scrollTo(0, props.threads[nextThread].y - 100); } }); useKeyBinding("shift+left", function () { var prevThread = props.currentOpenThread - 1; if (prevThread < 0) { prevThread = props.threads.length - 1; } props.onChangeOpenThread(prevThread); if (props.threads[prevThread] !== undefined && props.threads[prevThread].y !== undefined) { window.scrollTo(0, props.threads[prevThread].y - 100); } }); useKeyBinding("command+enter", function () { props.onMessageSend(); }); return null; } var API_HOSTNAME = "https://app.jam.dev"; var SOCKET_SERVER = "https://socket-server.jam.dev"; var support = { searchParams: 'URLSearchParams' in self, iterable: 'Symbol' in self && 'iterator' in Symbol, blob: 'FileReader' in self && 'Blob' in self && (function() { try { new Blob(); return true } catch (e) { return false } })(), formData: 'FormData' in self, arrayBuffer: 'ArrayBuffer' in self }; function isDataView(obj) { return obj && DataView.prototype.isPrototypeOf(obj) } if (support.arrayBuffer) { var viewClasses = [ '[object Int8Array]', '[object Uint8Array]', '[object Uint8ClampedArray]', '[object Int16Array]', '[object Uint16Array]', '[object Int32Array]', '[object Uint32Array]', '[object Float32Array]', '[object Float64Array]' ]; var isArrayBufferView = ArrayBuffer.isView || function(obj) { return obj && viewClasses.indexOf(Object.prototype.toString.call(obj)) > -1 }; } function normalizeName(name) { if (typeof name !== 'string') { name = String(name); } if (/[^a-z0-9\-#$%&'*+.^_`|~]/i.test(name)) { throw new TypeError('Invalid character in header field name') } return name.toLowerCase() } function normalizeValue(value) { if (typeof value !== 'string') { value = String(value); } return value } // Build a destructive iterator for the value list function iteratorFor(items) { var iterator = { next: function() { var value = items.shift(); return {done: value === undefined, value: value} } }; if (support.iterable) { iterator[Symbol.iterator] = function() { return iterator }; } return iterator } function Headers(headers) { this.map = {}; if (headers instanceof Headers) { headers.forEach(function(value, name) { this.append(name, value); }, this); } else if (Array.isArray(headers)) { headers.forEach(function(header) { this.append(header[0], header[1]); }, this); } else if (headers) { Object.getOwnPropertyNames(headers).forEach(function(name) { this.append(name, headers[name]); }, this); } } Headers.prototype.append = function(name, value) { name = normalizeName(name); value = normalizeValue(value); var oldValue = this.map[name]; this.map[name] = oldValue ? oldValue + ', ' + value : value; }; Headers.prototype['delete'] = function(name) { delete this.map[normalizeName(name)]; }; Headers.prototype.get = function(name) { name = normalizeName(name); return this.has(name) ? this.map[name] : null }; Headers.prototype.has = function(name) { return this.map.hasOwnProperty(normalizeName(name)) }; Headers.prototype.set = function(name, value) { this.map[normalizeName(name)] = normalizeValue(value); }; Headers.prototype.forEach = function(callback, thisArg) { for (var name in this.map) { if (this.map.hasOwnProperty(name)) { callback.call(thisArg, this.map[name], name, this); } } }; Headers.prototype.keys = function() { var items = []; this.forEach(function(value, name) { items.push(name); }); return iteratorFor(items) }; Headers.prototype.values = function() { var items = []; this.forEach(function(value) { items.push(value); }); return iteratorFor(items) }; Headers.prototype.entries = function() { var items = []; this.forEach(function(value, name) { items.push([name, value]); }); return iteratorFor(items) }; if (support.iterable) { Headers.prototype[Symbol.iterator] = Headers.prototype.entries; } function consumed(body) { if (body.bodyUsed) { return Promise.reject(new TypeError('Already read')) } body.bodyUsed = true; } function fileReaderReady(reader) { return new Promise(function(resolve, reject) { reader.onload = function() { resolve(reader.result); }; reader.onerror = function() { reject(reader.error); }; }) } function readBlobAsArrayBuffer(blob) { var reader = new FileReader(); var promise = fileReaderReady(reader); reader.readAsArrayBuffer(blob); return promise } function readBlobAsText(blob) { var reader = new FileReader(); var promise = fileReaderReady(reader); reader.readAsText(blob); return promise } function readArrayBufferAsText(buf) { var view = new Uint8Array(buf); var chars = new Array(view.length); for (var i = 0; i < view.length; i++) { chars[i] = String.fromCharCode(view[i]); } return chars.join('') } function bufferClone(buf) { if (buf.slice) { return buf.slice(0) } else { var view = new Uint8Array(buf.byteLength); view.set(new Uint8Array(buf)); return view.buffer } } function Body() { this.bodyUsed = false; this._initBody = function(body) { this._bodyInit = body; if (!body) { this._bodyText = ''; } else if (typeof body === 'string') { this._bodyText = body; } else if (support.blob && Blob.prototype.isPrototypeOf(body)) { this._bodyBlob = body; } else if (support.formData && FormData.prototype.isPrototypeOf(body)) { this._bodyFormData = body; } else if (support.searchParams && URLSearchParams.prototype.isPrototypeOf(body)) { this._bodyText = body.toString(); } else if (support.arrayBuffer && support.blob && isDataView(body)) { this._bodyArrayBuffer = bufferClone(body.buffer); // IE 10-11 can't handle a DataView body. this._bodyInit = new Blob([this._bodyArrayBuffer]); } else if (support.arrayBuffer && (ArrayBuffer.prototype.isPrototypeOf(body) || isArrayBufferView(body))) { this._bodyArrayBuffer = bufferClone(body); } else { this._bodyText = body = Object.prototype.toString.call(body); } if (!this.headers.get('content-type')) { if (typeof body === 'string') { this.headers.set('content-type', 'text/plain;charset=UTF-8'); } else if (this._bodyBlob && this._bodyBlob.type) { this.headers.set('content-type', this._bodyBlob.type); } else if (support.searchParams && URLSearchParams.prototype.isPrototypeOf(body)) { this.headers.set('content-type', 'application/x-www-form-urlencoded;charset=UTF-8'); } } }; if (support.blob) { this.blob = function() { var rejected = consumed(this); if (rejected) { return rejected } if (this._bodyBlob) { return Promise.resolve(this._bodyBlob) } else if (this._bodyArrayBuffer) { return Promise.resolve(new Blob([this._bodyArrayBuffer])) } else if (this._bodyFormData) { throw new Error('could not read FormData body as blob') } else { return Promise.resolve(new Blob([this._bodyText])) } }; this.arrayBuffer = function() { if (this._bodyArrayBuffer) { return consumed(this) || Promise.resolve(this._bodyArrayBuffer) } else { return this.blob().then(readBlobAsArrayBuffer) } }; } this.text = function() { var rejected = consumed(this); if (rejected) { return rejected } if (this._bodyBlob) { return readBlobAsText(this._bodyBlob) } else if (this._bodyArrayBuffer) { return Promise.resolve(readArrayBufferAsText(this._bodyArrayBuffer)) } else if (this._bodyFormData) { throw new Error('could not read FormData body as text') } else { return Promise.resolve(this._bodyText) } }; if (support.formData) { this.formData = function() { return this.text().then(decode) }; } this.json = function() { return this.text().then(JSON.parse) }; return this } // HTTP methods whose capitalization should be normalized var methods = ['DELETE', 'GET', 'HEAD', 'OPTIONS', 'POST', 'PUT']; function normalizeMethod(method) { var upcased = method.toUpperCase(); return methods.indexOf(upcased) > -1 ? upcased : method } function Request(input, options) { options = options || {}; var body = options.body; if (input instanceof Request) { if (input.bodyUsed) { throw new TypeError('Already read') } this.url = input.url; this.credentials = input.credentials; if (!options.headers) { this.headers = new Headers(input.headers); } this.method = input.method; this.mode = input.mode; this.signal = input.signal; if (!body && input._bodyInit != null) { body = input._bodyInit; input.bodyUsed = true; } } else { this.url = String(input); } this.credentials = options.credentials || this.credentials || 'same-origin'; if (options.headers || !this.headers) { this.headers = new Headers(options.headers); } this.method = normalizeMethod(options.method || this.method || 'GET'); this.mode = options.mode || this.mode || null; this.signal = options.signal || this.signal; this.referrer = null; if ((this.method === 'GET' || this.method === 'HEAD') && body) { throw new TypeError('Body not allowed for GET or HEAD requests') } this._initBody(body); } Request.prototype.clone = function() { return new Request(this, {body: this._bodyInit}) }; function decode(body) { var form = new FormData(); body .trim() .split('&') .forEach(function(bytes) { if (bytes) { var split = bytes.split('='); var name = split.shift().replace(/\+/g, ' '); var value = split.join('=').replace(/\+/g, ' '); form.append(decodeURIComponent(name), decodeURIComponent(value)); } }); return form } function parseHeaders(rawHeaders) { var headers = new Headers(); // Replace instances of \r\n and \n followed by at least one space or horizontal tab with a space // https://tools.ietf.org/html/rfc7230#section-3.2 var preProcessedHeaders = rawHeaders.replace(/\r?\n[\t ]+/g, ' '); preProcessedHeaders.split(/\r?\n/).forEach(function(line) { var parts = line.split(':'); var key = parts.shift().trim(); if (key) { var value = parts.join(':').trim(); headers.append(key, value); } }); return headers } Body.call(Request.prototype); function Response(bodyInit, options) { if (!options) { options = {}; } this.type = 'default'; this.status = options.status === undefined ? 200 : options.status; this.ok = this.status >= 200 && this.status < 300; this.statusText = 'statusText' in options ? options.statusText : 'OK'; this.headers = new Headers(options.headers); this.url = options.url || ''; this._initBody(bodyInit); } Body.call(Response.prototype); Response.prototype.clone = function() { return new Response(this._bodyInit, { status: this.status, statusText: this.statusText, headers: new Headers(this.headers), url: this.url }) }; Response.error = function() { var response = new Response(null, {status: 0, statusText: ''}); response.type = 'error'; return response }; var redirectStatuses = [301, 302, 303, 307, 308]; Response.redirect = function(url, status) { if (redirectStatuses.indexOf(status) === -1) { throw new RangeError('Invalid status code') } return new Response(null, {status: status, headers: {location: url}}) }; var DOMException = self.DOMException; try { new DOMException(); } catch (err) { DOMException = function(message, name) { this.message = message; this.name = name; var error = Error(message); this.stack = error.stack; }; DOMException.prototype = Object.create(Error.prototype); DOMException.prototype.constructor = DOMException; } function fetch$1(input, init) { return new Promise(function(resolve, reject) { var request = new Request(input, init); if (request.signal && request.signal.aborted) { return reject(new DOMException('Aborted', 'AbortError')) } var xhr = new XMLHttpRequest(); function abortXhr() { xhr.abort(); } xhr.onload = function() { var options = { status: xhr.status, statusText: xhr.statusText, headers: parseHeaders(xhr.getAllResponseHeaders() || '') }; options.url = 'responseURL' in xhr ? xhr.responseURL : options.headers.get('X-Request-URL'); var body = 'response' in xhr ? xhr.response : xhr.responseText; resolve(new Response(body, options)); }; xhr.onerror = function() { reject(new TypeError('Network request failed')); }; xhr.ontimeout = function() { reject(new TypeError('Network request failed')); }; xhr.onabort = function() { reject(new DOMException('Aborted', 'AbortError')); }; xhr.open(request.method, request.url, true); if (request.credentials === 'include') { xhr.withCredentials = true; } else if (request.credentials === 'omit') { xhr.withCredentials = false; } if ('responseType' in xhr && support.blob) { xhr.responseType = 'blob'; } request.headers.forEach(function(value, name) { xhr.setRequestHeader(name, value); }); if (request.signal) { request.signal.addEventListener('abort', abortXhr); xhr.onreadystatechange = function() { // DONE (success or failure) if (xhr.readyState === 4) { request.signal.removeEventListener('abort', abortXhr); } }; } xhr.send(typeof request._bodyInit === 'undefined' ? null : request._bodyInit); }) } fetch$1.polyfill = true; if (!self.fetch) { self.fetch = fetch$1; self.Headers = Headers; self.Request = Request; self.Response = Response; } // the whatwg-fetch polyfill installs the fetch() function // on the global object (window or self) // // Return that as the export for use in Webpack, Browserify etc. var fetchNpmBrowserify = self.fetch.bind(self); function _catch(body, recover) { try { var result = body(); } catch (e) { return recover(e); } if (result && result.then) { return result.then(void 0, recover); } return result; } var jamIsPublic = function jamIsPublic(JAM_ID) { var res, json; return Promise.resolve(_catch(function () { return Promise.resolve(fetchNpmBrowserify(API_HOSTNAME + "/api/plugin/jam/" + JAM_ID + "/is_public", { method: "GET", headers: { "Content-Type": "application/json" } })).then(function (_fetch) { res = _fetch; return Promise.resolve(res.json()).then(function (_res$json) { json = _res$json; return json["public"]; }); }); }, function () { return false; })); }; var isAuthenticated = function isAuthenticated(JAM_ID) { try { var user; return Promise.resolve(jamIsPublic(JAM_ID)).then(function (isPublic) { if (isPublic) { user = window.localStorage.getItem("jamUser"); return user ? true : false; } else { if (document.cookie.split(";").some(function (cookie) { return cookie.trim().startsWith("jam_filled_cookie="); })) { return true; } else { return false; } } }); } catch (e) { return Promise.reject(e); } }; function getJamFilledCookie() { try { var v = document.cookie.match("(^|;) ?" + "jam_filled_cookie" + "=([^;]*)(;|$)"); var cookie = v ? v[0] : null; if (!cookie) throw new Error("no cookie"); cookie = cookie.split(", domain=")[0]; if (cookie.includes("; ")) return cookie.replace("; ", ""); return cookie; } catch (e) { return "jam_filled_cookie=false"; } } function getUserIdFromJamFilledCookie() { try { var cookie = getJamFilledCookie(); var userId = jsBase64.Base64.decode(cookie.split(".")[1]).replace('{"_id":', "").split('"')[1]; return userId; } catch (e) { return false; } } function getUserIdFromLocalStorage() { return JSON.parse(window.localStorage.getItem("jamUser"))._id; } var isPermissioned = function isPermissioned(JAM_ID) { try { return Promise.resolve(fetchNpmBrowserify(API_HOSTNAME + "/api/plugin/jam/" + JAM_ID + "/check_user_allowed", { method: "POST", headers: { "content-type": "application/json", "jam-filled-cookie": getJamFilledCookie(), "jam-filled-userid": getUserIdFromLocalStorage() }, body: JSON.stringify({ userId: getUserIdFromJamFilledCookie() }) })).then(function (res) { return Promise.resolve(res.json()).then(function (json) { return json.allowed; }); }); } catch (e) { return Promise.reject(e); } }; function _catch$1(body, recover) { try { var result = body(); } catch (e) { return recover(e); } if (result && result.then) { return result.then(void 0, recover); } return result; } var getUserByIdInJamFilledStorage = function getUserByIdInJamFilledStorage(JAM_ID) { try { var res, json; return Promise.resolve(_catch$1(function () { return Promise.resolve(fetchNpmBrowserify(API_HOSTNAME + "/api/user/" + getUserIdFromJamFilledCookie(), { headers: { "Content-Type": "application/json", "jam-filled-cookie": getJamFilledCookie(), "jam-filled-userid": getUserIdFromLocalStorage(), jamid: JAM_ID } })).then(function (_fetch) { res = _fetch; return Promise.resolve(res.json()).then(function (_res$json) { json = _res$json; localStorage.setItem("jamUser", JSON.stringify(json.user)); return true; }); }); }, function (e) { console.log(e); return false; })); } catch (e) { return Promise.reject(e); } }; function getUserFromLocalStorage() { if (localStorage.getItem("jamUser") && localStorage.getItem("jamUser") !== "undefined") { return JSON.parse(localStorage.getItem("jamUser") || ""); } else return false; } function _catch$2(body, recover) { try { var result = body(); } catch (e) { return recover(e); } if (result && result.then) { return result.then(void 0, recover); } return result; } var getThreads = function getThreads(JAM_ID) { var res, json; return Promise.resolve(_catch$2(function () { return Promise.resolve(fetchNpmBrowserify(API_HOSTNAME + "/api/plugin/jam/" + JAM_ID + "/threads", { headers: { "Content-Type": "application/json", "jam-filled-cookie": getJamFilledCookie(), "jam-filled-userid": getUserIdFromLocalStorage() } })).then(function (_fetch) { res = _fetch; return Promise.resolve(res.json()).then(function (_res$json) { json = _res$json; return json; }); }); }, function () { return false; })); }; function humanReadableTimeAgo(objectId) { var commentDate = new Date(parseInt(objectId.substring(0, 8), 16) * 1000); var string = moment(commentDate).fromNow(); if (string === "a few seconds ago") string = "just now"; string = string.replace("minutes", "min"); return string; } function idOrSection(str) { if (str.includes("-") && str.includes("_")) { return { type: "id" }; } if (str.includes("@")) { return { type: "id" }; } if (str.length === 1) { if (str.match(/[a-z]/i)) { return { type: "section" }; } else { return { type: "id" }; } } if (!isNaN(Number(str))) { return { type: "id" }; } if ((str.match(/[A-Z]/g) || []).length > 2 && (str.match(/[a-z]/g) || []).length > 2) { return { type: "id" }; } if ((str.match(/-/g) || []).length > 3 || (str.match(/_/g) || []).length > 3) { return { type: "id" }; } var arr = str.includes("-") ? str.split("-") : str.split("_"); var isIdArray = arr.map(function (substring) { if ((substring.match(/[0-9]/g) || []).length > 0 && (substring.match(/[A-Za-z]/g) || []).length > 0) { return true; } if ((substring.match(/[A-Z]/g) || []).length > 2 && (substring.match(/[a-z]/g) || []).length > 2) { return true; } if (!isNaN(Number(substring))) { return true; } if (substring === substring.toUpperCase()) { return true; } return false; }); if (isIdArray.indexOf(true) > -1) return { type: "id" }; return { type: "section" }; } function isNotUndefined(value) { return typeof value !== "undefined"; } function createUrlPattern(host, pathname) { var path = pathname.split("/"); var pathPatternArray = path.map(function (subpath) { if (subpath.length === 0) return; var _idOrSection = idOrSection(subpath), type = _idOrSection.type; if (type === "section") return subpath; return "*"; }); var filtered = pathPatternArray.filter(isNotUndefined); return { host: host, pathPatternArray: filtered }; } function checkUrlAgainstPattern(urlObj, urlPatternObj) { if (urlObj.host !== urlPatternObj.host) { return false; } if (urlObj.pathPatternArray.length !== urlPatternObj.pathPatternArray.length) { return false; } var doItemsMatch = urlPatternObj.pathPatternArray.map(function (subpath, index) { if (subpath === "*") return true;else if (subpath === urlObj.pathPatternArray[index]) return true;else return false; }); if (doItemsMatch.indexOf(false) > -1) return false;else return true; } function positionCommentX(thread, type) { var _createUrlPattern = createUrlPattern(window.location.host, window.location.pathname), host = _createUrlPattern.host, pathPatternArray = _createUrlPattern.pathPatternArray; var correctPageToDisplayThreadOn = checkUrlAgainstPattern({ host: host, pathPatternArray: pathPatternArray }, { host: thread.location.host, pathPatternArray: JSON.parse(thread.location.path) }); var element = document.querySelector(thread.location.selector); if (!element || !correctPageToDisplayThreadOn) { return -1000; } else { var rect = element.getBoundingClientRect(); var newX = rect.x + thread.location.percentFromLeft * rect.width; var coords; if (type == "preview") { coords = document.querySelector("#jam--preview-thread-" + thread._id).getBoundingClientRect(); } else if (type == "thread") { coords = document.querySelector("#jam--thread-container-" + thread._id) ? document.querySelector("#jam--thread-container-" + thread._id).getBoundingClientRect() : document.querySelector("#jam--preview-thread-" + thread._id).getBoundingClientRect(); } else { throw new Error("TODO"); } if (window.innerWidth < thread.x + coords.width) { var amountToMoveLeft = thread.x + coords.width - window.innerWidth; newX = thread.x - amountToMoveLeft - 5; } if (newX < 5 || thread.x < 5) { newX = 5; } if (newX > coords.width / 2) { newX = newX - coords.width / 2; } return newX; } } function positionCommentY(thread, type) { var _createUrlPattern = createUrlPattern(window.location.host, window.location.pathname), host = _createUrlPattern.host, pathPatternArray = _createUrlPattern.pathPatternArray; var correctPageToDisplayThreadOn = checkUrlAgainstPattern({ host: host, pathPatternArray: pathPatternArray }, { host: thread.location.host, pathPatternArray: JSON.parse(thread.location.path) }); var element = document.querySelector(thread.location.selector); if (!element || !correctPageToDisplayThreadOn) { return -1000; } else { var rect = element.getBoundingClientRect(); var newY = rect.y + window.scrollY + thread.location.percentFromTop * rect.height; var coords; if (type == "preview") { coords = document.querySelector("#jam--preview-thread-" + thread._id).getBoundingClientRect(); } else if (type == "thread") { coords = document.querySelector("#jam--thread-container-" + thread._id) ? document.querySelector("#jam--thread-container-" + thread._id).getBoundingClientRect() : document.querySelector("#jam--preview-thread-" + thread._id).getBoundingClientRect(); } else { throw new Error("TODO"); } var body = document.body; var html = document.documentElement; var height = Math.max(body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight); if (height < thread.y + coords.height) { var amountToMoveUp = thread.y + coords.height - height; newY = thread.y - amountToMoveUp - 5; } if (newY < 5 || thread.y < 5) { newY = 5; } return newY; } } function generateReactionTooltip(emoji, upvotedUsers) { if (upvotedUsers.length === 0) { return ""; } else if (upvotedUsers.length === 1) { return upvotedUsers[0] + " said " + emoji; } else if (upvotedUsers.length === 2) { return upvotedUsers[0] + " and " + upvotedUsers[1] + " said " + emoji; } else if (upvotedUsers.length === 3) { var tempArray = upvotedUsers.slice(0, upvotedUsers.length - 1); return tempArray.join(", ") + " and " + upvotedUsers[upvotedUsers.length - 1] + " said " + emoji; } else { var _tempArray = upvotedUsers.slice(0, 3); return _tempArray.join(", ") + " and others said " + emoji; } } function JamPreview(props) { var thread = props.thread; var comments = thread.comments; var lastComment = comments[comments.length - 1]; var messagePreview = React.useMemo(function () { var jsonifiedCommentMessage = JSON.parse(lastComment.message); var messageConvertedFromRaw = draftJs.convertFromRaw(jsonifiedCommentMessage); var tempEditorState = draftJs.EditorState.createWithContent(messageConvertedFromRaw); var commentText = tempEditorState.getCurrentContent().getPlainText("\x01"); return commentText.replace("\x01", " "); }, [lastComment]); var authors = React.useMemo(function () { var authors = new Map(); for (var _iterator = _createForOfIteratorHelperLoose(comments), _step; !(_step = _iterator()).done;) { var comment = _step.value; if (!authors.has(comment.author.name)) { authors.set(comment.author.name, comment.author); } if (authors.size >= 6) { break; } } return Array.from(authors.values()); }, [comments]); var reactions = React.useMemo(function () { var reactions = []; for (var _iterator2 = _createForOfIteratorHelperLoose(comments.slice(0, 3)), _step2; !(_step2 = _iterator2()).done;) { var comment = _step2.value; if (comment.reactions) { for (var _iterator3 = _createForOfIteratorHelperLoose(comment.reactions), _step3; !(_step3 = _iterator3()).done;) { var reaction = _step3.value; reactions.push({ emoji: reaction.emoji, upvotedUsers: reaction.upvotedUsers }); } } } return reactions; }, [comments]); var _useState = React.useState(0), positionedX = _useState[0], setPositionedX = _useState[1]; var _useState2 = React.useState(0), positionedY = _useState2[0], setPositionedY = _useState2[1]; React.useLayoutEffect(function () { setPositionedX(positionCommentX(thread, "thread")); setPositionedY(positionCommentY(thread, "thread")); }, [thread]); return React__default.createElement("div", { onClick: props.onClick, key: "jam--preview-" + thread._id, style: { top: positionedY + "px", left: positionedX + "px" }, id: "jam--preview-thread-" + thread._id, className: "jam--preview " + thread._id }, React__default.createElement("div", { className: "jam--preview-conainer-outer" }, React__default.createElement("div", { className: "jam--preview-avatars" }, authors.map(function (author) { return React__default.createElement("img", { key: author._id, src: author.avatar }); })), React__default.createElement("div", { className: "jam--preview-container" }, React__default.createElement("div", { className: "jam--preview-container-row" }, React__default.createElement("p", { className: "jam--preview-text" }, messagePreview), React__default.createElement("div", { className: "jam--preview-reply-date" }, humanReadableTimeAgo(lastComment._id))), React__default.createElement("div", { className: "jam--preview-container-row" }, reactions.length > 0 && React__default.createElement("div", { className: "jam--preview-reactions" }, reactions.map(function (reaction, index) { var tooltipText = generateReactionTooltip(reaction.emoji, reaction.upvotedUsers); return React__default.createElement("div", { key: "emoji-" + index, className: "jam--preview-reaction", "data-tip": tooltipText }, reaction.emoji); }))), React__default.createElement(ReactTooltip, { place: "top", type: "dark", effect: "float" }))), React__default.createElement("style", null, "\n\t\t\t\t.jam--preview {\n\t\t\t\t\tmax-width: 400px;\n\t\t\t\t\theight: 66px;\n\t\t\t\t\tbackground: #fff;\n\t\t\t\t\tbox-sizing: border-box;\n\t\t\t\t\tdisplay: flex;\n\t\t\t\t\tflex-direction: row;\n\t\t\t\t\talign-items: center;\n\t\t\t\t\tjustify-content: space-around;\n\t\t\t\t\tborder-radius: 10px;\n\t\t\t\t\tbox-shadow: 0px 4px 10px rgba(0, 0, 0, 0.1);\n\t\t\t\t\tfont-family: \"SF Pro Text\",-apple-system,BlinkMacSystemFont,\"Segoe UI\",Roboto,\"Helvetica Neue\",Arial,\"Noto Sans\",sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\",\"Segoe UI Symbol\",\"Noto Color Emoji\";\n\t\t\t\t\tHelvetica, Arial, sans-serif;\n\t\t\t\t\tcolor: #2A3632;\n\t\t\t\t\tposition: absolute;\n\t\t\t\t\tfont-size: 14px;\n\t\t\t\t\tz-index: 1000000;\n\t\t\t\t\tpadding: 5px 10px;\n\t\t\t\t}\n\n\t\t\t\t@media screen and (max-width: 450px) {\n\t\t\t\t\t.jam--preview {\n\t\t\t\t\t\twidth: 365px;\n\t\t\t\t\t\tmargin-left: auto;\n\t\t\t\t\t\tmargin-right: auto;\n\t\t\t\t\t\tleft: 0 !important;\n\t\t\t\t\t\tright: 0;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t.jam--preview-conainer-outer {\n\t\t\t\t\tdisplay: flex;\n\t\t\t\t\tflex-direction: row;\n\t\t\t\t\twidth: 100%;\n\t\t\t\t\talign-items: center;\n\t\t\t\t\tz-index: 1000000;\n\t\t\t\t}\n\n\t\t\t\t.jam--preview-container-row {\n\t\t\t\t\talign-items: center;\n\t\t\t\t\tdisplay: flex;\n\t\t\t\t\tflex-direction: row;\n\t\t\t\t\twidth: 100%;\n\t\t\t\t\tfont-size: 14px;\n\t\t\t\t\toverflow: hidden;\n\t\t\t\t\tz-index: 1000000;\n\t\t\t\t}\n\n\t\t\t\t.jam--preview-container {\n\t\t\t\t\tdisplay: flex;\n\t\t\t\t\tflex-direction: column;\n\t\t\t\t\tmax-width: 310px;\n\t\t\t\t\tz-index: 1000000;\n\t\t\t\t}\n\n\t\t\t\t.jam--preview-container:hover {\n\t\t\t\t\tcursor: pointer;\n\t\t\t\t}\n\n\t\t\t\t.jam--preview-avatars {\n\t\t\t\t\tdisplay: flex;\n\t\t\t\t\tflex-direction: row;\n\t\t\t\t\talign-items: center;\n\t\t\t\t\tmargin-right: 4px;\n\t\t\t\t}\n\n\t\t\t\t.jam--preview-avatars img {\n\t\t\t\t\tborder-radius: 50%;\n\t\t\t\t\theight: 40px;\n\t\t\t\t\twidth: 40px;\n\t\t\t\t\tbox-shadow: 0px 4px 10px rgba(0, 0, 0, 0.05);\n\t\t\t\t}\n\n\t\t\t\t.jam--preview-avatars img:not(:first-child) {\n\t\t\t\t\tmargin-left: -13px;\n\t\t\t\t}\n\n\t\t\t\t.jam--preview-num-comments {\n\t\t\t\t\tfont-weight: 400;\n\t\t\t\t\tcolor: #142dbd;\n\t\t\t\t\tfont-size: 14px;\n\t\t\t\t\tmargin-right: 4px;\n\t\t\t\t\twhite-space: nowrap;\n\t\t\t\t\tline-height: 20px;\n\t\t\t\t}\n\n\t\t\t\t.jam--preview-reply-date {\n\t\t\t\t\tcolor: rgba(42, 54, 50, .5);\n\t\t\t\t\tfont-size: 14px;\n\t\t\t\t\twhite-space: nowrap;\n\t\t\t\t\tline-height: 20px;\n\t\t\t\t\tfont-weight: 400;\n\t\t\t\t}\n\n\t\t\t\t.jam--preview-text {\n\t\t\t\t\twhite-space: nowrap;\n\t\t\t\t\toverflow: hidden;\n\t\t\t\t\ttext-overflow: ellipsis;\n\t\t\t\t\tmargin: initial;\n\t\t\t\t\tmargin-right: 4px;\n\t\t\t\t\tmargin-left: 4px;\n\t\t\t\t\tline-height: 20px;\n\t\t\t\t\tfont-size: 14px;\n\t\t\t\t\tcolor: #3C81C7;\n\t\t\t\t\tbackground: rgba(100, 175, 250, .15);\n\t\t\t\t}\n\n\t\t\t\t.jam--preview-notification {\n\t\t\t\t\talign-self: center;\n\t\t\t\t\tborder-radius: 50%;\n\t\t\t\t\tbackground: #e8180a;\n\t\t\t\t\theight: 8px;\n\t\t\t\t\twidth: 8px;\n\t\t\t\t\tfont-size: 14px;\n\t\t\t\t}\n\n\t\t\t\t#jam--eye-icon-toggle-preview {\n\t\t\t\t\tmargin-right: 6px;\n\t\t\t\t\tmargin-left: 2px;\n\t\t\t\t\topacity: 0.5;\n\t\t\t\t}\n\n\t\t\t\t.jam--preview-reactions {\n\t\t\t\t\tdisplay: flex;\n\t\t\t\t\tflex-direction: row;\n\t\t\t\t\talign-items: center;\n\t\t\t\t\tpadding: 6px;\n\t\t\t\t\tmargin: 0 4px 0 0;\n\t\t\t\t\tjustify-content: center;\n\t\t\t\t\tbox-sizing: border-box;\n\t\t\t\t\tmargin-top: 5px;\n\t\t\t\t\theight: 12px;\n\t\t\t\t}\n\n\t\t\t\t.jam--preview-reaction {\n\t\t\t\t\tmargin-top: 1em;\n\t\t\t\t\tmargin-bottom: 1em;\n\t\t\t\t\tfont-size: 10px;\n\t\t\t\t}\n\t\t\t")); } function _catch$3(body, recover) { try { var result = body(); } catch (e) { return recover(e); } if (result && result.then) { return result.then(void 0, recover); } return result; } var resolveThreadById = function resolveThreadById(threadId, JAM_ID) { try { var res, json; return Promise.resolve(_catch$3(function () { return Promise.resolve(fetchNpmBrowserify(API_HOSTNAME + "/api/plugin/jam/" + JAM_ID + "/threads/" + threadId + "/delete", { method: "POST", headers: { "Content-Type": "application/json", "jam-filled-cookie": getJamFilledCookie(), "jam-filled-userid": getUserIdFromLocalStorage() } })).then(function (_fetch) { res = _fetch; return Promise.resolve(res.json()).then(function (_res$json) { json = _res$json; return json; }); }); }, function (e) { console.log(e); })); } catch (e) { return Promise.reject(e); } }; function _catch$4(body, recover) { try { var result = body(); } catch (e) { return recover(e); } if (result && result.then) { return result.then(void 0, recover); } return result; } var addMessageToThread = function addMessageToThread(threadId, message, JAM_ID) { var res, json; return Promise.resolve(_catch$4(function () { return Promise.resolve(fetch(API_HOSTNAME + "/api/plugin/jam/" + JAM_ID + "/threads/" + threadId, { method: "POST", headers: { "Content-Type": "application/json", "jam-filled-cookie": getJamFilledCookie(), "jam-filled-userid": getUserIdFromLocalStorage() }, body: JSON.stringify({ author: getUserIdFromLocalStorage(), message: message }) })).then(function (_fetch) { res = _fetch; return Promise.resolve(res.json()).then(function (_res$json) { json = _res$json; return json; }); }); }, function () { return false; })); }; function isALoomVideo(loomUrl) { var loomRe = /http(()|(s)):\/\/((www.)|())loom.com\/((share)|(embed))\/.[^ ]*/g; var loomUrlArr = loomRe.exec(loomUrl); if (loomUrlArr === null) { return null; } else { var embedUrl = loomUrlArr[0]; if (embedUrl.includes("share")) { embedUrl = embedUrl.replace("share", "embed"); return embedUrl; } return embedUrl; } } var hasCommandModifier = draftJs.KeyBindingUtil.hasCommandModifier; function processKeyBinding(event) { if (event.keyCode === 13 && hasCommandModifier(event)) { return "jameditor-enter"; } return draftJs.getDefaultKeyBinding(event); } var mentionsTheme = { mention: "mention", mentionSuggestions: "mentionSuggestions", mentionSuggestionsEntry: "mentionSuggestionsEntry", mentionSuggestionsEntryFocused: "mentionSuggestionsEntryFocused", mentionSuggestionsEntryText: "mentionSuggestionsEntryText", mentionSuggestionsEntryAvatar: "mentionSuggestionsEntryAvatar", mentionSuggestionsEntryContainer: "mentionSuggestionsEntryContainer", mentionSuggestionsEntryContainerRight: "mentionSuggestionsEntryContainerRight", mentionSuggestionsEntryTitle: "mentionSuggestionsEntryTitle" }; var linkifyPlugin = createLinkifyPlugin(); var staticToolbarPlugin = createToolbarPlugin(); function Entry(props) { var mention = props.mention, theme = props.theme, parentProps = _objectWithoutPropertiesLoose(props, ["mention", "theme"]); return React__default.createElement("div", Object.assign({}, parentProps), React__default.createElement("div", { className: theme.mentionSuggestionsEntryContainer }, React__default.createElement("div", { className: theme.mentionSuggestionsEntryContainerLeft }, React__default.createElement("img", { src: mention.avatar, className: theme.mentionSuggestionsEntryAvatar, role: "presentation" })), React__default.createElement("div", { className: theme.mentionSuggestionsEntryContainerRight }, React__default.createElement("div", { className: theme.mentionSuggestionsEntryText }, mention.name), React__default.createElement("div", { className: theme.mentionSuggestionsEntryTitle }, mention.title)))); } function getEmbeddedVideoSrc(text) { if (!text.includes("loom")) return null; if (!(text.includes("share") || text.includes("embed"))) return null; return isALoomVideo(text); } function JamEditor(props) { var editorState = props.editorState, mentions = props.mentions; var editorRef = React.useRef(null); var mentionPlugin = React.useMemo(function () { return createMentionPlugin__default({ mentions: mentions, entityMutability: "IMMUTABLE", theme: mentionsTheme, mentionPrefix: "@", supportWhitespace: true }); }, [mentions]); var _useState = React.useState(props.mentions), suggestions = _useState[0], setSuggestions = _useState[1]; var _useState2 = React.useState(false), readOnly = _useState2[0], setReadOnly = _useState2[1]; var embedVideoSrc = React.useMemo(function () { var state = draftJs.convertToRaw(editorState.getCurrentContent()); for (var _iterator = _createForOfIteratorHelperLoose(state.blocks), _step; !(_step = _iterator()).done;) { var block = _step.value; var text = block.text; var _embedVideoSrc = getEmbeddedVideoSrc(text); if (_embedVideoSrc !== null) return _embedVideoSrc; } return null; }, [editorState]); function handleChange(editorState) { props.onEditorChange(editorState); } function handleSearchChange(_ref) { var value = _ref.value; setSuggestions(createMentionPlugin.defaultSuggestionsFilter(value, props.mentions)); } function handleAddMention() {} function handleKeyCommand(command, editorState) { if (command === "jameditor-enter") { setReadOnly(false); props.onMessageSend(); return "handled"; } var newState = draftJs.RichUtils.handleKeyCommand(editorState, command); if (newState) { handleChange(newState); return "handled"; } return "not-handled"; } var MentionSuggestions = mentionPlugin.MentionSuggestions; var plugins = [mentionPlugin, linkifyPlugin, staticToolbarPlugin]; return React__default.createElement("div", { className: "jam--editor-draftjs-wrapper lds-grid" }, React__default.createElement(Editor, { editorState: props.editorState, handleKeyCommand: handleKeyCommand, onChange: handleChange, plugins: plugins, ref: function ref(_ref2) { editorRef.current = _ref2; }, placeholder: "Type a comment...", keyBindingFn: processKeyBinding, readOnly: readOnly }), React__default.createElement(MentionSuggestions, { onSearchChange: handleSearchChange, suggestions: suggestions, onAddMention: handleAddMention, entryComponent: Entry }), embedVideoSrc !== null && React__default.createElement("div", { className: "jam--embed-video-container" }, React__default.createElement("iframe", { width: "100%", height: "100%", src: embedVideoSrc, frameBorder: "0", allowFullScreen: true }), React__default.createElement("style", null, "\n\t\t\t\t\t\t.jam--embed-video-container {\n\t\t\t\t\t\t\tpadding: 15px;\n\t\t\t\t\t\t}\n\t\t\t\t\t")), React__default.createElement("style", null, "\n\t\t\t\t\t.jam--suggest-css {\n\t\t\t\t\t\tbox-sizing: border-box;\n\t\t\t\t\t\tborder-radius: 5px;\n\t\t\t\t\t\tdisplay: flex;\n\t\t\t\t\t\talign-items: center;\n\t\t\t\t\t\tjustify-content: center;\n\t\t\t\t\t\theight: 30px;\n\t\t\t\t\t\tmargin-left: 12px;\n\t\t\t\t\t\tfont-family: \"SFMono-Regular\", Consolas, \"Liberation Mono\", Menlo,\n\t\t\t\t\t\t\tCourier, monospace;\n\t\t\t\t\t\tfont-size: 10px;\n\t\t\t\t\t\tmargin-bottom: 20px;\n\t\t\t\t\t\tfont-weight: 600;\n\t\t\t\t\t\tcolor: #47b38f;\n\t\t\t\t\t\tbackground: rgba(115, 229, 191, 0.15);\n\t\t\t\t\t\tborder: none;\n\t\t\t\t\t}\n\t\t\t\t\t.jam--editor-draftjs-wrapper {\n\t\t\t\t\t\twidth: 100%;\n\t\t\t\t\t\tpadding: 0.5rem 0;\n\t\t\t\t\t}\n\t\t\t\t\t.DraftEditor-root {\n\t\t\t\t\t\twidth: 100%;\n\t\t\t\t\t\tbox-sizing: border-box;\n\t\t\t\t\t\tpadding: 0px 1rem 1rem;\n\t\t\t\t\t\tpadding-top: 0px;\n\t\t\t\t\t\tpadding-right: 1rem;\n\t\t\t\t\t\tpadding-bottom: 1rem;\n\t\t\t\t\t\tpadding-left: 1rem;\n\t\t\t\t\t\tfont-size: 14px;\n\t\t\t\t\t\tline-height: 20px;\n\t\t\t\t\t\tfont-weight: 400;\n\t\t\t\t\t\tcolor: #2a3632;\n\t\t\t\t\t}\n\n\t\t\t\t\t.DraftEditor-root a {\n\t\t\t\t\t\ttext-decoration: none;\n\t\t\t\t\t\tcolor: #3875fd;\n\t\t\t\t\t}\n\n\t\t\t\t\t.DraftEditor-editorContainer {\n\t\t\t\t\t\tbackground-color: rgba(255, 255, 255, 0);\n\t\t\t\t\t\tborder-left: 0.1px solid transparent;\n\t\t\t\t\t\tposition: relative;\n\t\t\t\t\t\ttext-align: left;\n\t\t\t\t\t\tz-index: 1;\n\t\t\t\t\t}\n\n\t\t\t\t\t.draftJsToolbar__buttonWrapper__1Dmqh {\n\t\t\t\t\t\tdisplay: inline-block;\n\t\t\t\t\t}\n\n\t\t\t\t\t.draftJsToolbar__button__qi1gf {\n\t\t\t\t\t\tbackground: #fbfbfb;\n\t\t\t\t\t\tcolor: #888;\n\t\t\t\t\t\tfont-size: 18px;\n\t\t\t\t\t\tborder: 0;\n\t\t\t\t\t\tpadding-top: 5px;\n\t\t\t\t\t\tvertical-align: bottom;\n\t\t\t\t\t\theight: 34px;\n\t\t\t\t\t\twidth: 36px;\n\t\t\t\t\t}\n\n\t\t\t\t\t.draftJsToolbar__button__qi1gf svg {\n\t\t\t\t\t\tfill: #888;\n\t\t\t\t\t}\n\n\t\t\t\t\t.draftJsToolbar__button__qi1gf:hover,\n\t\t\t\t\t.draftJsToolbar__button__qi1gf:focus {\n\t\t\t\t\t\tbackground: #f3f3f3;\n\t\t\t\t\t\toutline: 0; /* reset for :focus */\n\t\t\t\t\t}\n\n\t\t\t\t\t.draftJsToolbar__active__3qcpF {\n\t\t\t\t\t\tbackground: #efefef;\n\t\t\t\t\t\tcolor: #444;\n\t\t\t\t\t}\n\n\t\t\t\t\t.draftJsToolbar__active__3qcpF svg {\n\t\t\t\t\t\tfill: #444;\n\t\t\t\t\t}\n\t\t\t\t\t.draftJsToolbar__separator__3U7qt {\n\t\t\t\t\t\tdisplay: inline-block;\n\t\t\t\t\t\tborder-right: 1px solid #ddd;\n\t\t\t\t\t\theight: 24px;\n\t\t\t\t\t\tmargin: 0 0.5em;\n\t\t\t\t\t}\n\t\t\t\t\t.draftJsToolbar__toolbar__dNtBH {\n\t\t\t\t\t\tborder: none;\n\t\t\t\t\t\tpadding: 0.25rem;\n\t\t\t\t\t\tbackground: #fff;\n\t\t\t\t\t\tborder-radius: 2px;\n\t\t\t\t\t\tbox-shadow: none;\n\t\t\t\t\t\tz-index: 2;\n\t\t\t\t\t\tbox-sizing: border-box;\n\t\t\t\t\t}\n\n\t\t\t\t\t.draftJsToolbar__toolbar__dNtBH:after {\n\t\t\t\t\t\tborder-color: rgba(255, 255, 255, 0);\n\t\t\t\t\t\tborder-top-color: #fff;\n\t\t\t\t\t\tborder-width: 4px;\n\t\t\t\t\t\tmargin-left: -4px;\n\t\t\t\t\t}\n\t\t\t\t\t.draftJsToolbar__toolbar__dNtBH:before {\n\t\t\t\t\t\tborder-color: rgba(221, 221, 221, 0);\n\t\t\t\t\t\tborder-top-color: #ddd;\n\t\t\t\t\t\tborder-width: 6px;\n\t\t\t\t\t\tmargin-left: -6px;\n\t\t\t\t\t}\n\t\t\t\t\t.DraftEditor-alignLeft .publi