@allxsmith/bestax-bulma 5.62.0 → 5.64.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/dist/bestax.css +1 -1
- package/dist/bestax.css.map +1 -1
- package/dist/esm/components/EmptyState.js +2 -6
- package/dist/esm/components/EmptyState.js.map +1 -1
- package/dist/esm/components/ScrollArea.js +7 -7
- package/dist/esm/components/ScrollArea.js.map +1 -1
- package/dist/esm/components/TableOfContents.js +85 -0
- package/dist/esm/components/TableOfContents.js.map +1 -0
- package/dist/esm/components/Timeline.js +5 -9
- package/dist/esm/components/Timeline.js.map +1 -1
- package/dist/esm/components/TreeView.js +3 -7
- package/dist/esm/components/TreeView.js.map +1 -1
- package/dist/esm/elements/Buttons.js +2 -0
- package/dist/esm/elements/Buttons.js.map +1 -1
- package/dist/esm/elements/CopyButton.js +132 -0
- package/dist/esm/elements/CopyButton.js.map +1 -0
- package/dist/esm/elements/DescriptionList.js +1 -5
- package/dist/esm/elements/DescriptionList.js.map +1 -1
- package/dist/esm/elements/Stat.js +196 -0
- package/dist/esm/elements/Stat.js.map +1 -0
- package/dist/esm/elements/Stats.js +48 -0
- package/dist/esm/elements/Stats.js.map +1 -0
- package/dist/esm/elements/statContext.js +10 -0
- package/dist/esm/elements/statContext.js.map +1 -0
- package/dist/esm/form/Combobox.js +2 -1
- package/dist/esm/form/Combobox.js.map +1 -1
- package/dist/esm/form/PasswordInput.js +105 -0
- package/dist/esm/form/PasswordInput.js.map +1 -0
- package/dist/esm/form/PasswordInputBase.js +177 -0
- package/dist/esm/form/PasswordInputBase.js.map +1 -0
- package/dist/esm/helpers/checkIcon.js +20 -0
- package/dist/esm/helpers/checkIcon.js.map +1 -0
- package/dist/esm/helpers/isGiven.js +13 -0
- package/dist/esm/helpers/isGiven.js.map +1 -0
- package/dist/esm/helpers/statusRegion.js +3 -3
- package/dist/esm/helpers/useClipboard.js +176 -0
- package/dist/esm/helpers/useClipboard.js.map +1 -0
- package/dist/esm/helpers/useScrollSpy.js +286 -0
- package/dist/esm/helpers/useScrollSpy.js.map +1 -0
- package/dist/extras.css +1 -1
- package/dist/extras.css.map +1 -1
- package/dist/index.cjs +2671 -1544
- package/dist/index.cjs.map +1 -1
- package/dist/index.esm.js +8 -0
- package/dist/index.esm.js.map +1 -1
- package/dist/types/components/TableOfContents.d.ts +87 -0
- package/dist/types/elements/Buttons.d.ts +1 -0
- package/dist/types/elements/CopyButton.d.ts +105 -0
- package/dist/types/elements/Stat.d.ts +242 -0
- package/dist/types/elements/Stats.d.ts +40 -0
- package/dist/types/elements/statContext.d.ts +18 -0
- package/dist/types/form/PasswordInput.d.ts +98 -0
- package/dist/types/form/PasswordInputBase.d.ts +91 -0
- package/dist/types/helpers/checkIcon.d.ts +10 -0
- package/dist/types/helpers/isGiven.d.ts +7 -0
- package/dist/types/helpers/useClipboard.d.ts +65 -0
- package/dist/types/helpers/useScrollSpy.d.ts +61 -0
- package/dist/types/index.d.ts +10 -0
- package/dist/types-cjs/components/TableOfContents.d.ts +87 -0
- package/dist/types-cjs/elements/Buttons.d.ts +1 -0
- package/dist/types-cjs/elements/CopyButton.d.ts +105 -0
- package/dist/types-cjs/elements/Stat.d.ts +242 -0
- package/dist/types-cjs/elements/Stats.d.ts +40 -0
- package/dist/types-cjs/elements/statContext.d.ts +18 -0
- package/dist/types-cjs/form/PasswordInput.d.ts +98 -0
- package/dist/types-cjs/form/PasswordInputBase.d.ts +91 -0
- package/dist/types-cjs/helpers/checkIcon.d.ts +10 -0
- package/dist/types-cjs/helpers/isGiven.d.ts +7 -0
- package/dist/types-cjs/helpers/useClipboard.d.ts +65 -0
- package/dist/types-cjs/helpers/useScrollSpy.d.ts +61 -0
- package/dist/types-cjs/index.d.ts +10 -0
- package/dist/versions/bestax-no-dark-mode.css +1 -1
- package/dist/versions/bestax-no-dark-mode.css.map +1 -1
- package/dist/versions/bestax-no-helpers-prefixed.css +1 -1
- package/dist/versions/bestax-no-helpers-prefixed.css.map +1 -1
- package/dist/versions/bestax-no-helpers.css +1 -1
- package/dist/versions/bestax-no-helpers.css.map +1 -1
- package/dist/versions/bestax-prefixed.css +1 -1
- package/dist/versions/bestax-prefixed.css.map +1 -1
- package/package.json +1 -1
- package/src/scss/CLAUDE.md +3 -0
- package/src/scss/_input-trigger.scss +76 -0
- package/src/scss/components/_index.scss +1 -0
- package/src/scss/components/_tableofcontents.scss +42 -0
- package/src/scss/elements/_index.scss +1 -0
- package/src/scss/elements/_stat.scss +153 -0
- package/src/scss/form/_index.scss +1 -0
- package/src/scss/form/_passwordinput.scss +112 -0
- package/src/scss/form/_picker-popover.scss +24 -63
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { InputBaseProps } from './InputBase.js';
|
|
2
|
+
/** How PasswordInput's visibility toggle draws itself. */
|
|
3
|
+
export type PasswordInputVariant = 'icon' | 'text';
|
|
4
|
+
/** The strings PasswordInput's toggle shows and announces, for translating. */
|
|
5
|
+
export interface PasswordInputLabels {
|
|
6
|
+
/**
|
|
7
|
+
* The toggle's name. With the `icon` variant it's the name in both states,
|
|
8
|
+
* and `aria-pressed` says whether the password shows. With `text`, it's the
|
|
9
|
+
* name while the password is hidden, and it has to contain `show`, the word
|
|
10
|
+
* on the button.
|
|
11
|
+
* @defaultValue 'Show password'
|
|
12
|
+
*/
|
|
13
|
+
showPassword?: string;
|
|
14
|
+
/**
|
|
15
|
+
* The `text` variant's name while the password shows. It has to contain
|
|
16
|
+
* `hide`.
|
|
17
|
+
* @defaultValue 'Hide password'
|
|
18
|
+
*/
|
|
19
|
+
hidePassword?: string;
|
|
20
|
+
/**
|
|
21
|
+
* The `text` variant's word while the password is hidden.
|
|
22
|
+
* @defaultValue 'Show'
|
|
23
|
+
*/
|
|
24
|
+
show?: string;
|
|
25
|
+
/**
|
|
26
|
+
* The `text` variant's word while the password shows.
|
|
27
|
+
* @defaultValue 'Hide'
|
|
28
|
+
*/
|
|
29
|
+
hide?: string;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Props for PasswordInputBase, the input and its toggle without a Field or a
|
|
33
|
+
* Control.
|
|
34
|
+
*
|
|
35
|
+
* @helperProps Helper props go on the `.password-input-container` `<div>`, with
|
|
36
|
+
* `className` and `style`, so they move and size the field and its toggle
|
|
37
|
+
* together. The other attributes go on the `<input>`.
|
|
38
|
+
* @extraProp {string} [autoComplete="current-password"] - Tells the browser and password managers this is an existing password. Pass `"new-password"` where the user makes one up, on a sign-up or change-password form.
|
|
39
|
+
* @extraProp {boolean} [spellCheck=false] - Off, so a browser's spellcheck never sees the password once it shows.
|
|
40
|
+
* @extraProp {string} [autoCorrect="off"] - Off, so a phone's keyboard doesn't change what's typed.
|
|
41
|
+
* @extraProp {string} [autoCapitalize="none"] - Off, so a phone's keyboard doesn't capitalize the first letter.
|
|
42
|
+
* @extraProp {string} [value] - The password, controlled. React writes a controlled input's value into its `value` attribute, as it does on any input, so the password sits in the page's markup. Uncontrolled, read with `FormData`, the field never puts what's typed there.
|
|
43
|
+
* @extraProp {React.Ref<HTMLInputElement>} [ref] - Ref forwarded to the `<input>`.
|
|
44
|
+
*/
|
|
45
|
+
export interface PasswordInputBaseProps extends Omit<InputBaseProps, 'type'> {
|
|
46
|
+
/**
|
|
47
|
+
* Whether the password shows, when you hold the state. Setting it makes
|
|
48
|
+
* the visibility controlled: the toggle only calls `onVisibleChange`, and
|
|
49
|
+
* so does hiding again on its own. Apply that `false` and the field is a
|
|
50
|
+
* password field by the time the form reads it; keep `visible` true and
|
|
51
|
+
* the field stays shown.
|
|
52
|
+
*/
|
|
53
|
+
visible?: boolean;
|
|
54
|
+
/**
|
|
55
|
+
* Whether the password shows at first, when the input holds its own state.
|
|
56
|
+
* @defaultValue false
|
|
57
|
+
*/
|
|
58
|
+
defaultVisible?: boolean;
|
|
59
|
+
/**
|
|
60
|
+
* Called with the new visibility on each toggle, and with `false` when the
|
|
61
|
+
* form submits or resets, or the page is left, which it also is on the way
|
|
62
|
+
* into the back-forward cache. React renders those hides at once, a state
|
|
63
|
+
* update you make here included, so the form reads a password field. One
|
|
64
|
+
* that fires while React is rendering or committing, which includes your
|
|
65
|
+
* `useEffect` and `useLayoutEffect` callbacks, such as a `requestSubmit()`
|
|
66
|
+
* from an effect, can't render there, and lands just after the form is
|
|
67
|
+
* read: hide the password first, or submit from an event handler.
|
|
68
|
+
*/
|
|
69
|
+
onVisibleChange?: (visible: boolean) => void;
|
|
70
|
+
/**
|
|
71
|
+
* How the toggle draws itself: an eye icon with a fixed name and
|
|
72
|
+
* `aria-pressed`, or the words "Show" and "Hide" with a name that follows
|
|
73
|
+
* them.
|
|
74
|
+
* @defaultValue 'icon'
|
|
75
|
+
*/
|
|
76
|
+
variant?: PasswordInputVariant;
|
|
77
|
+
/** Translations for the toggle. */
|
|
78
|
+
labels?: PasswordInputLabels;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* The raw PasswordInput: a password field with a button inside it that shows what was typed, without Field/Control wrapping.
|
|
82
|
+
*
|
|
83
|
+
* Use `PasswordInput` for the convenience wrapper.
|
|
84
|
+
*
|
|
85
|
+
* @function
|
|
86
|
+
* @param {PasswordInputBaseProps} props - Props for PasswordInputBase.
|
|
87
|
+
* @param {React.Ref<HTMLInputElement>} ref - Forwarded ref to the `<input>`.
|
|
88
|
+
* @returns {JSX.Element} The input and its toggle, in a container.
|
|
89
|
+
*/
|
|
90
|
+
export declare const PasswordInputBase: import("react").ForwardRefExoticComponent<PasswordInputBaseProps & import("react").RefAttributes<HTMLInputElement>>;
|
|
91
|
+
export default PasswordInputBase;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A check mark, 1em square and drawn in `currentColor`, so it takes the text
|
|
3
|
+
* color around it, the system's in forced colors included. Combobox draws it
|
|
4
|
+
* beside a chosen item, and CopyButton after a copy. It's decorative: put it
|
|
5
|
+
* inside something `aria-hidden`.
|
|
6
|
+
*
|
|
7
|
+
* @function CheckIcon
|
|
8
|
+
* @returns The check mark's `<svg>`.
|
|
9
|
+
*/
|
|
10
|
+
export declare function CheckIcon(): import("react").JSX.Element;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* INTERNAL, deliberately not exported from `src/index.ts`. Whether a prop
|
|
4
|
+
* was given something to render: `undefined`, `null`, a boolean and `''`
|
|
5
|
+
* weren't, and `0` was, since React renders it.
|
|
6
|
+
*/
|
|
7
|
+
export declare const isGiven: (node: ReactNode) => boolean;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/** Options for useClipboard. */
|
|
2
|
+
export interface UseClipboardOptions {
|
|
3
|
+
/**
|
|
4
|
+
* How long `copied` stays `true` after a copy, in milliseconds. Another
|
|
5
|
+
* copy restarts it. `0` turns the timer off, as Toast's `0` does, so
|
|
6
|
+
* `copied` stays `true` until a later copy fails. A missing or `NaN` value
|
|
7
|
+
* uses the default, a negative one ends it at once, and `Infinity`, or
|
|
8
|
+
* anything longer than the longest delay `setTimeout` takes (2147483647 ms,
|
|
9
|
+
* about 24.8 days), is that longest delay.
|
|
10
|
+
* @defaultValue 2000
|
|
11
|
+
*/
|
|
12
|
+
duration?: number;
|
|
13
|
+
/**
|
|
14
|
+
* Called with `true` after each copy that worked, a repeat included, and
|
|
15
|
+
* with `false` when `duration` runs out or a later copy fails.
|
|
16
|
+
*/
|
|
17
|
+
onCopiedChange?: (copied: boolean) => void;
|
|
18
|
+
/**
|
|
19
|
+
* Called when neither the Clipboard API nor the copy command could write,
|
|
20
|
+
* with the Clipboard API's own error when it refused, or an `Error` saying
|
|
21
|
+
* neither could.
|
|
22
|
+
*/
|
|
23
|
+
onCopyError?: (error: Error) => void;
|
|
24
|
+
}
|
|
25
|
+
/** What useClipboard returns. */
|
|
26
|
+
export interface UseClipboardResult {
|
|
27
|
+
/**
|
|
28
|
+
* Writes `text` to the clipboard, and resolves `true` once it's written or
|
|
29
|
+
* `false` when it couldn't be. It never rejects. Call it from a click or a
|
|
30
|
+
* key press, with no `await` before it: browsers only allow a write
|
|
31
|
+
* shortly after one. A call that a later one overtakes leaves `copied`,
|
|
32
|
+
* `error` and the callbacks to the later one, and doesn't fall back to the
|
|
33
|
+
* copy command once the later one has started.
|
|
34
|
+
*/
|
|
35
|
+
copy: (text: string) => Promise<boolean>;
|
|
36
|
+
/**
|
|
37
|
+
* `true` for `duration` after a copy that worked, or, with a `duration` of
|
|
38
|
+
* `0`, until a later copy fails.
|
|
39
|
+
*/
|
|
40
|
+
copied: boolean;
|
|
41
|
+
/** Why the last copy failed, or `null` after one that worked. */
|
|
42
|
+
error: Error | null;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Copies text to the clipboard through the Clipboard API, falling back to the copy command where that's missing or refused, and keeps a `copied` flag for `duration` after a copy.
|
|
46
|
+
*
|
|
47
|
+
* It announces nothing. A trigger of your own says "Copied" in a
|
|
48
|
+
* `role="status"` region that's in the page before the click; `CopyButton`
|
|
49
|
+
* is this hook with the button, the label and the announcement built in.
|
|
50
|
+
*
|
|
51
|
+
* A failed copy sets `error`, calls `onCopyError`, and ends `copied` if a
|
|
52
|
+
* copy before it had set it. When copies overlap, only the latest one's
|
|
53
|
+
* outcome sets the state and fires the callbacks, whichever finishes first.
|
|
54
|
+
* Nothing changes and no callback fires once the component using it has
|
|
55
|
+
* unmounted, though a write already under way still finishes.
|
|
56
|
+
*
|
|
57
|
+
* @function useClipboard
|
|
58
|
+
* @param options - How long `copied` lasts, and the callbacks.
|
|
59
|
+
* @returns `copy`, which writes, and the `copied` and `error` state.
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* const { copy, copied } = useClipboard();
|
|
63
|
+
* <Button onClick={() => copy(url)}>{copied ? 'Copied' : 'Copy link'}</Button>
|
|
64
|
+
*/
|
|
65
|
+
export declare function useClipboard(options?: UseClipboardOptions): UseClipboardResult;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/** Options for useScrollSpy. */
|
|
2
|
+
export interface UseScrollSpyOptions {
|
|
3
|
+
/**
|
|
4
|
+
* **Required.** The ids of the sections to watch, without the `#`, in the
|
|
5
|
+
* order they come on the page. Each one is looked up each time the hook
|
|
6
|
+
* checks, so an id with no element on the page is skipped until one
|
|
7
|
+
* appears, and a section replaced under the same id keeps working.
|
|
8
|
+
*/
|
|
9
|
+
ids: string[];
|
|
10
|
+
/**
|
|
11
|
+
* Pixels from the viewport's top where a section counts as reached. Unset,
|
|
12
|
+
* it's the page's `scroll-padding-top`, read when the hook mounts and on
|
|
13
|
+
* resize, so the highlight agrees with where a jump lands under a sticky
|
|
14
|
+
* header. A `scroll-padding-top` that mixes a percentage with a length in
|
|
15
|
+
* `calc()` isn't read: pass `offset` then.
|
|
16
|
+
*/
|
|
17
|
+
offset?: number;
|
|
18
|
+
/** Called with the new current id when it changes, or `null` above the first section. */
|
|
19
|
+
onCurrentChange?: (id: string | null) => void;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* The `useScrollSpy` hook returns the id of the section being read: the last
|
|
23
|
+
* of `ids` whose top is at or above the offset line, or the last one once the
|
|
24
|
+
* page is scrolled to its end. After a jump to one of them, it's that one
|
|
25
|
+
* until the reader scrolls on. `null` above the first section, on the server
|
|
26
|
+
* and until the page hydrates.
|
|
27
|
+
*
|
|
28
|
+
* It checks once per frame while the page scrolls, and on resize. A jump is
|
|
29
|
+
* a plain click on a link to one of the ids (the main button, no modifier
|
|
30
|
+
* key, opening in this page), noted and never stopped, so the browser jumps
|
|
31
|
+
* as it always does; and the `#id` a page opened afresh opens at. Back,
|
|
32
|
+
* Forward and a reload aren't jumps. That `#id` is read once, when `ids`
|
|
33
|
+
* first has some: a section rendered after that isn't held, even if the
|
|
34
|
+
* page opened at it, and the reading rule marks where the page is. Once the
|
|
35
|
+
* page has been still for a
|
|
36
|
+
* moment, the section stays current only if it's where a jump puts it: its
|
|
37
|
+
* top at the line, give or take a shift of the layout smaller than its own
|
|
38
|
+
* height, or, at the end of the page, on screen below the line. Otherwise,
|
|
39
|
+
* as after a flick right after the click, the reading rule takes over. The
|
|
40
|
+
* next scroll after that lets it go, the browser's own included, so when
|
|
41
|
+
* content loading above it makes the browser scroll to keep the reader's
|
|
42
|
+
* place, the rule takes over too.
|
|
43
|
+
*
|
|
44
|
+
* A section that isn't drawn (`display: none`) is never current. A section
|
|
45
|
+
* that moves while nothing scrolls is seen at the next scroll or resize. It
|
|
46
|
+
* watches the document only: not a panel that scrolls inside it, and not
|
|
47
|
+
* sections inside a shadow root, which an `#id` link can't reach either.
|
|
48
|
+
* Whether a page was opened afresh is read from how the document loaded, so
|
|
49
|
+
* in an app that changes routes on the client, a route change can briefly
|
|
50
|
+
* mark the address bar's section until the page settles, when the reading
|
|
51
|
+
* rule takes over, and after a reload a route change to an `#id` holds
|
|
52
|
+
* nothing.
|
|
53
|
+
*
|
|
54
|
+
* @function
|
|
55
|
+
* @param {UseScrollSpyOptions} options - The ids to watch, the offset, and a change callback.
|
|
56
|
+
* @returns {string | null} The current section's id, or `null`.
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* const current = useScrollSpy({ ids: ['profile', 'security', 'billing'] });
|
|
60
|
+
*/
|
|
61
|
+
export declare function useScrollSpy({ ids, offset, onCurrentChange, }: UseScrollSpyOptions): string | null;
|
package/dist/types/index.d.ts
CHANGED
|
@@ -34,6 +34,7 @@ export * from './components/ScrollArea.js';
|
|
|
34
34
|
export * from './components/Command.js';
|
|
35
35
|
export * from './components/DataTable.js';
|
|
36
36
|
export * from './components/Affix.js';
|
|
37
|
+
export * from './components/TableOfContents.js';
|
|
37
38
|
export * from './elements/Block.js';
|
|
38
39
|
export * from './elements/Box.js';
|
|
39
40
|
export * from './elements/Button.js';
|
|
@@ -43,6 +44,7 @@ export * from './elements/ToggleButton.js';
|
|
|
43
44
|
export * from './elements/Code.js';
|
|
44
45
|
export * from './elements/ColorSwatch.js';
|
|
45
46
|
export * from './elements/Content.js';
|
|
47
|
+
export * from './elements/CopyButton.js';
|
|
46
48
|
export * from './elements/Delete.js';
|
|
47
49
|
export * from './elements/DescriptionList.js';
|
|
48
50
|
export * from './elements/Divider.js';
|
|
@@ -65,6 +67,8 @@ export * from './elements/Progress.js';
|
|
|
65
67
|
export * from './elements/RingProgress.js';
|
|
66
68
|
export * from './elements/Skeleton.js';
|
|
67
69
|
export * from './elements/Span.js';
|
|
70
|
+
export * from './elements/Stat.js';
|
|
71
|
+
export * from './elements/Stats.js';
|
|
68
72
|
export * from './elements/Strong.js';
|
|
69
73
|
export * from './elements/SubTitle.js';
|
|
70
74
|
export * from './elements/Table.js';
|
|
@@ -105,12 +109,16 @@ export { SelectBase } from './form/SelectBase.js';
|
|
|
105
109
|
export type { SelectBaseProps } from './form/SelectBase.js';
|
|
106
110
|
export { TextAreaBase } from './form/TextAreaBase.js';
|
|
107
111
|
export type { TextAreaBaseProps } from './form/TextAreaBase.js';
|
|
112
|
+
export { PasswordInputBase } from './form/PasswordInputBase.js';
|
|
113
|
+
export type { PasswordInputBaseProps, PasswordInputLabels, PasswordInputVariant, } from './form/PasswordInputBase.js';
|
|
108
114
|
export { Input } from './form/Input.js';
|
|
109
115
|
export type { InputProps } from './form/Input.js';
|
|
110
116
|
export { Select } from './form/Select.js';
|
|
111
117
|
export type { SelectProps } from './form/Select.js';
|
|
112
118
|
export { TextArea } from './form/TextArea.js';
|
|
113
119
|
export type { TextAreaProps } from './form/TextArea.js';
|
|
120
|
+
export { PasswordInput } from './form/PasswordInput.js';
|
|
121
|
+
export type { PasswordInputProps } from './form/PasswordInput.js';
|
|
114
122
|
export { DateInputBase } from './form/DateInputBase.js';
|
|
115
123
|
export type { DateInputBaseProps } from './form/DateInputBase.js';
|
|
116
124
|
export { DateInput } from './form/DateInput.js';
|
|
@@ -152,6 +160,8 @@ export { useNumberFormat } from './helpers/localeFormat.js';
|
|
|
152
160
|
export type { NumberFormatFunction } from './helpers/localeFormat.js';
|
|
153
161
|
export { useFocusTrap } from './helpers/useFocusTrap.js';
|
|
154
162
|
export type { UseFocusTrapOptions } from './helpers/useFocusTrap.js';
|
|
163
|
+
export { useClipboard } from './helpers/useClipboard.js';
|
|
164
|
+
export type { UseClipboardOptions, UseClipboardResult, } from './helpers/useClipboard.js';
|
|
155
165
|
export * from './layout/AppFrame.js';
|
|
156
166
|
export * from './layout/Center.js';
|
|
157
167
|
export * from './layout/Container.js';
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { BulmaClassesProps, validColors } from '../helpers/useBulmaClasses.js';
|
|
3
|
+
export { useScrollSpy } from '../helpers/useScrollSpy.js';
|
|
4
|
+
export type { UseScrollSpyOptions } from '../helpers/useScrollSpy.js';
|
|
5
|
+
/** One entry in a TableOfContents. */
|
|
6
|
+
export interface TableOfContentsItem {
|
|
7
|
+
/** **Required.** The `id` of the section or heading it links to, without the `#`. Unique on the page. */
|
|
8
|
+
id: string;
|
|
9
|
+
/** **Required.** What the link says, usually the heading's own text. */
|
|
10
|
+
label: React.ReactNode;
|
|
11
|
+
/** Entries under this one, drawn as a nested list. */
|
|
12
|
+
children?: TableOfContentsItem[];
|
|
13
|
+
}
|
|
14
|
+
/** The visible strings, in your app's language. */
|
|
15
|
+
export interface TableOfContentsLabels {
|
|
16
|
+
/**
|
|
17
|
+
* The list's visible title, which also names its `<nav>`.
|
|
18
|
+
* @defaultValue 'On this page'
|
|
19
|
+
*/
|
|
20
|
+
title?: string;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Props for the TableOfContents component. The helper props, the other
|
|
24
|
+
* attributes and the `ref` land on the `<nav>`.
|
|
25
|
+
*
|
|
26
|
+
* @extraProp {React.Ref<HTMLElement>} [ref] - Ref forwarded to the `<nav>`.
|
|
27
|
+
*/
|
|
28
|
+
export interface TableOfContentsProps extends Omit<React.HTMLAttributes<HTMLElement>, 'color' | 'children'>, Omit<BulmaClassesProps, 'color' | 'backgroundColor'> {
|
|
29
|
+
/** Additional CSS classes to apply. */
|
|
30
|
+
className?: string;
|
|
31
|
+
/**
|
|
32
|
+
* **Required.** The sections, in page order, as links to their ids. Each
|
|
33
|
+
* link is a plain `<a href="#id">`, so following one is the browser's own
|
|
34
|
+
* jump: put `scroll-padding-top` on the page to land clear of a sticky
|
|
35
|
+
* header, and smooth scrolling, if you want it, in page CSS inside
|
|
36
|
+
* `@media (prefers-reduced-motion: no-preference)`.
|
|
37
|
+
*/
|
|
38
|
+
items: TableOfContentsItem[];
|
|
39
|
+
/**
|
|
40
|
+
* Called with the current section's id when it changes, or `null` above
|
|
41
|
+
* the first section. Never called on the server or before hydration.
|
|
42
|
+
*/
|
|
43
|
+
onCurrentChange?: (id: string | null) => void;
|
|
44
|
+
/**
|
|
45
|
+
* Pixels from the viewport's top where a section counts as reached.
|
|
46
|
+
* Unset, it's the page's `scroll-padding-top`, so the highlight agrees
|
|
47
|
+
* with where a jump lands under a sticky header.
|
|
48
|
+
*/
|
|
49
|
+
offset?: number;
|
|
50
|
+
/**
|
|
51
|
+
* Sticks to the top of the viewport as the page scrolls, at
|
|
52
|
+
* `--bulma-table-of-contents-sticky-top`, and scrolls itself when it's
|
|
53
|
+
* taller than the viewport. Adds `is-sticky`.
|
|
54
|
+
*/
|
|
55
|
+
isSticky?: boolean;
|
|
56
|
+
/** The visible strings, in your app's language. */
|
|
57
|
+
labels?: TableOfContentsLabels;
|
|
58
|
+
/** Text color helper. */
|
|
59
|
+
textColor?: (typeof validColors)[number] | 'inherit' | 'current';
|
|
60
|
+
/** Background color helper. */
|
|
61
|
+
bgColor?: (typeof validColors)[number] | 'inherit' | 'current';
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* The `TableOfContents` component lists a long page's sections as links in Bulma's menu look, and marks the one being read.
|
|
65
|
+
*
|
|
66
|
+
* It's a `<nav>` named by its title, holding `MenuList` and `MenuItem` links
|
|
67
|
+
* to each `#id`, rendered in full on the server. `useScrollSpy` picks the
|
|
68
|
+
* current section, and its link alone gets `is-active` and
|
|
69
|
+
* `aria-current="location"`. Use the hook on its own to mark the section in
|
|
70
|
+
* view somewhere else, such as an app's nav `Menu`.
|
|
71
|
+
*
|
|
72
|
+
* @function
|
|
73
|
+
* @param {TableOfContentsProps} props - Props for the TableOfContents component.
|
|
74
|
+
* @param {React.Ref<HTMLElement>} ref - Forwarded ref to the `<nav>`.
|
|
75
|
+
* @returns {JSX.Element} The rendered table of contents.
|
|
76
|
+
*
|
|
77
|
+
* @example
|
|
78
|
+
* <TableOfContents
|
|
79
|
+
* isSticky
|
|
80
|
+
* items={[
|
|
81
|
+
* { id: 'install', label: 'Install' },
|
|
82
|
+
* { id: 'usage', label: 'Usage', children: [{ id: 'props', label: 'Props' }] },
|
|
83
|
+
* ]}
|
|
84
|
+
* />
|
|
85
|
+
*/
|
|
86
|
+
export declare const TableOfContents: React.ForwardRefExoticComponent<TableOfContentsProps & React.RefAttributes<HTMLElement>>;
|
|
87
|
+
export default TableOfContents;
|
|
@@ -38,5 +38,6 @@ export declare const Buttons: React.FC<ButtonsProps> & {
|
|
|
38
38
|
LinkButton: import("../index.js").PolymorphicComponent<import("./LinkButton.js").LinkButtonOwnProps, "button", never>;
|
|
39
39
|
ToggleButton: React.ForwardRefExoticComponent<import("./ToggleButton.js").ToggleButtonProps & React.RefAttributes<HTMLButtonElement>>;
|
|
40
40
|
IconButton: import("../index.js").PolymorphicComponent<import("./IconButton.js").IconButtonOwnProps & import("./IconButton.js").IconButtonName, "button", never>;
|
|
41
|
+
CopyButton: React.ForwardRefExoticComponent<import("./CopyButton.js").CopyButtonProps & React.RefAttributes<HTMLButtonElement>>;
|
|
41
42
|
};
|
|
42
43
|
export {};
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { type ButtonOwnProps } from './Button.js';
|
|
3
|
+
/**
|
|
4
|
+
* The strings CopyButton shows and announces, each with an English default. A
|
|
5
|
+
* key left out, or set to an empty string, keeps its default.
|
|
6
|
+
*/
|
|
7
|
+
export interface CopyButtonLabels {
|
|
8
|
+
/**
|
|
9
|
+
* The button's label, and so its name, until a copy. With `showLabel` off
|
|
10
|
+
* it's the name in both states, given as `aria-label`.
|
|
11
|
+
* @defaultValue 'Copy'
|
|
12
|
+
*/
|
|
13
|
+
copy?: string;
|
|
14
|
+
/**
|
|
15
|
+
* The label shown for `duration` after a copy, and so the name meanwhile.
|
|
16
|
+
* Not used with `showLabel` off, where only the glyph changes.
|
|
17
|
+
* @defaultValue 'Copied'
|
|
18
|
+
*/
|
|
19
|
+
copied?: string;
|
|
20
|
+
/**
|
|
21
|
+
* Announced after a copy.
|
|
22
|
+
* @defaultValue 'Copied to the clipboard'
|
|
23
|
+
*/
|
|
24
|
+
copiedStatus?: string;
|
|
25
|
+
/**
|
|
26
|
+
* Announced when the copy fails.
|
|
27
|
+
* @defaultValue "Couldn't copy to the clipboard"
|
|
28
|
+
*/
|
|
29
|
+
failedStatus?: string;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Props for the CopyButton component. The helper props, the other button
|
|
33
|
+
* attributes and the `ref` land on the `<button>`.
|
|
34
|
+
*
|
|
35
|
+
* @extraProp {'button' | 'submit' | 'reset'} [type=button] - `button` unless you pass `submit` or `reset`.
|
|
36
|
+
* @extraProp {React.MouseEventHandler<HTMLButtonElement>} [onClick] - Runs before the copy. An `onClick` that calls `preventDefault()` stops the copy, and neither `onCopiedChange` nor `onCopyError` fires.
|
|
37
|
+
* @extraProp {React.Ref<HTMLButtonElement>} [ref] - Ref forwarded to the `<button>`.
|
|
38
|
+
*/
|
|
39
|
+
export interface CopyButtonProps extends Omit<ButtonOwnProps, 'children'>, Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, keyof ButtonOwnProps | 'value'> {
|
|
40
|
+
/**
|
|
41
|
+
* The text it copies. This is not the `<button>`'s form value, which it
|
|
42
|
+
* doesn't render.
|
|
43
|
+
*/
|
|
44
|
+
value: string;
|
|
45
|
+
/**
|
|
46
|
+
* How long the "Copied" label stays, in milliseconds. Another copy
|
|
47
|
+
* restarts it. `0` turns the reset off, as Toast's `0` turns off its
|
|
48
|
+
* auto-close, so "Copied" stays until a later copy fails. A missing or `NaN`
|
|
49
|
+
* value uses the default, a negative one ends it at once, and `Infinity`,
|
|
50
|
+
* or anything longer than the longest delay `setTimeout` takes (about 24.8
|
|
51
|
+
* days), is that longest delay.
|
|
52
|
+
* @defaultValue 2000
|
|
53
|
+
*/
|
|
54
|
+
duration?: number;
|
|
55
|
+
/**
|
|
56
|
+
* Shows the label beside the icon, which is then the button's name: it
|
|
57
|
+
* carries no `aria-label`, so the name reads "Copy" and then "Copied" as
|
|
58
|
+
* the words on it do. Turned off, it's a square icon-only button named by
|
|
59
|
+
* `labels.copy` through `aria-label` in both states, and only the glyph
|
|
60
|
+
* changes. An `aria-label` you pass yourself names it in either form.
|
|
61
|
+
* @defaultValue true
|
|
62
|
+
*/
|
|
63
|
+
showLabel?: boolean;
|
|
64
|
+
/** Translations for the label and the announcements. */
|
|
65
|
+
labels?: CopyButtonLabels;
|
|
66
|
+
/**
|
|
67
|
+
* Called with `true` after each copy that worked, a repeat included, and
|
|
68
|
+
* with `false` when `duration` runs out or a later copy fails.
|
|
69
|
+
*/
|
|
70
|
+
onCopiedChange?: (copied: boolean) => void;
|
|
71
|
+
/**
|
|
72
|
+
* Called when neither the Clipboard API nor the fallback could write. A
|
|
73
|
+
* copy field can select its text from here, so the reader can copy it
|
|
74
|
+
* themselves.
|
|
75
|
+
*/
|
|
76
|
+
onCopyError?: (error: Error) => void;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* The `CopyButton` component renders a button that copies a piece of text to the clipboard, says "Copied" for a moment, and announces the result.
|
|
80
|
+
*
|
|
81
|
+
* It's a `Button` with a copy icon and "Copy", and takes everything `Button`
|
|
82
|
+
* takes. A click writes `value` through the Clipboard API, or through the
|
|
83
|
+
* older copy command where that's missing or refused, and reports a failure
|
|
84
|
+
* rather than showing "Copied". Each outcome is announced through a polite
|
|
85
|
+
* status region portaled out of the button's place, so it stays the last
|
|
86
|
+
* child of a `Control` or `Buttons`: into the open modal dialog the button is
|
|
87
|
+
* in, otherwise where `Portal` puts portaled content (the `ConfigProvider`'s
|
|
88
|
+
* `portalContainer`, or the end of the page). With `showLabel={false}` it's an
|
|
89
|
+
* `IconButton`. For a trigger of your own, use `useClipboard`, which it's
|
|
90
|
+
* built on.
|
|
91
|
+
*
|
|
92
|
+
* @function
|
|
93
|
+
* @param {CopyButtonProps} props - Props for the CopyButton component.
|
|
94
|
+
* @param {React.Ref<HTMLButtonElement>} ref - Forwarded ref to the `<button>`.
|
|
95
|
+
* @returns {JSX.Element} The rendered button.
|
|
96
|
+
* @see {@link https://www.w3.org/WAI/WCAG22/Understanding/status-messages.html | WCAG 4.1.3 Status Messages}
|
|
97
|
+
*
|
|
98
|
+
* @example
|
|
99
|
+
* <CopyButton value="https://bestax.io" />
|
|
100
|
+
*
|
|
101
|
+
* @example
|
|
102
|
+
* <CopyButton value={apiKey} showLabel={false} size="small" />
|
|
103
|
+
*/
|
|
104
|
+
export declare const CopyButton: React.ForwardRefExoticComponent<CopyButtonProps & React.RefAttributes<HTMLButtonElement>>;
|
|
105
|
+
export default CopyButton;
|