Skip to content

Commit

Permalink
[gem] <gem-*-link> expose method
Browse files Browse the repository at this point in the history
  • Loading branch information
mantou132 committed Dec 11, 2023
1 parent 8287a11 commit 45bf646
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 56 deletions.
21 changes: 21 additions & 0 deletions packages/gem-book/src/element/elements/side-link.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { connectStore, customElement, state } from '@mantou/gem';
import { GemActiveLinkElement } from '@mantou/gem/elements/link';

import { locationStore } from '../store';

/**
* @customElement gem-book-side-link
*/
@customElement('gem-book-side-link')
@connectStore(locationStore)
export class GemBookSideLinkElement extends GemActiveLinkElement {
@state match: boolean;

constructor() {
super();
this.effect(
() => (this.match = this.active),
() => [locationStore.path, locationStore.query],
);
}
}
7 changes: 4 additions & 3 deletions packages/gem-book/src/element/elements/sidebar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { container } from './icons';

import '@mantou/gem/elements/link';
import '@mantou/gem/elements/use';
import './side-link';

@customElement('gem-book-sidebar')
@connectStore(bookStore)
Expand Down Expand Up @@ -41,13 +42,13 @@ export class SideBar extends GemElement {
`;
} else {
return html`
<gem-active-link
<gem-book-side-link
class=${classMap({ item: true, link: true, single: isTop, [type]: true })}
pattern=${children ? new URL(link, location.origin).pathname : link}
href=${link}
>
${type === 'heading' ? '# ' : ''} ${title ? capitalize(title) : 'No title'}
</gem-active-link>
</gem-book-side-link>
${children ? html`<div class="links item hash">${children.map((item) => this.renderItem(item))}</div>` : null}
`;
}
Expand Down Expand Up @@ -98,7 +99,7 @@ export class SideBar extends GemElement {
.file:where(:state(active), [data-active]) {
font-weight: bolder;
}
.link:where(:state(active), [data-active]) + .hash {
.link:where(:state(match), [data-match]) + .hash {
display: block;
}
.heading:not(:where(:state(active), [data-active])):not(:hover),
Expand Down
2 changes: 2 additions & 0 deletions packages/gem/src/elements/base/gesture.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ export class GemGestureElement extends GemElement {
#pressTimer = 0;

#startEventMap: Map<number, PointerEvent> = new Map();

/** 指针移动事件记录 */
movesMap: Map<number, PanEventDetail[]> = new Map();

#getMoves = (pointerId: number) => {
Expand Down
108 changes: 56 additions & 52 deletions packages/gem/src/elements/base/link.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,29 +5,8 @@ import { absoluteLocation } from '../../lib/utils';

import { matchPath, RouteItem, RouteOptions, createHistoryParams, createPath } from './route';

// 不包含 basePath
function getPathInfo(ele: GemLinkElement) {
if (ele.route) {
const queryProp = ele.options?.query || '';
const hashProp = ele.options?.hash || '';
return createPath(ele.route, ele.options) + queryProp + hashProp;
} else {
const url = ele.href || ele.path + ele.query + ele.hash;
const { path, query } = history.getParams();
if (url.startsWith('#')) {
return `${path}${query}${url}`;
} else if (url.startsWith('?')) {
return `${path}${url}`;
} else if (url.startsWith('.')) {
return absoluteLocation(path, url);
} else {
return url;
}
}
}

function isExternal(pathInfo: string) {
return !pathInfo.startsWith('/');
function isExternal(path: string) {
return !path.startsWith('/');
}

/**
Expand Down Expand Up @@ -66,37 +45,41 @@ export class GemLinkElement extends GemElement {
return this.routeOptions || this.options;
}

get #hint() {
return this.hint || 'on';
}

constructor() {
super();
this.tabIndex = 0;
this.addEventListener('click', this.#clickHandle);
this.addEventListener('click', this.#onClick);
}

#clickHandle = async () => {
const pathInfo = getPathInfo(this);
#onClick = async () => {
const locationString = this.getLocationString();

if (!pathInfo) return;
if (!locationString) return;

// 外部链接使用 `window.open`
if (isExternal(pathInfo)) {
if (isExternal(locationString)) {
switch (this.target) {
case '_self':
window.location.href = pathInfo;
window.location.href = locationString;
return;
case '_parent':
window.parent.location.href = pathInfo;
window.parent.location.href = locationString;
return;
case '_top':
window.top!.location.href = pathInfo;
window.top!.location.href = locationString;
return;
default:
window.open(pathInfo);
window.open(locationString);
return;
}
}

const { path, query, hash } = history.getParams();
if (path + query + hash === pathInfo) {
if (path + query + hash === locationString) {
// 点击当前路由链接时,什么也没做
return;
}
Expand All @@ -109,7 +92,7 @@ export class GemLinkElement extends GemElement {
title: this.route.title || this.docTitle,
});
} else if (this.href) {
const { pathname, search, hash } = new URL(pathInfo, location.origin);
const { pathname, search, hash } = new URL(locationString, location.origin);
history.pushIgnoreCloseHandle({
path: pathname,
query: search,
Expand All @@ -125,7 +108,14 @@ export class GemLinkElement extends GemElement {
e.preventDefault();
};

render(pathInfo = getPathInfo(this)) {
#getHint = () => {
const locationString = this.getLocationString();
return isExternal(locationString)
? locationString
: new URL(history.basePath + locationString, location.origin).toString();
};

render() {
return html`
<style>
:host {
Expand All @@ -145,18 +135,35 @@ export class GemLinkElement extends GemElement {
<a
part=${this.link}
@click=${this.#preventDefault}
href=${ifDefined(
this.hint === 'off'
? undefined
: isExternal(pathInfo)
? pathInfo
: new URL(history.basePath + pathInfo, location.origin).toString(),
)}
href=${ifDefined(this.#hint === 'off' ? undefined : this.#getHint())}
>
<slot></slot>
</a>
`;
}

/**
* 如果该元素是外部链接返回 URL,否则返回路径(不包含 basePath)
*/
getLocationString() {
if (this.route) {
const queryProp = this.#routeOptions?.query || '';
const hashProp = this.#routeOptions?.hash || '';
return createPath(this.route, this.#routeOptions) + queryProp + hashProp;
} else {
const url = this.href || this.path + this.query + this.hash;
const { path, query } = history.getParams();
if (url.startsWith('#')) {
return `${path}${query}${url}`;
} else if (url.startsWith('?')) {
return `${path}${url}`;
} else if (url.startsWith('.')) {
return absoluteLocation(path, url);
} else {
return url;
}
}
}
}

/**
Expand All @@ -168,15 +175,12 @@ export class GemActiveLinkElement extends GemLinkElement {
@attribute pattern: string; // 使用匹配模式设定 active
@state active: boolean;

render() {
const { path, query, hash } = history.getParams();
const isMatchPattern = this.pattern && matchPath(this.pattern, path);
const pathInfo = getPathInfo(this);
if (isMatchPattern || path + query + hash === pathInfo) {
this.active = true;
} else {
this.active = false;
}
return super.render(pathInfo);
constructor() {
super();
this.effect(() => {
const { path, query, hash } = history.getParams();
const isMatchPattern = this.pattern && matchPath(this.pattern, path);
this.active = !!isMatchPattern || path + query + hash === this.getLocationString();
});
}
}
3 changes: 2 additions & 1 deletion packages/gem/src/elements/base/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,8 +132,9 @@ export class GemRouteElement extends GemElement<State> {
@emitter loading: Emitter<RouteItem>;
@emitter error: Emitter<any>;

/**当前使用的路由对象 */
currentRoute: RouteItem | null;
// 当前匹配的路由的 params
/**当前匹配的路由的 params */
currentParams: Params = {};

#lastLoader?: Promise<TemplateResult>;
Expand Down

0 comments on commit 45bf646

Please sign in to comment.