Skip to content

Commit

Permalink
hint position
Browse files Browse the repository at this point in the history
  • Loading branch information
binrysearch committed Sep 8, 2024
1 parent 9c6b72b commit a4bf005
Show file tree
Hide file tree
Showing 11 changed files with 94 additions and 93 deletions.
7 changes: 6 additions & 1 deletion src/packages/hint/components/HintIcon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import isFixed from "../../../util/isFixed";
import van from "../../dom/van";
import {
fixedHintClassName,
hideHintClassName,
hintClassName,
hintDotClassName,
hintNoAnimationClassName,
Expand Down Expand Up @@ -30,6 +31,10 @@ const className = (hintItem: HintItem) => {
classNames.push(fixedHintClassName);
}

if (!hintItem.isActive?.val) {
classNames.push(hideHintClassName);
}

return classNames.join(" ");
};

Expand All @@ -40,7 +45,7 @@ export const HintIcon = ({ index, hintItem, onClick }: HintProps) => {
const hintElement = a(
{
[dataStepAttribute]: index.toString(),
className: className(hintItem),
className: () => className(hintItem),
role: "button",
tabindex: 0,
onclick: onClick,
Expand Down
17 changes: 11 additions & 6 deletions src/packages/hint/components/HintTooltip.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,19 @@ import { HintItem } from "../hintItem";

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

export type HintTooltipProps = Omit<TooltipProps, "hintMode"> & {
text: string;
export type HintTooltipProps = Omit<
TooltipProps,
"hintMode" | "element" | "position"
> & {
hintItem: HintItem;
closeButtonEnabled: boolean;
closeButtonOnClick: () => void;
closeButtonOnClick: (hintItem: HintItem) => void;
closeButtonLabel: string;
closeButtonClassName: string;
};

export const HintTooltip = ({
text,
hintItem,
closeButtonEnabled,
closeButtonOnClick,
closeButtonLabel,
Expand All @@ -24,18 +27,20 @@ export const HintTooltip = ({
return Tooltip(
{
...props,
element: hintItem.hintTooltipElement as HTMLElement,
position: hintItem.position,
hintMode: true,
},
[
div(
{ className: tooltipTextClassName },
p(text),
p(hintItem.hint || ""),
closeButtonEnabled
? a(
{
className: closeButtonClassName,
role: "button",
onclick: closeButtonOnClick,
onclick: () => closeButtonOnClick(hintItem),
},
closeButtonLabel
)
Expand Down
25 changes: 14 additions & 11 deletions src/packages/hint/components/HintsRoot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import van from "../../dom/van";
import { hintsClassName } from "../className";
import { hideHint } from "../hide";
import { Hint } from "../hint";
import { HintItem } from "../hintItem";
import { showHintDialog } from "../tooltip";
import { HintIcon } from "./HintIcon";
import { ReferenceLayer } from "./ReferenceLayer";
Expand Down Expand Up @@ -33,13 +34,17 @@ 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 hintTooltipElement = HintIcon({
index: i,
hintItem,
onClick: getHintClick(hint, i),
});

// store the hint tooltip element in the hint item
// because we need to position the reference layer relative to the HintIcon
hintItem.hintTooltipElement = hintTooltipElement;

hintElements.push(hintTooltipElement);
}

const root = div(
Expand All @@ -58,9 +63,7 @@ export const HintsRoot = ({ hint }: HintsRootProps) => {

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

helperElementPadding: hint.getOption("helperElementPadding"),
targetElement: hint.getTargetElement(),
Expand All @@ -76,7 +79,7 @@ export const HintsRoot = ({ hint }: HintsRootProps) => {
closeButtonEnabled: hint.getOption("hintShowButton"),
closeButtonLabel: hint.getOption("hintButtonLabel"),
closeButtonClassName: hint.getOption("buttonClass"),
closeButtonOnClick: () => hideHint(hint, stepId),
closeButtonOnClick: (hintItem: HintItem) => hideHint(hint, hintItem),
});

van.add(root, referenceLayer);
Expand Down
8 changes: 7 additions & 1 deletion src/packages/hint/components/ReferenceLayer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,17 @@ export const ReferenceLayer = ({
helperElementPadding,
...props
}: ReferenceLayerProps) => {
const initialActiveHintSignal = activeHintSignal.val;

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;

// remove the reference layer if the active hint signal changes
// and the initial active hint signal is not same as the current active hint signal (e.g. when the user clicks on another hint)
if (initialActiveHintSignal !== activeHintSignal.val) return null;

const referenceLayer = div(
{
[dataStepAttribute]: activeHintSignal.val,
Expand All @@ -38,7 +44,7 @@ export const ReferenceLayer = ({
setPositionRelativeTo(
targetElement,
referenceLayer,
props.element as HTMLElement,
props.hintItem.hintTooltipElement as HTMLElement,
helperElementPadding
);
}, 1);
Expand Down
24 changes: 8 additions & 16 deletions src/packages/hint/hide.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,21 @@ import { addClass } from "../../util/className";
import { removeHintTooltip } from "./tooltip";
import { dataStepAttribute } from "./dataAttributes";
import { hintElement, hintElements } from "./selector";
import { HintItem } from "./hintItem";

/**
* Hide a hint
*
* @api private
*/
export async function hideHint(hint: Hint, stepId: number) {
const element = hintElement(stepId);
export async function hideHint(hint: Hint, hintItem: HintItem) {
const isActiveSignal = hintItem.isActive;

//removeHintTooltip();

if (element) {
addClass(element, hideHintClassName);
if (isActiveSignal) {
isActiveSignal.val = false;
}

// call the callback function (if any)
hint.callback("hintClose")?.call(hint, stepId);
hint.callback("hintClose")?.call(hint, hintItem);
}

/**
Expand All @@ -29,13 +27,7 @@ export async function hideHint(hint: Hint, stepId: number) {
* @api private
*/
export async function hideHints(hint: Hint) {
const elements = hintElements();

for (const hintElement of Array.from(elements)) {
const step = hintElement.getAttribute(dataStepAttribute);

if (!step) continue;

await hideHint(hint, parseInt(step, 10));
for (const hintItem of hint.getHints()) {
await hideHint(hint, hintItem);
}
}
37 changes: 27 additions & 10 deletions src/packages/hint/hint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,11 @@ import van from "../dom/van";
import { HintsRoot } from "./components/HintsRoot";

type hintsAddedCallback = (this: Hint) => void | Promise<void>;
type hintClickCallback = (
this: Hint,
hintElement: HTMLElement,
item: HintItem,
stepId: number
) => void | Promise<void>;
type hintCloseCallback = (this: Hint, stepId: number) => void | Promise<void>;
type hintClickCallback = (this: Hint, item: HintItem) => void | Promise<void>;
type hintCloseCallback = (this: Hint, item: HintItem) => void | Promise<void>;

export class Hint implements Package<HintOptions> {
private _root: HTMLElement | undefined;
private _hints: HintItem[] = [];
private readonly _targetElement: HTMLElement;
private _options: HintOptions;
Expand Down Expand Up @@ -105,12 +101,19 @@ export class Hint implements Package<HintOptions> {
* @param hint The Hint item
*/
addHint(hint: HintItem): this {
// always set isActive to true
hint.isActive = van.state(true);
this._hints.push(hint);
return this;
}

public isRendered() {
return this._root !== undefined;
}

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

/**
Expand Down Expand Up @@ -139,7 +142,12 @@ export class Hint implements Package<HintOptions> {
* @param stepId The hint step ID
*/
async hideHint(stepId: number) {
await hideHint(this, stepId);
const hintItem = this.getHint(stepId);

if (hintItem) {
await hideHint(this, hintItem);
}

return this;
}

Expand All @@ -156,7 +164,12 @@ export class Hint implements Package<HintOptions> {
* @param stepId The hint step ID
*/
showHint(stepId: number) {
showHint(stepId);
const hintItem = this.getHint(stepId);

if (hintItem) {
showHint(hintItem);
}

return this;
}

Expand All @@ -173,6 +186,10 @@ export class Hint implements Package<HintOptions> {
* Useful when you want to destroy the elements and add them again (e.g. a modal or popup)
*/
destroy() {
if (this._root) {
this._root.remove();
this._root = undefined;
}
removeHints(this);
return this;
}
Expand Down
6 changes: 5 additions & 1 deletion src/packages/hint/hintItem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
dataHintPositionAttribute,
dataTooltipClassAttribute,
} from "./dataAttributes";
import { State } from "../dom/van";

export type HintPosition =
| "top-left"
Expand All @@ -24,9 +25,12 @@ export type HintItem = {
tooltipClass?: string;
position: TooltipPosition;
hint?: string;
hintTargetElement?: HTMLElement;
// this is the HintIcon element for this particular hint
// used for positioning the HintTooltip
hintTooltipElement?: HTMLElement;
hintAnimation?: boolean;
hintPosition: HintPosition;
isActive?: State<boolean>;
};

export const fetchHintItems = (hint: Hint) => {
Expand Down
4 changes: 2 additions & 2 deletions src/packages/hint/position.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ export const alignHintPosition = (
* @api private
*/
export function reAlignHints(hint: Hint) {
for (const { hintTargetElement, hintPosition, element } of hint.getHints()) {
alignHintPosition(hintPosition, element as HTMLElement, hintTargetElement);
for (const { hintTooltipElement, hintPosition, element } of hint.getHints()) {
alignHintPosition(hintPosition, element as HTMLElement, hintTooltipElement);
}
}
18 changes: 0 additions & 18 deletions src/packages/hint/render.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,26 +15,8 @@ import setAnchorAsButton from "../../util/setAnchorAsButton";
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
*/
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);
};

/**
* Add all available hints to the page
*
Expand Down
25 changes: 8 additions & 17 deletions src/packages/hint/show.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,15 @@
import { Hint } from "./hint";
import { hideHintClassName } from "./className";
import { dataStepAttribute } from "./dataAttributes";
import { removeClass } from "../../util/className";
import { hintElement, hintElements } from "./selector";
import { HintItem } from "./hintItem";

/**
* Show all hints
*
* @api private
*/
export async function showHints(hint: Hint) {
const elements = hintElements();

if (elements?.length) {
for (const hintElement of Array.from(elements)) {
const step = hintElement.getAttribute(dataStepAttribute);

if (!step) continue;

showHint(parseInt(step, 10));
if (hint.isRendered()) {
for (const hintItem of hint.getHints()) {
showHint(hintItem);
}
} else {
// or render hints if there are none
Expand All @@ -31,10 +22,10 @@ export async function showHints(hint: Hint) {
*
* @api private
*/
export function showHint(stepId: number) {
const element = hintElement(stepId);
export function showHint(hintItem: HintItem) {
const activeSignal = hintItem.isActive;

if (element) {
removeClass(element, new RegExp(hideHintClassName, "g"));
if (activeSignal) {
activeSignal.val = true;
}
}
Loading

0 comments on commit a4bf005

Please sign in to comment.