@intentface/chat 0.1.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 +108 -0
- package/dist/ask-user/ask-user.d.ts +104 -0
- package/dist/ask-user/ask-user.js +226 -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 +41 -0
- package/dist/attachments/attachments.js +91 -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 +25 -0
- package/dist/chip/chip.js +25 -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 +52 -0
- package/dist/composer/actions.d.ts +35 -0
- package/dist/composer/actions.js +75 -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 +357 -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 +55 -0
- package/dist/composer/editor-dom.js +431 -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 +29 -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 +80 -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 +63 -0
- package/dist/composer/prefix-detection.d.ts +23 -0
- package/dist/composer/prefix-detection.js +58 -0
- package/dist/composer/root.d.ts +21 -0
- package/dist/composer/root.js +107 -0
- package/dist/composer/segments.d.ts +108 -0
- package/dist/composer/segments.js +366 -0
- package/dist/composer/store.d.ts +97 -0
- package/dist/composer/store.js +451 -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 +126 -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 +649 -0
- package/dist/internal/collapsible.d.ts +22 -0
- package/dist/internal/collapsible.js +90 -0
- package/dist/internal/primitive-props.d.ts +4 -0
- package/dist/internal/primitive-props.js +4 -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 +22 -0
- package/dist/internal/render/positioning.js +78 -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 +48 -0
- package/dist/internal/render/transition.js +203 -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/state-mappings.d.ts +8 -0
- package/dist/internal/state-mappings.js +17 -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 +43 -0
- package/dist/message/message.js +78 -0
- package/dist/message-utils.d.ts +55 -0
- package/dist/message-utils.js +79 -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 +20 -0
- package/dist/reasoning/reasoning.js +49 -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 +53 -0
- package/dist/steps/steps.js +79 -0
- package/dist/thread/geometry.d.ts +18 -0
- package/dist/thread/geometry.js +59 -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 +66 -0
- package/dist/thread/thread.js +639 -0
- package/dist/types.d.ts +58 -0
- package/dist/types.js +17 -0
- package/package.json +106 -0
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
// Minimal internal disclosure primitive — replaces the @base-ui/react
|
|
4
|
+
// Collapsible dependency for the package's own parts. Trigger toggles, Panel
|
|
5
|
+
// hides (or unmounts) its content; state is exposed Base UI-style via
|
|
6
|
+
// presence attributes (data-open / data-closed) generated from state, plus
|
|
7
|
+
// the animation contract: data-starting-style on the panel's first open
|
|
8
|
+
// frame, data-ending-style while its exit animations run (hide/unmount waits
|
|
9
|
+
// for them), and the panel's natural height as --collapsible-panel-height.
|
|
10
|
+
// Every part supports the Base UI render prop.
|
|
11
|
+
import { createContext, use, useCallback, useId, useRef, useState, } from "react";
|
|
12
|
+
import { useOpenTransition } from "./render/transition.js";
|
|
13
|
+
import { useRenderElement } from "./render/useRenderElement.js";
|
|
14
|
+
import { openStateMapping, transitionStatusMapping } from "./state-mappings.js";
|
|
15
|
+
const CollapsibleContext = createContext(null);
|
|
16
|
+
const useCollapsible = () => {
|
|
17
|
+
const ctx = use(CollapsibleContext);
|
|
18
|
+
if (!ctx)
|
|
19
|
+
throw new Error("Collapsible parts must be used within <Collapsible>");
|
|
20
|
+
return ctx;
|
|
21
|
+
};
|
|
22
|
+
const CollapsibleRoot = ({ open: controlledOpen, defaultOpen = false, onOpenChange, className, render, style, ...elementProps }) => {
|
|
23
|
+
const [internalOpen, setInternalOpen] = useState(defaultOpen);
|
|
24
|
+
const isControlled = controlledOpen !== undefined;
|
|
25
|
+
const open = isControlled ? controlledOpen : internalOpen;
|
|
26
|
+
const panelId = useId();
|
|
27
|
+
const setOpen = useCallback((value) => {
|
|
28
|
+
if (!isControlled)
|
|
29
|
+
setInternalOpen(value);
|
|
30
|
+
onOpenChange?.(value);
|
|
31
|
+
}, [isControlled, onOpenChange]);
|
|
32
|
+
const element = useRenderElement("div", { className, render, style }, {
|
|
33
|
+
state: { open },
|
|
34
|
+
stateAttributesMapping: openStateMapping,
|
|
35
|
+
props: elementProps,
|
|
36
|
+
});
|
|
37
|
+
return _jsx(CollapsibleContext, { value: { open, setOpen, panelId }, children: element });
|
|
38
|
+
};
|
|
39
|
+
const CollapsibleTrigger = ({ className, render, style, ...elementProps }) => {
|
|
40
|
+
const { open, setOpen, panelId } = useCollapsible();
|
|
41
|
+
return useRenderElement("button", { className, render, style }, {
|
|
42
|
+
state: { open },
|
|
43
|
+
stateAttributesMapping: openStateMapping,
|
|
44
|
+
props: [
|
|
45
|
+
{
|
|
46
|
+
"aria-expanded": open,
|
|
47
|
+
"aria-controls": panelId,
|
|
48
|
+
// mergeProps runs the consumer's onClick first (rightmost wins), so
|
|
49
|
+
// preventDefault there still cancels the toggle — same contract as
|
|
50
|
+
// the previous inline `if (!event.defaultPrevented)` handler.
|
|
51
|
+
onClick: (event) => {
|
|
52
|
+
if (!event.defaultPrevented)
|
|
53
|
+
setOpen(!open);
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
elementProps,
|
|
57
|
+
],
|
|
58
|
+
});
|
|
59
|
+
};
|
|
60
|
+
const CollapsiblePanel = ({ keepMounted = false, className, render, style, ...elementProps }) => {
|
|
61
|
+
const { open, panelId } = useCollapsible();
|
|
62
|
+
const panelRef = useRef(null);
|
|
63
|
+
// The shared transition hook owns the open/starting/ending/close lifecycle: it keeps the
|
|
64
|
+
// panel mounted through its exit (waiting on getAnimations), measures the natural height
|
|
65
|
+
// for the CSS var, and reports the status that drives data-starting/ending-style.
|
|
66
|
+
const { mounted, transitionStatus, height } = useOpenTransition(open, panelRef, {
|
|
67
|
+
measureHeight: true,
|
|
68
|
+
});
|
|
69
|
+
const hidden = !open && !mounted;
|
|
70
|
+
return useRenderElement("div", { className, render, style }, {
|
|
71
|
+
enabled: mounted || keepMounted,
|
|
72
|
+
state: { open, transitionStatus },
|
|
73
|
+
stateAttributesMapping: { ...openStateMapping, ...transitionStatusMapping },
|
|
74
|
+
ref: panelRef,
|
|
75
|
+
props: [
|
|
76
|
+
{
|
|
77
|
+
id: panelId,
|
|
78
|
+
hidden,
|
|
79
|
+
style: height !== null
|
|
80
|
+
? { "--collapsible-panel-height": `${height}px` }
|
|
81
|
+
: undefined,
|
|
82
|
+
},
|
|
83
|
+
elementProps,
|
|
84
|
+
],
|
|
85
|
+
});
|
|
86
|
+
};
|
|
87
|
+
export const Collapsible = Object.assign(CollapsibleRoot, {
|
|
88
|
+
Trigger: CollapsibleTrigger,
|
|
89
|
+
Panel: CollapsiblePanel,
|
|
90
|
+
});
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type * as React from "react";
|
|
2
|
+
import type { BaseUIComponentProps } from "./render/types.js";
|
|
3
|
+
export type EmptyState = Record<string, never>;
|
|
4
|
+
export type PrimitiveProps<ElementType extends React.ElementType, State = EmptyState> = BaseUIComponentProps<ElementType, State>;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type * as React from 'react';
|
|
2
|
+
export type HTMLProps<T = any> = React.HTMLAttributes<T> & {
|
|
3
|
+
ref?: React.Ref<T> | undefined;
|
|
4
|
+
};
|
|
5
|
+
export type WithDataAttributes<Props> = Props | (Props & {
|
|
6
|
+
[dataAttribute: `data-${string}`]: string | undefined;
|
|
7
|
+
});
|
|
8
|
+
/**
|
|
9
|
+
* Shape of the render prop: a function that takes props to be spread on the element and component's state and returns a React element.
|
|
10
|
+
*
|
|
11
|
+
* @template Props Props to be spread on the rendered element.
|
|
12
|
+
* @template State Component's internal state.
|
|
13
|
+
*/
|
|
14
|
+
export type ComponentRenderFn<Props, State> = (props: Props, state: State) => React.ReactElement<unknown>;
|
|
15
|
+
export type BaseUIEvent<E extends React.SyntheticEvent<Element, Event>> = E & {
|
|
16
|
+
preventBaseUIHandler: () => void;
|
|
17
|
+
readonly baseUIHandlerPrevented?: boolean | undefined;
|
|
18
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// Vendored from @base-ui/utils v1.6.0 (MIT) — packages/utils/src/getReactElementRef.ts
|
|
2
|
+
// https://github.com/mui/base-ui — exact copy.
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
import { isReactVersionAtLeast } from './reactVersion';
|
|
5
|
+
/**
|
|
6
|
+
* Extracts the `ref` from a React element, handling different React versions.
|
|
7
|
+
*/
|
|
8
|
+
export function getReactElementRef(element) {
|
|
9
|
+
if (!React.isValidElement(element)) {
|
|
10
|
+
return null;
|
|
11
|
+
}
|
|
12
|
+
const reactElement = element;
|
|
13
|
+
const propsWithRef = reactElement.props;
|
|
14
|
+
return (isReactVersionAtLeast(19) ? propsWithRef?.ref : reactElement.ref) ?? null;
|
|
15
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export type StateAttributesMapping<State> = {
|
|
2
|
+
[Property in keyof State]?: (state: State[Property]) => Record<string, string> | null;
|
|
3
|
+
};
|
|
4
|
+
export declare function getStateAttributesProps<State extends Record<string, any>>(state: State, customMapping?: StateAttributesMapping<State>): Record<string, string>;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// Vendored from @base-ui/react v1.6.0 (MIT) — packages/react/src/internals/getStateAttributesProps.ts
|
|
2
|
+
// https://github.com/mui/base-ui — exact copy.
|
|
3
|
+
export function getStateAttributesProps(state, customMapping) {
|
|
4
|
+
const props = {};
|
|
5
|
+
/* eslint-disable-next-line guard-for-in */
|
|
6
|
+
for (const key in state) {
|
|
7
|
+
const value = state[key];
|
|
8
|
+
if (customMapping?.hasOwnProperty(key)) {
|
|
9
|
+
const customProps = customMapping[key](value);
|
|
10
|
+
if (customProps != null) {
|
|
11
|
+
Object.assign(props, customProps);
|
|
12
|
+
}
|
|
13
|
+
continue;
|
|
14
|
+
}
|
|
15
|
+
if (value === true) {
|
|
16
|
+
props[`data-${key.toLowerCase()}`] = '';
|
|
17
|
+
}
|
|
18
|
+
else if (value) {
|
|
19
|
+
props[`data-${key.toLowerCase()}`] = value.toString();
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return props;
|
|
23
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function mergeObjects<A extends object | undefined, B extends object | undefined>(a: A, b: B): NonNullable<A> | NonNullable<B> | (A & B) | undefined;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// Vendored from @base-ui/utils v1.6.0 (MIT) — packages/utils/src/mergeObjects.ts
|
|
2
|
+
// https://github.com/mui/base-ui — exact copy.
|
|
3
|
+
export function mergeObjects(a, b) {
|
|
4
|
+
if (a && !b) {
|
|
5
|
+
return a;
|
|
6
|
+
}
|
|
7
|
+
if (!a && b) {
|
|
8
|
+
return b;
|
|
9
|
+
}
|
|
10
|
+
if (a || b) {
|
|
11
|
+
return { ...a, ...b };
|
|
12
|
+
}
|
|
13
|
+
return undefined;
|
|
14
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import type { BaseUIEvent, WithBaseUIEvent } from './types';
|
|
3
|
+
type ElementType = React.ElementType;
|
|
4
|
+
type PropsOf<T extends React.ElementType> = WithBaseUIEvent<React.ComponentPropsWithRef<T>>;
|
|
5
|
+
type InputProps<T extends React.ElementType> = PropsOf<T> | ((otherProps: PropsOf<T>) => PropsOf<T>) | undefined;
|
|
6
|
+
/**
|
|
7
|
+
* Merges multiple sets of React props. It follows the Object.assign pattern where the rightmost object's fields overwrite
|
|
8
|
+
* the conflicting ones from others. This doesn't apply to event handlers, `className` and `style` props.
|
|
9
|
+
*
|
|
10
|
+
* Event handlers are merged and called in right-to-left order (rightmost handler executes first, leftmost last).
|
|
11
|
+
* For React synthetic events, the rightmost handler can prevent prior (left-positioned) handlers from executing
|
|
12
|
+
* by calling `event.preventBaseUIHandler()`. For non-synthetic events (custom events with primitive/object values),
|
|
13
|
+
* all handlers always execute without prevention capability.
|
|
14
|
+
*
|
|
15
|
+
* The `className` prop is merged by concatenating classes in right-to-left order (rightmost class appears first in the string).
|
|
16
|
+
* The `style` prop is merged with rightmost styles overwriting the prior ones.
|
|
17
|
+
*
|
|
18
|
+
* Props can either be provided as objects or as functions that take the previous props as an argument.
|
|
19
|
+
* The function will receive the merged props up to that point (going from left to right):
|
|
20
|
+
* so in the case of `(obj1, obj2, fn, obj3)`, `fn` will receive the merged props of `obj1` and `obj2`.
|
|
21
|
+
* The function is responsible for chaining event handlers if needed (that is, we don't run the merge logic).
|
|
22
|
+
*
|
|
23
|
+
* Event handlers returned by the functions are not automatically prevented when `preventBaseUIHandler` is called.
|
|
24
|
+
* They must check `event.baseUIHandlerPrevented` themselves and bail out if it's true.
|
|
25
|
+
*
|
|
26
|
+
* @important **`ref` is not merged.**
|
|
27
|
+
* @param a Props object to merge.
|
|
28
|
+
* @param b Props object to merge. The function will overwrite conflicting props from `a`.
|
|
29
|
+
* @param c Props object to merge. The function will overwrite conflicting props from previous parameters.
|
|
30
|
+
* @param d Props object to merge. The function will overwrite conflicting props from previous parameters.
|
|
31
|
+
* @param e Props object to merge. The function will overwrite conflicting props from previous parameters.
|
|
32
|
+
* @returns The merged props.
|
|
33
|
+
* @public
|
|
34
|
+
*/
|
|
35
|
+
export declare function mergeProps<T extends ElementType>(a: InputProps<T>, b: InputProps<T>, c: InputProps<T>, d: InputProps<T>, e: InputProps<T>): PropsOf<T>;
|
|
36
|
+
export declare function mergeProps<T extends ElementType>(a: InputProps<T>, b: InputProps<T>, c: InputProps<T>, d: InputProps<T>): PropsOf<T>;
|
|
37
|
+
export declare function mergeProps<T extends ElementType>(a: InputProps<T>, b: InputProps<T>, c: InputProps<T>): PropsOf<T>;
|
|
38
|
+
export declare function mergeProps<T extends ElementType>(a: InputProps<T>, b: InputProps<T>): PropsOf<T>;
|
|
39
|
+
/**
|
|
40
|
+
* Merges an arbitrary number of React props using the same logic as {@link mergeProps}.
|
|
41
|
+
* This function accepts an array of props instead of individual arguments.
|
|
42
|
+
*
|
|
43
|
+
* This has slightly lower performance than {@link mergeProps} due to accepting an array
|
|
44
|
+
* instead of a fixed number of arguments. Prefer {@link mergeProps} when merging 5 or
|
|
45
|
+
* fewer prop sets for better performance.
|
|
46
|
+
*
|
|
47
|
+
* @param props Array of props to merge.
|
|
48
|
+
* @returns The merged props.
|
|
49
|
+
* @see mergeProps
|
|
50
|
+
* @public
|
|
51
|
+
*/
|
|
52
|
+
export declare function mergePropsN<T extends ElementType>(props: InputProps<T>[]): PropsOf<T>;
|
|
53
|
+
export declare function makeEventPreventable<T extends React.SyntheticEvent>(event: BaseUIEvent<T>): BaseUIEvent<T>;
|
|
54
|
+
export declare function mergeClassNames(ourClassName: string | undefined, theirClassName: string | undefined): string | undefined;
|
|
55
|
+
export {};
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
// Vendored from @base-ui/react v1.6.0 (MIT) — packages/react/src/merge-props/mergeProps.ts
|
|
2
|
+
// https://github.com/mui/base-ui — exact copy; only import specifiers rewired.
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
import { mergeObjects } from './mergeObjects';
|
|
5
|
+
const EMPTY_PROPS = {};
|
|
6
|
+
export function mergeProps(a, b, c, d, e) {
|
|
7
|
+
if (!c && !d && !e && !a) {
|
|
8
|
+
return createInitialMergedProps(b);
|
|
9
|
+
}
|
|
10
|
+
// We need to mutably own `merged`.
|
|
11
|
+
let merged = createInitialMergedProps(a);
|
|
12
|
+
if (b) {
|
|
13
|
+
merged = mergeInto(merged, b);
|
|
14
|
+
}
|
|
15
|
+
if (c) {
|
|
16
|
+
merged = mergeInto(merged, c);
|
|
17
|
+
}
|
|
18
|
+
if (d) {
|
|
19
|
+
merged = mergeInto(merged, d);
|
|
20
|
+
}
|
|
21
|
+
if (e) {
|
|
22
|
+
merged = mergeInto(merged, e);
|
|
23
|
+
}
|
|
24
|
+
return merged;
|
|
25
|
+
}
|
|
26
|
+
/* eslint-enable id-denylist */
|
|
27
|
+
/**
|
|
28
|
+
* Merges an arbitrary number of React props using the same logic as {@link mergeProps}.
|
|
29
|
+
* This function accepts an array of props instead of individual arguments.
|
|
30
|
+
*
|
|
31
|
+
* This has slightly lower performance than {@link mergeProps} due to accepting an array
|
|
32
|
+
* instead of a fixed number of arguments. Prefer {@link mergeProps} when merging 5 or
|
|
33
|
+
* fewer prop sets for better performance.
|
|
34
|
+
*
|
|
35
|
+
* @param props Array of props to merge.
|
|
36
|
+
* @returns The merged props.
|
|
37
|
+
* @see mergeProps
|
|
38
|
+
* @public
|
|
39
|
+
*/
|
|
40
|
+
export function mergePropsN(props) {
|
|
41
|
+
if (props.length === 0) {
|
|
42
|
+
return EMPTY_PROPS;
|
|
43
|
+
}
|
|
44
|
+
if (props.length === 1) {
|
|
45
|
+
return createInitialMergedProps(props[0]);
|
|
46
|
+
}
|
|
47
|
+
// We need to mutably own `merged`.
|
|
48
|
+
let merged = createInitialMergedProps(props[0]);
|
|
49
|
+
for (let i = 1; i < props.length; i += 1) {
|
|
50
|
+
merged = mergeInto(merged, props[i]);
|
|
51
|
+
}
|
|
52
|
+
return merged;
|
|
53
|
+
}
|
|
54
|
+
function createInitialMergedProps(inputProps) {
|
|
55
|
+
if (isPropsGetter(inputProps)) {
|
|
56
|
+
// Getter-returned handlers intentionally keep their existing semantics.
|
|
57
|
+
return { ...resolvePropsGetter(inputProps, EMPTY_PROPS) };
|
|
58
|
+
}
|
|
59
|
+
return copyInitialProps(inputProps);
|
|
60
|
+
}
|
|
61
|
+
function mergeInto(merged, inputProps) {
|
|
62
|
+
if (isPropsGetter(inputProps)) {
|
|
63
|
+
return resolvePropsGetter(inputProps, merged);
|
|
64
|
+
}
|
|
65
|
+
return mutablyMergeInto(merged, inputProps);
|
|
66
|
+
}
|
|
67
|
+
function copyInitialProps(inputProps) {
|
|
68
|
+
const copiedProps = { ...inputProps };
|
|
69
|
+
// `copiedProps` is our fresh own-object copy, so iterating with `for...in` is safe here.
|
|
70
|
+
// eslint-disable-next-line guard-for-in
|
|
71
|
+
for (const propName in copiedProps) {
|
|
72
|
+
const propValue = copiedProps[propName];
|
|
73
|
+
if (isEventHandler(propName, propValue)) {
|
|
74
|
+
copiedProps[propName] = wrapEventHandler(propValue);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return copiedProps;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Merges two sets of props. In case of conflicts, the external props take precedence.
|
|
81
|
+
*/
|
|
82
|
+
function mutablyMergeInto(mergedProps, externalProps) {
|
|
83
|
+
if (!externalProps) {
|
|
84
|
+
return mergedProps;
|
|
85
|
+
}
|
|
86
|
+
// eslint-disable-next-line guard-for-in
|
|
87
|
+
for (const propName in externalProps) {
|
|
88
|
+
const externalPropValue = externalProps[propName];
|
|
89
|
+
switch (propName) {
|
|
90
|
+
case 'style': {
|
|
91
|
+
mergedProps[propName] = mergeObjects(mergedProps.style, externalPropValue);
|
|
92
|
+
break;
|
|
93
|
+
}
|
|
94
|
+
case 'className': {
|
|
95
|
+
mergedProps[propName] = mergeClassNames(mergedProps.className, externalPropValue);
|
|
96
|
+
break;
|
|
97
|
+
}
|
|
98
|
+
default: {
|
|
99
|
+
if (isEventHandler(propName, externalPropValue)) {
|
|
100
|
+
mergedProps[propName] = mergeEventHandlers(mergedProps[propName], externalPropValue);
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
mergedProps[propName] = externalPropValue;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return mergedProps;
|
|
109
|
+
}
|
|
110
|
+
function isEventHandler(key, value) {
|
|
111
|
+
// This approach is more efficient than using a regex.
|
|
112
|
+
const code0 = key.charCodeAt(0);
|
|
113
|
+
const code1 = key.charCodeAt(1);
|
|
114
|
+
const code2 = key.charCodeAt(2);
|
|
115
|
+
return (code0 === 111 /* o */ &&
|
|
116
|
+
code1 === 110 /* n */ &&
|
|
117
|
+
code2 >= 65 /* A */ &&
|
|
118
|
+
code2 <= 90 /* Z */ &&
|
|
119
|
+
(typeof value === 'function' || typeof value === 'undefined'));
|
|
120
|
+
}
|
|
121
|
+
function isPropsGetter(inputProps) {
|
|
122
|
+
return typeof inputProps === 'function';
|
|
123
|
+
}
|
|
124
|
+
function resolvePropsGetter(inputProps, previousProps) {
|
|
125
|
+
if (isPropsGetter(inputProps)) {
|
|
126
|
+
return inputProps(previousProps);
|
|
127
|
+
}
|
|
128
|
+
return inputProps ?? EMPTY_PROPS;
|
|
129
|
+
}
|
|
130
|
+
function mergeEventHandlers(ourHandler, theirHandler) {
|
|
131
|
+
if (!theirHandler) {
|
|
132
|
+
return ourHandler;
|
|
133
|
+
}
|
|
134
|
+
if (!ourHandler) {
|
|
135
|
+
return wrapEventHandler(theirHandler);
|
|
136
|
+
}
|
|
137
|
+
return (...args) => {
|
|
138
|
+
const event = args[0];
|
|
139
|
+
if (isSyntheticEvent(event)) {
|
|
140
|
+
const baseUIEvent = event;
|
|
141
|
+
makeEventPreventable(baseUIEvent);
|
|
142
|
+
const result = theirHandler(...args);
|
|
143
|
+
if (!baseUIEvent.baseUIHandlerPrevented) {
|
|
144
|
+
ourHandler?.(...args);
|
|
145
|
+
}
|
|
146
|
+
return result;
|
|
147
|
+
}
|
|
148
|
+
const result = theirHandler(...args);
|
|
149
|
+
ourHandler?.(...args);
|
|
150
|
+
return result;
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
function wrapEventHandler(handler) {
|
|
154
|
+
if (!handler) {
|
|
155
|
+
return handler;
|
|
156
|
+
}
|
|
157
|
+
return (...args) => {
|
|
158
|
+
const event = args[0];
|
|
159
|
+
if (isSyntheticEvent(event)) {
|
|
160
|
+
makeEventPreventable(event);
|
|
161
|
+
}
|
|
162
|
+
return handler(...args);
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
export function makeEventPreventable(event) {
|
|
166
|
+
event.preventBaseUIHandler = () => {
|
|
167
|
+
event.baseUIHandlerPrevented = true;
|
|
168
|
+
};
|
|
169
|
+
return event;
|
|
170
|
+
}
|
|
171
|
+
export function mergeClassNames(ourClassName, theirClassName) {
|
|
172
|
+
if (theirClassName) {
|
|
173
|
+
if (ourClassName) {
|
|
174
|
+
// eslint-disable-next-line prefer-template
|
|
175
|
+
return theirClassName + ' ' + ourClassName;
|
|
176
|
+
}
|
|
177
|
+
return theirClassName;
|
|
178
|
+
}
|
|
179
|
+
return ourClassName;
|
|
180
|
+
}
|
|
181
|
+
function isSyntheticEvent(event) {
|
|
182
|
+
return event != null && typeof event === 'object' && 'nativeEvent' in event;
|
|
183
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type RefObject } from "react";
|
|
2
|
+
export type AnchorSide = "top" | "bottom" | "left" | "right";
|
|
3
|
+
export type AnchorAlign = "start" | "center" | "end";
|
|
4
|
+
export type UseAnchorPositioningOptions = {
|
|
5
|
+
/** Position only while true (e.g. while the surface is mounted/open). */
|
|
6
|
+
enabled?: boolean;
|
|
7
|
+
/** Preferred side; flips to the opposite when there's no room. Default "top". */
|
|
8
|
+
side?: AnchorSide;
|
|
9
|
+
/** Alignment along the side. Default "center". */
|
|
10
|
+
align?: AnchorAlign;
|
|
11
|
+
/** Gap between anchor and floating element. Default 0. */
|
|
12
|
+
sideOffset?: number;
|
|
13
|
+
/** Keep this many px from the collision boundary. Default 8. */
|
|
14
|
+
collisionPadding?: number;
|
|
15
|
+
/**
|
|
16
|
+
* Pin to `side`/`align` without collision repositioning — drops flip + shift, so the surface
|
|
17
|
+
* stays put and may run off-screen when there's no room. `size` still publishes its vars.
|
|
18
|
+
* Default false.
|
|
19
|
+
*/
|
|
20
|
+
pin?: boolean;
|
|
21
|
+
};
|
|
22
|
+
export declare const useAnchorPositioning: (getAnchor: () => Element | null, floatingRef: RefObject<HTMLElement | null>, { enabled, side, align, sideOffset, collisionPadding, pin, }?: UseAnchorPositioningOptions) => void;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
// Collision-aware anchor positioning via @floating-ui/dom, shared by Composer.Popover
|
|
3
|
+
// (anchored to the active command badge) and a positioned Composer.Panel (anchored to the
|
|
4
|
+
// composer container). Positions the floating element with flip/shift/size and keeps it there
|
|
5
|
+
// across scroll/resize/anchor movement (autoUpdate); `pin` opts out of flip/shift.
|
|
6
|
+
//
|
|
7
|
+
// Everything is written imperatively — no per-render React state — so a flip or a scroll never
|
|
8
|
+
// re-renders the tree: `position: absolute` + left/top (page coordinates, so the surface scrolls
|
|
9
|
+
// natively with the page instead of chasing the anchor a frame behind it); `--anchor-width` /
|
|
10
|
+
// `--anchor-height` (the anchor's own size, e.g. so a panel can be `width: var(--anchor-width)`)
|
|
11
|
+
// and `--anchor-available-height` (free space in the placement direction — cap max-height + scroll
|
|
12
|
+
// instead of overflow) from the size middleware; and `data-side`/`data-align` for the transition
|
|
13
|
+
// origin. Base UI-style: the styling layer opts into the vars, the primitive imposes nothing.
|
|
14
|
+
import { autoUpdate, computePosition, flip, offset, shift, size, } from "@floating-ui/dom";
|
|
15
|
+
import { useEffect } from "react";
|
|
16
|
+
const EMPTY_RECT = {
|
|
17
|
+
x: 0,
|
|
18
|
+
y: 0,
|
|
19
|
+
width: 0,
|
|
20
|
+
height: 0,
|
|
21
|
+
top: 0,
|
|
22
|
+
right: 0,
|
|
23
|
+
bottom: 0,
|
|
24
|
+
left: 0,
|
|
25
|
+
toJSON: () => "",
|
|
26
|
+
};
|
|
27
|
+
export const useAnchorPositioning = (getAnchor, floatingRef, { enabled = true, side = "top", align = "center", sideOffset = 0, collisionPadding = 8, pin = false, } = {}) => {
|
|
28
|
+
useEffect(() => {
|
|
29
|
+
const floating = floatingRef.current;
|
|
30
|
+
if (!enabled || !floating)
|
|
31
|
+
return;
|
|
32
|
+
const placement = (align === "center" ? side : `${side}-${align}`);
|
|
33
|
+
// Virtual reference: re-reads the anchor rect each run, so a re-created anchor (e.g. the
|
|
34
|
+
// command badge decoration re-rendering as you type) is tracked without re-subscribing.
|
|
35
|
+
const reference = {
|
|
36
|
+
getBoundingClientRect: () => getAnchor()?.getBoundingClientRect() ?? EMPTY_RECT,
|
|
37
|
+
get contextElement() {
|
|
38
|
+
return getAnchor() ?? undefined;
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
const update = () => {
|
|
42
|
+
computePosition(reference, floating, {
|
|
43
|
+
// Absolute (page-coordinate), not fixed: portaled to the body, the surface then
|
|
44
|
+
// scrolls *with* the page natively — so following the anchor on scroll needs no
|
|
45
|
+
// per-frame JS write and can't lag a frame behind it (the "wobble"). autoUpdate
|
|
46
|
+
// still re-runs for real layout changes (flip/shift/resize/anchor movement).
|
|
47
|
+
strategy: "absolute",
|
|
48
|
+
placement,
|
|
49
|
+
middleware: [
|
|
50
|
+
offset(sideOffset),
|
|
51
|
+
// Collision repositioning — skipped when pinned, so the surface holds `side`/`align`.
|
|
52
|
+
...(pin
|
|
53
|
+
? []
|
|
54
|
+
: [flip({ padding: collisionPadding }), shift({ padding: collisionPadding })]),
|
|
55
|
+
size({
|
|
56
|
+
padding: collisionPadding,
|
|
57
|
+
apply({ availableHeight, rects }) {
|
|
58
|
+
// Anchor's own size + the free space toward the placement side, published as
|
|
59
|
+
// vars for the styling layer to consume (e.g. `width: var(--anchor-width)`,
|
|
60
|
+
// `max-height: var(--anchor-available-height)`). Never sets width/height itself.
|
|
61
|
+
floating.style.setProperty("--anchor-width", `${Math.round(rects.reference.width)}px`);
|
|
62
|
+
floating.style.setProperty("--anchor-height", `${Math.round(rects.reference.height)}px`);
|
|
63
|
+
floating.style.setProperty("--anchor-available-height", `${Math.max(0, Math.round(availableHeight))}px`);
|
|
64
|
+
},
|
|
65
|
+
}),
|
|
66
|
+
],
|
|
67
|
+
}).then(({ x, y, placement: resolved }) => {
|
|
68
|
+
floating.style.position = "absolute";
|
|
69
|
+
floating.style.left = `${Math.round(x)}px`;
|
|
70
|
+
floating.style.top = `${Math.round(y)}px`;
|
|
71
|
+
const [resolvedSide = side, resolvedAlign = "center"] = resolved.split("-");
|
|
72
|
+
floating.setAttribute("data-side", resolvedSide);
|
|
73
|
+
floating.setAttribute("data-align", resolvedAlign);
|
|
74
|
+
});
|
|
75
|
+
};
|
|
76
|
+
return autoUpdate(reference, floating, update);
|
|
77
|
+
}, [enabled, getAnchor, floatingRef, side, align, sideOffset, collisionPadding, pin]);
|
|
78
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// Vendored from @base-ui/utils v1.6.0 (MIT) — packages/utils/src/reactVersion.ts
|
|
2
|
+
// https://github.com/mui/base-ui — exact copy.
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
const majorVersion = parseInt(React.version, 10);
|
|
5
|
+
export function isReactVersionAtLeast(reactVersionToCheck) {
|
|
6
|
+
return majorVersion >= reactVersionToCheck;
|
|
7
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* If the provided className is a string, it will be returned as is.
|
|
3
|
+
* Otherwise, the function will call the className function with the state as the first argument.
|
|
4
|
+
*
|
|
5
|
+
* @param className
|
|
6
|
+
* @param state
|
|
7
|
+
*/
|
|
8
|
+
export declare function resolveClassName<State>(className: string | ((state: State) => string | undefined) | undefined, state: State): string | undefined;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// Vendored from @base-ui/react v1.6.0 (MIT) — packages/react/src/utils/resolveClassName.ts
|
|
2
|
+
// https://github.com/mui/base-ui — exact copy.
|
|
3
|
+
/**
|
|
4
|
+
* If the provided className is a string, it will be returned as is.
|
|
5
|
+
* Otherwise, the function will call the className function with the state as the first argument.
|
|
6
|
+
*
|
|
7
|
+
* @param className
|
|
8
|
+
* @param state
|
|
9
|
+
*/
|
|
10
|
+
export function resolveClassName(className, state) {
|
|
11
|
+
return typeof className === 'function' ? className(state) : className;
|
|
12
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* If the provided style is an object, it will be returned as is.
|
|
3
|
+
* Otherwise, the function will call the style function with the state as the first argument.
|
|
4
|
+
*
|
|
5
|
+
* @param style
|
|
6
|
+
* @param state
|
|
7
|
+
*/
|
|
8
|
+
export declare function resolveStyle<State>(style: React.CSSProperties | ((state: State) => React.CSSProperties | undefined) | undefined, state: State): import("react").CSSProperties | undefined;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// Vendored from @base-ui/react v1.6.0 (MIT) — packages/react/src/utils/resolveStyle.ts
|
|
2
|
+
// https://github.com/mui/base-ui — exact copy.
|
|
3
|
+
/**
|
|
4
|
+
* If the provided style is an object, it will be returned as is.
|
|
5
|
+
* Otherwise, the function will call the style function with the state as the first argument.
|
|
6
|
+
*
|
|
7
|
+
* @param style
|
|
8
|
+
* @param state
|
|
9
|
+
*/
|
|
10
|
+
export function resolveStyle(style, state) {
|
|
11
|
+
return typeof style === 'function' ? style(state) : style;
|
|
12
|
+
}
|