@octanejs/aria 0.0.4 → 0.0.5
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/package.json +7 -5
- package/src/autocomplete/useAutocomplete.ts +656 -0
- package/src/collections/BaseCollection.ts +374 -0
- package/src/collections/CollectionBuilder.ts +343 -0
- package/src/collections/Document.ts +451 -0
- package/src/collections/Hidden.ts +84 -0
- package/src/collections/useCachedChildren.ts +103 -0
- package/src/components/Autocomplete.ts +124 -0
- package/src/components/Breadcrumbs.ts +170 -0
- package/src/components/Button.ts +209 -0
- package/src/components/Checkbox.ts +593 -0
- package/src/components/Collection.ts +301 -0
- package/src/components/ComboBox.ts +477 -0
- package/src/components/Dialog.ts +195 -0
- package/src/components/Disclosure.ts +322 -0
- package/src/components/DragAndDrop.ts +177 -0
- package/src/components/FieldError.ts +79 -0
- package/src/components/Form.ts +65 -0
- package/src/components/GridList.ts +1099 -0
- package/src/components/Group.ts +146 -0
- package/src/components/Header.ts +32 -0
- package/src/components/Heading.ts +45 -0
- package/src/components/Input.ts +139 -0
- package/src/components/Keyboard.ts +23 -0
- package/src/components/Label.ts +30 -0
- package/src/components/Link.ts +137 -0
- package/src/components/ListBox.ts +886 -0
- package/src/components/Menu.ts +685 -0
- package/src/components/Meter.ts +100 -0
- package/src/components/Modal.ts +352 -0
- package/src/components/NumberField.ts +221 -0
- package/src/components/OverlayArrow.ts +117 -0
- package/src/components/Popover.ts +385 -0
- package/src/components/ProgressBar.ts +112 -0
- package/src/components/RadioGroup.ts +542 -0
- package/src/components/SearchField.ts +208 -0
- package/src/components/Select.ts +505 -0
- package/src/components/SelectionIndicator.ts +52 -0
- package/src/components/Separator.ts +97 -0
- package/src/components/SharedElementTransition.ts +209 -0
- package/src/components/Slider.ts +472 -0
- package/src/components/Switch.ts +449 -0
- package/src/components/Tabs.ts +675 -0
- package/src/components/TagGroup.ts +443 -0
- package/src/components/Text.ts +27 -0
- package/src/components/TextArea.ts +92 -0
- package/src/components/TextField.ts +200 -0
- package/src/components/ToggleButton.ts +147 -0
- package/src/components/ToggleButtonGroup.ts +106 -0
- package/src/components/Toolbar.ts +74 -0
- package/src/components/Tooltip.ts +249 -0
- package/src/components/index.ts +302 -0
- package/src/components/useDragAndDrop.ts +164 -0
- package/src/components/utils.ts +521 -0
- package/src/intl/autocomplete/ar-AE.json +3 -0
- package/src/intl/autocomplete/bg-BG.json +3 -0
- package/src/intl/autocomplete/cs-CZ.json +3 -0
- package/src/intl/autocomplete/da-DK.json +3 -0
- package/src/intl/autocomplete/de-DE.json +3 -0
- package/src/intl/autocomplete/el-GR.json +3 -0
- package/src/intl/autocomplete/en-US.json +3 -0
- package/src/intl/autocomplete/es-ES.json +3 -0
- package/src/intl/autocomplete/et-EE.json +3 -0
- package/src/intl/autocomplete/fi-FI.json +3 -0
- package/src/intl/autocomplete/fr-FR.json +3 -0
- package/src/intl/autocomplete/he-IL.json +3 -0
- package/src/intl/autocomplete/hr-HR.json +3 -0
- package/src/intl/autocomplete/hu-HU.json +3 -0
- package/src/intl/autocomplete/index.ts +75 -0
- package/src/intl/autocomplete/it-IT.json +3 -0
- package/src/intl/autocomplete/ja-JP.json +3 -0
- package/src/intl/autocomplete/ko-KR.json +3 -0
- package/src/intl/autocomplete/lt-LT.json +3 -0
- package/src/intl/autocomplete/lv-LV.json +3 -0
- package/src/intl/autocomplete/nb-NO.json +3 -0
- package/src/intl/autocomplete/nl-NL.json +3 -0
- package/src/intl/autocomplete/pl-PL.json +3 -0
- package/src/intl/autocomplete/pt-BR.json +3 -0
- package/src/intl/autocomplete/pt-PT.json +3 -0
- package/src/intl/autocomplete/ro-RO.json +3 -0
- package/src/intl/autocomplete/ru-RU.json +3 -0
- package/src/intl/autocomplete/sk-SK.json +3 -0
- package/src/intl/autocomplete/sl-SI.json +3 -0
- package/src/intl/autocomplete/sr-SP.json +3 -0
- package/src/intl/autocomplete/sv-SE.json +3 -0
- package/src/intl/autocomplete/tr-TR.json +3 -0
- package/src/intl/autocomplete/uk-UA.json +3 -0
- package/src/intl/autocomplete/zh-CN.json +3 -0
- package/src/intl/autocomplete/zh-TW.json +3 -0
- package/src/stately/autocomplete/useAutocompleteState.ts +85 -0
- package/src/utils/animation.ts +149 -0
- package/src/utils/useLoadMoreSentinel.ts +78 -0
- package/src/utils/useViewportSize.ts +123 -0
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
// Ported from react-aria-components (source: .react-spectrum/packages/react-aria-components/src/useDragAndDrop.tsx).
|
|
2
|
+
// PHASE-7: the react-aria drag-and-drop ENGINE (useDraggableCollection(State),
|
|
3
|
+
// useDroppableCollection(State), useDropIndicator, DragManager, ListDropTargetDelegate)
|
|
4
|
+
// is NOT ported yet. This module ships the `DragAndDropHooks` / `DragAndDropOptions`
|
|
5
|
+
// TYPE surface so collection components can accept a `dragAndDropHooks` prop (their dnd
|
|
6
|
+
// branches stay inert until a consumer can construct hooks), with every engine-referencing
|
|
7
|
+
// member typed via local structural aliases below. The `useDragAndDrop()` function itself
|
|
8
|
+
// is a THROWING STUB (the remix-router framework-stub precedent): importing is safe;
|
|
9
|
+
// CALLING throws with a pointer to the phase plan instead of failing somewhere deep inside.
|
|
10
|
+
// octane adaptations: `.tsx` → `.ts`; `JSX.Element` → a structural `any` alias.
|
|
11
|
+
import type {
|
|
12
|
+
DragItem,
|
|
13
|
+
DraggableCollectionProps,
|
|
14
|
+
DropTarget,
|
|
15
|
+
DropTargetDelegate,
|
|
16
|
+
DroppableCollectionProps,
|
|
17
|
+
Key,
|
|
18
|
+
RefObject,
|
|
19
|
+
} from '@react-types/shared';
|
|
20
|
+
|
|
21
|
+
export { DropIndicator, DropIndicatorContext, DragAndDropContext } from './DragAndDrop';
|
|
22
|
+
export type { DropIndicatorProps, DropIndicatorRenderProps } from './DragAndDrop';
|
|
23
|
+
|
|
24
|
+
// octane adaptation: structural alias for React's JSX.Element.
|
|
25
|
+
type JSXElement = any;
|
|
26
|
+
|
|
27
|
+
// ── PHASE-7 structural aliases ──────────────────────────────────────────────
|
|
28
|
+
// Stand-ins for the unported react-aria/react-stately dnd engine types. They keep
|
|
29
|
+
// `DragAndDropHooks` importable as a TYPE without pulling any engine code; Phase 7
|
|
30
|
+
// replaces them with the real ported definitions.
|
|
31
|
+
/** PHASE-7: react-stately/useDraggableCollectionState's DraggableCollectionState (engine unported). */
|
|
32
|
+
export type DraggableCollectionState = any;
|
|
33
|
+
/** PHASE-7: react-stately/useDraggableCollectionState's DraggableCollectionStateOptions (engine unported). */
|
|
34
|
+
export type DraggableCollectionStateOptions = any;
|
|
35
|
+
/** PHASE-7: react-aria/useDraggableCollection's DraggableCollectionOptions (engine unported). */
|
|
36
|
+
export type DraggableCollectionOptions = any;
|
|
37
|
+
/** PHASE-7: react-aria/useDraggableCollection's DraggableItemProps (engine unported). */
|
|
38
|
+
export type DraggableItemProps = any;
|
|
39
|
+
/** PHASE-7: react-aria/useDraggableCollection's DraggableItemResult (engine unported). */
|
|
40
|
+
export type DraggableItemResult = any;
|
|
41
|
+
/** PHASE-7: react-aria/useDraggableCollection's DragPreview component type (engine unported). */
|
|
42
|
+
export type DragPreview = any;
|
|
43
|
+
/** PHASE-7: react-stately/useDroppableCollectionState's DroppableCollectionState (engine unported). */
|
|
44
|
+
export type DroppableCollectionState = any;
|
|
45
|
+
/** PHASE-7: react-stately/useDroppableCollectionState's DroppableCollectionStateOptions (engine unported). */
|
|
46
|
+
export type DroppableCollectionStateOptions = any;
|
|
47
|
+
/** PHASE-7: react-aria/useDroppableCollection's DroppableCollectionOptions (engine unported). */
|
|
48
|
+
export type DroppableCollectionOptions = any;
|
|
49
|
+
/** PHASE-7: react-aria/useDroppableCollection's DroppableCollectionResult (engine unported). */
|
|
50
|
+
export type DroppableCollectionResult = any;
|
|
51
|
+
/** PHASE-7: react-aria/useDroppableCollection's DroppableItemOptions (engine unported). */
|
|
52
|
+
export type DroppableItemOptions = any;
|
|
53
|
+
/** PHASE-7: react-aria/useDroppableCollection's DroppableItemResult (engine unported). */
|
|
54
|
+
export type DroppableItemResult = any;
|
|
55
|
+
/** PHASE-7: react-aria/useDropIndicator's DropIndicatorProps (engine unported; `target` is real). */
|
|
56
|
+
export interface AriaDropIndicatorProps {
|
|
57
|
+
/** The drop target that the drop indicator represents. */
|
|
58
|
+
target: DropTarget;
|
|
59
|
+
/** PHASE-7: the activate-button ref (engine unported). */
|
|
60
|
+
activateButtonRef?: RefObject<any>;
|
|
61
|
+
}
|
|
62
|
+
/** PHASE-7: react-aria/useDropIndicator's DropIndicatorAria (engine unported). */
|
|
63
|
+
export type DropIndicatorAria = any;
|
|
64
|
+
/** PHASE-7: react-aria/ListDropTargetDelegate's class type (engine unported). */
|
|
65
|
+
export type ListDropTargetDelegate = any;
|
|
66
|
+
|
|
67
|
+
interface DraggableCollectionStateOpts<T = object> extends Omit<
|
|
68
|
+
DraggableCollectionStateOptions,
|
|
69
|
+
'getItems'
|
|
70
|
+
> {}
|
|
71
|
+
|
|
72
|
+
interface DragHooks<T = object> {
|
|
73
|
+
useDraggableCollectionState?: (
|
|
74
|
+
props: DraggableCollectionStateOpts<T>,
|
|
75
|
+
) => DraggableCollectionState;
|
|
76
|
+
useDraggableCollection?: (
|
|
77
|
+
props: DraggableCollectionOptions,
|
|
78
|
+
state: DraggableCollectionState,
|
|
79
|
+
ref: RefObject<HTMLElement | null>,
|
|
80
|
+
) => void;
|
|
81
|
+
useDraggableItem?: (
|
|
82
|
+
props: DraggableItemProps,
|
|
83
|
+
state: DraggableCollectionState,
|
|
84
|
+
) => DraggableItemResult;
|
|
85
|
+
DragPreview?: DragPreview;
|
|
86
|
+
renderDragPreview?: (
|
|
87
|
+
items: DragItem[],
|
|
88
|
+
) => JSXElement | { element: JSXElement; x: number; y: number };
|
|
89
|
+
isVirtualDragging?: () => boolean;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
interface DropHooks {
|
|
93
|
+
useDroppableCollectionState?: (
|
|
94
|
+
props: DroppableCollectionStateOptions,
|
|
95
|
+
) => DroppableCollectionState;
|
|
96
|
+
useDroppableCollection?: (
|
|
97
|
+
props: DroppableCollectionOptions,
|
|
98
|
+
state: DroppableCollectionState,
|
|
99
|
+
ref: RefObject<HTMLElement | null>,
|
|
100
|
+
) => DroppableCollectionResult;
|
|
101
|
+
useDroppableItem?: (
|
|
102
|
+
options: DroppableItemOptions,
|
|
103
|
+
state: DroppableCollectionState,
|
|
104
|
+
ref: RefObject<HTMLElement | null>,
|
|
105
|
+
) => DroppableItemResult;
|
|
106
|
+
useDropIndicator?: (
|
|
107
|
+
props: AriaDropIndicatorProps,
|
|
108
|
+
state: DroppableCollectionState,
|
|
109
|
+
ref: RefObject<HTMLElement | null>,
|
|
110
|
+
) => DropIndicatorAria;
|
|
111
|
+
renderDropIndicator?: (target: DropTarget) => JSXElement;
|
|
112
|
+
dropTargetDelegate?: DropTargetDelegate;
|
|
113
|
+
ListDropTargetDelegate: ListDropTargetDelegate;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export type DragAndDropHooks<T = object> = DragHooks<T> & DropHooks;
|
|
117
|
+
|
|
118
|
+
export interface DragAndDrop<T = object> {
|
|
119
|
+
/** Drag and drop hooks for the collection element. */
|
|
120
|
+
dragAndDropHooks: DragAndDropHooks<T>;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export interface DragAndDropOptions<T = object>
|
|
124
|
+
extends Omit<DraggableCollectionProps, 'preview' | 'getItems'>, DroppableCollectionProps {
|
|
125
|
+
/**
|
|
126
|
+
* A function that returns the items being dragged. If not specified, we assume that the
|
|
127
|
+
* collection is not draggable.
|
|
128
|
+
*
|
|
129
|
+
* @default () => []
|
|
130
|
+
*/
|
|
131
|
+
getItems?: (keys: Set<Key>, items: T[]) => DragItem[];
|
|
132
|
+
/**
|
|
133
|
+
* A function that renders a drag preview, which is shown under the user's cursor while dragging.
|
|
134
|
+
* By default, a copy of the dragged element is rendered.
|
|
135
|
+
*/
|
|
136
|
+
renderDragPreview?: (
|
|
137
|
+
items: DragItem[],
|
|
138
|
+
) => JSXElement | { element: JSXElement; x: number; y: number };
|
|
139
|
+
/**
|
|
140
|
+
* A function that renders a drop indicator element between two items in a collection.
|
|
141
|
+
* This should render a `<DropIndicator>` element. If this function is not provided, a
|
|
142
|
+
* default DropIndicator is provided.
|
|
143
|
+
*/
|
|
144
|
+
renderDropIndicator?: (target: DropTarget) => JSXElement;
|
|
145
|
+
/**
|
|
146
|
+
* A custom delegate object that provides drop targets for pointer coordinates within the
|
|
147
|
+
* collection.
|
|
148
|
+
*/
|
|
149
|
+
dropTargetDelegate?: DropTargetDelegate;
|
|
150
|
+
/** Whether the drag and drop events should be disabled. */
|
|
151
|
+
isDisabled?: boolean;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Provides the hooks required to enable drag and drop behavior for a drag and drop compatible
|
|
156
|
+
* collection component.
|
|
157
|
+
*
|
|
158
|
+
* PHASE-7: throwing stub — the dnd engine is not ported yet.
|
|
159
|
+
*/
|
|
160
|
+
export function useDragAndDrop<T = object>(options: DragAndDropOptions<T>): DragAndDrop<T> {
|
|
161
|
+
throw new Error(
|
|
162
|
+
'@octanejs/aria: useDragAndDrop is not ported yet (drag and drop arrives in a later phase)',
|
|
163
|
+
);
|
|
164
|
+
}
|
|
@@ -0,0 +1,521 @@
|
|
|
1
|
+
// Ported from react-aria-components (source: .react-spectrum/packages/react-aria-components/src/utils.tsx).
|
|
2
|
+
// octane adaptations: `.tsx` → `.ts`, JSX → `createElement`; NO forwardRef — octane refs are
|
|
3
|
+
// ordinary props, so `useContextProps(props, ref, context)` keeps its upstream shape but the
|
|
4
|
+
// `ref` argument is the caller's `props.ref` (and the local `ref` key is stripped from the
|
|
5
|
+
// returned merged props — it is already folded into the returned merged object ref); the `dom`
|
|
6
|
+
// proxy caches plain bound components instead of forwardRef wrappers; public hooks get the
|
|
7
|
+
// binding's slot threading (splitSlot/subSlot) — `useSlottedContext` composes only the
|
|
8
|
+
// context-identity-keyed `useContext` but still strips a trailing injected slot symbol so its
|
|
9
|
+
// optional user args stay positionally sound; `useSlot` re-exports the identical react-aria
|
|
10
|
+
// hook from `../utils/useSlot`; React's CSSProperties/ReactNode/JSX-intrinsics types → minimal
|
|
11
|
+
// structural aliases (`E extends string`); explicit dep arrays are preserved verbatim.
|
|
12
|
+
import type { AriaLabelingProps, DOMProps as SharedDOMProps } from '@react-types/shared';
|
|
13
|
+
import { type Context, createElement, useContext, useMemo, useRef } from 'octane';
|
|
14
|
+
|
|
15
|
+
import { S, splitSlot, subSlot } from '../internal';
|
|
16
|
+
import { type MergableRef, mergeRefs } from '../utils/mergeRefs';
|
|
17
|
+
import { mergeProps } from '../utils/mergeProps';
|
|
18
|
+
import { useLayoutEffect } from '../utils/useLayoutEffect';
|
|
19
|
+
import { useObjectRef } from '../utils/useObjectRef';
|
|
20
|
+
|
|
21
|
+
// Identical implementation upstream duplicates in RAC's utils; import, don't duplicate.
|
|
22
|
+
export { useSlot } from '../utils/useSlot';
|
|
23
|
+
|
|
24
|
+
// octane adaptations: minimal structural aliases for the React types upstream drags along.
|
|
25
|
+
export type CSSProperties = Record<string, any>;
|
|
26
|
+
type ReactNode = any;
|
|
27
|
+
type ReactElement = any;
|
|
28
|
+
type ElementProps = Record<string, any>;
|
|
29
|
+
type MutableRefObject<T> = { current: T };
|
|
30
|
+
|
|
31
|
+
export const DEFAULT_SLOT = Symbol('default');
|
|
32
|
+
|
|
33
|
+
interface SlottedValue<T> {
|
|
34
|
+
slots?: Record<string | symbol, T>;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export type SlottedContextValue<T> = SlottedValue<T> | T | null | undefined;
|
|
38
|
+
export type ContextValue<T, E> = SlottedContextValue<WithRef<T, E>>;
|
|
39
|
+
|
|
40
|
+
type ProviderValue<T> = [Context<SlottedContextValue<T>>, SlottedContextValue<T>];
|
|
41
|
+
type ProviderValues<A, B, C, D, E, F, G, H, I, J, K, L> =
|
|
42
|
+
| [ProviderValue<A>]
|
|
43
|
+
| [ProviderValue<A>, ProviderValue<B>]
|
|
44
|
+
| [ProviderValue<A>, ProviderValue<B>, ProviderValue<C>]
|
|
45
|
+
| [ProviderValue<A>, ProviderValue<B>, ProviderValue<C>, ProviderValue<D>]
|
|
46
|
+
| [ProviderValue<A>, ProviderValue<B>, ProviderValue<C>, ProviderValue<D>, ProviderValue<E>]
|
|
47
|
+
| [
|
|
48
|
+
ProviderValue<A>,
|
|
49
|
+
ProviderValue<B>,
|
|
50
|
+
ProviderValue<C>,
|
|
51
|
+
ProviderValue<D>,
|
|
52
|
+
ProviderValue<E>,
|
|
53
|
+
ProviderValue<F>,
|
|
54
|
+
]
|
|
55
|
+
| [
|
|
56
|
+
ProviderValue<A>,
|
|
57
|
+
ProviderValue<B>,
|
|
58
|
+
ProviderValue<C>,
|
|
59
|
+
ProviderValue<D>,
|
|
60
|
+
ProviderValue<E>,
|
|
61
|
+
ProviderValue<F>,
|
|
62
|
+
ProviderValue<G>,
|
|
63
|
+
]
|
|
64
|
+
| [
|
|
65
|
+
ProviderValue<A>,
|
|
66
|
+
ProviderValue<B>,
|
|
67
|
+
ProviderValue<C>,
|
|
68
|
+
ProviderValue<D>,
|
|
69
|
+
ProviderValue<E>,
|
|
70
|
+
ProviderValue<F>,
|
|
71
|
+
ProviderValue<G>,
|
|
72
|
+
ProviderValue<H>,
|
|
73
|
+
]
|
|
74
|
+
| [
|
|
75
|
+
ProviderValue<A>,
|
|
76
|
+
ProviderValue<B>,
|
|
77
|
+
ProviderValue<C>,
|
|
78
|
+
ProviderValue<D>,
|
|
79
|
+
ProviderValue<E>,
|
|
80
|
+
ProviderValue<F>,
|
|
81
|
+
ProviderValue<G>,
|
|
82
|
+
ProviderValue<H>,
|
|
83
|
+
ProviderValue<I>,
|
|
84
|
+
]
|
|
85
|
+
| [
|
|
86
|
+
ProviderValue<A>,
|
|
87
|
+
ProviderValue<B>,
|
|
88
|
+
ProviderValue<C>,
|
|
89
|
+
ProviderValue<D>,
|
|
90
|
+
ProviderValue<E>,
|
|
91
|
+
ProviderValue<F>,
|
|
92
|
+
ProviderValue<G>,
|
|
93
|
+
ProviderValue<H>,
|
|
94
|
+
ProviderValue<I>,
|
|
95
|
+
ProviderValue<J>,
|
|
96
|
+
]
|
|
97
|
+
| [
|
|
98
|
+
ProviderValue<A>,
|
|
99
|
+
ProviderValue<B>,
|
|
100
|
+
ProviderValue<C>,
|
|
101
|
+
ProviderValue<D>,
|
|
102
|
+
ProviderValue<E>,
|
|
103
|
+
ProviderValue<F>,
|
|
104
|
+
ProviderValue<G>,
|
|
105
|
+
ProviderValue<H>,
|
|
106
|
+
ProviderValue<I>,
|
|
107
|
+
ProviderValue<J>,
|
|
108
|
+
ProviderValue<K>,
|
|
109
|
+
]
|
|
110
|
+
| [
|
|
111
|
+
ProviderValue<A>,
|
|
112
|
+
ProviderValue<B>,
|
|
113
|
+
ProviderValue<C>,
|
|
114
|
+
ProviderValue<D>,
|
|
115
|
+
ProviderValue<E>,
|
|
116
|
+
ProviderValue<F>,
|
|
117
|
+
ProviderValue<G>,
|
|
118
|
+
ProviderValue<H>,
|
|
119
|
+
ProviderValue<I>,
|
|
120
|
+
ProviderValue<J>,
|
|
121
|
+
ProviderValue<K>,
|
|
122
|
+
ProviderValue<L>,
|
|
123
|
+
];
|
|
124
|
+
|
|
125
|
+
interface ProviderProps<A, B, C, D, E, F, G, H, I, J, K, L> {
|
|
126
|
+
values: ProviderValues<A, B, C, D, E, F, G, H, I, J, K, L>;
|
|
127
|
+
children: ReactNode;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// No hooks (Provider nests plain Context.Provider descriptors), so no slot threading. The
|
|
131
|
+
// descriptor `{ value, children }` shape stays stable per values entry (see aria memory
|
|
132
|
+
// octane-provider-children-shape-flip).
|
|
133
|
+
export function Provider<A, B, C, D, E, F, G, H, I, J, K, L>(
|
|
134
|
+
props: ProviderProps<A, B, C, D, E, F, G, H, I, J, K, L>,
|
|
135
|
+
): any {
|
|
136
|
+
let { values, children } = props;
|
|
137
|
+
for (let [Context, value] of values) {
|
|
138
|
+
children = createElement((Context as any).Provider, { value, children });
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return children;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export interface StyleProps {
|
|
145
|
+
/**
|
|
146
|
+
* The CSS [className](https://developer.mozilla.org/en-US/docs/Web/API/Element/className) for the
|
|
147
|
+
* element.
|
|
148
|
+
*/
|
|
149
|
+
className?: string;
|
|
150
|
+
/**
|
|
151
|
+
* The inline [style](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/style) for the
|
|
152
|
+
* element.
|
|
153
|
+
*/
|
|
154
|
+
style?: CSSProperties;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
export interface DOMProps extends StyleProps, SharedDOMProps {
|
|
158
|
+
/** The children of the component. */
|
|
159
|
+
children?: ReactNode;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
export type ClassNameOrFunction<T> =
|
|
163
|
+
| string
|
|
164
|
+
| ((values: T & { defaultClassName: string | undefined }) => string);
|
|
165
|
+
type StyleOrFunction<T> =
|
|
166
|
+
| CSSProperties
|
|
167
|
+
| ((values: T & { defaultStyle: CSSProperties }) => CSSProperties | undefined);
|
|
168
|
+
|
|
169
|
+
export interface StyleRenderProps<T, E extends string = 'div'> extends DOMRenderProps<E, T> {
|
|
170
|
+
/**
|
|
171
|
+
* The CSS [className](https://developer.mozilla.org/en-US/docs/Web/API/Element/className) for the
|
|
172
|
+
* element. A function may be provided to compute the class based on component state.
|
|
173
|
+
*/
|
|
174
|
+
className?: ClassNameOrFunction<T>;
|
|
175
|
+
/**
|
|
176
|
+
* The inline [style](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/style) for the
|
|
177
|
+
* element. A function may be provided to compute the style based on component state.
|
|
178
|
+
*/
|
|
179
|
+
style?: StyleOrFunction<T>;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
export type ChildrenOrFunction<T> =
|
|
183
|
+
| ReactNode
|
|
184
|
+
| ((values: T & { defaultChildren: ReactNode | undefined }) => ReactNode);
|
|
185
|
+
|
|
186
|
+
export interface RenderProps<T, E extends string = 'div'> extends StyleRenderProps<T, E> {
|
|
187
|
+
/**
|
|
188
|
+
* The children of the component. A function may be provided to alter the children based on
|
|
189
|
+
* component state.
|
|
190
|
+
*/
|
|
191
|
+
children?: ChildrenOrFunction<T>;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
interface RenderPropsHookOptions<T, E extends string>
|
|
195
|
+
extends RenderProps<T, E>, SharedDOMProps, AriaLabelingProps {
|
|
196
|
+
values: T;
|
|
197
|
+
defaultChildren?: ReactNode;
|
|
198
|
+
defaultClassName?: string;
|
|
199
|
+
defaultStyle?: CSSProperties;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
interface RenderPropsHookRetVal<T, E extends string> {
|
|
203
|
+
className?: string;
|
|
204
|
+
style?: CSSProperties;
|
|
205
|
+
children?: ReactNode;
|
|
206
|
+
'data-rac': string;
|
|
207
|
+
render?: DOMRenderFunction<E, T>;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
export function useRenderProps<T, E extends string = 'div'>(
|
|
211
|
+
props: RenderPropsHookOptions<T, E>,
|
|
212
|
+
): RenderPropsHookRetVal<T, E>;
|
|
213
|
+
// Slot-threading form: sibling ported hooks pass their derived sub-slot as the trailing arg.
|
|
214
|
+
export function useRenderProps<T, E extends string = 'div'>(
|
|
215
|
+
props: RenderPropsHookOptions<T, E>,
|
|
216
|
+
slot: symbol | undefined,
|
|
217
|
+
): RenderPropsHookRetVal<T, E>;
|
|
218
|
+
export function useRenderProps(...args: any[]): RenderPropsHookRetVal<any, any> {
|
|
219
|
+
const [user, slotArg] = splitSlot(args);
|
|
220
|
+
const slot = slotArg ?? S('useRenderProps');
|
|
221
|
+
const props = user[0] as RenderPropsHookOptions<any, any>;
|
|
222
|
+
|
|
223
|
+
let {
|
|
224
|
+
className,
|
|
225
|
+
style,
|
|
226
|
+
children,
|
|
227
|
+
defaultClassName = undefined,
|
|
228
|
+
defaultChildren = undefined,
|
|
229
|
+
defaultStyle,
|
|
230
|
+
values,
|
|
231
|
+
render,
|
|
232
|
+
} = props;
|
|
233
|
+
|
|
234
|
+
return useMemo(
|
|
235
|
+
() => {
|
|
236
|
+
let computedClassName: string | undefined;
|
|
237
|
+
let computedStyle: CSSProperties | undefined;
|
|
238
|
+
let computedChildren: ReactNode | undefined;
|
|
239
|
+
|
|
240
|
+
if (typeof className === 'function') {
|
|
241
|
+
computedClassName = className({ ...values, defaultClassName });
|
|
242
|
+
} else {
|
|
243
|
+
computedClassName = className;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
if (typeof style === 'function') {
|
|
247
|
+
computedStyle = style({ ...values, defaultStyle: defaultStyle || {} });
|
|
248
|
+
} else {
|
|
249
|
+
computedStyle = style;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
if (typeof children === 'function') {
|
|
253
|
+
computedChildren = children({ ...values, defaultChildren });
|
|
254
|
+
} else if (children == null) {
|
|
255
|
+
computedChildren = defaultChildren;
|
|
256
|
+
} else {
|
|
257
|
+
computedChildren = children;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
return {
|
|
261
|
+
className: computedClassName ?? defaultClassName,
|
|
262
|
+
style: computedStyle || defaultStyle ? { ...defaultStyle, ...computedStyle } : undefined,
|
|
263
|
+
children: computedChildren ?? defaultChildren,
|
|
264
|
+
'data-rac': '',
|
|
265
|
+
render: render ? (props: ElementProps) => render(props, values) : undefined,
|
|
266
|
+
};
|
|
267
|
+
},
|
|
268
|
+
[className, style, children, defaultClassName, defaultChildren, defaultStyle, values, render],
|
|
269
|
+
subSlot(slot, 'result'),
|
|
270
|
+
);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* A helper function that accepts a user-provided render prop value (either a static value or a
|
|
275
|
+
* function), and combines it with another value to create a final result.
|
|
276
|
+
*/
|
|
277
|
+
export function composeRenderProps<T, U, V extends T>(
|
|
278
|
+
// https://stackoverflow.com/questions/60898079/typescript-type-t-or-function-t-usage
|
|
279
|
+
value: T extends any ? T | ((renderProps: U) => V) : never,
|
|
280
|
+
wrap: (prevValue: T, renderProps: U) => V,
|
|
281
|
+
): (renderProps: U) => V {
|
|
282
|
+
return (renderProps) =>
|
|
283
|
+
wrap(typeof value === 'function' ? (value as any)(renderProps) : value, renderProps);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
export type WithRef<T, E> = T & { ref?: MergableRef<E> };
|
|
287
|
+
export interface SlotProps {
|
|
288
|
+
/**
|
|
289
|
+
* A slot name for the component. Slots allow the component to receive props from a parent
|
|
290
|
+
* component. An explicit `null` value indicates that the local props completely override all
|
|
291
|
+
* props received from a parent.
|
|
292
|
+
*/
|
|
293
|
+
slot?: string | null;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
// The user `slot` argument is a string | null | undefined — never a symbol; a trailing symbol
|
|
297
|
+
// is always the compiler-injected call-site slot and is stripped (useContext itself is
|
|
298
|
+
// context-identity keyed, so nothing here consumes it).
|
|
299
|
+
export function useSlottedContext<T>(
|
|
300
|
+
context: Context<SlottedContextValue<T>>,
|
|
301
|
+
slot?: string | null,
|
|
302
|
+
): T | null | undefined;
|
|
303
|
+
// Slot-threading form: sibling ported hooks pass their derived sub-slot as the trailing arg.
|
|
304
|
+
export function useSlottedContext<T>(
|
|
305
|
+
context: Context<SlottedContextValue<T>>,
|
|
306
|
+
slot: string | null | undefined,
|
|
307
|
+
slotSymbol: symbol | undefined,
|
|
308
|
+
): T | null | undefined;
|
|
309
|
+
export function useSlottedContext(...args: any[]): any {
|
|
310
|
+
const [user] = splitSlot(args);
|
|
311
|
+
const context = user[0] as Context<SlottedContextValue<any>>;
|
|
312
|
+
const slot = user[1] as string | null | undefined;
|
|
313
|
+
|
|
314
|
+
let ctx = useContext(context);
|
|
315
|
+
if (slot === null) {
|
|
316
|
+
// An explicit `null` slot means don't use context.
|
|
317
|
+
return null;
|
|
318
|
+
}
|
|
319
|
+
if (ctx && typeof ctx === 'object' && 'slots' in ctx && ctx.slots) {
|
|
320
|
+
let slotKey = slot || DEFAULT_SLOT;
|
|
321
|
+
if (!ctx.slots[slotKey]) {
|
|
322
|
+
let availableSlots = new Intl.ListFormat().format(
|
|
323
|
+
Object.keys(ctx.slots).map((p) => `"${p}"`),
|
|
324
|
+
);
|
|
325
|
+
let errorMessage = slot ? `Invalid slot "${slot}".` : 'A slot prop is required.';
|
|
326
|
+
|
|
327
|
+
throw new Error(`${errorMessage} Valid slot names are ${availableSlots}.`);
|
|
328
|
+
}
|
|
329
|
+
return ctx.slots[slotKey];
|
|
330
|
+
}
|
|
331
|
+
return ctx;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
// octane ref-as-prop: `ref` is the caller's `props.ref`, passed explicitly so the merged object
|
|
335
|
+
// ref folds it in with the context ref. The local `ref` key is stripped from the returned merged
|
|
336
|
+
// props — spread the returned props and pass the returned ref separately, exactly like upstream.
|
|
337
|
+
export function useContextProps<T, U extends SlotProps, E extends Element>(
|
|
338
|
+
props: T & SlotProps,
|
|
339
|
+
ref: MergableRef<E> | undefined,
|
|
340
|
+
context: Context<ContextValue<U, E>>,
|
|
341
|
+
): [T, MutableRefObject<E | null>];
|
|
342
|
+
// Slot-threading form: sibling ported hooks pass their derived sub-slot as the trailing arg.
|
|
343
|
+
export function useContextProps<T, U extends SlotProps, E extends Element>(
|
|
344
|
+
props: T & SlotProps,
|
|
345
|
+
ref: MergableRef<E> | undefined,
|
|
346
|
+
context: Context<ContextValue<U, E>>,
|
|
347
|
+
slot: symbol | undefined,
|
|
348
|
+
): [T, MutableRefObject<E | null>];
|
|
349
|
+
export function useContextProps(...args: any[]): [any, MutableRefObject<any>] {
|
|
350
|
+
const [user, slotArg] = splitSlot(args);
|
|
351
|
+
const slot = slotArg ?? S('useContextProps');
|
|
352
|
+
const props = user[0] as SlotProps & Record<string, any>;
|
|
353
|
+
const ref = user[1] as MergableRef<any> | undefined;
|
|
354
|
+
const context = user[2] as Context<ContextValue<any, any>>;
|
|
355
|
+
|
|
356
|
+
let ctx = useSlottedContext(context, props.slot) || {};
|
|
357
|
+
let { ref: contextRef, ...contextProps } = ctx as any;
|
|
358
|
+
let mergedRef = useObjectRef(
|
|
359
|
+
useMemo(() => mergeRefs(ref, contextRef), [ref, contextRef], subSlot(slot, 'mergeRefs')),
|
|
360
|
+
subSlot(slot, 'objectRef'),
|
|
361
|
+
);
|
|
362
|
+
// octane adaptation: the local `ref` prop is already folded into `mergedRef` via the `ref`
|
|
363
|
+
// argument above; keep it out of the merged props so a bare spread can't re-apply it.
|
|
364
|
+
let { ref: _localRef, ...localProps } = props as any;
|
|
365
|
+
let mergedProps = mergeProps(contextProps, localProps) as any;
|
|
366
|
+
|
|
367
|
+
// mergeProps does not merge `style`. Adding this there might be a breaking change.
|
|
368
|
+
if ('style' in contextProps && contextProps.style && 'style' in props && props.style) {
|
|
369
|
+
if (typeof contextProps.style === 'function' || typeof props.style === 'function') {
|
|
370
|
+
mergedProps.style = (renderProps: any) => {
|
|
371
|
+
let contextStyle =
|
|
372
|
+
typeof contextProps.style === 'function'
|
|
373
|
+
? contextProps.style(renderProps)
|
|
374
|
+
: contextProps.style;
|
|
375
|
+
let defaultStyle = { ...renderProps.defaultStyle, ...contextStyle };
|
|
376
|
+
let style =
|
|
377
|
+
typeof props.style === 'function'
|
|
378
|
+
? (props.style as any)({ ...renderProps, defaultStyle })
|
|
379
|
+
: props.style;
|
|
380
|
+
return { ...defaultStyle, ...style };
|
|
381
|
+
};
|
|
382
|
+
} else {
|
|
383
|
+
mergedProps.style = { ...contextProps.style, ...props.style };
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
return [mergedProps, mergedRef];
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
/**
|
|
391
|
+
* Filters out `data-*` attributes to keep them from being passed down and duplicated.
|
|
392
|
+
*
|
|
393
|
+
* @param props
|
|
394
|
+
*/
|
|
395
|
+
export function removeDataAttributes<T>(props: T): T {
|
|
396
|
+
const prefix = /^(data-.*)$/;
|
|
397
|
+
let filteredProps = {} as T;
|
|
398
|
+
|
|
399
|
+
for (const prop in props) {
|
|
400
|
+
if (!prefix.test(prop)) {
|
|
401
|
+
filteredProps[prop] = props[prop];
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
return filteredProps;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
// Override base type to change the default.
|
|
409
|
+
export interface RACValidation {
|
|
410
|
+
/**
|
|
411
|
+
* Whether to use native HTML form validation to prevent form submission
|
|
412
|
+
* when the value is missing or invalid, or mark the field as required
|
|
413
|
+
* or invalid via ARIA.
|
|
414
|
+
*
|
|
415
|
+
* @default 'native'
|
|
416
|
+
*/
|
|
417
|
+
validationBehavior?: 'native' | 'aria';
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
export type DOMRenderFunction<E extends string, T> = (
|
|
421
|
+
props: ElementProps,
|
|
422
|
+
renderProps: T,
|
|
423
|
+
) => ReactElement;
|
|
424
|
+
export interface DOMRenderProps<E extends string, T> {
|
|
425
|
+
/**
|
|
426
|
+
* Overrides the default DOM element with a custom render function.
|
|
427
|
+
* This allows rendering existing components with built-in styles and behaviors
|
|
428
|
+
* such as router links, animation libraries, and pre-styled components.
|
|
429
|
+
*
|
|
430
|
+
* Requirements:
|
|
431
|
+
*
|
|
432
|
+
* - You must render the expected element type (e.g. if `<button>` is expected, you cannot render an
|
|
433
|
+
* `<a>`).
|
|
434
|
+
* - Only a single root DOM element can be rendered (no fragments).
|
|
435
|
+
* - You must pass through props and ref to the underlying DOM element, merging with your own prop
|
|
436
|
+
* as appropriate.
|
|
437
|
+
*/
|
|
438
|
+
render?: DOMRenderFunction<E, T>;
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
// Same as DOMRenderProps but specific for the case where the element could be a 'a' or 'div' element.
|
|
442
|
+
export interface PossibleLinkDOMRenderProps<Fallback extends string, T> {
|
|
443
|
+
/**
|
|
444
|
+
* Overrides the default DOM element with a custom render function.
|
|
445
|
+
* This allows rendering existing components with built-in styles and behaviors
|
|
446
|
+
* such as router links, animation libraries, and pre-styled components.
|
|
447
|
+
*
|
|
448
|
+
* Note: You can check if `'href' in props` in order to tell whether to render an `<a>` element.
|
|
449
|
+
*
|
|
450
|
+
* Requirements:
|
|
451
|
+
*
|
|
452
|
+
* - You must render the expected element type (e.g. if `<a>` is expected, you cannot render a
|
|
453
|
+
* `<button>`).
|
|
454
|
+
* - Only a single root DOM element can be rendered (no fragments).
|
|
455
|
+
* - You must pass through props and ref to the underlying DOM element, merging with your own prop
|
|
456
|
+
* as appropriate.
|
|
457
|
+
*/
|
|
458
|
+
render?: (props: ElementProps, renderProps: T) => ReactElement;
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
// octane adaptation: the forwarded ref arrives as `props.ref` (no forwardRef). The component
|
|
462
|
+
// runs in its own per-instance scope, so the shared S('DOMElement') slot is distinct per use.
|
|
463
|
+
function DOMElement(ElementType: string, props: DOMRenderProps<any, any> & ElementProps): any {
|
|
464
|
+
const slot = S('DOMElement');
|
|
465
|
+
let { render, ref: forwardedRef, ...otherProps } = props;
|
|
466
|
+
let elementRef: MutableRefObject<HTMLElement | null> = useRef(null, subSlot(slot, 'element'));
|
|
467
|
+
let ref = useMemo(
|
|
468
|
+
() => mergeRefs(forwardedRef, elementRef),
|
|
469
|
+
[forwardedRef, elementRef],
|
|
470
|
+
subSlot(slot, 'ref'),
|
|
471
|
+
);
|
|
472
|
+
|
|
473
|
+
useLayoutEffect(
|
|
474
|
+
() => {
|
|
475
|
+
if (process.env.NODE_ENV !== 'production' && render) {
|
|
476
|
+
if (!elementRef.current) {
|
|
477
|
+
console.warn(
|
|
478
|
+
'Ref was not connected to DOM element returned by custom `render` function. Did you forget to pass through or merge the `ref`?',
|
|
479
|
+
);
|
|
480
|
+
} else if (elementRef.current.localName !== ElementType) {
|
|
481
|
+
console.warn(
|
|
482
|
+
`Unexpected DOM element returned by custom \`render\` function. Expected <${ElementType}>, got <${elementRef.current.localName}>. This may break the component behavior and accessibility.`,
|
|
483
|
+
);
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
},
|
|
487
|
+
[ElementType, render],
|
|
488
|
+
subSlot(slot, 'validate'),
|
|
489
|
+
);
|
|
490
|
+
|
|
491
|
+
let domProps: any = { ...otherProps, ref };
|
|
492
|
+
if (render) {
|
|
493
|
+
return render(domProps, undefined);
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
return createElement(ElementType, domProps);
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
type DOMComponents = Record<string, (props: DOMRenderProps<any, any> & ElementProps) => any>;
|
|
500
|
+
|
|
501
|
+
const domComponentCache: Record<string, any> = {};
|
|
502
|
+
|
|
503
|
+
// Dynamically generates and caches components for each DOM element (e.g. `dom.button`).
|
|
504
|
+
export const dom = new Proxy(
|
|
505
|
+
{},
|
|
506
|
+
{
|
|
507
|
+
get(target, elementType) {
|
|
508
|
+
if (typeof elementType !== 'string') {
|
|
509
|
+
return undefined;
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
let res = domComponentCache[elementType];
|
|
513
|
+
if (!res) {
|
|
514
|
+
res = DOMElement.bind(null, elementType);
|
|
515
|
+
domComponentCache[elementType] = res;
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
return res;
|
|
519
|
+
},
|
|
520
|
+
},
|
|
521
|
+
) as DOMComponents;
|