@thewhateverapp/tile-sdk 0.13.31 → 0.13.33
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/react/index.d.ts.map +1 -1
- package/dist/react/index.js +1 -0
- package/dist/spec/host/OverlayHost.d.ts +68 -0
- package/dist/spec/host/OverlayHost.d.ts.map +1 -0
- package/dist/spec/host/OverlayHost.js +143 -0
- package/dist/spec/host/index.d.ts +7 -0
- package/dist/spec/host/index.d.ts.map +1 -0
- package/dist/spec/host/index.js +6 -0
- package/dist/spec/index.d.ts +29 -0
- package/dist/spec/index.d.ts.map +1 -0
- package/dist/spec/index.js +81 -0
- package/dist/spec/registry/ComponentRegistry.d.ts +208 -0
- package/dist/spec/registry/ComponentRegistry.d.ts.map +1 -0
- package/dist/spec/registry/ComponentRegistry.js +227 -0
- package/dist/spec/registry/composites/BottomSheet.d.ts +33 -0
- package/dist/spec/registry/composites/BottomSheet.d.ts.map +1 -0
- package/dist/spec/registry/composites/BottomSheet.js +98 -0
- package/dist/spec/registry/composites/CountdownCTA.d.ts +35 -0
- package/dist/spec/registry/composites/CountdownCTA.d.ts.map +1 -0
- package/dist/spec/registry/composites/CountdownCTA.js +91 -0
- package/dist/spec/registry/composites/Poll.d.ts +39 -0
- package/dist/spec/registry/composites/Poll.d.ts.map +1 -0
- package/dist/spec/registry/composites/Poll.js +76 -0
- package/dist/spec/registry/composites/Prediction.d.ts +37 -0
- package/dist/spec/registry/composites/Prediction.d.ts.map +1 -0
- package/dist/spec/registry/composites/Prediction.js +116 -0
- package/dist/spec/registry/composites/index.d.ts +33 -0
- package/dist/spec/registry/composites/index.d.ts.map +1 -0
- package/dist/spec/registry/composites/index.js +36 -0
- package/dist/spec/registry/index.d.ts +15 -0
- package/dist/spec/registry/index.d.ts.map +1 -0
- package/dist/spec/registry/index.js +24 -0
- package/dist/spec/registry/primitives/Button.d.ts +30 -0
- package/dist/spec/registry/primitives/Button.d.ts.map +1 -0
- package/dist/spec/registry/primitives/Button.js +62 -0
- package/dist/spec/registry/primitives/Divider.d.ts +22 -0
- package/dist/spec/registry/primitives/Divider.d.ts.map +1 -0
- package/dist/spec/registry/primitives/Divider.js +56 -0
- package/dist/spec/registry/primitives/Image.d.ts +27 -0
- package/dist/spec/registry/primitives/Image.d.ts.map +1 -0
- package/dist/spec/registry/primitives/Image.js +36 -0
- package/dist/spec/registry/primitives/ProgressBar.d.ts +28 -0
- package/dist/spec/registry/primitives/ProgressBar.d.ts.map +1 -0
- package/dist/spec/registry/primitives/ProgressBar.js +50 -0
- package/dist/spec/registry/primitives/Row.d.ts +26 -0
- package/dist/spec/registry/primitives/Row.d.ts.map +1 -0
- package/dist/spec/registry/primitives/Row.js +50 -0
- package/dist/spec/registry/primitives/Spacer.d.ts +18 -0
- package/dist/spec/registry/primitives/Spacer.d.ts.map +1 -0
- package/dist/spec/registry/primitives/Spacer.js +25 -0
- package/dist/spec/registry/primitives/Stack.d.ts +22 -0
- package/dist/spec/registry/primitives/Stack.d.ts.map +1 -0
- package/dist/spec/registry/primitives/Stack.js +41 -0
- package/dist/spec/registry/primitives/Text.d.ts +26 -0
- package/dist/spec/registry/primitives/Text.d.ts.map +1 -0
- package/dist/spec/registry/primitives/Text.js +33 -0
- package/dist/spec/registry/primitives/index.d.ts +45 -0
- package/dist/spec/registry/primitives/index.d.ts.map +1 -0
- package/dist/spec/registry/primitives/index.js +55 -0
- package/dist/spec/renderer/BindingResolver.d.ts +35 -0
- package/dist/spec/renderer/BindingResolver.d.ts.map +1 -0
- package/dist/spec/renderer/BindingResolver.js +131 -0
- package/dist/spec/renderer/CaptionTrack.d.ts +22 -0
- package/dist/spec/renderer/CaptionTrack.d.ts.map +1 -0
- package/dist/spec/renderer/CaptionTrack.js +83 -0
- package/dist/spec/renderer/LayoutRenderer.d.ts +24 -0
- package/dist/spec/renderer/LayoutRenderer.d.ts.map +1 -0
- package/dist/spec/renderer/LayoutRenderer.js +66 -0
- package/dist/spec/renderer/OverlayCue.d.ts +20 -0
- package/dist/spec/renderer/OverlayCue.d.ts.map +1 -0
- package/dist/spec/renderer/OverlayCue.js +161 -0
- package/dist/spec/renderer/index.d.ts +10 -0
- package/dist/spec/renderer/index.d.ts.map +1 -0
- package/dist/spec/renderer/index.js +13 -0
- package/dist/spec/runtime/ActionRouter.d.ts +33 -0
- package/dist/spec/runtime/ActionRouter.d.ts.map +1 -0
- package/dist/spec/runtime/ActionRouter.js +84 -0
- package/dist/spec/runtime/OverlayRuntime.d.ts +84 -0
- package/dist/spec/runtime/OverlayRuntime.d.ts.map +1 -0
- package/dist/spec/runtime/OverlayRuntime.js +216 -0
- package/dist/spec/runtime/StateManager.d.ts +31 -0
- package/dist/spec/runtime/StateManager.d.ts.map +1 -0
- package/dist/spec/runtime/StateManager.js +60 -0
- package/dist/spec/runtime/TimeSync.d.ts +47 -0
- package/dist/spec/runtime/TimeSync.d.ts.map +1 -0
- package/dist/spec/runtime/TimeSync.js +140 -0
- package/dist/spec/runtime/index.d.ts +10 -0
- package/dist/spec/runtime/index.d.ts.map +1 -0
- package/dist/spec/runtime/index.js +13 -0
- package/dist/spec/schema.d.ts +889 -0
- package/dist/spec/schema.d.ts.map +1 -0
- package/dist/spec/schema.js +284 -0
- package/dist/spec/theme/ThemeProvider.d.ts +151 -0
- package/dist/spec/theme/ThemeProvider.d.ts.map +1 -0
- package/dist/spec/theme/ThemeProvider.js +227 -0
- package/dist/spec/theme/index.d.ts +7 -0
- package/dist/spec/theme/index.d.ts.map +1 -0
- package/dist/spec/theme/index.js +12 -0
- package/dist/spec/types.d.ts +322 -0
- package/dist/spec/types.d.ts.map +1 -0
- package/dist/spec/types.js +36 -0
- package/package.json +8 -1
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Spacer Component
|
|
3
|
+
*
|
|
4
|
+
* Flexible spacer for layout control.
|
|
5
|
+
*/
|
|
6
|
+
import type { RegistryComponentProps } from '../ComponentRegistry';
|
|
7
|
+
import type { Size } from '../../types';
|
|
8
|
+
export interface SpacerProps extends RegistryComponentProps {
|
|
9
|
+
/** Fixed size (overrides flex) */
|
|
10
|
+
size?: Size | number;
|
|
11
|
+
/** Use flexible space */
|
|
12
|
+
flex?: boolean;
|
|
13
|
+
/** Additional CSS classes */
|
|
14
|
+
className?: string;
|
|
15
|
+
}
|
|
16
|
+
export declare function Spacer({ size, flex, className }: SpacerProps): JSX.Element;
|
|
17
|
+
export default Spacer;
|
|
18
|
+
//# sourceMappingURL=Spacer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Spacer.d.ts","sourceRoot":"","sources":["../../../../src/spec/registry/primitives/Spacer.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AACnE,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAExC,MAAM,WAAW,WAAY,SAAQ,sBAAsB;IACzD,kCAAkC;IAClC,IAAI,CAAC,EAAE,IAAI,GAAG,MAAM,CAAC;IAErB,yBAAyB;IACzB,IAAI,CAAC,EAAE,OAAO,CAAC;IAEf,6BAA6B;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAWD,wBAAgB,MAAM,CAAC,EAAE,IAAI,EAAE,IAAY,EAAE,SAAc,EAAE,EAAE,WAAW,GAAG,GAAG,CAAC,OAAO,CAiBvF;AAED,eAAe,MAAM,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Spacer Component
|
|
3
|
+
*
|
|
4
|
+
* Flexible spacer for layout control.
|
|
5
|
+
*/
|
|
6
|
+
import React from 'react';
|
|
7
|
+
const sizeClasses = {
|
|
8
|
+
xs: 'h-1 w-1',
|
|
9
|
+
sm: 'h-2 w-2',
|
|
10
|
+
md: 'h-4 w-4',
|
|
11
|
+
lg: 'h-6 w-6',
|
|
12
|
+
xl: 'h-8 w-8',
|
|
13
|
+
'2xl': 'h-10 w-10',
|
|
14
|
+
};
|
|
15
|
+
export function Spacer({ size, flex = false, className = '' }) {
|
|
16
|
+
if (flex) {
|
|
17
|
+
return React.createElement("div", { className: `flex-1 ${className}` });
|
|
18
|
+
}
|
|
19
|
+
if (typeof size === 'number') {
|
|
20
|
+
return (React.createElement("div", { className: className, style: { width: size, height: size, minWidth: size, minHeight: size } }));
|
|
21
|
+
}
|
|
22
|
+
const sizeClass = size ? sizeClasses[size] : 'h-4 w-4';
|
|
23
|
+
return React.createElement("div", { className: `${sizeClass} ${className}` });
|
|
24
|
+
}
|
|
25
|
+
export default Spacer;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stack Component
|
|
3
|
+
*
|
|
4
|
+
* Vertical flex container with gap and alignment options.
|
|
5
|
+
*/
|
|
6
|
+
import type { RegistryComponentProps } from '../ComponentRegistry';
|
|
7
|
+
import type { Size, Align } from '../../types';
|
|
8
|
+
export interface StackProps extends RegistryComponentProps {
|
|
9
|
+
/** Gap between items */
|
|
10
|
+
gap?: Size;
|
|
11
|
+
/** Horizontal alignment */
|
|
12
|
+
align?: Align;
|
|
13
|
+
/** Padding */
|
|
14
|
+
padding?: Size;
|
|
15
|
+
/** Full width */
|
|
16
|
+
fullWidth?: boolean;
|
|
17
|
+
/** Additional CSS classes */
|
|
18
|
+
className?: string;
|
|
19
|
+
}
|
|
20
|
+
export declare function Stack({ gap, align, padding, fullWidth, className, children, }: StackProps): JSX.Element;
|
|
21
|
+
export default Stack;
|
|
22
|
+
//# sourceMappingURL=Stack.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Stack.d.ts","sourceRoot":"","sources":["../../../../src/spec/registry/primitives/Stack.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AACnE,OAAO,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAE/C,MAAM,WAAW,UAAW,SAAQ,sBAAsB;IACxD,wBAAwB;IACxB,GAAG,CAAC,EAAE,IAAI,CAAC;IAEX,2BAA2B;IAC3B,KAAK,CAAC,EAAE,KAAK,CAAC;IAEd,cAAc;IACd,OAAO,CAAC,EAAE,IAAI,CAAC;IAEf,iBAAiB;IACjB,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB,6BAA6B;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AA0BD,wBAAgB,KAAK,CAAC,EACpB,GAAU,EACV,KAAc,EACd,OAAO,EACP,SAAiB,EACjB,SAAc,EACd,QAAQ,GACT,EAAE,UAAU,GAAG,GAAG,CAAC,OAAO,CAa1B;AAED,eAAe,KAAK,CAAC"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stack Component
|
|
3
|
+
*
|
|
4
|
+
* Vertical flex container with gap and alignment options.
|
|
5
|
+
*/
|
|
6
|
+
import React from 'react';
|
|
7
|
+
const gapClasses = {
|
|
8
|
+
xs: 'gap-1',
|
|
9
|
+
sm: 'gap-2',
|
|
10
|
+
md: 'gap-4',
|
|
11
|
+
lg: 'gap-6',
|
|
12
|
+
xl: 'gap-8',
|
|
13
|
+
'2xl': 'gap-10',
|
|
14
|
+
};
|
|
15
|
+
const alignClasses = {
|
|
16
|
+
left: 'items-start',
|
|
17
|
+
center: 'items-center',
|
|
18
|
+
right: 'items-end',
|
|
19
|
+
};
|
|
20
|
+
const paddingClasses = {
|
|
21
|
+
xs: 'p-1',
|
|
22
|
+
sm: 'p-2',
|
|
23
|
+
md: 'p-4',
|
|
24
|
+
lg: 'p-6',
|
|
25
|
+
xl: 'p-8',
|
|
26
|
+
'2xl': 'p-10',
|
|
27
|
+
};
|
|
28
|
+
export function Stack({ gap = 'md', align = 'left', padding, fullWidth = false, className = '', children, }) {
|
|
29
|
+
const classes = [
|
|
30
|
+
'flex flex-col',
|
|
31
|
+
gapClasses[gap],
|
|
32
|
+
alignClasses[align],
|
|
33
|
+
padding ? paddingClasses[padding] : '',
|
|
34
|
+
fullWidth ? 'w-full' : '',
|
|
35
|
+
className,
|
|
36
|
+
]
|
|
37
|
+
.filter(Boolean)
|
|
38
|
+
.join(' ');
|
|
39
|
+
return React.createElement("div", { className: classes }, children);
|
|
40
|
+
}
|
|
41
|
+
export default Stack;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Text Component
|
|
3
|
+
*
|
|
4
|
+
* Renders text with design token-based styling.
|
|
5
|
+
*/
|
|
6
|
+
import type { RegistryComponentProps } from '../ComponentRegistry';
|
|
7
|
+
import type { Size, Weight, Color, Align } from '../../types';
|
|
8
|
+
export interface TextProps extends RegistryComponentProps {
|
|
9
|
+
/** Text content (or use children) */
|
|
10
|
+
text?: string;
|
|
11
|
+
/** Text size */
|
|
12
|
+
size?: Size;
|
|
13
|
+
/** Font weight */
|
|
14
|
+
weight?: Weight;
|
|
15
|
+
/** Text color */
|
|
16
|
+
color?: Color;
|
|
17
|
+
/** Text alignment */
|
|
18
|
+
align?: Align;
|
|
19
|
+
/** Max lines before truncation */
|
|
20
|
+
maxLines?: number;
|
|
21
|
+
/** Additional CSS classes */
|
|
22
|
+
className?: string;
|
|
23
|
+
}
|
|
24
|
+
export declare function Text({ text, size, weight, color, align, maxLines, className, children, }: TextProps): JSX.Element;
|
|
25
|
+
export default Text;
|
|
26
|
+
//# sourceMappingURL=Text.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Text.d.ts","sourceRoot":"","sources":["../../../../src/spec/registry/primitives/Text.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAEnE,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAE9D,MAAM,WAAW,SAAU,SAAQ,sBAAsB;IACvD,qCAAqC;IACrC,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd,gBAAgB;IAChB,IAAI,CAAC,EAAE,IAAI,CAAC;IAEZ,kBAAkB;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,iBAAiB;IACjB,KAAK,CAAC,EAAE,KAAK,CAAC;IAEd,qBAAqB;IACrB,KAAK,CAAC,EAAE,KAAK,CAAC;IAEd,kCAAkC;IAClC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB,6BAA6B;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAQD,wBAAgB,IAAI,CAAC,EACnB,IAAI,EACJ,IAAW,EACX,MAAiB,EACjB,KAAe,EACf,KAAc,EACd,QAAQ,EACR,SAAc,EACd,QAAQ,GACT,EAAE,SAAS,GAAG,GAAG,CAAC,OAAO,CA2BzB;AAED,eAAe,IAAI,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Text Component
|
|
3
|
+
*
|
|
4
|
+
* Renders text with design token-based styling.
|
|
5
|
+
*/
|
|
6
|
+
import React from 'react';
|
|
7
|
+
import { sizeClasses, weightClasses, colorClasses } from '../ComponentRegistry';
|
|
8
|
+
const alignClasses = {
|
|
9
|
+
left: 'text-left',
|
|
10
|
+
center: 'text-center',
|
|
11
|
+
right: 'text-right',
|
|
12
|
+
};
|
|
13
|
+
export function Text({ text, size = 'md', weight = 'normal', color = 'white', align = 'left', maxLines, className = '', children, }) {
|
|
14
|
+
const content = text ?? children;
|
|
15
|
+
const classes = [
|
|
16
|
+
sizeClasses[size],
|
|
17
|
+
weightClasses[weight],
|
|
18
|
+
colorClasses[color],
|
|
19
|
+
alignClasses[align],
|
|
20
|
+
className,
|
|
21
|
+
]
|
|
22
|
+
.filter(Boolean)
|
|
23
|
+
.join(' ');
|
|
24
|
+
const style = {};
|
|
25
|
+
if (maxLines) {
|
|
26
|
+
style.display = '-webkit-box';
|
|
27
|
+
style.WebkitLineClamp = maxLines;
|
|
28
|
+
style.WebkitBoxOrient = 'vertical';
|
|
29
|
+
style.overflow = 'hidden';
|
|
30
|
+
}
|
|
31
|
+
return (React.createElement("span", { className: classes, style: style }, content));
|
|
32
|
+
}
|
|
33
|
+
export default Text;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Primitive Components Index
|
|
3
|
+
*
|
|
4
|
+
* Exports all primitive components and registers them with the global registry.
|
|
5
|
+
*/
|
|
6
|
+
import { type TextProps } from './Text';
|
|
7
|
+
import { type ButtonProps } from './Button';
|
|
8
|
+
import { type StackProps } from './Stack';
|
|
9
|
+
import { type RowProps } from './Row';
|
|
10
|
+
import { type ImageProps } from './Image';
|
|
11
|
+
import { type ProgressBarProps } from './ProgressBar';
|
|
12
|
+
import { type SpacerProps } from './Spacer';
|
|
13
|
+
import { type DividerProps } from './Divider';
|
|
14
|
+
export { Text, type TextProps } from './Text';
|
|
15
|
+
export { Button, type ButtonProps } from './Button';
|
|
16
|
+
export { Stack, type StackProps } from './Stack';
|
|
17
|
+
export { Row, type RowProps } from './Row';
|
|
18
|
+
export { Image, type ImageProps } from './Image';
|
|
19
|
+
export { ProgressBar, type ProgressBarProps } from './ProgressBar';
|
|
20
|
+
export { Spacer, type SpacerProps } from './Spacer';
|
|
21
|
+
export { Divider, type DividerProps } from './Divider';
|
|
22
|
+
/**
|
|
23
|
+
* Register all primitive components with the global registry.
|
|
24
|
+
* This function should be called once at app initialization.
|
|
25
|
+
*/
|
|
26
|
+
export declare function registerPrimitives(): void;
|
|
27
|
+
/**
|
|
28
|
+
* Component type to props mapping for type safety
|
|
29
|
+
*/
|
|
30
|
+
export interface PrimitivePropsMap {
|
|
31
|
+
'ui.text': TextProps;
|
|
32
|
+
'ui.button': ButtonProps;
|
|
33
|
+
'ui.stack': StackProps;
|
|
34
|
+
'ui.row': RowProps;
|
|
35
|
+
'ui.image': ImageProps;
|
|
36
|
+
'ui.progress': ProgressBarProps;
|
|
37
|
+
'ui.spacer': SpacerProps;
|
|
38
|
+
'ui.divider': DividerProps;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* All primitive component type IDs
|
|
42
|
+
*/
|
|
43
|
+
export declare const PRIMITIVE_TYPES: readonly ["ui.text", "ui.button", "ui.stack", "ui.row", "ui.image", "ui.progress", "ui.spacer", "ui.divider"];
|
|
44
|
+
export type PrimitiveType = (typeof PRIMITIVE_TYPES)[number];
|
|
45
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/spec/registry/primitives/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,OAAO,EAAQ,KAAK,SAAS,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAU,KAAK,WAAW,EAAE,MAAM,UAAU,CAAC;AACpD,OAAO,EAAS,KAAK,UAAU,EAAE,MAAM,SAAS,CAAC;AACjD,OAAO,EAAO,KAAK,QAAQ,EAAE,MAAM,OAAO,CAAC;AAC3C,OAAO,EAAS,KAAK,UAAU,EAAE,MAAM,SAAS,CAAC;AACjD,OAAO,EAAe,KAAK,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACnE,OAAO,EAAU,KAAK,WAAW,EAAE,MAAM,UAAU,CAAC;AACpD,OAAO,EAAW,KAAK,YAAY,EAAE,MAAM,WAAW,CAAC;AAGvD,OAAO,EAAE,IAAI,EAAE,KAAK,SAAS,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,MAAM,EAAE,KAAK,WAAW,EAAE,MAAM,UAAU,CAAC;AACpD,OAAO,EAAE,KAAK,EAAE,KAAK,UAAU,EAAE,MAAM,SAAS,CAAC;AACjD,OAAO,EAAE,GAAG,EAAE,KAAK,QAAQ,EAAE,MAAM,OAAO,CAAC;AAC3C,OAAO,EAAE,KAAK,EAAE,KAAK,UAAU,EAAE,MAAM,SAAS,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACnE,OAAO,EAAE,MAAM,EAAE,KAAK,WAAW,EAAE,MAAM,UAAU,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,WAAW,CAAC;AAEvD;;;GAGG;AACH,wBAAgB,kBAAkB,IAAI,IAAI,CAgBzC;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,SAAS,CAAC;IACrB,WAAW,EAAE,WAAW,CAAC;IACzB,UAAU,EAAE,UAAU,CAAC;IACvB,QAAQ,EAAE,QAAQ,CAAC;IACnB,UAAU,EAAE,UAAU,CAAC;IACvB,aAAa,EAAE,gBAAgB,CAAC;IAChC,WAAW,EAAE,WAAW,CAAC;IACzB,YAAY,EAAE,YAAY,CAAC;CAC5B;AAED;;GAEG;AACH,eAAO,MAAM,eAAe,+GASlB,CAAC;AAEX,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Primitive Components Index
|
|
3
|
+
*
|
|
4
|
+
* Exports all primitive components and registers them with the global registry.
|
|
5
|
+
*/
|
|
6
|
+
import { registerComponent } from '../ComponentRegistry';
|
|
7
|
+
// Import all primitives
|
|
8
|
+
import { Text } from './Text';
|
|
9
|
+
import { Button } from './Button';
|
|
10
|
+
import { Stack } from './Stack';
|
|
11
|
+
import { Row } from './Row';
|
|
12
|
+
import { Image } from './Image';
|
|
13
|
+
import { ProgressBar } from './ProgressBar';
|
|
14
|
+
import { Spacer } from './Spacer';
|
|
15
|
+
import { Divider } from './Divider';
|
|
16
|
+
// Re-export components
|
|
17
|
+
export { Text } from './Text';
|
|
18
|
+
export { Button } from './Button';
|
|
19
|
+
export { Stack } from './Stack';
|
|
20
|
+
export { Row } from './Row';
|
|
21
|
+
export { Image } from './Image';
|
|
22
|
+
export { ProgressBar } from './ProgressBar';
|
|
23
|
+
export { Spacer } from './Spacer';
|
|
24
|
+
export { Divider } from './Divider';
|
|
25
|
+
/**
|
|
26
|
+
* Register all primitive components with the global registry.
|
|
27
|
+
* This function should be called once at app initialization.
|
|
28
|
+
*/
|
|
29
|
+
export function registerPrimitives() {
|
|
30
|
+
// Layout primitives
|
|
31
|
+
registerComponent('ui.stack', Stack);
|
|
32
|
+
registerComponent('ui.row', Row);
|
|
33
|
+
registerComponent('ui.spacer', Spacer);
|
|
34
|
+
registerComponent('ui.divider', Divider);
|
|
35
|
+
// Content primitives
|
|
36
|
+
registerComponent('ui.text', Text);
|
|
37
|
+
registerComponent('ui.image', Image);
|
|
38
|
+
// Interactive primitives
|
|
39
|
+
registerComponent('ui.button', Button);
|
|
40
|
+
// Feedback primitives
|
|
41
|
+
registerComponent('ui.progress', ProgressBar);
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* All primitive component type IDs
|
|
45
|
+
*/
|
|
46
|
+
export const PRIMITIVE_TYPES = [
|
|
47
|
+
'ui.text',
|
|
48
|
+
'ui.button',
|
|
49
|
+
'ui.stack',
|
|
50
|
+
'ui.row',
|
|
51
|
+
'ui.image',
|
|
52
|
+
'ui.progress',
|
|
53
|
+
'ui.spacer',
|
|
54
|
+
'ui.divider',
|
|
55
|
+
];
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BindingResolver
|
|
3
|
+
*
|
|
4
|
+
* Resolves data bindings in spec props.
|
|
5
|
+
*/
|
|
6
|
+
import type { Binding, PropValue, Action } from '../types';
|
|
7
|
+
export interface BindingContext {
|
|
8
|
+
/** Local state */
|
|
9
|
+
local: Record<string, unknown>;
|
|
10
|
+
/** Host-provided data */
|
|
11
|
+
data: Record<string, unknown>;
|
|
12
|
+
/** User context */
|
|
13
|
+
ctx: Record<string, unknown>;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Resolves a binding path to its value.
|
|
17
|
+
*/
|
|
18
|
+
export declare function resolveBindingPath(path: string, context: BindingContext): unknown;
|
|
19
|
+
/**
|
|
20
|
+
* Resolves a single binding to its value.
|
|
21
|
+
*/
|
|
22
|
+
export declare function resolveBinding(binding: Binding, context: BindingContext): unknown;
|
|
23
|
+
/**
|
|
24
|
+
* Resolves all bindings in a props object.
|
|
25
|
+
*/
|
|
26
|
+
export declare function resolveProps(props: Record<string, PropValue> | undefined, context: BindingContext, actionHandler?: (action: Action) => void): Record<string, unknown>;
|
|
27
|
+
/**
|
|
28
|
+
* Resolves a single prop value.
|
|
29
|
+
*/
|
|
30
|
+
export declare function resolvePropValue(value: PropValue, context: BindingContext, actionHandler?: (action: Action) => void): unknown;
|
|
31
|
+
/**
|
|
32
|
+
* Creates a binding context from runtime values.
|
|
33
|
+
*/
|
|
34
|
+
export declare function createBindingContext(local: Record<string, unknown>, data: Record<string, unknown>, ctx: Record<string, unknown>): BindingContext;
|
|
35
|
+
//# sourceMappingURL=BindingResolver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BindingResolver.d.ts","sourceRoot":"","sources":["../../../src/spec/renderer/BindingResolver.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAG3D,MAAM,WAAW,cAAc;IAC7B,kBAAkB;IAClB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAE/B,yBAAyB;IACzB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAE9B,mBAAmB;IACnB,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC9B;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,OAAO,CAmBjF;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,cAAc,GAAG,OAAO,CAcjF;AAmDD;;GAEG;AACH,wBAAgB,YAAY,CAC1B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,SAAS,EAC5C,OAAO,EAAE,cAAc,EACvB,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,GACvC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAYzB;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,SAAS,EAChB,OAAO,EAAE,cAAc,EACvB,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,GACvC,OAAO,CA+BT;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC3B,cAAc,CAEhB"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BindingResolver
|
|
3
|
+
*
|
|
4
|
+
* Resolves data bindings in spec props.
|
|
5
|
+
*/
|
|
6
|
+
import { isBinding, isAction } from '../types';
|
|
7
|
+
/**
|
|
8
|
+
* Resolves a binding path to its value.
|
|
9
|
+
*/
|
|
10
|
+
export function resolveBindingPath(path, context) {
|
|
11
|
+
const parts = path.split('.');
|
|
12
|
+
const scope = parts[0];
|
|
13
|
+
const rest = parts.slice(1);
|
|
14
|
+
const scopeData = context[scope];
|
|
15
|
+
if (scopeData === undefined) {
|
|
16
|
+
return undefined;
|
|
17
|
+
}
|
|
18
|
+
return rest.reduce((current, key) => {
|
|
19
|
+
if (current === null || current === undefined) {
|
|
20
|
+
return undefined;
|
|
21
|
+
}
|
|
22
|
+
if (typeof current === 'object') {
|
|
23
|
+
return current[key];
|
|
24
|
+
}
|
|
25
|
+
return undefined;
|
|
26
|
+
}, scopeData);
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Resolves a single binding to its value.
|
|
30
|
+
*/
|
|
31
|
+
export function resolveBinding(binding, context) {
|
|
32
|
+
const value = resolveBindingPath(binding.$bind, context);
|
|
33
|
+
// Return fallback if value is undefined
|
|
34
|
+
if (value === undefined && binding.fallback !== undefined) {
|
|
35
|
+
return binding.fallback;
|
|
36
|
+
}
|
|
37
|
+
// Apply format if specified
|
|
38
|
+
if (value !== undefined && binding.format) {
|
|
39
|
+
return formatValue(value, binding.format);
|
|
40
|
+
}
|
|
41
|
+
return value;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Formats a value according to a format string.
|
|
45
|
+
*/
|
|
46
|
+
function formatValue(value, format) {
|
|
47
|
+
switch (format) {
|
|
48
|
+
case 'number':
|
|
49
|
+
return Number(value).toLocaleString();
|
|
50
|
+
case 'percent':
|
|
51
|
+
return `${Math.round(Number(value) * 100)}%`;
|
|
52
|
+
case 'currency':
|
|
53
|
+
return new Intl.NumberFormat('en-US', {
|
|
54
|
+
style: 'currency',
|
|
55
|
+
currency: 'USD',
|
|
56
|
+
}).format(Number(value));
|
|
57
|
+
case 'compact':
|
|
58
|
+
return new Intl.NumberFormat('en-US', {
|
|
59
|
+
notation: 'compact',
|
|
60
|
+
compactDisplay: 'short',
|
|
61
|
+
}).format(Number(value));
|
|
62
|
+
case 'date':
|
|
63
|
+
return new Date(value).toLocaleDateString();
|
|
64
|
+
case 'time':
|
|
65
|
+
return new Date(value).toLocaleTimeString();
|
|
66
|
+
case 'datetime':
|
|
67
|
+
return new Date(value).toLocaleString();
|
|
68
|
+
case 'duration': {
|
|
69
|
+
const ms = Number(value);
|
|
70
|
+
const seconds = Math.floor(ms / 1000);
|
|
71
|
+
const minutes = Math.floor(seconds / 60);
|
|
72
|
+
const hours = Math.floor(minutes / 60);
|
|
73
|
+
if (hours > 0) {
|
|
74
|
+
return `${hours}:${String(minutes % 60).padStart(2, '0')}:${String(seconds % 60).padStart(2, '0')}`;
|
|
75
|
+
}
|
|
76
|
+
return `${minutes}:${String(seconds % 60).padStart(2, '0')}`;
|
|
77
|
+
}
|
|
78
|
+
default:
|
|
79
|
+
return String(value);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Resolves all bindings in a props object.
|
|
84
|
+
*/
|
|
85
|
+
export function resolveProps(props, context, actionHandler) {
|
|
86
|
+
if (!props) {
|
|
87
|
+
return {};
|
|
88
|
+
}
|
|
89
|
+
const resolved = {};
|
|
90
|
+
for (const [key, value] of Object.entries(props)) {
|
|
91
|
+
resolved[key] = resolvePropValue(value, context, actionHandler);
|
|
92
|
+
}
|
|
93
|
+
return resolved;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Resolves a single prop value.
|
|
97
|
+
*/
|
|
98
|
+
export function resolvePropValue(value, context, actionHandler) {
|
|
99
|
+
// Handle bindings
|
|
100
|
+
if (isBinding(value)) {
|
|
101
|
+
return resolveBinding(value, context);
|
|
102
|
+
}
|
|
103
|
+
// Handle actions - convert to callback
|
|
104
|
+
if (isAction(value)) {
|
|
105
|
+
if (actionHandler) {
|
|
106
|
+
return () => actionHandler(value);
|
|
107
|
+
}
|
|
108
|
+
return undefined;
|
|
109
|
+
}
|
|
110
|
+
// Handle arrays (could contain bindings)
|
|
111
|
+
if (Array.isArray(value)) {
|
|
112
|
+
return value.map((item) => resolvePropValue(item, context, actionHandler));
|
|
113
|
+
}
|
|
114
|
+
// Handle nested objects (but not bindings/actions)
|
|
115
|
+
if (typeof value === 'object' && value !== null) {
|
|
116
|
+
const obj = value;
|
|
117
|
+
const resolved = {};
|
|
118
|
+
for (const [k, v] of Object.entries(obj)) {
|
|
119
|
+
resolved[k] = resolvePropValue(v, context, actionHandler);
|
|
120
|
+
}
|
|
121
|
+
return resolved;
|
|
122
|
+
}
|
|
123
|
+
// Return primitive values as-is
|
|
124
|
+
return value;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Creates a binding context from runtime values.
|
|
128
|
+
*/
|
|
129
|
+
export function createBindingContext(local, data, ctx) {
|
|
130
|
+
return { local, data, ctx };
|
|
131
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CaptionTrack
|
|
3
|
+
*
|
|
4
|
+
* Time-synced captions display with theme support.
|
|
5
|
+
*/
|
|
6
|
+
import type { CaptionTrack as CaptionTrackType, CaptionSegment } from '../types';
|
|
7
|
+
export interface CaptionTrackProps {
|
|
8
|
+
/** Caption track data */
|
|
9
|
+
track: CaptionTrackType;
|
|
10
|
+
/** Override styles */
|
|
11
|
+
className?: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Renders time-synced captions with theme support.
|
|
15
|
+
*/
|
|
16
|
+
export declare function CaptionTrackRenderer({ track, className }: CaptionTrackProps): JSX.Element | null;
|
|
17
|
+
/**
|
|
18
|
+
* Hook to get the current caption segment.
|
|
19
|
+
*/
|
|
20
|
+
export declare function useActiveCaption(track: CaptionTrackType | undefined): CaptionSegment | null;
|
|
21
|
+
export default CaptionTrackRenderer;
|
|
22
|
+
//# sourceMappingURL=CaptionTrack.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CaptionTrack.d.ts","sourceRoot":"","sources":["../../../src/spec/renderer/CaptionTrack.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,YAAY,IAAI,gBAAgB,EAAE,cAAc,EAAgB,MAAM,UAAU,CAAC;AAK/F,MAAM,WAAW,iBAAiB;IAChC,yBAAyB;IACzB,KAAK,EAAE,gBAAgB,CAAC;IAExB,sBAAsB;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAQD;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,EAAE,KAAK,EAAE,SAAc,EAAE,EAAE,iBAAiB,GAAG,GAAG,CAAC,OAAO,GAAG,IAAI,CAyErG;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,gBAAgB,GAAG,SAAS,GAAG,cAAc,GAAG,IAAI,CAW3F;AAED,eAAe,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CaptionTrack
|
|
3
|
+
*
|
|
4
|
+
* Time-synced captions display with theme support.
|
|
5
|
+
*/
|
|
6
|
+
import React, { useMemo } from 'react';
|
|
7
|
+
import { useOverlayRuntime } from '../runtime/OverlayRuntime';
|
|
8
|
+
import { isTimeInWindow } from '../runtime/TimeSync';
|
|
9
|
+
import { useTheme } from '../theme';
|
|
10
|
+
const positionStyles = {
|
|
11
|
+
top: { top: '1rem', left: '50%', transform: 'translateX(-50%)' },
|
|
12
|
+
center: { top: '50%', left: '50%', transform: 'translate(-50%, -50%)' },
|
|
13
|
+
bottom: { bottom: '1rem', left: '50%', transform: 'translateX(-50%)' },
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Renders time-synced captions with theme support.
|
|
17
|
+
*/
|
|
18
|
+
export function CaptionTrackRenderer({ track, className = '' }) {
|
|
19
|
+
const { time, spec } = useOverlayRuntime();
|
|
20
|
+
const theme = useTheme();
|
|
21
|
+
const toleranceMs = spec.sync?.toleranceMs ?? 100;
|
|
22
|
+
// Find active segment
|
|
23
|
+
const activeSegment = useMemo(() => {
|
|
24
|
+
return track.segments.find((segment) => isTimeInWindow(time.timeMs, segment.startMs, segment.endMs, toleranceMs));
|
|
25
|
+
}, [track.segments, time.timeMs, toleranceMs]);
|
|
26
|
+
if (!activeSegment) {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
const style = track.style ?? {};
|
|
30
|
+
const position = style.position ?? 'bottom';
|
|
31
|
+
const size = style.size ?? 'md';
|
|
32
|
+
// Get theme-aware component styles
|
|
33
|
+
const captionTheme = theme.components?.caption ?? {};
|
|
34
|
+
// Container styles
|
|
35
|
+
const containerStyle = {
|
|
36
|
+
position: 'absolute',
|
|
37
|
+
maxWidth: '90%',
|
|
38
|
+
...positionStyles[position],
|
|
39
|
+
};
|
|
40
|
+
// Background styles
|
|
41
|
+
const showBackground = style.background !== false && style.background !== 'none';
|
|
42
|
+
const bgStyle = showBackground
|
|
43
|
+
? {
|
|
44
|
+
backgroundColor: captionTheme.background ?? theme.colors.backgroundOverlay,
|
|
45
|
+
backdropFilter: captionTheme.backdropBlur !== false ? 'blur(8px)' : undefined,
|
|
46
|
+
WebkitBackdropFilter: captionTheme.backdropBlur !== false ? 'blur(8px)' : undefined,
|
|
47
|
+
borderRadius: captionTheme.borderRadius ?? theme.radius.lg,
|
|
48
|
+
padding: captionTheme.padding ?? `${theme.spacing.sm} ${theme.spacing.md}`,
|
|
49
|
+
}
|
|
50
|
+
: {};
|
|
51
|
+
// Text styles
|
|
52
|
+
const textStyle = {
|
|
53
|
+
color: style.color ?? captionTheme.textColor ?? theme.colors.foreground,
|
|
54
|
+
fontSize: theme.typography.fontSizes[size],
|
|
55
|
+
fontWeight: theme.typography.fontWeights.medium,
|
|
56
|
+
fontFamily: theme.typography.fontFamily,
|
|
57
|
+
textAlign: 'center',
|
|
58
|
+
textShadow: style.shadow !== false ? '0 2px 4px rgba(0,0,0,0.5)' : undefined,
|
|
59
|
+
};
|
|
60
|
+
// Speaker styles
|
|
61
|
+
const speakerStyle = {
|
|
62
|
+
color: captionTheme.speakerColor ?? theme.colors.foregroundMuted,
|
|
63
|
+
fontSize: theme.typography.fontSizes.sm,
|
|
64
|
+
marginBottom: theme.spacing.xs,
|
|
65
|
+
};
|
|
66
|
+
return (React.createElement("div", { style: containerStyle, className: className },
|
|
67
|
+
React.createElement("div", { style: bgStyle },
|
|
68
|
+
activeSegment.speaker && (React.createElement("div", { style: speakerStyle }, activeSegment.speaker)),
|
|
69
|
+
React.createElement("div", { style: textStyle }, activeSegment.text))));
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Hook to get the current caption segment.
|
|
73
|
+
*/
|
|
74
|
+
export function useActiveCaption(track) {
|
|
75
|
+
const { time, spec } = useOverlayRuntime();
|
|
76
|
+
const toleranceMs = spec.sync?.toleranceMs ?? 100;
|
|
77
|
+
return useMemo(() => {
|
|
78
|
+
if (!track)
|
|
79
|
+
return null;
|
|
80
|
+
return track.segments.find((segment) => isTimeInWindow(time.timeMs, segment.startMs, segment.endMs, toleranceMs)) ?? null;
|
|
81
|
+
}, [track, time.timeMs, toleranceMs]);
|
|
82
|
+
}
|
|
83
|
+
export default CaptionTrackRenderer;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LayoutRenderer
|
|
3
|
+
*
|
|
4
|
+
* Recursively renders a layout tree from spec.
|
|
5
|
+
*/
|
|
6
|
+
import type { LayoutNode } from '../types';
|
|
7
|
+
export interface LayoutRendererProps {
|
|
8
|
+
/** The layout node to render */
|
|
9
|
+
node: LayoutNode;
|
|
10
|
+
/** Optional key for React reconciliation */
|
|
11
|
+
nodeKey?: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Renders a single layout node and its children.
|
|
15
|
+
*/
|
|
16
|
+
export declare function LayoutRenderer({ node, nodeKey }: LayoutRendererProps): JSX.Element | null;
|
|
17
|
+
/**
|
|
18
|
+
* Renders a layout tree with error boundary.
|
|
19
|
+
*/
|
|
20
|
+
export declare function LayoutTree({ root }: {
|
|
21
|
+
root: LayoutNode;
|
|
22
|
+
}): JSX.Element;
|
|
23
|
+
export default LayoutRenderer;
|
|
24
|
+
//# sourceMappingURL=LayoutRenderer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LayoutRenderer.d.ts","sourceRoot":"","sources":["../../../src/spec/renderer/LayoutRenderer.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAU,MAAM,UAAU,CAAC;AAKnD,MAAM,WAAW,mBAAmB;IAClC,gCAAgC;IAChC,IAAI,EAAE,UAAU,CAAC;IAEjB,4CAA4C;IAC5C,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,mBAAmB,GAAG,GAAG,CAAC,OAAO,GAAG,IAAI,CAqDzF;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,EAAE,IAAI,EAAE,EAAE;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,GAAG,GAAG,CAAC,OAAO,CAMtE;AAyCD,eAAe,cAAc,CAAC"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LayoutRenderer
|
|
3
|
+
*
|
|
4
|
+
* Recursively renders a layout tree from spec.
|
|
5
|
+
*/
|
|
6
|
+
import React, { useMemo } from 'react';
|
|
7
|
+
import { useOverlayRuntime } from '../runtime/OverlayRuntime';
|
|
8
|
+
import { getComponent } from '../registry/ComponentRegistry';
|
|
9
|
+
import { resolveProps, createBindingContext } from './BindingResolver';
|
|
10
|
+
/**
|
|
11
|
+
* Renders a single layout node and its children.
|
|
12
|
+
*/
|
|
13
|
+
export function LayoutRenderer({ node, nodeKey }) {
|
|
14
|
+
const { state, data, ctx, executeAction } = useOverlayRuntime();
|
|
15
|
+
// Get component definition from registry
|
|
16
|
+
const componentDef = getComponent(node.type);
|
|
17
|
+
if (!componentDef) {
|
|
18
|
+
console.warn(`Unknown component type: ${node.type}`);
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
const Component = componentDef.component;
|
|
22
|
+
// Create binding context
|
|
23
|
+
const bindingContext = useMemo(() => createBindingContext(state, data, ctx), [state, data, ctx]);
|
|
24
|
+
// Action handler
|
|
25
|
+
const handleAction = useMemo(() => (action) => {
|
|
26
|
+
executeAction(action);
|
|
27
|
+
}, [executeAction]);
|
|
28
|
+
// Resolve props with bindings
|
|
29
|
+
const resolvedProps = useMemo(() => resolveProps(node.props, bindingContext, handleAction), [node.props, bindingContext, handleAction]);
|
|
30
|
+
// Render children recursively
|
|
31
|
+
const children = useMemo(() => {
|
|
32
|
+
if (!node.children || node.children.length === 0) {
|
|
33
|
+
return undefined;
|
|
34
|
+
}
|
|
35
|
+
return node.children.map((child, index) => (React.createElement(LayoutRenderer, { key: child.type + '-' + index, node: child, nodeKey: `${nodeKey || 'root'}-${index}` })));
|
|
36
|
+
}, [node.children, nodeKey]);
|
|
37
|
+
return (React.createElement(Component, { ...resolvedProps, key: nodeKey }, children));
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Renders a layout tree with error boundary.
|
|
41
|
+
*/
|
|
42
|
+
export function LayoutTree({ root }) {
|
|
43
|
+
return (React.createElement(LayoutErrorBoundary, null,
|
|
44
|
+
React.createElement(LayoutRenderer, { node: root })));
|
|
45
|
+
}
|
|
46
|
+
class LayoutErrorBoundary extends React.Component {
|
|
47
|
+
constructor(props) {
|
|
48
|
+
super(props);
|
|
49
|
+
this.state = { hasError: false };
|
|
50
|
+
}
|
|
51
|
+
static getDerivedStateFromError(error) {
|
|
52
|
+
return { hasError: true, error };
|
|
53
|
+
}
|
|
54
|
+
componentDidCatch(error, errorInfo) {
|
|
55
|
+
console.error('Layout render error:', error, errorInfo);
|
|
56
|
+
}
|
|
57
|
+
render() {
|
|
58
|
+
if (this.state.hasError) {
|
|
59
|
+
return (React.createElement("div", { className: "p-2 bg-red-500/20 rounded text-red-400 text-sm" },
|
|
60
|
+
"Render error: ",
|
|
61
|
+
this.state.error?.message));
|
|
62
|
+
}
|
|
63
|
+
return this.props.children;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
export default LayoutRenderer;
|