カスケード式ドロップダウンメニューを追加するコード

This commit is contained in:
Mouriya
2024-09-13 06:25:35 +09:00
parent 91d52cb6e2
commit 04200193a8
7 changed files with 875 additions and 1 deletions

View File

@@ -0,0 +1,86 @@
/**
* ページの種類を表す型
*/
export type PageType = 'app' | 'show' | 'edit' | 'other';
/**
* showページのモードを表す型
*/
export type ShowPageMode = 'show' | 'edit' | null;
/**
* ページの状態を表すインターフェース
*/
export interface PageState {
type: PageType;
mode: ShowPageMode;
}
/**
* URLの特定のセグメントを取得する
* @param url 分析対象のURL
* @param index 取得したいセグメントのインデックス(負の数は末尾からのインデックス)
*/
const getSegment = (url: URL, index: number): string => {
const segments = url.pathname.split('/').filter(Boolean);
return segments.at(index) ?? '';
};
/**
* URLとアプリIDに基づいて現在のページの状態を判断する
* @param url 分析対象のURL
* @param appId 確認するアプリID
*/
export const getPageState = (url: string, appId: string): PageState => {
const parsedUrl = new URL(url);
const lastSegment = getSegment(parsedUrl, -1);
const secondLastSegment = getSegment(parsedUrl, -2);
if (lastSegment === appId && /^\d+$/.test(appId)) {
return { type: 'app', mode: null };
}
if (lastSegment.toLowerCase() === 'show' && secondLastSegment === appId && /^\d+$/.test(appId)) {
const mode = parsedUrl.searchParams.get('mode');
return {
type: 'show',
mode: (mode === 'show' || mode === 'edit') ? mode : null
};
}
if (lastSegment.toLowerCase() === 'edit' && secondLastSegment === appId && /^\d+$/.test(appId)) {
return { type: 'edit', mode: null };
}
return { type: 'other', mode: null };
};
/**
* 現在のページの状態を判断する現在のURLを使用
* @param appId 確認するアプリID
*/
export const getCurrentPageState = (appId: string): PageState =>
getPageState(window.location.href, appId);
/**
* URLを正規化する末尾のスラッシュを削除
* @param url 正規化対象のURL
*/
export const normalizeUrl = (url: string): string => {
const parsedUrl = new URL(url);
parsedUrl.pathname = parsedUrl.pathname.replace(/\/$/, '');
return parsedUrl.toString();
};
/**
* URLを安全に解析する
* @param url 解析対象のURL文字列
*/
export const safeParseUrl = (url: string): URL | null => {
try {
return new URL(url);
} catch {
return null;
}
};