shelving 1.264.0 → 1.264.2

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 (210) hide show
  1. package/package.json +1 -1
  2. package/ui/README.md +2 -2
  3. package/ui/block/Blockquote.module.css +0 -3
  4. package/ui/block/Card.d.ts +1 -1
  5. package/ui/block/Card.js +1 -1
  6. package/ui/block/Card.md +3 -7
  7. package/ui/block/Card.module.css +0 -3
  8. package/ui/block/Card.tsx +1 -1
  9. package/ui/block/Heading.md +0 -1
  10. package/ui/block/Heading.module.css +0 -3
  11. package/ui/block/Image.d.ts +3 -3
  12. package/ui/block/Image.js +4 -4
  13. package/ui/block/Image.module.css +4 -1
  14. package/ui/block/Image.tsx +14 -4
  15. package/ui/block/Label.module.css +0 -3
  16. package/ui/block/List.md +1 -2
  17. package/ui/block/List.module.css +0 -3
  18. package/ui/block/Panel.md +1 -2
  19. package/ui/block/Panel.module.css +0 -3
  20. package/ui/block/Paragraph.md +1 -2
  21. package/ui/block/Paragraph.module.css +0 -3
  22. package/ui/block/Preformatted.module.css +0 -3
  23. package/ui/block/Subheading.md +0 -1
  24. package/ui/block/Subheading.module.css +0 -3
  25. package/ui/block/Title.md +0 -1
  26. package/ui/block/Title.module.css +0 -3
  27. package/ui/block/Video.d.ts +3 -58
  28. package/ui/block/Video.js +2 -52
  29. package/ui/block/Video.module.css +1 -51
  30. package/ui/block/Video.tsx +3 -99
  31. package/ui/{form → button}/Button.d.ts +6 -2
  32. package/ui/{form → button}/Button.md +1 -2
  33. package/ui/{form → button}/Button.module.css +0 -3
  34. package/ui/{form → button}/Button.tsx +6 -1
  35. package/ui/button/FullscreenButton.d.ts +31 -0
  36. package/ui/button/FullscreenButton.js +37 -0
  37. package/ui/button/FullscreenButton.tsx +58 -0
  38. package/ui/button/RetryButton.d.ts +29 -0
  39. package/ui/button/RetryButton.js +27 -0
  40. package/ui/button/RetryButton.tsx +48 -0
  41. package/ui/{form → button}/SubmitButton.d.ts +12 -8
  42. package/ui/{form → button}/SubmitButton.js +4 -4
  43. package/ui/{form → button}/SubmitButton.tsx +22 -18
  44. package/ui/button/index.d.ts +5 -0
  45. package/ui/button/index.js +5 -0
  46. package/ui/button/index.ts +5 -0
  47. package/ui/dialog/Dialog.d.ts +1 -1
  48. package/ui/dialog/Dialog.tsx +1 -1
  49. package/ui/docs/DocumentationPage.test.tsx +2 -4
  50. package/ui/docs/DocumentationParams.js +1 -1
  51. package/ui/docs/DocumentationParams.tsx +1 -1
  52. package/ui/docs/DocumentationProperties.js +1 -1
  53. package/ui/docs/DocumentationProperties.tsx +1 -1
  54. package/ui/docs/DocumentationReferences.js +1 -1
  55. package/ui/docs/DocumentationReferences.tsx +1 -1
  56. package/ui/docs/DocumentationReturns.js +1 -1
  57. package/ui/docs/DocumentationReturns.tsx +1 -1
  58. package/ui/docs/DocumentationSearchPage.js +2 -2
  59. package/ui/docs/DocumentationSearchPage.tsx +2 -2
  60. package/ui/docs/DocumentationThrows.js +1 -1
  61. package/ui/docs/DocumentationThrows.tsx +1 -1
  62. package/ui/form/Field.test.tsx +1 -1
  63. package/ui/form/FormContext.d.ts +1 -1
  64. package/ui/form/FormContext.js +1 -1
  65. package/ui/form/FormContext.tsx +1 -1
  66. package/ui/form/FormFields.d.ts +1 -1
  67. package/ui/form/FormFields.js +1 -1
  68. package/ui/form/FormFields.tsx +2 -2
  69. package/ui/form/FormFooter.js +1 -1
  70. package/ui/form/FormFooter.tsx +1 -1
  71. package/ui/form/FormInput.d.ts +1 -1
  72. package/ui/form/FormInput.js +1 -1
  73. package/ui/form/FormInput.tsx +2 -2
  74. package/ui/form/Progress.d.ts +6 -24
  75. package/ui/form/Progress.js +9 -20
  76. package/ui/form/Progress.module.css +13 -32
  77. package/ui/form/Progress.tsx +18 -51
  78. package/ui/form/index.d.ts +0 -23
  79. package/ui/form/index.js +0 -23
  80. package/ui/form/index.ts +0 -23
  81. package/ui/index.d.ts +2 -0
  82. package/ui/index.js +2 -0
  83. package/ui/index.ts +2 -0
  84. package/ui/inline/Deleted.md +4 -5
  85. package/ui/inline/Deleted.module.css +1 -3
  86. package/ui/inline/Inserted.md +4 -5
  87. package/ui/inline/Inserted.module.css +1 -3
  88. package/ui/inline/Link.d.ts +1 -1
  89. package/ui/inline/Link.js +1 -1
  90. package/ui/inline/Link.md +2 -3
  91. package/ui/inline/Link.module.css +1 -3
  92. package/ui/inline/Link.tsx +1 -1
  93. package/ui/inline/Mark.js +1 -2
  94. package/ui/inline/Mark.md +5 -5
  95. package/ui/inline/Mark.module.css +2 -3
  96. package/ui/inline/Mark.tsx +0 -2
  97. package/ui/{form → input}/ArrayInput.js +1 -1
  98. package/ui/{form → input}/ArrayInput.tsx +1 -1
  99. package/ui/{form → input}/ButtonInput.d.ts +1 -1
  100. package/ui/{form → input}/ButtonInput.js +1 -1
  101. package/ui/{form → input}/ButtonInput.tsx +1 -1
  102. package/ui/{form → input}/ButtonPopover.d.ts +1 -1
  103. package/ui/{form → input}/ButtonPopover.js +1 -1
  104. package/ui/{form → input}/ButtonPopover.tsx +1 -1
  105. package/ui/{form → input}/DictionaryInput.js +1 -1
  106. package/ui/{form → input}/DictionaryInput.tsx +1 -1
  107. package/ui/{form → input}/SchemaInput.js +1 -1
  108. package/ui/{form → input}/SchemaInput.test.tsx +3 -3
  109. package/ui/{form → input}/SchemaInput.tsx +1 -1
  110. package/ui/{form → input}/TextInput.d.ts +1 -1
  111. package/ui/{form → input}/TextInput.js +1 -1
  112. package/ui/{form → input}/TextInput.tsx +1 -1
  113. package/ui/input/index.d.ts +20 -0
  114. package/ui/input/index.js +20 -0
  115. package/ui/input/index.ts +20 -0
  116. package/ui/layout/CenteredLayout.d.ts +5 -7
  117. package/ui/layout/CenteredLayout.js +8 -4
  118. package/ui/layout/CenteredLayout.md +9 -2
  119. package/ui/layout/CenteredLayout.module.css +16 -22
  120. package/ui/layout/CenteredLayout.tsx +18 -12
  121. package/ui/layout/Layout.d.ts +1 -1
  122. package/ui/layout/Layout.js +4 -0
  123. package/ui/layout/Layout.ts +6 -0
  124. package/ui/layout/SidebarLayout.js +13 -6
  125. package/ui/layout/SidebarLayout.md +4 -4
  126. package/ui/layout/SidebarLayout.module.css +6 -9
  127. package/ui/layout/SidebarLayout.tsx +21 -18
  128. package/ui/menu/Menu.d.ts +1 -1
  129. package/ui/menu/Menu.js +1 -1
  130. package/ui/menu/Menu.tsx +1 -1
  131. package/ui/misc/Catcher.d.ts +2 -19
  132. package/ui/misc/Catcher.js +3 -22
  133. package/ui/misc/Catcher.tsx +4 -40
  134. package/ui/misc/MetaContext.test.tsx +2 -3
  135. package/ui/misc/Tag.d.ts +1 -1
  136. package/ui/misc/Tag.js +1 -1
  137. package/ui/misc/Tag.md +1 -2
  138. package/ui/misc/Tag.module.css +0 -3
  139. package/ui/misc/Tag.tsx +1 -1
  140. package/ui/notice/Message.module.css +0 -3
  141. package/ui/notice/Notice.md +1 -2
  142. package/ui/notice/Notice.module.css +0 -3
  143. package/ui/router/Router.test.tsx +1 -4
  144. package/ui/style/TINT_CLASS.md +1 -1
  145. package/ui/style/Width.d.ts +2 -1
  146. package/ui/style/Width.module.css +47 -17
  147. package/ui/style/Width.tsx +22 -1
  148. package/ui/style/getWidthClass.md +5 -9
  149. package/ui/table/Table.md +1 -1
  150. package/ui/tree/TreeButton.d.ts +1 -1
  151. package/ui/tree/TreeButton.js +1 -1
  152. package/ui/tree/TreeButton.test.tsx +2 -5
  153. package/ui/tree/TreeButton.tsx +1 -1
  154. package/ui/tree/TreeContext.test.tsx +2 -3
  155. package/ui/tree/TreeMarkup.test.tsx +2 -5
  156. package/ui/tree/TreeRouter.test.tsx +2 -5
  157. package/ui/tree/TreeSidebar.js +1 -1
  158. package/ui/tree/TreeSidebar.tsx +1 -1
  159. /package/ui/{form → button}/Button.js +0 -0
  160. /package/ui/{form → button}/Clickable.d.ts +0 -0
  161. /package/ui/{form → button}/Clickable.js +0 -0
  162. /package/ui/{form → button}/Clickable.tsx +0 -0
  163. /package/ui/{form → input}/ArrayInput.d.ts +0 -0
  164. /package/ui/{form → input}/ArrayRadioInputs.d.ts +0 -0
  165. /package/ui/{form → input}/ArrayRadioInputs.js +0 -0
  166. /package/ui/{form → input}/ArrayRadioInputs.tsx +0 -0
  167. /package/ui/{form → input}/ButtonInputPopover.d.ts +0 -0
  168. /package/ui/{form → input}/ButtonInputPopover.js +0 -0
  169. /package/ui/{form → input}/ButtonInputPopover.tsx +0 -0
  170. /package/ui/{form → input}/CheckboxInput.d.ts +0 -0
  171. /package/ui/{form → input}/CheckboxInput.js +0 -0
  172. /package/ui/{form → input}/CheckboxInput.tsx +0 -0
  173. /package/ui/{form → input}/ChoiceRadioInputs.d.ts +0 -0
  174. /package/ui/{form → input}/ChoiceRadioInputs.js +0 -0
  175. /package/ui/{form → input}/ChoiceRadioInputs.tsx +0 -0
  176. /package/ui/{form → input}/DataInput.d.ts +0 -0
  177. /package/ui/{form → input}/DataInput.js +0 -0
  178. /package/ui/{form → input}/DataInput.tsx +0 -0
  179. /package/ui/{form → input}/DateInput.d.ts +0 -0
  180. /package/ui/{form → input}/DateInput.js +0 -0
  181. /package/ui/{form → input}/DateInput.tsx +0 -0
  182. /package/ui/{form → input}/DictionaryInput.d.ts +0 -0
  183. /package/ui/{form → input}/FileInput.d.ts +0 -0
  184. /package/ui/{form → input}/FileInput.js +0 -0
  185. /package/ui/{form → input}/FileInput.tsx +0 -0
  186. /package/ui/{form → input}/Input.d.ts +0 -0
  187. /package/ui/{form → input}/Input.js +0 -0
  188. /package/ui/{form → input}/Input.module.css +0 -0
  189. /package/ui/{form → input}/Input.tsx +0 -0
  190. /package/ui/{form → input}/NumberInput.d.ts +0 -0
  191. /package/ui/{form → input}/NumberInput.js +0 -0
  192. /package/ui/{form → input}/NumberInput.tsx +0 -0
  193. /package/ui/{form → input}/OutputInput.d.ts +0 -0
  194. /package/ui/{form → input}/OutputInput.js +0 -0
  195. /package/ui/{form → input}/OutputInput.tsx +0 -0
  196. /package/ui/{form → input}/Popover.d.ts +0 -0
  197. /package/ui/{form → input}/Popover.js +0 -0
  198. /package/ui/{form → input}/Popover.module.css +0 -0
  199. /package/ui/{form → input}/Popover.tsx +0 -0
  200. /package/ui/{form → input}/QueryInput.d.ts +0 -0
  201. /package/ui/{form → input}/QueryInput.js +0 -0
  202. /package/ui/{form → input}/QueryInput.tsx +0 -0
  203. /package/ui/{form → input}/RadioInput.d.ts +0 -0
  204. /package/ui/{form → input}/RadioInput.js +0 -0
  205. /package/ui/{form → input}/RadioInput.tsx +0 -0
  206. /package/ui/{form → input}/SchemaInput.d.ts +0 -0
  207. /package/ui/{form → input}/SchemaInput.md +0 -0
  208. /package/ui/{form → input}/SelectInput.d.ts +0 -0
  209. /package/ui/{form → input}/SelectInput.js +0 -0
  210. /package/ui/{form → input}/SelectInput.tsx +0 -0
@@ -5,7 +5,7 @@ Inserted text — renders an `<ins>` element to mark content that has been added
5
5
  **Things to know:**
6
6
 
7
7
  - Use `Inserted` for content genuinely added to a document (edits, diffs, new prices), and `<Deleted>` for content removed — they pair up.
8
- - It drives its colour through the [tint ladder](/ui/TINT_CLASS), so the `color` variant (`color="purple"`, `color="blue"`, …) recolours the underline. The base tint defaults to `--color-green`.
8
+ - It colours itself directly from `--color-green` rather than the tint ladder, so an insertion stays a consistent green even inside a tinted region; change it with `--inserted-color`.
9
9
  - Inside `<Prose>` a raw `<ins>` picks up the same styling, so Markdown-rendered insertions match component ones.
10
10
 
11
11
  ## Usage
@@ -22,13 +22,12 @@ import { Paragraph, Deleted, Inserted } from "shelving/ui";
22
22
 
23
23
  ## Styling
24
24
 
25
- `Inserted` paints from the [tint ladder](/ui/TINT_CLASS): the `50` tint sets the text colour, defaulting to `--color-green`. Override `--inserted-tint` to recolour from the base, or set each property directly.
25
+ `Inserted` colours its text directly from `--color-green` (not the tint ladder), so insertions stay a consistent green regardless of the surrounding tint. Override `--inserted-color` to recolour.
26
26
 
27
27
  | Variable | Styles | Default |
28
28
  |---|---|---|
29
- | `--inserted-tint` | Base tint (`--tint-50`) the colour derives from | `var(--color-green)` |
30
- | `--inserted-color` | Text colour | `var(--tint-50)` |
29
+ | `--inserted-color` | Text colour | `var(--color-green)` |
31
30
  | `--inserted-decoration` | Text decoration | `underline var(--stroke-normal)` |
32
31
  | `--inserted-weight` | Font weight | `var(--weight-strong)` |
33
32
 
34
- **Global tokens it reads:** `--color-green`, `--stroke-normal`, `--weight-strong`, and the tint-ladder step `--tint-50`.
33
+ **Global tokens it reads:** `--color-green`, `--stroke-normal`, and `--weight-strong`.
@@ -6,10 +6,8 @@
6
6
  @layer components {
7
7
  .inserted,
8
8
  .prose ins {
9
- --tint-50: var(--inserted-tint, var(--color-green));
10
-
11
9
  /* Style */
12
- color: var(--inserted-color, var(--tint-50));
10
+ color: var(--inserted-color, var(--color-green));
13
11
  text-decoration: var(--inserted-decoration, underline var(--stroke-normal));
14
12
 
15
13
  /* Text */
@@ -1,5 +1,5 @@
1
1
  import type { ReactElement } from "react";
2
- import { type ClickableProps } from "../form/Clickable.js";
2
+ import { type ClickableProps } from "../button/Clickable.js";
3
3
  import { type TypographyVariants } from "../style/Typography.js";
4
4
  /**
5
5
  * Props for `Link` — `ClickableProps` (`href` for navigation or `onClick` for actions) plus colour and typography variants.
package/ui/inline/Link.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- import { Clickable } from "../form/Clickable.js";
2
+ import { Clickable } from "../button/Clickable.js";
3
3
  import { getTypographyClass } from "../style/Typography.js";
4
4
  import { getClass, getModuleClass } from "../util/css.js";
5
5
  import LINK_CSS from "./Link.module.css";
package/ui/inline/Link.md CHANGED
@@ -31,12 +31,11 @@ import { Link } from "shelving/ui";
31
31
 
32
32
  ## Styling
33
33
 
34
- `Link` drives its colour through the tint ladder, so the `color` variant (`color="purple"`, `color="red"`, …) recolours the link. By default the `50` tint resolves to the global `--color-link` token.
34
+ `Link` colours itself from the global `--color-link` token by default. Inside a tinted scope (`color=` / `status=` on an ancestor) `--color-link` resolves to `inherit`, so links adopt the surrounding tinted text colour. Override `--link-color` to set it directly.
35
35
 
36
36
  | Variable | Styles | Default |
37
37
  |---|---|---|
38
- | `--link-tint` | Base tint (`--tint-50`) the link colour derives from | `var(--color-link)` |
39
- | `--link-color` | Text colour | `var(--tint-50)` |
38
+ | `--link-color` | Text colour | `var(--color-link)` |
40
39
  | `--link-weight` | Font weight | `var(--weight-strong)` |
41
40
 
42
41
  **Global tokens it reads:** `--color-link`, `--weight-strong`, and `--stroke-normal` (the underline thickness).
@@ -6,10 +6,8 @@
6
6
  @layer components {
7
7
  .link,
8
8
  .prose a {
9
- --tint-50: var(--link-tint, var(--color-link));
10
-
11
9
  /* Style */
12
- color: var(--link-color, var(--tint-50));
10
+ color: var(--link-color, var(--color-link));
13
11
  text-decoration: none;
14
12
  cursor: inherit;
15
13
 
@@ -1,5 +1,5 @@
1
1
  import type { ReactElement } from "react";
2
- import { Clickable, type ClickableProps } from "../form/Clickable.js";
2
+ import { Clickable, type ClickableProps } from "../button/Clickable.js";
3
3
  import { getTypographyClass, type TypographyVariants } from "../style/Typography.js";
4
4
  import { getClass, getModuleClass } from "../util/css.js";
5
5
  import LINK_CSS from "./Link.module.css";
package/ui/inline/Mark.js CHANGED
@@ -1,5 +1,4 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- import { TINT_CLASS } from "../style/Tint.js";
3
2
  import { getTypographyClass } from "../style/Typography.js";
4
3
  import { getClass, getModuleClass } from "../util/css.js";
5
4
  import MARK_CSS from "./Mark.module.css";
@@ -12,5 +11,5 @@ const MARK_CLASS = getModuleClass(MARK_CSS, "mark");
12
11
  */
13
12
  export function Mark({ children, ...props }) {
14
13
  return (_jsx("mark", { className: getClass(MARK_CLASS, //
15
- TINT_CLASS, getTypographyClass(props)), children: children }));
14
+ getTypographyClass(props)), children: children }));
16
15
  }
package/ui/inline/Mark.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Mark
2
2
 
3
- Highlighted text — renders a `<mark>` element to call attention to a run of text, such as a matched search term. Painted as a small inline pill with a yellow background by default.
3
+ Highlighted text — renders a `<mark>` element to call attention to a run of text, such as a matched search term. Painted as a small inline pill with a translucent yellow background by default.
4
4
 
5
5
  **Things to know:**
6
6
 
@@ -20,15 +20,15 @@ import { Mark } from "shelving/ui";
20
20
 
21
21
  ## Styling
22
22
 
23
- `Mark` paints from the [tint ladder](/ui/TINT_CLASS): the `50` tint sets the background and the `00` tint the text. By default the base tint resolves to `--color-yellow`; override `--mark-tint` to recolour the whole pill, or `--mark-background` / `--mark-color` to set the two faces independently.
23
+ `Mark` highlights with a translucent wash of `--color-yellow` `color-mix(…, transparent)`, so the text underneath stays legible with the text painted from `--tint-00`. Override `--mark-tint` to change the highlight hue, `--mark-background` to replace the fill outright, or `--mark-color` for the text.
24
24
 
25
25
  | Variable | Styles | Default |
26
26
  |---|---|---|
27
- | `--mark-tint` | Base tint (`--tint-50`) the pill derives from | `var(--color-yellow)` |
28
- | `--mark-background` | Background fill | `var(--tint-50)` |
27
+ | `--mark-tint` | Highlight hue, mixed 50% with `transparent` for the background | `var(--color-yellow)` |
28
+ | `--mark-background` | Background fill | `color-mix(in oklch, var(--mark-tint, var(--color-yellow)), transparent)` |
29
29
  | `--mark-color` | Text colour | `var(--tint-00)` |
30
30
  | `--mark-padding` | Inline padding | `var(--space-xxsmall)` |
31
31
  | `--mark-radius` | Corner radius | `var(--radius-xxsmall)` |
32
32
  | `--mark-weight` | Font weight | `var(--weight-strong)` |
33
33
 
34
- **Global tokens it reads:** `--color-yellow`, `--space-xxsmall`, `--radius-xxsmall`, `--weight-strong`, and the tint-ladder steps `--tint-50` / `--tint-00`.
34
+ **Global tokens it reads:** `--color-yellow`, `--space-xxsmall`, `--radius-xxsmall`, `--weight-strong`, and the tint-ladder step `--tint-00`.
@@ -1,4 +1,5 @@
1
1
  @import "../style/layers.css";
2
+ @import "../style/Color.module.css";
2
3
  @import "../style/Radius.module.css";
3
4
  @import "../style/Typography.module.css";
4
5
  @import "../style/Tint.module.css";
@@ -6,8 +7,6 @@
6
7
  @layer components {
7
8
  .mark,
8
9
  .prose mark {
9
- --tint-50: var(--mark-tint, var(--color-yellow));
10
-
11
10
  /* Box */
12
11
  display: inline-block;
13
12
  padding-inline: var(--mark-padding, var(--space-xxsmall));
@@ -15,7 +14,7 @@
15
14
  vertical-align: baseline;
16
15
 
17
16
  /* Style */
18
- background: var(--mark-background, var(--tint-80));
17
+ background-color: var(--mark-background, color-mix(in oklch, var(--mark-tint, var(--color-yellow)), transparent));
19
18
  color: var(--mark-color, var(--tint-00));
20
19
 
21
20
  /* Text */
@@ -1,5 +1,4 @@
1
1
  import type { ReactElement } from "react";
2
- import { TINT_CLASS } from "../style/Tint.js";
3
2
  import { getTypographyClass, type TypographyVariants } from "../style/Typography.js";
4
3
  import { getClass, getModuleClass } from "../util/css.js";
5
4
  import type { OptionalChildProps } from "../util/props.js";
@@ -25,7 +24,6 @@ export function Mark({ children, ...props }: MarkProps): ReactElement {
25
24
  <mark
26
25
  className={getClass(
27
26
  MARK_CLASS, //
28
- TINT_CLASS,
29
27
  getTypographyClass(props),
30
28
  )}
31
29
  >
@@ -5,7 +5,7 @@ import { splitMessage } from "../../util/error.js";
5
5
  import { formatUnit } from "../../util/format.js";
6
6
  import { Column } from "../block/Column.js";
7
7
  import { Row } from "../block/Row.js";
8
- import { Button } from "./Button.js";
8
+ import { Button } from "../button/Button.js";
9
9
  import { ButtonInput } from "./ButtonInput.js";
10
10
  import { SchemaInput } from "./SchemaInput.js";
11
11
  export function ArrayInput({ name,
@@ -6,7 +6,7 @@ import { splitMessage } from "../../util/error.js";
6
6
  import { formatUnit } from "../../util/format.js";
7
7
  import { Column } from "../block/Column.js";
8
8
  import { Row } from "../block/Row.js";
9
- import { Button } from "./Button.js";
9
+ import { Button } from "../button/Button.js";
10
10
  import { ButtonInput } from "./ButtonInput.js";
11
11
  import type { ValueInputProps } from "./Input.js";
12
12
  import { SchemaInput } from "./SchemaInput.js";
@@ -1,6 +1,6 @@
1
1
  import type { ReactElement } from "react";
2
+ import { type ClickableProps } from "../button/Clickable.js";
2
3
  import { type FlexVariants } from "../style/Flex.js";
3
- import { type ClickableProps } from "./Clickable.js";
4
4
  import { type InputProps, type InputVariants } from "./Input.js";
5
5
  /**
6
6
  * Props for `ButtonInput`, a clickable element styled to match form inputs.
@@ -1,8 +1,8 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { notNullish } from "../../util/null.js";
3
+ import { Clickable } from "../button/Clickable.js";
3
4
  import { getFlexClass } from "../style/Flex.js";
4
5
  import { getClass, getModuleClass } from "../util/css.js";
5
- import { Clickable } from "./Clickable.js";
6
6
  import { getInputClass } from "./Input.js";
7
7
  import INPUT_CSS from "./Input.module.css";
8
8
  /**
@@ -1,8 +1,8 @@
1
1
  import type { ReactElement } from "react";
2
2
  import { notNullish } from "../../util/null.js";
3
+ import { Clickable, type ClickableProps } from "../button/Clickable.js";
3
4
  import { type FlexVariants, getFlexClass } from "../style/Flex.js";
4
5
  import { getClass, getModuleClass } from "../util/css.js";
5
- import { Clickable, type ClickableProps } from "./Clickable.js";
6
6
  import { getInputClass, type InputProps, type InputVariants } from "./Input.js";
7
7
  import INPUT_CSS from "./Input.module.css";
8
8
 
@@ -1,7 +1,7 @@
1
1
  /** biome-ignore-all lint/a11y/noStaticElementInteractions: This is fine we're only using this to listen for clicks on child buttons. */
2
2
  /** biome-ignore-all lint/a11y/useKeyWithClickEvents: This is fine we're only using this to listen for clicks on child buttons. */
3
3
  import { type ReactElement } from "react";
4
- import { type ButtonVariants } from "./Button.js";
4
+ import { type ButtonVariants } from "../button/Button.js";
5
5
  import { type PopoverChildren } from "./Popover.js";
6
6
  /**
7
7
  * Props for `ButtonPopover`, a button that toggles an adjacent popover.
@@ -2,7 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  /** biome-ignore-all lint/a11y/noStaticElementInteractions: This is fine we're only using this to listen for clicks on child buttons. */
3
3
  /** biome-ignore-all lint/a11y/useKeyWithClickEvents: This is fine we're only using this to listen for clicks on child buttons. */
4
4
  import { useState } from "react";
5
- import { Button } from "./Button.js";
5
+ import { Button } from "../button/Button.js";
6
6
  import { Popover } from "./Popover.js";
7
7
  /**
8
8
  * A button that, when clicked, shows a popover next to it when clicked or focused.
@@ -2,7 +2,7 @@
2
2
  /** biome-ignore-all lint/a11y/useKeyWithClickEvents: This is fine we're only using this to listen for clicks on child buttons. */
3
3
 
4
4
  import { type ReactElement, useState } from "react";
5
- import { Button, type ButtonVariants } from "./Button.js";
5
+ import { Button, type ButtonVariants } from "../button/Button.js";
6
6
  import { Popover, type PopoverChildren } from "./Popover.js";
7
7
 
8
8
  /**
@@ -5,7 +5,7 @@ import { splitMessage } from "../../util/error.js";
5
5
  import { formatUnit } from "../../util/format.js";
6
6
  import { omitProp } from "../../util/object.js";
7
7
  import { Row } from "../block/Row.js";
8
- import { Button } from "./Button.js";
8
+ import { Button } from "../button/Button.js";
9
9
  import { ButtonInput } from "./ButtonInput.js";
10
10
  import { SchemaInput } from "./SchemaInput.js";
11
11
  import { TextInput } from "./TextInput.js";
@@ -7,7 +7,7 @@ import { splitMessage } from "../../util/error.js";
7
7
  import { formatUnit } from "../../util/format.js";
8
8
  import { omitProp } from "../../util/object.js";
9
9
  import { Row } from "../block/Row.js";
10
- import { Button } from "./Button.js";
10
+ import { Button } from "../button/Button.js";
11
11
  import { ButtonInput } from "./ButtonInput.js";
12
12
  import type { ValueInputProps } from "./Input.js";
13
13
  import { SchemaInput } from "./SchemaInput.js";
@@ -17,13 +17,13 @@ import { getNumber } from "../../util/number.js";
17
17
  import { getKeys } from "../../util/object.js";
18
18
  import { getSource, requireSource } from "../../util/source.js";
19
19
  import { getString } from "../../util/string.js";
20
+ import { Field } from "../form/Field.js";
20
21
  import { ArrayInput } from "./ArrayInput.js";
21
22
  import { CheckboxInput } from "./CheckboxInput.js";
22
23
  import { ChoiceRadioInputs } from "./ChoiceRadioInputs.js";
23
24
  import { DataInput } from "./DataInput.js";
24
25
  import { DateInput } from "./DateInput.js";
25
26
  import { DictionaryInput } from "./DictionaryInput.js";
26
- import { Field } from "./Field.js";
27
27
  import { NumberInput } from "./NumberInput.js";
28
28
  import { SelectInput } from "./SelectInput.js";
29
29
  import { TextInput } from "./TextInput.js";
@@ -1,8 +1,8 @@
1
1
  import { describe, expect, test } from "bun:test";
2
2
  import { renderToStaticMarkup } from "react-dom/server";
3
- import { StringSchema } from "../../schema/index.js";
4
- import { PASSTHROUGH } from "../../util/function.js";
5
- import { StringSchemaInput } from "./SchemaInput.js";
3
+ import { StringSchema } from "shelving/schema";
4
+ import { StringSchemaInput } from "shelving/ui";
5
+ import { PASSTHROUGH } from "shelving/util/function";
6
6
 
7
7
  describe("StringSchemaInput", () => {
8
8
  test("formats the initial value to its clean sanitized value", () => {
@@ -19,6 +19,7 @@ import { getKeys } from "../../util/object.js";
19
19
  import { getSource, requireSource } from "../../util/source.js";
20
20
  import { getString } from "../../util/string.js";
21
21
  import type { ValidatorType } from "../../util/validate.js";
22
+ import { Field } from "../form/Field.js";
22
23
  import type { OptionalChildProps } from "../util/props.js";
23
24
  import { ArrayInput } from "./ArrayInput.js";
24
25
  import { CheckboxInput } from "./CheckboxInput.js";
@@ -26,7 +27,6 @@ import { ChoiceRadioInputs } from "./ChoiceRadioInputs.js";
26
27
  import { DataInput } from "./DataInput.js";
27
28
  import { DateInput } from "./DateInput.js";
28
29
  import { DictionaryInput } from "./DictionaryInput.js";
29
- import { Field } from "./Field.js";
30
30
  import type { ValueInputProps } from "./Input.js";
31
31
  import { NumberInput } from "./NumberInput.js";
32
32
  import { SelectInput } from "./SelectInput.js";
@@ -1,6 +1,6 @@
1
1
  import type { ReactElement } from "react";
2
2
  import type { StringInputType } from "../../schema/StringSchema.js";
3
- import { type InputVariants, type ValueInputProps } from "./Input.js";
3
+ import { type InputVariants, type ValueInputProps } from "../input/Input.js";
4
4
  type TextFormatter = (str: string) => string;
5
5
  /**
6
6
  * Props for `TextInput`, a single- or multi-line text input bound to a `string` value.
@@ -1,7 +1,7 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { PASSTHROUGH } from "../../util/function.js";
3
+ import { getInputClass } from "../input/Input.js";
3
4
  import { getClass, getModuleClass } from "../util/css.js";
4
- import { getInputClass } from "./Input.js";
5
5
  import INPUT_CSS from "./Input.module.css";
6
6
  /**
7
7
  * Text input bound to a `string` value, rendered as an `<input>` or a `<textarea>` when `rows > 1`.
@@ -1,8 +1,8 @@
1
1
  import type { ReactElement, SyntheticEvent } from "react";
2
2
  import type { StringInputType } from "../../schema/StringSchema.js";
3
3
  import { PASSTHROUGH } from "../../util/function.js";
4
+ import { getInputClass, type InputVariants, type ValueInputProps } from "../input/Input.js";
4
5
  import { getClass, getModuleClass } from "../util/css.js";
5
- import { getInputClass, type InputVariants, type ValueInputProps } from "./Input.js";
6
6
  import INPUT_CSS from "./Input.module.css";
7
7
 
8
8
  type TextFormatter = (str: string) => string;
@@ -0,0 +1,20 @@
1
+ export * from "./ArrayInput.js";
2
+ export * from "./ArrayRadioInputs.js";
3
+ export * from "./ButtonInput.js";
4
+ export * from "./ButtonInputPopover.js";
5
+ export * from "./ButtonPopover.js";
6
+ export * from "./CheckboxInput.js";
7
+ export * from "./ChoiceRadioInputs.js";
8
+ export * from "./DataInput.js";
9
+ export * from "./DateInput.js";
10
+ export * from "./DictionaryInput.js";
11
+ export * from "./FileInput.js";
12
+ export * from "./Input.js";
13
+ export * from "./NumberInput.js";
14
+ export * from "./OutputInput.js";
15
+ export * from "./Popover.js";
16
+ export * from "./QueryInput.js";
17
+ export * from "./RadioInput.js";
18
+ export * from "./SchemaInput.js";
19
+ export * from "./SelectInput.js";
20
+ export * from "./TextInput.js";
@@ -0,0 +1,20 @@
1
+ export * from "./ArrayInput.js";
2
+ export * from "./ArrayRadioInputs.js";
3
+ export * from "./ButtonInput.js";
4
+ export * from "./ButtonInputPopover.js";
5
+ export * from "./ButtonPopover.js";
6
+ export * from "./CheckboxInput.js";
7
+ export * from "./ChoiceRadioInputs.js";
8
+ export * from "./DataInput.js";
9
+ export * from "./DateInput.js";
10
+ export * from "./DictionaryInput.js";
11
+ export * from "./FileInput.js";
12
+ export * from "./Input.js";
13
+ export * from "./NumberInput.js";
14
+ export * from "./OutputInput.js";
15
+ export * from "./Popover.js";
16
+ export * from "./QueryInput.js";
17
+ export * from "./RadioInput.js";
18
+ export * from "./SchemaInput.js";
19
+ export * from "./SelectInput.js";
20
+ export * from "./TextInput.js";
@@ -0,0 +1,20 @@
1
+ export * from "./ArrayInput.js";
2
+ export * from "./ArrayRadioInputs.js";
3
+ export * from "./ButtonInput.js";
4
+ export * from "./ButtonInputPopover.js";
5
+ export * from "./ButtonPopover.js";
6
+ export * from "./CheckboxInput.js";
7
+ export * from "./ChoiceRadioInputs.js";
8
+ export * from "./DataInput.js";
9
+ export * from "./DateInput.js";
10
+ export * from "./DictionaryInput.js";
11
+ export * from "./FileInput.js";
12
+ export * from "./Input.js";
13
+ export * from "./NumberInput.js";
14
+ export * from "./OutputInput.js";
15
+ export * from "./Popover.js";
16
+ export * from "./QueryInput.js";
17
+ export * from "./RadioInput.js";
18
+ export * from "./SchemaInput.js";
19
+ export * from "./SelectInput.js";
20
+ export * from "./TextInput.js";
@@ -1,16 +1,14 @@
1
1
  import type { ReactElement } from "react";
2
+ import type { IndentVariants } from "../style/Indent.js";
3
+ import type { PaddingVariants } from "../style/Padding.js";
4
+ import type { WidthVariants } from "../style/Width.js";
2
5
  import type { OptionalChildProps } from "../util/props.js";
3
6
  /**
4
7
  * Props for `<CenteredLayout>` — optional `children` and a `fullWidth` flag to drop the max-width.
5
8
  *
6
9
  * @see https://shelving.cc/ui/CenteredLayoutProps
7
10
  */
8
- export interface CenteredLayoutProps extends OptionalChildProps {
9
- /**
10
- * Drop the narrow max-width and let content fill the width.
11
- * @default false
12
- */
13
- fullWidth?: boolean;
11
+ export interface CenteredLayoutProps extends WidthVariants, PaddingVariants, IndentVariants, OptionalChildProps {
14
12
  }
15
13
  /**
16
14
  * Layout that centres its content with no header/footer and a narrow max-width.
@@ -19,4 +17,4 @@ export interface CenteredLayoutProps extends OptionalChildProps {
19
17
  * @kind component
20
18
  * @see https://shelving.cc/ui/CenteredLayout
21
19
  */
22
- export declare function CenteredLayout({ children, fullWidth }: CenteredLayoutProps): ReactElement;
20
+ export declare function CenteredLayout({ children, ...props }: CenteredLayoutProps): ReactElement;
@@ -1,7 +1,10 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { RouteCache } from "../router/RouteCache.js";
3
- import { getModuleClass } from "../util/css.js";
4
- import CENTERED_LAYOUT_CSS from "./CenteredLayout.module.css";
3
+ import { getBlockClass } from "../style/Block.js";
4
+ import { getClass, getModuleClass } from "../util/css.js";
5
+ import LAYOUT_CSS from "./CenteredLayout.module.css";
6
+ const LAYOUT_MAIN_CLASS = getModuleClass(LAYOUT_CSS, "main");
7
+ const LAYOUT_INNER_CLASS = getModuleClass(LAYOUT_CSS, "inner");
5
8
  /**
6
9
  * Layout that centres its content with no header/footer and a narrow max-width.
7
10
  * - Used for e.g. login/register/error/form pages where the content is the only focus.
@@ -9,8 +12,9 @@ import CENTERED_LAYOUT_CSS from "./CenteredLayout.module.css";
9
12
  * @kind component
10
13
  * @see https://shelving.cc/ui/CenteredLayout
11
14
  */
12
- export function CenteredLayout({ children, fullWidth = false }) {
15
+ export function CenteredLayout({ children, ...props }) {
13
16
  // Wrap the scrolling `<main>` in `<RouteCache>` so recently-visited pages stay mounted but hidden,
14
17
  // keeping their scroll position and state intact across back/forward navigation.
15
- return (_jsx(RouteCache, { children: _jsx("main", { className: getModuleClass(CENTERED_LAYOUT_CSS, "main"), children: _jsx("div", { className: getModuleClass(CENTERED_LAYOUT_CSS, "mainInner"), style: fullWidth ? { maxWidth: "none" } : undefined, children: children }) }) }));
18
+ return (_jsx(RouteCache, { children: _jsx("main", { className: LAYOUT_MAIN_CLASS, children: _jsx("div", { className: getClass(LAYOUT_INNER_CLASS, //
19
+ getBlockClass(props)), children: children }) }) }));
16
20
  }
@@ -27,6 +27,13 @@ Layouts compose naturally as `<Router>` route values — wrap a group of routes
27
27
 
28
28
  ## Styling
29
29
 
30
- This layout exposes no own `--centered-layout-*` hooks. The inner column is capped at the global `--width-narrow` token (dropped when `fullWidth` is set), and the outer element owns its scroll, padding, and safe-area behaviour directly — reading the layout hooks `--layout-space`, `--layout-padding`, `--layout-body-bg`, and `--layout-inset-top` / `-bottom` / `-left` / `-right`.
30
+ | Variable | Styles | Default |
31
+ |---|---|---|
32
+ | `--centered-layout-width` | Max width of the centred column | `var(--width-narrow)` |
33
+ | `--centered-layout-space` | Top/bottom padding of the scroll area | `var(--space-normal)` |
34
+ | `--centered-layout-padding` | Left/right padding of the scroll area | `var(--space-normal)` |
35
+ | `--centered-layout-background` | Page background while the layout is mounted | Unset — the `body` default from `Typography.module.css` shows |
31
36
 
32
- **Global tokens it reads** `--width-narrow`.
37
+ The max-width cap is dropped entirely when `fullWidth` is set. The outer element owns its scroll, padding, and safe-area behaviour directly — it also reads the `--layout-inset-top` / `-bottom` / `-left` / `-right` hooks owned by `Layout.ts` (`useSafeKeyboardArea()` writes `--layout-inset-bottom`).
38
+
39
+ **Global tokens it reads** — `--width-narrow` and `--space-normal`.
@@ -1,24 +1,7 @@
1
1
  @import "../style/layers.css";
2
2
  @import "../style/Space.module.css";
3
- @import "../style/Tint.module.css";
4
3
  @import "../style/Width.module.css";
5
4
 
6
- /* Low-priority padding defaults live in `@layer defaults` so consumers can override them */
7
- /* with normal-specificity selectors without needing `:where()` tricks. */
8
- @layer defaults {
9
- .main {
10
- /* Top/bottom use `layout-space` and left/right use `layout-padding`, plus safe-area additions. */
11
- padding: var(--layout-space, var(--space-normal)) var(--layout-padding, var(--space-normal));
12
- padding-top: calc(var(--layout-space, var(--space-normal)) + max(var(--layout-inset-top, 0px), env(safe-area-inset-top, 0px)));
13
- padding-bottom: calc(var(--layout-space, var(--space-normal)) + max(var(--layout-inset-bottom, 0px), env(safe-area-inset-bottom, 0px)));
14
- padding-left: calc(var(--layout-padding, var(--space-normal)) + max(var(--layout-inset-left, 0px), env(safe-area-inset-left, 0px)));
15
- padding-right: calc(var(--layout-padding, var(--space-normal)) + max(var(--layout-inset-right, 0px), env(safe-area-inset-right, 0px)));
16
-
17
- /* Grow to fill the body. */
18
- flex: 1;
19
- }
20
- }
21
-
22
5
  @layer components {
23
6
  /*
24
7
  * Lock the document and let `.main` own the page scroll.
@@ -51,11 +34,22 @@
51
34
  position: fixed;
52
35
  inset: 0;
53
36
 
54
- /* Layout-specific bg hook. */
55
- background: var(--layout-body-bg, var(--tint-100));
37
+ /* Deliberately no fallback: when the hook is unset this declaration fails and the body default from Typography.module.css shows. */
38
+ background: var(--centered-layout-background);
56
39
  }
57
40
 
58
41
  .main {
42
+ /* Box */
43
+ border-top: env(safe-area-inset-top, 0px) solid transparent;
44
+ border-bottom: env(safe-area-inset-bottom, 0px) solid transparent;
45
+ border-left: env(safe-area-inset-left, 0px) solid transparent;
46
+ border-right: env(safe-area-inset-right, 0px) solid transparent;
47
+ padding-block: var(--centered-layout-padding, var(--space-normal));
48
+ padding-inline: var(--centered-layout-indent, var(--space-normal));
49
+
50
+ /* Grow to fill the body. */
51
+ flex: 1;
52
+
59
53
  /* Content — a flex column whose inner column centres itself with `margin: auto` (both axes). */
60
54
  display: flex;
61
55
  flex-direction: column;
@@ -70,9 +64,9 @@
70
64
  scroll-behavior: smooth;
71
65
  }
72
66
 
73
- .mainInner {
74
- width: 100%;
75
- max-width: var(--width-narrow);
67
+ .inner {
68
+ width: var(--centered-layout-width, var(--width-narrow));
69
+ max-width: 100%;
76
70
  margin: auto;
77
71
  }
78
72
  }
@@ -1,21 +1,22 @@
1
1
  import type { ReactElement } from "react";
2
2
  import { RouteCache } from "../router/RouteCache.js";
3
- import { getModuleClass } from "../util/css.js";
3
+ import { getBlockClass } from "../style/Block.js";
4
+ import type { IndentVariants } from "../style/Indent.js";
5
+ import type { PaddingVariants } from "../style/Padding.js";
6
+ import type { WidthVariants } from "../style/Width.js";
7
+ import { getClass, getModuleClass } from "../util/css.js";
4
8
  import type { OptionalChildProps } from "../util/props.js";
5
- import CENTERED_LAYOUT_CSS from "./CenteredLayout.module.css";
9
+ import LAYOUT_CSS from "./CenteredLayout.module.css";
10
+
11
+ const LAYOUT_MAIN_CLASS = getModuleClass(LAYOUT_CSS, "main");
12
+ const LAYOUT_INNER_CLASS = getModuleClass(LAYOUT_CSS, "inner");
6
13
 
7
14
  /**
8
15
  * Props for `<CenteredLayout>` — optional `children` and a `fullWidth` flag to drop the max-width.
9
16
  *
10
17
  * @see https://shelving.cc/ui/CenteredLayoutProps
11
18
  */
12
- export interface CenteredLayoutProps extends OptionalChildProps {
13
- /**
14
- * Drop the narrow max-width and let content fill the width.
15
- * @default false
16
- */
17
- fullWidth?: boolean;
18
- }
19
+ export interface CenteredLayoutProps extends WidthVariants, PaddingVariants, IndentVariants, OptionalChildProps {}
19
20
 
20
21
  /**
21
22
  * Layout that centres its content with no header/footer and a narrow max-width.
@@ -24,13 +25,18 @@ export interface CenteredLayoutProps extends OptionalChildProps {
24
25
  * @kind component
25
26
  * @see https://shelving.cc/ui/CenteredLayout
26
27
  */
27
- export function CenteredLayout({ children, fullWidth = false }: CenteredLayoutProps): ReactElement {
28
+ export function CenteredLayout({ children, ...props }: CenteredLayoutProps): ReactElement {
28
29
  // Wrap the scrolling `<main>` in `<RouteCache>` so recently-visited pages stay mounted but hidden,
29
30
  // keeping their scroll position and state intact across back/forward navigation.
30
31
  return (
31
32
  <RouteCache>
32
- <main className={getModuleClass(CENTERED_LAYOUT_CSS, "main")}>
33
- <div className={getModuleClass(CENTERED_LAYOUT_CSS, "mainInner")} style={fullWidth ? { maxWidth: "none" } : undefined}>
33
+ <main className={LAYOUT_MAIN_CLASS}>
34
+ <div
35
+ className={getClass(
36
+ LAYOUT_INNER_CLASS, //
37
+ getBlockClass(props),
38
+ )}
39
+ >
34
40
  {children}
35
41
  </div>
36
42
  </main>
@@ -7,4 +7,4 @@
7
7
  * @todo This can be removed once Safari iOS supports interactive-widget viewport property. https://caniuse.com/mdn-html_elements_meta_name_viewport_interactive-widget
8
8
  * @see https://shelving.cc/ui/useSafeKeyboardArea
9
9
  */
10
- export declare function useSafeKeyboardArea(): (() => void) | undefined;
10
+ export declare function useSafeKeyboardArea(): void;