@tcn/ui 0.12.2 → 0.12.4

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 (165) hide show
  1. package/dist/actions/index.d.ts +0 -2
  2. package/dist/actions/index.d.ts.map +1 -1
  3. package/dist/actions/index.js +6 -10
  4. package/dist/actions/index.js.map +1 -1
  5. package/dist/group.css +1 -0
  6. package/dist/inputs/color_input/color_input.js +2 -4
  7. package/dist/inputs/color_input/color_input.js.map +1 -1
  8. package/dist/inputs/date_picker/date_picker_header.js +20 -22
  9. package/dist/inputs/date_picker/date_picker_header.js.map +1 -1
  10. package/dist/inputs/date_picker/date_picker_input.js +2 -4
  11. package/dist/inputs/date_picker/date_picker_input.js.map +1 -1
  12. package/dist/inputs/date_picker/date_picker_time_selector.js +9 -11
  13. package/dist/inputs/date_picker/date_picker_time_selector.js.map +1 -1
  14. package/dist/inputs/date_picker/date_picker_year_input.js +5 -7
  15. package/dist/inputs/date_picker/date_picker_year_input.js.map +1 -1
  16. package/dist/inputs/date_picker/date_picker_year_selector.js +2 -4
  17. package/dist/inputs/date_picker/date_picker_year_selector.js.map +1 -1
  18. package/dist/inputs/index.d.ts +2 -0
  19. package/dist/inputs/index.d.ts.map +1 -1
  20. package/dist/inputs/index.js +24 -20
  21. package/dist/inputs/index.js.map +1 -1
  22. package/dist/inputs/multiselect/multiselect_inline_values.js +7 -9
  23. package/dist/inputs/multiselect/multiselect_inline_values.js.map +1 -1
  24. package/dist/inputs/multiselect/multiselect_values.js +2 -4
  25. package/dist/inputs/multiselect/multiselect_values.js.map +1 -1
  26. package/dist/inputs/phone_number_input/phone_number_input_adapter.js +2 -4
  27. package/dist/inputs/phone_number_input/phone_number_input_adapter.js.map +1 -1
  28. package/dist/inputs/phone_number_input/sip_input.js +13 -15
  29. package/dist/inputs/phone_number_input/sip_input.js.map +1 -1
  30. package/dist/inputs/select/select.js +2 -4
  31. package/dist/inputs/select/select.js.map +1 -1
  32. package/dist/{actions/button → inputs}/select_group/select_group.d.ts +1 -1
  33. package/dist/inputs/select_group/select_group.d.ts.map +1 -0
  34. package/dist/{actions/button → inputs}/select_group/select_group.js +3 -3
  35. package/dist/inputs/select_group/select_group.js.map +1 -0
  36. package/dist/inputs/select_group/single_select_group.d.ts.map +1 -0
  37. package/dist/inputs/select_group/single_select_group.js.map +1 -0
  38. package/dist/inputs/suggestions/suggestion_list.js +2 -4
  39. package/dist/inputs/suggestions/suggestion_list.js.map +1 -1
  40. package/dist/layouts/group/group.d.ts +5 -0
  41. package/dist/layouts/group/group.d.ts.map +1 -0
  42. package/dist/layouts/group/group.js +26 -0
  43. package/dist/layouts/group/group.js.map +1 -0
  44. package/dist/layouts/index.d.ts +2 -0
  45. package/dist/layouts/index.d.ts.map +1 -1
  46. package/dist/layouts/index.js +36 -32
  47. package/dist/layouts/index.js.map +1 -1
  48. package/dist/overlay/popper/base/dismissal_decorator.js +6 -6
  49. package/dist/overlay/popper/base/dismissal_decorator.js.map +1 -1
  50. package/dist/overlay/popper/context_popper.d.ts.map +1 -1
  51. package/dist/overlay/popper/context_popper.js +34 -26
  52. package/dist/overlay/popper/context_popper.js.map +1 -1
  53. package/dist/overlay/popper/element_popper.d.ts.map +1 -1
  54. package/dist/overlay/popper/element_popper.js +43 -25
  55. package/dist/overlay/popper/element_popper.js.map +1 -1
  56. package/dist/overlay/tethered/hooks/use_ref_dimensions.d.ts +3 -0
  57. package/dist/overlay/tethered/hooks/use_ref_dimensions.d.ts.map +1 -0
  58. package/dist/overlay/tethered/hooks/use_ref_dimensions.js +26 -0
  59. package/dist/overlay/tethered/hooks/use_ref_dimensions.js.map +1 -0
  60. package/dist/overlay/tethered/hooks/{useTether.d.ts → use_tether.d.ts} +7 -4
  61. package/dist/overlay/tethered/hooks/use_tether.d.ts.map +1 -0
  62. package/dist/overlay/tethered/hooks/{useTether.js → use_tether.js} +19 -15
  63. package/dist/overlay/tethered/hooks/use_tether.js.map +1 -0
  64. package/dist/overlay/tethered/hooks/use_tether_origin.d.ts +10 -0
  65. package/dist/overlay/tethered/hooks/use_tether_origin.d.ts.map +1 -0
  66. package/dist/overlay/tethered/hooks/use_tether_origin.js +22 -0
  67. package/dist/overlay/tethered/hooks/use_tether_origin.js.map +1 -0
  68. package/dist/overlay/tethered/hooks/{calculate_origin.d.ts → utils/calculate_origin.d.ts} +4 -10
  69. package/dist/overlay/tethered/hooks/utils/calculate_origin.d.ts.map +1 -0
  70. package/dist/overlay/tethered/hooks/utils/calculate_origin.js +41 -0
  71. package/dist/overlay/tethered/hooks/utils/calculate_origin.js.map +1 -0
  72. package/dist/overlay/tethered/hooks/{calculate_position.d.ts → utils/calculate_position.d.ts} +2 -2
  73. package/dist/overlay/tethered/hooks/utils/calculate_position.d.ts.map +1 -0
  74. package/dist/overlay/tethered/hooks/utils/calculate_position.js.map +1 -0
  75. package/dist/overlay/tethered/tethered.d.ts.map +1 -1
  76. package/dist/overlay/tethered/tethered.js +63 -62
  77. package/dist/overlay/tethered/tethered.js.map +1 -1
  78. package/dist/select_group.css +1 -1
  79. package/dist/surfaces/alert/alert.d.ts +0 -2
  80. package/dist/surfaces/alert/alert.d.ts.map +1 -1
  81. package/dist/surfaces/alert/alert.js +5 -7
  82. package/dist/surfaces/alert/alert.js.map +1 -1
  83. package/dist/surfaces/confirm/confirm.d.ts +3 -3
  84. package/dist/surfaces/confirm/confirm.d.ts.map +1 -1
  85. package/dist/surfaces/confirm/confirm.js +46 -45
  86. package/dist/surfaces/confirm/confirm.js.map +1 -1
  87. package/dist/surfaces/pop_confirm/pop_confirm.js +11 -9
  88. package/dist/surfaces/pop_confirm/pop_confirm.js.map +1 -1
  89. package/dist/surfaces/tooltip/tooltip.d.ts.map +1 -1
  90. package/dist/surfaces/tooltip/tooltip.js +27 -28
  91. package/dist/surfaces/tooltip/tooltip.js.map +1 -1
  92. package/dist/themes/stories/button_showcase.d.ts.map +1 -1
  93. package/dist/themes/stylesheets/reset.css +1 -1
  94. package/dist/themes/stylesheets/reset.js +3 -3
  95. package/dist/themes/stylesheets/reset.js.map +1 -1
  96. package/dist/themes/themes/ergo/ergo_theme.css +1 -1
  97. package/dist/themes/themes/ergo/ergo_theme.js +128 -12
  98. package/dist/themes/themes/ergo/ergo_theme.js.map +1 -1
  99. package/package.json +3 -2
  100. package/src/actions/index.ts +0 -8
  101. package/src/inputs/index.ts +9 -0
  102. package/src/{actions/button/__stories__ → inputs/select_group}/select_group.stories.tsx +5 -26
  103. package/src/{actions/button → inputs}/select_group/select_group.tsx +3 -3
  104. package/src/layouts/bar/bar.stories.tsx +61 -0
  105. package/src/layouts/group/group.module.css +8 -0
  106. package/src/layouts/group/group.tsx +23 -0
  107. package/src/layouts/index.ts +2 -0
  108. package/src/overlay/popper/__stories__/element_popper.stories.tsx +1 -1
  109. package/src/overlay/popper/base/dismissal_decorator.tsx +1 -1
  110. package/src/overlay/popper/context_popper.tsx +7 -3
  111. package/src/overlay/popper/element_popper.tsx +14 -4
  112. package/src/overlay/tethered/__stories__/shared/base_story_config.ts +1 -1
  113. package/src/overlay/tethered/hooks/use_ref_dimensions.ts +32 -0
  114. package/src/overlay/tethered/hooks/{useTether.ts → use_tether.ts} +7 -2
  115. package/src/overlay/tethered/hooks/use_tether_origin.ts +46 -0
  116. package/src/overlay/tethered/hooks/{calculate_origin.ts → utils/calculate_origin.ts} +12 -12
  117. package/src/overlay/tethered/hooks/{calculate_position.ts → utils/calculate_position.ts} +3 -3
  118. package/src/overlay/tethered/tethered.tsx +22 -26
  119. package/src/surfaces/alert/alert.tsx +0 -2
  120. package/src/surfaces/confirm/confirm.tsx +24 -9
  121. package/src/surfaces/pop_confirm/pop_confirm.stories.tsx +206 -6
  122. package/src/surfaces/pop_confirm/pop_confirm.tsx +1 -1
  123. package/src/surfaces/tooltip/__stories__/tooltip.stories.tsx +136 -0
  124. package/src/surfaces/tooltip/__stories__/tooltip_stories.module.css +14 -0
  125. package/src/surfaces/tooltip/tooltip.tsx +6 -2
  126. package/src/themes/stories/button_showcase.tsx +19 -51
  127. package/src/themes/stylesheets/reset.css +3 -3
  128. package/src/themes/themes/ergo/ergo_theme.css +128 -12
  129. package/dist/actions/button/select_group/select_group.d.ts.map +0 -1
  130. package/dist/actions/button/select_group/select_group.js.map +0 -1
  131. package/dist/actions/button/select_group/single_select_group.d.ts.map +0 -1
  132. package/dist/actions/button/select_group/single_select_group.js.map +0 -1
  133. package/dist/overlay/tethered/hooks/calculate_origin.d.ts.map +0 -1
  134. package/dist/overlay/tethered/hooks/calculate_origin.js +0 -41
  135. package/dist/overlay/tethered/hooks/calculate_origin.js.map +0 -1
  136. package/dist/overlay/tethered/hooks/calculate_position.d.ts.map +0 -1
  137. package/dist/overlay/tethered/hooks/calculate_position.js.map +0 -1
  138. package/dist/overlay/tethered/hooks/useCaretRefDimensions.d.ts +0 -9
  139. package/dist/overlay/tethered/hooks/useCaretRefDimensions.d.ts.map +0 -1
  140. package/dist/overlay/tethered/hooks/useCaretRefDimensions.js +0 -14
  141. package/dist/overlay/tethered/hooks/useCaretRefDimensions.js.map +0 -1
  142. package/dist/overlay/tethered/hooks/useTether.d.ts.map +0 -1
  143. package/dist/overlay/tethered/hooks/useTether.js.map +0 -1
  144. package/dist/overlay/tethered/hooks/useTetherContentRect.d.ts +0 -3
  145. package/dist/overlay/tethered/hooks/useTetherContentRect.d.ts.map +0 -1
  146. package/dist/overlay/tethered/hooks/useTetherContentRect.js +0 -36
  147. package/dist/overlay/tethered/hooks/useTetherContentRect.js.map +0 -1
  148. package/dist/overlay/tethered/hooks/useTetherOrigin.d.ts +0 -14
  149. package/dist/overlay/tethered/hooks/useTetherOrigin.d.ts.map +0 -1
  150. package/dist/overlay/tethered/hooks/useTetherOrigin.js +0 -24
  151. package/dist/overlay/tethered/hooks/useTetherOrigin.js.map +0 -1
  152. package/dist/surfaces/popconfirm/pop_confirm.d.ts +0 -5
  153. package/dist/surfaces/popconfirm/pop_confirm.d.ts.map +0 -1
  154. package/dist/surfaces/popconfirm/pop_confirm.js +0 -13
  155. package/dist/surfaces/popconfirm/pop_confirm.js.map +0 -1
  156. package/src/overlay/tethered/hooks/useCaretRefDimensions.ts +0 -22
  157. package/src/overlay/tethered/hooks/useTetherContentRect.ts +0 -49
  158. package/src/overlay/tethered/hooks/useTetherOrigin.ts +0 -49
  159. package/src/surfaces/popconfirm/pop_confirm.tsx +0 -18
  160. package/src/surfaces/tooltip/tooltip.stories.tsx +0 -54
  161. /package/dist/{actions/button → inputs}/select_group/single_select_group.d.ts +0 -0
  162. /package/dist/{actions/button → inputs}/select_group/single_select_group.js +0 -0
  163. /package/dist/overlay/tethered/hooks/{calculate_position.js → utils/calculate_position.js} +0 -0
  164. /package/src/{actions/button → inputs}/select_group/select_group.module.css +0 -0
  165. /package/src/{actions/button → inputs}/select_group/single_select_group.tsx +0 -0
@@ -1,8 +1,9 @@
1
- import { forwardRef, type PropsWithChildren } from 'react';
1
+ import { forwardRef, useRef, type PropsWithChildren } from 'react';
2
2
  import { BasePopper, type BasePopperProps } from './base/base_popper.js';
3
3
  import { Tethered, type TetheredProps } from '../tethered/tethered.js';
4
4
  import { useContextTrigger } from './hooks/use_context_trigger.js';
5
5
  import { PopperDismissal } from './base/dismissal_decorator.js';
6
+ import { useForkRef } from '../../utils/index.js';
6
7
 
7
8
  export type ContextPopperProps = Omit<BasePopperProps, 'open' | 'onDismissal'> &
8
9
  Omit<TetheredProps, 'anchor'> & {
@@ -25,6 +26,9 @@ export const ContextPopper = forwardRef<
25
26
  ref
26
27
  ) {
27
28
  const { isOpen, close, rectangle } = useContextTrigger(anchorElement);
29
+ const popperRef = useRef<HTMLDivElement>(null);
30
+ const mergedRef = useForkRef(ref, popperRef);
31
+ const effectiveAcceptedRefs = [popperRef, anchorElement, ...acceptedRefs];
28
32
 
29
33
  return (
30
34
  <BasePopper
@@ -32,10 +36,10 @@ export const ContextPopper = forwardRef<
32
36
  onDismissal={close}
33
37
  restoreFocus={restoreFocus}
34
38
  dismissals={dismissals}
35
- acceptedRefs={acceptedRefs}
39
+ acceptedRefs={effectiveAcceptedRefs}
36
40
  isException={isException}
37
41
  >
38
- <Tethered ref={ref} anchor={rectangle} {...tetheredProps}>
42
+ <Tethered ref={mergedRef} anchor={rectangle} {...tetheredProps}>
39
43
  {children}
40
44
  </Tethered>
41
45
  </BasePopper>
@@ -1,9 +1,10 @@
1
- import { forwardRef, type PropsWithChildren } from 'react';
1
+ import { forwardRef, useRef, type PropsWithChildren } from 'react';
2
2
  import { BasePopper, type BasePopperProps } from './base/base_popper.js';
3
3
  import {
4
4
  ElementTethered,
5
5
  type ElementTetheredProps,
6
6
  } from '../tethered/element_tethered.js';
7
+ import { useForkRef } from '../../utils/index.js';
7
8
 
8
9
  export type ElementPopperProps = BasePopperProps & ElementTetheredProps;
9
10
 
@@ -16,14 +17,19 @@ export const ElementPopper = forwardRef<
16
17
  open,
17
18
  onDismissal,
18
19
  isException,
19
- acceptedRefs,
20
+ acceptedRefs = [],
20
21
  veil,
21
22
  dismissals,
22
23
  children,
24
+ anchorElement,
23
25
  ...elementTetheredProps
24
26
  },
25
27
  ref
26
28
  ) {
29
+ const popperRef = useRef<HTMLDivElement>(null);
30
+ const mergedRef = useForkRef(ref, popperRef);
31
+ const effectiveAcceptedRefs = [popperRef, anchorElement, ...acceptedRefs];
32
+
27
33
  return (
28
34
  <BasePopper
29
35
  restoreFocus={restoreFocus}
@@ -31,10 +37,14 @@ export const ElementPopper = forwardRef<
31
37
  onDismissal={onDismissal}
32
38
  isException={isException}
33
39
  dismissals={dismissals}
34
- acceptedRefs={acceptedRefs}
40
+ acceptedRefs={effectiveAcceptedRefs}
35
41
  veil={veil}
36
42
  >
37
- <ElementTethered ref={ref} {...elementTetheredProps}>
43
+ <ElementTethered
44
+ ref={mergedRef}
45
+ anchorElement={anchorElement}
46
+ {...elementTetheredProps}
47
+ >
38
48
  {children}
39
49
  </ElementTethered>
40
50
  </BasePopper>
@@ -56,5 +56,5 @@ export const tetheredArgs: TetheredStoryArgs = {
56
56
  horizontalOrigin: 'center',
57
57
  verticalOffset: 0,
58
58
  horizontalOffset: 0,
59
- precision: 'low',
59
+ precision: undefined,
60
60
  };
@@ -0,0 +1,32 @@
1
+ import { useLayoutEffect, useState } from 'react';
2
+ import type { Dimensions } from '../../../utils/index.js';
3
+
4
+ function getDimensions(element: HTMLElement | null): Dimensions {
5
+ if (!element) return { width: 0, height: 0 };
6
+ const rect = element.getBoundingClientRect();
7
+ return { width: rect.width, height: rect.height };
8
+ }
9
+
10
+ export function useRefDimensions(ref: React.RefObject<HTMLElement>): Dimensions {
11
+ const [dimensions, setDimensions] = useState<Dimensions>(() =>
12
+ getDimensions(ref.current)
13
+ );
14
+
15
+ useLayoutEffect(() => {
16
+ const update = () => {
17
+ setDimensions(getDimensions(ref.current));
18
+ };
19
+
20
+ update();
21
+
22
+ const resizeObserver = new ResizeObserver(update);
23
+ if (!ref.current) return;
24
+ resizeObserver.observe(ref.current);
25
+
26
+ return () => {
27
+ resizeObserver.disconnect();
28
+ };
29
+ }, [ref]);
30
+
31
+ return dimensions;
32
+ }
@@ -1,7 +1,8 @@
1
1
  import { useCallback, useLayoutEffect, useRef, useState } from 'react';
2
2
  import { type Rectangle } from '../../../utils/index.js';
3
3
  import type { HorizontalTether, VerticalTether } from '../types.js';
4
- import { calculateTetheredPosition } from './calculate_position.js';
4
+ import { calculateTetheredPosition } from './utils/calculate_position.js';
5
+ import { useRefDimensions } from './use_ref_dimensions.js';
5
6
 
6
7
  export interface UseTetherParams {
7
8
  anchor: Rectangle | null;
@@ -24,6 +25,7 @@ export function useTether({
24
25
  }: UseTetherParams) {
25
26
  const [position, setPosition] = useState({ top: 0, left: 0 });
26
27
  const tetherRef = useRef<HTMLDivElement>(null);
28
+ const dimensions = useRefDimensions(tetherRef);
27
29
 
28
30
  const getPosition = useCallback(() => {
29
31
  if (!anchor || !tetherRef.current) return;
@@ -82,5 +84,8 @@ export function useTether({
82
84
  };
83
85
  });
84
86
 
85
- return { position, tetherRef };
87
+ return {
88
+ rectangle: { dimensions, position: { x: position.left, y: position.top } },
89
+ tetherRef,
90
+ };
86
91
  }
@@ -0,0 +1,46 @@
1
+ import { useRef } from 'react';
2
+ import type { Position, Rectangle } from '../../../utils/index.js';
3
+ import type { HorizontalTether, VerticalTether } from '../types.js';
4
+ import {
5
+ getOriginDirection,
6
+ getOriginOffset,
7
+ getOriginPosition,
8
+ type CaretDirection,
9
+ } from './utils/calculate_origin.js';
10
+ import { useRefDimensions } from './use_ref_dimensions.js';
11
+
12
+ export interface TetherOrigin {
13
+ rectangle: Rectangle;
14
+ offset: Position;
15
+ direction: CaretDirection;
16
+ }
17
+
18
+ const initialOriginResult: TetherOrigin = {
19
+ rectangle: { dimensions: { width: 0, height: 0 }, position: { x: 0, y: 0 } },
20
+ offset: { x: 0, y: 0 },
21
+ direction: 'none',
22
+ };
23
+
24
+ export function useTetherOrigin(
25
+ tetherRectangle: Rectangle,
26
+ hOrigin: HorizontalTether,
27
+ vOrigin: VerticalTether,
28
+ precision: 'high' | 'low'
29
+ ): [TetherOrigin, React.RefObject<HTMLElement>] {
30
+ const ref = useRef<HTMLElement | null>(null);
31
+ const dimensions = useRefDimensions(ref);
32
+
33
+ if (precision === 'low') return [initialOriginResult, ref];
34
+
35
+ // Calculate origin values for high precision
36
+ const originOffset = getOriginOffset(tetherRectangle.dimensions, hOrigin, vOrigin);
37
+ const originPosition = getOriginPosition(tetherRectangle.position, originOffset);
38
+ const originDirection = getOriginDirection(vOrigin, hOrigin);
39
+
40
+ const origin: TetherOrigin = {
41
+ rectangle: { dimensions, position: originPosition },
42
+ offset: originOffset,
43
+ direction: originDirection,
44
+ };
45
+ return [origin, ref];
46
+ }
@@ -1,5 +1,5 @@
1
- import type { Position, Rectangle } from '../../../utils/index.js';
2
- import type { HorizontalTether, VerticalTether } from '../types.js';
1
+ import type { Dimensions, Position } from '../../../../utils/index.js';
2
+ import type { HorizontalTether, VerticalTether } from '../../types.js';
3
3
 
4
4
  export type CaretDirection = 'top' | 'bottom' | 'start' | 'end' | 'none';
5
5
 
@@ -8,10 +8,10 @@ export type CaretDirection = 'top' | 'bottom' | 'start' | 'end' | 'none';
8
8
  * based on tether dimensions and origin alignment.
9
9
  */
10
10
  export function getOriginOffset(
11
- tether: Rectangle,
11
+ tetherDimensions: Dimensions,
12
12
  hOrigin: HorizontalTether,
13
13
  vOrigin: VerticalTether
14
- ): { yOffset: number; xOffset: number } {
14
+ ): Position {
15
15
  let yOffset = 0;
16
16
  let xOffset = 0;
17
17
 
@@ -21,10 +21,10 @@ export function getOriginOffset(
21
21
  yOffset = 0;
22
22
  break;
23
23
  case 'center':
24
- yOffset = tether.dimensions.height / 2;
24
+ yOffset = tetherDimensions.height / 2;
25
25
  break;
26
26
  case 'bottom':
27
- yOffset = tether.dimensions.height;
27
+ yOffset = tetherDimensions.height;
28
28
  break;
29
29
  }
30
30
 
@@ -34,14 +34,14 @@ export function getOriginOffset(
34
34
  xOffset = 0;
35
35
  break;
36
36
  case 'center':
37
- xOffset = tether.dimensions.width / 2;
37
+ xOffset = tetherDimensions.width / 2;
38
38
  break;
39
39
  case 'end':
40
- xOffset = tether.dimensions.width;
40
+ xOffset = tetherDimensions.width;
41
41
  break;
42
42
  }
43
43
 
44
- return { yOffset, xOffset };
44
+ return { y: yOffset, x: xOffset };
45
45
  }
46
46
 
47
47
  /**
@@ -49,11 +49,11 @@ export function getOriginOffset(
49
49
  */
50
50
  export function getOriginPosition(
51
51
  baselinePosition: Position,
52
- offset: { yOffset: number; xOffset: number }
52
+ offset: Position
53
53
  ): Position {
54
54
  return {
55
- x: baselinePosition.x + offset.xOffset,
56
- y: baselinePosition.y + offset.yOffset,
55
+ x: baselinePosition.x + offset.x,
56
+ y: baselinePosition.y + offset.y,
57
57
  };
58
58
  }
59
59
 
@@ -1,6 +1,6 @@
1
- import type { HorizontalTether, VerticalTether } from '../types.js';
2
- import type { Rectangle } from '../../../utils/index.js';
3
- import type { Dimensions } from '../../../utils/index.js';
1
+ import type { HorizontalTether, VerticalTether } from '../../types.js';
2
+ import type { Rectangle } from '../../../../utils/index.js';
3
+ import type { Dimensions } from '../../../../utils/index.js';
4
4
 
5
5
  export interface CalculateTetheredPositionParams {
6
6
  anchor: Rectangle;
@@ -4,9 +4,8 @@ import { ZStack, type ZStackProps } from '../../stacks/index.js';
4
4
  import { useForkRef, type Rectangle } from '../../utils/index.js';
5
5
  import { Caret } from '../caret/caret.js';
6
6
  import { Portal } from '../portal/portal.js';
7
- import { useCaretRefDimensions } from './hooks/useCaretRefDimensions.js';
8
- import { useTether } from './hooks/useTether.js';
9
- import { useTetherOrigin } from './hooks/useTetherOrigin.js';
7
+ import { useTether } from './hooks/use_tether.js';
8
+ import { useTetherOrigin } from './hooks/use_tether_origin.js';
10
9
  import type { HorizontalTether, VerticalTether } from './types.js';
11
10
 
12
11
  // Styles
@@ -25,6 +24,7 @@ export interface TetheredOwnProp extends BaseTetheredOwnProps {
25
24
  anchor: Rectangle | null;
26
25
  precision?: 'high' | 'low';
27
26
  }
27
+
28
28
  export interface TetheredProps extends TetheredOwnProp, ZStackProps {}
29
29
 
30
30
  export const Tethered = forwardRef<HTMLElement, PropsWithChildren<TetheredProps>>(
@@ -45,7 +45,7 @@ export const Tethered = forwardRef<HTMLElement, PropsWithChildren<TetheredProps>
45
45
  },
46
46
  ref
47
47
  ) {
48
- const { position, tetherRef } = useTether({
48
+ const { rectangle, tetherRef } = useTether({
49
49
  anchor,
50
50
  verticalAnchor,
51
51
  verticalOrigin,
@@ -55,28 +55,24 @@ export const Tethered = forwardRef<HTMLElement, PropsWithChildren<TetheredProps>
55
55
  horizontalOffset,
56
56
  });
57
57
 
58
- // Convert position from { top, left } to Position type { x, y }
59
- const tetherPosition = { x: position.left, y: position.top };
60
-
61
- const { originPosition, originOffset, containerRef, originDirection } =
62
- useTetherOrigin(tetherPosition, horizontalOrigin, verticalOrigin, precision);
63
-
64
- const { caretElementRef: setCaretElement, caretSize } = useCaretRefDimensions(
65
- precision,
66
- originDirection
58
+ const [origin, originRef] = useTetherOrigin(
59
+ rectangle,
60
+ horizontalOrigin,
61
+ verticalOrigin,
62
+ precision
67
63
  );
68
64
 
69
- const forkedRef = useForkRef(ref, tetherRef, containerRef);
65
+ const forkedRef = useForkRef(ref, tetherRef);
70
66
 
71
67
  const cssVariables = {
72
- '--tethered-top': `${position.top}px`,
73
- '--tethered-left': `${position.left}px`,
74
- '--tethered-origin-y': `${originPosition.y}px`,
75
- '--tethered-origin-x': `${originPosition.x}px`,
76
- '--tethered-origin-delta-y': `${originOffset.yOffset}px`,
77
- '--tethered-origin-delta-x': `${originOffset.xOffset}px`,
78
- '--origin-indicator-dimensions-width': `${caretSize.width}px`,
79
- '--origin-indicator-dimensions-height': `${caretSize.height}px`,
68
+ '--tethered-top': `${rectangle.position.y}px`,
69
+ '--tethered-left': `${rectangle.position.x}px`,
70
+ '--tethered-origin-y': `${origin.rectangle.position.y}px`,
71
+ '--tethered-origin-x': `${origin.rectangle.position.x}px`,
72
+ '--tethered-origin-delta-y': `${origin.offset.y}px`,
73
+ '--tethered-origin-delta-x': `${origin.offset.x}px`,
74
+ '--origin-indicator-dimensions-width': `${origin.rectangle.dimensions.width}px`,
75
+ '--origin-indicator-dimensions-height': `${origin.rectangle.dimensions.height}px`,
80
76
  };
81
77
 
82
78
  return (
@@ -89,14 +85,14 @@ export const Tethered = forwardRef<HTMLElement, PropsWithChildren<TetheredProps>
89
85
  data-h-anchor={horizontalAnchor}
90
86
  data-v-origin={verticalOrigin}
91
87
  data-h-origin={horizontalOrigin}
92
- data-anchor-direction={originDirection}
88
+ data-anchor-direction={origin.direction}
93
89
  {...rest}
94
90
  >
95
91
  {children}
96
- {precision === 'high' && originDirection !== 'none' && (
92
+ {precision === 'high' && origin.direction !== 'none' && (
97
93
  <Caret
98
- ref={setCaretElement}
99
- direction={originDirection}
94
+ ref={originRef}
95
+ direction={origin.direction}
100
96
  className={clsx(
101
97
  styles['origin-indicator'],
102
98
  'tcn-tethered-origin-indicator'
@@ -6,8 +6,6 @@ import { Confirm, ConfirmProps } from '../confirm/confirm.js';
6
6
  export interface AlertProps extends Omit<ConfirmProps, 'actions'> {
7
7
  open?: boolean;
8
8
  graphic?: React.ReactNode;
9
- title?: string;
10
- description?: string;
11
9
  onAccept?: () => void;
12
10
  }
13
11
 
@@ -8,11 +8,12 @@ import { BodyText, Title } from '../../typography/index.js';
8
8
  import styles from './confirm.module.css';
9
9
  import { Box, type BoxProps } from '../../stacks/box/box.js';
10
10
 
11
- export interface ConfirmProps extends React.HTMLAttributes<HTMLDivElement> {
11
+ export interface ConfirmProps
12
+ extends Omit<React.HTMLAttributes<HTMLDivElement>, 'title'> {
12
13
  open?: boolean;
13
14
  graphic?: React.ReactNode;
14
- title?: string;
15
- description?: string;
15
+ title?: React.ReactNode;
16
+ description?: React.ReactNode;
16
17
  actions?: React.ReactNode;
17
18
  veilProps?: BoxProps;
18
19
  }
@@ -54,6 +55,24 @@ export const Confirm = React.forwardRef(function Confirm(
54
55
  setShake(true);
55
56
  }
56
57
 
58
+ const descriptionElement =
59
+ typeof description === 'string' ? (
60
+ <BodyText className="tcn-confirm-description" hierarchy="tertiary">
61
+ {description}
62
+ </BodyText>
63
+ ) : (
64
+ description
65
+ );
66
+
67
+ const titleElement =
68
+ typeof title === 'string' ? (
69
+ <Title className="tcn-confirm-title" emphasis="strong" size="sm">
70
+ {title}
71
+ </Title>
72
+ ) : (
73
+ title
74
+ );
75
+
57
76
  return (
58
77
  <>
59
78
  {open && (
@@ -68,12 +87,8 @@ export const Confirm = React.forwardRef(function Confirm(
68
87
  >
69
88
  <VStack hAlign="center">
70
89
  {graphic}
71
- <Title className="tcn-confirm-title" emphasis="strong" size="sm">
72
- {title}
73
- </Title>
74
- <BodyText className="tcn-confirm-description" hierarchy="tertiary">
75
- {description}
76
- </BodyText>
90
+ {titleElement}
91
+ {descriptionElement}
77
92
  <Spacer height="16px" />
78
93
  <Box
79
94
  className={clsx(styles.actions, 'tcn-confirm-actions')}