@fluentui/react-utilities 0.0.0-nightly940de09b9520220131.1 → 0.0.0-nightly946f57cad420220203.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.
Files changed (50) hide show
  1. package/CHANGELOG.json +12 -6
  2. package/CHANGELOG.md +7 -6
  3. package/dist/react-utilities.d.ts +64 -24
  4. package/lib/hooks/index.d.ts +1 -1
  5. package/lib/hooks/index.js +1 -1
  6. package/lib/hooks/index.js.map +1 -1
  7. package/lib/hooks/useMergedEventCallbacks.d.ts +18 -0
  8. package/lib/hooks/useMergedEventCallbacks.js +26 -0
  9. package/lib/hooks/useMergedEventCallbacks.js.map +1 -0
  10. package/lib/utils/applyTriggerPropsToChildren.js +19 -2
  11. package/lib/utils/applyTriggerPropsToChildren.js.map +1 -1
  12. package/lib/utils/getTriggerChild.d.ts +22 -0
  13. package/lib/utils/getTriggerChild.js +26 -0
  14. package/lib/utils/getTriggerChild.js.map +1 -0
  15. package/lib/utils/index.d.ts +2 -1
  16. package/lib/utils/index.js +2 -1
  17. package/lib/utils/index.js.map +1 -1
  18. package/lib/utils/isFluentTrigger.d.ts +22 -0
  19. package/lib/utils/isFluentTrigger.js +8 -0
  20. package/lib/utils/isFluentTrigger.js.map +1 -0
  21. package/lib-commonjs/hooks/index.d.ts +1 -1
  22. package/lib-commonjs/hooks/index.js +2 -2
  23. package/lib-commonjs/hooks/index.js.map +1 -1
  24. package/lib-commonjs/hooks/useMergedEventCallbacks.d.ts +18 -0
  25. package/lib-commonjs/hooks/useMergedEventCallbacks.js +36 -0
  26. package/lib-commonjs/hooks/useMergedEventCallbacks.js.map +1 -0
  27. package/lib-commonjs/utils/applyTriggerPropsToChildren.js +19 -2
  28. package/lib-commonjs/utils/applyTriggerPropsToChildren.js.map +1 -1
  29. package/lib-commonjs/utils/getTriggerChild.d.ts +22 -0
  30. package/lib-commonjs/utils/getTriggerChild.js +37 -0
  31. package/lib-commonjs/utils/getTriggerChild.js.map +1 -0
  32. package/lib-commonjs/utils/index.d.ts +2 -1
  33. package/lib-commonjs/utils/index.js +4 -2
  34. package/lib-commonjs/utils/index.js.map +1 -1
  35. package/lib-commonjs/utils/isFluentTrigger.d.ts +22 -0
  36. package/lib-commonjs/utils/isFluentTrigger.js +17 -0
  37. package/lib-commonjs/utils/isFluentTrigger.js.map +1 -0
  38. package/package.json +2 -2
  39. package/lib/hooks/useTriggerElement.d.ts +0 -18
  40. package/lib/hooks/useTriggerElement.js +0 -90
  41. package/lib/hooks/useTriggerElement.js.map +0 -1
  42. package/lib/utils/onlyChild.d.ts +0 -5
  43. package/lib/utils/onlyChild.js +0 -13
  44. package/lib/utils/onlyChild.js.map +0 -1
  45. package/lib-commonjs/hooks/useTriggerElement.d.ts +0 -18
  46. package/lib-commonjs/hooks/useTriggerElement.js +0 -105
  47. package/lib-commonjs/hooks/useTriggerElement.js.map +0 -1
  48. package/lib-commonjs/utils/onlyChild.d.ts +0 -5
  49. package/lib-commonjs/utils/onlyChild.js +0 -23
  50. package/lib-commonjs/utils/onlyChild.js.map +0 -1
package/CHANGELOG.json CHANGED
@@ -2,15 +2,15 @@
2
2
  "name": "@fluentui/react-utilities",
3
3
  "entries": [
4
4
  {
5
- "date": "Mon, 31 Jan 2022 04:16:03 GMT",
6
- "tag": "@fluentui/react-utilities_v0.0.0-nightly940de09b9520220131.1",
7
- "version": "0.0.0-nightly940de09b9520220131.1",
5
+ "date": "Thu, 03 Feb 2022 04:16:57 GMT",
6
+ "tag": "@fluentui/react-utilities_v0.0.0-nightly946f57cad420220203.1",
7
+ "version": "0.0.0-nightly946f57cad420220203.1",
8
8
  "comments": {
9
9
  "prerelease": [
10
10
  {
11
11
  "author": "email not defined",
12
12
  "package": "@fluentui/react-utilities",
13
- "commit": "7343cc2ca2eaca5e933abf6a8b8b57f910107cc4",
13
+ "commit": "1d230926e10b3b722bd932be1ec39faaf340671c",
14
14
  "comment": "Release nightly v9"
15
15
  },
16
16
  {
@@ -43,6 +43,12 @@
43
43
  "commit": "e0b8e1fa6980077e7b311fd1c72c28d3e4305db0",
44
44
  "comment": "Renaming most *Shorthand* composition types to *SlotProps* so they better reflect what the types do."
45
45
  },
46
+ {
47
+ "author": "behowell@microsoft.com",
48
+ "package": "@fluentui/react-utilities",
49
+ "commit": "f30e7585a8d2abd9db06c4076f39a779008b0eca",
50
+ "comment": "Update trigger utilities to handle nested triggers"
51
+ },
46
52
  {
47
53
  "author": "elcraig@microsoft.com",
48
54
  "package": "@fluentui/react-utilities",
@@ -52,8 +58,8 @@
52
58
  {
53
59
  "author": "beachball",
54
60
  "package": "@fluentui/react-utilities",
55
- "comment": "Bump @fluentui/keyboard-keys to v0.0.0-nightly940de09b9520220131.1",
56
- "commit": "7343cc2ca2eaca5e933abf6a8b8b57f910107cc4"
61
+ "comment": "Bump @fluentui/keyboard-keys to v0.0.0-nightly946f57cad420220203.1",
62
+ "commit": "1d230926e10b3b722bd932be1ec39faaf340671c"
57
63
  }
58
64
  ],
59
65
  "none": [
package/CHANGELOG.md CHANGED
@@ -1,24 +1,25 @@
1
1
  # Change Log - @fluentui/react-utilities
2
2
 
3
- This log was last generated on Mon, 31 Jan 2022 04:16:03 GMT and should not be manually modified.
3
+ This log was last generated on Thu, 03 Feb 2022 04:16:57 GMT and should not be manually modified.
4
4
 
5
5
  <!-- Start content -->
6
6
 
7
- ## [0.0.0-nightly940de09b9520220131.1](https://github.com/microsoft/fluentui/tree/@fluentui/react-utilities_v0.0.0-nightly940de09b9520220131.1)
7
+ ## [0.0.0-nightly946f57cad420220203.1](https://github.com/microsoft/fluentui/tree/@fluentui/react-utilities_v0.0.0-nightly946f57cad420220203.1)
8
8
 
9
- Mon, 31 Jan 2022 04:16:03 GMT
10
- [Compare changes](https://github.com/microsoft/fluentui/compare/@fluentui/react-utilities_v9.0.0-beta.4..@fluentui/react-utilities_v0.0.0-nightly940de09b9520220131.1)
9
+ Thu, 03 Feb 2022 04:16:57 GMT
10
+ [Compare changes](https://github.com/microsoft/fluentui/compare/@fluentui/react-utilities_v9.0.0-beta.4..@fluentui/react-utilities_v0.0.0-nightly946f57cad420220203.1)
11
11
 
12
12
  ### Changes
13
13
 
14
- - Release nightly v9 ([commit](https://github.com/microsoft/fluentui/commit/7343cc2ca2eaca5e933abf6a8b8b57f910107cc4) by email not defined)
14
+ - Release nightly v9 ([commit](https://github.com/microsoft/fluentui/commit/1d230926e10b3b722bd932be1ec39faaf340671c) by email not defined)
15
15
  - Rename component hooks add the suffix _unstable, as their API has not been finalized yet ([PR #21365](https://github.com/microsoft/fluentui/pull/21365) by behowell@microsoft.com)
16
16
  - getSlots: remove slotNames param, and infer from state.components instead ([PR #21134](https://github.com/microsoft/fluentui/pull/21134) by behowell@microsoft.com)
17
17
  - add useTriggerElement() hook ([PR #21225](https://github.com/microsoft/fluentui/pull/21225) by olfedias@microsoft.com)
18
18
  - Adding ComponentSlotProps to allow ref to be passed in composite components. ([PR #20890](https://github.com/microsoft/fluentui/pull/20890) by Humberto.Morimoto@microsoft.com)
19
19
  - Renaming most *Shorthand* composition types to *SlotProps* so they better reflect what the types do. ([PR #20891](https://github.com/microsoft/fluentui/pull/20891) by Humberto.Morimoto@microsoft.com)
20
+ - Update trigger utilities to handle nested triggers ([PR #21495](https://github.com/microsoft/fluentui/pull/21495) by behowell@microsoft.com)
20
21
  - [breaking] Remove useControllableValue hook (use useControllableState instead) ([PR #20865](https://github.com/microsoft/fluentui/pull/20865) by elcraig@microsoft.com)
21
- - Bump @fluentui/keyboard-keys to v0.0.0-nightly940de09b9520220131.1 ([commit](https://github.com/microsoft/fluentui/commit/7343cc2ca2eaca5e933abf6a8b8b57f910107cc4) by beachball)
22
+ - Bump @fluentui/keyboard-keys to v0.0.0-nightly946f57cad420220203.1 ([commit](https://github.com/microsoft/fluentui/commit/1d230926e10b3b722bd932be1ec39faaf340671c) by beachball)
22
23
 
23
24
  ## [9.0.0-beta.4](https://github.com/microsoft/fluentui/tree/@fluentui/react-utilities_v9.0.0-beta.4)
24
25
 
@@ -119,6 +119,23 @@ export declare const defaultSSRContextValue: SSRContextValue;
119
119
  */
120
120
  export declare const divProperties: Record<string, number>;
121
121
 
122
+ /**
123
+ * Allows a component to be tagged as a FluentUI trigger component.
124
+ *
125
+ * Triggers are special-case components: they attach event listeners and other props on their child,
126
+ * and use them to trigger another component to show. Examples include `MenuTrigger` and `Tooltip`.
127
+ *
128
+ * A component can be tagged as a trigger as follows:
129
+ * ```ts
130
+ * const MyComponent: React.FC<MyComponentProps> & FluentTriggerComponent = ...;
131
+ *
132
+ * MyComponent.isFluentTriggerComponent = true; // MUST also set this to true
133
+ * ```
134
+ */
135
+ export declare type FluentTriggerComponent = {
136
+ isFluentTriggerComponent?: boolean;
137
+ };
138
+
122
139
  /**
123
140
  * An array of FORM tag properties and events.
124
141
  *
@@ -206,6 +223,28 @@ export declare function getSlots<R extends SlotPropsRecord>(state: ComponentStat
206
223
  slotProps: ObjectSlotProps<R>;
207
224
  };
208
225
 
226
+ /**
227
+ * Gets the trigger element of a FluentTriggerComponent (such as Tooltip or MenuTrigger).
228
+ *
229
+ * In the case where the immediate child is itself a FluentTriggerComponent and/or React Fragment,
230
+ * it returns the first descendant that is _not_ a FluentTriggerComponent or Fragment.
231
+ * This allows multiple triggers to be stacked, and still apply their props to the actual trigger element.
232
+ *
233
+ * For example, the following returns `<div id="child" />`:
234
+ * ```jsx
235
+ * getTriggerChild(
236
+ * <Tooltip>
237
+ * <MenuTrigger>
238
+ * <div id="child" />
239
+ * </MenuTrigger>
240
+ * </Tooltip>
241
+ * );
242
+ * ```
243
+ */
244
+ export declare const getTriggerChild: (children: React_2.ReactNode) => React_2.ReactElement & {
245
+ ref?: React_2.Ref<unknown>;
246
+ };
247
+
209
248
  /**
210
249
  * An array of HTML element properties and events.
211
250
  *
@@ -260,6 +299,12 @@ export declare type IntrinsicSlotProps<DefaultAs extends keyof JSX.IntrinsicElem
260
299
  } & SlotProps<React_2.PropsWithRef<JSX.IntrinsicElements[As]>>;
261
300
  }[AlternateAs];
262
301
 
302
+ /**
303
+ * Checks if a given element is a FluentUI trigger (e.g. `MenuTrigger` or `Tooltip`).
304
+ * See the {@link FluentTriggerComponent} type for more info.
305
+ */
306
+ export declare const isFluentTrigger: (element: React_2.ReactElement) => boolean | undefined;
307
+
263
308
  /**
264
309
  * Evaluates to true if the given type contains exactly one string, or false if it is a union of strings.
265
310
  *
@@ -331,11 +376,6 @@ export declare const olProperties: Record<string, number>;
331
376
  */
332
377
  export declare function omit<TObj extends Record<string, any>, Exclusions extends (keyof TObj)[]>(obj: TObj, exclusions: Exclusions): Omit<TObj, Exclusions[number]>;
333
378
 
334
- /**
335
- * Similar to React.Children.only, but drills into fragments rather than treating them as a single child
336
- */
337
- export declare const onlyChild: <P>(child: boolean | React_2.ReactText | React_2.ReactFragment | React_2.ReactPortal | React_2.ReactElement<P, string | React_2.JSXElementConstructor<any>> | null | undefined) => React_2.ReactElement<P, string | React_2.JSXElementConstructor<any>>;
338
-
339
379
  export declare const optionProperties: Record<string, number>;
340
380
 
341
381
  /**
@@ -599,6 +639,25 @@ export declare const useIsomorphicLayoutEffect: typeof React_2.useEffect;
599
639
  */
600
640
  export declare function useIsSSR(): boolean;
601
641
 
642
+ /**
643
+ * Combine two event callbacks into a single callback function that calls each one in order.
644
+ *
645
+ * This is useful to add an event listener to an existing element without overwriting the current listener, if any.
646
+ *
647
+ * For example:
648
+ * ```ts
649
+ * state.slot.onChange = useMergedCallbacks(state.slot.onChange, ev => {
650
+ * // Handle onChange
651
+ * });
652
+ * ```
653
+ *
654
+ * @param callback1 - The first callback to be called
655
+ * @param callback2 - The second callback to be called
656
+ *
657
+ * @returns An event callback that calls the callbacks in order, and is stable between renders
658
+ */
659
+ export declare function useMergedEventCallbacks<Args extends unknown[]>(callback1: ((...args: Args) => void) | undefined, callback2: ((...args: Args) => void) | undefined): (...args: Args) => void;
660
+
602
661
  /**
603
662
  * React hook to merge multiple React refs (either MutableRefObjects or ref callbacks) into a single ref callback that
604
663
  * updates all provided refs
@@ -665,25 +724,6 @@ export declare function useSSRContext(): SSRContextValue;
665
724
  */
666
725
  export declare function useTimeout(): readonly [(fn: () => void, delay: number) => void, () => void];
667
726
 
668
- /**
669
- * A hook that handles "trigger" pattern.
670
- *
671
- * Clones a passed element or calls render props. Merges props including refs and callbacks, callbacks are kept stable
672
- * by reference.
673
- */
674
- export declare function useTriggerElement<TriggerProps extends React_2.HTMLProps<unknown>>(options: UseTriggerElementOptions<TriggerProps>): React_2.ReactNode;
675
-
676
- export declare type UseTriggerElementOptions<TriggerProps> = {
677
- /** An actual trigger element or render props function. */
678
- children: React_2.ReactElement | ((props: TriggerProps) => React_2.ReactNode) | null | undefined;
679
- /** A ref to trigger element. */
680
- ref: React_2.Ref<unknown> | undefined;
681
- /** Props that are passed to a parent component and should be forwarded down. */
682
- outerProps: React_2.HTMLProps<unknown>;
683
- /** Custom props including callbacks. */
684
- overrideProps: TriggerProps;
685
- };
686
-
687
727
  /**
688
728
  * Hook which synchronously executes a callback when the component is about to unmount.
689
729
  *
@@ -5,12 +5,12 @@ export * from './useEventCallback';
5
5
  export * from './useFirstMount';
6
6
  export * from './useId';
7
7
  export * from './useIsomorphicLayoutEffect';
8
+ export * from './useMergedEventCallbacks';
8
9
  export * from './useMergedRefs';
9
10
  export * from './useMount';
10
11
  export * from './useOnClickOutside';
11
12
  export * from './useOnScrollOutside';
12
13
  export * from './usePrevious';
13
14
  export * from './useTimeout';
14
- export * from './useTriggerElement';
15
15
  export * from './useUnmount';
16
16
  export * from './useForceUpdate';
@@ -5,13 +5,13 @@ export * from './useEventCallback';
5
5
  export * from './useFirstMount';
6
6
  export * from './useId';
7
7
  export * from './useIsomorphicLayoutEffect';
8
+ export * from './useMergedEventCallbacks';
8
9
  export * from './useMergedRefs';
9
10
  export * from './useMount';
10
11
  export * from './useOnClickOutside';
11
12
  export * from './useOnScrollOutside';
12
13
  export * from './usePrevious';
13
14
  export * from './useTimeout';
14
- export * from './useTriggerElement';
15
15
  export * from './useUnmount';
16
16
  export * from './useForceUpdate';
17
17
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC;AACvC,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC;AAC3B,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC;AAChC,cAAc,SAAS,CAAC;AACxB,cAAc,6BAA6B,CAAC;AAC5C,cAAc,iBAAiB,CAAC;AAChC,cAAc,YAAY,CAAC;AAC3B,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,qBAAqB,CAAC;AACpC,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC;AACvC,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC;AAC3B,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC;AAChC,cAAc,SAAS,CAAC;AACxB,cAAc,6BAA6B,CAAC;AAC5C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,iBAAiB,CAAC;AAChC,cAAc,YAAY,CAAC;AAC3B,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Combine two event callbacks into a single callback function that calls each one in order.
3
+ *
4
+ * This is useful to add an event listener to an existing element without overwriting the current listener, if any.
5
+ *
6
+ * For example:
7
+ * ```ts
8
+ * state.slot.onChange = useMergedCallbacks(state.slot.onChange, ev => {
9
+ * // Handle onChange
10
+ * });
11
+ * ```
12
+ *
13
+ * @param callback1 - The first callback to be called
14
+ * @param callback2 - The second callback to be called
15
+ *
16
+ * @returns An event callback that calls the callbacks in order, and is stable between renders
17
+ */
18
+ export declare function useMergedEventCallbacks<Args extends unknown[]>(callback1: ((...args: Args) => void) | undefined, callback2: ((...args: Args) => void) | undefined): (...args: Args) => void;
@@ -0,0 +1,26 @@
1
+ import { useEventCallback } from './useEventCallback';
2
+ /**
3
+ * Combine two event callbacks into a single callback function that calls each one in order.
4
+ *
5
+ * This is useful to add an event listener to an existing element without overwriting the current listener, if any.
6
+ *
7
+ * For example:
8
+ * ```ts
9
+ * state.slot.onChange = useMergedCallbacks(state.slot.onChange, ev => {
10
+ * // Handle onChange
11
+ * });
12
+ * ```
13
+ *
14
+ * @param callback1 - The first callback to be called
15
+ * @param callback2 - The second callback to be called
16
+ *
17
+ * @returns An event callback that calls the callbacks in order, and is stable between renders
18
+ */
19
+
20
+ export function useMergedEventCallbacks(callback1, callback2) {
21
+ return useEventCallback((...args) => {
22
+ callback1 === null || callback1 === void 0 ? void 0 : callback1(...args);
23
+ callback2 === null || callback2 === void 0 ? void 0 : callback2(...args);
24
+ });
25
+ }
26
+ //# sourceMappingURL=useMergedEventCallbacks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/hooks/useMergedEventCallbacks.ts"],"names":[],"mappings":"AAAA,SAAS,gBAAT,QAAiC,oBAAjC;AAEA;;;;;;;;;;;;;;;;AAgBG;;AACH,OAAM,SAAU,uBAAV,CACJ,SADI,EAEJ,SAFI,EAE4C;AAEhD,SAAO,gBAAgB,CAAC,CAAC,GAAG,IAAJ,KAAkB;AACxC,IAAA,SAAS,KAAA,IAAT,IAAA,SAAS,KAAA,KAAA,CAAT,GAAS,KAAA,CAAT,GAAA,SAAS,CAAG,GAAG,IAAN,CAAT;AACA,IAAA,SAAS,KAAA,IAAT,IAAA,SAAS,KAAA,KAAA,CAAT,GAAS,KAAA,CAAT,GAAA,SAAS,CAAG,GAAG,IAAN,CAAT;AACD,GAHsB,CAAvB;AAID","sourceRoot":""}
@@ -1,5 +1,5 @@
1
1
  import * as React from 'react';
2
- import { onlyChild } from './onlyChild';
2
+ import { isFluentTrigger } from './isFluentTrigger';
3
3
  /**
4
4
  * Apply the trigger props to the children, either by calling the render function, or cloning with the new props.
5
5
  */
@@ -8,9 +8,26 @@ export const applyTriggerPropsToChildren = (children, triggerProps) => {
8
8
  if (typeof children === 'function') {
9
9
  return children(triggerProps);
10
10
  } else if (children) {
11
- return /*#__PURE__*/React.cloneElement(onlyChild(children), triggerProps);
11
+ return cloneTriggerTree(children, triggerProps);
12
12
  }
13
13
 
14
14
  return children;
15
15
  };
16
+ /**
17
+ * Clones a React element tree, and applies the given props to the first grandchild that is not
18
+ * a FluentTriggerComponent or React Fragment (the same element returned by {@link getTriggerChild}).
19
+ */
20
+
21
+ const cloneTriggerTree = (child, triggerProps) => {
22
+ if (! /*#__PURE__*/React.isValidElement(child) || child.type === React.Fragment) {
23
+ throw new Error('A trigger element must be a single element for this component. ' + "Please ensure that you're not using React Fragments.");
24
+ }
25
+
26
+ if (isFluentTrigger(child)) {
27
+ const grandchild = cloneTriggerTree(child.props.children, triggerProps);
28
+ return /*#__PURE__*/React.cloneElement(child, undefined, grandchild);
29
+ } else {
30
+ return /*#__PURE__*/React.cloneElement(child, triggerProps);
31
+ }
32
+ };
16
33
  //# sourceMappingURL=applyTriggerPropsToChildren.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/utils/applyTriggerPropsToChildren.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAZ,MAAuB,OAAvB;AACA,SAAS,SAAT,QAA0B,aAA1B;AAEA;;AAEG;;AACH,OAAO,MAAM,2BAA2B,GAAG,CACzC,QADyC,EAEzC,YAFyC,KAGtB;AACnB,MAAI,OAAO,QAAP,KAAoB,UAAxB,EAAoC;AAClC,WAAO,QAAQ,CAAC,YAAD,CAAf;AACD,GAFD,MAEO,IAAI,QAAJ,EAAc;AACnB,wBAAO,KAAK,CAAC,YAAN,CAAmB,SAAS,CAAC,QAAD,CAA5B,EAAwC,YAAxC,CAAP;AACD;;AAED,SAAO,QAAP;AACD,CAXM","sourceRoot":""}
1
+ {"version":3,"sources":["../../src/utils/applyTriggerPropsToChildren.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAZ,MAAuB,OAAvB;AACA,SAAS,eAAT,QAAgC,mBAAhC;AAEA;;AAEG;;AACH,OAAO,MAAM,2BAA2B,GAAG,CACzC,QADyC,EAEzC,YAFyC,KAGtB;AACnB,MAAI,OAAO,QAAP,KAAoB,UAAxB,EAAoC;AAClC,WAAO,QAAQ,CAAC,YAAD,CAAf;AACD,GAFD,MAEO,IAAI,QAAJ,EAAc;AACnB,WAAO,gBAAgB,CAAC,QAAD,EAAW,YAAX,CAAvB;AACD;;AAED,SAAO,QAAP;AACD,CAXM;AAaP;;;AAGG;;AACH,MAAM,gBAAgB,GAAG,CAAgB,KAAhB,EAAwC,YAAxC,KAA2F;AAClH,MAAI,eAAC,KAAK,CAAC,cAAN,CAAqB,KAArB,CAAD,IAAgC,KAAK,CAAC,IAAN,KAAe,KAAK,CAAC,QAAzD,EAAmE;AACjE,UAAM,IAAI,KAAJ,CACJ,oEACE,sDAFE,CAAN;AAID;;AAED,MAAI,eAAe,CAAC,KAAD,CAAnB,EAA4B;AAC1B,UAAM,UAAU,GAAG,gBAAgB,CAAC,KAAK,CAAC,KAAN,CAAY,QAAb,EAAuB,YAAvB,CAAnC;AACA,wBAAO,KAAK,CAAC,YAAN,CAAmB,KAAnB,EAA0B,SAA1B,EAAqC,UAArC,CAAP;AACD,GAHD,MAGO;AACL,wBAAO,KAAK,CAAC,YAAN,CAAmB,KAAnB,EAA0B,YAA1B,CAAP;AACD;AACF,CAdD","sourceRoot":""}
@@ -0,0 +1,22 @@
1
+ import * as React from 'react';
2
+ /**
3
+ * Gets the trigger element of a FluentTriggerComponent (such as Tooltip or MenuTrigger).
4
+ *
5
+ * In the case where the immediate child is itself a FluentTriggerComponent and/or React Fragment,
6
+ * it returns the first descendant that is _not_ a FluentTriggerComponent or Fragment.
7
+ * This allows multiple triggers to be stacked, and still apply their props to the actual trigger element.
8
+ *
9
+ * For example, the following returns `<div id="child" />`:
10
+ * ```jsx
11
+ * getTriggerChild(
12
+ * <Tooltip>
13
+ * <MenuTrigger>
14
+ * <div id="child" />
15
+ * </MenuTrigger>
16
+ * </Tooltip>
17
+ * );
18
+ * ```
19
+ */
20
+ export declare const getTriggerChild: (children: React.ReactNode) => React.ReactElement & {
21
+ ref?: React.Ref<unknown>;
22
+ };
@@ -0,0 +1,26 @@
1
+ import * as React from 'react';
2
+ import { isFluentTrigger } from './isFluentTrigger';
3
+ /**
4
+ * Gets the trigger element of a FluentTriggerComponent (such as Tooltip or MenuTrigger).
5
+ *
6
+ * In the case where the immediate child is itself a FluentTriggerComponent and/or React Fragment,
7
+ * it returns the first descendant that is _not_ a FluentTriggerComponent or Fragment.
8
+ * This allows multiple triggers to be stacked, and still apply their props to the actual trigger element.
9
+ *
10
+ * For example, the following returns `<div id="child" />`:
11
+ * ```jsx
12
+ * getTriggerChild(
13
+ * <Tooltip>
14
+ * <MenuTrigger>
15
+ * <div id="child" />
16
+ * </MenuTrigger>
17
+ * </Tooltip>
18
+ * );
19
+ * ```
20
+ */
21
+
22
+ export const getTriggerChild = children => {
23
+ const child = React.Children.only(children);
24
+ return isFluentTrigger(child) ? getTriggerChild(child.props.children) : child;
25
+ };
26
+ //# sourceMappingURL=getTriggerChild.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/utils/getTriggerChild.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAZ,MAAuB,OAAvB;AACA,SAAS,eAAT,QAAgC,mBAAhC;AAEA;;;;;;;;;;;;;;;;;AAiBG;;AACH,OAAO,MAAM,eAAe,GAAI,QAAD,IAAiF;AAC9G,QAAM,KAAK,GAAG,KAAK,CAAC,QAAN,CAAe,IAAf,CAAoB,QAApB,CAAd;AACA,SAAO,eAAe,CAAC,KAAD,CAAf,GAAyB,eAAe,CAAC,KAAK,CAAC,KAAN,CAAY,QAAb,CAAxC,GAAiE,KAAxE;AACD,CAHM","sourceRoot":""}
@@ -2,7 +2,8 @@ export * from './applyTriggerPropsToChildren';
2
2
  export * from './clamp';
3
3
  export * from './getNativeElementProps';
4
4
  export * from './getRTLSafeKey';
5
+ export * from './getTriggerChild';
6
+ export * from './isFluentTrigger';
5
7
  export * from './omit';
6
- export * from './onlyChild';
7
8
  export * from './properties';
8
9
  export * from './shouldPreventDefaultOnKeyDown';
@@ -2,8 +2,9 @@ export * from './applyTriggerPropsToChildren';
2
2
  export * from './clamp';
3
3
  export * from './getNativeElementProps';
4
4
  export * from './getRTLSafeKey';
5
+ export * from './getTriggerChild';
6
+ export * from './isFluentTrigger';
5
7
  export * from './omit';
6
- export * from './onlyChild';
7
8
  export * from './properties';
8
9
  export * from './shouldPreventDefaultOnKeyDown';
9
10
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,+BAA+B,CAAC;AAC9C,cAAc,SAAS,CAAC;AACxB,cAAc,yBAAyB,CAAC;AACxC,cAAc,iBAAiB,CAAC;AAChC,cAAc,QAAQ,CAAC;AACvB,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,iCAAiC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,+BAA+B,CAAC;AAC9C,cAAc,SAAS,CAAC;AACxB,cAAc,yBAAyB,CAAC;AACxC,cAAc,iBAAiB,CAAC;AAChC,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,QAAQ,CAAC;AACvB,cAAc,cAAc,CAAC;AAC7B,cAAc,iCAAiC,CAAC"}
@@ -0,0 +1,22 @@
1
+ import * as React from 'react';
2
+ /**
3
+ * Allows a component to be tagged as a FluentUI trigger component.
4
+ *
5
+ * Triggers are special-case components: they attach event listeners and other props on their child,
6
+ * and use them to trigger another component to show. Examples include `MenuTrigger` and `Tooltip`.
7
+ *
8
+ * A component can be tagged as a trigger as follows:
9
+ * ```ts
10
+ * const MyComponent: React.FC<MyComponentProps> & FluentTriggerComponent = ...;
11
+ *
12
+ * MyComponent.isFluentTriggerComponent = true; // MUST also set this to true
13
+ * ```
14
+ */
15
+ export declare type FluentTriggerComponent = {
16
+ isFluentTriggerComponent?: boolean;
17
+ };
18
+ /**
19
+ * Checks if a given element is a FluentUI trigger (e.g. `MenuTrigger` or `Tooltip`).
20
+ * See the {@link FluentTriggerComponent} type for more info.
21
+ */
22
+ export declare const isFluentTrigger: (element: React.ReactElement) => boolean | undefined;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Checks if a given element is a FluentUI trigger (e.g. `MenuTrigger` or `Tooltip`).
3
+ * See the {@link FluentTriggerComponent} type for more info.
4
+ */
5
+ export const isFluentTrigger = element => {
6
+ return element.type.isFluentTriggerComponent;
7
+ };
8
+ //# sourceMappingURL=isFluentTrigger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/utils/isFluentTrigger.ts"],"names":[],"mappings":"AAmBA;;;AAGG;AACH,OAAO,MAAM,eAAe,GAAI,OAAD,IAAgC;AAC7D,SAAQ,OAAO,CAAC,IAAR,CAAwC,wBAAhD;AACD,CAFM","sourceRoot":""}
@@ -5,12 +5,12 @@ export * from './useEventCallback';
5
5
  export * from './useFirstMount';
6
6
  export * from './useId';
7
7
  export * from './useIsomorphicLayoutEffect';
8
+ export * from './useMergedEventCallbacks';
8
9
  export * from './useMergedRefs';
9
10
  export * from './useMount';
10
11
  export * from './useOnClickOutside';
11
12
  export * from './useOnScrollOutside';
12
13
  export * from './usePrevious';
13
14
  export * from './useTimeout';
14
- export * from './useTriggerElement';
15
15
  export * from './useUnmount';
16
16
  export * from './useForceUpdate';
@@ -20,6 +20,8 @@ tslib_1.__exportStar(require("./useId"), exports);
20
20
 
21
21
  tslib_1.__exportStar(require("./useIsomorphicLayoutEffect"), exports);
22
22
 
23
+ tslib_1.__exportStar(require("./useMergedEventCallbacks"), exports);
24
+
23
25
  tslib_1.__exportStar(require("./useMergedRefs"), exports);
24
26
 
25
27
  tslib_1.__exportStar(require("./useMount"), exports);
@@ -32,8 +34,6 @@ tslib_1.__exportStar(require("./usePrevious"), exports);
32
34
 
33
35
  tslib_1.__exportStar(require("./useTimeout"), exports);
34
36
 
35
- tslib_1.__exportStar(require("./useTriggerElement"), exports);
36
-
37
37
  tslib_1.__exportStar(require("./useUnmount"), exports);
38
38
 
39
39
  tslib_1.__exportStar(require("./useForceUpdate"), exports);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/hooks/index.ts"],"names":[],"mappings":";;;;;;;;AAAA,OAAA,CAAA,YAAA,CAAA,OAAA,CAAA,wBAAA,CAAA,EAAA,OAAA;;AACA,OAAA,CAAA,YAAA,CAAA,OAAA,CAAA,cAAA,CAAA,EAAA,OAAA;;AACA,OAAA,CAAA,YAAA,CAAA,OAAA,CAAA,YAAA,CAAA,EAAA,OAAA;;AACA,OAAA,CAAA,YAAA,CAAA,OAAA,CAAA,oBAAA,CAAA,EAAA,OAAA;;AACA,OAAA,CAAA,YAAA,CAAA,OAAA,CAAA,iBAAA,CAAA,EAAA,OAAA;;AACA,OAAA,CAAA,YAAA,CAAA,OAAA,CAAA,SAAA,CAAA,EAAA,OAAA;;AACA,OAAA,CAAA,YAAA,CAAA,OAAA,CAAA,6BAAA,CAAA,EAAA,OAAA;;AACA,OAAA,CAAA,YAAA,CAAA,OAAA,CAAA,iBAAA,CAAA,EAAA,OAAA;;AACA,OAAA,CAAA,YAAA,CAAA,OAAA,CAAA,YAAA,CAAA,EAAA,OAAA;;AACA,OAAA,CAAA,YAAA,CAAA,OAAA,CAAA,qBAAA,CAAA,EAAA,OAAA;;AACA,OAAA,CAAA,YAAA,CAAA,OAAA,CAAA,sBAAA,CAAA,EAAA,OAAA;;AACA,OAAA,CAAA,YAAA,CAAA,OAAA,CAAA,eAAA,CAAA,EAAA,OAAA;;AACA,OAAA,CAAA,YAAA,CAAA,OAAA,CAAA,cAAA,CAAA,EAAA,OAAA;;AACA,OAAA,CAAA,YAAA,CAAA,OAAA,CAAA,qBAAA,CAAA,EAAA,OAAA;;AACA,OAAA,CAAA,YAAA,CAAA,OAAA,CAAA,cAAA,CAAA,EAAA,OAAA;;AACA,OAAA,CAAA,YAAA,CAAA,OAAA,CAAA,kBAAA,CAAA,EAAA,OAAA","sourceRoot":""}
1
+ {"version":3,"sources":["../../src/hooks/index.ts"],"names":[],"mappings":";;;;;;;;AAAA,OAAA,CAAA,YAAA,CAAA,OAAA,CAAA,wBAAA,CAAA,EAAA,OAAA;;AACA,OAAA,CAAA,YAAA,CAAA,OAAA,CAAA,cAAA,CAAA,EAAA,OAAA;;AACA,OAAA,CAAA,YAAA,CAAA,OAAA,CAAA,YAAA,CAAA,EAAA,OAAA;;AACA,OAAA,CAAA,YAAA,CAAA,OAAA,CAAA,oBAAA,CAAA,EAAA,OAAA;;AACA,OAAA,CAAA,YAAA,CAAA,OAAA,CAAA,iBAAA,CAAA,EAAA,OAAA;;AACA,OAAA,CAAA,YAAA,CAAA,OAAA,CAAA,SAAA,CAAA,EAAA,OAAA;;AACA,OAAA,CAAA,YAAA,CAAA,OAAA,CAAA,6BAAA,CAAA,EAAA,OAAA;;AACA,OAAA,CAAA,YAAA,CAAA,OAAA,CAAA,2BAAA,CAAA,EAAA,OAAA;;AACA,OAAA,CAAA,YAAA,CAAA,OAAA,CAAA,iBAAA,CAAA,EAAA,OAAA;;AACA,OAAA,CAAA,YAAA,CAAA,OAAA,CAAA,YAAA,CAAA,EAAA,OAAA;;AACA,OAAA,CAAA,YAAA,CAAA,OAAA,CAAA,qBAAA,CAAA,EAAA,OAAA;;AACA,OAAA,CAAA,YAAA,CAAA,OAAA,CAAA,sBAAA,CAAA,EAAA,OAAA;;AACA,OAAA,CAAA,YAAA,CAAA,OAAA,CAAA,eAAA,CAAA,EAAA,OAAA;;AACA,OAAA,CAAA,YAAA,CAAA,OAAA,CAAA,cAAA,CAAA,EAAA,OAAA;;AACA,OAAA,CAAA,YAAA,CAAA,OAAA,CAAA,cAAA,CAAA,EAAA,OAAA;;AACA,OAAA,CAAA,YAAA,CAAA,OAAA,CAAA,kBAAA,CAAA,EAAA,OAAA","sourceRoot":""}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Combine two event callbacks into a single callback function that calls each one in order.
3
+ *
4
+ * This is useful to add an event listener to an existing element without overwriting the current listener, if any.
5
+ *
6
+ * For example:
7
+ * ```ts
8
+ * state.slot.onChange = useMergedCallbacks(state.slot.onChange, ev => {
9
+ * // Handle onChange
10
+ * });
11
+ * ```
12
+ *
13
+ * @param callback1 - The first callback to be called
14
+ * @param callback2 - The second callback to be called
15
+ *
16
+ * @returns An event callback that calls the callbacks in order, and is stable between renders
17
+ */
18
+ export declare function useMergedEventCallbacks<Args extends unknown[]>(callback1: ((...args: Args) => void) | undefined, callback2: ((...args: Args) => void) | undefined): (...args: Args) => void;
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.useMergedEventCallbacks = void 0;
7
+
8
+ const useEventCallback_1 = /*#__PURE__*/require("./useEventCallback");
9
+ /**
10
+ * Combine two event callbacks into a single callback function that calls each one in order.
11
+ *
12
+ * This is useful to add an event listener to an existing element without overwriting the current listener, if any.
13
+ *
14
+ * For example:
15
+ * ```ts
16
+ * state.slot.onChange = useMergedCallbacks(state.slot.onChange, ev => {
17
+ * // Handle onChange
18
+ * });
19
+ * ```
20
+ *
21
+ * @param callback1 - The first callback to be called
22
+ * @param callback2 - The second callback to be called
23
+ *
24
+ * @returns An event callback that calls the callbacks in order, and is stable between renders
25
+ */
26
+
27
+
28
+ function useMergedEventCallbacks(callback1, callback2) {
29
+ return useEventCallback_1.useEventCallback((...args) => {
30
+ callback1 === null || callback1 === void 0 ? void 0 : callback1(...args);
31
+ callback2 === null || callback2 === void 0 ? void 0 : callback2(...args);
32
+ });
33
+ }
34
+
35
+ exports.useMergedEventCallbacks = useMergedEventCallbacks;
36
+ //# sourceMappingURL=useMergedEventCallbacks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/hooks/useMergedEventCallbacks.ts"],"names":[],"mappings":";;;;;;;AAAA,MAAA,kBAAA,gBAAA,OAAA,CAAA,oBAAA,CAAA;AAEA;;;;;;;;;;;;;;;;AAgBG;;;AACH,SAAgB,uBAAhB,CACE,SADF,EAEE,SAFF,EAEkD;AAEhD,SAAO,kBAAA,CAAA,gBAAA,CAAiB,CAAC,GAAG,IAAJ,KAAkB;AACxC,IAAA,SAAS,KAAA,IAAT,IAAA,SAAS,KAAA,KAAA,CAAT,GAAS,KAAA,CAAT,GAAA,SAAS,CAAG,GAAG,IAAN,CAAT;AACA,IAAA,SAAS,KAAA,IAAT,IAAA,SAAS,KAAA,KAAA,CAAT,GAAS,KAAA,CAAT,GAAA,SAAS,CAAG,GAAG,IAAN,CAAT;AACD,GAHM,CAAP;AAID;;AARD,OAAA,CAAA,uBAAA,GAAA,uBAAA","sourceRoot":""}
@@ -7,7 +7,7 @@ exports.applyTriggerPropsToChildren = void 0;
7
7
 
8
8
  const React = /*#__PURE__*/require("react");
9
9
 
10
- const onlyChild_1 = /*#__PURE__*/require("./onlyChild");
10
+ const isFluentTrigger_1 = /*#__PURE__*/require("./isFluentTrigger");
11
11
  /**
12
12
  * Apply the trigger props to the children, either by calling the render function, or cloning with the new props.
13
13
  */
@@ -17,11 +17,28 @@ const applyTriggerPropsToChildren = (children, triggerProps) => {
17
17
  if (typeof children === 'function') {
18
18
  return children(triggerProps);
19
19
  } else if (children) {
20
- return React.cloneElement(onlyChild_1.onlyChild(children), triggerProps);
20
+ return cloneTriggerTree(children, triggerProps);
21
21
  }
22
22
 
23
23
  return children;
24
24
  };
25
25
 
26
26
  exports.applyTriggerPropsToChildren = applyTriggerPropsToChildren;
27
+ /**
28
+ * Clones a React element tree, and applies the given props to the first grandchild that is not
29
+ * a FluentTriggerComponent or React Fragment (the same element returned by {@link getTriggerChild}).
30
+ */
31
+
32
+ const cloneTriggerTree = (child, triggerProps) => {
33
+ if (!React.isValidElement(child) || child.type === React.Fragment) {
34
+ throw new Error('A trigger element must be a single element for this component. ' + "Please ensure that you're not using React Fragments.");
35
+ }
36
+
37
+ if (isFluentTrigger_1.isFluentTrigger(child)) {
38
+ const grandchild = cloneTriggerTree(child.props.children, triggerProps);
39
+ return React.cloneElement(child, undefined, grandchild);
40
+ } else {
41
+ return React.cloneElement(child, triggerProps);
42
+ }
43
+ };
27
44
  //# sourceMappingURL=applyTriggerPropsToChildren.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/utils/applyTriggerPropsToChildren.ts"],"names":[],"mappings":";;;;;;;AAAA,MAAA,KAAA,gBAAA,OAAA,CAAA,OAAA,CAAA;;AACA,MAAA,WAAA,gBAAA,OAAA,CAAA,aAAA,CAAA;AAEA;;AAEG;;;AACI,MAAM,2BAA2B,GAAG,CACzC,QADyC,EAEzC,YAFyC,KAGtB;AACnB,MAAI,OAAO,QAAP,KAAoB,UAAxB,EAAoC;AAClC,WAAO,QAAQ,CAAC,YAAD,CAAf;AACD,GAFD,MAEO,IAAI,QAAJ,EAAc;AACnB,WAAO,KAAK,CAAC,YAAN,CAAmB,WAAA,CAAA,SAAA,CAAU,QAAV,CAAnB,EAAwC,YAAxC,CAAP;AACD;;AAED,SAAO,QAAP;AACD,CAXM;;AAAM,OAAA,CAAA,2BAAA,GAA2B,2BAA3B","sourceRoot":""}
1
+ {"version":3,"sources":["../../src/utils/applyTriggerPropsToChildren.ts"],"names":[],"mappings":";;;;;;;AAAA,MAAA,KAAA,gBAAA,OAAA,CAAA,OAAA,CAAA;;AACA,MAAA,iBAAA,gBAAA,OAAA,CAAA,mBAAA,CAAA;AAEA;;AAEG;;;AACI,MAAM,2BAA2B,GAAG,CACzC,QADyC,EAEzC,YAFyC,KAGtB;AACnB,MAAI,OAAO,QAAP,KAAoB,UAAxB,EAAoC;AAClC,WAAO,QAAQ,CAAC,YAAD,CAAf;AACD,GAFD,MAEO,IAAI,QAAJ,EAAc;AACnB,WAAO,gBAAgB,CAAC,QAAD,EAAW,YAAX,CAAvB;AACD;;AAED,SAAO,QAAP;AACD,CAXM;;AAAM,OAAA,CAAA,2BAAA,GAA2B,2BAA3B;AAab;;;AAGG;;AACH,MAAM,gBAAgB,GAAG,CAAgB,KAAhB,EAAwC,YAAxC,KAA2F;AAClH,MAAI,CAAC,KAAK,CAAC,cAAN,CAAqB,KAArB,CAAD,IAAgC,KAAK,CAAC,IAAN,KAAe,KAAK,CAAC,QAAzD,EAAmE;AACjE,UAAM,IAAI,KAAJ,CACJ,oEACE,sDAFE,CAAN;AAID;;AAED,MAAI,iBAAA,CAAA,eAAA,CAAgB,KAAhB,CAAJ,EAA4B;AAC1B,UAAM,UAAU,GAAG,gBAAgB,CAAC,KAAK,CAAC,KAAN,CAAY,QAAb,EAAuB,YAAvB,CAAnC;AACA,WAAO,KAAK,CAAC,YAAN,CAAmB,KAAnB,EAA0B,SAA1B,EAAqC,UAArC,CAAP;AACD,GAHD,MAGO;AACL,WAAO,KAAK,CAAC,YAAN,CAAmB,KAAnB,EAA0B,YAA1B,CAAP;AACD;AACF,CAdD","sourceRoot":""}
@@ -0,0 +1,22 @@
1
+ import * as React from 'react';
2
+ /**
3
+ * Gets the trigger element of a FluentTriggerComponent (such as Tooltip or MenuTrigger).
4
+ *
5
+ * In the case where the immediate child is itself a FluentTriggerComponent and/or React Fragment,
6
+ * it returns the first descendant that is _not_ a FluentTriggerComponent or Fragment.
7
+ * This allows multiple triggers to be stacked, and still apply their props to the actual trigger element.
8
+ *
9
+ * For example, the following returns `<div id="child" />`:
10
+ * ```jsx
11
+ * getTriggerChild(
12
+ * <Tooltip>
13
+ * <MenuTrigger>
14
+ * <div id="child" />
15
+ * </MenuTrigger>
16
+ * </Tooltip>
17
+ * );
18
+ * ```
19
+ */
20
+ export declare const getTriggerChild: (children: React.ReactNode) => React.ReactElement & {
21
+ ref?: React.Ref<unknown>;
22
+ };
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.getTriggerChild = void 0;
7
+
8
+ const React = /*#__PURE__*/require("react");
9
+
10
+ const isFluentTrigger_1 = /*#__PURE__*/require("./isFluentTrigger");
11
+ /**
12
+ * Gets the trigger element of a FluentTriggerComponent (such as Tooltip or MenuTrigger).
13
+ *
14
+ * In the case where the immediate child is itself a FluentTriggerComponent and/or React Fragment,
15
+ * it returns the first descendant that is _not_ a FluentTriggerComponent or Fragment.
16
+ * This allows multiple triggers to be stacked, and still apply their props to the actual trigger element.
17
+ *
18
+ * For example, the following returns `<div id="child" />`:
19
+ * ```jsx
20
+ * getTriggerChild(
21
+ * <Tooltip>
22
+ * <MenuTrigger>
23
+ * <div id="child" />
24
+ * </MenuTrigger>
25
+ * </Tooltip>
26
+ * );
27
+ * ```
28
+ */
29
+
30
+
31
+ const getTriggerChild = children => {
32
+ const child = React.Children.only(children);
33
+ return isFluentTrigger_1.isFluentTrigger(child) ? exports.getTriggerChild(child.props.children) : child;
34
+ };
35
+
36
+ exports.getTriggerChild = getTriggerChild;
37
+ //# sourceMappingURL=getTriggerChild.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/utils/getTriggerChild.ts"],"names":[],"mappings":";;;;;;;AAAA,MAAA,KAAA,gBAAA,OAAA,CAAA,OAAA,CAAA;;AACA,MAAA,iBAAA,gBAAA,OAAA,CAAA,mBAAA,CAAA;AAEA;;;;;;;;;;;;;;;;;AAiBG;;;AACI,MAAM,eAAe,GAAI,QAAD,IAAiF;AAC9G,QAAM,KAAK,GAAG,KAAK,CAAC,QAAN,CAAe,IAAf,CAAoB,QAApB,CAAd;AACA,SAAO,iBAAA,CAAA,eAAA,CAAgB,KAAhB,IAAyB,OAAA,CAAA,eAAA,CAAgB,KAAK,CAAC,KAAN,CAAY,QAA5B,CAAzB,GAAiE,KAAxE;AACD,CAHM;;AAAM,OAAA,CAAA,eAAA,GAAe,eAAf","sourceRoot":""}
@@ -2,7 +2,8 @@ export * from './applyTriggerPropsToChildren';
2
2
  export * from './clamp';
3
3
  export * from './getNativeElementProps';
4
4
  export * from './getRTLSafeKey';
5
+ export * from './getTriggerChild';
6
+ export * from './isFluentTrigger';
5
7
  export * from './omit';
6
- export * from './onlyChild';
7
8
  export * from './properties';
8
9
  export * from './shouldPreventDefaultOnKeyDown';
@@ -14,9 +14,11 @@ tslib_1.__exportStar(require("./getNativeElementProps"), exports);
14
14
 
15
15
  tslib_1.__exportStar(require("./getRTLSafeKey"), exports);
16
16
 
17
- tslib_1.__exportStar(require("./omit"), exports);
17
+ tslib_1.__exportStar(require("./getTriggerChild"), exports);
18
+
19
+ tslib_1.__exportStar(require("./isFluentTrigger"), exports);
18
20
 
19
- tslib_1.__exportStar(require("./onlyChild"), exports);
21
+ tslib_1.__exportStar(require("./omit"), exports);
20
22
 
21
23
  tslib_1.__exportStar(require("./properties"), exports);
22
24
 
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/utils/index.ts"],"names":[],"mappings":";;;;;;;;AAAA,OAAA,CAAA,YAAA,CAAA,OAAA,CAAA,+BAAA,CAAA,EAAA,OAAA;;AACA,OAAA,CAAA,YAAA,CAAA,OAAA,CAAA,SAAA,CAAA,EAAA,OAAA;;AACA,OAAA,CAAA,YAAA,CAAA,OAAA,CAAA,yBAAA,CAAA,EAAA,OAAA;;AACA,OAAA,CAAA,YAAA,CAAA,OAAA,CAAA,iBAAA,CAAA,EAAA,OAAA;;AACA,OAAA,CAAA,YAAA,CAAA,OAAA,CAAA,QAAA,CAAA,EAAA,OAAA;;AACA,OAAA,CAAA,YAAA,CAAA,OAAA,CAAA,aAAA,CAAA,EAAA,OAAA;;AACA,OAAA,CAAA,YAAA,CAAA,OAAA,CAAA,cAAA,CAAA,EAAA,OAAA;;AACA,OAAA,CAAA,YAAA,CAAA,OAAA,CAAA,iCAAA,CAAA,EAAA,OAAA","sourceRoot":""}
1
+ {"version":3,"sources":["../../src/utils/index.ts"],"names":[],"mappings":";;;;;;;;AAAA,OAAA,CAAA,YAAA,CAAA,OAAA,CAAA,+BAAA,CAAA,EAAA,OAAA;;AACA,OAAA,CAAA,YAAA,CAAA,OAAA,CAAA,SAAA,CAAA,EAAA,OAAA;;AACA,OAAA,CAAA,YAAA,CAAA,OAAA,CAAA,yBAAA,CAAA,EAAA,OAAA;;AACA,OAAA,CAAA,YAAA,CAAA,OAAA,CAAA,iBAAA,CAAA,EAAA,OAAA;;AACA,OAAA,CAAA,YAAA,CAAA,OAAA,CAAA,mBAAA,CAAA,EAAA,OAAA;;AACA,OAAA,CAAA,YAAA,CAAA,OAAA,CAAA,mBAAA,CAAA,EAAA,OAAA;;AACA,OAAA,CAAA,YAAA,CAAA,OAAA,CAAA,QAAA,CAAA,EAAA,OAAA;;AACA,OAAA,CAAA,YAAA,CAAA,OAAA,CAAA,cAAA,CAAA,EAAA,OAAA;;AACA,OAAA,CAAA,YAAA,CAAA,OAAA,CAAA,iCAAA,CAAA,EAAA,OAAA","sourceRoot":""}
@@ -0,0 +1,22 @@
1
+ import * as React from 'react';
2
+ /**
3
+ * Allows a component to be tagged as a FluentUI trigger component.
4
+ *
5
+ * Triggers are special-case components: they attach event listeners and other props on their child,
6
+ * and use them to trigger another component to show. Examples include `MenuTrigger` and `Tooltip`.
7
+ *
8
+ * A component can be tagged as a trigger as follows:
9
+ * ```ts
10
+ * const MyComponent: React.FC<MyComponentProps> & FluentTriggerComponent = ...;
11
+ *
12
+ * MyComponent.isFluentTriggerComponent = true; // MUST also set this to true
13
+ * ```
14
+ */
15
+ export declare type FluentTriggerComponent = {
16
+ isFluentTriggerComponent?: boolean;
17
+ };
18
+ /**
19
+ * Checks if a given element is a FluentUI trigger (e.g. `MenuTrigger` or `Tooltip`).
20
+ * See the {@link FluentTriggerComponent} type for more info.
21
+ */
22
+ export declare const isFluentTrigger: (element: React.ReactElement) => boolean | undefined;
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.isFluentTrigger = void 0;
7
+ /**
8
+ * Checks if a given element is a FluentUI trigger (e.g. `MenuTrigger` or `Tooltip`).
9
+ * See the {@link FluentTriggerComponent} type for more info.
10
+ */
11
+
12
+ const isFluentTrigger = element => {
13
+ return element.type.isFluentTriggerComponent;
14
+ };
15
+
16
+ exports.isFluentTrigger = isFluentTrigger;
17
+ //# sourceMappingURL=isFluentTrigger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/utils/isFluentTrigger.ts"],"names":[],"mappings":";;;;;;AAmBA;;;AAGG;;AACI,MAAM,eAAe,GAAI,OAAD,IAAgC;AAC7D,SAAQ,OAAO,CAAC,IAAR,CAAwC,wBAAhD;AACD,CAFM;;AAAM,OAAA,CAAA,eAAA,GAAe,eAAf","sourceRoot":""}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluentui/react-utilities",
3
- "version": "0.0.0-nightly940de09b9520220131.1",
3
+ "version": "0.0.0-nightly946f57cad420220203.1",
4
4
  "description": "A set of general React-specific utilities.",
5
5
  "main": "lib-commonjs/index.js",
6
6
  "module": "lib/index.js",
@@ -33,7 +33,7 @@
33
33
  "react-test-renderer": "^16.3.0"
34
34
  },
35
35
  "dependencies": {
36
- "@fluentui/keyboard-keys": "0.0.0-nightly940de09b9520220131.1",
36
+ "@fluentui/keyboard-keys": "0.0.0-nightly946f57cad420220203.1",
37
37
  "tslib": "^2.1.0"
38
38
  },
39
39
  "peerDependencies": {
@@ -1,18 +0,0 @@
1
- import * as React from 'react';
2
- export declare type UseTriggerElementOptions<TriggerProps> = {
3
- /** An actual trigger element or render props function. */
4
- children: React.ReactElement | ((props: TriggerProps) => React.ReactNode) | null | undefined;
5
- /** A ref to trigger element. */
6
- ref: React.Ref<unknown> | undefined;
7
- /** Props that are passed to a parent component and should be forwarded down. */
8
- outerProps: React.HTMLProps<unknown>;
9
- /** Custom props including callbacks. */
10
- overrideProps: TriggerProps;
11
- };
12
- /**
13
- * A hook that handles "trigger" pattern.
14
- *
15
- * Clones a passed element or calls render props. Merges props including refs and callbacks, callbacks are kept stable
16
- * by reference.
17
- */
18
- export declare function useTriggerElement<TriggerProps extends React.HTMLProps<unknown>>(options: UseTriggerElementOptions<TriggerProps>): React.ReactNode;
@@ -1,90 +0,0 @@
1
- import * as React from 'react';
2
- import { applyTriggerPropsToChildren } from '../utils/applyTriggerPropsToChildren';
3
- import { getReactCallbackName } from '../utils/getReactCallbackName';
4
- import { onlyChild } from '../utils/onlyChild';
5
- import { useEventCallback } from './useEventCallback';
6
- import { useMergedRefs } from './useMergedRefs';
7
- const CAPTURE_CALLBACK_REGEX = /on[A-Z].+Capture$/;
8
- const CALLBACK_REGEX = /on[A-Z].+/;
9
- /**
10
- * A hook that handles "trigger" pattern.
11
- *
12
- * Clones a passed element or calls render props. Merges props including refs and callbacks, callbacks are kept stable
13
- * by reference.
14
- */
15
-
16
- export function useTriggerElement(options) {
17
- const {
18
- children,
19
- ref,
20
- outerProps,
21
- overrideProps
22
- } = options;
23
- let childProps = {};
24
- let childRef = null; // child can be a render func, `applyTriggerPropsToChildren`does the same check again
25
- // TODO figure out a way to only do this check once
26
-
27
- if ( /*#__PURE__*/React.isValidElement(children)) {
28
- const child = onlyChild(children);
29
- childProps = child.props;
30
- childRef = child.ref;
31
- } // Two separate callbacks are needed to handle properly bubble and capture callbacks
32
- // "getReactCallbackName()" could return proper callback name, but it's possible only with React 17
33
-
34
-
35
- const handleBubbleEvent = useEventCallback(ev => {
36
- var _a, _b, _c;
37
-
38
- const callbackName = getReactCallbackName(ev);
39
-
40
- if (callbackName) {
41
- // Typecast is required as "ev" is "React.SyntheticEvent" while callbacks have stricter typings and accept
42
- // "FocusEvent", "ClipboardEvent" and etc.
43
-
44
- /* eslint-disable @typescript-eslint/no-explicit-any */
45
- (_a = childProps[callbackName]) === null || _a === void 0 ? void 0 : _a.call(childProps, ev);
46
- (_b = overrideProps[callbackName]) === null || _b === void 0 ? void 0 : _b.call(overrideProps, ev);
47
- (_c = outerProps[callbackName]) === null || _c === void 0 ? void 0 : _c.call(outerProps, ev);
48
- /* eslint-enable @typescript-eslint/no-explicit-any */
49
- }
50
- });
51
- const handleCaptureEvent = useEventCallback(ev => {
52
- var _a, _b, _c;
53
-
54
- const callbackName = getReactCallbackName(ev) + 'Capture';
55
-
56
- if (callbackName) {
57
- // Typecast is required as "ev" is "React.SyntheticEvent" while callbacks have stricter typings and accept
58
- // "FocusEvent", "ClipboardEvent" and etc.
59
-
60
- /* eslint-disable @typescript-eslint/no-explicit-any */
61
- (_a = childProps[callbackName]) === null || _a === void 0 ? void 0 : _a.call(childProps, ev);
62
- (_b = overrideProps[callbackName]) === null || _b === void 0 ? void 0 : _b.call(overrideProps, ev);
63
- (_c = outerProps[callbackName]) === null || _c === void 0 ? void 0 : _c.call(outerProps, ev);
64
- /* eslint-enable @typescript-eslint/no-explicit-any */
65
- }
66
- });
67
- const mergedPropEntries = Object.entries({ ...outerProps,
68
- ...overrideProps,
69
- ...childProps,
70
- // Undocumented, but React supports ref cloning through props
71
- ref: useMergedRefs(childRef, ref)
72
- }); // TODO: fix me after https://github.com/microsoft/fluentui/issues/21229
73
- // Causes TS error:
74
- // "Property 'fromEntries' does not exist on type 'ObjectConstructor'"
75
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
76
-
77
- const triggerProps = Object.fromEntries(mergedPropEntries.map(([propName, propValue]) => {
78
- if (propName.match(CAPTURE_CALLBACK_REGEX)) {
79
- return [propName, handleCaptureEvent];
80
- }
81
-
82
- if (propName.match(CALLBACK_REGEX)) {
83
- return [propName, handleBubbleEvent];
84
- }
85
-
86
- return [propName, propValue];
87
- }));
88
- return applyTriggerPropsToChildren(children, triggerProps);
89
- }
90
- //# sourceMappingURL=useTriggerElement.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/hooks/useTriggerElement.ts"],"names":[],"mappings":"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","sourceRoot":""}
@@ -1,5 +0,0 @@
1
- import * as React from 'react';
2
- /**
3
- * Similar to React.Children.only, but drills into fragments rather than treating them as a single child
4
- */
5
- export declare const onlyChild: <P>(child: boolean | React.ReactText | React.ReactFragment | React.ReactPortal | React.ReactElement<P, string | React.JSXElementConstructor<any>> | null | undefined) => React.ReactElement<P, string | React.JSXElementConstructor<any>>;
@@ -1,13 +0,0 @@
1
- import * as React from 'react';
2
- /**
3
- * Similar to React.Children.only, but drills into fragments rather than treating them as a single child
4
- */
5
-
6
- export const onlyChild = child => {
7
- if (! /*#__PURE__*/React.isValidElement(child)) {
8
- throw new Error(`Component's child must be a single element`);
9
- }
10
-
11
- return child.type === React.Fragment ? onlyChild(child.props.children) : child;
12
- };
13
- //# sourceMappingURL=onlyChild.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/utils/onlyChild.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAZ,MAAuB,OAAvB;AAEA;;AAEG;;AACH,OAAO,MAAM,SAAS,GACpB,KADuB,IAEE;AACzB,MAAI,eAAC,KAAK,CAAC,cAAN,CAAqB,KAArB,CAAL,EAAkC;AAChC,UAAM,IAAI,KAAJ,CAAU,4CAAV,CAAN;AACD;;AAED,SAAO,KAAK,CAAC,IAAN,KAAe,KAAK,CAAC,QAArB,GAAgC,SAAS,CAAC,KAAK,CAAC,KAAN,CAAY,QAAb,CAAzC,GAAkE,KAAzE;AACD,CARM","sourceRoot":""}
@@ -1,18 +0,0 @@
1
- import * as React from 'react';
2
- export declare type UseTriggerElementOptions<TriggerProps> = {
3
- /** An actual trigger element or render props function. */
4
- children: React.ReactElement | ((props: TriggerProps) => React.ReactNode) | null | undefined;
5
- /** A ref to trigger element. */
6
- ref: React.Ref<unknown> | undefined;
7
- /** Props that are passed to a parent component and should be forwarded down. */
8
- outerProps: React.HTMLProps<unknown>;
9
- /** Custom props including callbacks. */
10
- overrideProps: TriggerProps;
11
- };
12
- /**
13
- * A hook that handles "trigger" pattern.
14
- *
15
- * Clones a passed element or calls render props. Merges props including refs and callbacks, callbacks are kept stable
16
- * by reference.
17
- */
18
- export declare function useTriggerElement<TriggerProps extends React.HTMLProps<unknown>>(options: UseTriggerElementOptions<TriggerProps>): React.ReactNode;
@@ -1,105 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.useTriggerElement = void 0;
7
-
8
- const React = /*#__PURE__*/require("react");
9
-
10
- const applyTriggerPropsToChildren_1 = /*#__PURE__*/require("../utils/applyTriggerPropsToChildren");
11
-
12
- const getReactCallbackName_1 = /*#__PURE__*/require("../utils/getReactCallbackName");
13
-
14
- const onlyChild_1 = /*#__PURE__*/require("../utils/onlyChild");
15
-
16
- const useEventCallback_1 = /*#__PURE__*/require("./useEventCallback");
17
-
18
- const useMergedRefs_1 = /*#__PURE__*/require("./useMergedRefs");
19
-
20
- const CAPTURE_CALLBACK_REGEX = /on[A-Z].+Capture$/;
21
- const CALLBACK_REGEX = /on[A-Z].+/;
22
- /**
23
- * A hook that handles "trigger" pattern.
24
- *
25
- * Clones a passed element or calls render props. Merges props including refs and callbacks, callbacks are kept stable
26
- * by reference.
27
- */
28
-
29
- function useTriggerElement(options) {
30
- const {
31
- children,
32
- ref,
33
- outerProps,
34
- overrideProps
35
- } = options;
36
- let childProps = {};
37
- let childRef = null; // child can be a render func, `applyTriggerPropsToChildren`does the same check again
38
- // TODO figure out a way to only do this check once
39
-
40
- if (React.isValidElement(children)) {
41
- const child = onlyChild_1.onlyChild(children);
42
- childProps = child.props;
43
- childRef = child.ref;
44
- } // Two separate callbacks are needed to handle properly bubble and capture callbacks
45
- // "getReactCallbackName()" could return proper callback name, but it's possible only with React 17
46
-
47
-
48
- const handleBubbleEvent = useEventCallback_1.useEventCallback(ev => {
49
- var _a, _b, _c;
50
-
51
- const callbackName = getReactCallbackName_1.getReactCallbackName(ev);
52
-
53
- if (callbackName) {
54
- // Typecast is required as "ev" is "React.SyntheticEvent" while callbacks have stricter typings and accept
55
- // "FocusEvent", "ClipboardEvent" and etc.
56
-
57
- /* eslint-disable @typescript-eslint/no-explicit-any */
58
- (_a = childProps[callbackName]) === null || _a === void 0 ? void 0 : _a.call(childProps, ev);
59
- (_b = overrideProps[callbackName]) === null || _b === void 0 ? void 0 : _b.call(overrideProps, ev);
60
- (_c = outerProps[callbackName]) === null || _c === void 0 ? void 0 : _c.call(outerProps, ev);
61
- /* eslint-enable @typescript-eslint/no-explicit-any */
62
- }
63
- });
64
- const handleCaptureEvent = useEventCallback_1.useEventCallback(ev => {
65
- var _a, _b, _c;
66
-
67
- const callbackName = getReactCallbackName_1.getReactCallbackName(ev) + 'Capture';
68
-
69
- if (callbackName) {
70
- // Typecast is required as "ev" is "React.SyntheticEvent" while callbacks have stricter typings and accept
71
- // "FocusEvent", "ClipboardEvent" and etc.
72
-
73
- /* eslint-disable @typescript-eslint/no-explicit-any */
74
- (_a = childProps[callbackName]) === null || _a === void 0 ? void 0 : _a.call(childProps, ev);
75
- (_b = overrideProps[callbackName]) === null || _b === void 0 ? void 0 : _b.call(overrideProps, ev);
76
- (_c = outerProps[callbackName]) === null || _c === void 0 ? void 0 : _c.call(outerProps, ev);
77
- /* eslint-enable @typescript-eslint/no-explicit-any */
78
- }
79
- });
80
- const mergedPropEntries = Object.entries({ ...outerProps,
81
- ...overrideProps,
82
- ...childProps,
83
- // Undocumented, but React supports ref cloning through props
84
- ref: useMergedRefs_1.useMergedRefs(childRef, ref)
85
- }); // TODO: fix me after https://github.com/microsoft/fluentui/issues/21229
86
- // Causes TS error:
87
- // "Property 'fromEntries' does not exist on type 'ObjectConstructor'"
88
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
89
-
90
- const triggerProps = Object.fromEntries(mergedPropEntries.map(([propName, propValue]) => {
91
- if (propName.match(CAPTURE_CALLBACK_REGEX)) {
92
- return [propName, handleCaptureEvent];
93
- }
94
-
95
- if (propName.match(CALLBACK_REGEX)) {
96
- return [propName, handleBubbleEvent];
97
- }
98
-
99
- return [propName, propValue];
100
- }));
101
- return applyTriggerPropsToChildren_1.applyTriggerPropsToChildren(children, triggerProps);
102
- }
103
-
104
- exports.useTriggerElement = useTriggerElement;
105
- //# sourceMappingURL=useTriggerElement.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/hooks/useTriggerElement.ts"],"names":[],"mappings":"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","sourceRoot":""}
@@ -1,5 +0,0 @@
1
- import * as React from 'react';
2
- /**
3
- * Similar to React.Children.only, but drills into fragments rather than treating them as a single child
4
- */
5
- export declare const onlyChild: <P>(child: boolean | React.ReactText | React.ReactFragment | React.ReactPortal | React.ReactElement<P, string | React.JSXElementConstructor<any>> | null | undefined) => React.ReactElement<P, string | React.JSXElementConstructor<any>>;
@@ -1,23 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.onlyChild = void 0;
7
-
8
- const React = /*#__PURE__*/require("react");
9
- /**
10
- * Similar to React.Children.only, but drills into fragments rather than treating them as a single child
11
- */
12
-
13
-
14
- const onlyChild = child => {
15
- if (!React.isValidElement(child)) {
16
- throw new Error(`Component's child must be a single element`);
17
- }
18
-
19
- return child.type === React.Fragment ? exports.onlyChild(child.props.children) : child;
20
- };
21
-
22
- exports.onlyChild = onlyChild;
23
- //# sourceMappingURL=onlyChild.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/utils/onlyChild.ts"],"names":[],"mappings":";;;;;;;AAAA,MAAA,KAAA,gBAAA,OAAA,CAAA,OAAA,CAAA;AAEA;;AAEG;;;AACI,MAAM,SAAS,GACpB,KADuB,IAEE;AACzB,MAAI,CAAC,KAAK,CAAC,cAAN,CAAqB,KAArB,CAAL,EAAkC;AAChC,UAAM,IAAI,KAAJ,CAAU,4CAAV,CAAN;AACD;;AAED,SAAO,KAAK,CAAC,IAAN,KAAe,KAAK,CAAC,QAArB,GAAgC,OAAA,CAAA,SAAA,CAAU,KAAK,CAAC,KAAN,CAAY,QAAtB,CAAhC,GAAkE,KAAzE;AACD,CARM;;AAAM,OAAA,CAAA,SAAA,GAAS,SAAT","sourceRoot":""}