haori-bootstrap 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.ja.md +180 -0
- package/README.md +180 -0
- package/dist/bootstrap_haori.d.ts +73 -0
- package/dist/bootstrap_resolver.d.ts +45 -0
- package/dist/browser.d.ts +1 -0
- package/dist/dialog.d.ts +17 -0
- package/dist/haori-bootstrap.iife.js +3 -0
- package/dist/haori-bootstrap.iife.js.map +1 -0
- package/dist/haori-bootstrap.js +505 -0
- package/dist/haori-bootstrap.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/install.d.ts +27 -0
- package/dist/message.d.ts +15 -0
- package/dist/modal.d.ts +17 -0
- package/dist/toast.d.ts +10 -0
- package/dist/types.d.ts +147 -0
- package/package.json +74 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"haori-bootstrap.js","sources":["../src/bootstrap_resolver.ts","../src/dialog.ts","../src/message.ts","../src/modal.ts","../src/toast.ts","../src/bootstrap_haori.ts","../src/install.ts","../src/browser.ts","../src/index.ts"],"sourcesContent":["import type {\n BootstrapModalConstructor,\n BootstrapModalInstance,\n BootstrapModalOptions,\n BootstrapNamespace,\n BootstrapToastConstructor,\n BootstrapToastInstance,\n} from './types';\n\n/**\n * 値がコンストラクター関数かどうかを判定する。\n *\n * @param value 判定対象の値。\n * @return コンストラクター関数なら true。\n */\nfunction isConstructor<T>(value: unknown): value is new (...args: readonly unknown[]) => T {\n return typeof value === 'function';\n}\n\n/**\n * Bootstrap の Modal コンストラクターを返す。\n *\n * @param bootstrap Bootstrap 名前空間。\n * @return Modal コンストラクター。見つからない場合は undefined。\n */\nexport function resolveModalConstructor(\n bootstrap?: BootstrapNamespace,\n): BootstrapModalConstructor | undefined {\n return isConstructor<BootstrapModalInstance>(bootstrap?.Modal)\n ? (bootstrap?.Modal as BootstrapModalConstructor)\n : undefined;\n}\n\n/**\n * Bootstrap の Toast コンストラクターを返す。\n *\n * @param bootstrap Bootstrap 名前空間。\n * @return Toast コンストラクター。見つからない場合は undefined。\n */\nexport function resolveToastConstructor(\n bootstrap?: BootstrapNamespace,\n): BootstrapToastConstructor | undefined {\n return isConstructor<BootstrapToastInstance>(bootstrap?.Toast)\n ? (bootstrap?.Toast as BootstrapToastConstructor)\n : undefined;\n}\n\n/**\n * Modal が利用可能かどうかを返す。\n *\n * @param bootstrap Bootstrap 名前空間。\n * @return 利用可能なら true。\n */\nexport function hasModalSupport(bootstrap?: BootstrapNamespace): boolean {\n return Boolean(resolveModalConstructor(bootstrap));\n}\n\n/**\n * Toast が利用可能かどうかを返す。\n *\n * @param bootstrap Bootstrap 名前空間。\n * @return 利用可能なら true。\n */\nexport function hasToastSupport(bootstrap?: BootstrapNamespace): boolean {\n return Boolean(resolveToastConstructor(bootstrap));\n}\n\n/**\n * Modal インスタンスを取得または生成する。\n *\n * @param element 対象要素。\n * @param bootstrap Bootstrap 名前空間。\n * @return Modal インスタンス。生成できない場合は undefined。\n */\nexport function createModalInstance(\n element: HTMLElement,\n options?: BootstrapModalOptions,\n bootstrap?: BootstrapNamespace,\n): BootstrapModalInstance | undefined {\n const modalConstructor = resolveModalConstructor(bootstrap);\n if (!modalConstructor) {\n return undefined;\n }\n\n if (typeof modalConstructor.getOrCreateInstance === 'function') {\n return modalConstructor.getOrCreateInstance(element, options);\n }\n\n return new modalConstructor(element, options);\n}\n\n/**\n * Toast インスタンスを取得または生成する。\n *\n * @param element 対象要素。\n * @param bootstrap Bootstrap 名前空間。\n * @return Toast インスタンス。生成できない場合は undefined。\n */\nexport function createToastInstance(\n element: HTMLElement,\n bootstrap?: BootstrapNamespace,\n): BootstrapToastInstance | undefined {\n const toastConstructor = resolveToastConstructor(bootstrap);\n if (!toastConstructor) {\n return undefined;\n }\n\n if (typeof toastConstructor.getOrCreateInstance === 'function') {\n return toastConstructor.getOrCreateInstance(element);\n }\n\n return new toastConstructor(element);\n}\n","import { createModalInstance } from './bootstrap_resolver';\nimport type { ResolvedInstallOptions } from './types';\n\nconst DIALOG_CONTAINER_ATTRIBUTE = 'data-haori-bootstrap-dialog';\nconst ACTION_ATTRIBUTE = 'data-haori-bootstrap-action';\n\n/**\n * dialog 系 modal の既定オプションを返す。\n *\n * @return Bootstrap Modal の生成オプション。\n */\nfunction createDialogModalOptions() {\n return {\n backdrop: 'static' as const,\n };\n}\n\n/**\n * dialog を挿入する親要素を解決する。\n *\n * @param documentObject 検索に使用する document。\n * @param options 解決済み導入設定。\n * @return 挿入先の要素。\n */\nfunction resolveDialogContainer(documentObject: Document, options: ResolvedInstallOptions): HTMLElement {\n if (options.dialogContainerSelector) {\n const resolvedElement = documentObject.querySelector<HTMLElement>(\n options.dialogContainerSelector,\n );\n if (resolvedElement) {\n return resolvedElement;\n }\n }\n\n return documentObject.body;\n}\n\n/**\n * dialog または confirm 用の modal 要素を組み立てる。\n *\n * @param documentObject 生成に使用する document。\n * @param message 表示するメッセージ。\n * @param isConfirm confirm 用かどうか。\n * @return 生成した modal 要素。\n */\nfunction createModalShell(documentObject: Document, message: string, isConfirm: boolean): HTMLDivElement {\n const modalElement = documentObject.createElement('div');\n modalElement.className = 'modal fade';\n modalElement.tabIndex = -1;\n modalElement.setAttribute(DIALOG_CONTAINER_ATTRIBUTE, 'true');\n modalElement.setAttribute('aria-hidden', 'true');\n\n const dialogElement = documentObject.createElement('div');\n dialogElement.className = 'modal-dialog modal-dialog-centered';\n\n const contentElement = documentObject.createElement('div');\n contentElement.className = 'modal-content';\n\n const bodyElement = documentObject.createElement('div');\n bodyElement.className = 'modal-body';\n\n const messageElement = documentObject.createElement('p');\n messageElement.className = 'mb-0';\n messageElement.style.whiteSpace = 'pre-line';\n messageElement.textContent = message;\n bodyElement.appendChild(messageElement);\n\n const footerElement = documentObject.createElement('div');\n footerElement.className = 'modal-footer';\n\n if (isConfirm) {\n const cancelButton = documentObject.createElement('button');\n cancelButton.type = 'button';\n cancelButton.className = 'btn btn-secondary';\n cancelButton.setAttribute(ACTION_ATTRIBUTE, 'cancel');\n cancelButton.textContent = 'Cancel';\n footerElement.appendChild(cancelButton);\n }\n\n const okButton = documentObject.createElement('button');\n okButton.type = 'button';\n okButton.className = 'btn btn-primary';\n okButton.setAttribute(ACTION_ATTRIBUTE, 'ok');\n okButton.textContent = 'OK';\n footerElement.appendChild(okButton);\n\n contentElement.append(bodyElement, footerElement);\n dialogElement.appendChild(contentElement);\n modalElement.appendChild(dialogElement);\n return modalElement;\n}\n\n/**\n * 情報表示用の Bootstrap Modal を表示する。\n *\n * @param message 表示するメッセージ。\n * @param options 解決済み導入設定。\n * @return 完了時に解決される Promise。\n */\nexport function showDialog(message: string, options: ResolvedInstallOptions): Promise<void> {\n const documentObject = globalThis.document;\n const modalElement = createModalShell(documentObject, message, false);\n resolveDialogContainer(documentObject, options).appendChild(modalElement);\n\n const modalInstance = createModalInstance(\n modalElement,\n createDialogModalOptions(),\n options.bootstrap,\n );\n if (!modalInstance) {\n modalElement.remove();\n return Promise.reject(new Error('Bootstrap Modal is unavailable.'));\n }\n\n return new Promise<void>((resolve, reject) => {\n const finalize = (): void => {\n modalElement.removeEventListener('hidden.bs.modal', handleHidden);\n modalElement.remove();\n modalInstance.dispose?.();\n resolve();\n };\n\n const handleHidden = (): void => {\n finalize();\n };\n\n const okButton = modalElement.querySelector<HTMLButtonElement>(`[${ACTION_ATTRIBUTE}=\"ok\"]`);\n okButton?.addEventListener(\n 'click',\n () => {\n modalInstance.hide();\n },\n { once: true },\n );\n\n modalElement.addEventListener('hidden.bs.modal', handleHidden, { once: true });\n\n try {\n modalInstance.show();\n } catch (error) {\n modalElement.removeEventListener('hidden.bs.modal', handleHidden);\n modalElement.remove();\n modalInstance.dispose?.();\n reject(error);\n }\n });\n}\n\n/**\n * 確認用の Bootstrap Modal を表示する。\n *\n * @param message 表示するメッセージ。\n * @param options 解決済み導入設定。\n * @return OK のみ true を返す Promise。\n */\nexport function showConfirm(\n message: string,\n options: ResolvedInstallOptions,\n): Promise<boolean> {\n const documentObject = globalThis.document;\n const modalElement = createModalShell(documentObject, message, true);\n resolveDialogContainer(documentObject, options).appendChild(modalElement);\n\n const modalInstance = createModalInstance(\n modalElement,\n createDialogModalOptions(),\n options.bootstrap,\n );\n if (!modalInstance) {\n modalElement.remove();\n return Promise.reject(new Error('Bootstrap Modal is unavailable.'));\n }\n\n return new Promise<boolean>((resolve, reject) => {\n let confirmed = false;\n\n const finalize = (): void => {\n modalElement.removeEventListener('hidden.bs.modal', handleHidden);\n modalElement.remove();\n modalInstance.dispose?.();\n resolve(confirmed);\n };\n\n const handleHidden = (): void => {\n finalize();\n };\n\n const okButton = modalElement.querySelector<HTMLButtonElement>(`[${ACTION_ATTRIBUTE}=\"ok\"]`);\n const cancelButton = modalElement.querySelector<HTMLButtonElement>(\n `[${ACTION_ATTRIBUTE}=\"cancel\"]`,\n );\n\n okButton?.addEventListener(\n 'click',\n () => {\n confirmed = true;\n modalInstance.hide();\n },\n { once: true },\n );\n cancelButton?.addEventListener(\n 'click',\n () => {\n confirmed = false;\n modalInstance.hide();\n },\n { once: true },\n );\n\n modalElement.addEventListener('hidden.bs.modal', handleHidden, { once: true });\n\n try {\n modalInstance.show();\n } catch (error) {\n modalElement.removeEventListener('hidden.bs.modal', handleHidden);\n modalElement.remove();\n modalInstance.dispose?.();\n reject(error);\n }\n });\n}\n","const OWNED_ATTRIBUTE = 'data-haori-bootstrap-owned';\nconst CONTAINER_ATTRIBUTE = 'data-haori-bootstrap-message-container';\nconst INVALID_TARGET_ATTRIBUTE = 'data-haori-bootstrap-invalid-target';\n\n/**\n * 対象要素が checkbox または radio かどうかを判定する。\n *\n * @param target 判定対象の要素。\n * @return checkbox または radio の input 要素なら true。\n */\nfunction isChoiceInput(target: HTMLElement): target is HTMLInputElement {\n return (\n target instanceof HTMLInputElement &&\n (target.type === 'checkbox' || target.type === 'radio')\n );\n}\n\n/**\n * 対象要素が radio input かどうかを判定する。\n *\n * @param target 判定対象の要素。\n * @return radio の input 要素なら true。\n */\nfunction isRadioInput(target: HTMLElement): target is HTMLInputElement {\n return target instanceof HTMLInputElement && target.type === 'radio';\n}\n\n/**\n * 対象要素が通常の invalid-feedback を直後に付与するフィールドかどうかを判定する。\n *\n * @param target 判定対象の要素。\n * @return 入力系フィールドなら true。\n */\nfunction isFieldTarget(\n target: HTMLElement,\n): target is HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement {\n return (\n target instanceof HTMLInputElement ||\n target instanceof HTMLSelectElement ||\n target instanceof HTMLTextAreaElement\n );\n}\n\n/**\n * 子要素から管理対象のメッセージコンテナを取得する。\n *\n * @param target 検索対象の要素。\n * @return 管理対象コンテナ。見つからない場合は undefined。\n */\nfunction getDirectOwnedContainer(target: HTMLElement): HTMLElement | undefined {\n return Array.from(target.children).find(\n (element): element is HTMLElement =>\n element instanceof HTMLElement && element.getAttribute(CONTAINER_ATTRIBUTE) === 'true',\n );\n}\n\n/**\n * 管理対象のメッセージ要素を生成する。\n *\n * @param documentObject 生成に使用する document。\n * @param message 表示するメッセージ。\n * @return 生成したメッセージ要素。\n */\nfunction createMessageItem(documentObject: Document, message: string): HTMLDivElement {\n const messageElement = documentObject.createElement('div');\n messageElement.setAttribute(OWNED_ATTRIBUTE, 'true');\n messageElement.textContent = message;\n return messageElement;\n}\n\n/**\n * block container 配下の既存メッセージコンテナを取得する。\n *\n * @param target 検索対象の要素。\n * @return 既存コンテナ。見つからない場合は undefined。\n */\nfunction getOwnedDirectChild(target: HTMLElement): HTMLElement | undefined {\n return getDirectOwnedContainer(target);\n}\n\n/**\n * 指定した radio と同じグループに属する radio 要素一覧を取得する。\n *\n * @param target 基準となる radio 要素。\n * @return 同じグループに属する radio 要素一覧。\n */\nfunction getRadioGroupTargets(target: HTMLInputElement): HTMLInputElement[] {\n if (target.name) {\n const rootNode = target.form ?? target.ownerDocument;\n const escapedName = typeof CSS !== 'undefined' && typeof CSS.escape === 'function'\n ? CSS.escape(target.name)\n : target.name.replace(/([\"\\\\])/g, '\\\\$1');\n const groupTargets = Array.from(\n rootNode.querySelectorAll<HTMLInputElement>(`input[type=\"radio\"][name=\"${escapedName}\"]`),\n );\n if (groupTargets.length > 0) {\n return groupTargets;\n }\n }\n\n return [target];\n}\n\n/**\n * 複数要素の最も近い共通祖先要素を返す。\n *\n * @param elements 判定対象の要素一覧。\n * @return 共通祖先要素。見つからない場合は undefined。\n */\nfunction findCommonAncestor(elements: readonly HTMLElement[]): HTMLElement | undefined {\n const [firstElement, ...restElements] = elements;\n if (!firstElement) {\n return undefined;\n }\n\n let candidate: HTMLElement | null = firstElement;\n while (candidate) {\n if (restElements.every((element) => candidate?.contains(element))) {\n return candidate;\n }\n candidate = candidate.parentElement;\n }\n\n return undefined;\n}\n\n/**\n * radio group のメッセージ挿入先を解決する。\n *\n * @param target 対象の radio 要素。\n * @return 挿入先の要素。見つからない場合は undefined。\n */\nfunction resolveRadioMessageHost(target: HTMLInputElement): HTMLElement | undefined {\n const groupTargets = getRadioGroupTargets(target);\n const wrappers = groupTargets\n .map((element) => element.closest('.form-check'))\n .filter((element): element is HTMLElement => element instanceof HTMLElement);\n\n if (wrappers.length > 1) {\n const commonAncestor = findCommonAncestor(wrappers);\n if (commonAncestor && !wrappers.includes(commonAncestor)) {\n return commonAncestor;\n }\n }\n\n return resolveChoiceMessageHost(target);\n}\n\n/**\n * checkbox と radio のメッセージ挿入先を解決する。\n *\n * @param target 対象の input 要素。\n * @return 挿入先の form-check 要素。見つからない場合は undefined。\n */\nfunction resolveChoiceMessageHost(target: HTMLInputElement): HTMLElement | undefined {\n const closestFormCheck = target.closest('.form-check');\n return closestFormCheck instanceof HTMLElement ? closestFormCheck : undefined;\n}\n\n/**\n * 通常フィールドの直後に invalid-feedback コンテナを取得または生成する。\n *\n * @param target 対象の要素。\n * @return 取得または生成したコンテナ。\n */\nfunction ensureFieldContainer(target: HTMLElement): HTMLElement {\n const nextElement = target.nextElementSibling;\n if (\n nextElement instanceof HTMLElement &&\n nextElement.getAttribute(CONTAINER_ATTRIBUTE) === 'true'\n ) {\n return nextElement;\n }\n\n const container = document.createElement('div');\n container.className = 'invalid-feedback d-block';\n container.setAttribute(OWNED_ATTRIBUTE, 'true');\n container.setAttribute(CONTAINER_ATTRIBUTE, 'true');\n target.insertAdjacentElement('afterend', container);\n return container;\n}\n\n/**\n * checkbox と radio 用に form-check 末尾の invalid-feedback を取得または生成する。\n *\n * @param target 対象の input 要素。\n * @return 取得または生成したコンテナ。\n */\nfunction ensureChoiceContainer(target: HTMLInputElement): HTMLElement {\n const hostElement = isRadioInput(target)\n ? resolveRadioMessageHost(target)\n : resolveChoiceMessageHost(target);\n if (!hostElement) {\n return ensureFieldContainer(target);\n }\n\n const existingContainer = getDirectOwnedContainer(hostElement);\n if (existingContainer) {\n return existingContainer;\n }\n\n const container = document.createElement('div');\n container.className = 'invalid-feedback d-block';\n container.setAttribute(OWNED_ATTRIBUTE, 'true');\n container.setAttribute(CONTAINER_ATTRIBUTE, 'true');\n hostElement.appendChild(container);\n return container;\n}\n\n/**\n * container target の先頭に alert コンテナを取得または生成する。\n *\n * @param target 対象の要素。\n * @return 取得または生成したコンテナ。\n */\nfunction ensureBlockContainer(target: HTMLElement): HTMLElement {\n const existingContainer = getOwnedDirectChild(target);\n if (existingContainer) {\n return existingContainer;\n }\n\n const container = document.createElement('div');\n container.className = 'alert alert-danger';\n container.setAttribute('role', 'alert');\n container.setAttribute(OWNED_ATTRIBUTE, 'true');\n container.setAttribute(CONTAINER_ATTRIBUTE, 'true');\n target.insertAdjacentElement('afterbegin', container);\n return container;\n}\n\n/**\n * このライブラリが付けた is-invalid 状態だけを外す。\n *\n * @param target 状態を解除する要素。\n * @return 戻り値はない。\n */\nfunction removeOwnedInvalidState(target: HTMLElement): void {\n if (target.getAttribute(INVALID_TARGET_ATTRIBUTE) !== 'true') {\n return;\n }\n\n target.classList.remove('is-invalid');\n target.removeAttribute(INVALID_TARGET_ATTRIBUTE);\n}\n\n/**\n * choice input に対して、このライブラリが付けた invalid 状態を付与する。\n *\n * @param target 対象の input 要素。\n * @return 戻り値はない。\n */\nfunction markChoiceInvalidState(target: HTMLInputElement): void {\n const targets = isRadioInput(target) ? getRadioGroupTargets(target) : [target];\n targets.forEach((element) => {\n element.classList.add('is-invalid');\n element.setAttribute(INVALID_TARGET_ATTRIBUTE, 'true');\n });\n}\n\n/**\n * choice input に対して、このライブラリが付けた invalid 状態を解除する。\n *\n * @param target 対象の input 要素。\n * @return 戻り値はない。\n */\nfunction clearChoiceInvalidState(target: HTMLInputElement): void {\n const targets = isRadioInput(target) ? getRadioGroupTargets(target) : [target];\n targets.forEach((element) => {\n removeOwnedInvalidState(element);\n });\n}\n\n/**\n * 管理対象のエラーメッセージを追加する。\n *\n * @param target 追加先の要素。\n * @param message 表示するメッセージ。\n * @return 完了時に解決される Promise。\n */\nexport function addManagedErrorMessage(target: HTMLElement, message: string): Promise<void> {\n const container = isChoiceInput(target)\n ? ensureChoiceContainer(target)\n : isFieldTarget(target)\n ? ensureFieldContainer(target)\n : ensureBlockContainer(target);\n container.appendChild(createMessageItem(document, message));\n\n if (isChoiceInput(target)) {\n markChoiceInvalidState(target);\n } else if (isFieldTarget(target)) {\n target.classList.add('is-invalid');\n target.setAttribute(INVALID_TARGET_ATTRIBUTE, 'true');\n }\n\n return Promise.resolve();\n}\n\n/**\n * 管理対象のメッセージを削除する。\n *\n * @param parentOrTarget 削除対象の親要素または対象要素。\n * @return 完了時に解決される Promise。\n */\nexport function clearManagedMessages(parentOrTarget: HTMLElement): Promise<void> {\n if (isChoiceInput(parentOrTarget)) {\n const hostElement = isRadioInput(parentOrTarget)\n ? resolveRadioMessageHost(parentOrTarget)\n : resolveChoiceMessageHost(parentOrTarget);\n const ownedContainer = hostElement ? getDirectOwnedContainer(hostElement) : undefined;\n ownedContainer?.remove();\n clearChoiceInvalidState(parentOrTarget);\n } else if (isFieldTarget(parentOrTarget)) {\n const nextElement = parentOrTarget.nextElementSibling;\n if (\n nextElement instanceof HTMLElement &&\n nextElement.getAttribute(CONTAINER_ATTRIBUTE) === 'true'\n ) {\n nextElement.remove();\n }\n removeOwnedInvalidState(parentOrTarget);\n }\n\n const ownedContainers = parentOrTarget.querySelectorAll<HTMLElement>(\n `[${CONTAINER_ATTRIBUTE}=\"true\"]`,\n );\n ownedContainers.forEach((element) => {\n element.remove();\n });\n\n const invalidTargets = parentOrTarget.querySelectorAll<HTMLElement>(\n `[${INVALID_TARGET_ATTRIBUTE}=\"true\"]`,\n );\n invalidTargets.forEach((element) => {\n removeOwnedInvalidState(element);\n });\n\n return Promise.resolve();\n}\n","import { createModalInstance } from './bootstrap_resolver';\nimport type { ResolvedInstallOptions } from './types';\n\n/**\n * 既存要素を Bootstrap Modal として扱える最低限の属性へ整える。\n *\n * @param element 整形対象の要素。\n * @return 戻り値はない。\n */\nfunction prepareModalElement(element: HTMLElement): void {\n if (!element.classList.contains('modal')) {\n element.classList.add('modal');\n }\n\n if (element.tabIndex < 0) {\n element.tabIndex = -1;\n }\n\n if (!element.hasAttribute('aria-hidden')) {\n element.setAttribute('aria-hidden', 'true');\n }\n}\n\n/**\n * 任意要素を Bootstrap Modal として開く。\n *\n * @param element 開く対象の要素。\n * @param options 解決済み導入設定。\n * @return 完了時に解決される Promise。\n */\nexport function openDialogElement(\n element: HTMLElement,\n options: ResolvedInstallOptions,\n): Promise<void> {\n prepareModalElement(element);\n const modalInstance = createModalInstance(element, undefined, options.bootstrap);\n if (!modalInstance) {\n return Promise.reject(new Error('Bootstrap Modal is unavailable.'));\n }\n\n modalInstance.show();\n return Promise.resolve();\n}\n\n/**\n * 任意要素を Bootstrap Modal として閉じる。\n *\n * @param element 閉じる対象の要素。\n * @param options 解決済み導入設定。\n * @return 完了時に解決される Promise。\n */\nexport function closeDialogElement(\n element: HTMLElement,\n options: ResolvedInstallOptions,\n): Promise<void> {\n prepareModalElement(element);\n const modalInstance = createModalInstance(element, undefined, options.bootstrap);\n if (!modalInstance) {\n return Promise.reject(new Error('Bootstrap Modal is unavailable.'));\n }\n\n modalInstance.hide();\n return Promise.resolve();\n}\n","import { createToastInstance } from './bootstrap_resolver';\nimport type { ResolvedInstallOptions } from './types';\n\nconst TOAST_CONTAINER_ATTRIBUTE = 'data-haori-bootstrap-toast-container';\nconst TOAST_ATTRIBUTE = 'data-haori-bootstrap-toast';\nconst TOAST_ACCENT_ATTRIBUTE = 'data-haori-bootstrap-toast-accent';\n\ninterface ToastAppearance {\n accentClassName: string;\n}\n\n/**\n * 通知レベルを toast 表示用の見た目へ変換する。\n *\n * @param level 通知レベル。\n * @return 対応する見た目定義。\n */\nfunction resolveToastAppearance(level?: string): ToastAppearance {\n switch (level) {\n case 'warning':\n return { accentClassName: 'bg-warning' };\n case 'error':\n return { accentClassName: 'bg-danger' };\n default:\n return { accentClassName: 'bg-info' };\n }\n}\n\n/**\n * toast コンテナを配置する親要素を解決する。\n *\n * @param documentObject 検索に使用する document。\n * @param options 解決済み導入設定。\n * @return 配置先の要素。\n */\nfunction resolveToastRoot(documentObject: Document, options: ResolvedInstallOptions): HTMLElement {\n if (options.toastContainerSelector) {\n const resolvedElement = documentObject.querySelector<HTMLElement>(options.toastContainerSelector);\n if (resolvedElement) {\n return resolvedElement;\n }\n }\n\n return documentObject.body;\n}\n\n/**\n * toast コンテナを取得または生成する。\n *\n * @param documentObject 生成に使用する document。\n * @param options 解決済み導入設定。\n * @return 取得または生成したコンテナ。\n */\nfunction ensureToastContainer(documentObject: Document, options: ResolvedInstallOptions): HTMLElement {\n const rootElement = resolveToastRoot(documentObject, options);\n const existingContainer = rootElement.querySelector<HTMLElement>(\n `[${TOAST_CONTAINER_ATTRIBUTE}=\"true\"]`,\n );\n if (existingContainer) {\n return existingContainer;\n }\n\n const container = documentObject.createElement('div');\n container.className = 'toast-container position-fixed bottom-0 end-0 p-3';\n container.setAttribute(TOAST_CONTAINER_ATTRIBUTE, 'true');\n rootElement.appendChild(container);\n return container;\n}\n\n/**\n * Bootstrap Toast を表示する。\n *\n * @param message 表示するメッセージ。\n * @param level 通知レベル。\n * @param options 解決済み導入設定。\n * @return 完了時に解決される Promise。\n */\nexport function showToast(\n message: string,\n level: string | undefined,\n options: ResolvedInstallOptions,\n): Promise<void> {\n const documentObject = globalThis.document;\n const appearance = resolveToastAppearance(level);\n const toastElement = documentObject.createElement('div');\n toastElement.className = 'toast border bg-body text-body shadow-sm';\n toastElement.setAttribute('role', 'status');\n toastElement.setAttribute('aria-live', 'polite');\n toastElement.setAttribute('aria-atomic', 'true');\n toastElement.setAttribute(TOAST_ATTRIBUTE, 'true');\n\n const bodyWrapper = documentObject.createElement('div');\n bodyWrapper.className = 'd-flex align-items-stretch';\n\n const accentElement = documentObject.createElement('div');\n accentElement.className = `flex-shrink-0 rounded-start ${appearance.accentClassName}`;\n accentElement.style.width = '0.375rem';\n accentElement.setAttribute(TOAST_ACCENT_ATTRIBUTE, 'true');\n\n const bodyElement = documentObject.createElement('div');\n bodyElement.className = 'toast-body';\n bodyElement.style.whiteSpace = 'pre-line';\n bodyElement.textContent = message;\n\n bodyWrapper.appendChild(accentElement);\n bodyWrapper.appendChild(bodyElement);\n toastElement.appendChild(bodyWrapper);\n ensureToastContainer(documentObject, options).appendChild(toastElement);\n\n const toastInstance = createToastInstance(toastElement, options.bootstrap);\n if (!toastInstance) {\n toastElement.remove();\n return Promise.reject(new Error('Bootstrap Toast is unavailable.'));\n }\n\n toastElement.addEventListener(\n 'hidden.bs.toast',\n () => {\n toastElement.remove();\n toastInstance.dispose?.();\n },\n { once: true },\n );\n\n try {\n toastInstance.show();\n return Promise.resolve();\n } catch (error) {\n toastElement.remove();\n toastInstance.dispose?.();\n return Promise.reject(error);\n }\n}\n","import { hasModalSupport, hasToastSupport } from './bootstrap_resolver';\nimport { showConfirm, showDialog } from './dialog';\nimport { addManagedErrorMessage, clearManagedMessages } from './message';\nimport { closeDialogElement, openDialogElement } from './modal';\nimport { showToast } from './toast';\nimport type { HaoriGlobalObject, ResolvedInstallOptions } from './types';\n\n/**\n * BootstrapHaori が利用する内部コンテキスト。\n */\nexport interface BootstrapHaoriContext {\n /** 差し替え前の Haori 実装。 */\n originalHaori?: HaoriGlobalObject;\n /** 解決済みの導入設定。 */\n options: ResolvedInstallOptions;\n}\n\nconst defaultContext: BootstrapHaoriContext = {\n options: {\n fallbackToNative: true,\n },\n};\n\nlet context = defaultContext;\n\n/**\n * 表示用 message 中のエスケープ済み改行を実際の改行へ正規化する。\n *\n * @param message 正規化対象のメッセージ。\n * @return 正規化後のメッセージ。\n */\nfunction normalizeMessageText(message: string): string {\n return message.replace(/\\\\n/g, '\\n');\n}\n\n/**\n * 現在のブラウザ window を取得する。\n *\n * @return 現在の window。存在しない場合は undefined。\n */\nfunction getBrowserWindow(): Window | undefined {\n const scope = globalThis as typeof globalThis & { window?: Window };\n return scope.window;\n}\n\n/**\n * 値を Promise<void> 契約へ正規化する。\n *\n * @param value 正規化対象の値。\n * @return 完了時に解決される Promise。\n */\nfunction toPromiseVoid(value: Promise<void> | void | unknown): Promise<void> {\n return Promise.resolve(value).then(() => undefined);\n}\n\n/**\n * 元の Haori 実装から対象メソッドを取得する。\n *\n * @param methodName 取得対象のメソッド名。\n * @return 対象メソッド。見つからない場合は undefined。\n */\nfunction getOriginalMethod(\n methodName: keyof HaoriGlobalObject,\n): ((...args: readonly unknown[]) => unknown) | undefined {\n const method = context.originalHaori?.[methodName];\n return typeof method === 'function'\n ? (method as (...args: readonly unknown[]) => unknown)\n : undefined;\n}\n\n/**\n * no-op に正規化したことを警告する。\n *\n * @param apiName 利用できなかった API 名。\n * @return 戻り値はない。\n */\nfunction warnNoop(apiName: string): void {\n console.warn(`[haori-bootstrap] ${apiName} skipped because Bootstrap support is unavailable.`);\n}\n\n/**\n * dialog の fallback 経路を処理する。\n *\n * @param message 表示対象のメッセージ。\n * @return 完了時に解決される Promise。\n */\nfunction fallbackDialog(message: string): Promise<void> {\n const normalizedMessage = normalizeMessageText(message);\n const originalMethod = getOriginalMethod('dialog');\n if (originalMethod) {\n return toPromiseVoid(originalMethod(normalizedMessage));\n }\n\n const browserWindow = getBrowserWindow();\n if (context.options.fallbackToNative && typeof browserWindow?.alert === 'function') {\n browserWindow.alert(normalizedMessage);\n return Promise.resolve();\n }\n\n warnNoop('dialog');\n return Promise.resolve();\n}\n\n/**\n * confirm の fallback 経路を処理する。\n *\n * @param message 表示対象のメッセージ。\n * @return 確認結果を返す Promise。\n */\nfunction fallbackConfirm(message: string): Promise<boolean> {\n const normalizedMessage = normalizeMessageText(message);\n const originalMethod = getOriginalMethod('confirm');\n if (originalMethod) {\n return Promise.resolve(originalMethod(normalizedMessage) as Promise<boolean> | boolean).then(\n (value) => Boolean(value),\n );\n }\n\n const browserWindow = getBrowserWindow();\n if (context.options.fallbackToNative && typeof browserWindow?.confirm === 'function') {\n return Promise.resolve(browserWindow.confirm(normalizedMessage));\n }\n\n warnNoop('confirm');\n return Promise.resolve(false);\n}\n\n/**\n * toast の fallback 経路を処理する。\n *\n * @param message 表示対象のメッセージ。\n * @param level 通知レベル。\n * @return 完了時に解決される Promise。\n */\nfunction fallbackToast(message: string, level?: string): Promise<void> {\n const normalizedMessage = normalizeMessageText(message);\n const originalMethod = getOriginalMethod('toast');\n if (originalMethod) {\n return toPromiseVoid(originalMethod(normalizedMessage, level));\n }\n\n warnNoop('toast');\n return Promise.resolve();\n}\n\n/**\n * openDialog または closeDialog の fallback 経路を処理する。\n *\n * @param methodName 呼び出す API 名。\n * @param element 対象要素。\n * @return 完了時に解決される Promise。\n */\nfunction fallbackModal(methodName: 'openDialog' | 'closeDialog', element: HTMLElement): Promise<void> {\n const originalMethod = getOriginalMethod(methodName);\n if (originalMethod) {\n return toPromiseVoid(originalMethod(element));\n }\n\n warnNoop(methodName);\n return Promise.resolve();\n}\n\n/**\n * BootstrapHaori が参照する内部状態を更新する。\n *\n * @param nextContext 差し替え先が参照する内部コンテキスト。\n * @return 戻り値はない。\n */\nexport function setBootstrapHaoriContext(nextContext: BootstrapHaoriContext): void {\n context = nextContext;\n}\n\n/**\n * Haori の UI 系静的メソッドを差し替える最小ファサード。\n */\nexport class BootstrapHaori {\n /**\n * 情報表示ダイアログを表示する。\n *\n * @param message 表示するメッセージ。\n * @return 完了時に解決される Promise。\n */\n public static dialog(message: string): Promise<void> {\n const normalizedMessage = normalizeMessageText(message);\n if (hasModalSupport(context.options.bootstrap)) {\n return showDialog(normalizedMessage, context.options).catch(() => fallbackDialog(normalizedMessage));\n }\n\n return fallbackDialog(normalizedMessage);\n }\n\n /**\n * 確認ダイアログを表示する。\n *\n * @param message 表示するメッセージ。\n * @return OK のみ true を返す Promise。\n */\n public static confirm(message: string): Promise<boolean> {\n const normalizedMessage = normalizeMessageText(message);\n if (hasModalSupport(context.options.bootstrap)) {\n return showConfirm(normalizedMessage, context.options).catch(() => fallbackConfirm(normalizedMessage));\n }\n\n return fallbackConfirm(normalizedMessage);\n }\n\n /**\n * トースト通知を表示する。\n *\n * @param message 表示するメッセージ。\n * @param level 通知レベル。\n * @return 完了時に解決される Promise。\n */\n public static toast(message: string, level?: string): Promise<void> {\n const normalizedMessage = normalizeMessageText(message);\n if (hasToastSupport(context.options.bootstrap)) {\n return showToast(normalizedMessage, level, context.options).catch(() =>\n fallbackToast(normalizedMessage, level),\n );\n }\n\n return fallbackToast(normalizedMessage, level);\n }\n\n /**\n * 任意のダイアログ要素を開く。\n *\n * @param element 開く対象の要素。\n * @return 完了時に解決される Promise。\n */\n public static openDialog(element: HTMLElement): Promise<void> {\n if (hasModalSupport(context.options.bootstrap)) {\n return openDialogElement(element, context.options).catch(() =>\n fallbackModal('openDialog', element),\n );\n }\n\n return fallbackModal('openDialog', element);\n }\n\n /**\n * 任意のダイアログ要素を閉じる。\n *\n * @param element 閉じる対象の要素。\n * @return 完了時に解決される Promise。\n */\n public static closeDialog(element: HTMLElement): Promise<void> {\n if (hasModalSupport(context.options.bootstrap)) {\n return closeDialogElement(element, context.options).catch(() =>\n fallbackModal('closeDialog', element),\n );\n }\n\n return fallbackModal('closeDialog', element);\n }\n\n /**\n * 管理対象のエラーメッセージを追加する。\n *\n * @param target 追加先の要素。\n * @param message 表示するメッセージ。\n * @return 完了時に解決される Promise。\n */\n public static addErrorMessage(target: HTMLElement, message: string): Promise<void> {\n return addManagedErrorMessage(target, message);\n }\n\n /**\n * 管理対象のメッセージを削除する。\n *\n * @param parentOrTarget 削除対象の親要素または対象要素。\n * @return 完了時に解決される Promise。\n */\n public static clearMessages(parentOrTarget: HTMLElement): Promise<void> {\n return clearManagedMessages(parentOrTarget);\n }\n}\n","import { BootstrapHaori, setBootstrapHaoriContext } from './bootstrap_haori';\nimport type {\n BrowserWindow,\n HaoriGlobalObject,\n InstallOptions,\n ResolvedInstallOptions,\n} from './types';\n\nconst DEFAULT_INSTALL_OPTIONS: ResolvedInstallOptions = {\n fallbackToNative: true,\n};\n\nconst installState: {\n installed: boolean;\n originalHaori?: HaoriGlobalObject;\n options: ResolvedInstallOptions;\n} = {\n installed: false,\n options: DEFAULT_INSTALL_OPTIONS,\n};\n\n/**\n * 現在のブラウザ window を取得する。\n *\n * @return 現在の window。存在しない場合は undefined。\n */\nfunction getBrowserWindow(): BrowserWindow | undefined {\n const scope = globalThis as typeof globalThis & { window?: BrowserWindow };\n return scope.window;\n}\n\n/**\n * install に渡された設定を既定値込みで解決する。\n *\n * @param options 指定された導入設定。\n * @param browserWindow 現在の window。\n * @return 解決済みの導入設定。\n */\nfunction resolveInstallOptions(\n options: InstallOptions,\n browserWindow: BrowserWindow | undefined,\n): ResolvedInstallOptions {\n return {\n bootstrap: options.bootstrap ?? browserWindow?.bootstrap,\n fallbackToNative: options.fallbackToNative ?? DEFAULT_INSTALL_OPTIONS.fallbackToNative,\n toastContainerSelector: options.toastContainerSelector,\n dialogContainerSelector: options.dialogContainerSelector,\n };\n}\n\n/**\n * 自動有効化に必要な前提が揃っているかを返す。\n *\n * @param browserWindow 判定対象の window。\n * @return 自動有効化可能なら true。\n */\nexport function hasAutoEnablePrerequisites(\n browserWindow: BrowserWindow | undefined = getBrowserWindow(),\n): boolean {\n return Boolean(browserWindow?.Haori && browserWindow.bootstrap);\n}\n\n/**\n * Bootstrap 対応 Haori を再適用し、必要なら設定を上書きする。\n *\n * @param options 上書きする導入設定。\n * @return 戻り値はない。\n */\nexport function install(options: InstallOptions = {}): void {\n const browserWindow = getBrowserWindow();\n if (!browserWindow?.Haori) {\n throw new Error('window.Haori is required before calling install().');\n }\n\n if (!installState.originalHaori) {\n installState.originalHaori = browserWindow.Haori;\n }\n\n installState.options = resolveInstallOptions(options, browserWindow);\n setBootstrapHaoriContext({\n originalHaori: installState.originalHaori,\n options: installState.options,\n });\n browserWindow.Haori = BootstrapHaori as unknown as HaoriGlobalObject;\n installState.installed = true;\n}\n\n/**\n * 元の Haori 実装を復元する。\n *\n * @return 戻り値はない。\n */\nexport function uninstall(): void {\n const browserWindow = getBrowserWindow();\n if (!browserWindow || !installState.originalHaori) {\n return;\n }\n\n browserWindow.Haori = installState.originalHaori;\n installState.installed = false;\n installState.originalHaori = undefined;\n}\n\n/**\n * 現在 BootstrapHaori が有効かどうかを返す。\n *\n * @return 有効なら true。\n */\nexport function isInstalled(): boolean {\n return installState.installed;\n}\n","import { hasAutoEnablePrerequisites, install } from './install';\nimport type { BrowserWindow } from './types';\n\nconst AUTO_ENABLE_MARKER = '__haoriJsBootstrapAutoEnabled__';\n\n/**\n * 現在のブラウザ window を取得する。\n *\n * @return 現在の window。存在しない場合は undefined。\n */\nfunction getBrowserWindow(): BrowserWindow | undefined {\n const scope = globalThis as typeof globalThis & { window?: BrowserWindow };\n return scope.window;\n}\n\n/**\n * 既に自動有効化済みかどうかを返す。\n *\n * @param browserWindow 判定対象の window。\n * @return 既に自動有効化済みなら true。\n */\nfunction wasAutoEnabled(browserWindow: BrowserWindow): boolean {\n return Boolean((browserWindow as unknown as Record<string, unknown>)[AUTO_ENABLE_MARKER]);\n}\n\n/**\n * 自動有効化済みの印を付ける。\n *\n * @param browserWindow 更新対象の window。\n * @return 戻り値はない。\n */\nfunction markAutoEnabled(browserWindow: BrowserWindow): void {\n (browserWindow as unknown as Record<string, unknown>)[AUTO_ENABLE_MARKER] = true;\n}\n\n/**\n * 前提が揃っていれば自動有効化を試行する。\n *\n * @return 戻り値はない。\n */\nfunction autoEnable(): void {\n const browserWindow = getBrowserWindow();\n if (!browserWindow || wasAutoEnabled(browserWindow)) {\n return;\n }\n\n if (!hasAutoEnablePrerequisites(browserWindow)) {\n console.warn(\n '[haori-bootstrap] Auto-enable skipped because window.Haori or window.bootstrap is missing.',\n );\n return;\n }\n\n try {\n install({ bootstrap: browserWindow.bootstrap });\n markAutoEnabled(browserWindow);\n } catch (error) {\n console.warn('[haori-bootstrap] Auto-enable failed.', error);\n }\n}\n\nautoEnable();\n","import './browser';\n\nexport { BootstrapHaori } from './bootstrap_haori';\nexport { hasAutoEnablePrerequisites, install, isInstalled, uninstall } from './install';\nexport type {\n BootstrapNamespace,\n BrowserWindow,\n HaoriBootstrapGlobal,\n HaoriGlobalObject,\n InstallOptions,\n ResolvedInstallOptions,\n} from './types';\n\n/**\n * パッケージの公開版数。\n */\nexport const version = '0.2.0';\n"],"names":["isConstructor","value","resolveModalConstructor","bootstrap","resolveToastConstructor","hasModalSupport","hasToastSupport","createModalInstance","element","options","modalConstructor","createToastInstance","toastConstructor","DIALOG_CONTAINER_ATTRIBUTE","ACTION_ATTRIBUTE","createDialogModalOptions","resolveDialogContainer","documentObject","resolvedElement","createModalShell","message","isConfirm","modalElement","dialogElement","contentElement","bodyElement","messageElement","footerElement","cancelButton","okButton","showDialog","modalInstance","resolve","reject","finalize","handleHidden","error","showConfirm","confirmed","OWNED_ATTRIBUTE","CONTAINER_ATTRIBUTE","INVALID_TARGET_ATTRIBUTE","isChoiceInput","target","isRadioInput","isFieldTarget","getDirectOwnedContainer","createMessageItem","getOwnedDirectChild","getRadioGroupTargets","rootNode","escapedName","groupTargets","findCommonAncestor","elements","firstElement","restElements","candidate","resolveRadioMessageHost","wrappers","commonAncestor","resolveChoiceMessageHost","closestFormCheck","ensureFieldContainer","nextElement","container","ensureChoiceContainer","hostElement","existingContainer","ensureBlockContainer","removeOwnedInvalidState","markChoiceInvalidState","clearChoiceInvalidState","addManagedErrorMessage","clearManagedMessages","parentOrTarget","prepareModalElement","openDialogElement","closeDialogElement","TOAST_CONTAINER_ATTRIBUTE","TOAST_ATTRIBUTE","TOAST_ACCENT_ATTRIBUTE","resolveToastAppearance","level","resolveToastRoot","ensureToastContainer","rootElement","showToast","appearance","toastElement","bodyWrapper","accentElement","toastInstance","defaultContext","context","normalizeMessageText","getBrowserWindow","toPromiseVoid","getOriginalMethod","methodName","method","warnNoop","apiName","fallbackDialog","normalizedMessage","originalMethod","browserWindow","fallbackConfirm","fallbackToast","fallbackModal","setBootstrapHaoriContext","nextContext","BootstrapHaori","DEFAULT_INSTALL_OPTIONS","installState","resolveInstallOptions","hasAutoEnablePrerequisites","install","uninstall","isInstalled","AUTO_ENABLE_MARKER","wasAutoEnabled","markAutoEnabled","autoEnable","version"],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { BootstrapHaori } from './bootstrap_haori';
|
|
2
|
+
export { hasAutoEnablePrerequisites, install, isInstalled, uninstall } from './install';
|
|
3
|
+
export type { BootstrapNamespace, BrowserWindow, HaoriBootstrapGlobal, HaoriGlobalObject, InstallOptions, ResolvedInstallOptions, } from './types';
|
|
4
|
+
/**
|
|
5
|
+
* パッケージの公開版数。
|
|
6
|
+
*/
|
|
7
|
+
export declare const version = "0.2.0";
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { BrowserWindow, InstallOptions } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* 自動有効化に必要な前提が揃っているかを返す。
|
|
4
|
+
*
|
|
5
|
+
* @param browserWindow 判定対象の window。
|
|
6
|
+
* @return 自動有効化可能なら true。
|
|
7
|
+
*/
|
|
8
|
+
export declare function hasAutoEnablePrerequisites(browserWindow?: BrowserWindow | undefined): boolean;
|
|
9
|
+
/**
|
|
10
|
+
* Bootstrap 対応 Haori を再適用し、必要なら設定を上書きする。
|
|
11
|
+
*
|
|
12
|
+
* @param options 上書きする導入設定。
|
|
13
|
+
* @return 戻り値はない。
|
|
14
|
+
*/
|
|
15
|
+
export declare function install(options?: InstallOptions): void;
|
|
16
|
+
/**
|
|
17
|
+
* 元の Haori 実装を復元する。
|
|
18
|
+
*
|
|
19
|
+
* @return 戻り値はない。
|
|
20
|
+
*/
|
|
21
|
+
export declare function uninstall(): void;
|
|
22
|
+
/**
|
|
23
|
+
* 現在 BootstrapHaori が有効かどうかを返す。
|
|
24
|
+
*
|
|
25
|
+
* @return 有効なら true。
|
|
26
|
+
*/
|
|
27
|
+
export declare function isInstalled(): boolean;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 管理対象のエラーメッセージを追加する。
|
|
3
|
+
*
|
|
4
|
+
* @param target 追加先の要素。
|
|
5
|
+
* @param message 表示するメッセージ。
|
|
6
|
+
* @return 完了時に解決される Promise。
|
|
7
|
+
*/
|
|
8
|
+
export declare function addManagedErrorMessage(target: HTMLElement, message: string): Promise<void>;
|
|
9
|
+
/**
|
|
10
|
+
* 管理対象のメッセージを削除する。
|
|
11
|
+
*
|
|
12
|
+
* @param parentOrTarget 削除対象の親要素または対象要素。
|
|
13
|
+
* @return 完了時に解決される Promise。
|
|
14
|
+
*/
|
|
15
|
+
export declare function clearManagedMessages(parentOrTarget: HTMLElement): Promise<void>;
|
package/dist/modal.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { ResolvedInstallOptions } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* 任意要素を Bootstrap Modal として開く。
|
|
4
|
+
*
|
|
5
|
+
* @param element 開く対象の要素。
|
|
6
|
+
* @param options 解決済み導入設定。
|
|
7
|
+
* @return 完了時に解決される Promise。
|
|
8
|
+
*/
|
|
9
|
+
export declare function openDialogElement(element: HTMLElement, options: ResolvedInstallOptions): Promise<void>;
|
|
10
|
+
/**
|
|
11
|
+
* 任意要素を Bootstrap Modal として閉じる。
|
|
12
|
+
*
|
|
13
|
+
* @param element 閉じる対象の要素。
|
|
14
|
+
* @param options 解決済み導入設定。
|
|
15
|
+
* @return 完了時に解決される Promise。
|
|
16
|
+
*/
|
|
17
|
+
export declare function closeDialogElement(element: HTMLElement, options: ResolvedInstallOptions): Promise<void>;
|
package/dist/toast.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { ResolvedInstallOptions } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Bootstrap Toast を表示する。
|
|
4
|
+
*
|
|
5
|
+
* @param message 表示するメッセージ。
|
|
6
|
+
* @param level 通知レベル。
|
|
7
|
+
* @param options 解決済み導入設定。
|
|
8
|
+
* @return 完了時に解決される Promise。
|
|
9
|
+
*/
|
|
10
|
+
export declare function showToast(message: string, level: string | undefined, options: ResolvedInstallOptions): Promise<void>;
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bootstrap Modal インスタンスの最小契約。
|
|
3
|
+
*/
|
|
4
|
+
export interface BootstrapModalInstance {
|
|
5
|
+
/** Modal を表示する。 */
|
|
6
|
+
show: () => void;
|
|
7
|
+
/** Modal を閉じる。 */
|
|
8
|
+
hide: () => void;
|
|
9
|
+
/** 後始末を行う。 */
|
|
10
|
+
dispose?: () => void;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Bootstrap Modal の最小設定。
|
|
14
|
+
*/
|
|
15
|
+
export interface BootstrapModalOptions {
|
|
16
|
+
/** backdrop click を無効化して backdrop 自体は表示する。 */
|
|
17
|
+
backdrop?: 'static' | boolean;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Bootstrap Toast インスタンスの最小契約。
|
|
21
|
+
*/
|
|
22
|
+
export interface BootstrapToastInstance {
|
|
23
|
+
/** Toast を表示する。 */
|
|
24
|
+
show: () => void;
|
|
25
|
+
/** 後始末を行う。 */
|
|
26
|
+
dispose?: () => void;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Bootstrap Modal コンストラクターの最小契約。
|
|
30
|
+
*/
|
|
31
|
+
export interface BootstrapModalConstructor {
|
|
32
|
+
/**
|
|
33
|
+
* Modal インスタンスを生成する。
|
|
34
|
+
*
|
|
35
|
+
* @param element 対象要素。
|
|
36
|
+
* @param options Modal 設定。
|
|
37
|
+
*/
|
|
38
|
+
new (element: Element, options?: BootstrapModalOptions): BootstrapModalInstance;
|
|
39
|
+
/**
|
|
40
|
+
* Modal インスタンスを取得または生成する。
|
|
41
|
+
*
|
|
42
|
+
* @param element 対象要素。
|
|
43
|
+
* @param options Modal 設定。
|
|
44
|
+
* @return Modal インスタンス。
|
|
45
|
+
*/
|
|
46
|
+
getOrCreateInstance?: (element: Element, options?: BootstrapModalOptions) => BootstrapModalInstance;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Bootstrap Toast コンストラクターの最小契約。
|
|
50
|
+
*/
|
|
51
|
+
export interface BootstrapToastConstructor {
|
|
52
|
+
/**
|
|
53
|
+
* Toast インスタンスを生成する。
|
|
54
|
+
*
|
|
55
|
+
* @param element 対象要素。
|
|
56
|
+
*/
|
|
57
|
+
new (element: Element): BootstrapToastInstance;
|
|
58
|
+
/**
|
|
59
|
+
* Toast インスタンスを取得または生成する。
|
|
60
|
+
*
|
|
61
|
+
* @param element 対象要素。
|
|
62
|
+
* @return Toast インスタンス。
|
|
63
|
+
*/
|
|
64
|
+
getOrCreateInstance?: (element: Element) => BootstrapToastInstance;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Bootstrap 名前空間の最小契約。
|
|
68
|
+
*/
|
|
69
|
+
export interface BootstrapNamespace {
|
|
70
|
+
Modal?: BootstrapModalConstructor;
|
|
71
|
+
Toast?: BootstrapToastConstructor;
|
|
72
|
+
[key: string]: unknown;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Haori.js Bootstrap の導入設定。
|
|
76
|
+
*/
|
|
77
|
+
export interface InstallOptions {
|
|
78
|
+
/** Bootstrap 名前空間を明示的に渡す。 */
|
|
79
|
+
bootstrap?: BootstrapNamespace;
|
|
80
|
+
/** Bootstrap 利用不可時に元の Haori へ委譲するか。 */
|
|
81
|
+
fallbackToNative?: boolean;
|
|
82
|
+
/** Toast 配置先セレクター。 */
|
|
83
|
+
toastContainerSelector?: string;
|
|
84
|
+
/** Dialog 配置先セレクター。 */
|
|
85
|
+
dialogContainerSelector?: string;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* 内部で解決済みの導入設定。
|
|
89
|
+
*/
|
|
90
|
+
export interface ResolvedInstallOptions {
|
|
91
|
+
/** Bootstrap 名前空間。 */
|
|
92
|
+
bootstrap?: BootstrapNamespace;
|
|
93
|
+
/** Bootstrap 利用不可時に元の Haori へ委譲するか。 */
|
|
94
|
+
fallbackToNative: boolean;
|
|
95
|
+
/** Toast 配置先セレクター。 */
|
|
96
|
+
toastContainerSelector?: string;
|
|
97
|
+
/** Dialog 配置先セレクター。 */
|
|
98
|
+
dialogContainerSelector?: string;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Haori の静的メソッド群に対する最小契約。
|
|
102
|
+
*/
|
|
103
|
+
export interface HaoriGlobalObject {
|
|
104
|
+
[key: string]: unknown;
|
|
105
|
+
dialog?: (message: string) => Promise<void> | void;
|
|
106
|
+
confirm?: (message: string) => Promise<boolean> | boolean;
|
|
107
|
+
toast?: (message: string, level?: string) => Promise<void> | void;
|
|
108
|
+
openDialog?: (element: HTMLElement) => Promise<void> | void;
|
|
109
|
+
closeDialog?: (element: HTMLElement) => Promise<void> | void;
|
|
110
|
+
addErrorMessage?: (target: HTMLElement, message: string) => Promise<void> | void;
|
|
111
|
+
clearMessages?: (parentOrTarget: HTMLElement) => Promise<void> | void;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* ブラウザ環境で利用する window の拡張契約。
|
|
115
|
+
*/
|
|
116
|
+
export interface BrowserWindow extends Window {
|
|
117
|
+
Haori?: HaoriGlobalObject;
|
|
118
|
+
bootstrap?: BootstrapNamespace;
|
|
119
|
+
HaoriBootstrap?: HaoriBootstrapGlobal;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* IIFE 版で補助公開されるグローバル API。
|
|
123
|
+
*/
|
|
124
|
+
export interface HaoriBootstrapGlobal {
|
|
125
|
+
/**
|
|
126
|
+
* Bootstrap 対応 Haori を再適用する。
|
|
127
|
+
*
|
|
128
|
+
* @param options 上書きする導入設定。
|
|
129
|
+
* @return 戻り値はない。
|
|
130
|
+
*/
|
|
131
|
+
install: (options?: InstallOptions) => void;
|
|
132
|
+
/**
|
|
133
|
+
* 元の Haori 実装を復元する。
|
|
134
|
+
*
|
|
135
|
+
* @return 戻り値はない。
|
|
136
|
+
*/
|
|
137
|
+
uninstall: () => void;
|
|
138
|
+
/** パッケージ版数。 */
|
|
139
|
+
version: string;
|
|
140
|
+
}
|
|
141
|
+
declare global {
|
|
142
|
+
interface Window {
|
|
143
|
+
Haori?: HaoriGlobalObject;
|
|
144
|
+
bootstrap?: BootstrapNamespace;
|
|
145
|
+
HaoriBootstrap?: HaoriBootstrapGlobal;
|
|
146
|
+
}
|
|
147
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "haori-bootstrap",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Bootstrap-based UI extension library for Haori.js.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/haori-bootstrap.js",
|
|
7
|
+
"module": "./dist/haori-bootstrap.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/haori-bootstrap.js",
|
|
13
|
+
"default": "./dist/haori-bootstrap.js"
|
|
14
|
+
},
|
|
15
|
+
"./package.json": "./package.json"
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"dist"
|
|
19
|
+
],
|
|
20
|
+
"scripts": {
|
|
21
|
+
"dev": "vite",
|
|
22
|
+
"build": "vite build",
|
|
23
|
+
"predev:demo": "npm run build",
|
|
24
|
+
"dev:demo": "vite --config demo/vite.config.ts",
|
|
25
|
+
"prebuild:demo": "npm run build",
|
|
26
|
+
"build:demo": "vite build --config demo/vite.config.ts",
|
|
27
|
+
"prepreview:demo": "npm run build:demo",
|
|
28
|
+
"preview:demo": "vite preview --config demo/vite.config.ts",
|
|
29
|
+
"test": "vitest run",
|
|
30
|
+
"pretest:e2e": "npm run build",
|
|
31
|
+
"test:e2e": "playwright test",
|
|
32
|
+
"pretest:e2e:headed": "npm run build",
|
|
33
|
+
"test:e2e:headed": "playwright test --headed",
|
|
34
|
+
"test:watch": "vitest",
|
|
35
|
+
"lint": "eslint .",
|
|
36
|
+
"lint:fix": "eslint . --fix",
|
|
37
|
+
"format": "prettier --write \"{src,tests,demo}/**/*.{ts,js,json,html}\"",
|
|
38
|
+
"format:check": "prettier --check \"{src,tests,demo}/**/*.{ts,js,json,html}\"",
|
|
39
|
+
"type-check": "tsc --noEmit",
|
|
40
|
+
"compile": "npm run type-check",
|
|
41
|
+
"version": "node ./scripts/sync-version.mjs && git add src/index.ts package.json package-lock.json",
|
|
42
|
+
"preview": "vite preview"
|
|
43
|
+
},
|
|
44
|
+
"repository": {
|
|
45
|
+
"type": "git",
|
|
46
|
+
"url": "git+https://github.com/meibinlab/haori-js-bootstrap.git"
|
|
47
|
+
},
|
|
48
|
+
"keywords": [
|
|
49
|
+
"haori",
|
|
50
|
+
"bootstrap",
|
|
51
|
+
"ui-extension",
|
|
52
|
+
"frontend"
|
|
53
|
+
],
|
|
54
|
+
"author": "meibinlab",
|
|
55
|
+
"license": "MIT",
|
|
56
|
+
"bugs": {
|
|
57
|
+
"url": "https://github.com/meibinlab/haori-js-bootstrap/issues"
|
|
58
|
+
},
|
|
59
|
+
"homepage": "https://github.com/meibinlab/haori-js-bootstrap#readme",
|
|
60
|
+
"devDependencies": {
|
|
61
|
+
"@playwright/test": "^1.54.1",
|
|
62
|
+
"@eslint/js": "^9.31.0",
|
|
63
|
+
"@types/node": "^22.7.5",
|
|
64
|
+
"eslint": "^9.31.0",
|
|
65
|
+
"globals": "^15.9.0",
|
|
66
|
+
"jsdom": "^26.1.0",
|
|
67
|
+
"prettier": "^3.6.2",
|
|
68
|
+
"typescript": "^5.6.3",
|
|
69
|
+
"typescript-eslint": "^8.37.0",
|
|
70
|
+
"vite": "^7.0.4",
|
|
71
|
+
"vite-plugin-dts": "^4.5.4",
|
|
72
|
+
"vitest": "^3.2.4"
|
|
73
|
+
}
|
|
74
|
+
}
|