@kerfjs/ui 5.0.0-beta.32 → 5.0.0-beta.34

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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/list.tsx"],"names":[],"mappings":";;;;AAgBA,IAAM,UAAA,GAAqC;AAAA,EACzC,MAAA;AAAA,EACA,KAAA;AAAA,EACA,IAAA;AAAA,EACA,GAAA;AAAA,EACA,GAAA;AAAA,EACA,GAAA;AAAA,EACA;AACF,CAAA;AAoBO,SAAS,IAAA,CAAK;AAAA,EACnB,QAAA;AAAA,EACA,GAAA,GAAM,KAAA;AAAA,EACN,IAAA,GAAO,KAAA;AAAA,EACP,MAAA,GAAS,MAAA;AAAA,EACT,MAAA,GAAS,KAAA;AAAA,EACT,UAAA,GAAa,KAAA;AAAA,EACb,YAAA,GAAe,EAAA;AAAA,EACf,SAAA,GAAY;AACd,CAAA,EAAc;AACZ,EAAA,MAAM,QAAA,GACJ,GAAA,KAAQ,IAAA,GACJ,qBAAA,GACA,UAAA,CAAW,QAAA,CAAS,GAAkB,CAAA,GACpC,KAAA,CAAM,GAAkB,CAAA,GACxB,GAAA,IAAO,MAAA;AACf,EAAA,MAAM,SAAA,GAAY,IAAA,KAAS,IAAA,GAAO,UAAA,GAAa,IAAA,IAAQ,MAAA;AACvD,EAAA,MAAM,KAAA,GAAQ;AAAA,IACZ,QAAA,GAAW,CAAA,gBAAA,EAAmB,QAAQ,CAAA,CAAA,GAAK,EAAA;AAAA,IAC3C,SAAA,GAAY,CAAA,iBAAA,EAAoB,SAAS,CAAA,CAAA,GAAK;AAAA,GAChD,CACG,MAAA,CAAO,OAAO,CAAA,CACd,KAAK,GAAG,CAAA;AAEX,EAAA,uBACE,GAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,KAAA,EAAO,CAAA,SAAA,EAAY,SAAS,CAAA,CAAA,CAAG,IAAA,EAAK;AAAA,MACpC,gBAAA,EAAe,MAAA;AAAA,MACf,UAAA,EAAU,MAAA,CAAO,OAAA,CAAQ,GAAG,CAAC,CAAA;AAAA,MAC7B,WAAA,EAAW,MAAA,CAAO,OAAA,CAAQ,IAAI,CAAC,CAAA;AAAA,MAC/B,cAAA,EAAc,oBAAoB,MAAM,CAAA;AAAA,MACxC,cAAA,EAAc,kBAAkB,MAAM,CAAA;AAAA,MACtC,iBAAA,EAAiB,OAAO,UAAU,CAAA;AAAA,MAClC,iBAAe,YAAA,IAAgB,MAAA;AAAA,MAC/B,OAAO,KAAA,IAAS,MAAA;AAAA,MAEf;AAAA;AAAA,GACH;AAEJ","file":"chunk-7JQAQWVC.js","sourcesContent":["import {\n type CssFlex,\n type CssFlexKeyword,\n type CssLength,\n space,\n type UiSpaceName,\n} from './css-values.js';\nimport type { DividerSides } from './divider-sides.js';\nimport {\n type HorizontalAlignment,\n horizontalAlignment,\n type VerticalAlignment,\n verticalAlignment,\n} from './flex-alignment.js';\nimport type { KerfUiContent } from './semantic-content.js';\n\nconst spaceNames: readonly UiSpaceName[] = [\n 'none',\n '2xs',\n 'xs',\n 's',\n 'm',\n 'l',\n 'xl',\n];\n\nexport interface ListProps {\n children?: KerfUiContent;\n /** Use the standard item gap, a named UI spacing token, or a typed CSS length. Defaults to no gap. */\n gap?: boolean | UiSpaceName | CssLength;\n /** Allow this list to grow/shrink, use a keyword, or supply a typed CSS flex shorthand. */\n flex?: boolean | CssFlexKeyword | CssFlex;\n /** Horizontal alignment. Defaults to full to preserve stretch-aligned list children. */\n hAlign?: HorizontalAlignment;\n /** Vertical distribution. Defaults to top. */\n vAlign?: VerticalAlignment;\n /** Own vertical scrolling and overscroll containment. */\n scrollable?: boolean;\n /** Physical divider edges in canonical top/right/bottom/left order. */\n dividerSides?: DividerSides;\n className?: string;\n}\n\n/** A stretch-aligned vertical stack with optional gap, flex, scroll, and dividers. */\nexport function List({\n children,\n gap = false,\n flex = false,\n hAlign = 'full',\n vAlign = 'top',\n scrollable = false,\n dividerSides = '',\n className = '',\n}: ListProps) {\n const gapValue =\n gap === true\n ? 'var(--kui-list-gap)'\n : spaceNames.includes(gap as UiSpaceName)\n ? space(gap as UiSpaceName)\n : gap || undefined;\n const flexValue = flex === true ? '1 1 auto' : flex || undefined;\n const style = [\n gapValue ? `--_kui-list-gap:${gapValue}` : '',\n flexValue ? `--_kui-list-flex:${flexValue}` : '',\n ]\n .filter(Boolean)\n .join(';');\n\n return (\n <div\n class={`kui-list ${className}`.trim()}\n data-component=\"list\"\n data-gap={String(Boolean(gap))}\n data-flex={String(Boolean(flex))}\n data-h-align={horizontalAlignment(hAlign)}\n data-v-align={verticalAlignment(vAlign)}\n data-scrollable={String(scrollable)}\n divider-sides={dividerSides || undefined}\n style={style || undefined}\n >\n {children}\n </div>\n );\n}\n\nexport type {\n CssFlex,\n CssFlexKeyword,\n CssLength,\n UiSpaceName,\n} from './css-values.js';\nexport type { DividerSides } from './divider-sides.js';\nexport type {\n HorizontalAlignment,\n VerticalAlignment,\n} from './flex-alignment.js';\n"]}
@@ -0,0 +1,39 @@
1
+ import { verticalAlignment, horizontalAlignment } from './chunk-R3EBGEAW.js';
2
+ import { space } from './chunk-OL4TC3U2.js';
3
+ import { jsx } from 'kerfjs/jsx-runtime';
4
+
5
+ var spaceNames = [
6
+ "none",
7
+ "2xs",
8
+ "xs",
9
+ "s",
10
+ "m",
11
+ "l",
12
+ "xl"
13
+ ];
14
+ function Row({
15
+ children,
16
+ hAlign = "left",
17
+ vAlign = "full",
18
+ gap = "xs",
19
+ wrap = false,
20
+ className = ""
21
+ }) {
22
+ const gapValue = spaceNames.includes(gap) ? space(gap) : gap;
23
+ return /* @__PURE__ */ jsx(
24
+ "div",
25
+ {
26
+ class: `kui-row ${className}`.trim(),
27
+ "data-component": "row",
28
+ "data-h-align": horizontalAlignment(hAlign),
29
+ "data-v-align": verticalAlignment(vAlign),
30
+ "data-wrap": String(wrap),
31
+ style: `--_kui-row-gap:${gapValue}`,
32
+ children
33
+ }
34
+ );
35
+ }
36
+
37
+ export { Row };
38
+
39
+ //# sourceMappingURL=chunk-OKRCKIVO.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/row.tsx"],"names":[],"mappings":";;;;AASA,IAAM,UAAA,GAAqC;AAAA,EACzC,MAAA;AAAA,EACA,KAAA;AAAA,EACA,IAAA;AAAA,EACA,GAAA;AAAA,EACA,GAAA;AAAA,EACA,GAAA;AAAA,EACA;AACF,CAAA;AAgBO,SAAS,GAAA,CAAI;AAAA,EAClB,QAAA;AAAA,EACA,MAAA,GAAS,MAAA;AAAA,EACT,MAAA,GAAS,MAAA;AAAA,EACT,GAAA,GAAM,IAAA;AAAA,EACN,IAAA,GAAO,KAAA;AAAA,EACP,SAAA,GAAY;AACd,CAAA,EAAa;AACX,EAAA,MAAM,WAAW,UAAA,CAAW,QAAA,CAAS,GAAkB,CAAA,GACnD,KAAA,CAAM,GAAkB,CAAA,GACxB,GAAA;AAEJ,EAAA,uBACE,GAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,KAAA,EAAO,CAAA,QAAA,EAAW,SAAS,CAAA,CAAA,CAAG,IAAA,EAAK;AAAA,MACnC,gBAAA,EAAe,KAAA;AAAA,MACf,cAAA,EAAc,oBAAoB,MAAM,CAAA;AAAA,MACxC,cAAA,EAAc,kBAAkB,MAAM,CAAA;AAAA,MACtC,WAAA,EAAW,OAAO,IAAI,CAAA;AAAA,MACtB,KAAA,EAAO,kBAAkB,QAAQ,CAAA,CAAA;AAAA,MAEhC;AAAA;AAAA,GACH;AAEJ","file":"chunk-OKRCKIVO.js","sourcesContent":["import { type CssLength, space, type UiSpaceName } from './css-values.js';\nimport {\n type HorizontalAlignment,\n horizontalAlignment,\n type VerticalAlignment,\n verticalAlignment,\n} from './flex-alignment.js';\nimport type { KerfUiContent } from './semantic-content.js';\n\nconst spaceNames: readonly UiSpaceName[] = [\n 'none',\n '2xs',\n 'xs',\n 's',\n 'm',\n 'l',\n 'xl',\n];\n\nexport interface RowProps {\n children?: KerfUiContent;\n /** Horizontal distribution. Defaults to left. */\n hAlign?: HorizontalAlignment;\n /** Vertical alignment and wrapped-line distribution. Defaults to full. */\n vAlign?: VerticalAlignment;\n /** A named UI spacing token or typed CSS length. Defaults to xs. */\n gap?: UiSpaceName | CssLength;\n /** Allow children to wrap onto additional lines. */\n wrap?: boolean;\n className?: string;\n}\n\n/** A horizontal flex row with explicit physical-axis alignment and spacing. */\nexport function Row({\n children,\n hAlign = 'left',\n vAlign = 'full',\n gap = 'xs',\n wrap = false,\n className = '',\n}: RowProps) {\n const gapValue = spaceNames.includes(gap as UiSpaceName)\n ? space(gap as UiSpaceName)\n : gap;\n\n return (\n <div\n class={`kui-row ${className}`.trim()}\n data-component=\"row\"\n data-h-align={horizontalAlignment(hAlign)}\n data-v-align={verticalAlignment(vAlign)}\n data-wrap={String(wrap)}\n style={`--_kui-row-gap:${gapValue}`}\n >\n {children}\n </div>\n );\n}\n\nexport type { CssLength, UiSpaceName } from './css-values.js';\nexport type {\n HorizontalAlignment,\n VerticalAlignment,\n} from './flex-alignment.js';\n"]}
@@ -0,0 +1,46 @@
1
+ // src/flex-alignment.ts
2
+ function horizontalAlignment(value) {
3
+ switch (value) {
4
+ case "left":
5
+ case "l":
6
+ case "flex-start":
7
+ return "left";
8
+ case "center":
9
+ case "c":
10
+ case "space-around":
11
+ return "center";
12
+ case "right":
13
+ case "r":
14
+ case "flex-end":
15
+ return "right";
16
+ case "full":
17
+ case "f":
18
+ case "space-between":
19
+ return "full";
20
+ }
21
+ }
22
+ function verticalAlignment(value) {
23
+ switch (value) {
24
+ case "top":
25
+ case "t":
26
+ case "flex-start":
27
+ return "top";
28
+ case "middle":
29
+ case "m":
30
+ case "c":
31
+ case "space-around":
32
+ return "middle";
33
+ case "bottom":
34
+ case "b":
35
+ case "flex-end":
36
+ return "bottom";
37
+ case "full":
38
+ case "f":
39
+ case "space-between":
40
+ return "full";
41
+ }
42
+ }
43
+
44
+ export { horizontalAlignment, verticalAlignment };
45
+
46
+ //# sourceMappingURL=chunk-R3EBGEAW.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/flex-alignment.ts"],"names":[],"mappings":";AAgCO,SAAS,oBACd,KAAA,EAC8B;AAC9B,EAAA,QAAQ,KAAA;AAAO,IACb,KAAK,MAAA;AAAA,IACL,KAAK,GAAA;AAAA,IACL,KAAK,YAAA;AACH,MAAA,OAAO,MAAA;AAAA,IACT,KAAK,QAAA;AAAA,IACL,KAAK,GAAA;AAAA,IACL,KAAK,cAAA;AACH,MAAA,OAAO,QAAA;AAAA,IACT,KAAK,OAAA;AAAA,IACL,KAAK,GAAA;AAAA,IACL,KAAK,UAAA;AACH,MAAA,OAAO,OAAA;AAAA,IACT,KAAK,MAAA;AAAA,IACL,KAAK,GAAA;AAAA,IACL,KAAK,eAAA;AACH,MAAA,OAAO,MAAA;AAAA;AAEb;AAEO,SAAS,kBACd,KAAA,EAC4B;AAC5B,EAAA,QAAQ,KAAA;AAAO,IACb,KAAK,KAAA;AAAA,IACL,KAAK,GAAA;AAAA,IACL,KAAK,YAAA;AACH,MAAA,OAAO,KAAA;AAAA,IACT,KAAK,QAAA;AAAA,IACL,KAAK,GAAA;AAAA,IACL,KAAK,GAAA;AAAA,IACL,KAAK,cAAA;AACH,MAAA,OAAO,QAAA;AAAA,IACT,KAAK,QAAA;AAAA,IACL,KAAK,GAAA;AAAA,IACL,KAAK,UAAA;AACH,MAAA,OAAO,QAAA;AAAA,IACT,KAAK,MAAA;AAAA,IACL,KAAK,GAAA;AAAA,IACL,KAAK,eAAA;AACH,MAAA,OAAO,MAAA;AAAA;AAEb","file":"chunk-R3EBGEAW.js","sourcesContent":["export type HorizontalAlignment =\n | 'left'\n | 'l'\n | 'flex-start'\n | 'center'\n | 'c'\n | 'space-around'\n | 'right'\n | 'r'\n | 'flex-end'\n | 'full'\n | 'f'\n | 'space-between';\n\nexport type VerticalAlignment =\n | 'top'\n | 't'\n | 'flex-start'\n | 'middle'\n | 'm'\n | 'c'\n | 'space-around'\n | 'bottom'\n | 'b'\n | 'flex-end'\n | 'full'\n | 'f'\n | 'space-between';\n\nexport type CanonicalHorizontalAlignment = 'left' | 'center' | 'right' | 'full';\nexport type CanonicalVerticalAlignment = 'top' | 'middle' | 'bottom' | 'full';\n\nexport function horizontalAlignment(\n value: HorizontalAlignment,\n): CanonicalHorizontalAlignment {\n switch (value) {\n case 'left':\n case 'l':\n case 'flex-start':\n return 'left';\n case 'center':\n case 'c':\n case 'space-around':\n return 'center';\n case 'right':\n case 'r':\n case 'flex-end':\n return 'right';\n case 'full':\n case 'f':\n case 'space-between':\n return 'full';\n }\n}\n\nexport function verticalAlignment(\n value: VerticalAlignment,\n): CanonicalVerticalAlignment {\n switch (value) {\n case 'top':\n case 't':\n case 'flex-start':\n return 'top';\n case 'middle':\n case 'm':\n case 'c':\n case 'space-around':\n return 'middle';\n case 'bottom':\n case 'b':\n case 'flex-end':\n return 'bottom';\n case 'full':\n case 'f':\n case 'space-between':\n return 'full';\n }\n}\n"]}
@@ -0,0 +1,4 @@
1
+ type HorizontalAlignment = 'left' | 'l' | 'flex-start' | 'center' | 'c' | 'space-around' | 'right' | 'r' | 'flex-end' | 'full' | 'f' | 'space-between';
2
+ type VerticalAlignment = 'top' | 't' | 'flex-start' | 'middle' | 'm' | 'c' | 'space-around' | 'bottom' | 'b' | 'flex-end' | 'full' | 'f' | 'space-between';
3
+
4
+ export type { HorizontalAlignment as H, VerticalAlignment as V };
package/dist/index.d.ts CHANGED
@@ -13,6 +13,7 @@ export { LoadingSpinner, LoadingSpinnerProps } from './loading-spinner.js';
13
13
  export { LucideIcon, LucideIconProps, LucideNode } from './lucide-icon.js';
14
14
  export { Pane, PaneContentElement, PaneElement, PaneProps, PaneSeparatorSide } from './pane.js';
15
15
  export { ResizableRegion, ResizableRegionAxis, ResizableRegionCollapseMotion, ResizableRegionContentOverflow, ResizableRegionEdge, ResizableRegionPresentation, ResizableRegionProps, ResizableRegionRestorePosition, ResizableRegionSeparator, clampRegionSize, resizeRegionFromPointer } from './resizable-region.js';
16
+ export { Row, RowProps } from './row.js';
16
17
  export { SegmentedControl, SegmentedControlAppearance, SegmentedControlChoice, SegmentedControlLayout, SegmentedControlProps, SegmentedControlShape, SegmentedControlSize } from './segmented-control.js';
17
18
  export { Select, SelectChoice, SelectFocusRingOwner, SelectPresentation, SelectProps, SelectSelectedPresentation, SelectSize } from './select.js';
18
19
  export { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
@@ -30,5 +31,6 @@ export { ResizeCommit, WireResizableRegionsOptions, wireResizableRegions } from
30
31
  export { TabDropPosition, TabReorder, TabReorderSource, WireTabBarsOptions, reorderTabs, wireTabBars } from './wire-tab-bars.js';
31
32
  export { TokenSearchCollapsibleOptions, TokenSearchEdit, TokenSearchFieldsHandle, TokenSearchSubmit, WireTokenSearchFieldsOptions, wireTokenSearchFields } from './wire-token-search-fields.js';
32
33
  export { D as DividerSides } from './divider-sides-267FA7sY.js';
34
+ export { H as HorizontalAlignment, V as VerticalAlignment } from './flex-alignment-CF8NLj7i.js';
33
35
  import 'kerfjs';
34
36
  import 'lucide';
package/dist/index.js CHANGED
@@ -1,16 +1,17 @@
1
+ export { wireResizableRegions } from './chunk-WN52USHV.js';
1
2
  export { reorderTabs, wireTabBars } from './chunk-UKKSMZYT.js';
2
3
  export { wireTokenSearchFields } from './chunk-VDUJZF5G.js';
4
+ export { TokenSearchField, placeTokenSearchCaret, readTokenSearchField } from './chunk-TIGSG6BX.js';
3
5
  export { ValueTable, ValueTableRow } from './chunk-V6HCTCVD.js';
4
- export { wireResizableRegions } from './chunk-WN52USHV.js';
6
+ export { Select } from './chunk-CK6P5AUK.js';
5
7
  export { StateBanner } from './chunk-UDHHKZWO.js';
6
8
  export { SunkenPanel } from './chunk-SOK5EUF7.js';
7
9
  export { DialogSurface, PopupSurface } from './chunk-WSXUPSID.js';
8
10
  export { TabBar } from './chunk-ZPWZIVI6.js';
9
- export { TokenSearchField, placeTokenSearchCaret, readTokenSearchField } from './chunk-TIGSG6BX.js';
10
11
  export { ToolbarText } from './chunk-V6GQKOX2.js';
11
12
  export { ResizableRegion, clampRegionSize, resizeRegionFromPointer } from './chunk-CAB6NQ2T.js';
13
+ export { Row } from './chunk-OKRCKIVO.js';
12
14
  export { SegmentedControl } from './chunk-E34TE2ZI.js';
13
- export { Select } from './chunk-CK6P5AUK.js';
14
15
  export { FloatingToolbar } from './chunk-DYBPI5O2.js';
15
16
  export { ListActionRow } from './chunk-DAO2VFTT.js';
16
17
  export { ListInsetControl } from './chunk-MFR2IIFG.js';
@@ -21,7 +22,8 @@ export { Toolbar } from './chunk-VXFGMDA7.js';
21
22
  export { Pane } from './chunk-I4V3UDSA.js';
22
23
  export { ListHeader } from './chunk-OC275HHS.js';
23
24
  export { ListItem } from './chunk-I45QO2IZ.js';
24
- export { List } from './chunk-RL6COPKF.js';
25
+ export { List } from './chunk-7JQAQWVC.js';
26
+
25
27
 
26
28
  export { Skeleton } from './chunk-T7DOWS6T.js';
27
29
  export { calc, colorVar, em, flex, lengthVar, pct, plus, px, rem, space, uiColor } from './chunk-OL4TC3U2.js';
package/dist/list.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import * as kerfjs from 'kerfjs';
2
2
  import { UiSpaceName, CssLength, CssFlexKeyword, CssFlex } from './css-values.js';
3
3
  import { D as DividerSides } from './divider-sides-267FA7sY.js';
4
+ import { H as HorizontalAlignment, V as VerticalAlignment } from './flex-alignment-CF8NLj7i.js';
4
5
  import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
5
6
 
6
7
  interface ListProps {
@@ -9,6 +10,10 @@ interface ListProps {
9
10
  gap?: boolean | UiSpaceName | CssLength;
10
11
  /** Allow this list to grow/shrink, use a keyword, or supply a typed CSS flex shorthand. */
11
12
  flex?: boolean | CssFlexKeyword | CssFlex;
13
+ /** Horizontal alignment. Defaults to full to preserve stretch-aligned list children. */
14
+ hAlign?: HorizontalAlignment;
15
+ /** Vertical distribution. Defaults to top. */
16
+ vAlign?: VerticalAlignment;
12
17
  /** Own vertical scrolling and overscroll containment. */
13
18
  scrollable?: boolean;
14
19
  /** Physical divider edges in canonical top/right/bottom/left order. */
@@ -16,6 +21,6 @@ interface ListProps {
16
21
  className?: string;
17
22
  }
18
23
  /** A stretch-aligned vertical stack with optional gap, flex, scroll, and dividers. */
19
- declare function List({ children, gap, flex, scrollable, dividerSides, className, }: ListProps): kerfjs.SafeHtml;
24
+ declare function List({ children, gap, flex, hAlign, vAlign, scrollable, dividerSides, className, }: ListProps): kerfjs.SafeHtml;
20
25
 
21
- export { CssFlex, CssFlexKeyword, CssLength, DividerSides, List, type ListProps, UiSpaceName };
26
+ export { CssFlex, CssFlexKeyword, CssLength, DividerSides, HorizontalAlignment, List, type ListProps, UiSpaceName, VerticalAlignment };
package/dist/list.js CHANGED
@@ -1,4 +1,5 @@
1
- export { List } from './chunk-RL6COPKF.js';
1
+ export { List } from './chunk-7JQAQWVC.js';
2
+
2
3
 
3
4
 
4
5
  //# sourceMappingURL=list.js.map
package/dist/row.d.ts ADDED
@@ -0,0 +1,21 @@
1
+ import * as kerfjs from 'kerfjs';
2
+ import { UiSpaceName, CssLength } from './css-values.js';
3
+ import { H as HorizontalAlignment, V as VerticalAlignment } from './flex-alignment-CF8NLj7i.js';
4
+ import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
5
+
6
+ interface RowProps {
7
+ children?: KerfUiContent;
8
+ /** Horizontal distribution. Defaults to left. */
9
+ hAlign?: HorizontalAlignment;
10
+ /** Vertical alignment and wrapped-line distribution. Defaults to full. */
11
+ vAlign?: VerticalAlignment;
12
+ /** A named UI spacing token or typed CSS length. Defaults to xs. */
13
+ gap?: UiSpaceName | CssLength;
14
+ /** Allow children to wrap onto additional lines. */
15
+ wrap?: boolean;
16
+ className?: string;
17
+ }
18
+ /** A horizontal flex row with explicit physical-axis alignment and spacing. */
19
+ declare function Row({ children, hAlign, vAlign, gap, wrap, className, }: RowProps): kerfjs.SafeHtml;
20
+
21
+ export { CssLength, HorizontalAlignment, Row, type RowProps, UiSpaceName, VerticalAlignment };
package/dist/row.js ADDED
@@ -0,0 +1,5 @@
1
+ export { Row } from './chunk-OKRCKIVO.js';
2
+
3
+
4
+
5
+ //# sourceMappingURL=row.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"row.js"}
@@ -3,9 +3,134 @@ import '@awesome.me/webawesome/dist/components/divider/divider.js';
3
3
  import '@awesome.me/webawesome/dist/components/dropdown/dropdown.js';
4
4
  import '@awesome.me/webawesome/dist/components/dropdown-item/dropdown-item.js';
5
5
  import '@awesome.me/webawesome/dist/components/option/option.js';
6
- import '@awesome.me/webawesome/dist/components/select/select.js';
6
+ import WaSelect from '@awesome.me/webawesome/dist/components/select/select.js';
7
+ import { WaAfterHideEvent } from '@awesome.me/webawesome/dist/events/after-hide.js';
8
+ import { WaAfterShowEvent } from '@awesome.me/webawesome/dist/events/after-show.js';
9
+ import { WaHideEvent } from '@awesome.me/webawesome/dist/events/hide.js';
10
+ import { WaShowEvent } from '@awesome.me/webawesome/dist/events/show.js';
7
11
 
8
12
  // src/select-register.ts
13
+
14
+ // src/animate-select-popup.ts
15
+ function animateSelectPopup(popup, phase, signal) {
16
+ return new Promise((resolve) => {
17
+ let settled = false;
18
+ let frame = 0;
19
+ const finish = () => {
20
+ if (settled) return;
21
+ settled = true;
22
+ window.cancelAnimationFrame(frame);
23
+ signal.removeEventListener("abort", finish);
24
+ popup.classList.remove(phase);
25
+ resolve();
26
+ };
27
+ signal.addEventListener("abort", finish, { once: true });
28
+ popup.classList.add(phase);
29
+ frame = window.requestAnimationFrame(() => {
30
+ void Promise.all(
31
+ popup.getAnimations().map((animation) => animation.finished.catch(() => void 0))
32
+ ).then(finish);
33
+ });
34
+ if (signal.aborted) finish();
35
+ });
36
+ }
37
+
38
+ // src/install-select-lifecycle.ts
39
+ function installSelectLifecycle(prototype) {
40
+ const installed = /* @__PURE__ */ Symbol.for("@kerfjs/ui/select-lifecycle");
41
+ if (Object.prototype.hasOwnProperty.call(prototype, installed)) return;
42
+ Object.defineProperty(prototype, installed, { value: true });
43
+ const original = prototype.handleOpenChange;
44
+ const originalDisabled = prototype.handleDisabledChange;
45
+ prototype.handleDisabledChange = function() {
46
+ const host = this;
47
+ const wasOpen = host.open;
48
+ originalDisabled.call(this);
49
+ if (host.dataset.component === "select" && wasOpen && !host.open) {
50
+ void host.handleOpenChange();
51
+ }
52
+ };
53
+ const transitions = /* @__PURE__ */ new WeakMap();
54
+ const restorations = /* @__PURE__ */ new WeakMap();
55
+ prototype.handleOpenChange = async function() {
56
+ const host = this;
57
+ if (host.dataset.component !== "select") return original.call(this);
58
+ const restoring = restorations.get(host)?.open === host.open;
59
+ restorations.delete(host);
60
+ if (restoring) return;
61
+ const transition = new AbortController();
62
+ const opening = host.open && !host.disabled;
63
+ const current = () => !transition.signal.aborted && host.isConnected && (host.open && !host.disabled) === opening;
64
+ try {
65
+ if (!host.isConnected) return;
66
+ if (opening) {
67
+ host.setCurrentOption(host.selectedOptions[0] || host.getFirstOption());
68
+ }
69
+ const event = opening ? new WaShowEvent() : new WaHideEvent();
70
+ host.dispatchEvent(event);
71
+ if (event.defaultPrevented) {
72
+ host.open = !opening;
73
+ const restoration = { open: host.open };
74
+ restorations.set(host, restoration);
75
+ void host.updateComplete.then(() => {
76
+ if (restorations.get(host) === restoration) restorations.delete(host);
77
+ });
78
+ return;
79
+ }
80
+ if (!current()) return;
81
+ transitions.get(host)?.abort();
82
+ transitions.set(host, transition);
83
+ if (opening) {
84
+ host.addOpenListeners();
85
+ host.listbox.hidden = false;
86
+ host.popup.active = true;
87
+ window.requestAnimationFrame(() => {
88
+ if (current()) host.setCurrentOption(host.currentOption);
89
+ });
90
+ } else {
91
+ host.removeOpenListeners();
92
+ }
93
+ await animateSelectPopup(
94
+ host.popup.popup,
95
+ opening ? "show" : "hide",
96
+ transition.signal
97
+ );
98
+ if (!transition.signal.aborted && !host.isConnected) {
99
+ host.removeOpenListeners();
100
+ host.listbox.hidden = true;
101
+ host.popup.active = false;
102
+ }
103
+ if (!current()) return;
104
+ if (opening) {
105
+ const option = host.currentOption;
106
+ if (option) {
107
+ const list = host.listbox;
108
+ const offset = Math.round(
109
+ option.getBoundingClientRect().top - list.getBoundingClientRect().top
110
+ );
111
+ if (offset < 0)
112
+ list.scrollTo({ top: list.scrollTop + offset, behavior: "auto" });
113
+ else if (offset + option.clientHeight > list.offsetHeight) {
114
+ list.scrollTo({
115
+ top: list.scrollTop + offset - list.offsetHeight + option.clientHeight,
116
+ behavior: "auto"
117
+ });
118
+ }
119
+ }
120
+ host.dispatchEvent(new WaAfterShowEvent());
121
+ } else {
122
+ host.listbox.hidden = true;
123
+ host.popup.active = false;
124
+ host.dispatchEvent(new WaAfterHideEvent());
125
+ }
126
+ } finally {
127
+ if (transitions.get(host) === transition) transitions.delete(host);
128
+ }
129
+ };
130
+ }
131
+
132
+ // src/select-register.ts
133
+ installSelectLifecycle(WaSelect.prototype);
9
134
  var selectElementsRegistered = true;
10
135
 
11
136
  export { selectElementsRegistered };
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/select-register.ts"],"names":[],"mappings":";;;;;;;;AAYO,IAAM,wBAAA,GAA2B","file":"select-register.js","sourcesContent":["import '@awesome.me/webawesome/dist/components/button/button.js';\nimport '@awesome.me/webawesome/dist/components/divider/divider.js';\nimport '@awesome.me/webawesome/dist/components/dropdown/dropdown.js';\nimport '@awesome.me/webawesome/dist/components/dropdown-item/dropdown-item.js';\nimport '@awesome.me/webawesome/dist/components/option/option.js';\nimport '@awesome.me/webawesome/dist/components/select/select.js';\n\n/**\n * Marker export for tests and tooling; importing this module performs registration.\n * Registers both the `Select` elements and the `Catalog` related-entries popup-menu\n * elements (`wa-dropdown` / `wa-dropdown-item` / `wa-button`).\n */\nexport const selectElementsRegistered = true;\n"]}
1
+ {"version":3,"sources":["../src/animate-select-popup.ts","../src/install-select-lifecycle.ts","../src/select-register.ts"],"names":[],"mappings":"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","file":"select-register.js","sourcesContent":["/** Run one native Select CSS animation; a reversal owns cancellation and cleanup. */\nexport function animateSelectPopup(\n popup: HTMLElement,\n phase: 'show' | 'hide',\n signal: AbortSignal,\n): Promise<void> {\n return new Promise((resolve) => {\n let settled = false;\n let frame = 0;\n const finish = () => {\n if (settled) return;\n settled = true;\n window.cancelAnimationFrame(frame);\n signal.removeEventListener('abort', finish);\n popup.classList.remove(phase);\n resolve();\n };\n signal.addEventListener('abort', finish, { once: true });\n popup.classList.add(phase);\n // Activation renders asynchronously. Check for reduced/absent motion only\n // after the native popup has had its normal render opportunity.\n frame = window.requestAnimationFrame(() => {\n // Observe these exact animations. An old CSS animationcancel event can\n // arrive after the next phase starts and must not finish that new phase.\n void Promise.all(\n popup\n .getAnimations()\n .map((animation) => animation.finished.catch(() => undefined)),\n ).then(finish);\n });\n if (signal.aborted) finish();\n });\n}\n","import type WaSelect from '@awesome.me/webawesome/dist/components/select/select.js';\nimport { WaAfterHideEvent } from '@awesome.me/webawesome/dist/events/after-hide.js';\nimport { WaAfterShowEvent } from '@awesome.me/webawesome/dist/events/after-show.js';\nimport { WaHideEvent } from '@awesome.me/webawesome/dist/events/hide.js';\nimport { WaShowEvent } from '@awesome.me/webawesome/dist/events/show.js';\n\nimport { animateSelectPopup } from './animate-select-popup.js';\n\n// Web Awesome 3.12/3.13 expose the lifecycle method but not these helper types.\n// Keep this integration boundary local: native option selection, dismissal\n// listeners, popup positioning and rendering remain owned by Web Awesome.\ninterface SelectHost extends Pick<\n WaSelect,\n | 'open'\n | 'disabled'\n | 'isConnected'\n | 'dataset'\n | 'popup'\n | 'listbox'\n | 'currentOption'\n | 'selectedOptions'\n | 'dispatchEvent'\n | 'handleOpenChange'\n | 'updateComplete'\n> {\n getFirstOption(): WaSelect['currentOption'];\n setCurrentOption(option: WaSelect['currentOption']): void;\n addOpenListeners(): void;\n removeOpenListeners(): void;\n}\n\n/** Install once at the explicit registration boundary, only for Kerf Selects. */\nexport function installSelectLifecycle(\n prototype: Pick<WaSelect, 'handleOpenChange' | 'handleDisabledChange'>,\n): void {\n const installed = Symbol.for('@kerfjs/ui/select-lifecycle');\n if (Object.prototype.hasOwnProperty.call(prototype, installed)) return;\n Object.defineProperty(prototype, installed, { value: true });\n const original = prototype.handleOpenChange;\n const originalDisabled = prototype.handleDisabledChange;\n prototype.handleDisabledChange = function () {\n const host = this as unknown as SelectHost;\n const wasOpen = host.open;\n originalDisabled.call(this);\n // WA's disabled watcher runs after its open watcher in the same Lit update.\n // Its open=false mutation otherwise misses the open lifecycle altogether.\n if (host.dataset.component === 'select' && wasOpen && !host.open) {\n void host.handleOpenChange();\n }\n };\n const transitions = new WeakMap<SelectHost, AbortController>();\n const restorations = new WeakMap<SelectHost, { open: boolean }>();\n prototype.handleOpenChange = async function () {\n const host = this as unknown as SelectHost;\n if (host.dataset.component !== 'select') return original.call(this);\n const restoring = restorations.get(host)?.open === host.open;\n restorations.delete(host);\n if (restoring) return;\n const transition = new AbortController();\n const opening = host.open && !host.disabled;\n const current = () =>\n !transition.signal.aborted &&\n host.isConnected &&\n (host.open && !host.disabled) === opening;\n try {\n if (!host.isConnected) return;\n if (opening) {\n host.setCurrentOption(host.selectedOptions[0] || host.getFirstOption());\n }\n const event = opening ? new WaShowEvent() : new WaHideEvent();\n host.dispatchEvent(event);\n if (event.defaultPrevented) {\n // Restore the accepted state without emitting the opposite transition.\n // Clear at the update checkpoint too: Lit can coalesce a restoration.\n host.open = !opening;\n const restoration = { open: host.open };\n restorations.set(host, restoration);\n void host.updateComplete.then(() => {\n if (restorations.get(host) === restoration) restorations.delete(host);\n });\n return;\n }\n // A consumer can reverse the request synchronously in a lifecycle event.\n if (!current()) return;\n // A rejected reversal must not cancel the previously accepted animation.\n transitions.get(host)?.abort();\n transitions.set(host, transition);\n if (opening) {\n host.addOpenListeners();\n host.listbox.hidden = false;\n host.popup.active = true;\n window.requestAnimationFrame(() => {\n if (current()) host.setCurrentOption(host.currentOption);\n });\n } else {\n host.removeOpenListeners();\n }\n await animateSelectPopup(\n host.popup.popup,\n opening ? 'show' : 'hide',\n transition.signal,\n );\n if (!transition.signal.aborted && !host.isConnected) {\n host.removeOpenListeners();\n host.listbox.hidden = true;\n host.popup.active = false;\n }\n if (!current()) return;\n if (opening) {\n // Match native vertical, immediate option reveal without scrolling an\n // ancestor page or moving focus after animation completion.\n const option = host.currentOption;\n if (option) {\n const list = host.listbox;\n const offset = Math.round(\n option.getBoundingClientRect().top -\n list.getBoundingClientRect().top,\n );\n if (offset < 0)\n list.scrollTo({ top: list.scrollTop + offset, behavior: 'auto' });\n else if (offset + option.clientHeight > list.offsetHeight) {\n list.scrollTo({\n top:\n list.scrollTop +\n offset -\n list.offsetHeight +\n option.clientHeight,\n behavior: 'auto',\n });\n }\n }\n host.dispatchEvent(new WaAfterShowEvent());\n } else {\n host.listbox.hidden = true;\n host.popup.active = false;\n host.dispatchEvent(new WaAfterHideEvent());\n }\n } finally {\n if (transitions.get(host) === transition) transitions.delete(host);\n }\n };\n}\n","import '@awesome.me/webawesome/dist/components/button/button.js';\nimport '@awesome.me/webawesome/dist/components/divider/divider.js';\nimport '@awesome.me/webawesome/dist/components/dropdown/dropdown.js';\nimport '@awesome.me/webawesome/dist/components/dropdown-item/dropdown-item.js';\nimport '@awesome.me/webawesome/dist/components/option/option.js';\n\nimport WaSelect from '@awesome.me/webawesome/dist/components/select/select.js';\n\nimport { installSelectLifecycle } from './install-select-lifecycle.js';\n\ninstallSelectLifecycle(WaSelect.prototype);\n\n/**\n * Marker export for tests and tooling; importing this module performs registration.\n * Registers both the `Select` elements and the `Catalog` related-entries popup-menu\n * elements (`wa-dropdown` / `wa-dropdown-item` / `wa-button`).\n */\nexport const selectElementsRegistered = true;\n"]}
@@ -13,6 +13,8 @@
13
13
  flex: var(--_kui-list-flex, initial);
14
14
  flex-direction: column;
15
15
  align-items: stretch;
16
+ align-content: space-between;
17
+ justify-content: flex-start;
16
18
  gap: var(--_kui-list-gap, 0);
17
19
  box-shadow:
18
20
  inset 0 1px var(--_kui-list-divider-top),
@@ -21,6 +23,33 @@
21
23
  inset 1px 0 var(--_kui-list-divider-left);
22
24
  }
23
25
 
26
+ .kui-list[data-h-align="left"] {
27
+ align-items: flex-start;
28
+ align-content: flex-start;
29
+ }
30
+
31
+ .kui-list[data-h-align="center"] {
32
+ align-items: center;
33
+ align-content: space-around;
34
+ }
35
+
36
+ .kui-list[data-h-align="right"] {
37
+ align-items: flex-end;
38
+ align-content: flex-end;
39
+ }
40
+
41
+ .kui-list[data-v-align="middle"] {
42
+ justify-content: space-around;
43
+ }
44
+
45
+ .kui-list[data-v-align="bottom"] {
46
+ justify-content: flex-end;
47
+ }
48
+
49
+ .kui-list[data-v-align="full"] {
50
+ justify-content: space-between;
51
+ }
52
+
24
53
  .kui-list[data-scrollable="true"] {
25
54
  overflow-y: auto;
26
55
  overscroll-behavior-y: contain;
@@ -0,0 +1,45 @@
1
+ .kui-row {
2
+ --kui-row-gap: var(--kui-layout-item-gap, 0.5rem);
3
+
4
+ display: flex;
5
+ min-width: 0;
6
+ min-height: 0;
7
+ box-sizing: border-box;
8
+ flex-direction: row;
9
+ flex-wrap: nowrap;
10
+ align-items: stretch;
11
+ align-content: space-between;
12
+ justify-content: flex-start;
13
+ gap: var(--_kui-row-gap, var(--kui-row-gap));
14
+ }
15
+
16
+ .kui-row[data-wrap="true"] {
17
+ flex-wrap: wrap;
18
+ }
19
+
20
+ .kui-row[data-h-align="center"] {
21
+ justify-content: space-around;
22
+ }
23
+
24
+ .kui-row[data-h-align="right"] {
25
+ justify-content: flex-end;
26
+ }
27
+
28
+ .kui-row[data-h-align="full"] {
29
+ justify-content: space-between;
30
+ }
31
+
32
+ .kui-row[data-v-align="top"] {
33
+ align-items: flex-start;
34
+ align-content: flex-start;
35
+ }
36
+
37
+ .kui-row[data-v-align="middle"] {
38
+ align-items: center;
39
+ align-content: space-around;
40
+ }
41
+
42
+ .kui-row[data-v-align="bottom"] {
43
+ align-items: flex-end;
44
+ align-content: flex-end;
45
+ }
@@ -7,6 +7,7 @@
7
7
  @import "./surface-scaffold.css";
8
8
  @import "./toolbar-text.css";
9
9
  @import "./list.css";
10
+ @import "./row.css";
10
11
  @import "./list-action-row.css";
11
12
  @import "./list-item.css";
12
13
  @import "./list-header.css";
@@ -54,6 +54,19 @@ variants. `tests/browser/select-accessibility.spec.ts` verifies actual accessibl
54
54
  names, unchanged unlabeled geometry, keyboard selection, controlled rerenders,
55
55
  native hint wiring, and wide/narrow presentation in Chromium, Firefox, and WebKit.
56
56
 
57
+ The explicit `@kerfjs/ui/select/register` import also installs the canonical
58
+ Select lifecycle adapter. The latest open/close request owns animation completion
59
+ and deferred option focus. A stale close cannot hide a reopened popup after
60
+ resize; stale completion events are not emitted. Preventing `wa-show` or
61
+ `wa-hide` retains the accepted closed/open state, and removal prevents deferred
62
+ activation. Native option selection, keyboard behavior, dismissal listeners,
63
+ and popup anchor placement remain with Web Awesome. Raw `wa-select` elements
64
+ without the canonical `data-component="select"` marker are unchanged.
65
+ `tests/unit/select-lifecycle.test.ts` and `animate-select-popup.test.ts` cover
66
+ repeated and out-of-order completions, cancellation, instance isolation, and
67
+ removal. `tests/browser/select-lifecycle.spec.ts` repeats animation/resize/reopen
68
+ sequences at wide and narrow widths in Chromium, Firefox, and WebKit.
69
+
57
70
  ## ListActionRow
58
71
 
59
72
  `ListActionRow` renders a noninteractive visual root containing primary and
@@ -38,7 +38,7 @@ foreground/background contrast relationships and visible focus ring.
38
38
 
39
39
  ### Typed runtime dimensions
40
40
 
41
- Use `List` spacing shorthands for the common case: `gap="xs"`, `gap="m"`, and
41
+ Use `Row` or `List` spacing shorthands for the common case: `gap="xs"`, `gap="m"`, and
42
42
  the other `UiSpaceName` values resolve to their matching `--kui-space-*` token.
43
43
  The canonical rhythm is `none`, `2xs`, `xs`, `m`, and `l`; use `s` and `xl`
44
44
  only as deliberate exceptions.
@@ -47,19 +47,21 @@ When a value cannot be expressed by one spacing step, import the CSS-free
47
47
  `@kerfjs/ui/css-values` subpath. `px`, `rem`, `em`, and `pct` create typed
48
48
  `CssLength` values; `space` and `lengthVar` reference spacing or
49
49
  application-owned length tokens. `plus` creates a non-standalone
50
- `CssLengthExpression`, so wrap it with `calc` before passing it to `List.gap`:
50
+ `CssLengthExpression`, so wrap it with `calc` before passing it to a gap prop:
51
51
 
52
52
  ```tsx
53
53
  import { calc, pct, plus, rem, space } from "@kerfjs/ui/css-values";
54
54
  import { List } from "@kerfjs/ui/list";
55
+ import { Row } from "@kerfjs/ui/row";
55
56
 
56
57
  <List gap="xs">...</List>;
58
+ <Row hAlign="full" vAlign="middle" gap="m">...</Row>;
57
59
  <List gap={space("m")}>...</List>;
58
60
  <List gap={calc(plus(rem(0.25), pct(10)))}>...</List>;
59
61
  ```
60
62
 
61
63
  `CssValue` is the common branded base, not an arbitrary-string constructor.
62
- Raw strings such as `"0.25rem"` no longer satisfy `List.gap`; this breaking
64
+ Raw strings such as `"0.25rem"` no longer satisfy `Row.gap` or `List.gap`; this breaking
63
65
  contract lands before the 5.0 stable release so misspelled tokens and incomplete
64
66
  expressions fail during typechecking rather than in the browser.
65
67
 
@@ -141,7 +143,7 @@ an upstream component or recipe request.
141
143
  | Key/value facts — `ValueTable`, `ValueTableRow` | Read-only labels and values form a semantic definition list, optionally with a leading icon. | Do not use it for editable form fields or a row/column data grid; use native form or table semantics. | Compose typed `ValueTableRow` entries; pass `icon` when a 24px leading icon adds useful context. | Values, formatting, icon meaning, and empty/loading policy. | `@kerfjs/ui/value-table` | [Component ownership](./component-contract.md#ownership-boundaries) |
142
144
  | Indeterminate activity — `LoadingSpinner` | A Kerf surface needs compact, labeled or decorative indeterminate progress. | Do not use it for known progress; use Web Awesome `wa-progress-bar` or `wa-progress-ring`. Direct Web Awesome UI may use `wa-spinner`; do not mix spinner systems within one surface. | None; pass a label when the spinner conveys status. | Loading lifecycle and adjacent status copy. | `@kerfjs/ui/loading-spinner` | [Accessibility](./accessibility.md#shared-rules) |
143
145
  | Loading placeholder — `Skeleton` + a component's `placeholder` prop | A value or a whole component is still loading and should hold its space as a subtle, unanimated block, keeping the layout stable — an inspector or detail view rendering its real chrome with per-record values absent. | Do not use it for known progress (use `LoadingSpinner`), do not animate it, and do not hand-rebuild a component's empty state — set `placeholder` on the component instead. Prefer it over `wa-skeleton`, which the pure-Kerf primitives avoid to stay Web-Awesome-free. | Set `placeholder` on a value-bearing component (`Select`, `ListHeader`, `ListItem`, `ValueTableRow`, `SegmentedControl`, `StateBanner`, `AppTab`, `ToolbarText`, `ListActionRow`) to render skeletons in its value slots with interactivity disabled; use the standalone `Skeleton` for a custom slot. | Loading lifecycle, which slots are unknown, and announcing the loading region. | `@kerfjs/ui/skeleton` | [Accessibility](./accessibility.md#shared-rules) |
144
- | Value selection — `Select` | A controlled form, toolbar, or compact navigation value comes from a moderate or long choice list, possibly grouped, icon-bearing, icon-only when closed, or truncating. | Do not use it for commands; use a real action menu. Do not use it for a small visible choice set; use `SegmentedControl`. Prefer it over direct `wa-select`, `wa-option`, or value-like `wa-dropdown`/`wa-dropdown-item` composition. | Import `@kerfjs/ui/select/register` once; listen for standard input/change events. Use typed presentation props rather than consumer `::part()` overrides; let the parent own placement. | Controlled value, validation, choices, domain mapping, and outer placement. | `@kerfjs/ui/select` | [Web Awesome integration](../README.md#web-awesome-theme) |
146
+ | Value selection — `Select` | A controlled form, toolbar, or compact navigation value comes from a moderate or long choice list, possibly grouped, icon-bearing, icon-only when closed, or truncating. | Do not use it for commands; use a real action menu. Do not use it for a small visible choice set; use `SegmentedControl`. Prefer it over direct `wa-select`, `wa-option`, or value-like `wa-dropdown`/`wa-dropdown-item` composition. | Import `@kerfjs/ui/select/register` once for registration and current-request animation ownership; listen for standard input/change events. Do not add consumer popup timing or positioning repairs. Use typed presentation props rather than consumer `::part()` overrides; let the parent own placement. | Controlled value, validation, choices, domain mapping, and outer placement. | `@kerfjs/ui/select` | [Web Awesome integration](../README.md#web-awesome-theme) |
145
147
  | Small exclusive choice — `SegmentedControl` | A few visible choices switch a compact view or setting, with toolbar, rounded, or pill presentation. | Do not use it for tabpanel semantics; use `TabBar`. Do not use it for many choices; use `Select`. Prefer it over `wa-button-group` when the controls select one value. | Delegate its action, read `data-segment-value`, update `value`, and rerender. | Controlled value, labels, action, and persistence. | `@kerfjs/ui/segmented-control` | [SegmentedControl contract](./accessibility.md#segmentedcontrol) |
146
148
  | Structured search editor — `TokenSearchField`, `readTokenSearchField`, `placeTokenSearchCaret`, `wireTokenSearchFields` | Free text and ordered, editable, removable filter tokens share one searchbox; enable `collapsible` when an empty, unfocused field should reduce to one iconic action, standalone or in a toolbar group. | Do not use it for ordinary text entry; use a native input or Web Awesome `wa-input`. Do not use it when filters belong in separate form controls. | Read DOM-owned text on input, empty `textContent` on clear, and use `placeTokenSearchCaret` after explicit controlled focus changes. Call `wireTokenSearchFields` from `@kerfjs/ui/wire-token-search-fields` once so Enter submits without adding a line break and keyboard chip deletion restores focus plus the text-relative caret after controlled replacement. In `collapsible` mode it also manages the transient expand/collapse/focus by default (activate to reveal + focus, Escape or empty blur to collapse); bind the field's `expanded` to the signal on the returned handle (`handle.expanded(id)`) or adopt your own via `collapsible.signals`, and opt out per behavior only when the app must own it. | Parsing, suggestions, tokens, query execution, results, announcements, and — only if overriding the default — the collapsible `expanded` signal. | `@kerfjs/ui/token-search-field` | [TokenSearchField contract](./accessibility.md#tokensearchfield) |
147
149
  | Persistent inline status — `StateBanner` | A neutral, info, pop, success, warning, or danger message belongs next to the affected work; pop highlights featured or novel content without implying status. | Do not use pop as a success, warning, or danger substitute. Do not use StateBanner for a no-content screen; use `EmptyState`. Do not use it for transient confirmation; use a toast. Web Awesome `wa-callout` is the ecosystem alternative for Web Awesome-owned content. | Delegate an optional action; choose alert urgency only for attention-requiring failure. Use the optional tone-tinted `badge` for a terse count or status beside the title, not as the only expression of meaning. | State mapping, message lifetime, retry/action behavior, badge content, and copy. | `@kerfjs/ui/state-banner` | [Feedback accessibility](./accessibility.md#shared-rules) |
package/docs/layout.md CHANGED
@@ -112,12 +112,30 @@ The two relationships that get confused most are 8px vs 24px: 8px is _inside_ a
112
112
  group, 24px is _between_ major, differing regions. 16px sits between them for
113
113
  same-kind groups.
114
114
 
115
- For `List.gap`, pass these token names directly (`gap="xs"`, `gap="m"`) or use
115
+ For `Row.gap` and `List.gap`, pass these token names directly (`gap="xs"`, `gap="m"`) or use
116
116
  `space('xs')` from `@kerfjs/ui/css-values` when composing a value in JavaScript.
117
117
  Use `rem`, `em`, `px`, `pct`, `lengthVar`, and `calc(plus(...))` only when a
118
118
  named spacing relationship does not express the requirement; do not pass raw
119
119
  CSS strings.
120
120
 
121
+ ## Row and List alignment
122
+
123
+ Use `Row` for a horizontal flex layout and `List` for a vertical one. `Row`
124
+ defaults to `hAlign="left"`, `vAlign="full"`, `gap="xs"`, and no wrapping;
125
+ `List` retains its existing full-width, top-aligned defaults and zero gap.
126
+ Both components accept the same physical-axis vocabulary:
127
+
128
+ | Axis | Values and aliases | Flex behavior |
129
+ | ---------- | ------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------- |
130
+ | Horizontal | `left` / `l` / `flex-start`; `center` / `c` / `space-around`; `right` / `r` / `flex-end`; `full` / `f` / `space-between` | Distributes a Row's children; aligns a List's children across its width. |
131
+ | Vertical | `top` / `t` / `flex-start`; `middle` / `m` / `c` / `space-around`; `bottom` / `b` / `flex-end`; `full` / `f` / `space-between` | Aligns a Row's children across its height; distributes a List's children. |
132
+
133
+ Cross-axis `space-around` and `space-between` are not valid `align-items`
134
+ values. Kerf therefore maps `middle` to centered items and `full` to stretched
135
+ items, while applying the requested distribution to `align-content` when a
136
+ Row wraps. Prefer the descriptive values in application code; the short and
137
+ CSS-shaped aliases are provided for compact or migrated call sites.
138
+
121
139
  `--kui-space-s` (12px) and `--kui-space-xl` (32px) exist but are **off the
122
140
  canonical rhythm** — reach for them only as a deliberate exception, never as a
123
141
  default step. Prefer the five canonical tokens so spacing stays legible and