shelving 1.264.0 → 1.264.1

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.
Files changed (146) hide show
  1. package/package.json +1 -1
  2. package/ui/block/Card.d.ts +1 -1
  3. package/ui/block/Card.js +1 -1
  4. package/ui/block/Card.tsx +1 -1
  5. package/ui/block/Image.d.ts +3 -3
  6. package/ui/block/Image.js +4 -4
  7. package/ui/block/Image.module.css +4 -1
  8. package/ui/block/Image.tsx +14 -4
  9. package/ui/block/Video.d.ts +3 -58
  10. package/ui/block/Video.js +2 -52
  11. package/ui/block/Video.module.css +1 -51
  12. package/ui/block/Video.tsx +3 -99
  13. package/ui/{form → button}/Button.d.ts +6 -2
  14. package/ui/{form → button}/Button.tsx +6 -1
  15. package/ui/button/FullscreenButton.d.ts +31 -0
  16. package/ui/button/FullscreenButton.js +37 -0
  17. package/ui/button/FullscreenButton.tsx +58 -0
  18. package/ui/button/RetryButton.d.ts +29 -0
  19. package/ui/button/RetryButton.js +27 -0
  20. package/ui/button/RetryButton.tsx +48 -0
  21. package/ui/{form → button}/SubmitButton.d.ts +12 -8
  22. package/ui/{form → button}/SubmitButton.js +4 -4
  23. package/ui/{form → button}/SubmitButton.tsx +22 -18
  24. package/ui/button/index.d.ts +5 -0
  25. package/ui/button/index.js +5 -0
  26. package/ui/button/index.ts +5 -0
  27. package/ui/dialog/Dialog.d.ts +1 -1
  28. package/ui/dialog/Dialog.tsx +1 -1
  29. package/ui/docs/DocumentationSearchPage.js +2 -2
  30. package/ui/docs/DocumentationSearchPage.tsx +2 -2
  31. package/ui/form/FormContext.d.ts +1 -1
  32. package/ui/form/FormContext.js +1 -1
  33. package/ui/form/FormContext.tsx +1 -1
  34. package/ui/form/FormFields.d.ts +1 -1
  35. package/ui/form/FormFields.js +1 -1
  36. package/ui/form/FormFields.tsx +2 -2
  37. package/ui/form/FormFooter.js +1 -1
  38. package/ui/form/FormFooter.tsx +1 -1
  39. package/ui/form/FormInput.d.ts +1 -1
  40. package/ui/form/FormInput.js +1 -1
  41. package/ui/form/FormInput.tsx +2 -2
  42. package/ui/form/Progress.d.ts +6 -24
  43. package/ui/form/Progress.js +9 -20
  44. package/ui/form/Progress.module.css +13 -32
  45. package/ui/form/Progress.tsx +18 -51
  46. package/ui/form/index.d.ts +0 -23
  47. package/ui/form/index.js +0 -23
  48. package/ui/form/index.ts +0 -23
  49. package/ui/index.d.ts +2 -0
  50. package/ui/index.js +2 -0
  51. package/ui/index.ts +2 -0
  52. package/ui/inline/Link.d.ts +1 -1
  53. package/ui/inline/Link.js +1 -1
  54. package/ui/inline/Link.tsx +1 -1
  55. package/ui/{form → input}/ArrayInput.js +1 -1
  56. package/ui/{form → input}/ArrayInput.tsx +1 -1
  57. package/ui/{form → input}/ButtonInput.d.ts +1 -1
  58. package/ui/{form → input}/ButtonInput.js +1 -1
  59. package/ui/{form → input}/ButtonInput.tsx +1 -1
  60. package/ui/{form → input}/ButtonPopover.d.ts +1 -1
  61. package/ui/{form → input}/ButtonPopover.js +1 -1
  62. package/ui/{form → input}/ButtonPopover.tsx +1 -1
  63. package/ui/{form → input}/DictionaryInput.js +1 -1
  64. package/ui/{form → input}/DictionaryInput.tsx +1 -1
  65. package/ui/{form → input}/SchemaInput.js +1 -1
  66. package/ui/{form → input}/SchemaInput.test.tsx +2 -3
  67. package/ui/{form → input}/SchemaInput.tsx +1 -1
  68. package/ui/{form → input}/TextInput.d.ts +1 -1
  69. package/ui/{form → input}/TextInput.js +1 -1
  70. package/ui/{form → input}/TextInput.tsx +1 -1
  71. package/ui/input/index.d.ts +20 -0
  72. package/ui/input/index.js +20 -0
  73. package/ui/input/index.ts +20 -0
  74. package/ui/layout/Layout.d.ts +1 -1
  75. package/ui/layout/Layout.js +4 -0
  76. package/ui/layout/Layout.ts +6 -0
  77. package/ui/layout/SidebarLayout.js +1 -1
  78. package/ui/layout/SidebarLayout.tsx +1 -1
  79. package/ui/menu/Menu.d.ts +1 -1
  80. package/ui/menu/Menu.js +1 -1
  81. package/ui/menu/Menu.tsx +1 -1
  82. package/ui/misc/Catcher.d.ts +2 -19
  83. package/ui/misc/Catcher.js +3 -22
  84. package/ui/misc/Catcher.tsx +4 -40
  85. package/ui/misc/Tag.d.ts +1 -1
  86. package/ui/misc/Tag.js +1 -1
  87. package/ui/misc/Tag.tsx +1 -1
  88. package/ui/tree/TreeButton.d.ts +1 -1
  89. package/ui/tree/TreeButton.js +1 -1
  90. package/ui/tree/TreeButton.tsx +1 -1
  91. package/ui/tree/TreeSidebar.js +1 -1
  92. package/ui/tree/TreeSidebar.tsx +1 -1
  93. /package/ui/{form → button}/Button.js +0 -0
  94. /package/ui/{form → button}/Button.md +0 -0
  95. /package/ui/{form → button}/Button.module.css +0 -0
  96. /package/ui/{form → button}/Clickable.d.ts +0 -0
  97. /package/ui/{form → button}/Clickable.js +0 -0
  98. /package/ui/{form → button}/Clickable.tsx +0 -0
  99. /package/ui/{form → input}/ArrayInput.d.ts +0 -0
  100. /package/ui/{form → input}/ArrayRadioInputs.d.ts +0 -0
  101. /package/ui/{form → input}/ArrayRadioInputs.js +0 -0
  102. /package/ui/{form → input}/ArrayRadioInputs.tsx +0 -0
  103. /package/ui/{form → input}/ButtonInputPopover.d.ts +0 -0
  104. /package/ui/{form → input}/ButtonInputPopover.js +0 -0
  105. /package/ui/{form → input}/ButtonInputPopover.tsx +0 -0
  106. /package/ui/{form → input}/CheckboxInput.d.ts +0 -0
  107. /package/ui/{form → input}/CheckboxInput.js +0 -0
  108. /package/ui/{form → input}/CheckboxInput.tsx +0 -0
  109. /package/ui/{form → input}/ChoiceRadioInputs.d.ts +0 -0
  110. /package/ui/{form → input}/ChoiceRadioInputs.js +0 -0
  111. /package/ui/{form → input}/ChoiceRadioInputs.tsx +0 -0
  112. /package/ui/{form → input}/DataInput.d.ts +0 -0
  113. /package/ui/{form → input}/DataInput.js +0 -0
  114. /package/ui/{form → input}/DataInput.tsx +0 -0
  115. /package/ui/{form → input}/DateInput.d.ts +0 -0
  116. /package/ui/{form → input}/DateInput.js +0 -0
  117. /package/ui/{form → input}/DateInput.tsx +0 -0
  118. /package/ui/{form → input}/DictionaryInput.d.ts +0 -0
  119. /package/ui/{form → input}/FileInput.d.ts +0 -0
  120. /package/ui/{form → input}/FileInput.js +0 -0
  121. /package/ui/{form → input}/FileInput.tsx +0 -0
  122. /package/ui/{form → input}/Input.d.ts +0 -0
  123. /package/ui/{form → input}/Input.js +0 -0
  124. /package/ui/{form → input}/Input.module.css +0 -0
  125. /package/ui/{form → input}/Input.tsx +0 -0
  126. /package/ui/{form → input}/NumberInput.d.ts +0 -0
  127. /package/ui/{form → input}/NumberInput.js +0 -0
  128. /package/ui/{form → input}/NumberInput.tsx +0 -0
  129. /package/ui/{form → input}/OutputInput.d.ts +0 -0
  130. /package/ui/{form → input}/OutputInput.js +0 -0
  131. /package/ui/{form → input}/OutputInput.tsx +0 -0
  132. /package/ui/{form → input}/Popover.d.ts +0 -0
  133. /package/ui/{form → input}/Popover.js +0 -0
  134. /package/ui/{form → input}/Popover.module.css +0 -0
  135. /package/ui/{form → input}/Popover.tsx +0 -0
  136. /package/ui/{form → input}/QueryInput.d.ts +0 -0
  137. /package/ui/{form → input}/QueryInput.js +0 -0
  138. /package/ui/{form → input}/QueryInput.tsx +0 -0
  139. /package/ui/{form → input}/RadioInput.d.ts +0 -0
  140. /package/ui/{form → input}/RadioInput.js +0 -0
  141. /package/ui/{form → input}/RadioInput.tsx +0 -0
  142. /package/ui/{form → input}/SchemaInput.d.ts +0 -0
  143. /package/ui/{form → input}/SchemaInput.md +0 -0
  144. /package/ui/{form → input}/SelectInput.d.ts +0 -0
  145. /package/ui/{form → input}/SelectInput.js +0 -0
  146. /package/ui/{form → input}/SelectInput.tsx +0 -0
@@ -0,0 +1,27 @@
1
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { ArrowPathIcon } from "@heroicons/react/16/solid";
3
+ import { createContext, use } from "react";
4
+ import { Button } from "./Button.js";
5
+ /**
6
+ * Context for providing a "retry" callback to descendant `<RetryButton>` elements.
7
+ * - Used by `<Catcher>` to provide a retry callback to its children.
8
+ * - Default `<ErrorNotice>` and `<ErrorPage>` elements include `<RetryButton>` to trigger a retry on their parent `<Catcher>`
9
+ */
10
+ export const RetryContext = createContext(undefined);
11
+ RetryContext.displayName = "RetryContext";
12
+ const _RETRY_CHILDREN = (_jsxs(_Fragment, { children: [_jsx(ArrowPathIcon, {}), "Retry"] }));
13
+ /**
14
+ * Button that retries the nearest `<Catcher>` error boundary when clicked.
15
+ *
16
+ * - Reads the retry callback from `<Catcher>`'s private context, so it renders `null` when there is no boundary above it to retry.
17
+ * - Defaults to an "Retry" label with a refresh icon; pass `children` to override.
18
+ *
19
+ * @kind component
20
+ * @see https://shelving.cc/ui/RetryButton
21
+ */
22
+ export function RetryButton({ children = _RETRY_CHILDREN, ...props }) {
23
+ const retry = use(RetryContext);
24
+ if (!retry)
25
+ return null;
26
+ return (_jsx(Button, { onClick: retry, ...props, children: children }));
27
+ }
@@ -0,0 +1,48 @@
1
+ import { ArrowPathIcon } from "@heroicons/react/16/solid";
2
+ import { createContext, type ReactElement, use } from "react";
3
+ import type { Callback } from "../../util/function.js";
4
+ import type { OptionalChildProps } from "../util/index.js";
5
+ import { Button, type ButtonVariants } from "./Button.js";
6
+
7
+ /**
8
+ * Context for providing a "retry" callback to descendant `<RetryButton>` elements.
9
+ * - Used by `<Catcher>` to provide a retry callback to its children.
10
+ * - Default `<ErrorNotice>` and `<ErrorPage>` elements include `<RetryButton>` to trigger a retry on their parent `<Catcher>`
11
+ */
12
+ export const RetryContext = createContext<Callback | undefined>(undefined);
13
+ RetryContext.displayName = "RetryContext";
14
+
15
+ /**
16
+ * Component props for `<RetryButton>`
17
+ *
18
+ * @property children - The content of the button. Defaults to a refresh icon and `"Retry"`
19
+ *
20
+ * @see https://shelving.cc/ui/RetryButtonProps
21
+ */
22
+ export interface RetryButtonProps extends ButtonVariants, OptionalChildProps {}
23
+
24
+ const _RETRY_CHILDREN = (
25
+ <>
26
+ <ArrowPathIcon />
27
+ Retry
28
+ </>
29
+ );
30
+
31
+ /**
32
+ * Button that retries the nearest `<Catcher>` error boundary when clicked.
33
+ *
34
+ * - Reads the retry callback from `<Catcher>`'s private context, so it renders `null` when there is no boundary above it to retry.
35
+ * - Defaults to an "Retry" label with a refresh icon; pass `children` to override.
36
+ *
37
+ * @kind component
38
+ * @see https://shelving.cc/ui/RetryButton
39
+ */
40
+ export function RetryButton({ children = _RETRY_CHILDREN, ...props }: RetryButtonProps): ReactElement | null {
41
+ const retry = use(RetryContext);
42
+ if (!retry) return null;
43
+ return (
44
+ <Button onClick={retry} {...props}>
45
+ {children}
46
+ </Button>
47
+ );
48
+ }
@@ -1,6 +1,17 @@
1
1
  import type { ReactElement } from "react";
2
2
  import type { OptionalChildProps } from "../util/props.js";
3
3
  import { type ButtonVariants } from "./Button.js";
4
+ /**
5
+ * Component props for `<SubmitButton>`, a form submit button.
6
+ *
7
+ * @property children - The content of the button. Defaults to `"Save"` with a right-pointing arrow icon.
8
+ * @property strong - Whether the button should have strong styling. Defaults to `true`
9
+ * @property color - The color variant of the button. Defaults to `"primary"`
10
+ *
11
+ * @see https://shelving.cc/ui/SubmitButtonProps
12
+ */
13
+ export interface SubmitButtonProps extends ButtonVariants, OptionalChildProps {
14
+ }
4
15
  /**
5
16
  * Submit button for a form that disables itself and shows a spinner while the form is busy.
6
17
  * - Defaults to strong, full-width, primary styling and a "Save" label.
@@ -9,11 +20,4 @@ import { type ButtonVariants } from "./Button.js";
9
20
  * @example <SubmitButton>Save changes</SubmitButton>
10
21
  * @see https://shelving.cc/ui/SubmitButton
11
22
  */
12
- export declare function SubmitButton({ children, strong, color, full, ...variants }: SubmitButtonProps): ReactElement;
13
- /**
14
- * Props for `SubmitButton`, a form submit button.
15
- *
16
- * @see https://shelving.cc/ui/SubmitButtonProps
17
- */
18
- export interface SubmitButtonProps extends ButtonVariants, OptionalChildProps {
19
- }
23
+ export declare function SubmitButton({ children, strong, color, full, ...props }: SubmitButtonProps): ReactElement;
@@ -1,9 +1,10 @@
1
1
  import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { ArrowRightIcon } from "@heroicons/react/24/solid";
3
3
  import { useStore } from "../../react/useStore.js";
4
+ import { requireForm } from "../form/FormContext.js";
4
5
  import { LOADING } from "../misc/Loading.js";
5
6
  import { getButtonClass } from "./Button.js";
6
- import { requireForm } from "./FormContext.js";
7
+ const _SUBMIT_CHILDREN = (_jsxs(_Fragment, { children: ["Save", _jsx(ArrowRightIcon, {})] }));
7
8
  /**
8
9
  * Submit button for a form that disables itself and shows a spinner while the form is busy.
9
10
  * - Defaults to strong, full-width, primary styling and a "Save" label.
@@ -12,9 +13,8 @@ import { requireForm } from "./FormContext.js";
12
13
  * @example <SubmitButton>Save changes</SubmitButton>
13
14
  * @see https://shelving.cc/ui/SubmitButton
14
15
  */
15
- export function SubmitButton({ children = SUBMIT_CHILDREN, strong = true, color = "primary", full = true, ...variants }) {
16
+ export function SubmitButton({ children = _SUBMIT_CHILDREN, strong = true, color = "primary", full = true, ...props }) {
16
17
  const form = requireForm();
17
18
  const busy = useStore(form.busy).value;
18
- return (_jsx("button", { type: "submit", disabled: busy, className: getButtonClass({ strong, color, full, ...variants }), children: busy ? LOADING : children }));
19
+ return (_jsx("button", { type: "submit", disabled: busy, className: getButtonClass({ strong, color, full, ...props }), children: busy ? LOADING : children }));
19
20
  }
20
- const SUBMIT_CHILDREN = (_jsxs(_Fragment, { children: ["Save", _jsx(ArrowRightIcon, {})] }));
@@ -1,10 +1,28 @@
1
1
  import { ArrowRightIcon } from "@heroicons/react/24/solid";
2
2
  import type { ReactElement } from "react";
3
3
  import { useStore } from "../../react/useStore.js";
4
+ import { requireForm } from "../form/FormContext.js";
4
5
  import { LOADING } from "../misc/Loading.js";
5
6
  import type { OptionalChildProps } from "../util/props.js";
6
7
  import { type ButtonVariants, getButtonClass } from "./Button.js";
7
- import { requireForm } from "./FormContext.js";
8
+
9
+ /**
10
+ * Component props for `<SubmitButton>`, a form submit button.
11
+ *
12
+ * @property children - The content of the button. Defaults to `"Save"` with a right-pointing arrow icon.
13
+ * @property strong - Whether the button should have strong styling. Defaults to `true`
14
+ * @property color - The color variant of the button. Defaults to `"primary"`
15
+ *
16
+ * @see https://shelving.cc/ui/SubmitButtonProps
17
+ */
18
+ export interface SubmitButtonProps extends ButtonVariants, OptionalChildProps {}
19
+
20
+ const _SUBMIT_CHILDREN = (
21
+ <>
22
+ Save
23
+ <ArrowRightIcon />
24
+ </>
25
+ );
8
26
 
9
27
  /**
10
28
  * Submit button for a form that disables itself and shows a spinner while the form is busy.
@@ -15,31 +33,17 @@ import { requireForm } from "./FormContext.js";
15
33
  * @see https://shelving.cc/ui/SubmitButton
16
34
  */
17
35
  export function SubmitButton({
18
- children = SUBMIT_CHILDREN,
36
+ children = _SUBMIT_CHILDREN,
19
37
  strong = true,
20
38
  color = "primary",
21
39
  full = true,
22
- ...variants
40
+ ...props
23
41
  }: SubmitButtonProps): ReactElement {
24
42
  const form = requireForm();
25
43
  const busy = useStore(form.busy).value;
26
44
  return (
27
- <button type="submit" disabled={busy} className={getButtonClass({ strong, color, full, ...variants })}>
45
+ <button type="submit" disabled={busy} className={getButtonClass({ strong, color, full, ...props })}>
28
46
  {busy ? LOADING : children}
29
47
  </button>
30
48
  );
31
49
  }
32
-
33
- /**
34
- * Props for `SubmitButton`, a form submit button.
35
- *
36
- * @see https://shelving.cc/ui/SubmitButtonProps
37
- */
38
- export interface SubmitButtonProps extends ButtonVariants, OptionalChildProps {}
39
-
40
- const SUBMIT_CHILDREN = (
41
- <>
42
- Save
43
- <ArrowRightIcon />
44
- </>
45
- );
@@ -0,0 +1,5 @@
1
+ export * from "../button/Button.js";
2
+ export * from "../button/Clickable.js";
3
+ export * from "../button/FullscreenButton.js";
4
+ export * from "../button/RetryButton.js";
5
+ export * from "../button/SubmitButton.js";
@@ -0,0 +1,5 @@
1
+ export * from "../button/Button.js";
2
+ export * from "../button/Clickable.js";
3
+ export * from "../button/FullscreenButton.js";
4
+ export * from "../button/RetryButton.js";
5
+ export * from "../button/SubmitButton.js";
@@ -0,0 +1,5 @@
1
+ export * from "../button/Button.js";
2
+ export * from "../button/Clickable.js";
3
+ export * from "../button/FullscreenButton.js";
4
+ export * from "../button/RetryButton.js";
5
+ export * from "../button/SubmitButton.js";
@@ -1,6 +1,6 @@
1
1
  import { type ReactElement } from "react";
2
2
  import type { Callback } from "../../util/function.js";
3
- import type { ButtonVariants } from "../form/Button.js";
3
+ import type { ButtonVariants } from "../button/Button.js";
4
4
  import type { OptionalChildProps } from "../util/props.js";
5
5
  /**
6
6
  * Props for `<Dialog>` — optional `children` content and an `onClose` callback.
@@ -1,7 +1,7 @@
1
1
  import { XMarkIcon } from "@heroicons/react/24/solid";
2
2
  import { type MouseEvent, memo, type ReactElement, Suspense, useEffect, useRef } from "react";
3
3
  import type { Callback } from "../../util/function.js";
4
- import type { ButtonVariants } from "../form/Button.js";
4
+ import type { ButtonVariants } from "../button/Button.js";
5
5
  import { getModuleClass } from "../util/css.js";
6
6
  import type { OptionalChildProps } from "../util/props.js";
7
7
  import styles from "./Dialog.module.css";
@@ -7,8 +7,8 @@ import { Panel } from "../block/Panel.js";
7
7
  import { Row } from "../block/Row.js";
8
8
  import { Header, Section } from "../block/Section.js";
9
9
  import { Title } from "../block/Title.js";
10
- import { CheckboxInput } from "../form/CheckboxInput.js";
11
- import { TextInput } from "../form/TextInput.js";
10
+ import { CheckboxInput } from "../input/CheckboxInput.js";
11
+ import { TextInput } from "../input/TextInput.js";
12
12
  import { Page } from "../page/Page.js";
13
13
  import { TreeCards } from "../tree/TreeCards.js";
14
14
  import { useTreeMap } from "../tree/TreeContext.js";
@@ -8,8 +8,8 @@ import { Panel } from "../block/Panel.js";
8
8
  import { Row } from "../block/Row.js";
9
9
  import { Header, Section } from "../block/Section.js";
10
10
  import { Title } from "../block/Title.js";
11
- import { CheckboxInput } from "../form/CheckboxInput.js";
12
- import { TextInput } from "../form/TextInput.js";
11
+ import { CheckboxInput } from "../input/CheckboxInput.js";
12
+ import { TextInput } from "../input/TextInput.js";
13
13
  import { Page } from "../page/Page.js";
14
14
  import { TreeCards } from "../tree/TreeCards.js";
15
15
  import { useTreeMap } from "../tree/TreeContext.js";
@@ -1,8 +1,8 @@
1
1
  import type { Schema } from "../../schema/Schema.js";
2
2
  import type { Data } from "../../util/data.js";
3
3
  import type { AnyCaller } from "../../util/function.js";
4
+ import { type SchemaInputProps } from "../input/SchemaInput.js";
4
5
  import type { FormStore } from "./FormStore.js";
5
- import { type SchemaInputProps } from "./SchemaInput.js";
6
6
  /**
7
7
  * React context holding the current `FormStore`, provided by the `Form` component.
8
8
  *
@@ -1,7 +1,7 @@
1
1
  import { createContext } from "react";
2
2
  import { useStore } from "../../react/useStore.js";
3
+ import { isSchemaRequired } from "../input/SchemaInput.js";
3
4
  import { requireContext } from "../util/context.js";
4
- import { isSchemaRequired } from "./SchemaInput.js";
5
5
  /**
6
6
  * React context holding the current `FormStore`, provided by the `Form` component.
7
7
  *
@@ -3,9 +3,9 @@ import { useStore } from "../../react/useStore.js";
3
3
  import type { Schema } from "../../schema/Schema.js";
4
4
  import type { Data } from "../../util/data.js";
5
5
  import type { AnyCaller } from "../../util/function.js";
6
+ import { isSchemaRequired, type SchemaInputProps } from "../input/SchemaInput.js";
6
7
  import { requireContext } from "../util/context.js";
7
8
  import type { FormStore } from "./FormStore.js";
8
- import { isSchemaRequired, type SchemaInputProps } from "./SchemaInput.js";
9
9
 
10
10
  /**
11
11
  * React context holding the current `FormStore`, provided by the `Form` component.
@@ -1,5 +1,5 @@
1
1
  import type { ReactElement } from "react";
2
- import type { InputProps } from "./Input.js";
2
+ import type { InputProps } from "../input/Input.js";
3
3
  /**
4
4
  * Show a `<Field>` (label, input, and message) for a single named property of the current form.
5
5
  *
@@ -1,8 +1,8 @@
1
1
  import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
2
2
  import { useStore } from "../../react/useStore.js";
3
+ import { SchemaInput } from "../input/SchemaInput.js";
3
4
  import { Field } from "./Field.js";
4
5
  import { requireForm, useField } from "./FormContext.js";
5
- import { SchemaInput } from "./SchemaInput.js";
6
6
  /**
7
7
  * Show a `<Field>` (label, input, and message) for a single named property of the current form.
8
8
  *
@@ -1,9 +1,9 @@
1
1
  import type { ReactElement } from "react";
2
2
  import { useStore } from "../../react/useStore.js";
3
+ import type { InputProps } from "../input/Input.js";
4
+ import { SchemaInput } from "../input/SchemaInput.js";
3
5
  import { Field } from "./Field.js";
4
6
  import { requireForm, useField } from "./FormContext.js";
5
- import type { InputProps } from "./Input.js";
6
- import { SchemaInput } from "./SchemaInput.js";
7
7
 
8
8
  /**
9
9
  * Show a `<Field>` (label, input, and message) for a single named property of the current form.
@@ -1,8 +1,8 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Row } from "../block/Row.js";
3
3
  import { Footer } from "../block/Section.js";
4
+ import { SubmitButton } from "../button/SubmitButton.js";
4
5
  import { FormMessage } from "./FormMessage.js";
5
- import { SubmitButton } from "./SubmitButton.js";
6
6
  /**
7
7
  * Show a form footer with a submit button and the form's error message.
8
8
  * - Renders a row containing a `SubmitButton` (and any extra buttons passed as `children`).
@@ -1,9 +1,9 @@
1
1
  import type { ReactElement, ReactNode } from "react";
2
2
  import { Row } from "../block/Row.js";
3
3
  import { Footer } from "../block/Section.js";
4
+ import { SubmitButton } from "../button/SubmitButton.js";
4
5
  import type { OptionalChildProps } from "../util/props.js";
5
6
  import { FormMessage } from "./FormMessage.js";
6
- import { SubmitButton } from "./SubmitButton.js";
7
7
 
8
8
  /**
9
9
  * Props for `FormFooter`, the submit-button-and-message footer for a form.
@@ -1,5 +1,5 @@
1
1
  import type { ReactElement } from "react";
2
- import type { InputProps } from "./Input.js";
2
+ import type { InputProps } from "../input/Input.js";
3
3
  /**
4
4
  * Props for `FormInput`, a bare `SchemaInput` bound to a named form field.
5
5
  *
@@ -1,6 +1,6 @@
1
1
  import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
2
+ import { SchemaInput } from "../input/SchemaInput.js";
2
3
  import { requireForm, useField } from "./FormContext.js";
3
- import { SchemaInput } from "./SchemaInput.js";
4
4
  /**
5
5
  * Show a `SchemaInput` for a single named property of the current form.
6
6
  * - Reads the field's value, schema, and message from the form context via `useField()`.
@@ -1,7 +1,7 @@
1
1
  import type { ReactElement } from "react";
2
+ import type { InputProps } from "../input/Input.js";
3
+ import { SchemaInput } from "../input/SchemaInput.js";
2
4
  import { requireForm, useField } from "./FormContext.js";
3
- import type { InputProps } from "./Input.js";
4
- import { SchemaInput } from "./SchemaInput.js";
5
5
 
6
6
  /**
7
7
  * Props for `FormInput`, a bare `SchemaInput` bound to a named form field.
@@ -6,37 +6,19 @@ import type { ReactElement } from "react";
6
6
  */
7
7
  export interface ProgressProps {
8
8
  value: number;
9
+ min?: number;
10
+ max?: number;
9
11
  success?: boolean;
10
12
  warning?: boolean;
11
13
  danger?: boolean;
12
14
  }
13
15
  /**
14
- * Show progress as a single continuous horizontal bar, filled to `value` clamped between `0` and `1`.
16
+ * Show progress as a single continuous horizontal bar, filled to `value` within the `min`–`max` range (matches `getPercent()` and `formatPercent()`).
17
+ * - The fill is allowed to overspill; CSS clamps it to the `0%`–`100%` range via `min-width`/`max-width`.
15
18
  *
16
19
  * @returns A progress bar element.
17
20
  * @kind component
18
- * @example <Progress value={0.5} />
21
+ * @example <Progress value={3} max={4} />
19
22
  * @see https://shelving.cc/ui/Progress
20
23
  */
21
- export declare function Progress({ value, success, warning, danger }: ProgressProps): ReactElement | null;
22
- /**
23
- * Props for `SegmentedProgress`, a stepped progress bar of discrete segments.
24
- *
25
- * @see https://shelving.cc/ui/SegmentedProgressProps
26
- */
27
- export interface SegmentedProgressProps {
28
- total: number;
29
- current: number;
30
- success?: boolean;
31
- warning?: boolean;
32
- danger?: boolean;
33
- }
34
- /**
35
- * Show step progress as a horizontal bar of `total` segments, of which `current + 1` are filled.
36
- *
37
- * @returns A segmented progress bar element, or `null` when `total` is not positive.
38
- * @kind component
39
- * @example <SegmentedProgress total={4} current={1} />
40
- * @see https://shelving.cc/ui/SegmentedProgress
41
- */
42
- export declare function SegmentedProgress({ total, current, success, warning, danger }: SegmentedProgressProps): ReactElement | null;
24
+ export declare function Progress({ value, min, max, success, warning, danger }: ProgressProps): ReactElement | null;
@@ -1,30 +1,19 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { formatPercent } from "../../util/format.js";
3
+ import { getPercent } from "../../util/number.js";
2
4
  import { getClass, getModuleClass } from "../util/css.js";
3
5
  import styles from "./Progress.module.css";
4
6
  /**
5
- * Show progress as a single continuous horizontal bar, filled to `value` clamped between `0` and `1`.
7
+ * Show progress as a single continuous horizontal bar, filled to `value` within the `min`–`max` range (matches `getPercent()` and `formatPercent()`).
8
+ * - The fill is allowed to overspill; CSS clamps it to the `0%`–`100%` range via `min-width`/`max-width`.
6
9
  *
7
10
  * @returns A progress bar element.
8
11
  * @kind component
9
- * @example <Progress value={0.5} />
12
+ * @example <Progress value={3} max={4} />
10
13
  * @see https://shelving.cc/ui/Progress
11
14
  */
12
- export function Progress({ value, success, warning, danger }) {
13
- const clamped = Number.isFinite(value) ? Math.min(1, Math.max(0, value)) : 0;
14
- const progressStyle = { ["--progress-value"]: `${clamped * 100}%` };
15
- return (_jsx("div", { className: getClass(getModuleClass(styles, "track"), success && getModuleClass(styles, "success"), warning && getModuleClass(styles, "warning"), danger && getModuleClass(styles, "danger")), style: progressStyle, children: _jsx("span", { className: getModuleClass(styles, "fill") }) }));
16
- }
17
- /**
18
- * Show step progress as a horizontal bar of `total` segments, of which `current + 1` are filled.
19
- *
20
- * @returns A segmented progress bar element, or `null` when `total` is not positive.
21
- * @kind component
22
- * @example <SegmentedProgress total={4} current={1} />
23
- * @see https://shelving.cc/ui/SegmentedProgress
24
- */
25
- export function SegmentedProgress({ total, current, success, warning, danger }) {
26
- if (total <= 0)
27
- return null;
28
- const progressStyle = { ["--progress-steps"]: total };
29
- return (_jsx("div", { className: getClass(getModuleClass(styles, "segmented"), success && getModuleClass(styles, "success"), warning && getModuleClass(styles, "warning"), danger && getModuleClass(styles, "danger")), style: progressStyle, children: Array.from({ length: total }, (_, i) => (_jsx("span", { className: getClass(getModuleClass(styles, "item"), i <= current && getModuleClass(styles, "active")) }, i.toString()))) }));
15
+ export function Progress({ value, min = 0, max = 100, success, warning, danger }) {
16
+ const percent = getPercent(value - min, max - min);
17
+ const fillStyle = { width: `${Number.isFinite(percent) ? percent : 0}%` };
18
+ return (_jsx("figure", { className: getClass(getModuleClass(styles, "track"), success && getModuleClass(styles, "success"), warning && getModuleClass(styles, "warning"), danger && getModuleClass(styles, "danger")), role: "progressbar", "aria-valuemin": min, "aria-valuemax": max, "aria-valuenow": value, "aria-valuetext": formatPercent(value - min, max - min), children: _jsx("span", { className: getModuleClass(styles, "fill"), style: fillStyle }) }));
30
19
  }
@@ -7,51 +7,32 @@
7
7
  /* Continuous progress bar — a single track that fills horizontally. */
8
8
  .track {
9
9
  position: relative;
10
+ margin: 0;
10
11
  inline-size: 100%;
11
12
  height: var(--progress-height, 0.375rem);
12
13
  border-radius: var(--progress-radius, 999px);
13
- background: var(--progress-color-bg, var(--tint-90));
14
+ background: var(--progress-background, var(--tint-90));
14
15
  overflow: hidden;
15
16
  }
16
17
 
17
18
  .fill {
18
19
  display: block;
19
20
  block-size: 100%;
20
- inline-size: var(--progress-value, 0%);
21
- background: var(--progress-color-active, var(--color-blue));
22
- transition:
23
- inline-size 160ms ease-out,
24
- background-color var(--duration-fast) ease-in-out;
25
- }
26
-
27
- /* Segmented progress — a grid of N items, of which some are `.active`. */
28
- .segmented {
29
- display: grid;
30
- grid-template-columns: repeat(var(--progress-steps), minmax(0, 1fr));
31
- gap: var(--progress-gap, 0.375rem);
32
- }
33
-
34
- .item {
35
- height: var(--progress-height, 0.375rem);
36
- border-radius: var(--progress-radius, 999px);
37
- background: var(--progress-color-bg, var(--tint-90));
38
- }
39
-
40
- .active {
41
- background: var(--progress-color-active, var(--color-blue));
21
+ /* Width is set inline; clamp overspill to the track here. */
22
+ min-width: 0px;
23
+ max-width: 100%;
24
+ background: var(--progress-color, var(--color-blue));
25
+ transition: all var(--duration-fast);
42
26
  }
43
27
 
44
28
  /* Status variants applied at the container level. */
45
- .success .fill,
46
- .success .active {
47
- background: var(--progress-success-color-active, var(--color-green));
29
+ .success .fill {
30
+ background: var(--progress-success, var(--color-green));
48
31
  }
49
- .warning .fill,
50
- .warning .active {
51
- background: var(--progress-warning-color-active, var(--color-orange));
32
+ .warning .fill {
33
+ background: var(--progress-warning, var(--color-orange));
52
34
  }
53
- .danger .fill,
54
- .danger .active {
55
- background: var(--progress-danger-color-active, var(--color-red));
35
+ .danger .fill {
36
+ background: var(--progress-danger, var(--color-red));
56
37
  }
57
38
  }
@@ -1,4 +1,6 @@
1
1
  import type { CSSProperties, ReactElement } from "react";
2
+ import { formatPercent } from "../../util/format.js";
3
+ import { getPercent } from "../../util/number.js";
2
4
  import { getClass, getModuleClass } from "../util/css.js";
3
5
  import styles from "./Progress.module.css";
4
6
 
@@ -9,76 +11,41 @@ import styles from "./Progress.module.css";
9
11
  */
10
12
  export interface ProgressProps {
11
13
  value: number;
14
+ min?: number;
15
+ max?: number;
12
16
  success?: boolean;
13
17
  warning?: boolean;
14
18
  danger?: boolean;
15
19
  }
16
20
 
17
21
  /**
18
- * Show progress as a single continuous horizontal bar, filled to `value` clamped between `0` and `1`.
22
+ * Show progress as a single continuous horizontal bar, filled to `value` within the `min`–`max` range (matches `getPercent()` and `formatPercent()`).
23
+ * - The fill is allowed to overspill; CSS clamps it to the `0%`–`100%` range via `min-width`/`max-width`.
19
24
  *
20
25
  * @returns A progress bar element.
21
26
  * @kind component
22
- * @example <Progress value={0.5} />
27
+ * @example <Progress value={3} max={4} />
23
28
  * @see https://shelving.cc/ui/Progress
24
29
  */
25
- export function Progress({ value, success, warning, danger }: ProgressProps): ReactElement | null {
26
- const clamped = Number.isFinite(value) ? Math.min(1, Math.max(0, value)) : 0;
27
- const progressStyle = { ["--progress-value" as string]: `${clamped * 100}%` } as CSSProperties;
30
+ export function Progress({ value, min = 0, max = 100, success, warning, danger }: ProgressProps): ReactElement | null {
31
+ const percent = getPercent(value - min, max - min);
32
+ const fillStyle = { width: `${Number.isFinite(percent) ? percent : 0}%` } as CSSProperties;
28
33
 
29
34
  return (
30
- <div
35
+ <figure
31
36
  className={getClass(
32
37
  getModuleClass(styles, "track"),
33
38
  success && getModuleClass(styles, "success"),
34
39
  warning && getModuleClass(styles, "warning"),
35
40
  danger && getModuleClass(styles, "danger"),
36
41
  )}
37
- style={progressStyle}
42
+ role="progressbar"
43
+ aria-valuemin={min}
44
+ aria-valuemax={max}
45
+ aria-valuenow={value}
46
+ aria-valuetext={formatPercent(value - min, max - min)}
38
47
  >
39
- <span className={getModuleClass(styles, "fill")} />
40
- </div>
41
- );
42
- }
43
-
44
- /**
45
- * Props for `SegmentedProgress`, a stepped progress bar of discrete segments.
46
- *
47
- * @see https://shelving.cc/ui/SegmentedProgressProps
48
- */
49
- export interface SegmentedProgressProps {
50
- total: number;
51
- current: number;
52
- success?: boolean;
53
- warning?: boolean;
54
- danger?: boolean;
55
- }
56
-
57
- /**
58
- * Show step progress as a horizontal bar of `total` segments, of which `current + 1` are filled.
59
- *
60
- * @returns A segmented progress bar element, or `null` when `total` is not positive.
61
- * @kind component
62
- * @example <SegmentedProgress total={4} current={1} />
63
- * @see https://shelving.cc/ui/SegmentedProgress
64
- */
65
- export function SegmentedProgress({ total, current, success, warning, danger }: SegmentedProgressProps): ReactElement | null {
66
- if (total <= 0) return null;
67
- const progressStyle = { ["--progress-steps" as string]: total } as CSSProperties;
68
-
69
- return (
70
- <div
71
- className={getClass(
72
- getModuleClass(styles, "segmented"),
73
- success && getModuleClass(styles, "success"),
74
- warning && getModuleClass(styles, "warning"),
75
- danger && getModuleClass(styles, "danger"),
76
- )}
77
- style={progressStyle}
78
- >
79
- {Array.from({ length: total }, (_, i) => (
80
- <span key={i.toString()} className={getClass(getModuleClass(styles, "item"), i <= current && getModuleClass(styles, "active"))} />
81
- ))}
82
- </div>
48
+ <span className={getModuleClass(styles, "fill")} style={fillStyle} />
49
+ </figure>
83
50
  );
84
51
  }