diff --git a/.changeset/thirty-spies-fetch.md b/.changeset/thirty-spies-fetch.md new file mode 100644 index 00000000..816db2d7 --- /dev/null +++ b/.changeset/thirty-spies-fetch.md @@ -0,0 +1,9 @@ +--- +'@tanstack/preact-devtools': minor +'@tanstack/devtools-utils': minor +'@tanstack/react-devtools': minor +'@tanstack/solid-devtools': minor +'@tanstack/devtools': minor +--- + +Change the way props are passed to the plugins diff --git a/packages/devtools-utils/package.json b/packages/devtools-utils/package.json index 3353dc8f..874a01c0 100644 --- a/packages/devtools-utils/package.json +++ b/packages/devtools-utils/package.json @@ -62,6 +62,12 @@ "dependencies": { "@tanstack/devtools-ui": "workspace:^" }, + "devDependencies": { + "@tanstack/devtools": "workspace:^", + "tsup": "^8.5.0", + "tsup-preset-solid": "^2.2.0", + "vite-plugin-solid": "^2.11.8" + }, "peerDependencies": { "@types/react": ">=17.0.0", "preact": ">=10.0.0", @@ -99,10 +105,5 @@ "test:types": "tsc", "test:build": "publint --strict", "build": "vite build && vite build --config vite.config.preact.ts && vite build --config vite.config.vue.ts && tsup " - }, - "devDependencies": { - "tsup": "^8.5.0", - "tsup-preset-solid": "^2.2.0", - "vite-plugin-solid": "^2.11.8" } } diff --git a/packages/devtools-utils/src/preact/panel.tsx b/packages/devtools-utils/src/preact/panel.tsx index ab145404..5c8fcd60 100644 --- a/packages/devtools-utils/src/preact/panel.tsx +++ b/packages/devtools-utils/src/preact/panel.tsx @@ -1,10 +1,9 @@ /** @jsxImportSource preact */ import { useEffect, useRef } from 'preact/hooks' +import type { TanStackDevtoolsPluginProps } from '@tanstack/devtools' -export interface DevtoolsPanelProps { - theme?: 'light' | 'dark' -} +export interface DevtoolsPanelProps extends TanStackDevtoolsPluginProps {} /** * Creates a Preact component that dynamically imports and mounts a devtools panel. SSR friendly. @@ -24,9 +23,9 @@ export interface DevtoolsPanelProps { * ``` */ export function createPreactPanel< - TComponentProps extends DevtoolsPanelProps | undefined, + TComponentProps extends DevtoolsPanelProps, TCoreDevtoolsClass extends { - mount: (el: HTMLElement, theme: 'light' | 'dark') => void + mount: (el: HTMLElement, props: TanStackDevtoolsPluginProps) => void unmount: () => void }, >(CoreClass: new () => TCoreDevtoolsClass) { @@ -38,7 +37,7 @@ export function createPreactPanel< devtools.current = new CoreClass() if (devToolRef.current) { - devtools.current.mount(devToolRef.current, props?.theme ?? 'dark') + devtools.current.mount(devToolRef.current, props) } return () => { @@ -47,7 +46,7 @@ export function createPreactPanel< devtools.current = null } } - }, [props?.theme]) + }, [props]) return
} diff --git a/packages/devtools-utils/src/preact/plugin.tsx b/packages/devtools-utils/src/preact/plugin.tsx index a5485487..bd855e41 100644 --- a/packages/devtools-utils/src/preact/plugin.tsx +++ b/packages/devtools-utils/src/preact/plugin.tsx @@ -2,6 +2,7 @@ import type { JSX } from 'preact' import type { DevtoolsPanelProps } from './panel' +import type { TanStackDevtoolsPluginProps } from '@tanstack/devtools' export function createPreactPlugin({ Component, @@ -15,15 +16,15 @@ export function createPreactPlugin({ function Plugin() { return { ...config, - render: (_el: HTMLElement, theme: 'light' | 'dark') => ( - + render: (_el: HTMLElement, props: TanStackDevtoolsPluginProps) => ( + ), } } function NoOpPlugin() { return { ...config, - render: (_el: HTMLElement, _theme: 'light' | 'dark') => <>, + render: (_el: HTMLElement, _props: TanStackDevtoolsPluginProps) => <>, } } return [Plugin, NoOpPlugin] as const diff --git a/packages/devtools-utils/src/react/panel.tsx b/packages/devtools-utils/src/react/panel.tsx index 83d3ebc5..548f27de 100644 --- a/packages/devtools-utils/src/react/panel.tsx +++ b/packages/devtools-utils/src/react/panel.tsx @@ -1,8 +1,7 @@ import { useEffect, useRef } from 'react' +import type { TanStackDevtoolsPluginProps } from '@tanstack/devtools' -export interface DevtoolsPanelProps { - theme?: 'light' | 'dark' -} +export interface DevtoolsPanelProps extends TanStackDevtoolsPluginProps {} /** * Creates a React component that dynamically imports and mounts a devtools panel. SSR friendly. @@ -22,9 +21,9 @@ export interface DevtoolsPanelProps { * ``` */ export function createReactPanel< - TComponentProps extends DevtoolsPanelProps | undefined, + TComponentProps extends TanStackDevtoolsPluginProps, TCoreDevtoolsClass extends { - mount: (el: HTMLElement, theme: 'light' | 'dark') => void + mount: (el: HTMLElement, props: TanStackDevtoolsPluginProps) => void unmount: () => void }, >(CoreClass: new () => TCoreDevtoolsClass) { @@ -36,7 +35,7 @@ export function createReactPanel< devtools.current = new CoreClass() if (devToolRef.current) { - devtools.current.mount(devToolRef.current, props?.theme ?? 'dark') + devtools.current.mount(devToolRef.current, props) } return () => { @@ -45,7 +44,7 @@ export function createReactPanel< devtools.current = null } } - }, [props?.theme]) + }, [props]) return
} diff --git a/packages/devtools-utils/src/react/plugin.tsx b/packages/devtools-utils/src/react/plugin.tsx index fad8b8cd..1786bf53 100644 --- a/packages/devtools-utils/src/react/plugin.tsx +++ b/packages/devtools-utils/src/react/plugin.tsx @@ -1,5 +1,6 @@ import type { JSX } from 'react' import type { DevtoolsPanelProps } from './panel' +import type { TanStackDevtoolsPluginProps } from '@tanstack/devtools' export function createReactPlugin({ Component, @@ -13,15 +14,15 @@ export function createReactPlugin({ function Plugin() { return { ...config, - render: (_el: HTMLElement, theme: 'light' | 'dark') => ( - + render: (_el: HTMLElement, props: TanStackDevtoolsPluginProps) => ( + ), } } function NoOpPlugin() { return { ...config, - render: (_el: HTMLElement, _theme: 'light' | 'dark') => <>, + render: (_el: HTMLElement, _props: TanStackDevtoolsPluginProps) => <>, } } return [Plugin, NoOpPlugin] as const diff --git a/packages/devtools-utils/src/solid/class.test.tsx b/packages/devtools-utils/src/solid/class.test.tsx index 80ce341a..1ee8cd31 100644 --- a/packages/devtools-utils/src/solid/class.test.tsx +++ b/packages/devtools-utils/src/solid/class.test.tsx @@ -41,7 +41,10 @@ describe('constructCoreClass', () => {
Test Component
)) const instance = new DevtoolsCore() - await instance.mount(document.createElement('div'), 'dark') + await instance.mount(document.createElement('div'), { + theme: 'dark', + devtoolsOpen: true, + }) expect(renderMock).toHaveBeenCalled() }) @@ -50,9 +53,15 @@ describe('constructCoreClass', () => {
Test Component
)) const instance = new DevtoolsCore() - await instance.mount(document.createElement('div'), 'dark') + await instance.mount(document.createElement('div'), { + theme: 'dark', + devtoolsOpen: true, + }) await expect( - instance.mount(document.createElement('div'), 'dark'), + instance.mount(document.createElement('div'), { + theme: 'dark', + devtoolsOpen: true, + }), ).rejects.toThrow('Devtools is already mounted') }) @@ -69,10 +78,16 @@ describe('constructCoreClass', () => {
Test Component
)) const instance = new DevtoolsCore() - await instance.mount(document.createElement('div'), 'dark') + await instance.mount(document.createElement('div'), { + theme: 'dark', + devtoolsOpen: true, + }) instance.unmount() await expect( - instance.mount(document.createElement('div'), 'dark'), + instance.mount(document.createElement('div'), { + theme: 'dark', + devtoolsOpen: true, + }), ).resolves.not.toThrow() }) @@ -81,7 +96,10 @@ describe('constructCoreClass', () => {
Test Component
)) const noOpInstance = new NoOpDevtoolsCore() - await noOpInstance.mount(document.createElement('div'), 'dark') + await noOpInstance.mount(document.createElement('div'), { + theme: 'dark', + devtoolsOpen: true, + }) expect(lazyImportMock).not.toHaveBeenCalled() expect(renderMock).not.toHaveBeenCalled() @@ -93,9 +111,15 @@ describe('constructCoreClass', () => {
Test Component
)) const noOpInstance = new NoOpDevtoolsCore() - await noOpInstance.mount(document.createElement('div'), 'dark') + await noOpInstance.mount(document.createElement('div'), { + theme: 'dark', + devtoolsOpen: true, + }) await expect( - noOpInstance.mount(document.createElement('div'), 'dark'), + noOpInstance.mount(document.createElement('div'), { + theme: 'dark', + devtoolsOpen: true, + }), ).resolves.not.toThrow() }) @@ -112,7 +136,10 @@ describe('constructCoreClass', () => {
Test Component
)) const noOpInstance = new NoOpDevtoolsCore() - await noOpInstance.mount(document.createElement('div'), 'dark') + await noOpInstance.mount(document.createElement('div'), { + theme: 'dark', + devtoolsOpen: true, + }) expect(() => noOpInstance.unmount()).not.toThrow() }) }) diff --git a/packages/devtools-utils/src/solid/class.tsx b/packages/devtools-utils/src/solid/class.tsx index 7cbb94ae..c82d2c24 100644 --- a/packages/devtools-utils/src/solid/class.tsx +++ b/packages/devtools-utils/src/solid/class.tsx @@ -1,5 +1,6 @@ /** @jsxImportSource solid-js - we use Solid.js as JSX here */ +import type { TanStackDevtoolsPluginProps } from '@tanstack/devtools' import type { JSX } from 'solid-js' /** @@ -22,7 +23,10 @@ export function constructCoreClass(Component: () => JSX.Element) { constructor() {} - async mount(el: T, theme: 'light' | 'dark') { + async mount( + el: T, + props: TanStackDevtoolsPluginProps, + ) { this.#isMounting = true const { lazy } = await import('solid-js') const { render, Portal } = await import('solid-js/web') @@ -44,8 +48,8 @@ export function constructCoreClass(Component: () => JSX.Element) { return (
- - + +
@@ -79,7 +83,10 @@ export function constructCoreClass(Component: () => JSX.Element) { constructor() { super() } - async mount(_el: T, _theme: 'light' | 'dark') {} + async mount( + _el: T, + _props: TanStackDevtoolsPluginProps, + ) {} unmount() {} } return [DevtoolsCore, NoOpDevtoolsCore] as const diff --git a/packages/devtools-utils/src/solid/panel.tsx b/packages/devtools-utils/src/solid/panel.tsx index 8051118d..cecafe38 100644 --- a/packages/devtools-utils/src/solid/panel.tsx +++ b/packages/devtools-utils/src/solid/panel.tsx @@ -2,20 +2,19 @@ import { createSignal, onCleanup, onMount } from 'solid-js' import type { ClassType } from './class' +import type { TanStackDevtoolsPluginProps } from '@tanstack/devtools' -export interface DevtoolsPanelProps { - theme?: 'light' | 'dark' -} +export interface DevtoolsPanelProps extends TanStackDevtoolsPluginProps {} -export function createSolidPanel< - TComponentProps extends DevtoolsPanelProps | undefined, ->(CoreClass: ClassType) { +export function createSolidPanel( + CoreClass: ClassType, +) { function Panel(props: TComponentProps) { let devToolRef: HTMLDivElement | undefined const [devtools] = createSignal(new CoreClass()) onMount(() => { if (devToolRef) { - devtools().mount(devToolRef, props?.theme ?? 'dark') + devtools().mount(devToolRef, props) } onCleanup(() => { devtools().unmount() diff --git a/packages/devtools-utils/src/solid/plugin.tsx b/packages/devtools-utils/src/solid/plugin.tsx index 2bc378e6..81a7ef28 100644 --- a/packages/devtools-utils/src/solid/plugin.tsx +++ b/packages/devtools-utils/src/solid/plugin.tsx @@ -2,6 +2,7 @@ import type { JSX } from 'solid-js' import type { DevtoolsPanelProps } from './panel' +import type { TanStackDevtoolsPluginProps } from '@tanstack/devtools' export function createSolidPlugin({ Component, @@ -15,15 +16,15 @@ export function createSolidPlugin({ function Plugin() { return { ...config, - render: (_el: HTMLElement, theme: 'light' | 'dark') => { - return + render: (_el: HTMLElement, props: TanStackDevtoolsPluginProps) => { + return }, } } function NoOpPlugin() { return { ...config, - render: (_el: HTMLElement, _theme: 'light' | 'dark') => <>, + render: (_el: HTMLElement, _props: TanStackDevtoolsPluginProps) => <>, } } return [Plugin, NoOpPlugin] as const diff --git a/packages/devtools-utils/src/vue/panel.ts b/packages/devtools-utils/src/vue/panel.ts index b8dfbe19..2c2e6b9b 100644 --- a/packages/devtools-utils/src/vue/panel.ts +++ b/packages/devtools-utils/src/vue/panel.ts @@ -1,20 +1,19 @@ import { defineComponent, h, onMounted, onUnmounted, ref } from 'vue' +import type { TanStackDevtoolsPluginProps } from '@tanstack/devtools' import type { DefineComponent } from 'vue' -export interface DevtoolsPanelProps { - theme?: 'dark' | 'light' | 'system' -} +export interface DevtoolsPanelProps extends TanStackDevtoolsPluginProps {} export function createVuePanel< TComponentProps extends DevtoolsPanelProps, TCoreDevtoolsClass extends { - mount: (el: HTMLElement, theme?: DevtoolsPanelProps['theme']) => void + mount: (el: HTMLElement, props?: TanStackDevtoolsPluginProps) => void unmount: () => void }, >(CoreClass: new (props: TComponentProps) => TCoreDevtoolsClass) { const props = { - theme: { - type: String as () => DevtoolsPanelProps['theme'], + props: { + type: Object as () => DevtoolsPanelProps, }, devtoolsProps: { type: Object as () => TComponentProps, @@ -32,7 +31,7 @@ export function createVuePanel< devtools.value = instance if (devToolRef.value) { - instance.mount(devToolRef.value, config.theme) + instance.mount(devToolRef.value, config.props) } }) diff --git a/packages/devtools/src/components/tab-content.tsx b/packages/devtools/src/components/tab-content.tsx index 02e1378a..bbb64e56 100644 --- a/packages/devtools/src/components/tab-content.tsx +++ b/packages/devtools/src/components/tab-content.tsx @@ -4,12 +4,16 @@ import { tabs } from '../tabs' import { useStyles } from '../styles/use-styles' import type { JSX } from 'solid-js' -export const TabContent = () => { +export const TabContent = (props: { isOpen: boolean }) => { const { state } = useDevtoolsState() const styles = useStyles() - const component = createMemo<(() => JSX.Element) | null>( - () => tabs.find((t) => t.id === state().activeTab)?.component || null, - ) + const component = createMemo< + ((props: { isOpen: boolean }) => JSX.Element) | null + >(() => tabs.find((t) => t.id === state().activeTab)?.component || null) - return
{component()?.()}
+ return ( +
+ {component()?.({ isOpen: props.isOpen })} +
+ ) } diff --git a/packages/devtools/src/context/devtools-context.tsx b/packages/devtools/src/context/devtools-context.tsx index d92855df..362b2f4c 100644 --- a/packages/devtools/src/context/devtools-context.tsx +++ b/packages/devtools/src/context/devtools-context.tsx @@ -12,6 +12,10 @@ import { initialState } from './devtools-store' import type { DevtoolsStore } from './devtools-store' import type { JSX, Setter } from 'solid-js' +export interface TanStackDevtoolsPluginProps { + theme: DevtoolsStore['settings']['theme'] + devtoolsOpen: boolean +} export interface TanStackDevtoolsPlugin { /** * Name to be displayed in the devtools UI. @@ -41,10 +45,7 @@ export interface TanStackDevtoolsPlugin { */ name: | string - | (( - el: HTMLHeadingElement, - theme: DevtoolsStore['settings']['theme'], - ) => void) + | ((el: HTMLHeadingElement, props: TanStackDevtoolsPluginProps) => void) /** * Unique identifier for the plugin. * If not provided, it will be generated based on the name. @@ -69,11 +70,7 @@ export interface TanStackDevtoolsPlugin { * } * ``` */ - render: ( - el: HTMLDivElement, - theme: DevtoolsStore['settings']['theme'], - ) => void - + render: (el: HTMLDivElement, props: TanStackDevtoolsPluginProps) => void destroy?: (pluginId: string) => void } export const DevtoolsContext = createContext<{ diff --git a/packages/devtools/src/devtools.tsx b/packages/devtools/src/devtools.tsx index 5a68a04d..5db22a3b 100644 --- a/packages/devtools/src/devtools.tsx +++ b/packages/devtools/src/devtools.tsx @@ -196,7 +196,7 @@ export default function DevTools() { handleDragStart={(e) => handleDragStart(panelRef, e)} > - + diff --git a/packages/devtools/src/index.ts b/packages/devtools/src/index.ts index 058273ba..93293af0 100644 --- a/packages/devtools/src/index.ts +++ b/packages/devtools/src/index.ts @@ -3,5 +3,6 @@ export { TanStackDevtoolsCore } from './core' export type { TanStackDevtoolsInit, ClientEventBusConfig } from './core' export type { TanStackDevtoolsPlugin, + TanStackDevtoolsPluginProps, TanStackDevtoolsConfig, } from './context/devtools-context' diff --git a/packages/devtools/src/tabs/index.tsx b/packages/devtools/src/tabs/index.tsx index d7e93700..beb4f17e 100644 --- a/packages/devtools/src/tabs/index.tsx +++ b/packages/devtools/src/tabs/index.tsx @@ -7,7 +7,7 @@ export const tabs = [ { name: 'Plugins', id: 'plugins', - component: () => , + component: (props: { isOpen: boolean }) => , icon: () => , }, { diff --git a/packages/devtools/src/tabs/plugins-tab.tsx b/packages/devtools/src/tabs/plugins-tab.tsx index 4746087f..c9616777 100644 --- a/packages/devtools/src/tabs/plugins-tab.tsx +++ b/packages/devtools/src/tabs/plugins-tab.tsx @@ -6,10 +6,9 @@ import { useStyles } from '../styles/use-styles' import { PLUGIN_CONTAINER_ID, PLUGIN_TITLE_CONTAINER_ID } from '../constants' import { PluginMarketplace } from './plugin-marketplace' -export const PluginsTab = () => { +export const PluginsTab = (props: { isOpen: boolean }) => { const { plugins, activePlugins, toggleActivePlugins } = usePlugins() const { expanded, hoverUtils, animationMs, setForceExpand } = useDrawContext() - const [pluginRefs, setPluginRefs] = createSignal( new Map(), ) @@ -37,7 +36,10 @@ export const PluginsTab = () => { const ref = pluginRefs().get(plugin.id!) if (ref) { - plugin.render(ref, theme()) + plugin.render(ref, { + theme: theme(), + devtoolsOpen: props.isOpen, + }) } }) }) @@ -86,7 +88,10 @@ export const PluginsTab = () => { if (pluginHeading) { typeof plugin.name === 'string' ? (pluginHeading.textContent = plugin.name) - : plugin.name(pluginHeading, theme()) + : plugin.name(pluginHeading, { + theme: theme(), + devtoolsOpen: props.isOpen, + }) } }) diff --git a/packages/preact-devtools/src/devtools.tsx b/packages/preact-devtools/src/devtools.tsx index d5136cb1..19dbf547 100644 --- a/packages/preact-devtools/src/devtools.tsx +++ b/packages/preact-devtools/src/devtools.tsx @@ -6,11 +6,12 @@ import type { ClientEventBusConfig, TanStackDevtoolsConfig, TanStackDevtoolsPlugin, + TanStackDevtoolsPluginProps, } from '@tanstack/devtools' type PluginRender = | JSX.Element - | ((el: HTMLElement, theme: 'dark' | 'light') => JSX.Element) + | ((el: HTMLElement, props: TanStackDevtoolsPluginProps) => JSX.Element) type TriggerProps = { theme: 'dark' | 'light' @@ -140,10 +141,10 @@ const convertRender = ( | ((prev: Record) => Record), ) => void, e: HTMLElement, - theme: 'dark' | 'light', + props: TanStackDevtoolsPluginProps, ) => { const element = - typeof Component === 'function' ? Component(e, theme) : Component + typeof Component === 'function' ? Component(e, props) : Component setComponents((prev) => ({ ...prev, diff --git a/packages/react-devtools/src/devtools.tsx b/packages/react-devtools/src/devtools.tsx index 6d9b9729..43688150 100644 --- a/packages/react-devtools/src/devtools.tsx +++ b/packages/react-devtools/src/devtools.tsx @@ -6,11 +6,12 @@ import type { ClientEventBusConfig, TanStackDevtoolsConfig, TanStackDevtoolsPlugin, + TanStackDevtoolsPluginProps, } from '@tanstack/devtools' type PluginRender = | JSX.Element - | ((el: HTMLElement, theme: 'dark' | 'light') => JSX.Element) + | ((el: HTMLElement, props: TanStackDevtoolsPluginProps) => JSX.Element) type TriggerProps = { theme: 'dark' | 'light' @@ -120,10 +121,10 @@ const convertRender = ( React.SetStateAction> >, e: HTMLElement, - theme: 'dark' | 'light', + props: TanStackDevtoolsPluginProps, ) => { const element = - typeof Component === 'function' ? Component(e, theme) : Component + typeof Component === 'function' ? Component(e, props) : Component setComponents((prev) => ({ ...prev, @@ -177,7 +178,7 @@ export const TanStackDevtools = ({ name: typeof plugin.name === 'string' ? plugin.name - : (e, theme) => { + : (e, props) => { const id = e.getAttribute('id')! const target = e.ownerDocument.getElementById(id) @@ -192,7 +193,7 @@ export const TanStackDevtools = ({ plugin.name as PluginRender, setTitleComponents, e, - theme, + props, ) }, render: (e, theme) => { diff --git a/packages/solid-devtools/src/core.tsx b/packages/solid-devtools/src/core.tsx index 5b2938ef..84895299 100644 --- a/packages/solid-devtools/src/core.tsx +++ b/packages/solid-devtools/src/core.tsx @@ -12,21 +12,22 @@ import type { ClientEventBusConfig, TanStackDevtoolsConfig, TanStackDevtoolsPlugin, + TanStackDevtoolsPluginProps, } from '@tanstack/devtools' type SolidPluginRender = | JSX.Element | (( el: HTMLDivElement | HTMLHeadingElement, - theme: 'dark' | 'light', + props: TanStackDevtoolsPluginProps, ) => JSX.Element) const convertRender = ( el: HTMLDivElement | HTMLHeadingElement, Component: SolidPluginRender, - theme: 'dark' | 'light', + props: TanStackDevtoolsPluginProps, ) => ( - {typeof Component === 'function' ? Component(el, theme) : Component} + {typeof Component === 'function' ? Component(el, props) : Component} ) @@ -128,10 +129,10 @@ export default function SolidDevtoolsCore({ typeof plugin.name === 'string' ? plugin.name : // The check above confirms that `plugin.name` is of Render type - (el, theme) => - convertRender(el, plugin.name as SolidPluginRender, theme), - render: (el: HTMLDivElement, theme: 'dark' | 'light') => - convertRender(el, plugin.render, theme), + (el, props) => + convertRender(el, plugin.name as SolidPluginRender, props), + render: (el: HTMLDivElement, props: TanStackDevtoolsPluginProps) => + convertRender(el, plugin.render, props), })), ) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d13b7ee2..98f960bf 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -629,6 +629,9 @@ importers: specifier: '>=3.2.0' version: 3.5.25(typescript@5.9.3) devDependencies: + '@tanstack/devtools': + specifier: workspace:^ + version: link:../devtools tsup: specifier: ^8.5.0 version: 8.5.1(@microsoft/api-extractor@7.47.7(@types/node@24.10.4))(jiti@2.6.1)(postcss@8.5.6)(tsx@4.20.3)(typescript@5.9.3)(yaml@2.8.1)