From a06729b6b49cb922a0573cd1d2c0fc105de2ccbb Mon Sep 17 00:00:00 2001 From: Ryota Kameoka Date: Tue, 9 Jul 2024 18:10:10 +0900 Subject: [PATCH] Support the Popover API --- README.md | 8 +++++-- src/jsx-runtime.test.tsx | 46 ++++++++++++++++++++++++++++++++++++++++ src/jsx-runtime.ts | 6 ++++++ src/types.ts | 5 +++++ 4 files changed, 63 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index c22f0eb..5ed92ea 100644 --- a/README.md +++ b/README.md @@ -145,9 +145,10 @@ An attribute starting with `on` will passed to [the event listeners module](http // { on: { click: f } } ``` -### `list` and `role` +### `list`, `role`, and `popoverTarget` -The `list` and the `role` attributes will be passed to [the attributes module](https://github.com/snabbdom/snabbdom#the-attributes-module). +The `list`, the `role`, and the `popoverTarget` attributes will be passed to [the attributes module](https://github.com/snabbdom/snabbdom#the-attributes-module). +Note that the attribute names will be lowercased. ```tsx
@@ -155,6 +156,9 @@ The `list` and the `role` attributes will be passed to [the attributes module](h // { attrs: { list: 'options' } } + + +
Hello, world!
+ , + ).toStrictEqual({ + children: [ + { + children: undefined, + data: { + attrs: { + popovertarget: 'popover', + }, + props: { + popoverTargetAction: 'toggle', + }, + }, + elm: undefined, + key: undefined, + sel: 'button', + text: 'Toggle', + }, + { + children: undefined, + data: { + props: { + popover: 'auto', + }, + }, + elm: undefined, + key: undefined, + sel: 'div', + text: 'Hello, world!', + }, + ], + data: {}, + elm: undefined, + key: undefined, + sel: undefined, + text: undefined, + }); + }); }); diff --git a/src/jsx-runtime.ts b/src/jsx-runtime.ts index 5c72861..6b08402 100644 --- a/src/jsx-runtime.ts +++ b/src/jsx-runtime.ts @@ -63,6 +63,12 @@ const canonicalizeVNodeData = (orig: VNodeData): VNodeData => { } else if (key === 'list' || key === 'role') { data.attrs ??= {}; data.attrs[key] = v; + } else if (key === 'popover' && v === true) { + data.props ??= {}; + data.props['popover'] = 'auto'; + } else if (key === 'popoverTarget') { + data.attrs ??= {}; + data.attrs['popovertarget'] = v; } else if (key === '$style' || key === 'style') { data.style = v; } else if (key.startsWith('$')) { diff --git a/src/types.ts b/src/types.ts index ba23c92..6a60fa7 100644 --- a/src/types.ts +++ b/src/types.ts @@ -336,6 +336,7 @@ export declare namespace Internal { type Dir = 'ltr' | 'rtl' | 'auto' | Whatever; type EnterKeyHint = 'done' | 'enter' | 'go' | 'next' | 'previous' | 'search' | 'send' | Whatever; type InputMode = 'none' | 'text' | 'tel' | 'url' | 'email' | 'numeric' | 'decimal' | 'search' | Whatever; + type Popover = 'auto' | 'manual'; interface Props extends Element.Props { accessKey?: string | undefined; @@ -353,6 +354,7 @@ export declare namespace Internal { noModule?: boolean | undefined; nonce?: string | undefined; outerText?: string | undefined; + popover?: Popover | true | undefined; spellcheck?: boolean | undefined; tabIndex?: number | string | undefined; title?: string | undefined; @@ -408,6 +410,7 @@ export declare namespace Internal { } namespace HTMLButtonElement { + type PopoverTargetAction = 'hide' | 'show' | 'toggle'; type Type = 'button' | 'reset' | 'submit' | Whatever; interface Props extends HTMLElement.Props { @@ -419,6 +422,8 @@ export declare namespace Internal { formNoValidate?: boolean | undefined; formTarget?: string | undefined; name?: string | undefined; + popoverTarget?: string | undefined; + popoverTargetAction?: PopoverTargetAction | undefined; type?: Type | undefined; value?: string; }