mirror of
https://github.com/discourse/discourse.git
synced 2024-11-25 09:42:07 +08:00
FIX: uses tippy for popover (#15409)
Note this commit also introduce a new {{d-popover}} component, example usage: ```hbs {{#d-popover |state|}} {{d-button label="foo.things" class="d-popover-trigger"}} <div class="d-popover-content"> Some content <div> {{/d-popover}} ```
This commit is contained in:
parent
4885a2535a
commit
fad94160c7
|
@ -25,6 +25,10 @@ define("@popperjs/core", ["exports"], function (__exports__) {
|
|||
__exports__.popperGenerator = window.Popper.popperGenerator;
|
||||
});
|
||||
|
||||
define("tippy.js", ["exports"], function (__exports__) {
|
||||
__exports__.default = window.tippy;
|
||||
});
|
||||
|
||||
define("@uppy/core", ["exports"], function (__exports__) {
|
||||
__exports__.default = window.Uppy.Core;
|
||||
__exports__.BasePlugin = window.Uppy.Core.BasePlugin;
|
||||
|
|
61
app/assets/javascripts/discourse/app/components/d-popover.js
Normal file
61
app/assets/javascripts/discourse/app/components/d-popover.js
Normal file
|
@ -0,0 +1,61 @@
|
|||
import Component from "@ember/component";
|
||||
import { iconHTML } from "discourse-common/lib/icon-library";
|
||||
import tippy from "tippy.js";
|
||||
import { guidFor } from "@ember/object/internals";
|
||||
|
||||
export default class DiscoursePopover extends Component {
|
||||
tagName = "";
|
||||
|
||||
isExpanded = false;
|
||||
|
||||
options = null;
|
||||
|
||||
didInsertElement() {
|
||||
this._super(...arguments);
|
||||
|
||||
this._setupTippy();
|
||||
}
|
||||
|
||||
get componentId() {
|
||||
return guidFor(this);
|
||||
}
|
||||
|
||||
_setupTippy() {
|
||||
const baseOptions = {
|
||||
trigger: "click",
|
||||
zIndex: 1400,
|
||||
arrow: iconHTML("tippy-rounded-arrow"),
|
||||
interactive: true,
|
||||
allowHTML: false,
|
||||
appendTo: "parent",
|
||||
content:
|
||||
this.options?.content ||
|
||||
document
|
||||
.getElementById(this.componentId)
|
||||
.querySelector(
|
||||
":scope > .d-popover-content, :scope > div, :scope > ul"
|
||||
),
|
||||
onShow: () => {
|
||||
if (this.isDestroyed || this.isDestroying) {
|
||||
return;
|
||||
}
|
||||
this.set("isExpanded", true);
|
||||
},
|
||||
onHide: () => {
|
||||
if (this.isDestroyed || this.isDestroying) {
|
||||
return;
|
||||
}
|
||||
this.set("isExpanded", false);
|
||||
},
|
||||
};
|
||||
|
||||
tippy(
|
||||
document
|
||||
.getElementById(this.componentId)
|
||||
.querySelector(
|
||||
':scope > .d-popover-trigger, :scope > .btn, :scope > [role="button"]'
|
||||
),
|
||||
Object.assign({}, baseOptions, this.options || {})
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,20 +1,19 @@
|
|||
import {
|
||||
POPOVER_SELECTORS,
|
||||
hidePopover,
|
||||
showPopover,
|
||||
} from "discourse/lib/d-popover";
|
||||
import { showPopover } from "discourse/lib/d-popover";
|
||||
|
||||
export default {
|
||||
name: "d-popover",
|
||||
|
||||
initialize(container) {
|
||||
const router = container.lookup("router:main");
|
||||
router.on("routeWillChange", hidePopover);
|
||||
|
||||
$("#main")
|
||||
.on("click.d-popover mouseenter.d-popover", POPOVER_SELECTORS, (e) =>
|
||||
showPopover(e)
|
||||
)
|
||||
.on("mouseleave.d-popover", POPOVER_SELECTORS, (e) => hidePopover(e));
|
||||
initialize() {
|
||||
["click", "mouseover"].forEach((eventType) => {
|
||||
document.addEventListener(eventType, (e) => {
|
||||
if (e.target.dataset.tooltip || e.target.dataset.popover) {
|
||||
showPopover(e, {
|
||||
interactive: false,
|
||||
content: (reference) =>
|
||||
reference.dataset.tooltip || reference.dataset.popover,
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,168 +1,48 @@
|
|||
import { siteDir } from "discourse/lib/text-direction";
|
||||
import { isLegacyEmber } from "discourse-common/config/environment";
|
||||
import { run } from "@ember/runloop";
|
||||
import tippy from "tippy.js";
|
||||
import { iconHTML } from "discourse-common/lib/icon-library";
|
||||
|
||||
const D_POPOVER_ID = "d-popover";
|
||||
|
||||
const D_POPOVER_TEMPLATE = `
|
||||
<div id="${D_POPOVER_ID}" class="is-under">
|
||||
<div class="d-popover-arrow d-popover-top-arrow"></div>
|
||||
<div class="d-popover-content">
|
||||
<div class="spinner small"></div>
|
||||
</div>
|
||||
<div class="d-popover-arrow d-popover-bottom-arrow"></div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
const D_ARROW_HEIGHT = 10;
|
||||
|
||||
const D_HORIZONTAL_MARGIN = 5;
|
||||
|
||||
export const POPOVER_SELECTORS = "[data-popover], [data-tooltip]";
|
||||
|
||||
export function hidePopover() {
|
||||
getPopover().fadeOut().remove();
|
||||
|
||||
return getPopover();
|
||||
export function hidePopover(event) {
|
||||
if (event?.target?._tippy) {
|
||||
showPopover(event);
|
||||
}
|
||||
}
|
||||
|
||||
// options accepts all tippy.js options as defined in their documentation
|
||||
// https://atomiks.github.io/tippyjs/v6/all-props/
|
||||
export function showPopover(event, options = {}) {
|
||||
let $enteredElement = $(event.target).closest(POPOVER_SELECTORS).first();
|
||||
const tippyOptions = Object.assign(
|
||||
{
|
||||
arrow: iconHTML("tippy-rounded-arrow"),
|
||||
content: options.textContent || options.htmlContent,
|
||||
allowHTML: options?.htmlContent?.length,
|
||||
trigger: "mouseenter click",
|
||||
hideOnClick: true,
|
||||
zIndex: 1400,
|
||||
},
|
||||
options
|
||||
);
|
||||
|
||||
if (!$enteredElement.length) {
|
||||
$enteredElement = $(event.target);
|
||||
// legacy support
|
||||
delete tippyOptions.textContent;
|
||||
delete tippyOptions.htmlContent;
|
||||
|
||||
const instance = event.target._tippy
|
||||
? event.target._tippy
|
||||
: tippy(event.target, tippyOptions);
|
||||
|
||||
// hangs on legacy ember
|
||||
if (!isLegacyEmber) {
|
||||
run.begin();
|
||||
instance.popper.addEventListener("transitionend", run.end, {
|
||||
once: true,
|
||||
});
|
||||
}
|
||||
|
||||
if (isRetina()) {
|
||||
getPopover().addClass("retina");
|
||||
}
|
||||
|
||||
if (!getPopover().length) {
|
||||
$("body").append($(D_POPOVER_TEMPLATE));
|
||||
}
|
||||
|
||||
setPopoverHtmlContent($enteredElement, options.htmlContent);
|
||||
setPopoverTextContent($enteredElement, options.textContent);
|
||||
|
||||
getPopover().fadeIn();
|
||||
|
||||
positionPopover($enteredElement);
|
||||
|
||||
return {
|
||||
html: (content) => replaceHtmlContent($enteredElement, content),
|
||||
text: (content) => replaceTextContent($enteredElement, content),
|
||||
hide: hidePopover,
|
||||
};
|
||||
}
|
||||
|
||||
function setPopoverHtmlContent($enteredElement, content) {
|
||||
replaceHtmlContent($enteredElement, content);
|
||||
}
|
||||
|
||||
function setPopoverTextContent($enteredElement, content) {
|
||||
content =
|
||||
content ||
|
||||
$enteredElement.attr("data-popover") ||
|
||||
$enteredElement.attr("data-tooltip");
|
||||
|
||||
replaceTextContent($enteredElement, content);
|
||||
}
|
||||
|
||||
function replaceTextContent($enteredElement, content) {
|
||||
if (content) {
|
||||
getPopover().find(".d-popover-content").text(content);
|
||||
window.requestAnimationFrame(() => positionPopover($enteredElement));
|
||||
}
|
||||
}
|
||||
|
||||
function replaceHtmlContent($enteredElement, content) {
|
||||
if (content) {
|
||||
getPopover().find(".d-popover-content").html(content);
|
||||
window.requestAnimationFrame(() => positionPopover($enteredElement));
|
||||
}
|
||||
}
|
||||
|
||||
function positionPopover($element) {
|
||||
const $popover = getPopover();
|
||||
$popover.removeClass("is-above is-under is-left-aligned is-right-aligned");
|
||||
|
||||
const $dHeader = $(".d-header");
|
||||
const windowRect = {
|
||||
left: 0,
|
||||
top: $dHeader.length ? $dHeader[0].getBoundingClientRect().bottom : 0,
|
||||
width: $(window).width(),
|
||||
height: $(window).height(),
|
||||
};
|
||||
|
||||
const popoverRect = {
|
||||
width: $popover.width(),
|
||||
height: $popover.height(),
|
||||
left: null,
|
||||
right: null,
|
||||
};
|
||||
|
||||
if (popoverRect.width > windowRect.width - D_HORIZONTAL_MARGIN * 2) {
|
||||
popoverRect.width = windowRect.width - D_HORIZONTAL_MARGIN * 2;
|
||||
$popover.width(popoverRect.width);
|
||||
}
|
||||
|
||||
const targetRect = $element[0].getBoundingClientRect();
|
||||
const underSpace = windowRect.height - targetRect.bottom - D_ARROW_HEIGHT;
|
||||
const topSpace = targetRect.top - windowRect.top - D_ARROW_HEIGHT;
|
||||
|
||||
if (
|
||||
underSpace > popoverRect.height + D_HORIZONTAL_MARGIN ||
|
||||
underSpace > topSpace
|
||||
) {
|
||||
$popover
|
||||
.css("top", targetRect.bottom + window.pageYOffset + D_ARROW_HEIGHT)
|
||||
.addClass("is-under");
|
||||
if (instance.state.isShown) {
|
||||
instance.hide();
|
||||
} else {
|
||||
$popover
|
||||
.css(
|
||||
"top",
|
||||
targetRect.top +
|
||||
window.pageYOffset -
|
||||
popoverRect.height -
|
||||
D_ARROW_HEIGHT
|
||||
)
|
||||
.addClass("is-above");
|
||||
instance.show();
|
||||
}
|
||||
|
||||
const leftSpace = targetRect.left + targetRect.width / 2;
|
||||
|
||||
if (siteDir() === "ltr") {
|
||||
if (leftSpace > popoverRect.width / 2 + D_HORIZONTAL_MARGIN) {
|
||||
popoverRect.left = leftSpace - popoverRect.width / 2;
|
||||
$popover.css("left", popoverRect.left);
|
||||
} else {
|
||||
popoverRect.left = D_HORIZONTAL_MARGIN;
|
||||
$popover.css("left", popoverRect.left).addClass("is-left-aligned");
|
||||
}
|
||||
} else {
|
||||
const rightSpace = windowRect.width - targetRect.right;
|
||||
|
||||
if (rightSpace > popoverRect.width / 2 + D_HORIZONTAL_MARGIN) {
|
||||
popoverRect.left = leftSpace - popoverRect.width / 2;
|
||||
$popover.css("left", popoverRect.left);
|
||||
} else {
|
||||
popoverRect.left =
|
||||
windowRect.width - popoverRect.width - D_HORIZONTAL_MARGIN * 2;
|
||||
$popover.css("left", popoverRect.left).addClass("is-right-aligned");
|
||||
}
|
||||
}
|
||||
|
||||
let arrowPosition;
|
||||
if (siteDir() === "ltr") {
|
||||
arrowPosition = Math.abs(targetRect.left - popoverRect.left);
|
||||
} else {
|
||||
arrowPosition = targetRect.left - popoverRect.left + targetRect.width / 2;
|
||||
}
|
||||
$popover.find(".d-popover-arrow").css("left", arrowPosition);
|
||||
}
|
||||
|
||||
function isRetina() {
|
||||
return window.devicePixelRatio && window.devicePixelRatio > 1;
|
||||
}
|
||||
|
||||
function getPopover() {
|
||||
return $(document.getElementById(D_POPOVER_ID));
|
||||
}
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
<div id={{componentId}} class="d-popover {{if isExpanded "is-expanded"}}">
|
||||
{{yield (hash isExpanded=isExpanded)}}
|
||||
</div>
|
|
@ -23,6 +23,7 @@
|
|||
"@ember/test-helpers": "^2.2.0",
|
||||
"@glimmer/component": "^1.0.4",
|
||||
"@glimmer/tracking": "^1.0.4",
|
||||
"tippy.js": "^6.3.7",
|
||||
"@popperjs/core": "2.10.2",
|
||||
"@uppy/aws-s3": "^2.0.8",
|
||||
"@uppy/aws-s3-multipart": "^2.2.1",
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
import componentTest, {
|
||||
setupRenderingTest,
|
||||
} from "discourse/tests/helpers/component-test";
|
||||
import {
|
||||
discourseModule,
|
||||
exists,
|
||||
query,
|
||||
} from "discourse/tests/helpers/qunit-helpers";
|
||||
import hbs from "htmlbars-inline-precompile";
|
||||
import { showPopover } from "discourse/lib/d-popover";
|
||||
import { click } from "@ember/test-helpers";
|
||||
|
||||
discourseModule("Integration | Component | d-popover", function (hooks) {
|
||||
setupRenderingTest(hooks);
|
||||
|
||||
componentTest("show/hide popover from lib", {
|
||||
template: hbs`{{d-button translatedLabel="test" action=onButtonClick forwardEvent=true}}`,
|
||||
|
||||
beforeEach() {
|
||||
this.set("onButtonClick", (_, event) => {
|
||||
showPopover(event, { content: "test", trigger: "click", duration: 0 });
|
||||
});
|
||||
},
|
||||
|
||||
async test(assert) {
|
||||
assert.notOk(document.querySelector("div[data-tippy-root]"));
|
||||
|
||||
await click(".btn");
|
||||
|
||||
assert.equal(
|
||||
document.querySelector("div[data-tippy-root]").innerText.trim(),
|
||||
"test"
|
||||
);
|
||||
|
||||
await click(".btn");
|
||||
|
||||
assert.notOk(document.querySelector("div[data-tippy-root]"));
|
||||
},
|
||||
});
|
||||
|
||||
componentTest("show/hide popover from component", {
|
||||
template: hbs`{{#d-popover}}{{d-button icon="chevron-down"}}<ul><li class="test">foo</li></ul>{{/d-popover}}`,
|
||||
|
||||
async test(assert) {
|
||||
assert.notOk(exists(".d-popover.is-expanded"));
|
||||
assert.notOk(exists(".test"));
|
||||
|
||||
await click(".btn");
|
||||
|
||||
assert.ok(exists(".d-popover.is-expanded"));
|
||||
assert.equal(query(".test").innerText.trim(), "foo");
|
||||
},
|
||||
});
|
||||
|
||||
componentTest("using options with component", {
|
||||
template: hbs`{{#d-popover options=(hash content="bar")}}{{d-button icon="chevron-down"}}{{/d-popover}}`,
|
||||
|
||||
async test(assert) {
|
||||
await click(".btn");
|
||||
|
||||
assert.equal(query(".tippy-content").innerText.trim(), "bar");
|
||||
},
|
||||
});
|
||||
|
||||
componentTest("d-popover component accepts a block", {
|
||||
template: hbs`{{#d-popover as |state|}}{{d-button icon=(if state.isExpanded "chevron-up" "chevron-down")}}{{/d-popover}}`,
|
||||
|
||||
async test(assert) {
|
||||
assert.ok(exists(".d-icon-chevron-down"));
|
||||
|
||||
await click(".btn");
|
||||
|
||||
assert.ok(exists(".d-icon-chevron-up"));
|
||||
},
|
||||
});
|
||||
});
|
|
@ -6,6 +6,7 @@
|
|||
//= require Markdown.Converter.js
|
||||
//= require bootbox.js
|
||||
//= require popper.js
|
||||
//= require tippy.umd.js
|
||||
//= require bootstrap-modal.js
|
||||
//= require caret_position
|
||||
//= require itsatrap.js
|
||||
|
|
|
@ -5,6 +5,10 @@ define("@popperjs/core", ["exports"], function (__exports__) {
|
|||
__exports__.popperGenerator = window.Popper.popperGenerator;
|
||||
});
|
||||
|
||||
define("tippy.js", ["exports"], function (__exports__) {
|
||||
__exports__.default = window.tippy;
|
||||
});
|
||||
|
||||
define("@uppy/core", ["exports"], function (__exports__) {
|
||||
__exports__.default = window.Uppy.Core;
|
||||
__exports__.BasePlugin = window.Uppy.Core.BasePlugin;
|
||||
|
|
|
@ -6,4 +6,5 @@
|
|||
//= require virtual-dom
|
||||
//= require virtual-dom-amd
|
||||
//= require popper.js
|
||||
//= require tippy.umd.js
|
||||
//= require wizard-shims
|
||||
|
|
|
@ -2120,6 +2120,11 @@
|
|||
resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.10.2.tgz#0798c03351f0dea1a5a4cabddf26a55a7cbee590"
|
||||
integrity sha512-IXf3XA7+XyN7CP9gGh/XB0UxVMlvARGEgGXLubFICsUMGz6Q+DU+i4gGlpOxTjKvXjkJDJC8YdqdKkDj9qZHEQ==
|
||||
|
||||
"@popperjs/core@^2.9.0":
|
||||
version "2.11.0"
|
||||
resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.11.0.tgz#6734f8ebc106a0860dff7f92bf90df193f0935d7"
|
||||
integrity sha512-zrsUxjLOKAzdewIDRWy9nsV1GQsKBCWaGwsZQlCgr6/q+vjyZhFgqedLfFBuI9anTPEUT4APq9Mu0SZBTzIcGQ==
|
||||
|
||||
"@simple-dom/interface@^1.4.0":
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/@simple-dom/interface/-/interface-1.4.0.tgz#e8feea579232017f89b0138e2726facda6fbb71f"
|
||||
|
@ -12905,6 +12910,13 @@ tiny-lr@^2.0.0:
|
|||
object-assign "^4.1.0"
|
||||
qs "^6.4.0"
|
||||
|
||||
tippy.js@^6.3.7:
|
||||
version "6.3.7"
|
||||
resolved "https://registry.yarnpkg.com/tippy.js/-/tippy.js-6.3.7.tgz#8ccfb651d642010ed9a32ff29b0e9e19c5b8c61c"
|
||||
integrity sha512-E1d3oP2emgJ9dRQZdf3Kkn0qJgI6ZLpyS5z6ZkY1DF3kaQaBsGZsndEpHwx+eC+tYM41HaSNvNtLx8tU57FzTQ==
|
||||
dependencies:
|
||||
"@popperjs/core" "^2.9.0"
|
||||
|
||||
tmp@0.0.28:
|
||||
version "0.0.28"
|
||||
resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.28.tgz#172735b7f614ea7af39664fa84cf0de4e515d120"
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
@import "vendor/normalize";
|
||||
@import "vendor/normalize-ext";
|
||||
@import "vendor/pikaday";
|
||||
@import "vendor/tippy";
|
||||
@import "vendor/svg-arrow";
|
||||
@import "common/foundation/helpers";
|
||||
@import "common/foundation/base";
|
||||
@import "common/select-kit/_index";
|
||||
|
|
|
@ -1,112 +1,30 @@
|
|||
$d-popover-background: var(--secondary);
|
||||
$d-popover-border: var(--primary-medium);
|
||||
|
||||
@-webkit-keyframes popoverFadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
.tippy-box {
|
||||
color: var(--primary);
|
||||
background: $d-popover-background;
|
||||
box-shadow: shadow("card");
|
||||
border: 1px solid $d-popover-border;
|
||||
}
|
||||
|
||||
.tippy-box[data-placement^="top"] .tippy-svg-arrow > svg {
|
||||
top: 12px;
|
||||
}
|
||||
.tippy-box[data-placement^="bottom"] .tippy-svg-arrow > svg {
|
||||
top: -10px;
|
||||
}
|
||||
.tippy-rounded-arrow {
|
||||
fill: $d-popover-background;
|
||||
.svg-arrow {
|
||||
fill: $d-popover-border;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
.svg-content {
|
||||
fill: $d-popover-background;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes popoverFadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
#d-popover {
|
||||
background-color: $d-popover-background;
|
||||
position: absolute;
|
||||
z-index: z("modal", "tooltip");
|
||||
border-color: $d-popover-border;
|
||||
border-style: solid;
|
||||
border-width: 1px;
|
||||
max-width: 300px;
|
||||
-webkit-animation: popoverFadeIn 0.5s;
|
||||
animation: popoverFadeIn 0.5s;
|
||||
background-clip: padding-box;
|
||||
display: block;
|
||||
box-shadow: shadow("dropdown");
|
||||
border-radius: 2px;
|
||||
|
||||
&.is-under {
|
||||
margin-top: 0px;
|
||||
|
||||
.d-popover-top-arrow {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.d-popover-bottom-arrow {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
&.is-above {
|
||||
margin-top: 0px;
|
||||
|
||||
.d-popover-bottom-arrow {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.d-popover-top-arrow {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
&.retina {
|
||||
border-width: 0.5px;
|
||||
}
|
||||
|
||||
.d-popover-content {
|
||||
padding: 0.5em;
|
||||
font-size: $font-down-1;
|
||||
overflow-wrap: break-word;
|
||||
-webkit-animation: popoverFadeIn 0.5s;
|
||||
animation: popoverFadeIn 0.5s;
|
||||
}
|
||||
|
||||
.d-popover-arrow {
|
||||
border-style: solid;
|
||||
color: transparent;
|
||||
content: "";
|
||||
position: absolute;
|
||||
z-index: z("tooltip") - 100;
|
||||
}
|
||||
|
||||
.d-popover-top-arrow {
|
||||
border-color: transparent transparent $d-popover-border;
|
||||
top: -8px;
|
||||
border-width: 0 8px 8px;
|
||||
|
||||
&:after {
|
||||
border-color: transparent transparent $d-popover-background;
|
||||
border-style: solid;
|
||||
border-width: 0 7px 7px;
|
||||
bottom: -8.5px;
|
||||
margin-left: -7px;
|
||||
position: absolute;
|
||||
content: "";
|
||||
}
|
||||
}
|
||||
|
||||
.d-popover-bottom-arrow {
|
||||
border-color: $d-popover-border transparent transparent;
|
||||
top: 100%;
|
||||
border-width: 8px 8px 0;
|
||||
|
||||
&:after {
|
||||
position: absolute;
|
||||
content: "";
|
||||
border-color: $d-popover-background transparent transparent;
|
||||
border-style: solid;
|
||||
border-width: 7px 7px 0;
|
||||
bottom: 1.5px;
|
||||
transform: translate(-7px, 0);
|
||||
}
|
||||
}
|
||||
[data-tooltip] > *,
|
||||
[data-popover] > * {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
margin-top: 2em;
|
||||
}
|
||||
|
||||
#d-popover .download-calendar {
|
||||
div[data-tippy-root] .download-calendar {
|
||||
color: var(--primary-med-or-secondary-med);
|
||||
}
|
||||
|
||||
|
|
1
app/assets/stylesheets/vendor/svg-arrow.css
vendored
Normal file
1
app/assets/stylesheets/vendor/svg-arrow.css
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
.tippy-box[data-placement^=top]>.tippy-svg-arrow{bottom:0}.tippy-box[data-placement^=top]>.tippy-svg-arrow:after,.tippy-box[data-placement^=top]>.tippy-svg-arrow>svg{top:16px;transform:rotate(180deg)}.tippy-box[data-placement^=bottom]>.tippy-svg-arrow{top:0}.tippy-box[data-placement^=bottom]>.tippy-svg-arrow>svg{bottom:16px}.tippy-box[data-placement^=left]>.tippy-svg-arrow{right:0}.tippy-box[data-placement^=left]>.tippy-svg-arrow:after,.tippy-box[data-placement^=left]>.tippy-svg-arrow>svg{transform:rotate(90deg);top:calc(50% - 3px);left:11px}.tippy-box[data-placement^=right]>.tippy-svg-arrow{left:0}.tippy-box[data-placement^=right]>.tippy-svg-arrow:after,.tippy-box[data-placement^=right]>.tippy-svg-arrow>svg{transform:rotate(-90deg);top:calc(50% - 3px);right:11px}.tippy-svg-arrow{width:16px;height:16px;fill:#333;text-align:initial}.tippy-svg-arrow,.tippy-svg-arrow>svg{position:absolute}
|
1
app/assets/stylesheets/vendor/tippy.css
vendored
Normal file
1
app/assets/stylesheets/vendor/tippy.css
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
.tippy-box[data-animation=fade][data-state=hidden]{opacity:0}[data-tippy-root]{max-width:calc(100vw - 10px)}.tippy-box{position:relative;background-color:#333;color:#fff;border-radius:4px;font-size:14px;line-height:1.4;white-space:normal;outline:0;transition-property:transform,visibility,opacity}.tippy-box[data-placement^=top]>.tippy-arrow{bottom:0}.tippy-box[data-placement^=top]>.tippy-arrow:before{bottom:-7px;left:0;border-width:8px 8px 0;border-top-color:initial;transform-origin:center top}.tippy-box[data-placement^=bottom]>.tippy-arrow{top:0}.tippy-box[data-placement^=bottom]>.tippy-arrow:before{top:-7px;left:0;border-width:0 8px 8px;border-bottom-color:initial;transform-origin:center bottom}.tippy-box[data-placement^=left]>.tippy-arrow{right:0}.tippy-box[data-placement^=left]>.tippy-arrow:before{border-width:8px 0 8px 8px;border-left-color:initial;right:-7px;transform-origin:center left}.tippy-box[data-placement^=right]>.tippy-arrow{left:0}.tippy-box[data-placement^=right]>.tippy-arrow:before{left:-7px;border-width:8px 8px 8px 0;border-right-color:initial;transform-origin:center right}.tippy-box[data-inertia][data-state=visible]{transition-timing-function:cubic-bezier(.54,1.5,.38,1.11)}.tippy-arrow{width:16px;height:16px;color:#333}.tippy-arrow:before{content:"";position:absolute;border-color:transparent;border-style:solid}.tippy-content{position:relative;padding:5px 9px;z-index:1}
|
|
@ -213,7 +213,8 @@ module SvgSprite
|
|||
"user-times",
|
||||
"users",
|
||||
"wrench",
|
||||
"spinner"
|
||||
"spinner",
|
||||
"tippy-rounded-arrow"
|
||||
])
|
||||
|
||||
FA_ICON_MAP = { 'far fa-' => 'far-', 'fab fa-' => 'fab-', 'fas fa-' => '', 'fa-' => '' }
|
||||
|
|
|
@ -148,8 +148,18 @@ def dependencies
|
|||
}, {
|
||||
source: '@popperjs/core/dist/umd/popper.js.map',
|
||||
public_root: true
|
||||
},
|
||||
{
|
||||
}, {
|
||||
source: 'tippy.js/dist/tippy.umd.js'
|
||||
}, {
|
||||
source: 'tippy.js/dist/tippy.umd.js.map',
|
||||
public_root: true
|
||||
}, {
|
||||
source: 'tippy.js/dist/tippy.css',
|
||||
destination: '../../../app/assets/stylesheets/vendor'
|
||||
}, {
|
||||
source: 'tippy.js/dist/svg-arrow.css',
|
||||
destination: '../../../app/assets/stylesheets/vendor'
|
||||
}, {
|
||||
source: 'route-recognizer/dist/route-recognizer.js'
|
||||
}, {
|
||||
source: 'route-recognizer/dist/route-recognizer.js.map',
|
||||
|
@ -206,6 +216,14 @@ def public_path_name(f)
|
|||
f[:destination] || node_package_name(f)
|
||||
end
|
||||
|
||||
def absolute_sourcemap(dest)
|
||||
File.open(dest) do |file|
|
||||
contents = file.read
|
||||
contents.gsub!(/sourceMappingURL=(.*)/, 'sourceMappingURL=/\1')
|
||||
File.open(dest, "w+") { |d| d.write(contents) }
|
||||
end
|
||||
end
|
||||
|
||||
task 'javascript:update_constants' => :environment do
|
||||
task_name = 'update_constants'
|
||||
|
||||
|
@ -330,14 +348,12 @@ task 'javascript:update' => 'clean_up' do
|
|||
FileUtils.cp_r(src, dest)
|
||||
end
|
||||
|
||||
# use absolute path for popper.js's sourcemap
|
||||
# avoids noisy console warnings in dev environment for non-homepage paths
|
||||
if dest.end_with? "popper.js"
|
||||
File.open(dest) do |file|
|
||||
contents = file.read
|
||||
contents.gsub!("sourceMappingURL=popper", "sourceMappingURL=/popper")
|
||||
File.open(dest, "w+") { |d| d.write(contents) }
|
||||
absolute_sourcemap(dest)
|
||||
end
|
||||
if dest.end_with? "tippy.umd.js"
|
||||
absolute_sourcemap(dest)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
"@discourse/moment-timezone-names-translations": "^1.0.0",
|
||||
"@highlightjs/cdn-assets": "^10.7.0",
|
||||
"@json-editor/json-editor": "^2.6.1",
|
||||
"tippy.js": "^6.3.7",
|
||||
"@popperjs/core": "v2.10.2",
|
||||
"@uppy/aws-s3": "^2.0.8",
|
||||
"@uppy/aws-s3-multipart": "^2.2.1",
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
import deprecated from "discourse-common/lib/deprecated";
|
||||
import { getOwner } from "discourse-common/lib/get-owner";
|
||||
import { hidePopover, showPopover } from "discourse/lib/d-popover";
|
||||
import LocalDateBuilder from "../lib/local-date-builder";
|
||||
import { withPluginApi } from "discourse/lib/plugin-api";
|
||||
import showModal from "discourse/lib/show-modal";
|
||||
import { downloadCalendar } from "discourse/lib/download-calendar";
|
||||
import { renderIcon } from "discourse-common/lib/icon-library";
|
||||
import I18n from "I18n";
|
||||
import { hidePopover, showPopover } from "discourse/lib/d-popover";
|
||||
|
||||
// Import applyLocalDates from discourse/lib/local-dates instead
|
||||
export function applyLocalDates(dates, siteSettings) {
|
||||
|
@ -238,39 +238,37 @@ export default {
|
|||
return;
|
||||
}
|
||||
|
||||
const siteSettings = owner.lookup("site-settings:main");
|
||||
if (event?.target?.classList?.contains("discourse-local-date")) {
|
||||
if ($(document.getElementById("d-popover"))[0]) {
|
||||
hidePopover(event);
|
||||
} else {
|
||||
showPopover(event, {
|
||||
htmlContent: buildHtmlPreview(event.target, siteSettings),
|
||||
});
|
||||
}
|
||||
} else if (event?.target?.classList?.contains("download-calendar")) {
|
||||
if (event?.target?.classList?.contains("download-calendar")) {
|
||||
const dataset = event.target.dataset;
|
||||
hidePopover(event);
|
||||
downloadCalendar(dataset.title, [
|
||||
{
|
||||
startsAt: dataset.startsAt,
|
||||
endsAt: dataset.endsAt,
|
||||
},
|
||||
]);
|
||||
} else {
|
||||
hidePopover(event);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!event?.target?.classList?.contains("discourse-local-date")) {
|
||||
return;
|
||||
}
|
||||
|
||||
const siteSettings = owner.lookup("site-settings:main");
|
||||
|
||||
showPopover(event, {
|
||||
trigger: "click",
|
||||
content: buildHtmlPreview(event.target, siteSettings),
|
||||
allowHTML: true,
|
||||
interactive: true,
|
||||
appendTo: "parent",
|
||||
});
|
||||
},
|
||||
|
||||
hideDatePopover(event) {
|
||||
if (event?.target?.classList?.contains("discourse-local-date")) {
|
||||
hidePopover(event);
|
||||
}
|
||||
},
|
||||
|
||||
initialize(container) {
|
||||
const router = container.lookup("router:main");
|
||||
router.on("routeWillChange", hidePopover);
|
||||
|
||||
window.addEventListener("click", this.showDatePopover);
|
||||
|
||||
const siteSettings = container.lookup("site-settings:main");
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
#d-popover {
|
||||
div[data-tippy-root] {
|
||||
.locale-dates-previews {
|
||||
max-width: 360px;
|
||||
.preview {
|
||||
|
|
1
public/tippy.umd.js.map
Normal file
1
public/tippy.umd.js.map
Normal file
File diff suppressed because one or more lines are too long
2496
vendor/assets/javascripts/tippy.umd.js
vendored
Normal file
2496
vendor/assets/javascripts/tippy.umd.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
|
@ -35,4 +35,9 @@ Additional SVG icons
|
|||
<symbol id="discourse-emojis" viewBox="0 0 216.3 152.3">
|
||||
<path d="M121.1 70.7c1.9 2 5.1 2.1 7.2.2l.2-.2 31.2-32.2c9.1-9.4 8.6-24.9-1.6-33.5-8.8-7.5-22-6.2-30.1 2.2l-3.2 3.3-3.2-3.3c-8.1-8.4-21.3-9.7-30.1-2.2-10.1 8.6-10.7 24.2-1.6 33.5l31.2 32.2zM53.5 45.3C23.9 45.3 0 69.2 0 98.8s23.9 53.5 53.5 53.5 53.5-24 53.5-53.5-23.9-53.5-53.5-53.5zm18.8 24.6c5.5 0 9.9 4.4 9.9 9.9s-4.4 9.9-9.9 9.9-9.9-4.4-9.9-9.9c-.1-5.5 4.4-9.9 9.9-9.9zm-38.2 0c5.5 0 9.9 4.4 9.9 9.9s-4.4 9.9-9.9 9.9-9.9-4.4-9.9-9.9 4.4-9.9 9.9-9.9zm52.4 45.4c-8.2 9.8-20.2 15.5-33.1 15.5s-24.9-5.6-33.1-15.5c-3.9-4.7 3.2-10.6 7.1-5.9 6.5 7.7 15.9 12.2 26 12.2s19.5-4.4 26-12.2c3.8-4.7 10.9 1.2 7.1 5.9zm129.8-22.5c0-6.4-6.3-9.5-13.3-9.5h-24c1.5-6 10.3-13.8 10.3-22.8 0-15.5-10.1-17.2-15.2-17.2-4.3 0-6.2 8.3-7.2 12.2-1.1 4.6-2.2 9.3-5.4 12.4-6.7 6.8-10.3 15.3-18.4 23.5-.7-1.8-2.6-3.1-4.7-3.1h-10.7c-2.8 0-5.1 2.2-5.1 4.9V142c0 2.7 2.3 4.9 5.1 4.9h10.7c2.8 0 5.1-2.2 5.1-4.9v-.9c.3.1.6.2.9.2 3.3.1 7.8 1.9 11.1 3.4 6.7 3 15.1 6.7 25.3 6.7h.6c9 0 19.7-.1 24-6.3 1.8-2.5 2.7-4.4.5-9.9 5-3 7-10 1-15 8-5 8-13 1-17 6.1-1.9 8.5-6.6 8.4-10.4z"></path>
|
||||
</symbol>
|
||||
<!-- Rounded svg arrow for tippy.js, allows to change border color -->
|
||||
<symbol id="tippy-rounded-arrow" class="tippy-rounded-arrow" viewBox="0 0 16 6">
|
||||
<path class="svg-arrow" d="M0 6s1.796-.013 4.67-3.615C5.851.9 6.93.006 8 0c1.07-.006 2.148.887 3.343 2.385C14.233 6.005 16 6 16 6H0z"/>
|
||||
<path class="svg-content" d="m0 7s2 0 5-4c1-1 2-2 3-2 1 0 2 1 3 2 3 4 5 4 5 4h-16z"/>
|
||||
</symbol>
|
||||
</svg>
|
||||
|
|
Before Width: | Height: | Size: 6.4 KiB After Width: | Height: | Size: 6.8 KiB |
12
yarn.lock
12
yarn.lock
|
@ -203,6 +203,11 @@
|
|||
"@nodelib/fs.scandir" "2.1.3"
|
||||
fastq "^1.6.0"
|
||||
|
||||
"@popperjs/core@^2.9.0":
|
||||
version "2.11.0"
|
||||
resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.11.0.tgz#6734f8ebc106a0860dff7f92bf90df193f0935d7"
|
||||
integrity sha512-zrsUxjLOKAzdewIDRWy9nsV1GQsKBCWaGwsZQlCgr6/q+vjyZhFgqedLfFBuI9anTPEUT4APq9Mu0SZBTzIcGQ==
|
||||
|
||||
"@popperjs/core@v2.10.2":
|
||||
version "2.10.2"
|
||||
resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.10.2.tgz#0798c03351f0dea1a5a4cabddf26a55a7cbee590"
|
||||
|
@ -4009,6 +4014,13 @@ timers-browserify@^1.0.1:
|
|||
dependencies:
|
||||
process "~0.11.0"
|
||||
|
||||
tippy.js@^6.3.7:
|
||||
version "6.3.7"
|
||||
resolved "https://registry.yarnpkg.com/tippy.js/-/tippy.js-6.3.7.tgz#8ccfb651d642010ed9a32ff29b0e9e19c5b8c61c"
|
||||
integrity sha512-E1d3oP2emgJ9dRQZdf3Kkn0qJgI6ZLpyS5z6ZkY1DF3kaQaBsGZsndEpHwx+eC+tYM41HaSNvNtLx8tU57FzTQ==
|
||||
dependencies:
|
||||
"@popperjs/core" "^2.9.0"
|
||||
|
||||
tmp@^0.0.33:
|
||||
version "0.0.33"
|
||||
resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"
|
||||
|
|
Loading…
Reference in New Issue
Block a user