Skip to content

Commit

Permalink
HintsRoot
Browse files Browse the repository at this point in the history
  • Loading branch information
binrysearch committed Sep 8, 2024
1 parent edc92ca commit 9c6b72b
Show file tree
Hide file tree
Showing 8 changed files with 311 additions and 101 deletions.
59 changes: 59 additions & 0 deletions src/packages/hint/components/HintIcon.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import isFixed from "../../../util/isFixed";
import van from "../../dom/van";
import {
fixedHintClassName,
hintClassName,
hintDotClassName,
hintNoAnimationClassName,
hintPulseClassName,
} from "../className";
import { HintItem, HintPosition } from "../hintItem";
import { dataStepAttribute } from "../dataAttributes";
import { alignHintPosition } from "../position";

const { a, div } = van.tags;

export type HintProps = {
index: number;
hintItem: HintItem;
onClick: (e: any) => void;
};

const className = (hintItem: HintItem) => {
const classNames = [hintClassName];

if (!hintItem.hintAnimation) {
classNames.push(hintNoAnimationClassName);
}

if (isFixed(hintItem.element as HTMLElement)) {
classNames.push(fixedHintClassName);
}

return classNames.join(" ");
};

const HintDot = () => div({ className: hintDotClassName });
const HintPulse = () => div({ className: hintPulseClassName });

export const HintIcon = ({ index, hintItem, onClick }: HintProps) => {
const hintElement = a(
{
[dataStepAttribute]: index.toString(),
className: className(hintItem),
role: "button",
tabindex: 0,
onclick: onClick,
},
HintDot(),
HintPulse()
);

alignHintPosition(
hintItem.hintPosition as HintPosition,
hintElement,
hintItem.element as HTMLElement
);

return hintElement;
};
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Tooltip, TooltipProps } from "../tooltip/tooltip";
import van from "../dom/van";
import { tooltipTextClassName } from "./className";
import { Tooltip, TooltipProps } from "../../tooltip/tooltip";
import van from "../../dom/van";
import { tooltipTextClassName } from "../className";
import { HintItem } from "../hintItem";

const { a, p, div } = van.tags;

Expand Down
86 changes: 86 additions & 0 deletions src/packages/hint/components/HintsRoot.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import van from "../../dom/van";
import { hintsClassName } from "../className";
import { hideHint } from "../hide";
import { Hint } from "../hint";
import { showHintDialog } from "../tooltip";
import { HintIcon } from "./HintIcon";
import { ReferenceLayer } from "./ReferenceLayer";

const { div } = van.tags;

export type HintsRootProps = {
hint: Hint;
};

/**
* Returns an event handler unique to the hint iteration
*/
const getHintClick = (hint: Hint, i: number) => (e: Event) => {
const evt = e ? e : window.event;

if (evt && evt.stopPropagation) {
evt.stopPropagation();
}

if (evt && evt.cancelBubble !== null) {
evt.cancelBubble = true;
}

showHintDialog(hint, i);
};

export const HintsRoot = ({ hint }: HintsRootProps) => {
const hintElements = [];

for (const [i, hintItem] of hint.getHints().entries()) {
hintElements.push(
HintIcon({
index: i,
hintItem,
onClick: getHintClick(hint, i),
})
);
}

const root = div(
{
className: hintsClassName,
},
...hintElements
);

van.derive(() => {
if (hint._activeHintSignal.val === undefined) return;

const stepId = hint._activeHintSignal.val;
const hints = hint.getHints();
const hintItem = hints[stepId];

const referenceLayer = ReferenceLayer({
activeHintSignal: hint._activeHintSignal,
text: hintItem.hint || "",
element: hintItem.element as HTMLElement,
position: hintItem.position,

helperElementPadding: hint.getOption("helperElementPadding"),
targetElement: hint.getTargetElement(),

refreshes: hint._refreshes,

// hints don't have step numbers
showStepNumbers: false,

autoPosition: hint.getOption("autoPosition"),
positionPrecedence: hint.getOption("positionPrecedence"),

closeButtonEnabled: hint.getOption("hintShowButton"),
closeButtonLabel: hint.getOption("hintButtonLabel"),
closeButtonClassName: hint.getOption("buttonClass"),
closeButtonOnClick: () => hideHint(hint, stepId),
});

van.add(root, referenceLayer);
});

return root;
};
48 changes: 48 additions & 0 deletions src/packages/hint/components/ReferenceLayer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { setPositionRelativeTo } from "../../../util/positionRelativeTo";
import van, { State } from "../../dom/van";
import {
hintReferenceClassName,
tooltipReferenceLayerClassName,
} from "../className";
import { dataStepAttribute } from "../dataAttributes";
import { HintTooltip, HintTooltipProps } from "./HintTooltip";

const { div } = van.tags;

export type ReferenceLayerProps = HintTooltipProps & {
activeHintSignal: State<number | undefined>;
targetElement: HTMLElement;
helperElementPadding: number;
};

export const ReferenceLayer = ({
activeHintSignal,
targetElement,
helperElementPadding,
...props
}: ReferenceLayerProps) => {
return () => {
// remove the reference layer if the active hint signal is set to undefined
// e.g. when the user clicks outside the hint
if (activeHintSignal.val == undefined) return null;

const referenceLayer = div(
{
[dataStepAttribute]: activeHintSignal.val,
className: `${tooltipReferenceLayerClassName} ${hintReferenceClassName}`,
},
HintTooltip(props)
);

setTimeout(() => {
setPositionRelativeTo(
targetElement,
referenceLayer,
props.element as HTMLElement,
helperElementPadding
);
}, 1);

return referenceLayer;
};
};
2 changes: 1 addition & 1 deletion src/packages/hint/hide.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { hintElement, hintElements } from "./selector";
export async function hideHint(hint: Hint, stepId: number) {
const element = hintElement(stepId);

removeHintTooltip();
//removeHintTooltip();

if (element) {
addClass(element, hideHintClassName);
Expand Down
10 changes: 10 additions & 0 deletions src/packages/hint/hint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import { hideHint, hideHints } from "./hide";
import { showHint, showHints } from "./show";
import { removeHint, removeHints } from "./remove";
import { showHintDialog } from "./tooltip";
import van from "../dom/van";
import { HintsRoot } from "./components/HintsRoot";

type hintsAddedCallback = (this: Hint) => void | Promise<void>;
type hintClickCallback = (
Expand All @@ -26,6 +28,8 @@ export class Hint implements Package<HintOptions> {
private _hints: HintItem[] = [];
private readonly _targetElement: HTMLElement;
private _options: HintOptions;
public _activeHintSignal = van.state<number | undefined>(undefined);
public _refreshes = van.state(0);

private readonly callbacks: {
hintsAdded?: hintsAddedCallback;
Expand Down Expand Up @@ -105,6 +109,10 @@ export class Hint implements Package<HintOptions> {
return this;
}

private createRoot() {
van.add(this._targetElement, HintsRoot({ hint: this }));
}

/**
* Render hints on the page
*/
Expand All @@ -115,6 +123,7 @@ export class Hint implements Package<HintOptions> {

fetchHintItems(this);
await renderHints(this);
this.createRoot();
return this;
}

Expand Down Expand Up @@ -193,6 +202,7 @@ export class Hint implements Package<HintOptions> {
* @param stepId The hint step ID
*/
async showHintDialog(stepId: number) {
this._activeHintSignal.val = stepId;
await showHintDialog(this, stepId);
return this;
}
Expand Down
85 changes: 44 additions & 41 deletions src/packages/hint/render.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { addClass } from "../../util/className";
import isFixed from "../../util/isFixed";
import { alignHintPosition } from "./position";
import { showHintDialog } from "./tooltip";
import { HintsRoot } from "./components/HintsRoot";

/**
* Returns an event handler unique to the hint iteration
Expand Down Expand Up @@ -48,60 +49,62 @@ export async function renderHints(hint: Hint) {
});
}

const hints = hint.getHints();
for (let i = 0; i < hints.length; i++) {
const hintItem = hints[i];
//const hints = hint.getHints();
//for (let i = 0; i < hints.length; i++) {
// const hintItem = hints[i];

// avoid append a hint twice
if (queryElement(`.${hintClassName}[${dataStepAttribute}="${i}"]`)) {
return;
}
// // avoid append a hint twice
// if (queryElement(`.${hintClassName}[${dataStepAttribute}="${i}"]`)) {
// return;
// }

const hintElement = createElement("a", {
className: hintClassName,
});
setAnchorAsButton(hintElement);
// const hintElement = createElement("a", {
// className: hintClassName,
// });
// setAnchorAsButton(hintElement);

hintElement.onclick = getHintClick(hint, i);
// hintElement.onclick = getHintClick(hint, i);

if (!hintItem.hintAnimation) {
addClass(hintElement, hintNoAnimationClassName);
}
// if (!hintItem.hintAnimation) {
// addClass(hintElement, hintNoAnimationClassName);
// }

// hint's position should be fixed if the target element's position is fixed
if (isFixed(hintItem.element as HTMLElement)) {
addClass(hintElement, fixedHintClassName);
}
// // hint's position should be fixed if the target element's position is fixed
// if (isFixed(hintItem.element as HTMLElement)) {
// addClass(hintElement, fixedHintClassName);
// }

const hintDot = createElement("div", {
className: hintDotClassName,
});
// const hintDot = createElement("div", {
// className: hintDotClassName,
// });

const hintPulse = createElement("div", {
className: hintPulseClassName,
});
// const hintPulse = createElement("div", {
// className: hintPulseClassName,
// });

hintElement.appendChild(hintDot);
hintElement.appendChild(hintPulse);
hintElement.setAttribute(dataStepAttribute, i.toString());
// hintElement.appendChild(hintDot);
// hintElement.appendChild(hintPulse);
// hintElement.setAttribute(dataStepAttribute, i.toString());

// we swap the hint element with target element
// because _setHelperLayerPosition uses `element` property
hintItem.hintTargetElement = hintItem.element as HTMLElement;
hintItem.element = hintElement;
// // we swap the hint element with target element
// // because _setHelperLayerPosition uses `element` property
// hintItem.hintTargetElement = hintItem.element as HTMLElement;
// hintItem.element = hintElement;

// align the hint position
alignHintPosition(
hintItem.hintPosition as HintPosition,
hintElement,
hintItem.hintTargetElement as HTMLElement
);
// // align the hint position
// alignHintPosition(
// hintItem.hintPosition as HintPosition,
// hintElement,
// hintItem.hintTargetElement as HTMLElement
// );

hintsWrapper.appendChild(hintElement);
}
// hintsWrapper.appendChild(hintElement);
//}

//HintsRoot({ hint });

// adding the hints wrapper
document.body.appendChild(hintsWrapper);
//document.body.appendChild(HintsRoot({ hint }));

// call the callback function (if any)
hint.callback("hintsAdded")?.call(hint);
Expand Down
Loading

0 comments on commit 9c6b72b

Please sign in to comment.