@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,343 @@
|
|
|
1
|
+
// Ported from react-aria (source: .react-spectrum/packages/react-aria/src/collections/CollectionBuilder.tsx).
|
|
2
|
+
// octane adaptations (docs/aria-migration-plan.md §2a — the detached-real-DOM
|
|
3
|
+
// collection host):
|
|
4
|
+
// - The hidden structural copy renders through `Hidden` via octane
|
|
5
|
+
// `createPortal` into the Document's DETACHED real container (upstream:
|
|
6
|
+
// a React portal into the fake Document). `CollectionRoot` therefore does
|
|
7
|
+
// not portal again — its subtree is already inside the hidden portal — it
|
|
8
|
+
// only flips the contexts (doc → null so nested Collections render inline,
|
|
9
|
+
// shallow → the Document so leaf/branch wrappers render placeholders).
|
|
10
|
+
// - `ShallowRenderContext` carries the owning `Document` instead of upstream's
|
|
11
|
+
// boolean: real placeholder elements have no `ownerDocument` back-pointer to
|
|
12
|
+
// the store (upstream's fake elements do), so the ref-registration callback
|
|
13
|
+
// reads the Document from context. `isShallow` ≙ `doc != null`.
|
|
14
|
+
// - Leaf/branch placeholder refs register `(NodeClass, props, rendered,
|
|
15
|
+
// render)` through `Document.setElementProps` — the user-visible JSX is
|
|
16
|
+
// cached on the node (`rendered`/`render`), NOT rendered in the hidden tree,
|
|
17
|
+
// exactly upstream's contract.
|
|
18
|
+
// - React 16/17 useSyncExternalStore shim fallback dropped (octane's native
|
|
19
|
+
// useSyncExternalStore supports getServerSnapshot).
|
|
20
|
+
// - `.tsx` → `.ts` (JSX → createElement), no forwardRef (octane refs are
|
|
21
|
+
// props), S()/subSlot slot conventions; hooks may sit behind conditions
|
|
22
|
+
// (octane hooks are slot-keyed, so upstream's rules-of-hooks escape comments
|
|
23
|
+
// collapse away).
|
|
24
|
+
// - SSR follows upstream's render-phase in-order registration path against the
|
|
25
|
+
// Document's lightweight SSR tree. PHASE-8: SSR/hydration coverage deferred.
|
|
26
|
+
import type { Key, Node } from '@react-types/shared';
|
|
27
|
+
import {
|
|
28
|
+
Fragment,
|
|
29
|
+
createContext,
|
|
30
|
+
createElement,
|
|
31
|
+
useCallback,
|
|
32
|
+
useContext,
|
|
33
|
+
useMemo,
|
|
34
|
+
useState,
|
|
35
|
+
useSyncExternalStore,
|
|
36
|
+
} from 'octane';
|
|
37
|
+
import { BaseCollection, CollectionNode } from './BaseCollection';
|
|
38
|
+
import { Document, ElementNode } from './Document';
|
|
39
|
+
import { CachedChildrenOptions, useCachedChildren } from './useCachedChildren';
|
|
40
|
+
import { FocusableContext } from '../interactions/useFocusable';
|
|
41
|
+
import { Hidden } from './Hidden';
|
|
42
|
+
import { useIsSSR } from '../ssr/SSRProvider';
|
|
43
|
+
|
|
44
|
+
import { S, subSlot } from '../internal';
|
|
45
|
+
|
|
46
|
+
// octane adaptation: carries the owning Document (not a boolean) so placeholder
|
|
47
|
+
// refs can reach the store; a non-null value means "shallow render".
|
|
48
|
+
const ShallowRenderContext = createContext<Document<any, BaseCollection<any>> | null>(null);
|
|
49
|
+
const CollectionDocumentContext = createContext<Document<any, BaseCollection<any>> | null>(null);
|
|
50
|
+
|
|
51
|
+
export interface CollectionBuilderProps<C extends BaseCollection<any>> {
|
|
52
|
+
content: any;
|
|
53
|
+
children: (collection: C) => any;
|
|
54
|
+
createCollection?: () => C;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Builds a `Collection` from the children provided to the `content` prop, and passes it to the
|
|
59
|
+
* child render prop function.
|
|
60
|
+
*/
|
|
61
|
+
export function CollectionBuilder<C extends BaseCollection<any>>(
|
|
62
|
+
props: CollectionBuilderProps<C>,
|
|
63
|
+
): any {
|
|
64
|
+
const slot = S('CollectionBuilder');
|
|
65
|
+
// If a document was provided above us, we're already in a hidden tree. Just render the content.
|
|
66
|
+
let doc = useContext(CollectionDocumentContext);
|
|
67
|
+
if (doc) {
|
|
68
|
+
return props.content;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Otherwise, render a hidden copy of the children so that we can build the collection
|
|
72
|
+
// before constructing the state. This should always come before the real DOM content so
|
|
73
|
+
// we have built the collection by the time it renders during SSR.
|
|
74
|
+
let { collection, document } = useCollectionDocument<any, C>(
|
|
75
|
+
props.createCollection,
|
|
76
|
+
subSlot(slot, 'doc'),
|
|
77
|
+
);
|
|
78
|
+
return createElement(
|
|
79
|
+
Fragment,
|
|
80
|
+
null,
|
|
81
|
+
createElement(Hidden, {
|
|
82
|
+
target: document.getRootElement(),
|
|
83
|
+
children: createElement(CollectionDocumentContext.Provider, {
|
|
84
|
+
value: document,
|
|
85
|
+
children: props.content,
|
|
86
|
+
}),
|
|
87
|
+
}),
|
|
88
|
+
createElement(CollectionInner, { render: props.children, collection }),
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function CollectionInner(props: { collection: any; render: (collection: any) => any }): any {
|
|
93
|
+
return props.render(props.collection);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
interface CollectionDocumentResult<T, C extends BaseCollection<T>> {
|
|
97
|
+
collection: C;
|
|
98
|
+
document: Document<T, C>;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function useCollectionDocument<T extends object, C extends BaseCollection<T>>(
|
|
102
|
+
createCollection: (() => C) | undefined,
|
|
103
|
+
slot: symbol | undefined,
|
|
104
|
+
): CollectionDocumentResult<T, C> {
|
|
105
|
+
// The document instance is mutable, and should never change between renders.
|
|
106
|
+
// useSyncExternalStore is used to subscribe to updates, which vends immutable
|
|
107
|
+
// Collection objects.
|
|
108
|
+
let [document] = useState(
|
|
109
|
+
() => new Document<T, C>(createCollection?.() || (new BaseCollection() as C)),
|
|
110
|
+
subSlot(slot, 'document'),
|
|
111
|
+
);
|
|
112
|
+
let subscribe = useCallback(
|
|
113
|
+
(fn: () => void) => document.subscribe(fn),
|
|
114
|
+
[document],
|
|
115
|
+
subSlot(slot, 'subscribe'),
|
|
116
|
+
);
|
|
117
|
+
let getSnapshot = useCallback(
|
|
118
|
+
() => {
|
|
119
|
+
let collection = document.getCollection();
|
|
120
|
+
if (document.isSSR) {
|
|
121
|
+
// After SSR is complete, reset the document to empty so it is ready for the
|
|
122
|
+
// client to render the portal into. We do this _after_ getting the collection
|
|
123
|
+
// above so that the collection still has content in it from SSR during the
|
|
124
|
+
// current render, before the client render has finished.
|
|
125
|
+
document.resetAfterSSR();
|
|
126
|
+
}
|
|
127
|
+
return collection;
|
|
128
|
+
},
|
|
129
|
+
[document],
|
|
130
|
+
subSlot(slot, 'getSnapshot'),
|
|
131
|
+
);
|
|
132
|
+
let getServerSnapshot = useCallback(
|
|
133
|
+
() => {
|
|
134
|
+
document.isSSR = true;
|
|
135
|
+
return document.getCollection();
|
|
136
|
+
},
|
|
137
|
+
[document],
|
|
138
|
+
subSlot(slot, 'getServerSnapshot'),
|
|
139
|
+
);
|
|
140
|
+
let collection = useSyncExternalStore(
|
|
141
|
+
subscribe,
|
|
142
|
+
getSnapshot,
|
|
143
|
+
getServerSnapshot,
|
|
144
|
+
subSlot(slot, 'collection'),
|
|
145
|
+
);
|
|
146
|
+
return { collection, document };
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
const SSRContext = createContext<Document<any, any> | ElementNode<any> | null>(null);
|
|
150
|
+
|
|
151
|
+
export type CollectionNodeClass<T> = {
|
|
152
|
+
new (key: Key): CollectionNode<T>;
|
|
153
|
+
readonly type: string;
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
function createCollectionNodeClass(type: string): CollectionNodeClass<any> {
|
|
157
|
+
let NodeClass = class extends CollectionNode<any> {
|
|
158
|
+
static readonly type = type;
|
|
159
|
+
};
|
|
160
|
+
return NodeClass;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function useSSRCollectionNode<T extends Element>(
|
|
164
|
+
CollectionNodeClass: CollectionNodeClass<T> | string,
|
|
165
|
+
props: object,
|
|
166
|
+
ref: any,
|
|
167
|
+
rendered: any,
|
|
168
|
+
children: any,
|
|
169
|
+
render: ((node: Node<any>) => any) | undefined,
|
|
170
|
+
slot: symbol | undefined,
|
|
171
|
+
): any {
|
|
172
|
+
// To prevent breaking change, if CollectionNodeClass is a string, create a
|
|
173
|
+
// CollectionNodeClass using the string as the type
|
|
174
|
+
if (typeof CollectionNodeClass === 'string') {
|
|
175
|
+
CollectionNodeClass = createCollectionNodeClass(CollectionNodeClass);
|
|
176
|
+
}
|
|
177
|
+
const NodeClass = CollectionNodeClass as CollectionNodeClass<any>;
|
|
178
|
+
|
|
179
|
+
let doc = useContext(ShallowRenderContext);
|
|
180
|
+
// octane adaptation: the ref receives the REAL placeholder element; it
|
|
181
|
+
// registers into the Document store read from context (upstream's fake
|
|
182
|
+
// element carried `setProps` itself). Prop updates re-fire the ref (new
|
|
183
|
+
// callback identity per render), which is the synchronous dirty signal;
|
|
184
|
+
// structural-only changes are caught by the Document's MutationObserver.
|
|
185
|
+
let itemRef = useCallback(
|
|
186
|
+
(element: Element | null) => {
|
|
187
|
+
if (element !== null) {
|
|
188
|
+
doc!.setElementProps(element, props as any, ref, NodeClass, rendered, render);
|
|
189
|
+
}
|
|
190
|
+
},
|
|
191
|
+
[doc, props, ref, rendered, render, NodeClass],
|
|
192
|
+
subSlot(slot, 'itemRef'),
|
|
193
|
+
);
|
|
194
|
+
let parentNode = useContext(SSRContext);
|
|
195
|
+
if (parentNode) {
|
|
196
|
+
// During SSR, portals are not supported, so the collection children are wrapped
|
|
197
|
+
// in an SSRContext. Since SSR occurs only once, we assume that the elements are
|
|
198
|
+
// rendered in order and never re-render. Therefore we can create nodes in our
|
|
199
|
+
// collection document during render so that they are in the collection by the
|
|
200
|
+
// time we need it to render the real DOM. (Re-render guard kept from upstream.)
|
|
201
|
+
let element = parentNode.ownerDocument.nodesByProps.get(props);
|
|
202
|
+
if (!element) {
|
|
203
|
+
element = parentNode.ownerDocument.createElement(NodeClass.type);
|
|
204
|
+
element.setProps(props as any, ref, NodeClass, rendered, render);
|
|
205
|
+
parentNode.appendChild(element);
|
|
206
|
+
parentNode.ownerDocument.updateCollection();
|
|
207
|
+
parentNode.ownerDocument.nodesByProps.set(props, element);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
return children ? createElement(SSRContext.Provider, { value: element, children }) : null;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// The placeholder tag is the node type (`<item>`/`<section>`-style) — a valid
|
|
214
|
+
// real HTMLUnknownElement in the detached container.
|
|
215
|
+
return createElement(NodeClass.type, { ref: itemRef, children });
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
export function createLeafComponent<T, P extends object, E extends Element>(
|
|
219
|
+
CollectionNodeClass: CollectionNodeClass<any> | string,
|
|
220
|
+
render: (props: P, ref: any, node?: Node<T>) => any,
|
|
221
|
+
): (props: P & { ref?: any }) => any {
|
|
222
|
+
let Component = ({ node }: { node: Node<any> }) => render(node.props, node.props.ref, node);
|
|
223
|
+
let Result = (props: P & { ref?: any }) => {
|
|
224
|
+
const slot = S('createLeafComponent');
|
|
225
|
+
let ref = (props as any).ref;
|
|
226
|
+
let focusableProps = useContext(FocusableContext);
|
|
227
|
+
let doc = useContext(ShallowRenderContext);
|
|
228
|
+
if (!doc) {
|
|
229
|
+
if (render.length >= 3) {
|
|
230
|
+
throw new Error(render.name + ' cannot be rendered outside a collection.');
|
|
231
|
+
}
|
|
232
|
+
return render(props, ref);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
return useSSRCollectionNode(
|
|
236
|
+
CollectionNodeClass,
|
|
237
|
+
props,
|
|
238
|
+
ref,
|
|
239
|
+
'children' in props ? (props as any).children : null,
|
|
240
|
+
null,
|
|
241
|
+
(node) =>
|
|
242
|
+
// Forward FocusableContext to real DOM tree so tooltips work.
|
|
243
|
+
createElement(FocusableContext.Provider, {
|
|
244
|
+
value: focusableProps,
|
|
245
|
+
children: createElement(Component, { node }),
|
|
246
|
+
}),
|
|
247
|
+
subSlot(slot, 'node'),
|
|
248
|
+
);
|
|
249
|
+
};
|
|
250
|
+
return Result;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
export function createBranchComponent<T, P extends { children?: any }, E extends Element>(
|
|
254
|
+
CollectionNodeClass: CollectionNodeClass<any> | string,
|
|
255
|
+
render: (props: P, ref: any, node: Node<T>) => any,
|
|
256
|
+
useChildren: (props: P, slot?: symbol) => any = useCollectionChildren,
|
|
257
|
+
): (props: P & { ref?: any }) => any {
|
|
258
|
+
let Component = ({ node }: { node: Node<any> }) => render(node.props, node.props.ref, node);
|
|
259
|
+
let Result = (props: P & { ref?: any }) => {
|
|
260
|
+
const slot = S('createBranchComponent');
|
|
261
|
+
let children = useChildren(props, subSlot(slot, 'children'));
|
|
262
|
+
return (
|
|
263
|
+
useSSRCollectionNode(
|
|
264
|
+
CollectionNodeClass,
|
|
265
|
+
props,
|
|
266
|
+
(props as any).ref,
|
|
267
|
+
null,
|
|
268
|
+
children,
|
|
269
|
+
(node) => createElement(Component, { node }),
|
|
270
|
+
subSlot(slot, 'node'),
|
|
271
|
+
) ?? null
|
|
272
|
+
);
|
|
273
|
+
};
|
|
274
|
+
return Result;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
function useCollectionChildren<T>(options: CachedChildrenOptions<T>, slot?: symbol): any {
|
|
278
|
+
return useCachedChildren({ ...options, addIdAndValue: true }, slot);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
export interface CollectionProps<T> extends CachedChildrenOptions<T> {}
|
|
282
|
+
|
|
283
|
+
const CollectionContext = createContext<CachedChildrenOptions<unknown> | null>(null);
|
|
284
|
+
|
|
285
|
+
/** A Collection renders a list of items, automatically managing caching and keys. */
|
|
286
|
+
export function Collection<T>(props: CollectionProps<T>): any {
|
|
287
|
+
const slot = S('Collection');
|
|
288
|
+
let ctx = useContext(CollectionContext)!;
|
|
289
|
+
let dependencies = (ctx?.dependencies || []).concat(props.dependencies);
|
|
290
|
+
let idScope = props.idScope ?? ctx?.idScope;
|
|
291
|
+
let children = useCollectionChildren(
|
|
292
|
+
{
|
|
293
|
+
...props,
|
|
294
|
+
idScope,
|
|
295
|
+
dependencies,
|
|
296
|
+
},
|
|
297
|
+
subSlot(slot, 'children'),
|
|
298
|
+
);
|
|
299
|
+
|
|
300
|
+
let doc = useContext(CollectionDocumentContext);
|
|
301
|
+
if (doc) {
|
|
302
|
+
children = createElement(CollectionRoot, { children });
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
// Propagate dependencies and idScope to child collections.
|
|
306
|
+
ctx = useMemo(
|
|
307
|
+
() => ({
|
|
308
|
+
dependencies,
|
|
309
|
+
idScope,
|
|
310
|
+
}),
|
|
311
|
+
[idScope, ...dependencies],
|
|
312
|
+
subSlot(slot, 'ctx'),
|
|
313
|
+
);
|
|
314
|
+
|
|
315
|
+
return createElement(CollectionContext.Provider, { value: ctx, children });
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
function CollectionRoot(props: { children: any }): any {
|
|
319
|
+
const slot = S('CollectionRoot');
|
|
320
|
+
let doc = useContext(CollectionDocumentContext);
|
|
321
|
+
let wrappedChildren = useMemo(
|
|
322
|
+
() =>
|
|
323
|
+
createElement(CollectionDocumentContext.Provider, {
|
|
324
|
+
value: null,
|
|
325
|
+
children: createElement(ShallowRenderContext.Provider, {
|
|
326
|
+
value: doc,
|
|
327
|
+
children: props.children,
|
|
328
|
+
}),
|
|
329
|
+
}),
|
|
330
|
+
[props.children, doc],
|
|
331
|
+
subSlot(slot, 'wrapped'),
|
|
332
|
+
);
|
|
333
|
+
// During SSR, we render the content directly, and append nodes to the document
|
|
334
|
+
// during render. The collection children return null so that nothing is actually
|
|
335
|
+
// rendered into the HTML.
|
|
336
|
+
// octane adaptation: on the client there is NO second portal — this subtree
|
|
337
|
+
// already renders inside `Hidden`'s portal into the Document's detached
|
|
338
|
+
// container, so the placeholders land in the walked tree directly.
|
|
339
|
+
let isSSR = useIsSSR(subSlot(slot, 'ssr'));
|
|
340
|
+
return isSSR
|
|
341
|
+
? createElement(SSRContext.Provider, { value: doc, children: wrappedChildren })
|
|
342
|
+
: wrappedChildren;
|
|
343
|
+
}
|