shelving 1.282.2 → 1.284.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/package.json +2 -2
- package/ui/README.md +2 -1
- package/ui/block/Address.d.ts +7 -7
- package/ui/block/Address.js +6 -6
- package/ui/block/Address.tsx +10 -9
- package/ui/block/Block.d.ts +3 -3
- package/ui/block/Block.js +3 -2
- package/ui/block/Block.tsx +5 -4
- package/ui/block/Blockquote.d.ts +3 -3
- package/ui/block/Blockquote.js +2 -2
- package/ui/block/Blockquote.tsx +4 -3
- package/ui/block/Caption.d.ts +3 -3
- package/ui/block/Caption.js +3 -3
- package/ui/block/Caption.tsx +5 -4
- package/ui/block/Card.d.ts +3 -2
- package/ui/block/Card.js +2 -2
- package/ui/block/Card.tsx +4 -2
- package/ui/block/Column.d.ts +3 -3
- package/ui/block/Column.js +2 -2
- package/ui/block/Column.tsx +4 -3
- package/ui/block/Definitions.d.ts +3 -3
- package/ui/block/Definitions.js +2 -2
- package/ui/block/Definitions.tsx +4 -3
- package/ui/block/Details.d.ts +3 -2
- package/ui/block/Details.js +2 -2
- package/ui/block/Details.tsx +4 -3
- package/ui/block/Divider.d.ts +3 -2
- package/ui/block/Divider.js +2 -2
- package/ui/block/Divider.tsx +4 -2
- package/ui/block/Heading.d.ts +3 -3
- package/ui/block/Heading.js +2 -2
- package/ui/block/Heading.tsx +4 -3
- package/ui/block/Image.d.ts +3 -2
- package/ui/block/Image.js +2 -2
- package/ui/block/Image.tsx +4 -2
- package/ui/block/Label.d.ts +1 -1
- package/ui/block/Label.js +2 -2
- package/ui/block/Label.tsx +2 -1
- package/ui/block/List.d.ts +3 -2
- package/ui/block/List.js +4 -4
- package/ui/block/List.tsx +6 -4
- package/ui/block/Panel.d.ts +3 -3
- package/ui/block/Panel.js +2 -2
- package/ui/block/Panel.tsx +4 -3
- package/ui/block/Paragraph.d.ts +3 -3
- package/ui/block/Paragraph.js +2 -2
- package/ui/block/Paragraph.tsx +4 -3
- package/ui/block/Preformatted.d.ts +3 -3
- package/ui/block/Preformatted.js +2 -2
- package/ui/block/Preformatted.tsx +4 -3
- package/ui/block/Row.d.ts +3 -3
- package/ui/block/Row.js +2 -2
- package/ui/block/Row.tsx +4 -3
- package/ui/block/Section.js +1 -1
- package/ui/block/Section.tsx +1 -0
- package/ui/block/Subheading.d.ts +1 -1
- package/ui/block/Subheading.js +2 -2
- package/ui/block/Subheading.tsx +2 -1
- package/ui/block/Title.d.ts +1 -1
- package/ui/block/Title.js +2 -2
- package/ui/block/Title.tsx +2 -1
- package/ui/block/Video.d.ts +3 -3
- package/ui/block/Video.js +2 -2
- package/ui/block/Video.tsx +4 -3
- package/ui/button/Button.d.ts +3 -2
- package/ui/button/Button.js +2 -2
- package/ui/button/Button.md +28 -0
- package/ui/button/Button.module.css +23 -5
- package/ui/button/Button.tsx +4 -3
- package/ui/button/Clickable.d.ts +3 -3
- package/ui/button/Clickable.js +6 -4
- package/ui/button/Clickable.tsx +9 -9
- package/ui/button/FullscreenButton.d.ts +3 -5
- package/ui/button/FullscreenButton.tsx +3 -2
- package/ui/button/RetryButton.d.ts +2 -2
- package/ui/button/RetryButton.tsx +2 -2
- package/ui/button/SubmitButton.d.ts +3 -3
- package/ui/button/SubmitButton.js +3 -2
- package/ui/button/SubmitButton.tsx +5 -3
- package/ui/dialog/Dialog.d.ts +6 -4
- package/ui/dialog/Dialog.js +7 -4
- package/ui/dialog/Dialog.tsx +19 -7
- package/ui/dialog/Modal.d.ts +3 -3
- package/ui/dialog/Modal.js +3 -3
- package/ui/dialog/Modal.tsx +5 -5
- package/ui/docs/DocumentationButtons.d.ts +3 -2
- package/ui/docs/DocumentationButtons.js +2 -2
- package/ui/docs/DocumentationButtons.tsx +4 -1
- package/ui/form/Field.d.ts +3 -3
- package/ui/form/Field.js +2 -2
- package/ui/form/Field.tsx +4 -3
- package/ui/form/Form.d.ts +2 -2
- package/ui/form/Form.js +3 -2
- package/ui/form/Form.tsx +5 -3
- package/ui/form/FormFields.d.ts +1 -1
- package/ui/form/FormFields.js +2 -2
- package/ui/form/FormFields.tsx +2 -2
- package/ui/form/FormFooter.d.ts +3 -3
- package/ui/form/FormFooter.js +2 -2
- package/ui/form/FormFooter.tsx +4 -4
- package/ui/form/FormMessage.d.ts +2 -2
- package/ui/form/FormMessage.tsx +2 -3
- package/ui/form/Progress.d.ts +3 -2
- package/ui/form/Progress.js +2 -2
- package/ui/form/Progress.tsx +4 -2
- package/ui/inline/Code.d.ts +3 -3
- package/ui/inline/Code.js +2 -2
- package/ui/inline/Code.tsx +4 -3
- package/ui/inline/Deleted.d.ts +3 -3
- package/ui/inline/Deleted.js +2 -2
- package/ui/inline/Deleted.tsx +4 -3
- package/ui/inline/Emphasis.d.ts +3 -3
- package/ui/inline/Emphasis.js +2 -2
- package/ui/inline/Emphasis.tsx +4 -3
- package/ui/inline/Inserted.d.ts +3 -3
- package/ui/inline/Inserted.js +2 -2
- package/ui/inline/Inserted.tsx +4 -3
- package/ui/inline/Link.d.ts +3 -2
- package/ui/inline/Link.js +2 -2
- package/ui/inline/Link.tsx +4 -2
- package/ui/inline/Mark.d.ts +3 -3
- package/ui/inline/Mark.js +2 -2
- package/ui/inline/Mark.tsx +4 -3
- package/ui/inline/Small.d.ts +3 -3
- package/ui/inline/Small.js +2 -2
- package/ui/inline/Small.tsx +4 -3
- package/ui/inline/Span.d.ts +3 -3
- package/ui/inline/Span.js +3 -2
- package/ui/inline/Span.tsx +5 -4
- package/ui/inline/Strong.d.ts +3 -3
- package/ui/inline/Strong.js +2 -2
- package/ui/inline/Strong.tsx +4 -3
- package/ui/inline/Subscript.d.ts +3 -3
- package/ui/inline/Subscript.js +3 -3
- package/ui/inline/Subscript.tsx +5 -5
- package/ui/inline/Superscript.d.ts +3 -3
- package/ui/inline/Superscript.js +3 -3
- package/ui/inline/Superscript.tsx +5 -5
- package/ui/input/ArrayInput.js +2 -2
- package/ui/input/ArrayInput.tsx +2 -1
- package/ui/input/ArrayRadioInputs.d.ts +1 -1
- package/ui/input/ArrayRadioInputs.js +2 -2
- package/ui/input/ArrayRadioInputs.tsx +2 -1
- package/ui/input/ButtonInput.d.ts +1 -1
- package/ui/input/ButtonInput.js +2 -2
- package/ui/input/ButtonInput.tsx +2 -1
- package/ui/input/CheckboxInput.d.ts +1 -1
- package/ui/input/CheckboxInput.js +2 -2
- package/ui/input/CheckboxInput.tsx +2 -0
- package/ui/input/ChoiceRadioInputs.js +2 -2
- package/ui/input/ChoiceRadioInputs.tsx +2 -1
- package/ui/input/DataInput.js +2 -2
- package/ui/input/DataInput.tsx +2 -1
- package/ui/input/DateInput.d.ts +1 -1
- package/ui/input/DateInput.js +2 -2
- package/ui/input/DateInput.tsx +2 -1
- package/ui/input/DictionaryInput.js +2 -2
- package/ui/input/DictionaryInput.tsx +2 -1
- package/ui/input/FileInput.d.ts +1 -1
- package/ui/input/FileInput.js +3 -2
- package/ui/input/FileInput.tsx +3 -1
- package/ui/input/Input.d.ts +10 -3
- package/ui/input/Input.js +2 -2
- package/ui/input/Input.tsx +11 -4
- package/ui/input/NumberInput.d.ts +1 -1
- package/ui/input/NumberInput.js +2 -2
- package/ui/input/NumberInput.tsx +2 -1
- package/ui/input/OutputInput.d.ts +1 -1
- package/ui/input/OutputInput.js +2 -2
- package/ui/input/OutputInput.tsx +2 -2
- package/ui/input/Popover.d.ts +4 -2
- package/ui/input/Popover.js +4 -3
- package/ui/input/Popover.tsx +6 -3
- package/ui/input/PopoverButton.d.ts +28 -0
- package/ui/input/{ButtonPopover.js → PopoverButton.js} +10 -8
- package/ui/input/PopoverButton.tsx +44 -0
- package/ui/input/PopoverButtonInput.d.ts +27 -0
- package/ui/input/{ButtonInputPopover.js → PopoverButtonInput.js} +10 -8
- package/ui/input/PopoverButtonInput.tsx +44 -0
- package/ui/input/QueryInput.d.ts +1 -1
- package/ui/input/QueryInput.js +2 -2
- package/ui/input/QueryInput.tsx +2 -0
- package/ui/input/RadioInput.d.ts +1 -1
- package/ui/input/RadioInput.js +2 -2
- package/ui/input/RadioInput.tsx +2 -0
- package/ui/input/SchemaInput.d.ts +1 -1
- package/ui/input/SchemaInput.js +2 -2
- package/ui/input/SchemaInput.tsx +2 -2
- package/ui/input/SelectInput.js +2 -2
- package/ui/input/SelectInput.tsx +2 -1
- package/ui/input/TextInput.d.ts +1 -1
- package/ui/input/TextInput.js +3 -3
- package/ui/input/TextInput.tsx +3 -2
- package/ui/input/index.d.ts +2 -2
- package/ui/input/index.js +2 -2
- package/ui/input/index.ts +2 -2
- package/ui/menu/Menu.d.ts +5 -5
- package/ui/menu/Menu.js +4 -4
- package/ui/menu/Menu.tsx +7 -6
- package/ui/misc/Icon.d.ts +2 -1
- package/ui/misc/Icon.js +2 -1
- package/ui/misc/Icon.tsx +3 -1
- package/ui/misc/Loading.d.ts +2 -3
- package/ui/misc/Loading.js +2 -2
- package/ui/misc/Loading.tsx +10 -3
- package/ui/misc/Tag.d.ts +3 -2
- package/ui/misc/Tag.js +2 -2
- package/ui/misc/Tag.tsx +4 -3
- package/ui/notice/Message.d.ts +3 -3
- package/ui/notice/Message.js +2 -2
- package/ui/notice/Message.tsx +4 -3
- package/ui/notice/Notice.d.ts +3 -3
- package/ui/notice/Notice.js +2 -2
- package/ui/notice/Notice.tsx +4 -2
- package/ui/notice/Notices.d.ts +3 -2
- package/ui/notice/Notices.js +2 -2
- package/ui/notice/Notices.tsx +4 -3
- package/ui/table/Cell.d.ts +3 -3
- package/ui/table/Cell.js +2 -2
- package/ui/table/Cell.tsx +4 -3
- package/ui/table/Table.d.ts +3 -3
- package/ui/table/Table.js +2 -2
- package/ui/table/Table.tsx +4 -3
- package/ui/tree/TreeBreadcrumbs.d.ts +3 -2
- package/ui/tree/TreeBreadcrumbs.js +2 -2
- package/ui/tree/TreeBreadcrumbs.tsx +4 -2
- package/ui/tree/TreeButton.d.ts +2 -1
- package/ui/tree/TreeButton.tsx +2 -1
- package/ui/util/ClassProps.md +56 -0
- package/ui/util/css.d.ts +1 -1
- package/ui/util/css.js +2 -2
- package/ui/util/css.test.ts +29 -0
- package/ui/util/css.ts +2 -2
- package/ui/util/props.d.ts +12 -0
- package/ui/util/props.test.tsx +100 -0
- package/ui/util/props.ts +13 -0
- package/ui/input/ButtonInputPopover.d.ts +0 -25
- package/ui/input/ButtonInputPopover.tsx +0 -41
- package/ui/input/ButtonPopover.d.ts +0 -25
- package/ui/input/ButtonPopover.tsx +0 -40
package/ui/input/Popover.tsx
CHANGED
|
@@ -5,9 +5,10 @@ import type { ReactElement, ReactNode } from "react";
|
|
|
5
5
|
|
|
6
6
|
import { isTruthy } from "../../util/boolean.js";
|
|
7
7
|
import type { Callback } from "../../util/function.js";
|
|
8
|
-
import { getModuleClass } from "../util/css.js";
|
|
8
|
+
import { getClass, getModuleClass } from "../util/css.js";
|
|
9
9
|
import { eventPreventDefault } from "../util/event.js";
|
|
10
10
|
import { eventLoopFocus } from "../util/focus.js";
|
|
11
|
+
import type { ClassProps } from "../util/props.js";
|
|
11
12
|
import styles from "./Popover.module.css";
|
|
12
13
|
|
|
13
14
|
/**
|
|
@@ -32,7 +33,7 @@ export type PopoverChildren = readonly [
|
|
|
32
33
|
*
|
|
33
34
|
* @see https://shelving.cc/ui/PopoverProps
|
|
34
35
|
*/
|
|
35
|
-
export interface PopoverProps {
|
|
36
|
+
export interface PopoverProps extends ClassProps {
|
|
36
37
|
/** Children for the popover. */
|
|
37
38
|
children: PopoverChildren;
|
|
38
39
|
/** Callback that gets called when the Popover closes. */
|
|
@@ -45,6 +46,7 @@ export interface PopoverProps {
|
|
|
45
46
|
* Trigger element that reveals a floating popover panel beside it when active or focused.
|
|
46
47
|
* - The first `children` node is the trigger; the rest become the popover contents.
|
|
47
48
|
* - Closes on blur away or `Escape`, calling `onClose`.
|
|
49
|
+
* - `className` lands on the floating panel rather than the wrapper, since the panel is the surface worth styling.
|
|
48
50
|
*
|
|
49
51
|
* @returns A wrapper element containing the trigger and (when open) the popover panel.
|
|
50
52
|
* @example <Popover>{trigger}{panelContent}</Popover>
|
|
@@ -56,6 +58,7 @@ export function Popover({
|
|
|
56
58
|
children: [trigger, ...popover], //
|
|
57
59
|
onClose,
|
|
58
60
|
open = popover.flat().some(isTruthy),
|
|
61
|
+
className,
|
|
59
62
|
}: PopoverProps): ReactElement {
|
|
60
63
|
return (
|
|
61
64
|
<div
|
|
@@ -68,7 +71,7 @@ export function Popover({
|
|
|
68
71
|
>
|
|
69
72
|
{trigger}
|
|
70
73
|
{open ? (
|
|
71
|
-
<section className={getModuleClass(styles, "panel")} onMouseDown={eventPreventDefault}>
|
|
74
|
+
<section className={getClass(getModuleClass(styles, "panel"), className)} onMouseDown={eventPreventDefault}>
|
|
72
75
|
{popover}
|
|
73
76
|
</section>
|
|
74
77
|
) : null}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/** biome-ignore-all lint/a11y/noStaticElementInteractions: This is fine we're only using this to listen for clicks on child buttons. */
|
|
2
|
+
/** biome-ignore-all lint/a11y/useKeyWithClickEvents: This is fine we're only using this to listen for clicks on child buttons. */
|
|
3
|
+
import { type ReactElement } from "react";
|
|
4
|
+
import { type ButtonVariants } from "../button/Button.js";
|
|
5
|
+
import type { ClassProps } from "../util/props.js";
|
|
6
|
+
import { type PopoverChildren } from "./Popover.js";
|
|
7
|
+
/**
|
|
8
|
+
* Props for `PopoverButton` — all the `Button` styling variants, plus `children` whose first node is the button label and the rest the popover contents.
|
|
9
|
+
*
|
|
10
|
+
* @see https://shelving.cc/ui/PopoverButtonProps
|
|
11
|
+
*/
|
|
12
|
+
export interface PopoverButtonProps extends ButtonVariants, ClassProps {
|
|
13
|
+
children: PopoverChildren;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Popover variant of `<Button>` — a button that reveals floating popover content beside it when clicked.
|
|
17
|
+
* - The button is the primary element: it takes all the `ButtonVariants` styling props, and `className` lands on it (not the popover panel).
|
|
18
|
+
* - The first element passed to `children` is the button label; the rest become the popover contents.
|
|
19
|
+
*
|
|
20
|
+
* DH: Would love to use new HTML `popover="auto"` functionality for this but the anchor positioning it needs is not supported everywhere yet.
|
|
21
|
+
*
|
|
22
|
+
* @returns A `Button` that toggles its attached `Popover` open and closed.
|
|
23
|
+
* @example <PopoverButton>{label}{panel}</PopoverButton>
|
|
24
|
+
* @kind component
|
|
25
|
+
* @see https://shelving.cc/ui/PopoverButton
|
|
26
|
+
*/
|
|
27
|
+
export declare function PopoverButton({ children: [buttonChildren, ...popoverChildren], //
|
|
28
|
+
className, ...props }: PopoverButtonProps): ReactElement;
|
|
@@ -5,17 +5,19 @@ import { useState } from "react";
|
|
|
5
5
|
import { Button } from "../button/Button.js";
|
|
6
6
|
import { Popover } from "./Popover.js";
|
|
7
7
|
/**
|
|
8
|
-
*
|
|
9
|
-
* - The
|
|
8
|
+
* Popover variant of `<Button>` — a button that reveals floating popover content beside it when clicked.
|
|
9
|
+
* - The button is the primary element: it takes all the `ButtonVariants` styling props, and `className` lands on it (not the popover panel).
|
|
10
|
+
* - The first element passed to `children` is the button label; the rest become the popover contents.
|
|
10
11
|
*
|
|
11
12
|
* DH: Would love to use new HTML `popover="auto"` functionality for this but the anchor positioning it needs is not supported everywhere yet.
|
|
12
13
|
*
|
|
13
|
-
* @returns A `
|
|
14
|
-
* @example <
|
|
15
|
-
* @
|
|
14
|
+
* @returns A `Button` that toggles its attached `Popover` open and closed.
|
|
15
|
+
* @example <PopoverButton>{label}{panel}</PopoverButton>
|
|
16
|
+
* @kind component
|
|
17
|
+
* @see https://shelving.cc/ui/PopoverButton
|
|
16
18
|
*/
|
|
17
|
-
export function
|
|
18
|
-
...props }) {
|
|
19
|
+
export function PopoverButton({ children: [buttonChildren, ...popoverChildren], //
|
|
20
|
+
className, ...props }) {
|
|
19
21
|
const [open, setOpen] = useState(false);
|
|
20
|
-
return (_jsxs(Popover, { open: open, onClose: () => setOpen(false), children: [_jsx(Button, { onClick: () => setOpen(!open), ...props, children: buttonChildren }), popoverChildren] }));
|
|
22
|
+
return (_jsxs(Popover, { open: open, onClose: () => setOpen(false), children: [_jsx(Button, { onClick: () => setOpen(!open), ...props, className: className, children: buttonChildren }), popoverChildren] }));
|
|
21
23
|
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/** biome-ignore-all lint/a11y/noStaticElementInteractions: This is fine we're only using this to listen for clicks on child buttons. */
|
|
2
|
+
/** biome-ignore-all lint/a11y/useKeyWithClickEvents: This is fine we're only using this to listen for clicks on child buttons. */
|
|
3
|
+
|
|
4
|
+
import { type ReactElement, useState } from "react";
|
|
5
|
+
import { Button, type ButtonVariants } from "../button/Button.js";
|
|
6
|
+
import type { ClassProps } from "../util/props.js";
|
|
7
|
+
import { Popover, type PopoverChildren } from "./Popover.js";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Props for `PopoverButton` — all the `Button` styling variants, plus `children` whose first node is the button label and the rest the popover contents.
|
|
11
|
+
*
|
|
12
|
+
* @see https://shelving.cc/ui/PopoverButtonProps
|
|
13
|
+
*/
|
|
14
|
+
export interface PopoverButtonProps extends ButtonVariants, ClassProps {
|
|
15
|
+
children: PopoverChildren;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Popover variant of `<Button>` — a button that reveals floating popover content beside it when clicked.
|
|
20
|
+
* - The button is the primary element: it takes all the `ButtonVariants` styling props, and `className` lands on it (not the popover panel).
|
|
21
|
+
* - The first element passed to `children` is the button label; the rest become the popover contents.
|
|
22
|
+
*
|
|
23
|
+
* DH: Would love to use new HTML `popover="auto"` functionality for this but the anchor positioning it needs is not supported everywhere yet.
|
|
24
|
+
*
|
|
25
|
+
* @returns A `Button` that toggles its attached `Popover` open and closed.
|
|
26
|
+
* @example <PopoverButton>{label}{panel}</PopoverButton>
|
|
27
|
+
* @kind component
|
|
28
|
+
* @see https://shelving.cc/ui/PopoverButton
|
|
29
|
+
*/
|
|
30
|
+
export function PopoverButton({
|
|
31
|
+
children: [buttonChildren, ...popoverChildren], //
|
|
32
|
+
className,
|
|
33
|
+
...props
|
|
34
|
+
}: PopoverButtonProps): ReactElement {
|
|
35
|
+
const [open, setOpen] = useState(false);
|
|
36
|
+
return (
|
|
37
|
+
<Popover open={open} onClose={() => setOpen(false)}>
|
|
38
|
+
<Button onClick={() => setOpen(!open)} {...props} className={className}>
|
|
39
|
+
{buttonChildren}
|
|
40
|
+
</Button>
|
|
41
|
+
{popoverChildren}
|
|
42
|
+
</Popover>
|
|
43
|
+
);
|
|
44
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/** biome-ignore-all lint/a11y/noStaticElementInteractions: This is fine we're only using this to listen for clicks on child buttons. */
|
|
2
|
+
/** biome-ignore-all lint/a11y/useKeyWithClickEvents: This is fine we're only using this to listen for clicks on child buttons. */
|
|
3
|
+
import { type ReactElement } from "react";
|
|
4
|
+
import type { InputProps } from "./Input.js";
|
|
5
|
+
import { type PopoverChildren } from "./Popover.js";
|
|
6
|
+
/**
|
|
7
|
+
* Props for `PopoverButtonInput` — the shared `InputProps`, plus `children` whose first node is the button label and the rest the popover contents.
|
|
8
|
+
*
|
|
9
|
+
* @see https://shelving.cc/ui/PopoverButtonInputProps
|
|
10
|
+
*/
|
|
11
|
+
export interface PopoverButtonInputProps extends InputProps {
|
|
12
|
+
children: PopoverChildren;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Popover variant of `<ButtonInput>` — an input-styled button that reveals floating popover content beside it when clicked.
|
|
16
|
+
* - The button is the primary element: it takes the shared `InputProps`, and `className` lands on it (not the popover panel).
|
|
17
|
+
* - The first element passed to `children` is the button label; the rest become the popover contents.
|
|
18
|
+
*
|
|
19
|
+
* DH: Would love to use new HTML `popover="auto"` functionality for this but the anchor positioning it needs is not supported everywhere yet.
|
|
20
|
+
*
|
|
21
|
+
* @returns A `ButtonInput` that toggles its attached `Popover` open and closed.
|
|
22
|
+
* @example <PopoverButtonInput name="filter">{label}{panel}</PopoverButtonInput>
|
|
23
|
+
* @kind component
|
|
24
|
+
* @see https://shelving.cc/ui/PopoverButtonInput
|
|
25
|
+
*/
|
|
26
|
+
export declare function PopoverButtonInput({ children: [buttonChildren, ...popoverChildren], //
|
|
27
|
+
className, ...props }: PopoverButtonInputProps): ReactElement;
|
|
@@ -5,17 +5,19 @@ import { useState } from "react";
|
|
|
5
5
|
import { ButtonInput } from "./ButtonInput.js";
|
|
6
6
|
import { Popover } from "./Popover.js";
|
|
7
7
|
/**
|
|
8
|
-
*
|
|
9
|
-
* - The
|
|
8
|
+
* Popover variant of `<ButtonInput>` — an input-styled button that reveals floating popover content beside it when clicked.
|
|
9
|
+
* - The button is the primary element: it takes the shared `InputProps`, and `className` lands on it (not the popover panel).
|
|
10
|
+
* - The first element passed to `children` is the button label; the rest become the popover contents.
|
|
10
11
|
*
|
|
11
12
|
* DH: Would love to use new HTML `popover="auto"` functionality for this but the anchor positioning it needs is not supported everywhere yet.
|
|
12
13
|
*
|
|
13
|
-
* @returns A `
|
|
14
|
-
* @example <
|
|
15
|
-
* @
|
|
14
|
+
* @returns A `ButtonInput` that toggles its attached `Popover` open and closed.
|
|
15
|
+
* @example <PopoverButtonInput name="filter">{label}{panel}</PopoverButtonInput>
|
|
16
|
+
* @kind component
|
|
17
|
+
* @see https://shelving.cc/ui/PopoverButtonInput
|
|
16
18
|
*/
|
|
17
|
-
export function
|
|
18
|
-
...props }) {
|
|
19
|
+
export function PopoverButtonInput({ children: [buttonChildren, ...popoverChildren], //
|
|
20
|
+
className, ...props }) {
|
|
19
21
|
const [open, setOpen] = useState(false);
|
|
20
|
-
return (_jsxs(Popover, { open: open, onClose: () => setOpen(false), children: [_jsx(ButtonInput, { onClick: () => setOpen(!open), ...props, children: buttonChildren }), popoverChildren] }));
|
|
22
|
+
return (_jsxs(Popover, { open: open, onClose: () => setOpen(false), children: [_jsx(ButtonInput, { onClick: () => setOpen(!open), ...props, className: className, children: buttonChildren }), popoverChildren] }));
|
|
21
23
|
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/** biome-ignore-all lint/a11y/noStaticElementInteractions: This is fine we're only using this to listen for clicks on child buttons. */
|
|
2
|
+
/** biome-ignore-all lint/a11y/useKeyWithClickEvents: This is fine we're only using this to listen for clicks on child buttons. */
|
|
3
|
+
|
|
4
|
+
import { type ReactElement, useState } from "react";
|
|
5
|
+
import { ButtonInput } from "./ButtonInput.js";
|
|
6
|
+
import type { InputProps } from "./Input.js";
|
|
7
|
+
import { Popover, type PopoverChildren } from "./Popover.js";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Props for `PopoverButtonInput` — the shared `InputProps`, plus `children` whose first node is the button label and the rest the popover contents.
|
|
11
|
+
*
|
|
12
|
+
* @see https://shelving.cc/ui/PopoverButtonInputProps
|
|
13
|
+
*/
|
|
14
|
+
export interface PopoverButtonInputProps extends InputProps {
|
|
15
|
+
children: PopoverChildren;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Popover variant of `<ButtonInput>` — an input-styled button that reveals floating popover content beside it when clicked.
|
|
20
|
+
* - The button is the primary element: it takes the shared `InputProps`, and `className` lands on it (not the popover panel).
|
|
21
|
+
* - The first element passed to `children` is the button label; the rest become the popover contents.
|
|
22
|
+
*
|
|
23
|
+
* DH: Would love to use new HTML `popover="auto"` functionality for this but the anchor positioning it needs is not supported everywhere yet.
|
|
24
|
+
*
|
|
25
|
+
* @returns A `ButtonInput` that toggles its attached `Popover` open and closed.
|
|
26
|
+
* @example <PopoverButtonInput name="filter">{label}{panel}</PopoverButtonInput>
|
|
27
|
+
* @kind component
|
|
28
|
+
* @see https://shelving.cc/ui/PopoverButtonInput
|
|
29
|
+
*/
|
|
30
|
+
export function PopoverButtonInput({
|
|
31
|
+
children: [buttonChildren, ...popoverChildren], //
|
|
32
|
+
className,
|
|
33
|
+
...props
|
|
34
|
+
}: PopoverButtonInputProps): ReactElement {
|
|
35
|
+
const [open, setOpen] = useState(false);
|
|
36
|
+
return (
|
|
37
|
+
<Popover open={open} onClose={() => setOpen(false)}>
|
|
38
|
+
<ButtonInput onClick={() => setOpen(!open)} {...props} className={className}>
|
|
39
|
+
{buttonChildren}
|
|
40
|
+
</ButtonInput>
|
|
41
|
+
{popoverChildren}
|
|
42
|
+
</Popover>
|
|
43
|
+
);
|
|
44
|
+
}
|
package/ui/input/QueryInput.d.ts
CHANGED
|
@@ -33,4 +33,4 @@ export interface QueryInputProps<I, O> extends ValueInputProps<O> {
|
|
|
33
33
|
* @example <QueryInput schema={SEARCH} onQuery={search} value={user} onValue={setUser} />
|
|
34
34
|
* @see https://shelving.cc/ui/QueryInput
|
|
35
35
|
*/
|
|
36
|
-
export declare function QueryInput<I, O>({ empty, value, onValue, onQuery, formatter, ...props }: QueryInputProps<I, O>): ReactElement;
|
|
36
|
+
export declare function QueryInput<I, O>({ empty, value, onValue, onQuery, formatter, className, ...props }: QueryInputProps<I, O>): ReactElement;
|
package/ui/input/QueryInput.js
CHANGED
|
@@ -19,7 +19,7 @@ import { SchemaInput } from "./SchemaInput.js";
|
|
|
19
19
|
* @example <QueryInput schema={SEARCH} onQuery={search} value={user} onValue={setUser} />
|
|
20
20
|
* @see https://shelving.cc/ui/QueryInput
|
|
21
21
|
*/
|
|
22
|
-
export function QueryInput({ empty = "No results", value, onValue, onQuery, formatter = formatValue, ...props }) {
|
|
22
|
+
export function QueryInput({ empty = "No results", value, onValue, onQuery, formatter = formatValue, className, ...props }) {
|
|
23
23
|
const store = useStore(useInstance(PayloadFetchStore, NONE, undefined, onQuery, SECOND));
|
|
24
24
|
const busy = useStore(store.busy).value;
|
|
25
25
|
// Is popover open?
|
|
@@ -28,7 +28,7 @@ export function QueryInput({ empty = "No results", value, onValue, onQuery, form
|
|
|
28
28
|
store.payload.value = NONE;
|
|
29
29
|
store.value = undefined;
|
|
30
30
|
};
|
|
31
|
-
return (_jsxs(Popover, { open: isOpen, onClose: close, children: [_jsx(SchemaInput, { ...props, value: value, onValue: v => {
|
|
31
|
+
return (_jsxs(Popover, { open: isOpen, onClose: close, children: [_jsx(SchemaInput, { ...props, className: className, value: value, onValue: v => {
|
|
32
32
|
if (v)
|
|
33
33
|
store.payload.value = v;
|
|
34
34
|
else
|
package/ui/input/QueryInput.tsx
CHANGED
|
@@ -53,6 +53,7 @@ export function QueryInput<I, O>({
|
|
|
53
53
|
onValue,
|
|
54
54
|
onQuery,
|
|
55
55
|
formatter = formatValue,
|
|
56
|
+
className,
|
|
56
57
|
...props
|
|
57
58
|
}: QueryInputProps<I, O>): ReactElement {
|
|
58
59
|
const store = useStore(useInstance(PayloadFetchStore, NONE, undefined, onQuery, SECOND));
|
|
@@ -70,6 +71,7 @@ export function QueryInput<I, O>({
|
|
|
70
71
|
<Popover open={isOpen} onClose={close}>
|
|
71
72
|
<SchemaInput
|
|
72
73
|
{...props}
|
|
74
|
+
className={className}
|
|
73
75
|
value={value as I}
|
|
74
76
|
onValue={v => {
|
|
75
77
|
if (v) store.payload.value = v;
|
package/ui/input/RadioInput.d.ts
CHANGED
|
@@ -17,4 +17,4 @@ export interface RadioInputProps extends ValueInputProps<boolean>, OptionalChild
|
|
|
17
17
|
* @example <RadioInput name="plan" value={isPro} onValue={selectPro}>Pro</RadioInput>
|
|
18
18
|
* @see https://shelving.cc/ui/RadioInput
|
|
19
19
|
*/
|
|
20
|
-
export declare function RadioInput({ name, title, placeholder, required, disabled, message, value, onValue, children, ...props }: RadioInputProps): ReactElement;
|
|
20
|
+
export declare function RadioInput({ name, title, placeholder, required, disabled, message, value, onValue, children, className, ...props }: RadioInputProps): ReactElement;
|
package/ui/input/RadioInput.js
CHANGED
|
@@ -12,7 +12,7 @@ const INPUT_LABEL_CLASS = getModuleClass(INPUT_CSS, "label");
|
|
|
12
12
|
* @example <RadioInput name="plan" value={isPro} onValue={selectPro}>Pro</RadioInput>
|
|
13
13
|
* @see https://shelving.cc/ui/RadioInput
|
|
14
14
|
*/
|
|
15
|
-
export function RadioInput({ name, title, placeholder = title || "Choose", required = false, disabled = false, message = "", value = false, onValue, children = placeholder, ...props }) {
|
|
15
|
+
export function RadioInput({ name, title, placeholder = title || "Choose", required = false, disabled = false, message = "", value = false, onValue, children = placeholder, className, ...props }) {
|
|
16
16
|
return (_jsxs("label", { className: getClass(getInputClass(props), //
|
|
17
|
-
getFlexClass(props), INPUT_LABEL_CLASS), children: [_jsx("input", { className: getModuleClass(INPUT_CSS, "radio"), type: "radio", name: name, defaultChecked: !!value, onChange: () => onValue(true), disabled: disabled, required: required, title: message, "aria-invalid": !!message }), _jsx("span", { children: children })] }));
|
|
17
|
+
getFlexClass(props), INPUT_LABEL_CLASS, className), children: [_jsx("input", { className: getModuleClass(INPUT_CSS, "radio"), type: "radio", name: name, defaultChecked: !!value, onChange: () => onValue(true), disabled: disabled, required: required, title: message, "aria-invalid": !!message }), _jsx("span", { children: children })] }));
|
|
18
18
|
}
|
package/ui/input/RadioInput.tsx
CHANGED
|
@@ -32,6 +32,7 @@ export function RadioInput({
|
|
|
32
32
|
value = false,
|
|
33
33
|
onValue,
|
|
34
34
|
children = placeholder,
|
|
35
|
+
className,
|
|
35
36
|
...props
|
|
36
37
|
}: RadioInputProps): ReactElement {
|
|
37
38
|
return (
|
|
@@ -40,6 +41,7 @@ export function RadioInput({
|
|
|
40
41
|
getInputClass(props), //
|
|
41
42
|
getFlexClass(props),
|
|
42
43
|
INPUT_LABEL_CLASS,
|
|
44
|
+
className,
|
|
43
45
|
)}
|
|
44
46
|
>
|
|
45
47
|
<input
|
|
@@ -185,4 +185,4 @@ export interface SchemaFieldProps extends SchemaInputProps<Schema, unknown>, Opt
|
|
|
185
185
|
* @kind component
|
|
186
186
|
* @see https://shelving.cc/ui/SchemaField
|
|
187
187
|
*/
|
|
188
|
-
export declare function SchemaField({ schema, children, ...props }: SchemaFieldProps): ReactElement;
|
|
188
|
+
export declare function SchemaField({ schema, children, className, ...props }: SchemaFieldProps): ReactElement;
|
package/ui/input/SchemaInput.js
CHANGED
|
@@ -173,6 +173,6 @@ export function DataSchemaInput({ schema, value, ...props }) {
|
|
|
173
173
|
* @kind component
|
|
174
174
|
* @see https://shelving.cc/ui/SchemaField
|
|
175
175
|
*/
|
|
176
|
-
export function SchemaField({ schema, children, ...props }) {
|
|
177
|
-
return (_jsx(Field, { ...props, ...schema, children: children ?? _jsx(SchemaInput, { schema: schema, ...props }) }));
|
|
176
|
+
export function SchemaField({ schema, children, className, ...props }) {
|
|
177
|
+
return (_jsx(Field, { ...props, ...schema, className: className, children: children ?? _jsx(SchemaInput, { schema: schema, ...props }) }));
|
|
178
178
|
}
|
package/ui/input/SchemaInput.tsx
CHANGED
|
@@ -274,9 +274,9 @@ export interface SchemaFieldProps extends SchemaInputProps<Schema, unknown>, Opt
|
|
|
274
274
|
* @kind component
|
|
275
275
|
* @see https://shelving.cc/ui/SchemaField
|
|
276
276
|
*/
|
|
277
|
-
export function SchemaField({ schema, children, ...props }: SchemaFieldProps): ReactElement {
|
|
277
|
+
export function SchemaField({ schema, children, className, ...props }: SchemaFieldProps): ReactElement {
|
|
278
278
|
return (
|
|
279
|
-
<Field {...props} {...schema}>
|
|
279
|
+
<Field {...props} {...schema} className={className}>
|
|
280
280
|
{children ?? <SchemaInput schema={schema} {...props} />}
|
|
281
281
|
</Field>
|
|
282
282
|
);
|
package/ui/input/SelectInput.js
CHANGED
|
@@ -3,6 +3,6 @@ import { getProps } from "../../util/object.js";
|
|
|
3
3
|
import { getClass, getModuleClass } from "../util/css.js";
|
|
4
4
|
import { getInputClass } from "./Input.js";
|
|
5
5
|
import INPUT_CSS from "./Input.module.css";
|
|
6
|
-
export function SelectInput({ name, placeholder = "Choose...", required = false, disabled = false, message = "", value = "", onValue, options, ...variants }) {
|
|
7
|
-
return (_jsxs("select", { name: name, defaultValue: value, onChange: e => onValue(e.currentTarget.value || undefined), className: getClass(getInputClass(variants), getModuleClass(INPUT_CSS, "select")), title: message, "aria-invalid": !!message, disabled: disabled, required: required, children: [!required || !value ? (_jsx("option", { value: "", className: getModuleClass(INPUT_CSS, "empty"), children: placeholder })) : null, getProps(options).map(([k, t]) => (_jsx("option", { value: k, className: getModuleClass(INPUT_CSS, "value"), children: t }, k)))] }));
|
|
6
|
+
export function SelectInput({ name, placeholder = "Choose...", required = false, disabled = false, message = "", value = "", onValue, options, className, ...variants }) {
|
|
7
|
+
return (_jsxs("select", { name: name, defaultValue: value, onChange: e => onValue(e.currentTarget.value || undefined), className: getClass(getInputClass(variants), getModuleClass(INPUT_CSS, "select"), className), title: message, "aria-invalid": !!message, disabled: disabled, required: required, children: [!required || !value ? (_jsx("option", { value: "", className: getModuleClass(INPUT_CSS, "empty"), children: placeholder })) : null, getProps(options).map(([k, t]) => (_jsx("option", { value: k, className: getModuleClass(INPUT_CSS, "value"), children: t }, k)))] }));
|
|
8
8
|
}
|
package/ui/input/SelectInput.tsx
CHANGED
|
@@ -34,6 +34,7 @@ export function SelectInput({
|
|
|
34
34
|
value = "",
|
|
35
35
|
onValue,
|
|
36
36
|
options,
|
|
37
|
+
className,
|
|
37
38
|
...variants
|
|
38
39
|
}: SelectProps<string>): ReactElement {
|
|
39
40
|
return (
|
|
@@ -41,7 +42,7 @@ export function SelectInput({
|
|
|
41
42
|
name={name}
|
|
42
43
|
defaultValue={value}
|
|
43
44
|
onChange={e => onValue(e.currentTarget.value || undefined)}
|
|
44
|
-
className={getClass(getInputClass(variants), getModuleClass(INPUT_CSS, "select"))}
|
|
45
|
+
className={getClass(getInputClass(variants), getModuleClass(INPUT_CSS, "select"), className)}
|
|
45
46
|
title={message}
|
|
46
47
|
aria-invalid={!!message}
|
|
47
48
|
disabled={disabled}
|
package/ui/input/TextInput.d.ts
CHANGED
|
@@ -26,5 +26,5 @@ export interface TextInputProps extends ValueInputProps<string>, InputVariants {
|
|
|
26
26
|
* @see https://shelving.cc/ui/TextInput
|
|
27
27
|
*/
|
|
28
28
|
export declare function TextInput({ name, title, placeholder, // Placeholder must be defined or `:placeholder-shown` CSS rules won't show.
|
|
29
|
-
required, disabled, message, value, onValue, input, min, max, rows, formatter, ...variants }: TextInputProps): ReactElement;
|
|
29
|
+
required, disabled, message, value, onValue, input, min, max, rows, formatter, className, ...variants }: TextInputProps): ReactElement;
|
|
30
30
|
export {};
|
package/ui/input/TextInput.js
CHANGED
|
@@ -13,7 +13,7 @@ import INPUT_CSS from "./Input.module.css";
|
|
|
13
13
|
* @see https://shelving.cc/ui/TextInput
|
|
14
14
|
*/
|
|
15
15
|
export function TextInput({ name, title = "", placeholder = title, // Placeholder must be defined or `:placeholder-shown` CSS rules won't show.
|
|
16
|
-
required = false, disabled = false, message = "", value, onValue, input = "text", min = 0, max = Number.POSITIVE_INFINITY, rows = 1, formatter = PASSTHROUGH, ...variants }) {
|
|
16
|
+
required = false, disabled = false, message = "", value, onValue, input = "text", min = 0, max = Number.POSITIVE_INFINITY, rows = 1, formatter = PASSTHROUGH, className, ...variants }) {
|
|
17
17
|
const onBlur = ({ currentTarget }) => {
|
|
18
18
|
currentTarget.value = formatter(currentTarget.value);
|
|
19
19
|
};
|
|
@@ -22,12 +22,12 @@ required = false, disabled = false, message = "", value, onValue, input = "text"
|
|
|
22
22
|
onValue?.(formatter(e.currentTarget.value));
|
|
23
23
|
_resize(e.currentTarget, rows);
|
|
24
24
|
};
|
|
25
|
-
return (_jsx("textarea", { ref: el => void (el && _resize(el, rows)), name: name, defaultValue: value !== undefined ? formatter(value) : "", minLength: Number.isFinite(min) ? min : 0, maxLength: Number.isFinite(max) ? max : undefined, rows: rows, required: required && min > 0, disabled: disabled, placeholder: placeholder || " ", className: getClass(getInputClass(variants), getModuleClass(INPUT_CSS, "text"), getModuleClass(INPUT_CSS, "multiline")), onInput: onChange, onChange: onChange, onBlur: onBlur, title: message, "aria-invalid": !!message }));
|
|
25
|
+
return (_jsx("textarea", { ref: el => void (el && _resize(el, rows)), name: name, defaultValue: value !== undefined ? formatter(value) : "", minLength: Number.isFinite(min) ? min : 0, maxLength: Number.isFinite(max) ? max : undefined, rows: rows, required: required && min > 0, disabled: disabled, placeholder: placeholder || " ", className: getClass(getInputClass(variants), getModuleClass(INPUT_CSS, "text"), getModuleClass(INPUT_CSS, "multiline"), className), onInput: onChange, onChange: onChange, onBlur: onBlur, title: message, "aria-invalid": !!message }));
|
|
26
26
|
}
|
|
27
27
|
const onChange = (e) => {
|
|
28
28
|
onValue?.(formatter(e.currentTarget.value));
|
|
29
29
|
};
|
|
30
|
-
return (_jsx("input", { name: name, type: input, defaultValue: value !== undefined ? formatter(value) : "", minLength: Number.isFinite(min) ? min : 0, maxLength: Number.isFinite(max) ? max : undefined, required: required && min > 0, disabled: disabled, placeholder: placeholder || " ", className: getClass(getInputClass(variants), getModuleClass(INPUT_CSS, "text")), onInput: onChange, onChange: onChange, onBlur: onBlur, title: message, "aria-invalid": !!message }));
|
|
30
|
+
return (_jsx("input", { name: name, type: input, defaultValue: value !== undefined ? formatter(value) : "", minLength: Number.isFinite(min) ? min : 0, maxLength: Number.isFinite(max) ? max : undefined, required: required && min > 0, disabled: disabled, placeholder: placeholder || " ", className: getClass(getInputClass(variants), getModuleClass(INPUT_CSS, "text"), className), onInput: onChange, onChange: onChange, onBlur: onBlur, title: message, "aria-invalid": !!message }));
|
|
31
31
|
}
|
|
32
32
|
/**
|
|
33
33
|
* @todo This can be removed when Firefox supports `field-sizing:` in CSS.
|
package/ui/input/TextInput.tsx
CHANGED
|
@@ -45,6 +45,7 @@ export function TextInput({
|
|
|
45
45
|
max = Number.POSITIVE_INFINITY,
|
|
46
46
|
rows = 1,
|
|
47
47
|
formatter = PASSTHROUGH,
|
|
48
|
+
className,
|
|
48
49
|
...variants
|
|
49
50
|
}: TextInputProps): ReactElement {
|
|
50
51
|
const onBlur = ({ currentTarget }: SyntheticEvent<HTMLInputElement | HTMLTextAreaElement>) => {
|
|
@@ -68,7 +69,7 @@ export function TextInput({
|
|
|
68
69
|
required={required && min > 0}
|
|
69
70
|
disabled={disabled}
|
|
70
71
|
placeholder={placeholder || " "}
|
|
71
|
-
className={getClass(getInputClass(variants), getModuleClass(INPUT_CSS, "text"), getModuleClass(INPUT_CSS, "multiline"))}
|
|
72
|
+
className={getClass(getInputClass(variants), getModuleClass(INPUT_CSS, "text"), getModuleClass(INPUT_CSS, "multiline"), className)}
|
|
72
73
|
onInput={onChange}
|
|
73
74
|
onChange={onChange}
|
|
74
75
|
onBlur={onBlur}
|
|
@@ -92,7 +93,7 @@ export function TextInput({
|
|
|
92
93
|
required={required && min > 0}
|
|
93
94
|
disabled={disabled}
|
|
94
95
|
placeholder={placeholder || " "}
|
|
95
|
-
className={getClass(getInputClass(variants), getModuleClass(INPUT_CSS, "text"))}
|
|
96
|
+
className={getClass(getInputClass(variants), getModuleClass(INPUT_CSS, "text"), className)}
|
|
96
97
|
onInput={onChange}
|
|
97
98
|
onChange={onChange}
|
|
98
99
|
onBlur={onBlur}
|
package/ui/input/index.d.ts
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
export * from "./ArrayInput.js";
|
|
2
2
|
export * from "./ArrayRadioInputs.js";
|
|
3
3
|
export * from "./ButtonInput.js";
|
|
4
|
-
export * from "./ButtonInputPopover.js";
|
|
5
|
-
export * from "./ButtonPopover.js";
|
|
6
4
|
export * from "./CheckboxInput.js";
|
|
7
5
|
export * from "./ChoiceRadioInputs.js";
|
|
8
6
|
export * from "./DataInput.js";
|
|
@@ -13,6 +11,8 @@ export * from "./Input.js";
|
|
|
13
11
|
export * from "./NumberInput.js";
|
|
14
12
|
export * from "./OutputInput.js";
|
|
15
13
|
export * from "./Popover.js";
|
|
14
|
+
export * from "./PopoverButton.js";
|
|
15
|
+
export * from "./PopoverButtonInput.js";
|
|
16
16
|
export * from "./QueryInput.js";
|
|
17
17
|
export * from "./RadioInput.js";
|
|
18
18
|
export * from "./SchemaInput.js";
|
package/ui/input/index.js
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
export * from "./ArrayInput.js";
|
|
2
2
|
export * from "./ArrayRadioInputs.js";
|
|
3
3
|
export * from "./ButtonInput.js";
|
|
4
|
-
export * from "./ButtonInputPopover.js";
|
|
5
|
-
export * from "./ButtonPopover.js";
|
|
6
4
|
export * from "./CheckboxInput.js";
|
|
7
5
|
export * from "./ChoiceRadioInputs.js";
|
|
8
6
|
export * from "./DataInput.js";
|
|
@@ -13,6 +11,8 @@ export * from "./Input.js";
|
|
|
13
11
|
export * from "./NumberInput.js";
|
|
14
12
|
export * from "./OutputInput.js";
|
|
15
13
|
export * from "./Popover.js";
|
|
14
|
+
export * from "./PopoverButton.js";
|
|
15
|
+
export * from "./PopoverButtonInput.js";
|
|
16
16
|
export * from "./QueryInput.js";
|
|
17
17
|
export * from "./RadioInput.js";
|
|
18
18
|
export * from "./SchemaInput.js";
|
package/ui/input/index.ts
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
export * from "./ArrayInput.js";
|
|
2
2
|
export * from "./ArrayRadioInputs.js";
|
|
3
3
|
export * from "./ButtonInput.js";
|
|
4
|
-
export * from "./ButtonInputPopover.js";
|
|
5
|
-
export * from "./ButtonPopover.js";
|
|
6
4
|
export * from "./CheckboxInput.js";
|
|
7
5
|
export * from "./ChoiceRadioInputs.js";
|
|
8
6
|
export * from "./DataInput.js";
|
|
@@ -13,6 +11,8 @@ export * from "./Input.js";
|
|
|
13
11
|
export * from "./NumberInput.js";
|
|
14
12
|
export * from "./OutputInput.js";
|
|
15
13
|
export * from "./Popover.js";
|
|
14
|
+
export * from "./PopoverButton.js";
|
|
15
|
+
export * from "./PopoverButtonInput.js";
|
|
16
16
|
export * from "./QueryInput.js";
|
|
17
17
|
export * from "./RadioInput.js";
|
|
18
18
|
export * from "./SchemaInput.js";
|
package/ui/menu/Menu.d.ts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import type { ReactNode } from "react";
|
|
2
2
|
import { type ClickableProps } from "../button/Clickable.js";
|
|
3
3
|
import { type BlockVariants } from "../style/Block.js";
|
|
4
|
-
import type { OptionalChildProps } from "../util/props.js";
|
|
4
|
+
import type { ClassProps, OptionalChildProps } from "../util/props.js";
|
|
5
5
|
/**
|
|
6
6
|
* Props for `<Menu>` — optional `<MenuItem>` `children`.
|
|
7
7
|
*
|
|
8
8
|
* @see https://shelving.cc/ui/MenuProps
|
|
9
9
|
*/
|
|
10
|
-
export interface MenuProps extends BlockVariants, OptionalChildProps {
|
|
10
|
+
export interface MenuProps extends BlockVariants, OptionalChildProps, ClassProps {
|
|
11
11
|
}
|
|
12
12
|
/**
|
|
13
13
|
* A `<menu>` list of `<MenuItem>` children.
|
|
@@ -17,13 +17,13 @@ export interface MenuProps extends BlockVariants, OptionalChildProps {
|
|
|
17
17
|
* @kind component
|
|
18
18
|
* @see https://shelving.cc/ui/Menu
|
|
19
19
|
*/
|
|
20
|
-
export declare function Menu({ children, ...props }: MenuProps): ReactNode;
|
|
20
|
+
export declare function Menu({ children, className, ...props }: MenuProps): ReactNode;
|
|
21
21
|
/**
|
|
22
22
|
* Props for `<MenuItem>` — `<Clickable>` props plus `children` whose first node is the label and the rest the submenu.
|
|
23
23
|
*
|
|
24
24
|
* @see https://shelving.cc/ui/MenuItemProps
|
|
25
25
|
*/
|
|
26
|
-
export interface MenuItemProps extends ClickableProps {
|
|
26
|
+
export interface MenuItemProps extends ClickableProps, ClassProps {
|
|
27
27
|
/**
|
|
28
28
|
* The first child becomes the link label (rendered inside the `<a>`).
|
|
29
29
|
* - Any additional children form the submenu — only rendered when this item is "proud" (an ancestor of the current page). The caller is responsible for wrapping the submenu in a nested `<Menu>` if it wants the CSS `.menu .menu` descendant rules to apply.
|
|
@@ -38,4 +38,4 @@ export interface MenuItemProps extends ClickableProps {
|
|
|
38
38
|
* @kind component
|
|
39
39
|
* @see https://shelving.cc/ui/MenuItem
|
|
40
40
|
*/
|
|
41
|
-
export declare function MenuItem({ href, children, ...props }: MenuItemProps): ReactNode;
|
|
41
|
+
export declare function MenuItem({ href, children, className, ...props }: MenuItemProps): ReactNode;
|
package/ui/menu/Menu.js
CHANGED
|
@@ -19,9 +19,9 @@ const MENU_ACTIVE_CLASS = getModuleClass(MENU_CSS, "active");
|
|
|
19
19
|
* @kind component
|
|
20
20
|
* @see https://shelving.cc/ui/Menu
|
|
21
21
|
*/
|
|
22
|
-
export function Menu({ children, ...props }) {
|
|
22
|
+
export function Menu({ children, className, ...props }) {
|
|
23
23
|
return (_jsx("menu", { className: getClass(MENU_CLASS, //
|
|
24
|
-
getBlockClass(props)), children: children }));
|
|
24
|
+
getBlockClass(props), className), children: children }));
|
|
25
25
|
}
|
|
26
26
|
/**
|
|
27
27
|
* A `<li>` containing an `<a>` link, plus optional submenu content shown when this item is "proud".
|
|
@@ -31,12 +31,12 @@ export function Menu({ children, ...props }) {
|
|
|
31
31
|
* @kind component
|
|
32
32
|
* @see https://shelving.cc/ui/MenuItem
|
|
33
33
|
*/
|
|
34
|
-
export function MenuItem({ href, children, ...props }) {
|
|
34
|
+
export function MenuItem({ href, children, className, ...props }) {
|
|
35
35
|
const { url, root } = requireMeta();
|
|
36
36
|
const link = getLink(href, url, root);
|
|
37
37
|
const proud = isURLProud(url, link);
|
|
38
38
|
const active = isURLActive(url, link);
|
|
39
39
|
const [label, ...after] = isArray(children) ? children : [children];
|
|
40
|
-
return (_jsxs("li", { className: MENU_ITEM_CLASS, children: [_jsx(Clickable, { href: href, ...props, className: getClass(MENU_LINK_CLASS, //
|
|
40
|
+
return (_jsxs("li", { className: getClass(MENU_ITEM_CLASS, className), children: [_jsx(Clickable, { href: href, ...props, className: getClass(MENU_LINK_CLASS, //
|
|
41
41
|
proud && MENU_PROUD_CLASS, active && MENU_ACTIVE_CLASS), children: label }), proud && after] }));
|
|
42
42
|
}
|
package/ui/menu/Menu.tsx
CHANGED
|
@@ -5,7 +5,7 @@ import { Clickable, type ClickableProps } from "../button/Clickable.js";
|
|
|
5
5
|
import { requireMeta } from "../misc/MetaContext.js";
|
|
6
6
|
import { type BlockVariants, getBlockClass } from "../style/Block.js";
|
|
7
7
|
import { getClass, getModuleClass } from "../util/css.js";
|
|
8
|
-
import type { OptionalChildProps } from "../util/props.js";
|
|
8
|
+
import type { ClassProps, OptionalChildProps } from "../util/props.js";
|
|
9
9
|
import MENU_CSS from "./Menu.module.css";
|
|
10
10
|
|
|
11
11
|
const MENU_CLASS = getModuleClass(MENU_CSS, "menu");
|
|
@@ -19,7 +19,7 @@ const MENU_ACTIVE_CLASS = getModuleClass(MENU_CSS, "active");
|
|
|
19
19
|
*
|
|
20
20
|
* @see https://shelving.cc/ui/MenuProps
|
|
21
21
|
*/
|
|
22
|
-
export interface MenuProps extends BlockVariants, OptionalChildProps {}
|
|
22
|
+
export interface MenuProps extends BlockVariants, OptionalChildProps, ClassProps {}
|
|
23
23
|
|
|
24
24
|
/**
|
|
25
25
|
* A `<menu>` list of `<MenuItem>` children.
|
|
@@ -29,12 +29,13 @@ export interface MenuProps extends BlockVariants, OptionalChildProps {}
|
|
|
29
29
|
* @kind component
|
|
30
30
|
* @see https://shelving.cc/ui/Menu
|
|
31
31
|
*/
|
|
32
|
-
export function Menu({ children, ...props }: MenuProps): ReactNode {
|
|
32
|
+
export function Menu({ children, className, ...props }: MenuProps): ReactNode {
|
|
33
33
|
return (
|
|
34
34
|
<menu
|
|
35
35
|
className={getClass(
|
|
36
36
|
MENU_CLASS, //
|
|
37
37
|
getBlockClass(props),
|
|
38
|
+
className,
|
|
38
39
|
)}
|
|
39
40
|
>
|
|
40
41
|
{children}
|
|
@@ -47,7 +48,7 @@ export function Menu({ children, ...props }: MenuProps): ReactNode {
|
|
|
47
48
|
*
|
|
48
49
|
* @see https://shelving.cc/ui/MenuItemProps
|
|
49
50
|
*/
|
|
50
|
-
export interface MenuItemProps extends ClickableProps {
|
|
51
|
+
export interface MenuItemProps extends ClickableProps, ClassProps {
|
|
51
52
|
/**
|
|
52
53
|
* The first child becomes the link label (rendered inside the `<a>`).
|
|
53
54
|
* - Any additional children form the submenu — only rendered when this item is "proud" (an ancestor of the current page). The caller is responsible for wrapping the submenu in a nested `<Menu>` if it wants the CSS `.menu .menu` descendant rules to apply.
|
|
@@ -63,14 +64,14 @@ export interface MenuItemProps extends ClickableProps {
|
|
|
63
64
|
* @kind component
|
|
64
65
|
* @see https://shelving.cc/ui/MenuItem
|
|
65
66
|
*/
|
|
66
|
-
export function MenuItem({ href, children, ...props }: MenuItemProps): ReactNode {
|
|
67
|
+
export function MenuItem({ href, children, className, ...props }: MenuItemProps): ReactNode {
|
|
67
68
|
const { url, root } = requireMeta();
|
|
68
69
|
const link = getLink(href, url, root);
|
|
69
70
|
const proud = isURLProud(url, link);
|
|
70
71
|
const active = isURLActive(url, link);
|
|
71
72
|
const [label, ...after] = isArray(children) ? children : [children];
|
|
72
73
|
return (
|
|
73
|
-
<li className={MENU_ITEM_CLASS}>
|
|
74
|
+
<li className={getClass(MENU_ITEM_CLASS, className)}>
|
|
74
75
|
<Clickable
|
|
75
76
|
href={href}
|
|
76
77
|
{...props}
|