@nightingale-elements/nightingale-new-core
Version:
Base Elements for Nightingale Components
128 lines (117 loc) • 3.9 kB
text/typescript
import { Selection } from "d3";
import { property } from "lit/decorators.js";
import NightingaleBaseElement, {
Constructor,
} from "../../nightingale-base-element";
import withDimensions, { WithDimensionsInterface } from "../withDimensions";
const DEFAULT_MARGIN_COLOR = "#FFFFFFDD";
export interface withMarginInterface
extends NightingaleBaseElement,
WithDimensionsInterface {
"margin-top": number;
"margin-bottom": number;
"margin-left": number;
"margin-right": number;
"margin-color": string;
getWidthWithMargins: () => number;
getHeightWithMargins: () => number;
renderMarginOnGroup: (
g?: Selection<
SVGGElement,
unknown,
HTMLElement | SVGElement | null,
unknown
>,
) => void;
}
const defaultOptions = {
"margin-top": 0,
"margin-bottom": 0,
"margin-left": 10,
"margin-right": 10,
"margin-color": DEFAULT_MARGIN_COLOR,
};
const withMargin = <T extends Constructor<NightingaleBaseElement>>(
superClass: T,
options: {
"margin-top"?: number;
"margin-bottom"?: number;
"margin-left"?: number;
"margin-right"?: number;
"margin-color"?: string | null;
} = {},
) => {
class WithMargin extends withDimensions(superClass) implements withMarginInterface {
#initialOptions = { ...defaultOptions, ...options };
"margin-top": number = this.#initialOptions["margin-top"];
"margin-bottom": number = this.#initialOptions["margin-bottom"];
"margin-left": number = this.#initialOptions["margin-left"];
"margin-right": number = this.#initialOptions["margin-right"];
"margin-color": string = this.#initialOptions["margin-color"] ?? DEFAULT_MARGIN_COLOR;
getWidthWithMargins() {
return this.width
? this.width - this["margin-left"] - this["margin-right"]
: 0;
}
getHeightWithMargins() {
return this.height
? this.height - this["margin-top"] - this["margin-bottom"]
: 0;
}
renderMarginOnGroup(
g?: Selection<
SVGGElement,
unknown,
HTMLElement | SVGElement | null,
unknown
>,
) {
if (!g) return;
if (g.select("rect").empty()) {
g.append("rect")
.style("pointer-events", "none")
.attr("class", "margin-left");
g.append("rect")
.style("pointer-events", "none")
.attr("class", "margin-right");
g.append("rect")
.style("pointer-events", "none")
.attr("class", "margin-top");
g.append("rect")
.style("pointer-events", "none")
.attr("class", "margin-bottom");
}
g.select("rect.margin-left")
.attr("fill", this["margin-color"])
.attr("x", 0)
.attr("y", 0)
.attr("width", this["margin-left"])
.attr("height", this["height"]);
g.select("rect.margin-right")
.attr("fill", this["margin-color"])
.attr("x", this["width"] - this["margin-right"])
.attr("y", 0)
.attr("width", this["margin-right"])
.attr("height", this["height"]);
g.select("rect.margin-top")
.attr("fill", this["margin-color"])
.attr("x", this["margin-left"])
.attr("y", 0)
.attr("width", this["width"] - this["margin-left"] - this["margin-right"])
.attr("height", this["margin-top"]);
g.select("rect.margin-bottom")
.attr("fill", this["margin-color"])
.attr("x", this["margin-left"])
.attr("y", this["height"] - this["margin-bottom"])
.attr("width", this["width"] - this["margin-left"] - this["margin-right"])
.attr("height", this["margin-bottom"]);
}
}
return WithMargin as Constructor<withMarginInterface> & T;
};
export default withMargin;