@brika/ui-kit 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/README.md +3 -0
  2. package/package.json +32 -0
  3. package/src/__tests__/define-brick.test.ts +125 -0
  4. package/src/__tests__/mutations.test.ts +211 -0
  5. package/src/__tests__/nodes.test.ts +1595 -0
  6. package/src/colors.ts +99 -0
  7. package/src/define-brick.ts +92 -0
  8. package/src/descriptors.ts +28 -0
  9. package/src/index.ts +154 -0
  10. package/src/jsx-dev-runtime.ts +3 -0
  11. package/src/jsx-runtime.ts +60 -0
  12. package/src/mutations.ts +79 -0
  13. package/src/nodes/_shared.ts +129 -0
  14. package/src/nodes/avatar.ts +36 -0
  15. package/src/nodes/badge.ts +29 -0
  16. package/src/nodes/box.ts +69 -0
  17. package/src/nodes/button.ts +44 -0
  18. package/src/nodes/callout.ts +23 -0
  19. package/src/nodes/chart.ts +43 -0
  20. package/src/nodes/checkbox.ts +27 -0
  21. package/src/nodes/code-block.ts +27 -0
  22. package/src/nodes/column.ts +37 -0
  23. package/src/nodes/divider.ts +25 -0
  24. package/src/nodes/grid.ts +44 -0
  25. package/src/nodes/icon.ts +28 -0
  26. package/src/nodes/image.ts +29 -0
  27. package/src/nodes/index.ts +54 -0
  28. package/src/nodes/key-value.ts +31 -0
  29. package/src/nodes/link.ts +25 -0
  30. package/src/nodes/markdown.ts +16 -0
  31. package/src/nodes/progress.ts +28 -0
  32. package/src/nodes/row.ts +37 -0
  33. package/src/nodes/section.ts +42 -0
  34. package/src/nodes/select.ts +44 -0
  35. package/src/nodes/skeleton.ts +23 -0
  36. package/src/nodes/slider.ts +40 -0
  37. package/src/nodes/spacer.ts +17 -0
  38. package/src/nodes/stat-value.ts +26 -0
  39. package/src/nodes/status.ts +20 -0
  40. package/src/nodes/table.ts +35 -0
  41. package/src/nodes/tabs.ts +52 -0
  42. package/src/nodes/text-input.ts +53 -0
  43. package/src/nodes/text.ts +66 -0
  44. package/src/nodes/toggle.ts +32 -0
  45. package/src/nodes/video.ts +24 -0
@@ -0,0 +1,29 @@
1
+ import type { ColorValue } from '../colors';
2
+ import type { ActionHandler, BaseNode } from './_shared';
3
+ import { resolveAction } from './_shared';
4
+
5
+ export interface BadgeNode extends BaseNode {
6
+ type: 'badge';
7
+ label: string;
8
+ /** Semantic variant */
9
+ variant?: 'default' | 'secondary' | 'outline' | 'success' | 'warning' | 'destructive';
10
+ /** Lucide icon name */
11
+ icon?: string;
12
+ /** Custom tint color (overrides variant) */
13
+ color?: ColorValue;
14
+ /** Action dispatched when clicked */
15
+ onPress?: string;
16
+ }
17
+
18
+ export function Badge(
19
+ props: Omit<BadgeNode, 'type' | 'onPress'> & { onPress?: ActionHandler }
20
+ ): BadgeNode {
21
+ const { onPress, ...rest } = props;
22
+ return { type: 'badge', ...rest, onPress: onPress ? resolveAction(onPress) : undefined };
23
+ }
24
+
25
+ declare module './_shared' {
26
+ interface NodeTypeMap {
27
+ badge: BadgeNode;
28
+ }
29
+ }
@@ -0,0 +1,69 @@
1
+ import type { BackgroundValue } from '../colors';
2
+ import {
3
+ type ActionHandler,
4
+ type BaseNode,
5
+ type Child,
6
+ type ComponentNode,
7
+ normalizeChildren,
8
+ resolveAction,
9
+ } from './_shared';
10
+
11
+ export interface BoxNode extends BaseNode {
12
+ type: 'box';
13
+ children: ComponentNode[];
14
+
15
+ /** CSS color, gradient, or theme token (e.g. "#ff6b35", "muted", "card") */
16
+ background?: BackgroundValue;
17
+ /** Background image URL */
18
+ backgroundImage?: string;
19
+ /** How the background image fits */
20
+ backgroundFit?: 'cover' | 'contain' | 'fill';
21
+ /** Background image anchor position */
22
+ backgroundPosition?: 'center' | 'top' | 'bottom' | 'left' | 'right';
23
+ /** Backdrop blur level (glassmorphism) */
24
+ blur?: 'sm' | 'md' | 'lg';
25
+ /** Background layer opacity (0-1), useful with backgroundImage + background overlay */
26
+ opacity?: number;
27
+ /** Inner padding */
28
+ padding?: 'none' | 'sm' | 'md' | 'lg';
29
+ /** Border radius */
30
+ rounded?: 'none' | 'sm' | 'md' | 'lg' | 'full';
31
+ /** Fill available space (flex-1) */
32
+ grow?: boolean;
33
+ /** Explicit width — CSS value like "50%", "200px" */
34
+ width?: string;
35
+ /** Explicit height — CSS value like "50%", "100px" */
36
+ height?: string;
37
+ /** Action dispatched when clicked */
38
+ onPress?: string;
39
+ }
40
+
41
+ export function Box(props: {
42
+ background?: BackgroundValue;
43
+ backgroundImage?: string;
44
+ backgroundFit?: 'cover' | 'contain' | 'fill';
45
+ backgroundPosition?: 'center' | 'top' | 'bottom' | 'left' | 'right';
46
+ blur?: 'sm' | 'md' | 'lg';
47
+ opacity?: number;
48
+ padding?: 'none' | 'sm' | 'md' | 'lg';
49
+ rounded?: 'none' | 'sm' | 'md' | 'lg' | 'full';
50
+ grow?: boolean;
51
+ width?: string;
52
+ height?: string;
53
+ onPress?: ActionHandler;
54
+ children?: Child | Child[];
55
+ }): BoxNode {
56
+ const { children, onPress, ...rest } = props;
57
+ return {
58
+ type: 'box',
59
+ ...rest,
60
+ onPress: onPress ? resolveAction(onPress) : undefined,
61
+ children: normalizeChildren(children),
62
+ };
63
+ }
64
+
65
+ declare module './_shared' {
66
+ interface NodeTypeMap {
67
+ box: BoxNode;
68
+ }
69
+ }
@@ -0,0 +1,44 @@
1
+ import type { ColorValue } from '../colors';
2
+ import type { ActionHandler, BaseNode } from './_shared';
3
+ import { resolveAction } from './_shared';
4
+
5
+ export interface ButtonNode extends BaseNode {
6
+ type: 'button';
7
+ label?: string;
8
+ onPress?: string;
9
+ /** When set, clicking opens this URL in a new tab instead of dispatching an action. */
10
+ url?: string;
11
+ icon?: string;
12
+ variant?: 'default' | 'secondary' | 'outline' | 'ghost' | 'destructive' | 'link';
13
+ color?: ColorValue;
14
+ /** Disable the button */
15
+ disabled?: boolean;
16
+ /** Show loading spinner */
17
+ loading?: boolean;
18
+ /** Button size */
19
+ size?: 'sm' | 'md' | 'lg';
20
+ /** Stretch to full width */
21
+ fullWidth?: boolean;
22
+ }
23
+
24
+ export function Button(props: {
25
+ label?: string;
26
+ onPress?: ActionHandler;
27
+ url?: string;
28
+ icon?: string;
29
+ variant?: 'default' | 'secondary' | 'outline' | 'ghost' | 'destructive' | 'link';
30
+ color?: ColorValue;
31
+ disabled?: boolean;
32
+ loading?: boolean;
33
+ size?: 'sm' | 'md' | 'lg';
34
+ fullWidth?: boolean;
35
+ }): ButtonNode {
36
+ const { onPress, ...rest } = props;
37
+ return { type: 'button', ...rest, onPress: onPress ? resolveAction(onPress) : undefined };
38
+ }
39
+
40
+ declare module './_shared' {
41
+ interface NodeTypeMap {
42
+ button: ButtonNode;
43
+ }
44
+ }
@@ -0,0 +1,23 @@
1
+ import type { BaseNode } from './_shared';
2
+
3
+ export interface CalloutNode extends BaseNode {
4
+ type: 'callout';
5
+ /** Semantic variant controlling color and icon */
6
+ variant: 'info' | 'warning' | 'error' | 'success';
7
+ /** Main message text */
8
+ message: string;
9
+ /** Optional title */
10
+ title?: string;
11
+ /** Override the default icon (Lucide icon name) */
12
+ icon?: string;
13
+ }
14
+
15
+ export function Callout(props: Omit<CalloutNode, 'type'>): CalloutNode {
16
+ return { type: 'callout', ...props };
17
+ }
18
+
19
+ declare module './_shared' {
20
+ interface NodeTypeMap {
21
+ callout: CalloutNode;
22
+ }
23
+ }
@@ -0,0 +1,43 @@
1
+ import type { ColorValue } from '../colors';
2
+ import type { BaseNode } from './_shared';
3
+
4
+ export interface ChartDataPoint {
5
+ ts: number;
6
+ value: number;
7
+ }
8
+
9
+ export interface ChartSeries {
10
+ key: string;
11
+ label?: string;
12
+ data: ChartDataPoint[];
13
+ color?: ColorValue;
14
+ }
15
+
16
+ export interface ChartNode extends BaseNode {
17
+ type: 'chart';
18
+ variant: 'line' | 'area' | 'bar';
19
+ data: ChartDataPoint[];
20
+ color?: ColorValue;
21
+ label?: string;
22
+ height?: number;
23
+ /** Multi-series data — when present, overrides data and color */
24
+ series?: ChartSeries[];
25
+ /** Show X-axis labels */
26
+ showXAxis?: boolean;
27
+ /** Show Y-axis labels */
28
+ showYAxis?: boolean;
29
+ /** Show grid lines */
30
+ showGrid?: boolean;
31
+ /** Show legend for multi-series */
32
+ showLegend?: boolean;
33
+ }
34
+
35
+ export function Chart(props: Omit<ChartNode, 'type'>): ChartNode {
36
+ return { type: 'chart', ...props };
37
+ }
38
+
39
+ declare module './_shared' {
40
+ interface NodeTypeMap {
41
+ chart: ChartNode;
42
+ }
43
+ }
@@ -0,0 +1,27 @@
1
+ import { type ActionHandler, type BaseNode, resolveAction } from './_shared';
2
+
3
+ export interface CheckboxNode extends BaseNode {
4
+ type: 'checkbox';
5
+ label: string;
6
+ checked: boolean;
7
+ /** Action dispatched when toggled */
8
+ onToggle: string;
9
+ /** Optional description below the label */
10
+ description?: string;
11
+ /** Lucide icon name */
12
+ icon?: string;
13
+ disabled?: boolean;
14
+ }
15
+
16
+ export function Checkbox(
17
+ props: Omit<CheckboxNode, 'type' | 'onToggle'> & { onToggle: ActionHandler }
18
+ ): CheckboxNode {
19
+ const { onToggle, ...rest } = props;
20
+ return { type: 'checkbox', ...rest, onToggle: resolveAction(onToggle) };
21
+ }
22
+
23
+ declare module './_shared' {
24
+ interface NodeTypeMap {
25
+ checkbox: CheckboxNode;
26
+ }
27
+ }
@@ -0,0 +1,27 @@
1
+ import type { BaseNode } from './_shared';
2
+
3
+ export interface CodeBlockNode extends BaseNode {
4
+ type: 'code-block';
5
+ /** Code content */
6
+ code: string;
7
+ /** Programming language for syntax highlighting */
8
+ language?: string;
9
+ /** Show line numbers */
10
+ showLineNumbers?: boolean;
11
+ /** Max visible lines before scroll */
12
+ maxLines?: number;
13
+ /** Show copy button */
14
+ copyable?: boolean;
15
+ /** Optional label/filename above the block */
16
+ label?: string;
17
+ }
18
+
19
+ export function CodeBlock(props: Omit<CodeBlockNode, 'type'>): CodeBlockNode {
20
+ return { type: 'code-block', ...props };
21
+ }
22
+
23
+ declare module './_shared' {
24
+ interface NodeTypeMap {
25
+ 'code-block': CodeBlockNode;
26
+ }
27
+ }
@@ -0,0 +1,37 @@
1
+ import {
2
+ type ActionHandler,
3
+ type BaseNode,
4
+ type Child,
5
+ type ComponentNode,
6
+ type FlexLayoutProps,
7
+ normalizeChildren,
8
+ resolveAction,
9
+ } from './_shared';
10
+
11
+ export interface ColumnNode extends BaseNode, FlexLayoutProps {
12
+ type: 'column';
13
+ children: ComponentNode[];
14
+ /** Action dispatched when clicked */
15
+ onPress?: string;
16
+ }
17
+
18
+ export function Column(
19
+ props: FlexLayoutProps & {
20
+ onPress?: ActionHandler;
21
+ children?: Child | Child[];
22
+ }
23
+ ): ColumnNode {
24
+ const { children, onPress, ...rest } = props;
25
+ return {
26
+ type: 'column',
27
+ ...rest,
28
+ onPress: onPress ? resolveAction(onPress) : undefined,
29
+ children: normalizeChildren(children),
30
+ };
31
+ }
32
+
33
+ declare module './_shared' {
34
+ interface NodeTypeMap {
35
+ column: ColumnNode;
36
+ }
37
+ }
@@ -0,0 +1,25 @@
1
+ import type { BaseNode } from './_shared';
2
+
3
+ export interface DividerNode extends BaseNode {
4
+ type: 'divider';
5
+ /** Line direction (default: horizontal) */
6
+ direction?: 'horizontal' | 'vertical';
7
+ /** Custom color (default: border/50) */
8
+ color?: string;
9
+ /** Optional label displayed centered within the divider */
10
+ label?: string;
11
+ }
12
+
13
+ export function Divider(props?: {
14
+ direction?: 'horizontal' | 'vertical';
15
+ color?: string;
16
+ label?: string;
17
+ }): DividerNode {
18
+ return { type: 'divider', ...props };
19
+ }
20
+
21
+ declare module './_shared' {
22
+ interface NodeTypeMap {
23
+ divider: DividerNode;
24
+ }
25
+ }
@@ -0,0 +1,44 @@
1
+ import {
2
+ type ActionHandler,
3
+ type BaseNode,
4
+ type Child,
5
+ type ComponentNode,
6
+ normalizeChildren,
7
+ resolveAction,
8
+ } from './_shared';
9
+
10
+ export interface GridNode extends BaseNode {
11
+ type: 'grid';
12
+ columns?: number;
13
+ children: ComponentNode[];
14
+ gap?: 'sm' | 'md' | 'lg';
15
+ /** Use auto-fit columns based on minColumnWidth */
16
+ autoFit?: boolean;
17
+ /** Minimum column width in px when autoFit is true (default: 120) */
18
+ minColumnWidth?: number;
19
+ /** Action dispatched when clicked */
20
+ onPress?: string;
21
+ }
22
+
23
+ export function Grid(props: {
24
+ columns?: number;
25
+ gap?: 'sm' | 'md' | 'lg';
26
+ autoFit?: boolean;
27
+ minColumnWidth?: number;
28
+ onPress?: ActionHandler;
29
+ children?: Child | Child[];
30
+ }): GridNode {
31
+ const { children, onPress, ...rest } = props;
32
+ return {
33
+ type: 'grid',
34
+ ...rest,
35
+ onPress: onPress ? resolveAction(onPress) : undefined,
36
+ children: normalizeChildren(children),
37
+ };
38
+ }
39
+
40
+ declare module './_shared' {
41
+ interface NodeTypeMap {
42
+ grid: GridNode;
43
+ }
44
+ }
@@ -0,0 +1,28 @@
1
+ import type { ColorValue } from '../colors';
2
+ import type { ActionHandler, BaseNode } from './_shared';
3
+ import { resolveAction } from './_shared';
4
+
5
+ export interface IconNode extends BaseNode {
6
+ type: 'icon';
7
+ /** Lucide icon name */
8
+ name: string;
9
+ /** Display size */
10
+ size?: 'sm' | 'md' | 'lg';
11
+ /** Icon color */
12
+ color?: ColorValue;
13
+ /** Action dispatched when clicked */
14
+ onPress?: string;
15
+ }
16
+
17
+ export function Icon(
18
+ props: Omit<IconNode, 'type' | 'onPress'> & { onPress?: ActionHandler }
19
+ ): IconNode {
20
+ const { onPress, ...rest } = props;
21
+ return { type: 'icon', ...rest, onPress: onPress ? resolveAction(onPress) : undefined };
22
+ }
23
+
24
+ declare module './_shared' {
25
+ interface NodeTypeMap {
26
+ icon: IconNode;
27
+ }
28
+ }
@@ -0,0 +1,29 @@
1
+ import { type ActionHandler, type BaseNode, resolveAction } from './_shared';
2
+
3
+ export interface ImageNode extends BaseNode {
4
+ type: 'image';
5
+ src: string;
6
+ alt?: string;
7
+ /** px number or CSS string like "30%" */
8
+ width?: number | string;
9
+ height?: number | string;
10
+ fit?: 'cover' | 'contain' | 'fill';
11
+ rounded?: boolean;
12
+ aspectRatio?: string;
13
+ caption?: string;
14
+ /** Action dispatched when clicked */
15
+ onPress?: string;
16
+ }
17
+
18
+ export function Image(
19
+ props: Omit<ImageNode, 'type' | 'onPress'> & { onPress?: ActionHandler }
20
+ ): ImageNode {
21
+ const { onPress, ...rest } = props;
22
+ return { type: 'image', ...rest, onPress: onPress ? resolveAction(onPress) : undefined };
23
+ }
24
+
25
+ declare module './_shared' {
26
+ interface NodeTypeMap {
27
+ image: ImageNode;
28
+ }
29
+ }
@@ -0,0 +1,54 @@
1
+ // Shared types — ComponentNode and NodeTypeMap are auto-derived via declaration merging
2
+ export type {
3
+ ActionHandler,
4
+ BaseNode,
5
+ ComponentNode,
6
+ FlexLayoutProps,
7
+ I18nRef,
8
+ IntlRef,
9
+ NodeTypeMap,
10
+ TextContent,
11
+ } from './_shared';
12
+ export {
13
+ _setActionRegistrar,
14
+ type Child,
15
+ i18nRef,
16
+ intlRef,
17
+ isI18nRef,
18
+ isIntlRef,
19
+ normalizeChildren,
20
+ resolveAction,
21
+ resolveIntlRef,
22
+ } from './_shared';
23
+ export { Avatar, type AvatarNode } from './avatar';
24
+ export { Badge, type BadgeNode } from './badge';
25
+ export { Box, type BoxNode } from './box';
26
+ export { Button, type ButtonNode } from './button';
27
+ export { Callout, type CalloutNode } from './callout';
28
+ export { Chart, type ChartDataPoint, type ChartNode, type ChartSeries } from './chart';
29
+ export { Checkbox, type CheckboxNode } from './checkbox';
30
+ export { CodeBlock, type CodeBlockNode } from './code-block';
31
+ export { Column, type ColumnNode } from './column';
32
+ export { Divider, type DividerNode } from './divider';
33
+ export { Grid, type GridNode } from './grid';
34
+ export { Icon, type IconNode } from './icon';
35
+ export { Image, type ImageNode } from './image';
36
+ export { KeyValue, type KeyValueItem, type KeyValueNode } from './key-value';
37
+ export { Link, type LinkNode } from './link';
38
+ export { Markdown, type MarkdownNode } from './markdown';
39
+ export { Progress, type ProgressNode } from './progress';
40
+ // Node types + components (each file self-registers into NodeTypeMap)
41
+ export { Row, type RowNode } from './row';
42
+ export { Section, type SectionNode } from './section';
43
+ export { Select, type SelectNode, type SelectOption } from './select';
44
+ export { Skeleton, type SkeletonNode } from './skeleton';
45
+ export { Slider, type SliderNode } from './slider';
46
+ export { Spacer, type SpacerNode } from './spacer';
47
+ export { Stat, type StatValueNode } from './stat-value';
48
+ export { Status, type StatusNode } from './status';
49
+ export { Table, type TableColumn, type TableNode } from './table';
50
+ export { type TabItem, Tabs, type TabsNode } from './tabs';
51
+ export { Text, type TextNode, type TextProps } from './text';
52
+ export { TextInput, type TextInputNode } from './text-input';
53
+ export { Toggle, type ToggleNode } from './toggle';
54
+ export { Video, type VideoNode } from './video';
@@ -0,0 +1,31 @@
1
+ import type { ColorValue } from '../colors';
2
+ import type { BaseNode } from './_shared';
3
+
4
+ export interface KeyValueItem {
5
+ label: string;
6
+ value: string | number;
7
+ icon?: string;
8
+ color?: ColorValue;
9
+ copyable?: boolean;
10
+ }
11
+
12
+ export interface KeyValueNode extends BaseNode {
13
+ type: 'key-value';
14
+ items: KeyValueItem[];
15
+ /** Label/value arrangement */
16
+ layout?: 'horizontal' | 'stacked';
17
+ /** Show dividers between items */
18
+ dividers?: boolean;
19
+ /** Compact spacing */
20
+ compact?: boolean;
21
+ }
22
+
23
+ export function KeyValue(props: Omit<KeyValueNode, 'type'>): KeyValueNode {
24
+ return { type: 'key-value', ...props };
25
+ }
26
+
27
+ declare module './_shared' {
28
+ interface NodeTypeMap {
29
+ 'key-value': KeyValueNode;
30
+ }
31
+ }
@@ -0,0 +1,25 @@
1
+ import type { BaseNode } from './_shared';
2
+
3
+ export interface LinkNode extends BaseNode {
4
+ type: 'link';
5
+ /** Display text */
6
+ label: string;
7
+ /** URL to open in a new tab */
8
+ url: string;
9
+ /** Lucide icon name */
10
+ icon?: string;
11
+ /** Visual style */
12
+ variant?: 'default' | 'muted' | 'underline';
13
+ /** Font size */
14
+ size?: 'xs' | 'sm' | 'md';
15
+ }
16
+
17
+ export function Link(props: Omit<LinkNode, 'type'>): LinkNode {
18
+ return { type: 'link', ...props };
19
+ }
20
+
21
+ declare module './_shared' {
22
+ interface NodeTypeMap {
23
+ link: LinkNode;
24
+ }
25
+ }
@@ -0,0 +1,16 @@
1
+ import type { BaseNode } from './_shared';
2
+
3
+ export interface MarkdownNode extends BaseNode {
4
+ type: 'markdown';
5
+ content: string;
6
+ }
7
+
8
+ export function Markdown(props: Omit<MarkdownNode, 'type'>): MarkdownNode {
9
+ return { type: 'markdown', ...props };
10
+ }
11
+
12
+ declare module './_shared' {
13
+ interface NodeTypeMap {
14
+ markdown: MarkdownNode;
15
+ }
16
+ }
@@ -0,0 +1,28 @@
1
+ import type { ColorValue } from '../colors';
2
+ import type { BaseNode } from './_shared';
3
+
4
+ export interface ProgressNode extends BaseNode {
5
+ type: 'progress';
6
+ /** Progress value (0-100) */
7
+ value: number;
8
+ /** Optional label above the bar */
9
+ label?: string;
10
+ /** Bar color (default: primary) */
11
+ color?: ColorValue;
12
+ /** Show percentage text */
13
+ showValue?: boolean;
14
+ /** Bar thickness */
15
+ size?: 'sm' | 'md' | 'lg';
16
+ /** Visual style */
17
+ variant?: 'bar' | 'ring';
18
+ }
19
+
20
+ export function Progress(props: Omit<ProgressNode, 'type'>): ProgressNode {
21
+ return { type: 'progress', ...props };
22
+ }
23
+
24
+ declare module './_shared' {
25
+ interface NodeTypeMap {
26
+ progress: ProgressNode;
27
+ }
28
+ }
@@ -0,0 +1,37 @@
1
+ import {
2
+ type ActionHandler,
3
+ type BaseNode,
4
+ type Child,
5
+ type ComponentNode,
6
+ type FlexLayoutProps,
7
+ normalizeChildren,
8
+ resolveAction,
9
+ } from './_shared';
10
+
11
+ export interface RowNode extends BaseNode, FlexLayoutProps {
12
+ type: 'row';
13
+ children: ComponentNode[];
14
+ /** Action dispatched when clicked */
15
+ onPress?: string;
16
+ }
17
+
18
+ export function Row(
19
+ props: FlexLayoutProps & {
20
+ onPress?: ActionHandler;
21
+ children?: Child | Child[];
22
+ }
23
+ ): RowNode {
24
+ const { children, onPress, ...rest } = props;
25
+ return {
26
+ type: 'row',
27
+ ...rest,
28
+ onPress: onPress ? resolveAction(onPress) : undefined,
29
+ children: normalizeChildren(children),
30
+ };
31
+ }
32
+
33
+ declare module './_shared' {
34
+ interface NodeTypeMap {
35
+ row: RowNode;
36
+ }
37
+ }
@@ -0,0 +1,42 @@
1
+ import {
2
+ type ActionHandler,
3
+ type BaseNode,
4
+ type Child,
5
+ type ComponentNode,
6
+ normalizeChildren,
7
+ resolveAction,
8
+ } from './_shared';
9
+
10
+ export interface SectionNode extends BaseNode {
11
+ type: 'section';
12
+ title: string;
13
+ children: ComponentNode[];
14
+ /** Action dispatched when clicked */
15
+ onPress?: string;
16
+ /** Gap between children */
17
+ gap?: 'sm' | 'md' | 'lg';
18
+ /** Lucide icon name shown before the title */
19
+ icon?: string;
20
+ }
21
+
22
+ export function Section(props: {
23
+ title: string;
24
+ onPress?: ActionHandler;
25
+ gap?: 'sm' | 'md' | 'lg';
26
+ icon?: string;
27
+ children?: Child | Child[];
28
+ }): SectionNode {
29
+ const { children, onPress, ...rest } = props;
30
+ return {
31
+ type: 'section',
32
+ ...rest,
33
+ onPress: onPress ? resolveAction(onPress) : undefined,
34
+ children: normalizeChildren(children),
35
+ };
36
+ }
37
+
38
+ declare module './_shared' {
39
+ interface NodeTypeMap {
40
+ section: SectionNode;
41
+ }
42
+ }