@ablogcms/tab 3.2.28-beta.0 → 3.2.29

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/dist/index.mjs CHANGED
@@ -251,45 +251,42 @@ var Tab = class _Tab {
251
251
  };
252
252
 
253
253
  // src/tab-manager.ts
254
+ import domReady from "@ablogcms/dom-ready";
254
255
  var TabManager = class _TabManager {
255
256
  static instance = null;
256
- tabRepository = /* @__PURE__ */ new Map();
257
257
  static getInstance() {
258
258
  if (!_TabManager.instance) {
259
259
  _TabManager.instance = new _TabManager();
260
260
  }
261
261
  return _TabManager.instance;
262
262
  }
263
+ /**
264
+ * 指定コンテキスト内のタブ要素にTabインスタンスを登録する。
265
+ * 呼び出し元は戻り値の要素一覧を保持しておき、destroy() に渡すことで
266
+ * 自分が登録した要素だけを後片付けできる(他の呼び出し元の登録には影響しない)。
267
+ */
263
268
  async apply(selector, options = {}, context = document) {
264
269
  const tabOptions = {
265
270
  tabList: selector,
266
271
  ...options
267
272
  };
268
- ACMS.Loaded(() => {
269
- context.querySelectorAll(SELECTOR_TAB).forEach((element) => {
270
- if (element.closest(selector) !== null) {
271
- Tab.getOrCreateInstance(element, tabOptions);
272
- this.tabRepository.set(selector, [...this.tabRepository.get(selector) || [], element]);
273
- }
273
+ return new Promise((resolve) => {
274
+ domReady(() => {
275
+ const applied = [];
276
+ context.querySelectorAll(SELECTOR_TAB).forEach((element) => {
277
+ if (element.closest(selector) !== null) {
278
+ Tab.getOrCreateInstance(element, tabOptions);
279
+ applied.push(element);
280
+ }
281
+ });
282
+ resolve(applied);
274
283
  });
275
284
  });
276
285
  }
277
- destroy(selector) {
278
- const elements = this.tabRepository.get(selector);
279
- if (elements) {
280
- elements.forEach((element) => {
281
- Tab.getOrCreateInstance(element).destroy();
282
- });
283
- this.tabRepository.delete(selector);
284
- }
285
- }
286
- destroyAll() {
287
- for (const [, elements] of this.tabRepository) {
288
- elements.forEach((element) => {
289
- Tab.getOrCreateInstance(element).destroy();
290
- });
291
- }
292
- this.tabRepository.clear();
286
+ destroy(elements) {
287
+ elements.forEach((element) => {
288
+ Tab.getOrCreateInstance(element).destroy();
289
+ });
293
290
  }
294
291
  };
295
292
  export {
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/tab.ts","../src/tab-manager.ts"],"sourcesContent":["import { getNextActiveElement, getSelector, isDisabled, hide, show } from '@ablogcms/utils/dom';\n\nconst ARROW_LEFT_KEY = 'ArrowLeft';\nconst ARROW_RIGHT_KEY = 'ArrowRight';\nconst ARROW_UP_KEY = 'ArrowUp';\nconst ARROW_DOWN_KEY = 'ArrowDown';\nconst HOME_KEY = 'Home';\nconst END_KEY = 'End';\n\nconst SELECTOR_OUTER = 'li';\nexport const SELECTOR_TAB = 'a[href^=\"#\"], [role=\"tab\"]';\n\nexport interface TabOptions {\n tabList: string | HTMLElement;\n tabClass: string;\n activeClass: string;\n readyMark: string;\n enableHashNavigation: boolean;\n onShow: ({ tab, panel }: { tab: HTMLElement; panel: HTMLElement | null }) => void;\n onHide: ({ tab, panel }: { tab: HTMLElement; panel: HTMLElement | null }) => void;\n}\n\nexport const defaultOptions: TabOptions = {\n tabList: '.js-acms_admin_tabs',\n tabClass: 'js-acms_tab',\n activeClass: 'js-acms_tab-active',\n readyMark: '.js-ready-acms_tabs',\n enableHashNavigation: false,\n onShow: () => {},\n onHide: () => {},\n};\n\ntype TabElement = HTMLElement & { Tab?: Tab };\n\nexport default class Tab {\n private _element: TabElement;\n\n private _tabList: HTMLElement;\n\n private _options: TabOptions;\n\n private eventRegistry: Map<\n Element | Document,\n Array<{\n type: string;\n listener: EventListener;\n options?: AddEventListenerOptions;\n }>\n > = new Map();\n\n constructor(element: TabElement, options: Partial<TabOptions> = {}) {\n this._options = { ...defaultOptions, ...options };\n this._element = element;\n const tabList =\n this._options.tabList instanceof HTMLElement\n ? this._options.tabList\n : this._element.closest<HTMLElement>(this._options.tabList);\n\n if (!tabList) {\n throw new TypeError(`${element.outerHTML} has not a valid parent ${this._options.tabList}`);\n }\n\n this._tabList = tabList;\n\n const tabs = this._getTabs();\n // Set up initial aria attributes\n this._setInitialAttributes(this._tabList, tabs);\n this._keydown = this._keydown.bind(this);\n this._click = this._click.bind(this);\n this._element.addEventListener('click', this._click);\n this._element.addEventListener('keydown', this._keydown);\n this.eventRegistry.set(this._element, [\n {\n type: 'click',\n listener: this._click as EventListener,\n },\n {\n type: 'keydown',\n listener: this._keydown as EventListener,\n },\n ]);\n }\n\n public destroy() {\n delete this._element.Tab;\n for (const [eventTarget, listeners] of this.eventRegistry) {\n listeners.forEach(({ type, listener, options }) => {\n eventTarget.removeEventListener(type, listener, options);\n });\n }\n this.eventRegistry.clear();\n }\n\n // Public\n public show() {\n // Shows this elem and deactivate the active sibling if exists\n const tab = this._element;\n if (this._tabIsActive(tab)) {\n return;\n }\n\n // Search for active tab on same parent to deactivate it\n const activeTab = this._getActiveTab();\n\n if (activeTab) {\n this._deactivate(activeTab);\n }\n\n this._activate(tab);\n const panel = this._getTargetPanel(tab);\n if (this._enableHashNavigation() && panel && `#${panel.id}` !== location.hash) {\n const hash = panel.id;\n if ('history' in window) {\n history.replaceState(null, '', `#${hash}`);\n }\n panel.id = hash;\n }\n }\n\n public get options(): TabOptions {\n return this._options;\n }\n\n // Private\n private _activate(tab: HTMLElement) {\n const panel = this._getTargetPanel(tab);\n\n tab.classList.add(this._options.activeClass);\n\n if (panel !== null) {\n show(panel);\n panel.setAttribute('aria-hidden', 'false');\n }\n\n tab.removeAttribute('tabindex');\n tab.setAttribute('aria-selected', 'true');\n\n this._options.onShow({ tab, panel });\n }\n\n private _deactivate(tab: HTMLElement) {\n const panel = this._getTargetPanel(tab);\n\n tab.classList.remove(this._options.activeClass);\n tab.blur();\n\n if (panel !== null) {\n hide(panel);\n panel.setAttribute('aria-hidden', 'true');\n }\n\n tab.setAttribute('aria-selected', 'false');\n tab.setAttribute('tabindex', '-1');\n\n this._options.onHide({ tab, panel });\n }\n\n private _click(event: MouseEvent) {\n const { currentTarget } = event;\n if (!(currentTarget instanceof HTMLElement)) {\n return;\n }\n\n if (['A', 'AREA'].includes(currentTarget.tagName)) {\n event.preventDefault();\n }\n\n if (isDisabled(currentTarget)) {\n return;\n }\n\n Tab.getOrCreateInstance(currentTarget).show();\n }\n\n private _keydown(event: KeyboardEvent) {\n if (![ARROW_LEFT_KEY, ARROW_RIGHT_KEY, ARROW_UP_KEY, ARROW_DOWN_KEY, HOME_KEY, END_KEY].includes(event.key)) {\n return;\n }\n\n if (!(event.target instanceof HTMLElement)) {\n return;\n }\n\n event.stopPropagation(); // stopPropagation/preventDefault both added to support up/down keys without scrolling the page\n event.preventDefault();\n\n const activeTabs = this._getTabs().filter((tab) => !isDisabled(tab));\n let nextActiveElement;\n\n if ([HOME_KEY, END_KEY].includes(event.key)) {\n nextActiveElement = activeTabs[event.key === HOME_KEY ? 0 : activeTabs.length - 1];\n } else {\n const isNext = [ARROW_RIGHT_KEY, ARROW_DOWN_KEY].includes(event.key);\n nextActiveElement = getNextActiveElement(activeTabs, event.target, isNext, true);\n }\n\n if (nextActiveElement) {\n nextActiveElement.focus({ preventScroll: true });\n Tab.getOrCreateInstance(nextActiveElement).show();\n }\n }\n\n private _getTabs() {\n return Array.from(this._tabList.querySelectorAll<HTMLElement>(SELECTOR_TAB));\n }\n\n private _getActiveTab() {\n return this._getTabs().find((tab) => this._tabIsActive(tab)) || null;\n }\n\n private _getReadyTab() {\n return this._getTabs().find((tab) => tab.matches(this._options.readyMark)) || null;\n }\n\n private _getTabFromHash() {\n return this._getTabs().find((tab) => getSelector(tab) === location.hash) || null;\n }\n\n private _getInitialActiveTab() {\n if (this._enableHashNavigation()) {\n const hashTab = this._getTabFromHash();\n if (hashTab) {\n return hashTab;\n }\n }\n const readyTab = this._getReadyTab();\n if (readyTab) {\n return readyTab;\n }\n return this._getTabs().at(0);\n }\n\n private _setInitialAttributes(parent: HTMLElement, tabs: HTMLElement[]) {\n this._setAttributeIfNotExists(parent, 'role', 'tablist');\n\n const initialActiveTab = this._getInitialActiveTab();\n if (initialActiveTab) {\n this._activate(initialActiveTab);\n }\n\n for (const tab of tabs) {\n this._setInitialAttributesOnTab(tab);\n }\n }\n\n private _setInitialAttributesOnTab(tab: HTMLElement) {\n const isActive = this._tabIsActive(tab);\n const outerElem = this._getOuterElement(tab);\n const panel = this._getTargetPanel(tab);\n\n tab.classList.add(this._options.tabClass);\n tab.setAttribute('aria-selected', isActive ? 'true' : 'false');\n\n if (outerElem !== tab) {\n this._setAttributeIfNotExists(outerElem, 'role', 'presentation');\n }\n\n if (!isActive) {\n tab.setAttribute('tabindex', '-1');\n }\n\n this._setAttributeIfNotExists(tab, 'role', 'tab');\n\n if (panel) {\n this._setAttributeIfNotExists(tab, 'aria-controls', panel.id);\n this._setAttributeIfNotExists(tab, 'id', `${panel.id}-tab`);\n }\n\n // set attributes to the related panel too\n this._setInitialAttributesOnTargetPanel(tab);\n }\n\n private _setInitialAttributesOnTargetPanel(tab: HTMLElement) {\n const panel = this._getTargetPanel(tab);\n\n if (!panel) {\n return;\n }\n\n const isActive = this._tabIsActive(tab);\n this._setAttributeIfNotExists(panel, 'role', 'tabpanel');\n this._setAttributeIfNotExists(panel, 'aria-hidden', isActive ? 'false' : 'true');\n if (!isActive) {\n panel.style.display = 'none';\n }\n\n if (tab.id) {\n this._setAttributeIfNotExists(panel, 'aria-labelledby', `${tab.id}`);\n }\n }\n\n private _getTargetPanel(tab: HTMLElement): HTMLElement | null {\n const selector = getSelector(tab);\n if (!selector) {\n return null;\n }\n return document.querySelector(selector);\n }\n\n private _setAttributeIfNotExists(element: HTMLElement, attribute: string, value: string) {\n if (!element.hasAttribute(attribute)) {\n element.setAttribute(attribute, value);\n }\n }\n\n private _tabIsActive(tab: HTMLElement) {\n return tab.classList.contains(this._options.activeClass);\n }\n\n // Try to get the outer element (usually the .nav-item)\n private _getOuterElement(elem: HTMLElement) {\n return elem.closest(SELECTOR_OUTER) || elem;\n }\n\n /**\n * ハッシュナビゲーションを有効にするかどうかを判断する\n */\n private _enableHashNavigation() {\n if (this._options.enableHashNavigation) {\n return true;\n }\n\n if (this._options.readyMark.startsWith('#')) {\n // readyMarkにハッシュが含まれている場合はハッシュナビゲーションを有効にする\n return true;\n }\n return false;\n }\n\n static getOrCreateInstance(element: HTMLElement & { Tab?: Tab }, options: Partial<TabOptions> = {}): Tab {\n if (element.Tab instanceof Tab) {\n return element.Tab;\n }\n const tab = new Tab(element, options);\n element.Tab = tab;\n return tab;\n }\n}\n","import Tab, { SELECTOR_TAB, TabOptions } from './tab';\n\nexport default class TabManager {\n private static instance: TabManager | null = null;\n\n private tabRepository: Map<TabOptions['tabList'], HTMLElement[]> = new Map();\n\n static getInstance(): TabManager {\n if (!TabManager.instance) {\n TabManager.instance = new TabManager();\n }\n return TabManager.instance;\n }\n\n async apply(\n selector: Extract<TabOptions['tabList'], string>,\n options: Partial<Omit<TabOptions, 'tabListSelector'>> = {},\n context: Document | HTMLElement = document\n ): Promise<void> {\n const tabOptions: Partial<TabOptions> = {\n tabList: selector,\n ...options,\n };\n\n ACMS.Loaded(() => {\n context.querySelectorAll<HTMLElement>(SELECTOR_TAB).forEach((element) => {\n if (element.closest(selector) !== null) {\n Tab.getOrCreateInstance(element, tabOptions);\n this.tabRepository.set(selector, [...(this.tabRepository.get(selector) || []), element]);\n }\n });\n });\n }\n\n destroy(selector: Extract<TabOptions['tabList'], string>): void {\n const elements = this.tabRepository.get(selector);\n if (elements) {\n elements.forEach((element) => {\n Tab.getOrCreateInstance(element).destroy();\n });\n this.tabRepository.delete(selector);\n }\n }\n\n destroyAll(): void {\n for (const [, elements] of this.tabRepository) {\n elements.forEach((element) => {\n Tab.getOrCreateInstance(element).destroy();\n });\n }\n this.tabRepository.clear();\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/tab.ts","../src/tab-manager.ts"],"sourcesContent":["import { getNextActiveElement, getSelector, isDisabled, hide, show } from '@ablogcms/utils/dom';\n\nconst ARROW_LEFT_KEY = 'ArrowLeft';\nconst ARROW_RIGHT_KEY = 'ArrowRight';\nconst ARROW_UP_KEY = 'ArrowUp';\nconst ARROW_DOWN_KEY = 'ArrowDown';\nconst HOME_KEY = 'Home';\nconst END_KEY = 'End';\n\nconst SELECTOR_OUTER = 'li';\nexport const SELECTOR_TAB = 'a[href^=\"#\"], [role=\"tab\"]';\n\nexport interface TabOptions {\n tabList: string | HTMLElement;\n tabClass: string;\n activeClass: string;\n readyMark: string;\n enableHashNavigation: boolean;\n onShow: ({ tab, panel }: { tab: HTMLElement; panel: HTMLElement | null }) => void;\n onHide: ({ tab, panel }: { tab: HTMLElement; panel: HTMLElement | null }) => void;\n}\n\nexport const defaultOptions: TabOptions = {\n tabList: '.js-acms_admin_tabs',\n tabClass: 'js-acms_tab',\n activeClass: 'js-acms_tab-active',\n readyMark: '.js-ready-acms_tabs',\n enableHashNavigation: false,\n onShow: () => {},\n onHide: () => {},\n};\n\ntype TabElement = HTMLElement & { Tab?: Tab };\n\nexport default class Tab {\n private _element: TabElement;\n\n private _tabList: HTMLElement;\n\n private _options: TabOptions;\n\n private eventRegistry: Map<\n Element | Document,\n Array<{\n type: string;\n listener: EventListener;\n options?: AddEventListenerOptions;\n }>\n > = new Map();\n\n constructor(element: TabElement, options: Partial<TabOptions> = {}) {\n this._options = { ...defaultOptions, ...options };\n this._element = element;\n const tabList =\n this._options.tabList instanceof HTMLElement\n ? this._options.tabList\n : this._element.closest<HTMLElement>(this._options.tabList);\n\n if (!tabList) {\n throw new TypeError(`${element.outerHTML} has not a valid parent ${this._options.tabList}`);\n }\n\n this._tabList = tabList;\n\n const tabs = this._getTabs();\n // Set up initial aria attributes\n this._setInitialAttributes(this._tabList, tabs);\n this._keydown = this._keydown.bind(this);\n this._click = this._click.bind(this);\n this._element.addEventListener('click', this._click);\n this._element.addEventListener('keydown', this._keydown);\n this.eventRegistry.set(this._element, [\n {\n type: 'click',\n listener: this._click as EventListener,\n },\n {\n type: 'keydown',\n listener: this._keydown as EventListener,\n },\n ]);\n }\n\n public destroy() {\n delete this._element.Tab;\n for (const [eventTarget, listeners] of this.eventRegistry) {\n listeners.forEach(({ type, listener, options }) => {\n eventTarget.removeEventListener(type, listener, options);\n });\n }\n this.eventRegistry.clear();\n }\n\n // Public\n public show() {\n // Shows this elem and deactivate the active sibling if exists\n const tab = this._element;\n if (this._tabIsActive(tab)) {\n return;\n }\n\n // Search for active tab on same parent to deactivate it\n const activeTab = this._getActiveTab();\n\n if (activeTab) {\n this._deactivate(activeTab);\n }\n\n this._activate(tab);\n const panel = this._getTargetPanel(tab);\n if (this._enableHashNavigation() && panel && `#${panel.id}` !== location.hash) {\n const hash = panel.id;\n if ('history' in window) {\n history.replaceState(null, '', `#${hash}`);\n }\n panel.id = hash;\n }\n }\n\n public get options(): TabOptions {\n return this._options;\n }\n\n // Private\n private _activate(tab: HTMLElement) {\n const panel = this._getTargetPanel(tab);\n\n tab.classList.add(this._options.activeClass);\n\n if (panel !== null) {\n show(panel);\n panel.setAttribute('aria-hidden', 'false');\n }\n\n tab.removeAttribute('tabindex');\n tab.setAttribute('aria-selected', 'true');\n\n this._options.onShow({ tab, panel });\n }\n\n private _deactivate(tab: HTMLElement) {\n const panel = this._getTargetPanel(tab);\n\n tab.classList.remove(this._options.activeClass);\n tab.blur();\n\n if (panel !== null) {\n hide(panel);\n panel.setAttribute('aria-hidden', 'true');\n }\n\n tab.setAttribute('aria-selected', 'false');\n tab.setAttribute('tabindex', '-1');\n\n this._options.onHide({ tab, panel });\n }\n\n private _click(event: MouseEvent) {\n const { currentTarget } = event;\n if (!(currentTarget instanceof HTMLElement)) {\n return;\n }\n\n if (['A', 'AREA'].includes(currentTarget.tagName)) {\n event.preventDefault();\n }\n\n if (isDisabled(currentTarget)) {\n return;\n }\n\n Tab.getOrCreateInstance(currentTarget).show();\n }\n\n private _keydown(event: KeyboardEvent) {\n if (![ARROW_LEFT_KEY, ARROW_RIGHT_KEY, ARROW_UP_KEY, ARROW_DOWN_KEY, HOME_KEY, END_KEY].includes(event.key)) {\n return;\n }\n\n if (!(event.target instanceof HTMLElement)) {\n return;\n }\n\n event.stopPropagation(); // stopPropagation/preventDefault both added to support up/down keys without scrolling the page\n event.preventDefault();\n\n const activeTabs = this._getTabs().filter((tab) => !isDisabled(tab));\n let nextActiveElement;\n\n if ([HOME_KEY, END_KEY].includes(event.key)) {\n nextActiveElement = activeTabs[event.key === HOME_KEY ? 0 : activeTabs.length - 1];\n } else {\n const isNext = [ARROW_RIGHT_KEY, ARROW_DOWN_KEY].includes(event.key);\n nextActiveElement = getNextActiveElement(activeTabs, event.target, isNext, true);\n }\n\n if (nextActiveElement) {\n nextActiveElement.focus({ preventScroll: true });\n Tab.getOrCreateInstance(nextActiveElement).show();\n }\n }\n\n private _getTabs() {\n return Array.from(this._tabList.querySelectorAll<HTMLElement>(SELECTOR_TAB));\n }\n\n private _getActiveTab() {\n return this._getTabs().find((tab) => this._tabIsActive(tab)) || null;\n }\n\n private _getReadyTab() {\n return this._getTabs().find((tab) => tab.matches(this._options.readyMark)) || null;\n }\n\n private _getTabFromHash() {\n return this._getTabs().find((tab) => getSelector(tab) === location.hash) || null;\n }\n\n private _getInitialActiveTab() {\n if (this._enableHashNavigation()) {\n const hashTab = this._getTabFromHash();\n if (hashTab) {\n return hashTab;\n }\n }\n const readyTab = this._getReadyTab();\n if (readyTab) {\n return readyTab;\n }\n return this._getTabs().at(0);\n }\n\n private _setInitialAttributes(parent: HTMLElement, tabs: HTMLElement[]) {\n this._setAttributeIfNotExists(parent, 'role', 'tablist');\n\n const initialActiveTab = this._getInitialActiveTab();\n if (initialActiveTab) {\n this._activate(initialActiveTab);\n }\n\n for (const tab of tabs) {\n this._setInitialAttributesOnTab(tab);\n }\n }\n\n private _setInitialAttributesOnTab(tab: HTMLElement) {\n const isActive = this._tabIsActive(tab);\n const outerElem = this._getOuterElement(tab);\n const panel = this._getTargetPanel(tab);\n\n tab.classList.add(this._options.tabClass);\n tab.setAttribute('aria-selected', isActive ? 'true' : 'false');\n\n if (outerElem !== tab) {\n this._setAttributeIfNotExists(outerElem, 'role', 'presentation');\n }\n\n if (!isActive) {\n tab.setAttribute('tabindex', '-1');\n }\n\n this._setAttributeIfNotExists(tab, 'role', 'tab');\n\n if (panel) {\n this._setAttributeIfNotExists(tab, 'aria-controls', panel.id);\n this._setAttributeIfNotExists(tab, 'id', `${panel.id}-tab`);\n }\n\n // set attributes to the related panel too\n this._setInitialAttributesOnTargetPanel(tab);\n }\n\n private _setInitialAttributesOnTargetPanel(tab: HTMLElement) {\n const panel = this._getTargetPanel(tab);\n\n if (!panel) {\n return;\n }\n\n const isActive = this._tabIsActive(tab);\n this._setAttributeIfNotExists(panel, 'role', 'tabpanel');\n this._setAttributeIfNotExists(panel, 'aria-hidden', isActive ? 'false' : 'true');\n if (!isActive) {\n panel.style.display = 'none';\n }\n\n if (tab.id) {\n this._setAttributeIfNotExists(panel, 'aria-labelledby', `${tab.id}`);\n }\n }\n\n private _getTargetPanel(tab: HTMLElement): HTMLElement | null {\n const selector = getSelector(tab);\n if (!selector) {\n return null;\n }\n return document.querySelector(selector);\n }\n\n private _setAttributeIfNotExists(element: HTMLElement, attribute: string, value: string) {\n if (!element.hasAttribute(attribute)) {\n element.setAttribute(attribute, value);\n }\n }\n\n private _tabIsActive(tab: HTMLElement) {\n return tab.classList.contains(this._options.activeClass);\n }\n\n // Try to get the outer element (usually the .nav-item)\n private _getOuterElement(elem: HTMLElement) {\n return elem.closest(SELECTOR_OUTER) || elem;\n }\n\n /**\n * ハッシュナビゲーションを有効にするかどうかを判断する\n */\n private _enableHashNavigation() {\n if (this._options.enableHashNavigation) {\n return true;\n }\n\n if (this._options.readyMark.startsWith('#')) {\n // readyMarkにハッシュが含まれている場合はハッシュナビゲーションを有効にする\n return true;\n }\n return false;\n }\n\n static getOrCreateInstance(element: HTMLElement & { Tab?: Tab }, options: Partial<TabOptions> = {}): Tab {\n if (element.Tab instanceof Tab) {\n return element.Tab;\n }\n const tab = new Tab(element, options);\n element.Tab = tab;\n return tab;\n }\n}\n","import domReady from '@ablogcms/dom-ready';\n\nimport Tab, { SELECTOR_TAB, TabOptions } from './tab';\n\nexport default class TabManager {\n private static instance: TabManager | null = null;\n\n static getInstance(): TabManager {\n if (!TabManager.instance) {\n TabManager.instance = new TabManager();\n }\n return TabManager.instance;\n }\n\n /**\n * 指定コンテキスト内のタブ要素にTabインスタンスを登録する。\n * 呼び出し元は戻り値の要素一覧を保持しておき、destroy() に渡すことで\n * 自分が登録した要素だけを後片付けできる(他の呼び出し元の登録には影響しない)。\n */\n async apply(\n selector: Extract<TabOptions['tabList'], string>,\n options: Partial<Omit<TabOptions, 'tabListSelector'>> = {},\n context: Document | HTMLElement = document\n ): Promise<HTMLElement[]> {\n const tabOptions: Partial<TabOptions> = {\n tabList: selector,\n ...options,\n };\n\n return new Promise((resolve) => {\n domReady(() => {\n const applied: HTMLElement[] = [];\n context.querySelectorAll<HTMLElement>(SELECTOR_TAB).forEach((element) => {\n if (element.closest(selector) !== null) {\n Tab.getOrCreateInstance(element, tabOptions);\n applied.push(element);\n }\n });\n resolve(applied);\n });\n });\n }\n\n destroy(elements: HTMLElement[]): void {\n elements.forEach((element) => {\n Tab.getOrCreateInstance(element).destroy();\n });\n }\n}\n"],"mappings":"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","names":[]}
@@ -1,9 +1,12 @@
1
1
  import { TabOptions } from './tab.js';
2
2
  export default class TabManager {
3
3
  private static instance;
4
- private tabRepository;
5
4
  static getInstance(): TabManager;
6
- apply(selector: Extract<TabOptions['tabList'], string>, options?: Partial<Omit<TabOptions, 'tabListSelector'>>, context?: Document | HTMLElement): Promise<void>;
7
- destroy(selector: Extract<TabOptions['tabList'], string>): void;
8
- destroyAll(): void;
5
+ /**
6
+ * 指定コンテキスト内のタブ要素にTabインスタンスを登録する。
7
+ * 呼び出し元は戻り値の要素一覧を保持しておき、destroy() に渡すことで
8
+ * 自分が登録した要素だけを後片付けできる(他の呼び出し元の登録には影響しない)。
9
+ */
10
+ apply(selector: Extract<TabOptions['tabList'], string>, options?: Partial<Omit<TabOptions, 'tabListSelector'>>, context?: Document | HTMLElement): Promise<HTMLElement[]>;
11
+ destroy(elements: HTMLElement[]): void;
9
12
  }
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@ablogcms/tab",
3
- "version": "3.2.28-beta.0",
3
+ "version": "3.2.29",
4
4
  "type": "module",
5
- "description": "タブ切り替え UI の制御",
5
+ "description": "Tab-switching UI controller for a-blog cms admin",
6
6
  "license": "MIT",
7
7
  "homepage": "https://www.a-blogcms.jp",
8
8
  "repository": {
@@ -12,10 +12,11 @@
12
12
  },
13
13
  "sideEffects": false,
14
14
  "dependencies": {
15
- "@ablogcms/utils": "3.2.28-beta.0"
15
+ "@ablogcms/dom-ready": "3.2.29",
16
+ "@ablogcms/utils": "3.2.29"
16
17
  },
17
18
  "devDependencies": {
18
- "vitest": "^4.1.9"
19
+ "vitest": "^4.1.10"
19
20
  },
20
21
  "exports": {
21
22
  ".": {