@domphy/ui 0.21.4 → 0.21.6

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/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { ValueOrState, PartialElement, DomphyElement, State, Listener } from '@domphy/core';
2
- import { ThemeColor } from '@domphy/theme';
2
+ import { ThemeColor, ElementSize } from '@domphy/theme';
3
3
  import { Placement as Placement$1 } from '@domphy/floating';
4
4
  export { Placement } from '@domphy/floating';
5
5
 
@@ -213,7 +213,8 @@ declare function code(props?: {
213
213
  * @param props.placement - Floating popover placement. Optional `ValueOrState<Placement>`, default "bottom".
214
214
  * @param props.content - The floating popover content element. Required `DomphyElement`.
215
215
  * @param props.color - Color tone for the control. Optional `ThemeColor`, default "neutral".
216
- * @param props.open - Whether the popover is open. Optional `ValueOrState<boolean>`, default false.
216
+ * @param props.open - Whether the popover is open. Optional `ValueOrState<boolean>` (including `Computed`/`ReadableState`), default false. When the source is read-only, pass `onDismiss` so dismiss can close.
217
+ * @param props.onDismiss - Called when the popover requests close. Optional. Required to close when `open` is a read-only `Computed`/`ReadableState`.
217
218
  * @param props.input - Custom input element; when omitted a default `<input>` is created. Optional `DomphyElement`.
218
219
  * @example { div: null, $: [combobox({ options: [{ label: "A", value: "a" }], content: { div: null } })] }
219
220
  */
@@ -228,6 +229,7 @@ declare function combobox(props: {
228
229
  content: DomphyElement;
229
230
  color?: ThemeColor;
230
231
  open?: ValueOrState<boolean>;
232
+ onDismiss?: () => void;
231
233
  input?: DomphyElement;
232
234
  }): PartialElement;
233
235
 
@@ -368,7 +370,8 @@ declare function details(props?: {
368
370
  *
369
371
  * @hostTag dialog
370
372
  * @param props.color - Theme color tone for the dialog surface. Defaults to "neutral".
371
- * @param props.open - Open state (`ValueOrState<boolean>`); set it to true/false to show/hide. Defaults to false.
373
+ * @param props.open - Open state (`ValueOrState<boolean>`), including `Computed`/`ReadableState`. When the source is read-only, pass `onDismiss` so Escape/backdrop can close. Defaults to false.
374
+ * @param props.onDismiss - Called when Escape/backdrop/`requestClose` request close. Optional. Required to close when `open` is a read-only `Computed`/`ReadableState`.
372
375
  * @param props.labelledBy - `id` of the element labeling the dialog (wired to `aria-labelledby`). Optional.
373
376
  * @param props.describedBy - `id` of the element describing the dialog (wired to `aria-describedby`). Optional.
374
377
  * @example { dialog: [{ h2: "Confirm", id: "dlg-title" }], $: [dialog({ open, labelledBy: "dlg-title" })] }
@@ -376,6 +379,7 @@ declare function details(props?: {
376
379
  declare function dialog(props?: {
377
380
  color?: ThemeColor;
378
381
  open?: ValueOrState<boolean>;
382
+ onDismiss?: () => void;
379
383
  labelledBy?: string;
380
384
  describedBy?: string;
381
385
  }): PartialElement;
@@ -412,7 +416,8 @@ type Placement = PhysicalPlacement | "start" | "end";
412
416
  *
413
417
  * @hostTag dialog
414
418
  * @param props.color - Theme color tone for the drawer surface. Defaults to "neutral".
415
- * @param props.open - Open state (`ValueOrState<boolean>`); set true/false to show/hide. Defaults to false.
419
+ * @param props.open - Open state (`ValueOrState<boolean>`), including `Computed`/`ReadableState`. When the source is read-only, pass `onDismiss` so Escape/backdrop can close. Defaults to false.
420
+ * @param props.onDismiss - Called when Escape/backdrop/`requestClose` request close. Optional. Required to close when `open` is a read-only `Computed`/`ReadableState`.
416
421
  * @param props.placement - Edge to anchor to. "left" | "right" | "top" | "bottom" | "start" | "end". Defaults to "end".
417
422
  * @param props.size - CSS length for the drawer's width (left/right/start/end) or height (top/bottom). Defaults to themeSpacing(80) for left/right, themeSpacing(64) for top/bottom.
418
423
  * @example { dialog: [...], $: [drawer({ open, placement: "start" })] }
@@ -420,6 +425,7 @@ type Placement = PhysicalPlacement | "start" | "end";
420
425
  declare function drawer(props?: {
421
426
  color?: ThemeColor;
422
427
  open?: ValueOrState<boolean>;
428
+ onDismiss?: () => void;
423
429
  placement?: Placement;
424
430
  size?: string;
425
431
  }): PartialElement;
@@ -517,20 +523,32 @@ declare function formGroup(props?: {
517
523
  }): PartialElement;
518
524
 
519
525
  type FlexAlign = "flex-start" | "center" | "flex-end" | "stretch" | "baseline";
526
+ type FlexJustify = "flex-start" | "center" | "flex-end" | "space-between" | "space-around" | "space-evenly";
520
527
  /**
521
528
  * A vertical flex column with spacing between children. The general-purpose
522
529
  * primitive for stacking blocks — form sections, panel content, card bodies —
523
530
  * instead of hand-rolling `display: flex; flexDirection: column; gap: ...`.
524
531
  * Styles the host only; apply to any block element.
525
532
  *
526
- * @param props.gap - Spacing multiplier for gap between children (default 3 = 0.75em at density 1).
533
+ * @param props.gap - Spacing multiplier for gap between children (default 3).
534
+ * Bounded-control mode (`density: true`, default): `themeSpacing(themeDensity(l) * gap)`
535
+ * — at default density 1.5, gap 3 = 1.125em.
536
+ * Structural/page-column mode (`density: false`): bare `themeSpacing(gap)` with no
537
+ * density multiply — gap 3 = 0.75em, matching AGENTS.md "bare themeSpacing(n)".
527
538
  * @param props.align - Cross-axis alignment (`alignItems`). Unset by default (flex default, stretch).
539
+ * @param props.justify - Main-axis distribution (`justifyContent`). Unset by default (flex-start).
540
+ * @param props.density - When true (default), gap is multiplied by theme density
541
+ * (bounded controls). When false, gap is structural `themeSpacing(n)` — use this
542
+ * for page/form columns.
528
543
  * @example { div: [{ h3: "Title" }, { p: "Body" }], $: [stack()] }
529
544
  * @example { div: [...], $: [stack({ gap: 2, align: "center" })] }
545
+ * @example { div: [...], $: [stack({ gap: 3, density: false, justify: "space-between" })] }
530
546
  */
531
547
  declare function stack(props?: {
532
548
  gap?: number;
533
549
  align?: FlexAlign;
550
+ justify?: FlexJustify;
551
+ density?: boolean;
534
552
  }): PartialElement;
535
553
 
536
554
  /**
@@ -559,10 +577,13 @@ declare function grid(props?: {
559
577
  *
560
578
  * @hostTag h1
561
579
  * @param props.color - Theme color tone (`ValueOrState<ThemeColor>`) for the heading text. Defaults to "neutral".
580
+ * @param props.size - Optional `ElementSize` (`"inherit"` | `"increase-N"` | `"decrease-N"`, N ≤ 7). When set, font size is `themeSize(listener, size)` including `"inherit"` (no tag bump). When omitted, follows the host tag (`h1` increase-4 … `h6` decrease-1).
562
581
  * @example { h2: "Section title", $: [heading()] }
582
+ * @example { h3: "Panel title", $: [heading({ size: "inherit" })] }
563
583
  */
564
584
  declare function heading(props?: {
565
585
  color?: ValueOrState<ThemeColor>;
586
+ size?: ElementSize;
566
587
  }): PartialElement;
567
588
 
568
589
  /**
@@ -1051,7 +1072,8 @@ declare function paragraph(props?: {
1051
1072
  *
1052
1073
  * @param props - Configuration.
1053
1074
  * @param props.openOn - Interaction that opens the popover: `"click"` or `"hover"`. Defaults to `"click"`.
1054
- * @param props.open - Open state, accepts a value or `State`. Defaults to `false`.
1075
+ * @param props.open - Open state (`ValueOrState<boolean>`), including `Computed`/`ReadableState`. When the source is read-only, pass `onDismiss` so Escape/outside click can close. Defaults to `false`.
1076
+ * @param props.onDismiss - Called when the panel requests close. Optional. Required to close when `open` is a read-only `Computed`/`ReadableState`.
1055
1077
  * @param props.placement - Floating placement (e.g. `"bottom"`, `"top-start"`), value or `State`. Defaults to `"bottom"`.
1056
1078
  * @param props.content - The floating content element to display.
1057
1079
  * @example { button: "Open", $: [popover({ openOn: "click", content: { div: "Hi" } })] }
@@ -1059,6 +1081,7 @@ declare function paragraph(props?: {
1059
1081
  declare function popover(props: {
1060
1082
  openOn?: "click" | "hover";
1061
1083
  open?: ValueOrState<boolean>;
1084
+ onDismiss?: () => void;
1062
1085
  placement?: ValueOrState<Placement$1>;
1063
1086
  content: DomphyElement;
1064
1087
  }): PartialElement;
@@ -1164,7 +1187,6 @@ declare function ringProgress(props?: {
1164
1187
  thickness?: number;
1165
1188
  }): PartialElement;
1166
1189
 
1167
- type FlexJustify = "flex-start" | "center" | "flex-end" | "space-between" | "space-around" | "space-evenly";
1168
1190
  /**
1169
1191
  * A horizontal flex row with spacing between children, vertically centered by
1170
1192
  * default. The general-purpose primitive for icon+label rows, field rows,
@@ -1172,18 +1194,27 @@ type FlexJustify = "flex-start" | "center" | "flex-end" | "space-between" | "spa
1172
1194
  * center; gap: ...`. `toolbar()` is a semantic alias of this same shape for
1173
1195
  * headers/nav bars. Styles the host only; apply to any block element.
1174
1196
  *
1175
- * @param props.gap - Spacing multiplier for gap between items (default 4 = 1em at density 1).
1197
+ * @param props.gap - Spacing multiplier for gap between items (default 4).
1198
+ * Bounded-control mode (`density: true`, default): `themeSpacing(themeDensity(l) * gap)`
1199
+ * — at default density 1.5, gap 4 = 1.5em.
1200
+ * Structural/page-column mode (`density: false`): bare `themeSpacing(gap)` with no
1201
+ * density multiply — gap 4 = 1em, matching AGENTS.md "bare themeSpacing(n)".
1176
1202
  * @param props.align - Cross-axis alignment (`alignItems`). Defaults to `"center"`.
1177
1203
  * @param props.justify - Main-axis distribution (`justifyContent`). Unset by default (flex-start).
1178
1204
  * @param props.wrap - Allow items to wrap onto multiple lines. Defaults to `false`.
1205
+ * @param props.density - When true (default), gap is multiplied by theme density
1206
+ * (bounded controls). When false, gap is structural `themeSpacing(n)` — use this
1207
+ * for page/form columns.
1179
1208
  * @example { div: [{ span: "Icon" }, { span: "Label" }], $: [row()] }
1180
1209
  * @example { div: [...], $: [row({ justify: "space-between", wrap: true })] }
1210
+ * @example { div: [...], $: [row({ gap: 4, density: false })] }
1181
1211
  */
1182
1212
  declare function row(props?: {
1183
1213
  gap?: number;
1184
1214
  align?: FlexAlign;
1185
1215
  justify?: FlexJustify;
1186
1216
  wrap?: boolean;
1217
+ density?: boolean;
1187
1218
  }): PartialElement;
1188
1219
 
1189
1220
  /**
@@ -1263,7 +1294,8 @@ declare function select(props?: {
1263
1294
  * reactive state. Defaults to `"bottom"`.
1264
1295
  * @param props.content - Required. The popover/dropdown content element shown when open.
1265
1296
  * @param props.color - Theme color tone for the box text/background. Defaults to `"neutral"`.
1266
- * @param props.open - Whether the popover is open. Accepts a value or reactive state. Defaults to `false`.
1297
+ * @param props.open - Whether the popover is open. Accepts a value or reactive state (`ValueOrState<boolean>`, including `Computed`/`ReadableState`). Defaults to `false`. When the source is read-only, pass `onDismiss` so dismiss can close.
1298
+ * @param props.onDismiss - Called when the popover requests close. Optional. Required to close when `open` is a read-only `Computed`/`ReadableState`.
1267
1299
  * @example { div: null, $: [selectBox({ content: { div: [...] }, options: [{ label: "A", value: "a" }] })] }
1268
1300
  */
1269
1301
  declare function selectBox(props: {
@@ -1277,6 +1309,7 @@ declare function selectBox(props: {
1277
1309
  content: DomphyElement;
1278
1310
  color?: ThemeColor;
1279
1311
  open?: ValueOrState<boolean>;
1312
+ onDismiss?: () => void;
1280
1313
  }): PartialElement;
1281
1314
 
1282
1315
  /**
@@ -1523,7 +1556,7 @@ declare function tag(props?: {
1523
1556
  * @hostTag textarea
1524
1557
  * @param props.color - Theme color for the border and text. Optional, accepts a value or state. Defaults to `"neutral"`.
1525
1558
  * @param props.accentColor - Theme color for hover/focus outline. Optional, accepts a value or state. Defaults to `"primary"`.
1526
- * @param props.autoResize - When true, grows the textarea height to fit its content on input and when `value` updates. Optional. Defaults to `false`.
1559
+ * @param props.autoResize - When true, grows the textarea height to fit its content on input and when `value` updates, and remeasures when the host becomes visible (IntersectionObserver) and when its box size changes (ResizeObserver). Optional. Defaults to `false`.
1527
1560
  * @example { textarea: null, $: [textarea({ autoResize: true })] }
1528
1561
  */
1529
1562
  declare function textarea(props?: {
@@ -1603,16 +1636,28 @@ declare function toggleGroup(props?: {
1603
1636
 
1604
1637
  /**
1605
1638
  * A horizontal flex row with vertically centered items. Useful for headers,
1606
- * toolbars, navigation bars, and action strips. A semantic alias of `row()`
1607
- * at its default alignment — reach for `row()` directly for `justify`/`wrap`/
1608
- * `align` beyond this shape.
1639
+ * toolbars, navigation bars, and action strips. A semantic alias of `row()`;
1640
+ * wrap/justify/align/density are forwarded so callers do not drop down to
1641
+ * hand-rolled flex.
1609
1642
  *
1610
- * @param props.gap - Spacing multiplier for gap between items (default 4 = 1em).
1643
+ * @param props.gap - Spacing multiplier for gap between items (default 4).
1644
+ * Bounded-control mode (`density: true`, default): `themeSpacing(themeDensity(l) * gap)`.
1645
+ * Structural mode (`density: false`): bare `themeSpacing(gap)`.
1646
+ * @param props.wrap - Allow items to wrap onto multiple lines. Defaults to `false`.
1647
+ * @param props.justify - Main-axis distribution (`justifyContent`). Unset by default.
1648
+ * @param props.align - Cross-axis alignment (`alignItems`). Defaults to `"center"` (row default).
1649
+ * @param props.density - When true (default), gap is multiplied by theme density.
1650
+ * When false, gap is structural `themeSpacing(n)`.
1611
1651
  * @example { header: [...], $: [toolbar()] }
1612
1652
  * @example { nav: [...], $: [toolbar({ gap: 3 })] }
1653
+ * @example { header: [...], $: [toolbar({ wrap: true, justify: "space-between" })] }
1613
1654
  */
1614
1655
  declare function toolbar(props?: {
1615
1656
  gap?: number;
1657
+ wrap?: boolean;
1658
+ justify?: FlexJustify;
1659
+ align?: FlexAlign;
1660
+ density?: boolean;
1616
1661
  }): PartialElement;
1617
1662
  /**
1618
1663
  * A flex spacer that expands to fill available space in a toolbar, pushing
@@ -1628,13 +1673,15 @@ declare function toolbarSpacer(): DomphyElement;
1628
1673
  * surface is positioned via the floating utility and linked with
1629
1674
  * `aria-describedby`. No host tag check; applied to the trigger element.
1630
1675
  *
1631
- * @param props.open - Controlled open state. Optional, accepts a value or state. Defaults to `false`.
1676
+ * @param props.open - Controlled open state (`ValueOrState<boolean>`), including `Computed`/`ReadableState`. When the source is read-only, pass `onDismiss` so leave/blur/Escape can close. Optional. Defaults to `false`.
1677
+ * @param props.onDismiss - Called when the tooltip requests close. Optional. Required to close when `open` is a read-only `Computed`/`ReadableState`.
1632
1678
  * @param props.placement - Floating placement relative to the trigger. Optional, accepts a value or state (`Placement`). Defaults to `"top"`.
1633
1679
  * @param props.content - Tooltip text content. Optional, accepts a value or state (string only). Defaults to `"Tooltip Content"`.
1634
1680
  * @example { button: "Hover me", $: [tooltip({ content: "Help text" })] }
1635
1681
  */
1636
1682
  declare function tooltip(props?: {
1637
1683
  open?: ValueOrState<boolean>;
1684
+ onDismiss?: () => void;
1638
1685
  placement?: ValueOrState<Placement$1>;
1639
1686
  content?: ValueOrState<string>;
1640
1687
  }): PartialElement;
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { ValueOrState, PartialElement, DomphyElement, State, Listener } from '@domphy/core';
2
- import { ThemeColor } from '@domphy/theme';
2
+ import { ThemeColor, ElementSize } from '@domphy/theme';
3
3
  import { Placement as Placement$1 } from '@domphy/floating';
4
4
  export { Placement } from '@domphy/floating';
5
5
 
@@ -213,7 +213,8 @@ declare function code(props?: {
213
213
  * @param props.placement - Floating popover placement. Optional `ValueOrState<Placement>`, default "bottom".
214
214
  * @param props.content - The floating popover content element. Required `DomphyElement`.
215
215
  * @param props.color - Color tone for the control. Optional `ThemeColor`, default "neutral".
216
- * @param props.open - Whether the popover is open. Optional `ValueOrState<boolean>`, default false.
216
+ * @param props.open - Whether the popover is open. Optional `ValueOrState<boolean>` (including `Computed`/`ReadableState`), default false. When the source is read-only, pass `onDismiss` so dismiss can close.
217
+ * @param props.onDismiss - Called when the popover requests close. Optional. Required to close when `open` is a read-only `Computed`/`ReadableState`.
217
218
  * @param props.input - Custom input element; when omitted a default `<input>` is created. Optional `DomphyElement`.
218
219
  * @example { div: null, $: [combobox({ options: [{ label: "A", value: "a" }], content: { div: null } })] }
219
220
  */
@@ -228,6 +229,7 @@ declare function combobox(props: {
228
229
  content: DomphyElement;
229
230
  color?: ThemeColor;
230
231
  open?: ValueOrState<boolean>;
232
+ onDismiss?: () => void;
231
233
  input?: DomphyElement;
232
234
  }): PartialElement;
233
235
 
@@ -368,7 +370,8 @@ declare function details(props?: {
368
370
  *
369
371
  * @hostTag dialog
370
372
  * @param props.color - Theme color tone for the dialog surface. Defaults to "neutral".
371
- * @param props.open - Open state (`ValueOrState<boolean>`); set it to true/false to show/hide. Defaults to false.
373
+ * @param props.open - Open state (`ValueOrState<boolean>`), including `Computed`/`ReadableState`. When the source is read-only, pass `onDismiss` so Escape/backdrop can close. Defaults to false.
374
+ * @param props.onDismiss - Called when Escape/backdrop/`requestClose` request close. Optional. Required to close when `open` is a read-only `Computed`/`ReadableState`.
372
375
  * @param props.labelledBy - `id` of the element labeling the dialog (wired to `aria-labelledby`). Optional.
373
376
  * @param props.describedBy - `id` of the element describing the dialog (wired to `aria-describedby`). Optional.
374
377
  * @example { dialog: [{ h2: "Confirm", id: "dlg-title" }], $: [dialog({ open, labelledBy: "dlg-title" })] }
@@ -376,6 +379,7 @@ declare function details(props?: {
376
379
  declare function dialog(props?: {
377
380
  color?: ThemeColor;
378
381
  open?: ValueOrState<boolean>;
382
+ onDismiss?: () => void;
379
383
  labelledBy?: string;
380
384
  describedBy?: string;
381
385
  }): PartialElement;
@@ -412,7 +416,8 @@ type Placement = PhysicalPlacement | "start" | "end";
412
416
  *
413
417
  * @hostTag dialog
414
418
  * @param props.color - Theme color tone for the drawer surface. Defaults to "neutral".
415
- * @param props.open - Open state (`ValueOrState<boolean>`); set true/false to show/hide. Defaults to false.
419
+ * @param props.open - Open state (`ValueOrState<boolean>`), including `Computed`/`ReadableState`. When the source is read-only, pass `onDismiss` so Escape/backdrop can close. Defaults to false.
420
+ * @param props.onDismiss - Called when Escape/backdrop/`requestClose` request close. Optional. Required to close when `open` is a read-only `Computed`/`ReadableState`.
416
421
  * @param props.placement - Edge to anchor to. "left" | "right" | "top" | "bottom" | "start" | "end". Defaults to "end".
417
422
  * @param props.size - CSS length for the drawer's width (left/right/start/end) or height (top/bottom). Defaults to themeSpacing(80) for left/right, themeSpacing(64) for top/bottom.
418
423
  * @example { dialog: [...], $: [drawer({ open, placement: "start" })] }
@@ -420,6 +425,7 @@ type Placement = PhysicalPlacement | "start" | "end";
420
425
  declare function drawer(props?: {
421
426
  color?: ThemeColor;
422
427
  open?: ValueOrState<boolean>;
428
+ onDismiss?: () => void;
423
429
  placement?: Placement;
424
430
  size?: string;
425
431
  }): PartialElement;
@@ -517,20 +523,32 @@ declare function formGroup(props?: {
517
523
  }): PartialElement;
518
524
 
519
525
  type FlexAlign = "flex-start" | "center" | "flex-end" | "stretch" | "baseline";
526
+ type FlexJustify = "flex-start" | "center" | "flex-end" | "space-between" | "space-around" | "space-evenly";
520
527
  /**
521
528
  * A vertical flex column with spacing between children. The general-purpose
522
529
  * primitive for stacking blocks — form sections, panel content, card bodies —
523
530
  * instead of hand-rolling `display: flex; flexDirection: column; gap: ...`.
524
531
  * Styles the host only; apply to any block element.
525
532
  *
526
- * @param props.gap - Spacing multiplier for gap between children (default 3 = 0.75em at density 1).
533
+ * @param props.gap - Spacing multiplier for gap between children (default 3).
534
+ * Bounded-control mode (`density: true`, default): `themeSpacing(themeDensity(l) * gap)`
535
+ * — at default density 1.5, gap 3 = 1.125em.
536
+ * Structural/page-column mode (`density: false`): bare `themeSpacing(gap)` with no
537
+ * density multiply — gap 3 = 0.75em, matching AGENTS.md "bare themeSpacing(n)".
527
538
  * @param props.align - Cross-axis alignment (`alignItems`). Unset by default (flex default, stretch).
539
+ * @param props.justify - Main-axis distribution (`justifyContent`). Unset by default (flex-start).
540
+ * @param props.density - When true (default), gap is multiplied by theme density
541
+ * (bounded controls). When false, gap is structural `themeSpacing(n)` — use this
542
+ * for page/form columns.
528
543
  * @example { div: [{ h3: "Title" }, { p: "Body" }], $: [stack()] }
529
544
  * @example { div: [...], $: [stack({ gap: 2, align: "center" })] }
545
+ * @example { div: [...], $: [stack({ gap: 3, density: false, justify: "space-between" })] }
530
546
  */
531
547
  declare function stack(props?: {
532
548
  gap?: number;
533
549
  align?: FlexAlign;
550
+ justify?: FlexJustify;
551
+ density?: boolean;
534
552
  }): PartialElement;
535
553
 
536
554
  /**
@@ -559,10 +577,13 @@ declare function grid(props?: {
559
577
  *
560
578
  * @hostTag h1
561
579
  * @param props.color - Theme color tone (`ValueOrState<ThemeColor>`) for the heading text. Defaults to "neutral".
580
+ * @param props.size - Optional `ElementSize` (`"inherit"` | `"increase-N"` | `"decrease-N"`, N ≤ 7). When set, font size is `themeSize(listener, size)` including `"inherit"` (no tag bump). When omitted, follows the host tag (`h1` increase-4 … `h6` decrease-1).
562
581
  * @example { h2: "Section title", $: [heading()] }
582
+ * @example { h3: "Panel title", $: [heading({ size: "inherit" })] }
563
583
  */
564
584
  declare function heading(props?: {
565
585
  color?: ValueOrState<ThemeColor>;
586
+ size?: ElementSize;
566
587
  }): PartialElement;
567
588
 
568
589
  /**
@@ -1051,7 +1072,8 @@ declare function paragraph(props?: {
1051
1072
  *
1052
1073
  * @param props - Configuration.
1053
1074
  * @param props.openOn - Interaction that opens the popover: `"click"` or `"hover"`. Defaults to `"click"`.
1054
- * @param props.open - Open state, accepts a value or `State`. Defaults to `false`.
1075
+ * @param props.open - Open state (`ValueOrState<boolean>`), including `Computed`/`ReadableState`. When the source is read-only, pass `onDismiss` so Escape/outside click can close. Defaults to `false`.
1076
+ * @param props.onDismiss - Called when the panel requests close. Optional. Required to close when `open` is a read-only `Computed`/`ReadableState`.
1055
1077
  * @param props.placement - Floating placement (e.g. `"bottom"`, `"top-start"`), value or `State`. Defaults to `"bottom"`.
1056
1078
  * @param props.content - The floating content element to display.
1057
1079
  * @example { button: "Open", $: [popover({ openOn: "click", content: { div: "Hi" } })] }
@@ -1059,6 +1081,7 @@ declare function paragraph(props?: {
1059
1081
  declare function popover(props: {
1060
1082
  openOn?: "click" | "hover";
1061
1083
  open?: ValueOrState<boolean>;
1084
+ onDismiss?: () => void;
1062
1085
  placement?: ValueOrState<Placement$1>;
1063
1086
  content: DomphyElement;
1064
1087
  }): PartialElement;
@@ -1164,7 +1187,6 @@ declare function ringProgress(props?: {
1164
1187
  thickness?: number;
1165
1188
  }): PartialElement;
1166
1189
 
1167
- type FlexJustify = "flex-start" | "center" | "flex-end" | "space-between" | "space-around" | "space-evenly";
1168
1190
  /**
1169
1191
  * A horizontal flex row with spacing between children, vertically centered by
1170
1192
  * default. The general-purpose primitive for icon+label rows, field rows,
@@ -1172,18 +1194,27 @@ type FlexJustify = "flex-start" | "center" | "flex-end" | "space-between" | "spa
1172
1194
  * center; gap: ...`. `toolbar()` is a semantic alias of this same shape for
1173
1195
  * headers/nav bars. Styles the host only; apply to any block element.
1174
1196
  *
1175
- * @param props.gap - Spacing multiplier for gap between items (default 4 = 1em at density 1).
1197
+ * @param props.gap - Spacing multiplier for gap between items (default 4).
1198
+ * Bounded-control mode (`density: true`, default): `themeSpacing(themeDensity(l) * gap)`
1199
+ * — at default density 1.5, gap 4 = 1.5em.
1200
+ * Structural/page-column mode (`density: false`): bare `themeSpacing(gap)` with no
1201
+ * density multiply — gap 4 = 1em, matching AGENTS.md "bare themeSpacing(n)".
1176
1202
  * @param props.align - Cross-axis alignment (`alignItems`). Defaults to `"center"`.
1177
1203
  * @param props.justify - Main-axis distribution (`justifyContent`). Unset by default (flex-start).
1178
1204
  * @param props.wrap - Allow items to wrap onto multiple lines. Defaults to `false`.
1205
+ * @param props.density - When true (default), gap is multiplied by theme density
1206
+ * (bounded controls). When false, gap is structural `themeSpacing(n)` — use this
1207
+ * for page/form columns.
1179
1208
  * @example { div: [{ span: "Icon" }, { span: "Label" }], $: [row()] }
1180
1209
  * @example { div: [...], $: [row({ justify: "space-between", wrap: true })] }
1210
+ * @example { div: [...], $: [row({ gap: 4, density: false })] }
1181
1211
  */
1182
1212
  declare function row(props?: {
1183
1213
  gap?: number;
1184
1214
  align?: FlexAlign;
1185
1215
  justify?: FlexJustify;
1186
1216
  wrap?: boolean;
1217
+ density?: boolean;
1187
1218
  }): PartialElement;
1188
1219
 
1189
1220
  /**
@@ -1263,7 +1294,8 @@ declare function select(props?: {
1263
1294
  * reactive state. Defaults to `"bottom"`.
1264
1295
  * @param props.content - Required. The popover/dropdown content element shown when open.
1265
1296
  * @param props.color - Theme color tone for the box text/background. Defaults to `"neutral"`.
1266
- * @param props.open - Whether the popover is open. Accepts a value or reactive state. Defaults to `false`.
1297
+ * @param props.open - Whether the popover is open. Accepts a value or reactive state (`ValueOrState<boolean>`, including `Computed`/`ReadableState`). Defaults to `false`. When the source is read-only, pass `onDismiss` so dismiss can close.
1298
+ * @param props.onDismiss - Called when the popover requests close. Optional. Required to close when `open` is a read-only `Computed`/`ReadableState`.
1267
1299
  * @example { div: null, $: [selectBox({ content: { div: [...] }, options: [{ label: "A", value: "a" }] })] }
1268
1300
  */
1269
1301
  declare function selectBox(props: {
@@ -1277,6 +1309,7 @@ declare function selectBox(props: {
1277
1309
  content: DomphyElement;
1278
1310
  color?: ThemeColor;
1279
1311
  open?: ValueOrState<boolean>;
1312
+ onDismiss?: () => void;
1280
1313
  }): PartialElement;
1281
1314
 
1282
1315
  /**
@@ -1523,7 +1556,7 @@ declare function tag(props?: {
1523
1556
  * @hostTag textarea
1524
1557
  * @param props.color - Theme color for the border and text. Optional, accepts a value or state. Defaults to `"neutral"`.
1525
1558
  * @param props.accentColor - Theme color for hover/focus outline. Optional, accepts a value or state. Defaults to `"primary"`.
1526
- * @param props.autoResize - When true, grows the textarea height to fit its content on input and when `value` updates. Optional. Defaults to `false`.
1559
+ * @param props.autoResize - When true, grows the textarea height to fit its content on input and when `value` updates, and remeasures when the host becomes visible (IntersectionObserver) and when its box size changes (ResizeObserver). Optional. Defaults to `false`.
1527
1560
  * @example { textarea: null, $: [textarea({ autoResize: true })] }
1528
1561
  */
1529
1562
  declare function textarea(props?: {
@@ -1603,16 +1636,28 @@ declare function toggleGroup(props?: {
1603
1636
 
1604
1637
  /**
1605
1638
  * A horizontal flex row with vertically centered items. Useful for headers,
1606
- * toolbars, navigation bars, and action strips. A semantic alias of `row()`
1607
- * at its default alignment — reach for `row()` directly for `justify`/`wrap`/
1608
- * `align` beyond this shape.
1639
+ * toolbars, navigation bars, and action strips. A semantic alias of `row()`;
1640
+ * wrap/justify/align/density are forwarded so callers do not drop down to
1641
+ * hand-rolled flex.
1609
1642
  *
1610
- * @param props.gap - Spacing multiplier for gap between items (default 4 = 1em).
1643
+ * @param props.gap - Spacing multiplier for gap between items (default 4).
1644
+ * Bounded-control mode (`density: true`, default): `themeSpacing(themeDensity(l) * gap)`.
1645
+ * Structural mode (`density: false`): bare `themeSpacing(gap)`.
1646
+ * @param props.wrap - Allow items to wrap onto multiple lines. Defaults to `false`.
1647
+ * @param props.justify - Main-axis distribution (`justifyContent`). Unset by default.
1648
+ * @param props.align - Cross-axis alignment (`alignItems`). Defaults to `"center"` (row default).
1649
+ * @param props.density - When true (default), gap is multiplied by theme density.
1650
+ * When false, gap is structural `themeSpacing(n)`.
1611
1651
  * @example { header: [...], $: [toolbar()] }
1612
1652
  * @example { nav: [...], $: [toolbar({ gap: 3 })] }
1653
+ * @example { header: [...], $: [toolbar({ wrap: true, justify: "space-between" })] }
1613
1654
  */
1614
1655
  declare function toolbar(props?: {
1615
1656
  gap?: number;
1657
+ wrap?: boolean;
1658
+ justify?: FlexJustify;
1659
+ align?: FlexAlign;
1660
+ density?: boolean;
1616
1661
  }): PartialElement;
1617
1662
  /**
1618
1663
  * A flex spacer that expands to fill available space in a toolbar, pushing
@@ -1628,13 +1673,15 @@ declare function toolbarSpacer(): DomphyElement;
1628
1673
  * surface is positioned via the floating utility and linked with
1629
1674
  * `aria-describedby`. No host tag check; applied to the trigger element.
1630
1675
  *
1631
- * @param props.open - Controlled open state. Optional, accepts a value or state. Defaults to `false`.
1676
+ * @param props.open - Controlled open state (`ValueOrState<boolean>`), including `Computed`/`ReadableState`. When the source is read-only, pass `onDismiss` so leave/blur/Escape can close. Optional. Defaults to `false`.
1677
+ * @param props.onDismiss - Called when the tooltip requests close. Optional. Required to close when `open` is a read-only `Computed`/`ReadableState`.
1632
1678
  * @param props.placement - Floating placement relative to the trigger. Optional, accepts a value or state (`Placement`). Defaults to `"top"`.
1633
1679
  * @param props.content - Tooltip text content. Optional, accepts a value or state (string only). Defaults to `"Tooltip Content"`.
1634
1680
  * @example { button: "Hover me", $: [tooltip({ content: "Help text" })] }
1635
1681
  */
1636
1682
  declare function tooltip(props?: {
1637
1683
  open?: ValueOrState<boolean>;
1684
+ onDismiss?: () => void;
1638
1685
  placement?: ValueOrState<Placement$1>;
1639
1686
  content?: ValueOrState<string>;
1640
1687
  }): PartialElement;