@intentface/ui 0.0.0 → 0.7.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.
- package/LICENSE +21 -0
- package/README.md +145 -2
- package/dist/ask-user/ask-user.d.ts +104 -0
- package/dist/ask-user/ask-user.js +245 -0
- package/dist/ask-user/index.d.ts +3 -0
- package/dist/ask-user/index.js +3 -0
- package/dist/ask-user/index.parts.d.ts +1 -0
- package/dist/ask-user/index.parts.js +5 -0
- package/dist/attachments/attachments.d.ts +73 -0
- package/dist/attachments/attachments.js +121 -0
- package/dist/attachments/index.d.ts +3 -0
- package/dist/attachments/index.js +3 -0
- package/dist/attachments/index.parts.d.ts +1 -0
- package/dist/attachments/index.parts.js +5 -0
- package/dist/chip/chip.d.ts +45 -0
- package/dist/chip/chip.js +43 -0
- package/dist/chip/index.d.ts +2 -0
- package/dist/chip/index.js +2 -0
- package/dist/chip/index.parts.d.ts +1 -0
- package/dist/chip/index.parts.js +5 -0
- package/dist/chip-markdown.d.ts +25 -0
- package/dist/chip-markdown.js +54 -0
- package/dist/composer/actions.d.ts +35 -0
- package/dist/composer/actions.js +76 -0
- package/dist/composer/ask-user-machine.d.ts +52 -0
- package/dist/composer/ask-user-machine.js +164 -0
- package/dist/composer/attachments-machine.d.ts +34 -0
- package/dist/composer/attachments-machine.js +91 -0
- package/dist/composer/attachments.d.ts +16 -0
- package/dist/composer/attachments.js +32 -0
- package/dist/composer/command-list.d.ts +49 -0
- package/dist/composer/command-list.js +360 -0
- package/dist/composer/commands.d.ts +28 -0
- package/dist/composer/commands.js +56 -0
- package/dist/composer/container.d.ts +3 -0
- package/dist/composer/container.js +32 -0
- package/dist/composer/controller.d.ts +3 -0
- package/dist/composer/controller.js +6 -0
- package/dist/composer/editor-dom.d.ts +57 -0
- package/dist/composer/editor-dom.js +517 -0
- package/dist/composer/fuzzy.d.ts +4 -0
- package/dist/composer/fuzzy.js +49 -0
- package/dist/composer/index.d.ts +25 -0
- package/dist/composer/index.js +13 -0
- package/dist/composer/index.parts.d.ts +11 -0
- package/dist/composer/index.parts.js +15 -0
- package/dist/composer/internals.d.ts +30 -0
- package/dist/composer/internals.js +102 -0
- package/dist/composer/keyboard.d.ts +61 -0
- package/dist/composer/keyboard.js +75 -0
- package/dist/composer/panel.d.ts +28 -0
- package/dist/composer/panel.js +76 -0
- package/dist/composer/placeholder.d.ts +10 -0
- package/dist/composer/placeholder.js +8 -0
- package/dist/composer/popover.d.ts +12 -0
- package/dist/composer/popover.js +62 -0
- package/dist/composer/prefix-detection.d.ts +23 -0
- package/dist/composer/prefix-detection.js +67 -0
- package/dist/composer/root.d.ts +21 -0
- package/dist/composer/root.js +124 -0
- package/dist/composer/segments.d.ts +108 -0
- package/dist/composer/segments.js +366 -0
- package/dist/composer/store.d.ts +98 -0
- package/dist/composer/store.js +457 -0
- package/dist/composer/textarea.d.ts +39 -0
- package/dist/composer/textarea.js +64 -0
- package/dist/composer/trigger-tracker.d.ts +12 -0
- package/dist/composer/trigger-tracker.js +90 -0
- package/dist/composer/types.d.ts +127 -0
- package/dist/composer/types.js +4 -0
- package/dist/composer/use-composer-editor.d.ts +43 -0
- package/dist/composer/use-composer-editor.js +653 -0
- package/dist/generative/catalog.d.ts +177 -0
- package/dist/generative/catalog.js +20 -0
- package/dist/generative/index.d.ts +26 -0
- package/dist/generative/index.js +20 -0
- package/dist/generative/json-schema.d.ts +45 -0
- package/dist/generative/json-schema.js +216 -0
- package/dist/generative/markdown.d.ts +21 -0
- package/dist/generative/markdown.js +76 -0
- package/dist/generative/tree.d.ts +56 -0
- package/dist/generative/tree.js +365 -0
- package/dist/generative/use-tree.d.ts +12 -0
- package/dist/generative/use-tree.js +64 -0
- package/dist/internal/change-event-details.d.ts +12 -0
- package/dist/internal/change-event-details.js +16 -0
- package/dist/internal/collapsible.d.ts +22 -0
- package/dist/internal/collapsible.js +94 -0
- package/dist/internal/collection.d.ts +32 -0
- package/dist/internal/collection.js +72 -0
- package/dist/internal/iso-layout-effect.d.ts +2 -0
- package/dist/internal/iso-layout-effect.js +6 -0
- package/dist/internal/portal.d.ts +6 -0
- package/dist/internal/portal.js +18 -0
- package/dist/internal/primitive-props.d.ts +4 -0
- package/dist/internal/primitive-props.js +3 -0
- package/dist/internal/render/baseTypes.d.ts +18 -0
- package/dist/internal/render/baseTypes.js +4 -0
- package/dist/internal/render/empty.d.ts +3 -0
- package/dist/internal/render/empty.js +5 -0
- package/dist/internal/render/getReactElementRef.d.ts +5 -0
- package/dist/internal/render/getReactElementRef.js +15 -0
- package/dist/internal/render/getStateAttributesProps.d.ts +4 -0
- package/dist/internal/render/getStateAttributesProps.js +23 -0
- package/dist/internal/render/mergeObjects.d.ts +1 -0
- package/dist/internal/render/mergeObjects.js +14 -0
- package/dist/internal/render/mergeProps.d.ts +55 -0
- package/dist/internal/render/mergeProps.js +183 -0
- package/dist/internal/render/positioning.d.ts +33 -0
- package/dist/internal/render/positioning.js +112 -0
- package/dist/internal/render/reactVersion.d.ts +3 -0
- package/dist/internal/render/reactVersion.js +7 -0
- package/dist/internal/render/resolveClassName.d.ts +8 -0
- package/dist/internal/render/resolveClassName.js +12 -0
- package/dist/internal/render/resolveStyle.d.ts +8 -0
- package/dist/internal/render/resolveStyle.js +12 -0
- package/dist/internal/render/transition.d.ts +47 -0
- package/dist/internal/render/transition.js +259 -0
- package/dist/internal/render/types.d.ts +74 -0
- package/dist/internal/render/types.js +3 -0
- package/dist/internal/render/useMergedRefs.d.ts +21 -0
- package/dist/internal/render/useMergedRefs.js +102 -0
- package/dist/internal/render/useRefWithInit.d.ts +10 -0
- package/dist/internal/render/useRefWithInit.js +12 -0
- package/dist/internal/render/useRender.d.ts +71 -0
- package/dist/internal/render/useRender.js +12 -0
- package/dist/internal/render/useRenderElement.d.ts +62 -0
- package/dist/internal/render/useRenderElement.js +157 -0
- package/dist/internal/render/warn.d.ts +1 -0
- package/dist/internal/render/warn.js +15 -0
- package/dist/internal/safe-polygon.d.ts +21 -0
- package/dist/internal/safe-polygon.js +179 -0
- package/dist/internal/scroll-into-view-within.d.ts +1 -0
- package/dist/internal/scroll-into-view-within.js +26 -0
- package/dist/internal/standard-schema.d.ts +38 -0
- package/dist/internal/standard-schema.js +4 -0
- package/dist/internal/state-mappings.d.ts +8 -0
- package/dist/internal/state-mappings.js +17 -0
- package/dist/internal/use-controlled.d.ts +19 -0
- package/dist/internal/use-controlled.js +33 -0
- package/dist/message/index.d.ts +3 -0
- package/dist/message/index.js +3 -0
- package/dist/message/index.parts.d.ts +1 -0
- package/dist/message/index.parts.js +5 -0
- package/dist/message/message.d.ts +58 -0
- package/dist/message/message.js +93 -0
- package/dist/message-utils.d.ts +55 -0
- package/dist/message-utils.js +79 -0
- package/dist/nav/index.d.ts +4 -0
- package/dist/nav/index.js +5 -0
- package/dist/nav/index.parts.d.ts +3 -0
- package/dist/nav/index.parts.js +7 -0
- package/dist/nav/nav.d.ts +152 -0
- package/dist/nav/nav.js +660 -0
- package/dist/nav/store.d.ts +50 -0
- package/dist/nav/store.js +95 -0
- package/dist/reasoning/index.d.ts +3 -0
- package/dist/reasoning/index.js +3 -0
- package/dist/reasoning/index.parts.d.ts +1 -0
- package/dist/reasoning/index.parts.js +5 -0
- package/dist/reasoning/reasoning.d.ts +38 -0
- package/dist/reasoning/reasoning.js +67 -0
- package/dist/shell/index.d.ts +5 -0
- package/dist/shell/index.js +5 -0
- package/dist/shell/index.parts.d.ts +3 -0
- package/dist/shell/index.parts.js +7 -0
- package/dist/shell/shell.d.ts +108 -0
- package/dist/shell/shell.js +390 -0
- package/dist/shell/store.d.ts +112 -0
- package/dist/shell/store.js +134 -0
- package/dist/steps/index.d.ts +2 -0
- package/dist/steps/index.js +2 -0
- package/dist/steps/index.parts.d.ts +1 -0
- package/dist/steps/index.parts.js +5 -0
- package/dist/steps/steps.d.ts +90 -0
- package/dist/steps/steps.js +116 -0
- package/dist/tabs/anchored.d.ts +59 -0
- package/dist/tabs/anchored.js +109 -0
- package/dist/tabs/hover.d.ts +33 -0
- package/dist/tabs/hover.js +169 -0
- package/dist/tabs/index.d.ts +5 -0
- package/dist/tabs/index.js +4 -0
- package/dist/tabs/index.parts.d.ts +4 -0
- package/dist/tabs/index.parts.js +8 -0
- package/dist/tabs/store.d.ts +131 -0
- package/dist/tabs/store.js +248 -0
- package/dist/tabs/tabs.d.ts +217 -0
- package/dist/tabs/tabs.js +458 -0
- package/dist/thread/geometry.d.ts +23 -0
- package/dist/thread/geometry.js +48 -0
- package/dist/thread/index.d.ts +4 -0
- package/dist/thread/index.js +3 -0
- package/dist/thread/index.parts.d.ts +1 -0
- package/dist/thread/index.parts.js +5 -0
- package/dist/thread/stores.d.ts +21 -0
- package/dist/thread/stores.js +63 -0
- package/dist/thread/thread.d.ts +57 -0
- package/dist/thread/thread.js +663 -0
- package/dist/types.d.ts +58 -0
- package/dist/types.js +17 -0
- package/package.json +120 -4
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import type { ComponentRenderFn, HTMLProps } from './types.js';
|
|
3
|
+
import type { WithDataAttributes } from './baseTypes.js';
|
|
4
|
+
import { type StateAttributesMapping } from './getStateAttributesProps.js';
|
|
5
|
+
type IntrinsicTagName = keyof React.JSX.IntrinsicElements;
|
|
6
|
+
/**
|
|
7
|
+
* Renders a primitive part's element.
|
|
8
|
+
*
|
|
9
|
+
* @param element The default HTML element to render. Can be overridden by the `render` prop.
|
|
10
|
+
* @param componentProps An object containing the `render` and `className` props to be used for element customization. Other props are ignored.
|
|
11
|
+
* @param params Additional parameters for rendering the element.
|
|
12
|
+
*/
|
|
13
|
+
export declare function useRenderElement<State extends Record<string, any>, RenderedElementType extends Element, TagName extends IntrinsicTagName | undefined, Enabled extends boolean | undefined = undefined>(element: TagName, componentProps: UseRenderElementComponentProps<State>, params?: UseRenderElementParameters<State, RenderedElementType, TagName, Enabled>): Enabled extends false ? null : React.ReactElement;
|
|
14
|
+
type RenderFunctionProps<TagName> = TagName extends keyof React.JSX.IntrinsicElements ? React.JSX.IntrinsicElements[TagName] : React.HTMLAttributes<any>;
|
|
15
|
+
export type UseRenderElementParameters<State, RenderedElementType extends Element, TagName, Enabled extends boolean | undefined> = {
|
|
16
|
+
/**
|
|
17
|
+
* If `false`, the hook will skip most of its internal logic and return `null`.
|
|
18
|
+
* This is useful for rendering a component conditionally.
|
|
19
|
+
* @default true
|
|
20
|
+
*/
|
|
21
|
+
enabled?: Enabled | undefined;
|
|
22
|
+
/**
|
|
23
|
+
* @deprecated
|
|
24
|
+
*/
|
|
25
|
+
propGetter?: ((externalProps: HTMLProps) => HTMLProps) | undefined;
|
|
26
|
+
/**
|
|
27
|
+
* The ref to apply to the rendered element.
|
|
28
|
+
*/
|
|
29
|
+
ref?: React.Ref<RenderedElementType> | (React.Ref<RenderedElementType> | undefined)[] | undefined;
|
|
30
|
+
/**
|
|
31
|
+
* The state of the component.
|
|
32
|
+
*/
|
|
33
|
+
state?: State | undefined;
|
|
34
|
+
/**
|
|
35
|
+
* Intrinsic props to be spread on the rendered element. Accepts bespoke
|
|
36
|
+
* data-* part attributes in plain object literals (WithDataAttributes).
|
|
37
|
+
*/
|
|
38
|
+
props?: WithDataAttributes<RenderFunctionProps<TagName>> | Array<WithDataAttributes<RenderFunctionProps<TagName>> | undefined | ((props: RenderFunctionProps<TagName>) => RenderFunctionProps<TagName>)> | undefined;
|
|
39
|
+
/**
|
|
40
|
+
* A mapping of state to `data-*` attributes.
|
|
41
|
+
*/
|
|
42
|
+
stateAttributesMapping?: StateAttributesMapping<State> | undefined;
|
|
43
|
+
};
|
|
44
|
+
export interface UseRenderElementComponentProps<State> {
|
|
45
|
+
/**
|
|
46
|
+
* The class name to apply to the rendered element.
|
|
47
|
+
* Can be a string or a function that accepts the state and returns a string.
|
|
48
|
+
*/
|
|
49
|
+
className?: string | ((state: State) => string | undefined) | undefined;
|
|
50
|
+
/**
|
|
51
|
+
* The render prop or React element to override the default element.
|
|
52
|
+
*/
|
|
53
|
+
render?: undefined | React.ReactElement | ComponentRenderFn<React.HTMLAttributes<any>, State>;
|
|
54
|
+
/**
|
|
55
|
+
* The style to apply to the rendered element.
|
|
56
|
+
* Can be a style object or a function that accepts the state and returns a style object.
|
|
57
|
+
*/
|
|
58
|
+
style?: React.CSSProperties | ((state: State) => React.CSSProperties | undefined) | undefined;
|
|
59
|
+
}
|
|
60
|
+
export interface UseRenderElementState {
|
|
61
|
+
}
|
|
62
|
+
export {};
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { createElement as _createElement } from "react";
|
|
2
|
+
// Vendored from @base-ui/react v1.6.0 (MIT) — packages/react/src/internals/useRenderElement.tsx
|
|
3
|
+
// https://github.com/mui/base-ui — import specifiers rewired, names and messages made neutral; one local departure:
|
|
4
|
+
// the `props` config accepts bespoke data-* part attributes (WithDataAttributes).
|
|
5
|
+
import * as React from 'react';
|
|
6
|
+
import { useMergedRefs, useMergedRefsN } from './useMergedRefs.js';
|
|
7
|
+
import { getReactElementRef } from './getReactElementRef.js';
|
|
8
|
+
import { mergeObjects } from './mergeObjects.js';
|
|
9
|
+
import { warn } from './warn.js';
|
|
10
|
+
import { EMPTY_OBJECT } from './empty.js';
|
|
11
|
+
import { getStateAttributesProps } from './getStateAttributesProps.js';
|
|
12
|
+
import { resolveClassName } from './resolveClassName.js';
|
|
13
|
+
import { resolveStyle } from './resolveStyle.js';
|
|
14
|
+
import { mergeProps, mergePropsN, mergeClassNames } from './mergeProps.js';
|
|
15
|
+
/**
|
|
16
|
+
* Renders a primitive part's element.
|
|
17
|
+
*
|
|
18
|
+
* @param element The default HTML element to render. Can be overridden by the `render` prop.
|
|
19
|
+
* @param componentProps An object containing the `render` and `className` props to be used for element customization. Other props are ignored.
|
|
20
|
+
* @param params Additional parameters for rendering the element.
|
|
21
|
+
*/
|
|
22
|
+
export function useRenderElement(element, componentProps, params = {}) {
|
|
23
|
+
const renderProp = componentProps.render;
|
|
24
|
+
const outProps = useRenderElementProps(componentProps, params);
|
|
25
|
+
if (params.enabled === false) {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
const state = params.state ?? EMPTY_OBJECT;
|
|
29
|
+
return evaluateRenderProp(element, renderProp, outProps, state);
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Computes render element final props.
|
|
33
|
+
*/
|
|
34
|
+
function useRenderElementProps(componentProps, params = {}) {
|
|
35
|
+
const { className: classNameProp, style: styleProp, render: renderProp } = componentProps;
|
|
36
|
+
const { state = EMPTY_OBJECT, ref, props, stateAttributesMapping, enabled = true, } = params;
|
|
37
|
+
const className = enabled ? resolveClassName(classNameProp, state) : undefined;
|
|
38
|
+
const style = enabled ? resolveStyle(styleProp, state) : undefined;
|
|
39
|
+
const stateProps = enabled
|
|
40
|
+
? getStateAttributesProps(state, stateAttributesMapping)
|
|
41
|
+
: EMPTY_OBJECT;
|
|
42
|
+
const resolvedProps = enabled && props ? resolveRenderFunctionProps(props) : undefined;
|
|
43
|
+
// Ensure outProps is always a new mutable object when enabled, never EMPTY_OBJECT.
|
|
44
|
+
// This prevents potential TypeError when setting ref, className, or style properties,
|
|
45
|
+
// since EMPTY_OBJECT is frozen and mutations would fail in strict mode.
|
|
46
|
+
const outProps = enabled
|
|
47
|
+
? (mergeObjects(stateProps, resolvedProps) ?? {})
|
|
48
|
+
: EMPTY_OBJECT;
|
|
49
|
+
// SAFETY: The `useMergedRefs` functions use a single hook to store the same value,
|
|
50
|
+
// switching between them at runtime is safe. If this assertion fails, React will
|
|
51
|
+
// throw at runtime anyway.
|
|
52
|
+
// This also skips the `useMergedRefs` call on the server, which is fine because
|
|
53
|
+
// refs are not used on the server side.
|
|
54
|
+
/* eslint-disable react-hooks/rules-of-hooks */
|
|
55
|
+
if (typeof document !== 'undefined') {
|
|
56
|
+
if (!enabled) {
|
|
57
|
+
useMergedRefs(null, null);
|
|
58
|
+
}
|
|
59
|
+
else if (Array.isArray(ref)) {
|
|
60
|
+
outProps.ref = useMergedRefsN([outProps.ref, getReactElementRef(renderProp), ...ref]);
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
outProps.ref = useMergedRefs(outProps.ref, getReactElementRef(renderProp), ref);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
if (!enabled) {
|
|
67
|
+
return EMPTY_OBJECT;
|
|
68
|
+
}
|
|
69
|
+
if (className !== undefined) {
|
|
70
|
+
outProps.className = mergeClassNames(outProps.className, className);
|
|
71
|
+
}
|
|
72
|
+
if (style !== undefined) {
|
|
73
|
+
outProps.style = mergeObjects(outProps.style, style);
|
|
74
|
+
}
|
|
75
|
+
return outProps;
|
|
76
|
+
}
|
|
77
|
+
function resolveRenderFunctionProps(props) {
|
|
78
|
+
if (Array.isArray(props)) {
|
|
79
|
+
return mergePropsN(props);
|
|
80
|
+
}
|
|
81
|
+
return mergeProps(undefined, props);
|
|
82
|
+
}
|
|
83
|
+
// The symbol React uses internally for lazy components
|
|
84
|
+
// https://github.com/facebook/react/blob/a0566250b210499b4c5677f5ac2eedbd71d51a1b/packages/shared/ReactSymbols.js#L31
|
|
85
|
+
//
|
|
86
|
+
// TODO delete once https://github.com/facebook/react/issues/32392 is fixed
|
|
87
|
+
const REACT_LAZY_TYPE = Symbol.for('react.lazy');
|
|
88
|
+
const COMPONENT_IDENTIFIER_PATTERN = /^[A-Z][A-Za-z0-9$]*$/;
|
|
89
|
+
const LOWERCASE_CHARACTER_PATTERN = /[a-z]/;
|
|
90
|
+
function evaluateRenderProp(element, render, props, state) {
|
|
91
|
+
if (render) {
|
|
92
|
+
if (typeof render === 'function') {
|
|
93
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
94
|
+
warnIfRenderPropLooksLikeComponent(render);
|
|
95
|
+
}
|
|
96
|
+
return render(props, state);
|
|
97
|
+
}
|
|
98
|
+
const mergedProps = mergeProps(props, render.props);
|
|
99
|
+
mergedProps.ref = props.ref;
|
|
100
|
+
let newElement = render;
|
|
101
|
+
// Workaround for https://github.com/facebook/react/issues/32392
|
|
102
|
+
// This works because the toArray() logic unwrap lazy element type in
|
|
103
|
+
// https://github.com/facebook/react/blob/a0566250b210499b4c5677f5ac2eedbd71d51a1b/packages/react/src/ReactChildren.js#L186
|
|
104
|
+
if (newElement?.$$typeof === REACT_LAZY_TYPE) {
|
|
105
|
+
const children = React.Children.toArray(render);
|
|
106
|
+
newElement = children[0];
|
|
107
|
+
}
|
|
108
|
+
// There is a high number of indirections, the error message thrown by React.cloneElement() is
|
|
109
|
+
// hard to use for developers, this logic provides a better context.
|
|
110
|
+
//
|
|
111
|
+
// Our general guideline is to never change the control flow depending on the environment.
|
|
112
|
+
// However, React.cloneElement() throws if React.isValidElement() is false,
|
|
113
|
+
// so we can throw before with custom message.
|
|
114
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
115
|
+
if (!React.isValidElement(newElement)) {
|
|
116
|
+
// TODO: fix mui/no-guarded-throw
|
|
117
|
+
// eslint-disable-next-line mui/no-guarded-throw
|
|
118
|
+
throw new Error([
|
|
119
|
+
'@intentface/ui: The `render` prop was provided an invalid React element as `React.isValidElement(render)` is `false`.',
|
|
120
|
+
'A valid React element must be provided to the `render` prop because it is cloned with props to replace the default element.',
|
|
121
|
+
'https://ui.intentface.com/handbook/composition',
|
|
122
|
+
].join('\n'));
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return React.cloneElement(newElement, mergedProps);
|
|
126
|
+
}
|
|
127
|
+
if (element) {
|
|
128
|
+
if (typeof element === 'string') {
|
|
129
|
+
return renderTag(element, props);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
// Unreachable, but the typings on `useRenderElement` need to be reworked
|
|
133
|
+
// to annotate it correctly.
|
|
134
|
+
throw new Error('@intentface/ui: Render element or function are not defined.');
|
|
135
|
+
}
|
|
136
|
+
function warnIfRenderPropLooksLikeComponent(renderFn) {
|
|
137
|
+
const functionName = renderFn.name;
|
|
138
|
+
if (functionName.length === 0) {
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
if (!COMPONENT_IDENTIFIER_PATTERN.test(functionName)) {
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
if (!LOWERCASE_CHARACTER_PATTERN.test(functionName)) {
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
warn(`The \`render\` prop received a function named \`${functionName}\` that starts with an uppercase letter.`, 'This usually means a React component was passed directly as `render={Component}`.', 'The part calls `render` as a plain function, which can break the Rules of Hooks during reconciliation.', 'If this is an intentional render callback, rename it to start with a lowercase letter.', 'Use `render={<Component />}` or `render={(props) => <Component {...props} />}` instead.', 'https://ui.intentface.com/handbook/composition');
|
|
148
|
+
}
|
|
149
|
+
function renderTag(Tag, props) {
|
|
150
|
+
if (Tag === 'button') {
|
|
151
|
+
return _createElement("button", { type: "button", ...props, key: props.key });
|
|
152
|
+
}
|
|
153
|
+
if (Tag === 'img') {
|
|
154
|
+
return _createElement("img", { alt: "", ...props, key: props.key });
|
|
155
|
+
}
|
|
156
|
+
return React.createElement(Tag, props);
|
|
157
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function warn(...messages: string[]): void;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// Vendored from @base-ui/utils v1.6.0 (MIT) — packages/utils/src/warn.ts
|
|
2
|
+
// https://github.com/mui/base-ui — exact copy apart from the message prefix.
|
|
3
|
+
let set;
|
|
4
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
5
|
+
set = new Set();
|
|
6
|
+
}
|
|
7
|
+
export function warn(...messages) {
|
|
8
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
9
|
+
const messageKey = messages.join(' ');
|
|
10
|
+
if (!set.has(messageKey)) {
|
|
11
|
+
set.add(messageKey);
|
|
12
|
+
console.warn(`@intentface/ui: ${messageKey}`);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export type Side = "top" | "right" | "bottom" | "left";
|
|
2
|
+
export type SafePolygonOptions = {
|
|
3
|
+
/** Where the mouse left the reference. */
|
|
4
|
+
x: number;
|
|
5
|
+
y: number;
|
|
6
|
+
/** Which side of the reference the floating element sits on. */
|
|
7
|
+
side: Side;
|
|
8
|
+
reference: Element;
|
|
9
|
+
floating: Element;
|
|
10
|
+
/** Called once the mouse leaves the safe area. */
|
|
11
|
+
onClose: () => void;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* The prediction cone: keeps a floating element open while the mouse travels
|
|
15
|
+
* from its reference towards it. `onMouseMove` listens on the document and calls
|
|
16
|
+
* `onClose` once the mouse leaves the safe area; `stop` cancels a pending check.
|
|
17
|
+
*/
|
|
18
|
+
export declare const createSafePolygon: ({ x, y, side, reference, floating, onClose, }: SafePolygonOptions) => {
|
|
19
|
+
onMouseMove: (event: MouseEvent) => void;
|
|
20
|
+
stop: () => void;
|
|
21
|
+
};
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
// Adapted from @floating-ui/react v0.27.20 (MIT) — packages/react/src/safePolygon.ts
|
|
2
|
+
// https://github.com/floating-ui/floating-ui — the same geometry, trimmed to one
|
|
3
|
+
// floating element with no nested tree, and typed to the fields it reads.
|
|
4
|
+
const BUFFER = 0.5;
|
|
5
|
+
/** Slower than this, in px per ms, the mouse has stopped heading anywhere. */
|
|
6
|
+
const INTENT_SPEED = 0.1;
|
|
7
|
+
/** How long a mouse inside the cone may take to land before it counts as gone. */
|
|
8
|
+
const LANDING_TIMEOUT = 40;
|
|
9
|
+
const isPointInPolygon = ([x, y], polygon) => {
|
|
10
|
+
let inside = false;
|
|
11
|
+
for (let index = 0, previous = polygon.length - 1; index < polygon.length; previous = index++) {
|
|
12
|
+
const [currentX, currentY] = polygon[index] ?? [0, 0];
|
|
13
|
+
const [previousX, previousY] = polygon[previous] ?? [0, 0];
|
|
14
|
+
const crosses = currentY >= y !== previousY >= y &&
|
|
15
|
+
x <= ((previousX - currentX) * (y - currentY)) / (previousY - currentY) + currentX;
|
|
16
|
+
if (crosses)
|
|
17
|
+
inside = !inside;
|
|
18
|
+
}
|
|
19
|
+
return inside;
|
|
20
|
+
};
|
|
21
|
+
const isInsideRect = ([x, y], rect) => x >= rect.x && x <= rect.x + rect.width && y >= rect.y && y <= rect.y + rect.height;
|
|
22
|
+
const contains = (parent, target) => target instanceof Node && parent.contains(target);
|
|
23
|
+
/** The rectangular gap between the two elements, which always counts as safe. */
|
|
24
|
+
const troughBetween = (side, reference, floating) => {
|
|
25
|
+
const floatingWider = floating.width > reference.width;
|
|
26
|
+
const floatingTaller = floating.height > reference.height;
|
|
27
|
+
const left = (floatingWider ? reference : floating).left;
|
|
28
|
+
const right = (floatingWider ? reference : floating).right;
|
|
29
|
+
const top = (floatingTaller ? reference : floating).top;
|
|
30
|
+
const bottom = (floatingTaller ? reference : floating).bottom;
|
|
31
|
+
switch (side) {
|
|
32
|
+
case "top":
|
|
33
|
+
return [
|
|
34
|
+
[left, reference.top + 1],
|
|
35
|
+
[left, floating.bottom - 1],
|
|
36
|
+
[right, floating.bottom - 1],
|
|
37
|
+
[right, reference.top + 1],
|
|
38
|
+
];
|
|
39
|
+
case "bottom":
|
|
40
|
+
return [
|
|
41
|
+
[left, floating.top + 1],
|
|
42
|
+
[left, reference.bottom - 1],
|
|
43
|
+
[right, reference.bottom - 1],
|
|
44
|
+
[right, floating.top + 1],
|
|
45
|
+
];
|
|
46
|
+
case "left":
|
|
47
|
+
return [
|
|
48
|
+
[floating.right - 1, bottom],
|
|
49
|
+
[floating.right - 1, top],
|
|
50
|
+
[reference.left + 1, top],
|
|
51
|
+
[reference.left + 1, bottom],
|
|
52
|
+
];
|
|
53
|
+
case "right":
|
|
54
|
+
return [
|
|
55
|
+
[reference.right - 1, bottom],
|
|
56
|
+
[reference.right - 1, top],
|
|
57
|
+
[floating.left + 1, top],
|
|
58
|
+
[floating.left + 1, bottom],
|
|
59
|
+
];
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
/** The triangle from where the mouse left to the near edge of the floating element. */
|
|
63
|
+
const coneFrom = ([x, y], side, reference, floating) => {
|
|
64
|
+
const floatingWider = floating.width > reference.width;
|
|
65
|
+
const floatingTaller = floating.height > reference.height;
|
|
66
|
+
const leftFromRight = x > floating.right - floating.width / 2;
|
|
67
|
+
const leftFromBottom = y > floating.bottom - floating.height / 2;
|
|
68
|
+
// Two points either side of the cursor, so the triangle has a base to start from.
|
|
69
|
+
const acrossX = (spread) => floatingWider ? x + (spread * BUFFER) / 2 : leftFromRight ? x + BUFFER * 4 : x - BUFFER * 4;
|
|
70
|
+
const acrossY = (spread) => floatingTaller ? y + (spread * BUFFER) / 2 : leftFromBottom ? y + BUFFER * 4 : y - BUFFER * 4;
|
|
71
|
+
switch (side) {
|
|
72
|
+
case "top": {
|
|
73
|
+
const nearEdge = floating.bottom - BUFFER;
|
|
74
|
+
return [
|
|
75
|
+
[acrossX(1), y + BUFFER + 1],
|
|
76
|
+
[acrossX(-1), y + BUFFER + 1],
|
|
77
|
+
[floating.left, leftFromRight || floatingWider ? nearEdge : floating.top],
|
|
78
|
+
[floating.right, leftFromRight ? (floatingWider ? nearEdge : floating.top) : nearEdge],
|
|
79
|
+
];
|
|
80
|
+
}
|
|
81
|
+
case "bottom": {
|
|
82
|
+
const nearEdge = floating.top + BUFFER;
|
|
83
|
+
return [
|
|
84
|
+
[acrossX(1), y - BUFFER],
|
|
85
|
+
[acrossX(-1), y - BUFFER],
|
|
86
|
+
[floating.left, leftFromRight || floatingWider ? nearEdge : floating.bottom],
|
|
87
|
+
[floating.right, leftFromRight ? (floatingWider ? nearEdge : floating.bottom) : nearEdge],
|
|
88
|
+
];
|
|
89
|
+
}
|
|
90
|
+
case "left": {
|
|
91
|
+
const nearEdge = floating.right - BUFFER;
|
|
92
|
+
return [
|
|
93
|
+
[leftFromBottom || floatingTaller ? nearEdge : floating.left, floating.top],
|
|
94
|
+
[leftFromBottom ? (floatingTaller ? nearEdge : floating.left) : nearEdge, floating.bottom],
|
|
95
|
+
[x + BUFFER + 1, acrossY(1)],
|
|
96
|
+
[x + BUFFER + 1, acrossY(-1)],
|
|
97
|
+
];
|
|
98
|
+
}
|
|
99
|
+
case "right": {
|
|
100
|
+
const nearEdge = floating.left + BUFFER;
|
|
101
|
+
return [
|
|
102
|
+
[x - BUFFER, acrossY(1)],
|
|
103
|
+
[x - BUFFER, acrossY(-1)],
|
|
104
|
+
[leftFromBottom || floatingTaller ? nearEdge : floating.right, floating.top],
|
|
105
|
+
[leftFromBottom ? (floatingTaller ? nearEdge : floating.right) : nearEdge, floating.bottom],
|
|
106
|
+
];
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
/**
|
|
111
|
+
* The prediction cone: keeps a floating element open while the mouse travels
|
|
112
|
+
* from its reference towards it. `onMouseMove` listens on the document and calls
|
|
113
|
+
* `onClose` once the mouse leaves the safe area; `stop` cancels a pending check.
|
|
114
|
+
*/
|
|
115
|
+
export const createSafePolygon = ({ x, y, side, reference, floating, onClose, }) => {
|
|
116
|
+
let landingTimer;
|
|
117
|
+
let hasLanded = false;
|
|
118
|
+
let lastPoint = null;
|
|
119
|
+
let lastTime = performance.now();
|
|
120
|
+
const speedTo = ([pointX, pointY]) => {
|
|
121
|
+
const now = performance.now();
|
|
122
|
+
const elapsed = now - lastTime;
|
|
123
|
+
const previous = lastPoint;
|
|
124
|
+
lastPoint = [pointX, pointY];
|
|
125
|
+
lastTime = now;
|
|
126
|
+
if (!previous || elapsed === 0)
|
|
127
|
+
return null;
|
|
128
|
+
return Math.hypot(pointX - previous[0], pointY - previous[1]) / elapsed;
|
|
129
|
+
};
|
|
130
|
+
const close = () => {
|
|
131
|
+
clearTimeout(landingTimer);
|
|
132
|
+
onClose();
|
|
133
|
+
};
|
|
134
|
+
const onMouseMove = (event) => {
|
|
135
|
+
clearTimeout(landingTimer);
|
|
136
|
+
const point = [event.clientX, event.clientY];
|
|
137
|
+
const target = event.composedPath?.()[0] ?? event.target;
|
|
138
|
+
const leaving = event.type === "mouseleave";
|
|
139
|
+
const overFloating = contains(floating, target);
|
|
140
|
+
const overReference = contains(reference, target);
|
|
141
|
+
const referenceRect = reference.getBoundingClientRect();
|
|
142
|
+
const floatingRect = floating.getBoundingClientRect();
|
|
143
|
+
if (overFloating) {
|
|
144
|
+
hasLanded = true;
|
|
145
|
+
if (!leaving)
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
if (overReference)
|
|
149
|
+
hasLanded = false;
|
|
150
|
+
if (overReference && !leaving) {
|
|
151
|
+
hasLanded = true;
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
// An overlapping floating element would otherwise loop between open and closed.
|
|
155
|
+
if (leaving && contains(floating, event.relatedTarget))
|
|
156
|
+
return;
|
|
157
|
+
// Leaving from the far side; the buffer would otherwise keep it open. 1px covers rounding.
|
|
158
|
+
const leftFromFarSide = (side === "top" && y >= referenceRect.bottom - 1) ||
|
|
159
|
+
(side === "bottom" && y <= referenceRect.top + 1) ||
|
|
160
|
+
(side === "left" && x >= referenceRect.right - 1) ||
|
|
161
|
+
(side === "right" && x <= referenceRect.left + 1);
|
|
162
|
+
if (leftFromFarSide)
|
|
163
|
+
return close();
|
|
164
|
+
if (isPointInPolygon(point, troughBetween(side, referenceRect, floatingRect)))
|
|
165
|
+
return;
|
|
166
|
+
if (hasLanded && !isInsideRect(point, referenceRect))
|
|
167
|
+
return close();
|
|
168
|
+
if (!leaving) {
|
|
169
|
+
const speed = speedTo(point);
|
|
170
|
+
if (speed !== null && speed < INTENT_SPEED)
|
|
171
|
+
return close();
|
|
172
|
+
}
|
|
173
|
+
if (!isPointInPolygon(point, coneFrom([x, y], side, referenceRect, floatingRect)))
|
|
174
|
+
close();
|
|
175
|
+
else if (!hasLanded)
|
|
176
|
+
landingTimer = setTimeout(close, LANDING_TIMEOUT);
|
|
177
|
+
};
|
|
178
|
+
return { onMouseMove, stop: () => clearTimeout(landingTimer) };
|
|
179
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const scrollIntoViewWithin: (rect: DOMRect, from: HTMLElement, boundary: Element) => void;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// Bring a rect into view by scrolling each scrollable ancestor of `from` just
|
|
2
|
+
// enough — but never one outside `boundary`. A primitive scrolls only its own
|
|
3
|
+
// scroll areas: walking further would reach the page around it (an embedded
|
|
4
|
+
// composer's docs page, say) and yank it, which is exactly what scrollIntoView
|
|
5
|
+
// does and why it isn't used. `boundary` itself may scroll.
|
|
6
|
+
export const scrollIntoViewWithin = (rect, from, boundary) => {
|
|
7
|
+
let { top, bottom } = rect;
|
|
8
|
+
let scroller = from;
|
|
9
|
+
while (scroller && boundary.contains(scroller)) {
|
|
10
|
+
const { overflowY } = getComputedStyle(scroller);
|
|
11
|
+
if ((overflowY === "auto" || overflowY === "scroll") &&
|
|
12
|
+
scroller.scrollHeight > scroller.clientHeight) {
|
|
13
|
+
const view = scroller.getBoundingClientRect();
|
|
14
|
+
const before = scroller.scrollTop;
|
|
15
|
+
if (top < view.top)
|
|
16
|
+
scroller.scrollTop -= view.top - top;
|
|
17
|
+
else if (bottom > view.bottom)
|
|
18
|
+
scroller.scrollTop += bottom - view.bottom;
|
|
19
|
+
// The rect moves with the scrolled content; carry that to the next scroller out.
|
|
20
|
+
const moved = scroller.scrollTop - before;
|
|
21
|
+
top -= moved;
|
|
22
|
+
bottom -= moved;
|
|
23
|
+
}
|
|
24
|
+
scroller = scroller.parentElement;
|
|
25
|
+
}
|
|
26
|
+
};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/** One problem found by a validator. */
|
|
2
|
+
export type StandardIssue = {
|
|
3
|
+
readonly message: string;
|
|
4
|
+
readonly path?: ReadonlyArray<PropertyKey | {
|
|
5
|
+
readonly key: PropertyKey;
|
|
6
|
+
}> | undefined;
|
|
7
|
+
};
|
|
8
|
+
type StandardResult<Output> = {
|
|
9
|
+
readonly value: Output;
|
|
10
|
+
readonly issues?: undefined;
|
|
11
|
+
} | {
|
|
12
|
+
readonly issues: ReadonlyArray<StandardIssue>;
|
|
13
|
+
};
|
|
14
|
+
/** A schema that validates: zod, Valibot, ArkType and others implement it. */
|
|
15
|
+
export type StandardSchema<Input = unknown, Output = Input> = {
|
|
16
|
+
readonly "~standard": {
|
|
17
|
+
readonly version: 1;
|
|
18
|
+
readonly vendor: string;
|
|
19
|
+
readonly validate: (value: unknown) => StandardResult<Output> | Promise<StandardResult<Output>>;
|
|
20
|
+
readonly types?: {
|
|
21
|
+
readonly input: Input;
|
|
22
|
+
readonly output: Output;
|
|
23
|
+
} | undefined;
|
|
24
|
+
};
|
|
25
|
+
};
|
|
26
|
+
/** A schema that can describe itself as JSON Schema (zod 4.2+, ArkType 2.1.28+, Valibot 1.2+). */
|
|
27
|
+
export type StandardJSONSchema = {
|
|
28
|
+
readonly "~standard": {
|
|
29
|
+
readonly jsonSchema: {
|
|
30
|
+
readonly input: (options: {
|
|
31
|
+
readonly target: string;
|
|
32
|
+
}) => Record<string, unknown>;
|
|
33
|
+
};
|
|
34
|
+
};
|
|
35
|
+
};
|
|
36
|
+
export type InferOutput<Schema extends StandardSchema> = NonNullable<Schema["~standard"]["types"]>["output"];
|
|
37
|
+
export type InferInput<Schema extends StandardSchema> = NonNullable<Schema["~standard"]["types"]>["input"];
|
|
38
|
+
export {};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { StateAttributesMapping } from "./render/getStateAttributesProps.js";
|
|
2
|
+
import type { TransitionStatus } from "./render/transition.js";
|
|
3
|
+
export declare const openStateMapping: StateAttributesMapping<{
|
|
4
|
+
open: boolean;
|
|
5
|
+
}>;
|
|
6
|
+
export declare const transitionStatusMapping: StateAttributesMapping<{
|
|
7
|
+
transitionStatus: TransitionStatus;
|
|
8
|
+
}>;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// Shared state → data-attribute mappings for useRenderElement. Base UI
|
|
2
|
+
// convention: `open` produces a data-open / data-closed presence pair so both
|
|
3
|
+
// directions are styleable (exit transitions target data-closed).
|
|
4
|
+
export const openStateMapping = {
|
|
5
|
+
open: (value) => (value ? { "data-open": "" } : { "data-closed": "" }),
|
|
6
|
+
};
|
|
7
|
+
// Base UI convention: the transitional frames of an open/close animation surface as
|
|
8
|
+
// data-starting-style (entering) / data-ending-style (exiting); settled states emit nothing.
|
|
9
|
+
export const transitionStatusMapping = {
|
|
10
|
+
transitionStatus: (value) => {
|
|
11
|
+
if (value === "starting")
|
|
12
|
+
return { "data-starting-style": "" };
|
|
13
|
+
if (value === "ending")
|
|
14
|
+
return { "data-ending-style": "" };
|
|
15
|
+
return null;
|
|
16
|
+
},
|
|
17
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Controlled/uncontrolled state, decided once.
|
|
3
|
+
*
|
|
4
|
+
* Whether a component is controlled is latched on the first render and never
|
|
5
|
+
* re-read. A component that flipped mid-life would silently drop state, so in
|
|
6
|
+
* development the flip is reported — loudly, but without throwing, since a
|
|
7
|
+
* render-time throw makes the very UI you need to inspect disappear.
|
|
8
|
+
*
|
|
9
|
+
* The setter is a no-op while controlled: whoever owns `value` is the only
|
|
10
|
+
* thing that can change it.
|
|
11
|
+
*/
|
|
12
|
+
export declare const useControlled: <Value>({ controlled, default: defaultValue, name, state, }: {
|
|
13
|
+
controlled: Value | undefined;
|
|
14
|
+
default: Value;
|
|
15
|
+
/** Component name, for the development warning. */
|
|
16
|
+
name: string;
|
|
17
|
+
/** Prop name, for the development warning. */
|
|
18
|
+
state?: string;
|
|
19
|
+
}) => readonly [Value, (next: Value) => void];
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useCallback, useRef, useState } from "react";
|
|
3
|
+
/**
|
|
4
|
+
* Controlled/uncontrolled state, decided once.
|
|
5
|
+
*
|
|
6
|
+
* Whether a component is controlled is latched on the first render and never
|
|
7
|
+
* re-read. A component that flipped mid-life would silently drop state, so in
|
|
8
|
+
* development the flip is reported — loudly, but without throwing, since a
|
|
9
|
+
* render-time throw makes the very UI you need to inspect disappear.
|
|
10
|
+
*
|
|
11
|
+
* The setter is a no-op while controlled: whoever owns `value` is the only
|
|
12
|
+
* thing that can change it.
|
|
13
|
+
*/
|
|
14
|
+
export const useControlled = ({ controlled, default: defaultValue, name, state = "value", }) => {
|
|
15
|
+
const isControlledRef = useRef(controlled !== undefined);
|
|
16
|
+
const isControlled = isControlledRef.current;
|
|
17
|
+
const [uncontrolledValue, setUncontrolledValue] = useState(defaultValue);
|
|
18
|
+
if (process.env.NODE_ENV !== "production" && isControlled !== (controlled !== undefined)) {
|
|
19
|
+
console.error(`[@intentface/ui] ${name} is switching between controlled and uncontrolled for \`${state}\`. ` +
|
|
20
|
+
"Pick one for the component's lifetime: pass the prop always, or never.");
|
|
21
|
+
}
|
|
22
|
+
// Reads the ref rather than the destructured value, so the dependency list is
|
|
23
|
+
// genuinely empty and the setter's identity never changes.
|
|
24
|
+
const setValueIfUncontrolled = useCallback((next) => {
|
|
25
|
+
if (isControlledRef.current)
|
|
26
|
+
return;
|
|
27
|
+
setUncontrolledValue(next);
|
|
28
|
+
}, []);
|
|
29
|
+
return [
|
|
30
|
+
isControlled ? controlled : uncontrolledValue,
|
|
31
|
+
setValueIfUncontrolled,
|
|
32
|
+
];
|
|
33
|
+
};
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export * as Message from "./index.parts.js";
|
|
2
|
+
export type { MessageChipSegment, MessageRootProps, MessageSelection, MessageState, MessageTextProps, MessageTurnProps, } from "./message.js";
|
|
3
|
+
export { readMessageSelection, useMessageSelection, useMessageSelectionScope, } from "./message.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { MessageRoot as Root, MessageText as Text, MessageTurn as Turn, } from "./message.js";
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
// Part names for the `Message` namespace. Deliberately carries no
|
|
2
|
+
// "use client" directive: this module and index.ts must stay server-resolvable
|
|
3
|
+
// so a React Server Component can reach Message.Root and its siblings
|
|
4
|
+
// through them. The directive lives one level down, on message.tsx.
|
|
5
|
+
export { MessageRoot as Root, MessageText as Text, MessageTurn as Turn, } from "./message.js";
|