@tamagui/accordion 2.7.7 → 3.0.0-beta.643.1

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.
@@ -0,0 +1,440 @@
1
+ "use strict";
2
+
3
+
4
+ var __create = Object.create;
5
+ var __defProp = Object.defineProperty;
6
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
7
+ var __getOwnPropNames = Object.getOwnPropertyNames;
8
+ var __getProtoOf = Object.getPrototypeOf;
9
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
10
+ var __export = (target, all) => {
11
+ for (var name in all) __defProp(target, name, {
12
+ get: all[name],
13
+ enumerable: true
14
+ });
15
+ };
16
+ var __copyProps = (to, from, except, desc) => {
17
+ if (from && typeof from === "object" || typeof from === "function") {
18
+ for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
19
+ get: () => from[key],
20
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
21
+ });
22
+ }
23
+ return to;
24
+ };
25
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
26
+ value: mod,
27
+ enumerable: true
28
+ }) : target, mod));
29
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
30
+ var Accordion_exports = {};
31
+ __export(Accordion_exports, { Accordion: () => Accordion });
32
+ module.exports = __toCommonJS(Accordion_exports);
33
+ var import_jsx_runtime = require("react/jsx-runtime");
34
+ var import_core = require("@tamagui/core");
35
+ var import_collapsible = require("@tamagui/collapsible");
36
+ var import_collection = require("@tamagui/collection");
37
+ var import_compose_refs = require("@tamagui/compose-refs");
38
+ var import_constants = require("@tamagui/constants");
39
+ var import_core2 = require("@tamagui/core");
40
+ var import_helpers = require("@tamagui/helpers");
41
+ var import_stacks = require("@tamagui/stacks");
42
+ var import_text = require("@tamagui/text");
43
+ var import_use_controllable_state = require("@tamagui/use-controllable-state");
44
+ var import_use_direction = require("@tamagui/use-direction");
45
+ var React = __toESM(require("react"), 1);
46
+ var ACCORDION_NAME = "Accordion";
47
+ var ACCORDION_KEYS = [
48
+ "Home",
49
+ "End",
50
+ "ArrowDown",
51
+ "ArrowUp",
52
+ "ArrowLeft",
53
+ "ArrowRight"
54
+ ];
55
+ var [Collection, useCollection] = (0, import_collection.createCollection)(ACCORDION_NAME);
56
+ var ACCORDION_CONTEXT = "Accordion";
57
+ var AccordionComponent = (0, import_core.createRefComponent)(function(props, forwardedRef) {
58
+ var { type, ...accordionProps } = props;
59
+ var singleProps = accordionProps;
60
+ var multipleProps = accordionProps;
61
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Collection.Provider, {
62
+ scope: props.__scopeAccordion || ACCORDION_CONTEXT,
63
+ children: type === "multiple" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AccordionImplMultiple, {
64
+ ...multipleProps,
65
+ ref: forwardedRef
66
+ }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AccordionImplSingle, {
67
+ ...singleProps,
68
+ ref: forwardedRef
69
+ })
70
+ });
71
+ });
72
+ AccordionComponent.displayName = ACCORDION_NAME;
73
+ AccordionComponent.propTypes = { type(props) {
74
+ var value = props.value || props.defaultValue;
75
+ if (props.type && !["single", "multiple"].includes(props.type)) {
76
+ return new Error("Invalid prop `type` supplied to `Accordion`. Expected one of `single | multiple`.");
77
+ }
78
+ if (props.type === "multiple" && typeof value === "string") {
79
+ return new Error("Invalid prop `type` supplied to `Accordion`. Expected `single` when `defaultValue` or `value` is type `string`.");
80
+ }
81
+ if (props.type === "single" && Array.isArray(value)) {
82
+ return new Error("Invalid prop `type` supplied to `Accordion`. Expected `multiple` when `defaultValue` or `value` is type `string[]`.");
83
+ }
84
+ return null;
85
+ } };
86
+ var { Provider: AccordionValueProvider, useStyledContext: useAccordionValueContext } = (0, import_core2.createStyledContext)();
87
+ var { Provider: AccordionCollapsibleProvider, useStyledContext: useAccordionCollapsibleContext } = (0, import_core2.createStyledContext)();
88
+ var AccordionImplSingle = (0, import_core.createRefComponent)(function(props, forwardedRef) {
89
+ var { value: valueProp, defaultValue, control, onValueChange = function() {}, collapsible = false, ...accordionSingleProps } = props;
90
+ var [value, setValue] = (0, import_use_controllable_state.useControllableState)({
91
+ prop: valueProp,
92
+ defaultProp: defaultValue || "",
93
+ onChange: onValueChange
94
+ });
95
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AccordionValueProvider, {
96
+ scope: props.__scopeAccordion,
97
+ value: value ? [value] : [],
98
+ onItemOpen: setValue,
99
+ onItemClose: React.useCallback(function() {
100
+ return collapsible && setValue("");
101
+ }, [setValue, collapsible]),
102
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AccordionCollapsibleProvider, {
103
+ scope: props.__scopeAccordion,
104
+ collapsible,
105
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AccordionImpl, {
106
+ ...accordionSingleProps,
107
+ ref: forwardedRef
108
+ })
109
+ })
110
+ });
111
+ });
112
+ var AccordionImplMultiple = (0, import_core.createRefComponent)(function(props, forwardedRef) {
113
+ var { value: valueProp, defaultValue, onValueChange = function() {}, ...accordionMultipleProps } = props;
114
+ var [value, setValue] = (0, import_use_controllable_state.useControllableState)({
115
+ prop: valueProp,
116
+ defaultProp: defaultValue || [],
117
+ onChange: onValueChange
118
+ });
119
+ var handleItemOpen = React.useCallback(function(itemValue) {
120
+ return setValue(function() {
121
+ var prevValue = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : [];
122
+ return [...prevValue, itemValue];
123
+ });
124
+ }, [setValue]);
125
+ var handleItemClose = React.useCallback(function(itemValue) {
126
+ return setValue(function() {
127
+ var prevValue = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : [];
128
+ return prevValue.filter(function(value2) {
129
+ return value2 !== itemValue;
130
+ });
131
+ });
132
+ }, [setValue]);
133
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AccordionValueProvider, {
134
+ scope: props.__scopeAccordion,
135
+ value: value || [],
136
+ onItemOpen: handleItemOpen,
137
+ onItemClose: handleItemClose,
138
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AccordionCollapsibleProvider, {
139
+ scope: props.__scopeAccordion,
140
+ collapsible: true,
141
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AccordionImpl, {
142
+ ...accordionMultipleProps,
143
+ ref: forwardedRef
144
+ })
145
+ })
146
+ });
147
+ });
148
+ var { Provider: AccordionImplProvider, useStyledContext: useAccordionContext } = (0, import_core2.createStyledContext)();
149
+ var AccordionImpl = (0, import_core.createRefComponent)(function(props, forwardedRef) {
150
+ var { __scopeAccordion, disabled, dir, orientation = "vertical", ...accordionProps } = props;
151
+ var accordionRef = React.useRef(null);
152
+ var composedRef = (0, import_compose_refs.useComposedRefs)(accordionRef, forwardedRef);
153
+ var getItems = useCollection(__scopeAccordion || ACCORDION_CONTEXT);
154
+ var direction = (0, import_use_direction.useDirection)(dir);
155
+ var isDirectionLTR = direction === "ltr";
156
+ var handleKeyDown = (0, import_helpers.composeEventHandlers)(props.onKeyDown, function(event) {
157
+ var _triggerCollection_clampedIndex_ref_current;
158
+ if (!ACCORDION_KEYS.includes(event.key)) return;
159
+ var target = event.target;
160
+ var triggerCollection = getItems().filter(function(item) {
161
+ var el = item.ref.current;
162
+ return !(el === null || el === void 0 ? void 0 : el.disabled);
163
+ });
164
+ var triggerIndex = triggerCollection.findIndex(function(item) {
165
+ return item.ref.current === target;
166
+ });
167
+ var triggerCount = triggerCollection.length;
168
+ if (triggerIndex === -1) return;
169
+ event.preventDefault();
170
+ var nextIndex = triggerIndex;
171
+ var homeIndex = 0;
172
+ var endIndex = triggerCount - 1;
173
+ var moveNext = function() {
174
+ nextIndex = triggerIndex + 1;
175
+ if (nextIndex > endIndex) {
176
+ nextIndex = homeIndex;
177
+ }
178
+ };
179
+ var movePrev = function() {
180
+ nextIndex = triggerIndex - 1;
181
+ if (nextIndex < homeIndex) {
182
+ nextIndex = endIndex;
183
+ }
184
+ };
185
+ switch (event.key) {
186
+ case "Home":
187
+ nextIndex = homeIndex;
188
+ break;
189
+ case "End":
190
+ nextIndex = endIndex;
191
+ break;
192
+ case "ArrowRight":
193
+ if (orientation === "horizontal") {
194
+ if (isDirectionLTR) {
195
+ moveNext();
196
+ } else {
197
+ movePrev();
198
+ }
199
+ }
200
+ break;
201
+ case "ArrowDown":
202
+ if (orientation === "vertical") {
203
+ moveNext();
204
+ }
205
+ break;
206
+ case "ArrowLeft":
207
+ if (orientation === "horizontal") {
208
+ if (isDirectionLTR) {
209
+ movePrev();
210
+ } else {
211
+ moveNext();
212
+ }
213
+ }
214
+ break;
215
+ case "ArrowUp":
216
+ if (orientation === "vertical") {
217
+ movePrev();
218
+ }
219
+ break;
220
+ }
221
+ var clampedIndex = nextIndex % triggerCount;
222
+ (_triggerCollection_clampedIndex_ref_current = triggerCollection[clampedIndex].ref.current) === null || _triggerCollection_clampedIndex_ref_current === void 0 ? void 0 : _triggerCollection_clampedIndex_ref_current.focus();
223
+ });
224
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AccordionImplProvider, {
225
+ scope: __scopeAccordion,
226
+ disabled,
227
+ direction: dir,
228
+ orientation,
229
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Collection.Slot, {
230
+ scope: __scopeAccordion || ACCORDION_CONTEXT,
231
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stacks.YStack, {
232
+ "data-orientation": orientation,
233
+ ref: composedRef,
234
+ ...accordionProps,
235
+ ...import_constants.isWeb && { onKeyDown: handleKeyDown }
236
+ })
237
+ })
238
+ });
239
+ });
240
+ var ITEM_NAME = "AccordionItem";
241
+ var { Provider: AccordionItemProvider, useStyledContext: useAccordionItemContext } = (0, import_core2.createStyledContext)();
242
+ var AccordionItem = (0, import_core.createRefComponent)(function(props, forwardedRef) {
243
+ var { __scopeAccordion, value, ...accordionItemProps } = props;
244
+ var accordionContext = useAccordionContext(__scopeAccordion);
245
+ var valueContext = useAccordionValueContext(__scopeAccordion);
246
+ var triggerId = React.useId();
247
+ var open = value && valueContext.value.includes(value) || false;
248
+ var disabled = accordionContext.disabled || props.disabled;
249
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AccordionItemProvider, {
250
+ scope: __scopeAccordion,
251
+ open,
252
+ disabled,
253
+ triggerId,
254
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_collapsible.Collapsible, {
255
+ "data-orientation": accordionContext.orientation,
256
+ "data-state": open ? "open" : "closed",
257
+ __scopeCollapsible: __scopeAccordion || ACCORDION_CONTEXT,
258
+ ...accordionItemProps,
259
+ ref: forwardedRef,
260
+ disabled,
261
+ open,
262
+ onOpenChange: function(open2) {
263
+ if (open2) {
264
+ valueContext.onItemOpen(value);
265
+ } else {
266
+ valueContext.onItemClose(value);
267
+ }
268
+ }
269
+ })
270
+ });
271
+ });
272
+ AccordionItem.displayName = ITEM_NAME;
273
+ var HEADER_NAME = "AccordionHeader";
274
+ var AccordionHeader = (0, import_core.createRefComponent)(function(props, forwardedRef) {
275
+ var { __scopeAccordion, ...headerProps } = props;
276
+ var accordionContext = useAccordionContext(__scopeAccordion);
277
+ var itemContext = useAccordionItemContext(__scopeAccordion);
278
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_text.H1, {
279
+ "data-orientation": accordionContext.orientation,
280
+ "data-state": getState(itemContext.open),
281
+ "data-disabled": itemContext.disabled ? "" : void 0,
282
+ ...headerProps,
283
+ ref: forwardedRef
284
+ });
285
+ });
286
+ AccordionHeader.displayName = HEADER_NAME;
287
+ var AccordionTriggerFrame = (0, import_core2.styled)(import_collapsible.Collapsible.Trigger, { displayName: "AccordionTrigger" });
288
+ var AccordionTrigger = (0, import_core.createStyledHOC)(AccordionTriggerFrame, function AccordionTrigger2(props, forwardedRef) {
289
+ var { __scopeAccordion, ...triggerProps } = props;
290
+ var accordionContext = useAccordionContext(__scopeAccordion);
291
+ var itemContext = useAccordionItemContext(__scopeAccordion);
292
+ var collapsibleContext = useAccordionCollapsibleContext(__scopeAccordion);
293
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Collection.ItemSlot, {
294
+ scope: __scopeAccordion || ACCORDION_CONTEXT,
295
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AccordionTriggerFrame, {
296
+ __scopeCollapsible: __scopeAccordion || ACCORDION_CONTEXT,
297
+ "aria-disabled": itemContext.open && !collapsibleContext.collapsible || void 0,
298
+ "data-orientation": accordionContext.orientation,
299
+ id: itemContext.triggerId,
300
+ ...triggerProps,
301
+ ref: forwardedRef
302
+ })
303
+ });
304
+ });
305
+ var AccordionContentFrame = (0, import_core2.styled)(import_collapsible.Collapsible.Content, { displayName: "AccordionContent" });
306
+ var AccordionHeightAnimatorContext = /* @__PURE__ */ React.createContext(false);
307
+ var AccordionContent = (0, import_core.createStyledHOC)(AccordionContentFrame, function AccordionContent2(props, forwardedRef) {
308
+ var { __scopeAccordion, forceMount, ...contentProps } = props;
309
+ var accordionContext = useAccordionContext(__scopeAccordion);
310
+ var itemContext = useAccordionItemContext(__scopeAccordion);
311
+ var heightAnimatorPresent = React.useContext(AccordionHeightAnimatorContext);
312
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AccordionContentFrame, {
313
+ role: "region",
314
+ "aria-labelledby": itemContext.triggerId,
315
+ "data-orientation": accordionContext.orientation,
316
+ __scopeCollapsible: __scopeAccordion || ACCORDION_CONTEXT,
317
+ ...contentProps,
318
+ forceMount: forceMount || heightAnimatorPresent,
319
+ ref: forwardedRef
320
+ });
321
+ });
322
+ var HeightAnimator = (0, import_core.createStyledHOC)(import_core2.View, function(props, ref) {
323
+ var itemContext = useAccordionItemContext();
324
+ var { children, transition, ...rest } = props;
325
+ var open = !!itemContext.open;
326
+ var [fixed, setFixed] = React.useState(!open);
327
+ var [pinned, setPinned] = React.useState(false);
328
+ var [contentPresent, setContentPresent] = React.useState(open);
329
+ var [contentHeight, setContentHeight] = React.useState(0);
330
+ var outerRef = React.useRef(null);
331
+ var innerRef = React.useRef(null);
332
+ var composedRef = (0, import_compose_refs.useComposedRefs)(outerRef, ref);
333
+ var lastOuterHeightRef = React.useRef(0);
334
+ var pinnedHeightRef = React.useRef(0);
335
+ var settleTimerRef = React.useRef(void 0);
336
+ var prevOpenRef = React.useRef(open);
337
+ if (prevOpenRef.current !== open) {
338
+ prevOpenRef.current = open;
339
+ clearTimeout(settleTimerRef.current);
340
+ if (open) {
341
+ setContentPresent(true);
342
+ } else if (lastOuterHeightRef.current < 1) {
343
+ setContentPresent(false);
344
+ }
345
+ if (!fixed) {
346
+ pinnedHeightRef.current = lastOuterHeightRef.current;
347
+ setFixed(true);
348
+ setPinned(true);
349
+ }
350
+ }
351
+ (0, import_constants.useIsomorphicLayoutEffect)(function() {
352
+ if (!pinned) return;
353
+ if (import_constants.isWeb) {
354
+ var _outerRef_current;
355
+ void ((_outerRef_current = outerRef.current) === null || _outerRef_current === void 0 ? void 0 : _outerRef_current.offsetHeight);
356
+ setPinned(false);
357
+ return;
358
+ }
359
+ var frame = requestAnimationFrame(function() {
360
+ return setPinned(false);
361
+ });
362
+ return function() {
363
+ return cancelAnimationFrame(frame);
364
+ };
365
+ }, [pinned]);
366
+ React.useEffect(function() {
367
+ return function() {
368
+ return clearTimeout(settleTimerRef.current);
369
+ };
370
+ }, []);
371
+ (0, import_constants.useIsomorphicLayoutEffect)(function() {
372
+ var _el_getBoundingClientRect;
373
+ if (!fixed || !open) return;
374
+ var el = innerRef.current;
375
+ var naturalHeight = el === null || el === void 0 ? void 0 : (_el_getBoundingClientRect = el.getBoundingClientRect) === null || _el_getBoundingClientRect === void 0 ? void 0 : _el_getBoundingClientRect.call(el).height;
376
+ if (naturalHeight && naturalHeight > 0 && naturalHeight !== contentHeight) {
377
+ setContentHeight(naturalHeight);
378
+ }
379
+ });
380
+ var minHeight = pinned ? pinnedHeightRef.current : open ? contentHeight : 0;
381
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_core2.View, {
382
+ ref: composedRef,
383
+ position: "relative",
384
+ ...rest,
385
+ transition: fixed ? transition : void 0,
386
+ height: "auto",
387
+ minHeight,
388
+ overflow: "hidden",
389
+ onLayout: function(param) {
390
+ var { nativeEvent } = param;
391
+ var outerHeight = nativeEvent.layout.height;
392
+ lastOuterHeightRef.current = outerHeight;
393
+ if (import_constants.isWeb && !open && contentPresent && outerHeight < 1) {
394
+ setContentPresent(false);
395
+ }
396
+ clearTimeout(settleTimerRef.current);
397
+ if (fixed && !pinned && open && contentHeight > 0) {
398
+ if (Math.abs(outerHeight - contentHeight) < 1) {
399
+ settleTimerRef.current = setTimeout(function() {
400
+ return setFixed(false);
401
+ }, 100);
402
+ }
403
+ }
404
+ },
405
+ onTransition: function(event) {
406
+ if (event.phase !== "end" || event.cause !== "update" || !event.finished) return;
407
+ if (!prevOpenRef.current && !pinned) {
408
+ setContentPresent(false);
409
+ }
410
+ },
411
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_core2.View, {
412
+ ref: innerRef,
413
+ position: fixed ? "absolute" : "relative",
414
+ top: fixed ? 0 : void 0,
415
+ left: fixed ? 0 : void 0,
416
+ right: fixed ? 0 : void 0,
417
+ onLayout: function(param) {
418
+ var { nativeEvent } = param;
419
+ var naturalHeight = nativeEvent.layout.height;
420
+ if (open && naturalHeight !== contentHeight) {
421
+ setContentHeight(naturalHeight);
422
+ }
423
+ },
424
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AccordionHeightAnimatorContext.Provider, {
425
+ value: contentPresent,
426
+ children
427
+ })
428
+ })
429
+ });
430
+ });
431
+ function getState(open) {
432
+ return open ? "open" : "closed";
433
+ }
434
+ var Accordion = (0, import_helpers.withStaticProperties)(AccordionComponent, {
435
+ Trigger: AccordionTrigger,
436
+ Header: AccordionHeader,
437
+ Content: AccordionContent,
438
+ Item: AccordionItem,
439
+ HeightAnimator
440
+ });