smarthr-ui 96.1.0 → 96.1.2

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 (189) hide show
  1. package/lib/components/AppHeader/components/common/CommonButton.cjs +3 -2
  2. package/lib/components/AppHeader/components/common/CommonButton.cjs.map +1 -1
  3. package/lib/components/AppHeader/components/common/CommonButton.js +3 -2
  4. package/lib/components/AppHeader/components/common/CommonButton.js.map +1 -1
  5. package/lib/components/Base/Base.cjs +7 -1
  6. package/lib/components/Base/Base.cjs.map +1 -1
  7. package/lib/components/Base/Base.js +7 -1
  8. package/lib/components/Base/Base.js.map +1 -1
  9. package/lib/components/Base/BaseColumn/BaseColumn.cjs +7 -1
  10. package/lib/components/Base/BaseColumn/BaseColumn.cjs.map +1 -1
  11. package/lib/components/Base/BaseColumn/BaseColumn.js +7 -1
  12. package/lib/components/Base/BaseColumn/BaseColumn.js.map +1 -1
  13. package/lib/components/BottomFixedArea/BottomFixedArea.cjs +1 -3
  14. package/lib/components/BottomFixedArea/BottomFixedArea.cjs.map +1 -1
  15. package/lib/components/BottomFixedArea/BottomFixedArea.js +2 -4
  16. package/lib/components/BottomFixedArea/BottomFixedArea.js.map +1 -1
  17. package/lib/components/Button/AnchorButton.cjs +2 -7
  18. package/lib/components/Button/AnchorButton.cjs.map +1 -1
  19. package/lib/components/Button/AnchorButton.js +2 -7
  20. package/lib/components/Button/AnchorButton.js.map +1 -1
  21. package/lib/components/Button/useButtonWrapper.cjs +24 -6
  22. package/lib/components/Button/useButtonWrapper.cjs.map +1 -1
  23. package/lib/components/Button/useButtonWrapper.js +24 -6
  24. package/lib/components/Button/useButtonWrapper.js.map +1 -1
  25. package/lib/components/Combobox/MultiCombobox/MultiSelectedItem.cjs +8 -4
  26. package/lib/components/Combobox/MultiCombobox/MultiSelectedItem.cjs.map +1 -1
  27. package/lib/components/Combobox/MultiCombobox/MultiSelectedItem.js +8 -4
  28. package/lib/components/Combobox/MultiCombobox/MultiSelectedItem.js.map +1 -1
  29. package/lib/components/Dialog/DialogBody.cjs +7 -1
  30. package/lib/components/Dialog/DialogBody.cjs.map +1 -1
  31. package/lib/components/Dialog/DialogBody.js +7 -1
  32. package/lib/components/Dialog/DialogBody.js.map +1 -1
  33. package/lib/components/Dialog/DialogContentInner.cjs +7 -1
  34. package/lib/components/Dialog/DialogContentInner.cjs.map +1 -1
  35. package/lib/components/Dialog/DialogContentInner.js +7 -1
  36. package/lib/components/Dialog/DialogContentInner.js.map +1 -1
  37. package/lib/components/Dialog/DialogOverlap.cjs +22 -5
  38. package/lib/components/Dialog/DialogOverlap.cjs.map +1 -1
  39. package/lib/components/Dialog/DialogOverlap.js +23 -6
  40. package/lib/components/Dialog/DialogOverlap.js.map +1 -1
  41. package/lib/components/Dialog/ModelessDialog/ModelessDialog.cjs +7 -1
  42. package/lib/components/Dialog/ModelessDialog/ModelessDialog.cjs.map +1 -1
  43. package/lib/components/Dialog/ModelessDialog/ModelessDialog.js +7 -1
  44. package/lib/components/Dialog/ModelessDialog/ModelessDialog.js.map +1 -1
  45. package/lib/components/Dialog/RemoteDialogTrigger/RemoteDialogTrigger.cjs +51 -11
  46. package/lib/components/Dialog/RemoteDialogTrigger/RemoteDialogTrigger.cjs.map +1 -1
  47. package/lib/components/Dialog/RemoteDialogTrigger/RemoteDialogTrigger.d.ts +3 -4
  48. package/lib/components/Dialog/RemoteDialogTrigger/RemoteDialogTrigger.js +52 -12
  49. package/lib/components/Dialog/RemoteDialogTrigger/RemoteDialogTrigger.js.map +1 -1
  50. package/lib/components/Dropdown/Dropdown.cjs +3 -3
  51. package/lib/components/Dropdown/Dropdown.cjs.map +1 -1
  52. package/lib/components/Dropdown/Dropdown.d.ts +1 -1
  53. package/lib/components/Dropdown/Dropdown.js +3 -3
  54. package/lib/components/Dropdown/Dropdown.js.map +1 -1
  55. package/lib/components/Dropdown/DropdownMenuButton/DropdownMenuButton.cjs +20 -10
  56. package/lib/components/Dropdown/DropdownMenuButton/DropdownMenuButton.cjs.map +1 -1
  57. package/lib/components/Dropdown/DropdownMenuButton/DropdownMenuButton.js +21 -11
  58. package/lib/components/Dropdown/DropdownMenuButton/DropdownMenuButton.js.map +1 -1
  59. package/lib/components/Dropdown/DropdownTrigger.cjs +33 -16
  60. package/lib/components/Dropdown/DropdownTrigger.cjs.map +1 -1
  61. package/lib/components/Dropdown/DropdownTrigger.js +33 -16
  62. package/lib/components/Dropdown/DropdownTrigger.js.map +1 -1
  63. package/lib/components/Header/Header.cjs +3 -3
  64. package/lib/components/Header/Header.cjs.map +1 -1
  65. package/lib/components/Header/Header.js +3 -3
  66. package/lib/components/Header/Header.js.map +1 -1
  67. package/lib/components/Icon/generateIcon.cjs +9 -1
  68. package/lib/components/Icon/generateIcon.cjs.map +1 -1
  69. package/lib/components/Icon/generateIcon.js +9 -1
  70. package/lib/components/Icon/generateIcon.js.map +1 -1
  71. package/lib/components/Layout/Cluster/Cluster.cjs +4 -0
  72. package/lib/components/Layout/Cluster/Cluster.cjs.map +1 -1
  73. package/lib/components/Layout/Cluster/Cluster.d.ts +1 -1
  74. package/lib/components/Layout/Cluster/Cluster.js +4 -0
  75. package/lib/components/Layout/Cluster/Cluster.js.map +1 -1
  76. package/lib/components/Layout/Container/Container.cjs +2 -2
  77. package/lib/components/Layout/Container/Container.js +2 -2
  78. package/lib/components/Scroller/Scroller.cjs +12 -19
  79. package/lib/components/Scroller/Scroller.cjs.map +1 -1
  80. package/lib/components/Scroller/Scroller.js +13 -20
  81. package/lib/components/Scroller/Scroller.js.map +1 -1
  82. package/lib/components/Table/TableReel.cjs +1 -1
  83. package/lib/components/Table/TableReel.cjs.map +1 -1
  84. package/lib/components/Table/TableReel.js +1 -1
  85. package/lib/components/Table/TableReel.js.map +1 -1
  86. package/lib/components/Table/TableScrollContext.cjs +4 -4
  87. package/lib/components/Table/TableScrollContext.js +4 -4
  88. package/lib/components/Table/useReelCells.cjs +13 -7
  89. package/lib/components/Table/useReelCells.cjs.map +1 -1
  90. package/lib/components/Table/useReelCells.d.ts +1 -3
  91. package/lib/components/Table/useReelCells.js +13 -7
  92. package/lib/components/Table/useReelCells.js.map +1 -1
  93. package/lib/components/Text/Text.cjs +3 -1
  94. package/lib/components/Text/Text.cjs.map +1 -1
  95. package/lib/components/Text/Text.js +3 -1
  96. package/lib/components/Text/Text.js.map +1 -1
  97. package/lib/components/TextLink/TextLink.cjs +14 -28
  98. package/lib/components/TextLink/TextLink.cjs.map +1 -1
  99. package/lib/components/TextLink/TextLink.js +15 -29
  100. package/lib/components/TextLink/TextLink.js.map +1 -1
  101. package/lib/components/TextLink/UpwardLink/UpwardLink.cjs +2 -2
  102. package/lib/components/TextLink/UpwardLink/UpwardLink.js +2 -2
  103. package/lib/components/Textarea/Textarea.cjs +7 -6
  104. package/lib/components/Textarea/Textarea.cjs.map +1 -1
  105. package/lib/components/Textarea/Textarea.js +7 -6
  106. package/lib/components/Textarea/Textarea.js.map +1 -1
  107. package/lib/components/Tooltip/Tooltip.cjs +12 -21
  108. package/lib/components/Tooltip/Tooltip.cjs.map +1 -1
  109. package/lib/components/Tooltip/Tooltip.js +14 -23
  110. package/lib/components/Tooltip/Tooltip.js.map +1 -1
  111. package/lib/components/Tooltip/TooltipPortal.cjs +2 -2
  112. package/lib/components/Tooltip/TooltipPortal.cjs.map +1 -1
  113. package/lib/components/Tooltip/TooltipPortal.d.ts +1 -0
  114. package/lib/components/Tooltip/TooltipPortal.js +2 -2
  115. package/lib/components/Tooltip/TooltipPortal.js.map +1 -1
  116. package/lib/components/Tooltip/tooltipHelper.cjs +2 -2
  117. package/lib/components/Tooltip/tooltipHelper.cjs.map +1 -1
  118. package/lib/components/Tooltip/tooltipHelper.js +2 -2
  119. package/lib/components/Tooltip/tooltipHelper.js.map +1 -1
  120. package/lib/components/WarekiPicker/WarekiPicker.cjs +2 -3
  121. package/lib/components/WarekiPicker/WarekiPicker.cjs.map +1 -1
  122. package/lib/components/WarekiPicker/WarekiPicker.js +2 -3
  123. package/lib/components/WarekiPicker/WarekiPicker.js.map +1 -1
  124. package/lib/configureTwMerge.cjs +2 -2
  125. package/lib/configureTwMerge.js +2 -2
  126. package/lib/hooks/useDevice/DeviceProvider.cjs +2 -2
  127. package/lib/hooks/useDevice/DeviceProvider.js +2 -2
  128. package/lib/hooks/useEnvironment/EnvironmentProvider.cjs +2 -2
  129. package/lib/hooks/useEnvironment/EnvironmentProvider.js +2 -2
  130. package/lib/hooks/useOuterClick.cjs +5 -2
  131. package/lib/hooks/useOuterClick.cjs.map +1 -1
  132. package/lib/hooks/useOuterClick.js +6 -3
  133. package/lib/hooks/useOuterClick.js.map +1 -1
  134. package/lib/hooks/usePortal.cjs +1 -1
  135. package/lib/hooks/usePortal.cjs.map +1 -1
  136. package/lib/hooks/usePortal.js +1 -1
  137. package/lib/hooks/usePortal.js.map +1 -1
  138. package/lib/hooks/useSV/useSV.cjs +2 -2
  139. package/lib/hooks/useSV/useSV.js +2 -2
  140. package/lib/hooks/useTheme.cjs +3 -0
  141. package/lib/hooks/useTheme.cjs.map +1 -1
  142. package/lib/hooks/useTheme.js +3 -0
  143. package/lib/hooks/useTheme.js.map +1 -1
  144. package/lib/index.cjs +14 -8
  145. package/lib/index.cjs.map +1 -1
  146. package/lib/index.d.ts +1 -10
  147. package/lib/index.js +10 -4
  148. package/lib/index.js.map +1 -1
  149. package/lib/intl/locales/index.cjs +1 -0
  150. package/lib/intl/locales/index.cjs.map +1 -1
  151. package/lib/intl/locales/index.js +1 -0
  152. package/lib/intl/locales/index.js.map +1 -1
  153. package/lib/libs/ua.cjs +1 -2
  154. package/lib/libs/ua.cjs.map +1 -1
  155. package/lib/libs/ua.js +1 -2
  156. package/lib/libs/ua.js.map +1 -1
  157. package/lib/smarthr-ui-preset.cjs +4 -4
  158. package/lib/smarthr-ui-preset.js +4 -4
  159. package/lib/tailwind/color.cjs +9 -0
  160. package/lib/tailwind/color.cjs.map +1 -1
  161. package/lib/tailwind/color.d.ts +1 -1
  162. package/lib/tailwind/color.js +9 -0
  163. package/lib/tailwind/color.js.map +1 -1
  164. package/lib/tailwind/fontSize.cjs +10 -0
  165. package/lib/tailwind/fontSize.cjs.map +1 -1
  166. package/lib/tailwind/fontSize.d.ts +1 -1
  167. package/lib/tailwind/fontSize.js +10 -0
  168. package/lib/tailwind/fontSize.js.map +1 -1
  169. package/lib/tailwind/index.cjs +10 -2
  170. package/lib/tailwind/index.cjs.map +1 -1
  171. package/lib/tailwind/index.js +9 -1
  172. package/lib/tailwind/index.js.map +1 -1
  173. package/lib/tailwind/textColor.cjs +9 -0
  174. package/lib/tailwind/textColor.cjs.map +1 -1
  175. package/lib/tailwind/textColor.d.ts +1 -1
  176. package/lib/tailwind/textColor.js +9 -0
  177. package/lib/tailwind/textColor.js.map +1 -1
  178. package/lib/themes/createWidth.cjs +1 -3
  179. package/lib/themes/createWidth.cjs.map +1 -1
  180. package/lib/themes/createWidth.d.ts +3 -1
  181. package/lib/themes/createWidth.js +1 -3
  182. package/lib/themes/createWidth.js.map +1 -1
  183. package/lib/themes/index.cjs +14 -0
  184. package/lib/themes/index.cjs.map +1 -1
  185. package/lib/themes/index.d.ts +7 -1
  186. package/lib/themes/index.js +9 -1
  187. package/lib/themes/index.js.map +1 -1
  188. package/metadata.json +1 -1
  189. package/package.json +2 -2
@@ -4,10 +4,8 @@
4
4
  var jsxRuntime = require('react/jsx-runtime');
5
5
  var React = require('react');
6
6
  var ReactDOM = require('react-dom');
7
- var index$1 = require('../../_virtual/index3.cjs');
8
7
  var index = require('./../../vendor/.pnpm/tailwind-variants@0.3.1_tailwindcss@3.4.19_ts-node@10.9.2_@swc_core@1.15.17_@types_node@20.19.35_typescript@5.9.3__/vendor/tailwind-variants/dist/index.cjs');
9
8
  var hooks_useEnhancedEffect = require('../../hooks/useEnhancedEffect.cjs');
10
- var components_VisuallyHiddenText_VisuallyHiddenText = require('../VisuallyHiddenText/VisuallyHiddenText.cjs');
11
9
  var components_Tooltip_TooltipPortal = require('./TooltipPortal.cjs');
12
10
 
13
11
  const subscribeFullscreenChange = (callback) => {
@@ -18,6 +16,7 @@ const subscribeFullscreenChange = (callback) => {
18
16
  };
19
17
  const getFullscreenElement = () => document.fullscreenElement;
20
18
  const getFullscreenElementOnSSR = () => null;
19
+ const FOCUSABLE_SELECTOR = 'a[href], button, input, select, textarea, [tabindex]:not([tabindex="-1"])';
21
20
  const classNameGenerator = index.tv({
22
21
  base: [
23
22
  'smarthr-ui-Tooltip',
@@ -36,21 +35,25 @@ const Tooltip = ({ message, children, type = 'description', triggerType, ellipsi
36
35
  const [isVisible, setIsVisible] = React.useState(false);
37
36
  const [rect, setRect] = React.useState(null);
38
37
  const ref = React.useRef(null);
38
+ const childrenWrapperRef = React.useRef(null);
39
39
  const messageId = React.useId();
40
40
  const fullscreenElement = React.useSyncExternalStore(subscribeFullscreenChange, getFullscreenElement, getFullscreenElementOnSSR);
41
41
  const [isFocusableChild, setIsFocusableChild] = React.useState(false);
42
42
  const [actualTabIndex, setActualTabIndex] = React.useState(tabIndex ?? 0);
43
+ const isLabel = type === 'label';
43
44
  hooks_useEnhancedEffect.useEnhancedEffect(() => {
44
45
  setPortalRoot(fullscreenElement ?? document.body);
45
46
  }, [fullscreenElement]);
46
47
  hooks_useEnhancedEffect.useEnhancedEffect(() => {
47
- const childElement = ref.current?.querySelector(':scope > :not(.smarthr-ui-VisuallyHiddenText)');
48
- const focusable = !!childElement &&
49
- childElement.matches('a[href], button, input, select, textarea, [tabindex]') &&
50
- !childElement.matches('[tabindex="-1"]');
48
+ const childElement = childrenWrapperRef.current?.firstElementChild;
49
+ const focusable = !!childElement && childElement.matches(FOCUSABLE_SELECTOR);
51
50
  setIsFocusableChild(focusable);
52
51
  setActualTabIndex(tabIndex !== undefined ? tabIndex : focusable ? undefined : 0);
53
- }, [tabIndex]);
52
+ // focusableな要素に直接aria属性を設定
53
+ if (focusable) {
54
+ childElement.setAttribute(isLabel ? 'aria-labelledby' : 'aria-describedby', messageId);
55
+ }
56
+ }, [tabIndex, isLabel, messageId]);
54
57
  const toShowAction = React.useCallback((e) => {
55
58
  // Tooltipのtriggerの他の要素(Dropwdown menu buttonで開いたmenu contentとか)に移動されたらtooltipを表示しない
56
59
  if (!ref.current?.contains(e.target)) {
@@ -106,23 +109,11 @@ const Tooltip = ({ message, children, type = 'description', triggerType, ellipsi
106
109
  : toCloseAction, [onBlur, toCloseAction]);
107
110
  const isIcon = triggerType === 'icon';
108
111
  const actualClassName = React.useMemo(() => classNameGenerator({ isIcon, className }), [isIcon, className]);
109
- const isLabel = type === 'label';
110
- const isInnerTarget = isLabel || isFocusableChild || ariaDescribedbyTarget === 'inner';
111
- const childrenWithProps = React.useMemo(() => isLabel
112
- ? React.cloneElement(children, { 'aria-labelledby': messageId })
113
- : isInnerTarget
114
- ? React.cloneElement(children, { 'aria-describedby': messageId })
115
- : children, [children, isLabel, isInnerTarget, messageId]);
116
- const actualWrapperAriaDescribedby = React.useMemo(() => (!isInnerTarget ? messageId : undefined), [isInnerTarget, messageId]);
117
112
  return (
118
113
  // eslint-disable-next-line jsx-a11y/no-static-element-interactions
119
- jsxRuntime.jsxs("span", { ...rest, ref: ref, tabIndex: actualTabIndex, "aria-describedby": actualWrapperAriaDescribedby, onPointerEnter: onDelegatePointerEnter, onTouchStart: onDelegateTouchStart, onFocus: onDelegateFocus, onPointerLeave: onDelegatePointerLeave, onTouchEnd: onDelegateTouchEnd, onBlur: onDelegateBlur, className: actualClassName, children: [portalRoot &&
120
- ReactDOM.createPortal(jsxRuntime.jsx(components_Tooltip_TooltipPortal.TooltipPortal, { message: message, isVisible: isVisible, parentRect: rect, isIcon: isIcon }), portalRoot), childrenWithProps, jsxRuntime.jsx(MemoizedVisuallyHiddenText, { id: messageId, visible: isVisible, children: message })] }));
114
+ jsxRuntime.jsxs("span", { ...rest, ref: ref, tabIndex: actualTabIndex, "aria-describedby": isLabel || isFocusableChild || ariaDescribedbyTarget === 'inner' ? undefined : messageId, onPointerEnter: onDelegatePointerEnter, onTouchStart: onDelegateTouchStart, onFocus: onDelegateFocus, onPointerLeave: onDelegatePointerLeave, onTouchEnd: onDelegateTouchEnd, onBlur: onDelegateBlur, className: actualClassName, children: [portalRoot &&
115
+ ReactDOM.createPortal(jsxRuntime.jsx(components_Tooltip_TooltipPortal.TooltipPortal, { messageId: messageId, message: message, isVisible: isVisible, parentRect: rect, isIcon: isIcon }), portalRoot), jsxRuntime.jsx("span", { ref: childrenWrapperRef, className: "shr-contents", children: children })] }));
121
116
  };
122
- const MemoizedVisuallyHiddenText = React.memo(({ id, visible, children }) => {
123
- const hiddenText = React.useMemo(() => index$1(children), [children]);
124
- return (jsxRuntime.jsx(components_VisuallyHiddenText_VisuallyHiddenText.VisuallyHiddenText, { id: id, "aria-hidden": !visible, children: hiddenText }));
125
- });
126
117
 
127
118
  exports.Tooltip = Tooltip;
128
119
  //# sourceMappingURL=Tooltip.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"Tooltip.cjs","sources":["../../../src/components/Tooltip/Tooltip.tsx"],"sourcesContent":["'use client'\n\nimport {\n type BaseSyntheticEvent,\n type ComponentProps,\n type FC,\n type FocusEvent,\n type PointerEvent,\n type PropsWithChildren,\n type ReactElement,\n type ReactNode,\n type TouchEvent,\n cloneElement,\n memo,\n useCallback,\n useId,\n useMemo,\n useRef,\n useState,\n useSyncExternalStore,\n} from 'react'\nimport { createPortal } from 'react-dom'\nimport innerText from 'react-innertext'\nimport { tv } from 'tailwind-variants'\n\nimport { useEnhancedEffect } from '../../hooks/useEnhancedEffect'\nimport { VisuallyHiddenText } from '../VisuallyHiddenText'\n\nimport { TooltipPortal } from './TooltipPortal'\n\nconst subscribeFullscreenChange = (callback: () => void) => {\n window.addEventListener('fullscreenchange', callback)\n\n return () => {\n window.removeEventListener('fullscreenchange', callback)\n }\n}\nconst getFullscreenElement = () => document.fullscreenElement\nconst getFullscreenElementOnSSR = () => null\n\ntype AbstractProps = PropsWithChildren<{\n /** ツールチップ内に表示するメッセージ */\n message: ReactNode\n /** ツールチップの種類。`label` の場合は children の要素に `aria-labelledby` を付与しアクセシブルネームとして機能する。`description`(デフォルト)の場合は `aria-describedby` を付与し補足説明として機能する */\n type?: 'label' | 'description'\n /** ツールチップを表示する対象のタイプ。アイコンの場合は `icon` を指定する */\n triggerType?: 'icon' | 'text'\n /** `true` のとき、ツールチップを表示する対象が省略されている場合のみツールチップ表示を有効にする */\n ellipsisOnly?: boolean\n /** ツールチップを表示する対象の tabIndex 値 */\n tabIndex?: number\n /** `type` が `description` の場合に `aria-describedby` を付与する対象。children が focusable な場合は常に children に付与されるため無視される */\n ariaDescribedbyTarget?: 'wrapper' | 'inner'\n}>\ntype Props = AbstractProps &\n Omit<ComponentProps<'span'>, keyof AbstractProps | 'aria-describedby' | 'aria-labelledby'>\n\nconst classNameGenerator = tv({\n base: [\n 'smarthr-ui-Tooltip',\n 'shr-relative',\n 'shr-inline-block shr-max-w-full shr-align-bottom',\n 'focus-visible:shr-focus-indicator--outer',\n ],\n variants: {\n isIcon: {\n true: 'shr-leading-[0]',\n },\n },\n})\n\nexport const Tooltip: FC<Props> = ({\n message,\n children,\n type = 'description',\n triggerType,\n ellipsisOnly,\n tabIndex,\n ariaDescribedbyTarget = 'wrapper',\n className,\n onPointerEnter,\n onPointerLeave,\n onTouchStart,\n onTouchEnd,\n onFocus,\n onBlur,\n ...rest\n}) => {\n const [portalRoot, setPortalRoot] = useState<Element | null>(null)\n const [isVisible, setIsVisible] = useState(false)\n const [rect, setRect] = useState<DOMRect | null>(null)\n const ref = useRef<HTMLDivElement>(null)\n const messageId = useId()\n const fullscreenElement = useSyncExternalStore(\n subscribeFullscreenChange,\n getFullscreenElement,\n getFullscreenElementOnSSR,\n )\n\n const [isFocusableChild, setIsFocusableChild] = useState(false)\n const [actualTabIndex, setActualTabIndex] = useState<number | undefined>(tabIndex ?? 0)\n\n useEnhancedEffect(() => {\n setPortalRoot(fullscreenElement ?? document.body)\n }, [fullscreenElement])\n\n useEnhancedEffect(() => {\n const childElement = ref.current?.querySelector<HTMLElement>(\n ':scope > :not(.smarthr-ui-VisuallyHiddenText)',\n )\n\n const focusable =\n !!childElement &&\n childElement.matches('a[href], button, input, select, textarea, [tabindex]') &&\n !childElement.matches('[tabindex=\"-1\"]')\n\n setIsFocusableChild(focusable)\n setActualTabIndex(tabIndex !== undefined ? tabIndex : focusable ? undefined : 0)\n }, [tabIndex])\n\n const toShowAction = useCallback(\n (e: BaseSyntheticEvent) => {\n // Tooltipのtriggerの他の要素(Dropwdown menu buttonで開いたmenu contentとか)に移動されたらtooltipを表示しない\n if (!ref.current?.contains(e.target)) {\n return\n }\n\n if (ellipsisOnly) {\n const outerWidth = parseInt(\n window\n .getComputedStyle(ref.current.parentNode! as HTMLElement, null)\n .width.match(/\\d+/)![0],\n 10,\n )\n\n if (outerWidth < 0 || outerWidth > ref.current.clientWidth) {\n return\n }\n }\n\n setRect(ref.current.getBoundingClientRect())\n setIsVisible(true)\n },\n [ellipsisOnly],\n )\n const onDelegatePointerEnter = useMemo(\n () =>\n onPointerEnter\n ? (e: PointerEvent<HTMLSpanElement>) => {\n onPointerEnter(e)\n toShowAction(e)\n }\n : toShowAction,\n [onPointerEnter, toShowAction],\n )\n const onDelegateTouchStart = useMemo(\n () =>\n onTouchStart\n ? (e: TouchEvent<HTMLSpanElement>) => {\n onTouchStart(e)\n toShowAction(e)\n }\n : toShowAction,\n [onTouchStart, toShowAction],\n )\n const onDelegateFocus = useMemo(\n () =>\n onFocus\n ? (e: FocusEvent<HTMLSpanElement>) => {\n onFocus(e)\n toShowAction(e)\n }\n : toShowAction,\n [onFocus, toShowAction],\n )\n\n const toCloseAction = useCallback(() => setIsVisible(false), [])\n const onDelegatePointerLeave = useMemo(\n () =>\n onPointerLeave\n ? (e: PointerEvent<HTMLSpanElement>) => {\n onPointerLeave(e)\n toCloseAction()\n }\n : toCloseAction,\n [onPointerLeave, toCloseAction],\n )\n const onDelegateTouchEnd = useMemo(\n () =>\n onTouchEnd\n ? (e: TouchEvent<HTMLSpanElement>) => {\n onTouchEnd(e)\n toCloseAction()\n }\n : toCloseAction,\n [onTouchEnd, toCloseAction],\n )\n const onDelegateBlur = useMemo(\n () =>\n onBlur\n ? (e: FocusEvent<HTMLSpanElement>) => {\n onBlur(e)\n toCloseAction()\n }\n : toCloseAction,\n [onBlur, toCloseAction],\n )\n\n const isIcon = triggerType === 'icon'\n const actualClassName = useMemo(\n () => classNameGenerator({ isIcon, className }),\n [isIcon, className],\n )\n const isLabel = type === 'label'\n const isInnerTarget = isLabel || isFocusableChild || ariaDescribedbyTarget === 'inner'\n const childrenWithProps = useMemo(\n () =>\n isLabel\n ? cloneElement(children as ReactElement, { 'aria-labelledby': messageId })\n : isInnerTarget\n ? cloneElement(children as ReactElement, { 'aria-describedby': messageId })\n : children,\n [children, isLabel, isInnerTarget, messageId],\n )\n const actualWrapperAriaDescribedby = useMemo(\n () => (!isInnerTarget ? messageId : undefined),\n [isInnerTarget, messageId],\n )\n\n return (\n // eslint-disable-next-line jsx-a11y/no-static-element-interactions\n <span\n {...rest}\n ref={ref}\n tabIndex={actualTabIndex}\n aria-describedby={actualWrapperAriaDescribedby}\n onPointerEnter={onDelegatePointerEnter}\n onTouchStart={onDelegateTouchStart}\n onFocus={onDelegateFocus}\n onPointerLeave={onDelegatePointerLeave}\n onTouchEnd={onDelegateTouchEnd}\n onBlur={onDelegateBlur}\n className={actualClassName}\n >\n {portalRoot &&\n createPortal(\n <TooltipPortal\n message={message}\n isVisible={isVisible}\n parentRect={rect}\n isIcon={isIcon}\n />,\n portalRoot,\n )}\n {childrenWithProps}\n <MemoizedVisuallyHiddenText id={messageId} visible={isVisible}>\n {message}\n </MemoizedVisuallyHiddenText>\n </span>\n )\n}\n\nconst MemoizedVisuallyHiddenText = memo<PropsWithChildren<{ id: string; visible: boolean }>>(\n ({ id, visible, children }) => {\n const hiddenText = useMemo(() => innerText(children), [children])\n\n return (\n <VisuallyHiddenText id={id} aria-hidden={!visible}>\n {hiddenText}\n </VisuallyHiddenText>\n )\n },\n)\n"],"names":[],"mappings":";;;;;;;;;;;;AA8BA;AACE;AAEA;AACE;AACF;AACF;AACA;AACA;AAmBA;AACE;;;;;AAKC;AACD;AACE;AACE;AACD;AACF;AACF;AAEM;;;;AAoBL;AACA;;;AAQA;;AAGE;AACF;;;AAOE;AAEE;AACA;;;AAIJ;AAEA;;AAGI;;;;AAKE;;;AAOA;;;;;;AAOJ;AAGF;AAGM;;;;;AAON;AAGM;;;;;AAON;AAGM;;;;;AAQN;AACA;AAGM;;AAEI;;;AAKV;AAGM;;AAEI;;;AAKV;AAGM;;AAEI;;;AAMV;;AAKA;;AAEA;;AAIM;;AAEE;;;;AAUN;AAcI;AAeR;AAEA;AAEI;AAEA;AAKF;;"}
1
+ {"version":3,"file":"Tooltip.cjs","sources":["../../../src/components/Tooltip/Tooltip.tsx"],"sourcesContent":["'use client'\n\nimport {\n type BaseSyntheticEvent,\n type ComponentProps,\n type FC,\n type FocusEvent,\n type PointerEvent,\n type PropsWithChildren,\n type ReactNode,\n type TouchEvent,\n useCallback,\n useId,\n useMemo,\n useRef,\n useState,\n useSyncExternalStore,\n} from 'react'\nimport { createPortal } from 'react-dom'\nimport { tv } from 'tailwind-variants'\n\nimport { useEnhancedEffect } from '../../hooks/useEnhancedEffect'\n\nimport { TooltipPortal } from './TooltipPortal'\n\nconst subscribeFullscreenChange = (callback: () => void) => {\n window.addEventListener('fullscreenchange', callback)\n\n return () => {\n window.removeEventListener('fullscreenchange', callback)\n }\n}\nconst getFullscreenElement = () => document.fullscreenElement\nconst getFullscreenElementOnSSR = () => null\n\nconst FOCUSABLE_SELECTOR =\n 'a[href], button, input, select, textarea, [tabindex]:not([tabindex=\"-1\"])'\n\ntype AbstractProps = PropsWithChildren<{\n /** ツールチップ内に表示するメッセージ */\n message: ReactNode\n /** ツールチップの種類。`label` の場合は children の要素に `aria-labelledby` を付与しアクセシブルネームとして機能する。`description`(デフォルト)の場合は `aria-describedby` を付与し補足説明として機能する */\n type?: 'label' | 'description'\n /** ツールチップを表示する対象のタイプ。アイコンの場合は `icon` を指定する */\n triggerType?: 'icon' | 'text'\n /** `true` のとき、ツールチップを表示する対象が省略されている場合のみツールチップ表示を有効にする */\n ellipsisOnly?: boolean\n /** ツールチップを表示する対象の tabIndex 値 */\n tabIndex?: number\n /** `type` が `description` の場合に `aria-describedby` を付与する対象。children が focusable な場合は常に children に付与されるため無視される */\n ariaDescribedbyTarget?: 'wrapper' | 'inner'\n}>\ntype Props = AbstractProps &\n Omit<ComponentProps<'span'>, keyof AbstractProps | 'aria-describedby' | 'aria-labelledby'>\n\nconst classNameGenerator = tv({\n base: [\n 'smarthr-ui-Tooltip',\n 'shr-relative',\n 'shr-inline-block shr-max-w-full shr-align-bottom',\n 'focus-visible:shr-focus-indicator--outer',\n ],\n variants: {\n isIcon: {\n true: 'shr-leading-[0]',\n },\n },\n})\n\nexport const Tooltip: FC<Props> = ({\n message,\n children,\n type = 'description',\n triggerType,\n ellipsisOnly,\n tabIndex,\n ariaDescribedbyTarget = 'wrapper',\n className,\n onPointerEnter,\n onPointerLeave,\n onTouchStart,\n onTouchEnd,\n onFocus,\n onBlur,\n ...rest\n}) => {\n const [portalRoot, setPortalRoot] = useState<Element | null>(null)\n const [isVisible, setIsVisible] = useState(false)\n const [rect, setRect] = useState<DOMRect | null>(null)\n const ref = useRef<HTMLDivElement>(null)\n const childrenWrapperRef = useRef<HTMLSpanElement>(null)\n const messageId = useId()\n const fullscreenElement = useSyncExternalStore(\n subscribeFullscreenChange,\n getFullscreenElement,\n getFullscreenElementOnSSR,\n )\n\n const [isFocusableChild, setIsFocusableChild] = useState(false)\n const [actualTabIndex, setActualTabIndex] = useState<number | undefined>(tabIndex ?? 0)\n\n const isLabel = type === 'label'\n\n useEnhancedEffect(() => {\n setPortalRoot(fullscreenElement ?? document.body)\n }, [fullscreenElement])\n\n useEnhancedEffect(() => {\n const childElement = childrenWrapperRef.current?.firstElementChild as HTMLElement | undefined\n\n const focusable = !!childElement && childElement.matches(FOCUSABLE_SELECTOR)\n\n setIsFocusableChild(focusable)\n setActualTabIndex(tabIndex !== undefined ? tabIndex : focusable ? undefined : 0)\n\n // focusableな要素に直接aria属性を設定\n if (focusable) {\n childElement.setAttribute(isLabel ? 'aria-labelledby' : 'aria-describedby', messageId)\n }\n }, [tabIndex, isLabel, messageId])\n\n const toShowAction = useCallback(\n (e: BaseSyntheticEvent) => {\n // Tooltipのtriggerの他の要素(Dropwdown menu buttonで開いたmenu contentとか)に移動されたらtooltipを表示しない\n if (!ref.current?.contains(e.target)) {\n return\n }\n\n if (ellipsisOnly) {\n const outerWidth = parseInt(\n window\n .getComputedStyle(ref.current.parentNode! as HTMLElement, null)\n .width.match(/\\d+/)![0],\n 10,\n )\n\n if (outerWidth < 0 || outerWidth > ref.current.clientWidth) {\n return\n }\n }\n\n setRect(ref.current.getBoundingClientRect())\n setIsVisible(true)\n },\n [ellipsisOnly],\n )\n const onDelegatePointerEnter = useMemo(\n () =>\n onPointerEnter\n ? (e: PointerEvent<HTMLSpanElement>) => {\n onPointerEnter(e)\n toShowAction(e)\n }\n : toShowAction,\n [onPointerEnter, toShowAction],\n )\n const onDelegateTouchStart = useMemo(\n () =>\n onTouchStart\n ? (e: TouchEvent<HTMLSpanElement>) => {\n onTouchStart(e)\n toShowAction(e)\n }\n : toShowAction,\n [onTouchStart, toShowAction],\n )\n const onDelegateFocus = useMemo(\n () =>\n onFocus\n ? (e: FocusEvent<HTMLSpanElement>) => {\n onFocus(e)\n toShowAction(e)\n }\n : toShowAction,\n [onFocus, toShowAction],\n )\n\n const toCloseAction = useCallback(() => setIsVisible(false), [])\n const onDelegatePointerLeave = useMemo(\n () =>\n onPointerLeave\n ? (e: PointerEvent<HTMLSpanElement>) => {\n onPointerLeave(e)\n toCloseAction()\n }\n : toCloseAction,\n [onPointerLeave, toCloseAction],\n )\n const onDelegateTouchEnd = useMemo(\n () =>\n onTouchEnd\n ? (e: TouchEvent<HTMLSpanElement>) => {\n onTouchEnd(e)\n toCloseAction()\n }\n : toCloseAction,\n [onTouchEnd, toCloseAction],\n )\n const onDelegateBlur = useMemo(\n () =>\n onBlur\n ? (e: FocusEvent<HTMLSpanElement>) => {\n onBlur(e)\n toCloseAction()\n }\n : toCloseAction,\n [onBlur, toCloseAction],\n )\n\n const isIcon = triggerType === 'icon'\n const actualClassName = useMemo(\n () => classNameGenerator({ isIcon, className }),\n [isIcon, className],\n )\n\n return (\n // eslint-disable-next-line jsx-a11y/no-static-element-interactions\n <span\n {...rest}\n ref={ref}\n tabIndex={actualTabIndex}\n aria-describedby={\n isLabel || isFocusableChild || ariaDescribedbyTarget === 'inner' ? undefined : messageId\n }\n onPointerEnter={onDelegatePointerEnter}\n onTouchStart={onDelegateTouchStart}\n onFocus={onDelegateFocus}\n onPointerLeave={onDelegatePointerLeave}\n onTouchEnd={onDelegateTouchEnd}\n onBlur={onDelegateBlur}\n className={actualClassName}\n >\n {portalRoot &&\n createPortal(\n <TooltipPortal\n messageId={messageId}\n message={message}\n isVisible={isVisible}\n parentRect={rect}\n isIcon={isIcon}\n />,\n portalRoot,\n )}\n <span ref={childrenWrapperRef} className=\"shr-contents\">\n {children}\n </span>\n </span>\n )\n}\n"],"names":[],"mappings":";;;;;;;;;;AAyBA;AACE;AAEA;AACE;AACF;AACF;AACA;AACA;AAEA;AAoBA;AACE;;;;;AAKC;AACD;AACE;AACE;AACD;AACF;AACF;AAEM;;;;AAoBL;AACA;AACA;;;AAQA;AAEA;;AAGE;AACF;;AAGE;AAEA;;;;;AAOE;;;AAIJ;;AAGI;;;;AAKE;;;AAOA;;;;;;AAOJ;AAGF;AAGM;;;;;AAON;AAGM;;;;;AAON;AAGM;;;;;AAQN;AACA;AAGM;;AAEI;;;AAKV;AAGM;;AAEI;;;AAKV;AAGM;;AAEI;;;AAMV;;;;;AAwBM;AAeR;;"}
@@ -1,11 +1,9 @@
1
1
  "use client";
2
- import { jsx, jsxs } from 'react/jsx-runtime';
3
- import { memo, useMemo, useState, useRef, useId, useSyncExternalStore, useCallback, cloneElement } from 'react';
2
+ import { jsxs, jsx } from 'react/jsx-runtime';
3
+ import { useState, useRef, useId, useSyncExternalStore, useCallback, useMemo } from 'react';
4
4
  import { createPortal } from 'react-dom';
5
- import innerText from '../../_virtual/index3.js';
6
5
  import { tv as ce } from './../../vendor/.pnpm/tailwind-variants@0.3.1_tailwindcss@3.4.19_ts-node@10.9.2_@swc_core@1.15.17_@types_node@20.19.35_typescript@5.9.3__/vendor/tailwind-variants/dist/index.js';
7
6
  import { useEnhancedEffect } from '../../hooks/useEnhancedEffect.js';
8
- import { VisuallyHiddenText } from '../VisuallyHiddenText/VisuallyHiddenText.js';
9
7
  import { TooltipPortal } from './TooltipPortal.js';
10
8
 
11
9
  const subscribeFullscreenChange = (callback) => {
@@ -16,6 +14,7 @@ const subscribeFullscreenChange = (callback) => {
16
14
  };
17
15
  const getFullscreenElement = () => document.fullscreenElement;
18
16
  const getFullscreenElementOnSSR = () => null;
17
+ const FOCUSABLE_SELECTOR = 'a[href], button, input, select, textarea, [tabindex]:not([tabindex="-1"])';
19
18
  const classNameGenerator = ce({
20
19
  base: [
21
20
  'smarthr-ui-Tooltip',
@@ -34,21 +33,25 @@ const Tooltip = ({ message, children, type = 'description', triggerType, ellipsi
34
33
  const [isVisible, setIsVisible] = useState(false);
35
34
  const [rect, setRect] = useState(null);
36
35
  const ref = useRef(null);
36
+ const childrenWrapperRef = useRef(null);
37
37
  const messageId = useId();
38
38
  const fullscreenElement = useSyncExternalStore(subscribeFullscreenChange, getFullscreenElement, getFullscreenElementOnSSR);
39
39
  const [isFocusableChild, setIsFocusableChild] = useState(false);
40
40
  const [actualTabIndex, setActualTabIndex] = useState(tabIndex ?? 0);
41
+ const isLabel = type === 'label';
41
42
  useEnhancedEffect(() => {
42
43
  setPortalRoot(fullscreenElement ?? document.body);
43
44
  }, [fullscreenElement]);
44
45
  useEnhancedEffect(() => {
45
- const childElement = ref.current?.querySelector(':scope > :not(.smarthr-ui-VisuallyHiddenText)');
46
- const focusable = !!childElement &&
47
- childElement.matches('a[href], button, input, select, textarea, [tabindex]') &&
48
- !childElement.matches('[tabindex="-1"]');
46
+ const childElement = childrenWrapperRef.current?.firstElementChild;
47
+ const focusable = !!childElement && childElement.matches(FOCUSABLE_SELECTOR);
49
48
  setIsFocusableChild(focusable);
50
49
  setActualTabIndex(tabIndex !== undefined ? tabIndex : focusable ? undefined : 0);
51
- }, [tabIndex]);
50
+ // focusableな要素に直接aria属性を設定
51
+ if (focusable) {
52
+ childElement.setAttribute(isLabel ? 'aria-labelledby' : 'aria-describedby', messageId);
53
+ }
54
+ }, [tabIndex, isLabel, messageId]);
52
55
  const toShowAction = useCallback((e) => {
53
56
  // Tooltipのtriggerの他の要素(Dropwdown menu buttonで開いたmenu contentとか)に移動されたらtooltipを表示しない
54
57
  if (!ref.current?.contains(e.target)) {
@@ -104,23 +107,11 @@ const Tooltip = ({ message, children, type = 'description', triggerType, ellipsi
104
107
  : toCloseAction, [onBlur, toCloseAction]);
105
108
  const isIcon = triggerType === 'icon';
106
109
  const actualClassName = useMemo(() => classNameGenerator({ isIcon, className }), [isIcon, className]);
107
- const isLabel = type === 'label';
108
- const isInnerTarget = isLabel || isFocusableChild || ariaDescribedbyTarget === 'inner';
109
- const childrenWithProps = useMemo(() => isLabel
110
- ? cloneElement(children, { 'aria-labelledby': messageId })
111
- : isInnerTarget
112
- ? cloneElement(children, { 'aria-describedby': messageId })
113
- : children, [children, isLabel, isInnerTarget, messageId]);
114
- const actualWrapperAriaDescribedby = useMemo(() => (!isInnerTarget ? messageId : undefined), [isInnerTarget, messageId]);
115
110
  return (
116
111
  // eslint-disable-next-line jsx-a11y/no-static-element-interactions
117
- jsxs("span", { ...rest, ref: ref, tabIndex: actualTabIndex, "aria-describedby": actualWrapperAriaDescribedby, onPointerEnter: onDelegatePointerEnter, onTouchStart: onDelegateTouchStart, onFocus: onDelegateFocus, onPointerLeave: onDelegatePointerLeave, onTouchEnd: onDelegateTouchEnd, onBlur: onDelegateBlur, className: actualClassName, children: [portalRoot &&
118
- createPortal(jsx(TooltipPortal, { message: message, isVisible: isVisible, parentRect: rect, isIcon: isIcon }), portalRoot), childrenWithProps, jsx(MemoizedVisuallyHiddenText, { id: messageId, visible: isVisible, children: message })] }));
112
+ jsxs("span", { ...rest, ref: ref, tabIndex: actualTabIndex, "aria-describedby": isLabel || isFocusableChild || ariaDescribedbyTarget === 'inner' ? undefined : messageId, onPointerEnter: onDelegatePointerEnter, onTouchStart: onDelegateTouchStart, onFocus: onDelegateFocus, onPointerLeave: onDelegatePointerLeave, onTouchEnd: onDelegateTouchEnd, onBlur: onDelegateBlur, className: actualClassName, children: [portalRoot &&
113
+ createPortal(jsx(TooltipPortal, { messageId: messageId, message: message, isVisible: isVisible, parentRect: rect, isIcon: isIcon }), portalRoot), jsx("span", { ref: childrenWrapperRef, className: "shr-contents", children: children })] }));
119
114
  };
120
- const MemoizedVisuallyHiddenText = memo(({ id, visible, children }) => {
121
- const hiddenText = useMemo(() => innerText(children), [children]);
122
- return (jsx(VisuallyHiddenText, { id: id, "aria-hidden": !visible, children: hiddenText }));
123
- });
124
115
 
125
116
  export { Tooltip };
126
117
  //# sourceMappingURL=Tooltip.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Tooltip.js","sources":["../../../src/components/Tooltip/Tooltip.tsx"],"sourcesContent":["'use client'\n\nimport {\n type BaseSyntheticEvent,\n type ComponentProps,\n type FC,\n type FocusEvent,\n type PointerEvent,\n type PropsWithChildren,\n type ReactElement,\n type ReactNode,\n type TouchEvent,\n cloneElement,\n memo,\n useCallback,\n useId,\n useMemo,\n useRef,\n useState,\n useSyncExternalStore,\n} from 'react'\nimport { createPortal } from 'react-dom'\nimport innerText from 'react-innertext'\nimport { tv } from 'tailwind-variants'\n\nimport { useEnhancedEffect } from '../../hooks/useEnhancedEffect'\nimport { VisuallyHiddenText } from '../VisuallyHiddenText'\n\nimport { TooltipPortal } from './TooltipPortal'\n\nconst subscribeFullscreenChange = (callback: () => void) => {\n window.addEventListener('fullscreenchange', callback)\n\n return () => {\n window.removeEventListener('fullscreenchange', callback)\n }\n}\nconst getFullscreenElement = () => document.fullscreenElement\nconst getFullscreenElementOnSSR = () => null\n\ntype AbstractProps = PropsWithChildren<{\n /** ツールチップ内に表示するメッセージ */\n message: ReactNode\n /** ツールチップの種類。`label` の場合は children の要素に `aria-labelledby` を付与しアクセシブルネームとして機能する。`description`(デフォルト)の場合は `aria-describedby` を付与し補足説明として機能する */\n type?: 'label' | 'description'\n /** ツールチップを表示する対象のタイプ。アイコンの場合は `icon` を指定する */\n triggerType?: 'icon' | 'text'\n /** `true` のとき、ツールチップを表示する対象が省略されている場合のみツールチップ表示を有効にする */\n ellipsisOnly?: boolean\n /** ツールチップを表示する対象の tabIndex 値 */\n tabIndex?: number\n /** `type` が `description` の場合に `aria-describedby` を付与する対象。children が focusable な場合は常に children に付与されるため無視される */\n ariaDescribedbyTarget?: 'wrapper' | 'inner'\n}>\ntype Props = AbstractProps &\n Omit<ComponentProps<'span'>, keyof AbstractProps | 'aria-describedby' | 'aria-labelledby'>\n\nconst classNameGenerator = tv({\n base: [\n 'smarthr-ui-Tooltip',\n 'shr-relative',\n 'shr-inline-block shr-max-w-full shr-align-bottom',\n 'focus-visible:shr-focus-indicator--outer',\n ],\n variants: {\n isIcon: {\n true: 'shr-leading-[0]',\n },\n },\n})\n\nexport const Tooltip: FC<Props> = ({\n message,\n children,\n type = 'description',\n triggerType,\n ellipsisOnly,\n tabIndex,\n ariaDescribedbyTarget = 'wrapper',\n className,\n onPointerEnter,\n onPointerLeave,\n onTouchStart,\n onTouchEnd,\n onFocus,\n onBlur,\n ...rest\n}) => {\n const [portalRoot, setPortalRoot] = useState<Element | null>(null)\n const [isVisible, setIsVisible] = useState(false)\n const [rect, setRect] = useState<DOMRect | null>(null)\n const ref = useRef<HTMLDivElement>(null)\n const messageId = useId()\n const fullscreenElement = useSyncExternalStore(\n subscribeFullscreenChange,\n getFullscreenElement,\n getFullscreenElementOnSSR,\n )\n\n const [isFocusableChild, setIsFocusableChild] = useState(false)\n const [actualTabIndex, setActualTabIndex] = useState<number | undefined>(tabIndex ?? 0)\n\n useEnhancedEffect(() => {\n setPortalRoot(fullscreenElement ?? document.body)\n }, [fullscreenElement])\n\n useEnhancedEffect(() => {\n const childElement = ref.current?.querySelector<HTMLElement>(\n ':scope > :not(.smarthr-ui-VisuallyHiddenText)',\n )\n\n const focusable =\n !!childElement &&\n childElement.matches('a[href], button, input, select, textarea, [tabindex]') &&\n !childElement.matches('[tabindex=\"-1\"]')\n\n setIsFocusableChild(focusable)\n setActualTabIndex(tabIndex !== undefined ? tabIndex : focusable ? undefined : 0)\n }, [tabIndex])\n\n const toShowAction = useCallback(\n (e: BaseSyntheticEvent) => {\n // Tooltipのtriggerの他の要素(Dropwdown menu buttonで開いたmenu contentとか)に移動されたらtooltipを表示しない\n if (!ref.current?.contains(e.target)) {\n return\n }\n\n if (ellipsisOnly) {\n const outerWidth = parseInt(\n window\n .getComputedStyle(ref.current.parentNode! as HTMLElement, null)\n .width.match(/\\d+/)![0],\n 10,\n )\n\n if (outerWidth < 0 || outerWidth > ref.current.clientWidth) {\n return\n }\n }\n\n setRect(ref.current.getBoundingClientRect())\n setIsVisible(true)\n },\n [ellipsisOnly],\n )\n const onDelegatePointerEnter = useMemo(\n () =>\n onPointerEnter\n ? (e: PointerEvent<HTMLSpanElement>) => {\n onPointerEnter(e)\n toShowAction(e)\n }\n : toShowAction,\n [onPointerEnter, toShowAction],\n )\n const onDelegateTouchStart = useMemo(\n () =>\n onTouchStart\n ? (e: TouchEvent<HTMLSpanElement>) => {\n onTouchStart(e)\n toShowAction(e)\n }\n : toShowAction,\n [onTouchStart, toShowAction],\n )\n const onDelegateFocus = useMemo(\n () =>\n onFocus\n ? (e: FocusEvent<HTMLSpanElement>) => {\n onFocus(e)\n toShowAction(e)\n }\n : toShowAction,\n [onFocus, toShowAction],\n )\n\n const toCloseAction = useCallback(() => setIsVisible(false), [])\n const onDelegatePointerLeave = useMemo(\n () =>\n onPointerLeave\n ? (e: PointerEvent<HTMLSpanElement>) => {\n onPointerLeave(e)\n toCloseAction()\n }\n : toCloseAction,\n [onPointerLeave, toCloseAction],\n )\n const onDelegateTouchEnd = useMemo(\n () =>\n onTouchEnd\n ? (e: TouchEvent<HTMLSpanElement>) => {\n onTouchEnd(e)\n toCloseAction()\n }\n : toCloseAction,\n [onTouchEnd, toCloseAction],\n )\n const onDelegateBlur = useMemo(\n () =>\n onBlur\n ? (e: FocusEvent<HTMLSpanElement>) => {\n onBlur(e)\n toCloseAction()\n }\n : toCloseAction,\n [onBlur, toCloseAction],\n )\n\n const isIcon = triggerType === 'icon'\n const actualClassName = useMemo(\n () => classNameGenerator({ isIcon, className }),\n [isIcon, className],\n )\n const isLabel = type === 'label'\n const isInnerTarget = isLabel || isFocusableChild || ariaDescribedbyTarget === 'inner'\n const childrenWithProps = useMemo(\n () =>\n isLabel\n ? cloneElement(children as ReactElement, { 'aria-labelledby': messageId })\n : isInnerTarget\n ? cloneElement(children as ReactElement, { 'aria-describedby': messageId })\n : children,\n [children, isLabel, isInnerTarget, messageId],\n )\n const actualWrapperAriaDescribedby = useMemo(\n () => (!isInnerTarget ? messageId : undefined),\n [isInnerTarget, messageId],\n )\n\n return (\n // eslint-disable-next-line jsx-a11y/no-static-element-interactions\n <span\n {...rest}\n ref={ref}\n tabIndex={actualTabIndex}\n aria-describedby={actualWrapperAriaDescribedby}\n onPointerEnter={onDelegatePointerEnter}\n onTouchStart={onDelegateTouchStart}\n onFocus={onDelegateFocus}\n onPointerLeave={onDelegatePointerLeave}\n onTouchEnd={onDelegateTouchEnd}\n onBlur={onDelegateBlur}\n className={actualClassName}\n >\n {portalRoot &&\n createPortal(\n <TooltipPortal\n message={message}\n isVisible={isVisible}\n parentRect={rect}\n isIcon={isIcon}\n />,\n portalRoot,\n )}\n {childrenWithProps}\n <MemoizedVisuallyHiddenText id={messageId} visible={isVisible}>\n {message}\n </MemoizedVisuallyHiddenText>\n </span>\n )\n}\n\nconst MemoizedVisuallyHiddenText = memo<PropsWithChildren<{ id: string; visible: boolean }>>(\n ({ id, visible, children }) => {\n const hiddenText = useMemo(() => innerText(children), [children])\n\n return (\n <VisuallyHiddenText id={id} aria-hidden={!visible}>\n {hiddenText}\n </VisuallyHiddenText>\n )\n },\n)\n"],"names":[],"mappings":";;;;;;;;;;AA8BA;AACE;AAEA;AACE;AACF;AACF;AACA;AACA;AAmBA;AACE;;;;;AAKC;AACD;AACE;AACE;AACD;AACF;AACF;AAEM;;;;AAoBL;AACA;;;AAQA;;AAGE;AACF;;;AAOE;AAEE;AACA;;;AAIJ;AAEA;;AAGI;;;;AAKE;;;AAOA;;;;;;AAOJ;AAGF;AAGM;;;;;AAON;AAGM;;;;;AAON;AAGM;;;;;AAQN;AACA;AAGM;;AAEI;;;AAKV;AAGM;;AAEI;;;AAKV;AAGM;;AAEI;;;AAMV;;AAKA;;AAEA;;AAIM;;AAEE;;;;AAUN;AAcI;AAeR;AAEA;AAEI;AAEA;AAKF;;"}
1
+ {"version":3,"file":"Tooltip.js","sources":["../../../src/components/Tooltip/Tooltip.tsx"],"sourcesContent":["'use client'\n\nimport {\n type BaseSyntheticEvent,\n type ComponentProps,\n type FC,\n type FocusEvent,\n type PointerEvent,\n type PropsWithChildren,\n type ReactNode,\n type TouchEvent,\n useCallback,\n useId,\n useMemo,\n useRef,\n useState,\n useSyncExternalStore,\n} from 'react'\nimport { createPortal } from 'react-dom'\nimport { tv } from 'tailwind-variants'\n\nimport { useEnhancedEffect } from '../../hooks/useEnhancedEffect'\n\nimport { TooltipPortal } from './TooltipPortal'\n\nconst subscribeFullscreenChange = (callback: () => void) => {\n window.addEventListener('fullscreenchange', callback)\n\n return () => {\n window.removeEventListener('fullscreenchange', callback)\n }\n}\nconst getFullscreenElement = () => document.fullscreenElement\nconst getFullscreenElementOnSSR = () => null\n\nconst FOCUSABLE_SELECTOR =\n 'a[href], button, input, select, textarea, [tabindex]:not([tabindex=\"-1\"])'\n\ntype AbstractProps = PropsWithChildren<{\n /** ツールチップ内に表示するメッセージ */\n message: ReactNode\n /** ツールチップの種類。`label` の場合は children の要素に `aria-labelledby` を付与しアクセシブルネームとして機能する。`description`(デフォルト)の場合は `aria-describedby` を付与し補足説明として機能する */\n type?: 'label' | 'description'\n /** ツールチップを表示する対象のタイプ。アイコンの場合は `icon` を指定する */\n triggerType?: 'icon' | 'text'\n /** `true` のとき、ツールチップを表示する対象が省略されている場合のみツールチップ表示を有効にする */\n ellipsisOnly?: boolean\n /** ツールチップを表示する対象の tabIndex 値 */\n tabIndex?: number\n /** `type` が `description` の場合に `aria-describedby` を付与する対象。children が focusable な場合は常に children に付与されるため無視される */\n ariaDescribedbyTarget?: 'wrapper' | 'inner'\n}>\ntype Props = AbstractProps &\n Omit<ComponentProps<'span'>, keyof AbstractProps | 'aria-describedby' | 'aria-labelledby'>\n\nconst classNameGenerator = tv({\n base: [\n 'smarthr-ui-Tooltip',\n 'shr-relative',\n 'shr-inline-block shr-max-w-full shr-align-bottom',\n 'focus-visible:shr-focus-indicator--outer',\n ],\n variants: {\n isIcon: {\n true: 'shr-leading-[0]',\n },\n },\n})\n\nexport const Tooltip: FC<Props> = ({\n message,\n children,\n type = 'description',\n triggerType,\n ellipsisOnly,\n tabIndex,\n ariaDescribedbyTarget = 'wrapper',\n className,\n onPointerEnter,\n onPointerLeave,\n onTouchStart,\n onTouchEnd,\n onFocus,\n onBlur,\n ...rest\n}) => {\n const [portalRoot, setPortalRoot] = useState<Element | null>(null)\n const [isVisible, setIsVisible] = useState(false)\n const [rect, setRect] = useState<DOMRect | null>(null)\n const ref = useRef<HTMLDivElement>(null)\n const childrenWrapperRef = useRef<HTMLSpanElement>(null)\n const messageId = useId()\n const fullscreenElement = useSyncExternalStore(\n subscribeFullscreenChange,\n getFullscreenElement,\n getFullscreenElementOnSSR,\n )\n\n const [isFocusableChild, setIsFocusableChild] = useState(false)\n const [actualTabIndex, setActualTabIndex] = useState<number | undefined>(tabIndex ?? 0)\n\n const isLabel = type === 'label'\n\n useEnhancedEffect(() => {\n setPortalRoot(fullscreenElement ?? document.body)\n }, [fullscreenElement])\n\n useEnhancedEffect(() => {\n const childElement = childrenWrapperRef.current?.firstElementChild as HTMLElement | undefined\n\n const focusable = !!childElement && childElement.matches(FOCUSABLE_SELECTOR)\n\n setIsFocusableChild(focusable)\n setActualTabIndex(tabIndex !== undefined ? tabIndex : focusable ? undefined : 0)\n\n // focusableな要素に直接aria属性を設定\n if (focusable) {\n childElement.setAttribute(isLabel ? 'aria-labelledby' : 'aria-describedby', messageId)\n }\n }, [tabIndex, isLabel, messageId])\n\n const toShowAction = useCallback(\n (e: BaseSyntheticEvent) => {\n // Tooltipのtriggerの他の要素(Dropwdown menu buttonで開いたmenu contentとか)に移動されたらtooltipを表示しない\n if (!ref.current?.contains(e.target)) {\n return\n }\n\n if (ellipsisOnly) {\n const outerWidth = parseInt(\n window\n .getComputedStyle(ref.current.parentNode! as HTMLElement, null)\n .width.match(/\\d+/)![0],\n 10,\n )\n\n if (outerWidth < 0 || outerWidth > ref.current.clientWidth) {\n return\n }\n }\n\n setRect(ref.current.getBoundingClientRect())\n setIsVisible(true)\n },\n [ellipsisOnly],\n )\n const onDelegatePointerEnter = useMemo(\n () =>\n onPointerEnter\n ? (e: PointerEvent<HTMLSpanElement>) => {\n onPointerEnter(e)\n toShowAction(e)\n }\n : toShowAction,\n [onPointerEnter, toShowAction],\n )\n const onDelegateTouchStart = useMemo(\n () =>\n onTouchStart\n ? (e: TouchEvent<HTMLSpanElement>) => {\n onTouchStart(e)\n toShowAction(e)\n }\n : toShowAction,\n [onTouchStart, toShowAction],\n )\n const onDelegateFocus = useMemo(\n () =>\n onFocus\n ? (e: FocusEvent<HTMLSpanElement>) => {\n onFocus(e)\n toShowAction(e)\n }\n : toShowAction,\n [onFocus, toShowAction],\n )\n\n const toCloseAction = useCallback(() => setIsVisible(false), [])\n const onDelegatePointerLeave = useMemo(\n () =>\n onPointerLeave\n ? (e: PointerEvent<HTMLSpanElement>) => {\n onPointerLeave(e)\n toCloseAction()\n }\n : toCloseAction,\n [onPointerLeave, toCloseAction],\n )\n const onDelegateTouchEnd = useMemo(\n () =>\n onTouchEnd\n ? (e: TouchEvent<HTMLSpanElement>) => {\n onTouchEnd(e)\n toCloseAction()\n }\n : toCloseAction,\n [onTouchEnd, toCloseAction],\n )\n const onDelegateBlur = useMemo(\n () =>\n onBlur\n ? (e: FocusEvent<HTMLSpanElement>) => {\n onBlur(e)\n toCloseAction()\n }\n : toCloseAction,\n [onBlur, toCloseAction],\n )\n\n const isIcon = triggerType === 'icon'\n const actualClassName = useMemo(\n () => classNameGenerator({ isIcon, className }),\n [isIcon, className],\n )\n\n return (\n // eslint-disable-next-line jsx-a11y/no-static-element-interactions\n <span\n {...rest}\n ref={ref}\n tabIndex={actualTabIndex}\n aria-describedby={\n isLabel || isFocusableChild || ariaDescribedbyTarget === 'inner' ? undefined : messageId\n }\n onPointerEnter={onDelegatePointerEnter}\n onTouchStart={onDelegateTouchStart}\n onFocus={onDelegateFocus}\n onPointerLeave={onDelegatePointerLeave}\n onTouchEnd={onDelegateTouchEnd}\n onBlur={onDelegateBlur}\n className={actualClassName}\n >\n {portalRoot &&\n createPortal(\n <TooltipPortal\n messageId={messageId}\n message={message}\n isVisible={isVisible}\n parentRect={rect}\n isIcon={isIcon}\n />,\n portalRoot,\n )}\n <span ref={childrenWrapperRef} className=\"shr-contents\">\n {children}\n </span>\n </span>\n )\n}\n"],"names":[],"mappings":";;;;;;;;AAyBA;AACE;AAEA;AACE;AACF;AACF;AACA;AACA;AAEA;AAoBA;AACE;;;;;AAKC;AACD;AACE;AACE;AACD;AACF;AACF;AAEM;;;;AAoBL;AACA;AACA;;;AAQA;AAEA;;AAGE;AACF;;AAGE;AAEA;;;;;AAOE;;;AAIJ;;AAGI;;;;AAKE;;;AAOA;;;;;;AAOJ;AAGF;AAGM;;;;;AAON;AAGM;;;;;AAON;AAGM;;;;;AAQN;AACA;AAGM;;AAEI;;;AAKV;AAGM;;AAEI;;;AAKV;AAGM;;AAEI;;;AAMV;;;;;AAwBM;AAeR;;"}
@@ -17,7 +17,7 @@ const classNameGenerator = index.tv({
17
17
  });
18
18
  const OUTER_MARGIN = 10;
19
19
  const SPACING = 5;
20
- const TooltipPortal = ({ message, isVisible, parentRect, isIcon }) => {
20
+ const TooltipPortal = ({ messageId, message, isVisible, parentRect, isIcon }) => {
21
21
  const theme = hooks_useTheme.useTheme();
22
22
  const portalRef = React.useRef(null);
23
23
  const [style, setStyle] = React.useState({});
@@ -56,7 +56,7 @@ const TooltipPortal = ({ message, isVisible, parentRect, isIcon }) => {
56
56
  balloonText: balloonText(),
57
57
  };
58
58
  }, []);
59
- return (jsxRuntime.jsx("div", { ref: portalRef, role: "tooltip", "aria-hidden": !isVisible, className: classNames.container, style: style, children: jsxRuntime.jsx(components_Tooltip_ControlledTooltip.ControlledTooltip, { horizontal: actualHorizontal, vertical: actualVertical, triggerIcon: isIcon, className: classNames.balloon, children: jsxRuntime.jsx("div", { className: classNames.balloonText, children: message }) }) }));
59
+ return (jsxRuntime.jsx("div", { ref: portalRef, role: "tooltip", "aria-hidden": !isVisible, className: classNames.container, style: style, children: jsxRuntime.jsx(components_Tooltip_ControlledTooltip.ControlledTooltip, { horizontal: actualHorizontal, vertical: actualVertical, triggerIcon: isIcon, className: classNames.balloon, children: jsxRuntime.jsx("div", { id: messageId, className: classNames.balloonText, children: message }) }) }));
60
60
  };
61
61
  const calculateVertical = (portalHeight, parentRect) => {
62
62
  // トリガの上側の領域に収まる場合
@@ -1 +1 @@
1
- {"version":3,"file":"TooltipPortal.cjs","sources":["../../../src/components/Tooltip/TooltipPortal.tsx"],"sourcesContent":["'use client'\n\nimport { type FC, type ReactNode, useEffect, useMemo, useRef, useState } from 'react'\nimport { tv } from 'tailwind-variants'\n\nimport { useTheme } from '../../hooks/useTheme'\nimport { debounce } from '../../libs/debounce'\n\nimport { ControlledTooltip } from './ControlledTooltip'\n\ntype Props = {\n message: ReactNode\n isVisible: boolean\n parentRect: DOMRect | null\n isIcon?: boolean\n}\n\nconst classNameGenerator = tv({\n slots: {\n container: 'smarthr-ui-Tooltip-popup shr-absolute shr-z-overlap aria-hidden:shr-hidden',\n balloon: 'shr-max-w-full [&&&]:shr-whitespace-normal',\n balloonText: 'shr-m-0 shr-px-1 shr-py-0.5',\n },\n})\n\nconst OUTER_MARGIN = 10\nconst SPACING = 5\n\ntype HorizontalType = 'left' | 'center' | 'right'\ntype VerticalType = 'top' | 'middle' | 'bottom'\n\nexport const TooltipPortal: FC<Props> = ({ message, isVisible, parentRect, isIcon }) => {\n const theme = useTheme()\n const portalRef = useRef<HTMLDivElement>(null)\n const [style, setStyle] = useState<{ [key: string]: undefined | string }>({})\n const [actualHorizontal, setActualHorizontal] = useState<HorizontalType>('center')\n const [actualVertical, setActualVertical] = useState<VerticalType>('bottom')\n\n useEffect(() => {\n if (!portalRef.current || !parentRect) {\n return\n }\n\n const portal = portalRef.current\n\n const action = () => {\n const vertical = calculateVertical(portal.offsetHeight, parentRect)\n const horizontal = calculateHorizontal(portal.offsetWidth, parentRect, theme)\n\n setStyle({\n insetBlockStart: vertical.insetBlockStart,\n insetInlineStart: horizontal.insetInlineStart,\n insetInlineEnd: horizontal.insetInlineEnd,\n maxWidth: horizontal.maxWidth,\n maxHeight: vertical.maxHeight,\n })\n setActualVertical(vertical.alignment)\n setActualHorizontal(horizontal.alignment)\n }\n const debouncedAction = debounce(action, 100)\n\n action()\n\n window.addEventListener('resize', debouncedAction)\n\n return () => {\n window.removeEventListener('resize', debouncedAction)\n }\n }, [parentRect, theme])\n\n const classNames = useMemo(() => {\n const { container, balloon, balloonText } = classNameGenerator()\n\n return {\n container: container(),\n balloon: balloon(),\n balloonText: balloonText(),\n }\n }, [])\n\n return (\n <div\n ref={portalRef}\n role=\"tooltip\"\n aria-hidden={!isVisible}\n className={classNames.container}\n style={style}\n >\n <ControlledTooltip\n horizontal={actualHorizontal}\n vertical={actualVertical}\n triggerIcon={isIcon}\n className={classNames.balloon}\n >\n <div className={classNames.balloonText}>{message}</div>\n </ControlledTooltip>\n </div>\n )\n}\n\nconst calculateVertical = (\n portalHeight: number,\n parentRect: DOMRect,\n): { insetBlockStart: string; maxHeight: string | undefined; alignment: VerticalType } => {\n // トリガの上側の領域に収まる場合\n if (parentRect.top - portalHeight >= 0) {\n return {\n insetBlockStart: `${scrollY + parentRect.top - portalHeight - SPACING}px`,\n maxHeight: undefined,\n alignment: 'bottom',\n }\n }\n\n // トリガの下側の領域に収まる場合\n if (parentRect.bottom + portalHeight <= innerHeight) {\n return {\n insetBlockStart: `${scrollY + parentRect.bottom + SPACING}px`,\n maxHeight: undefined,\n alignment: 'top',\n }\n }\n\n const triggerHeight = parentRect.bottom - parentRect.top\n\n // 上側の領域のほうが広い場合\n if (parentRect.top + triggerHeight / 2 >= innerHeight / 2) {\n return {\n insetBlockStart: `${scrollY + OUTER_MARGIN - SPACING}px`,\n maxHeight: `${parentRect.top - OUTER_MARGIN}px`,\n alignment: 'bottom',\n }\n }\n\n // 下側の領域のほうが広い場合\n return {\n insetBlockStart: `${scrollY + parentRect.bottom + SPACING}px`,\n maxHeight: `${innerHeight - parentRect.bottom - OUTER_MARGIN}px`,\n alignment: 'top',\n }\n}\n\ntype ReturnCalculateHorizontalType = {\n insetInlineStart: string | undefined\n insetInlineEnd: string | undefined\n maxWidth: string\n alignment: HorizontalType\n}\nconst calculateHorizontal = (\n portalWidth: number,\n parentRect: DOMRect,\n theme: ReturnType<typeof useTheme>,\n): ReturnCalculateHorizontalType => {\n const triggerAlignCenter = parentRect.left + parentRect.width / 2\n const portalHalfWidth = portalWidth / 2\n const edgeSpacing = theme.spacingByChar(0.5)\n\n // トリガを中心に左右に十分な余白がある場合\n if (\n triggerAlignCenter - portalHalfWidth > SPACING &&\n triggerAlignCenter + portalHalfWidth < document.body.clientWidth - SPACING\n ) {\n const insetInlineStart = `${triggerAlignCenter - portalHalfWidth}px`\n\n return {\n insetInlineStart,\n insetInlineEnd: undefined,\n maxWidth: `calc(100% - max(${insetInlineStart}, 0px) - ${edgeSpacing})`,\n alignment: 'center',\n }\n }\n\n // トリガが画面左寄りの場合\n if (triggerAlignCenter <= document.body.clientWidth / 2) {\n const insetInlineStart = `${scrollX + parentRect.left - SPACING}px`\n\n return {\n insetInlineStart,\n insetInlineEnd: undefined,\n maxWidth: `calc(100% - max(${insetInlineStart}, 0px) - ${edgeSpacing})`,\n alignment: 'left',\n }\n }\n\n // トリガが画面右寄りの場合\n const insetInlineEnd = `${document.body.clientWidth - parentRect.right - scrollX - SPACING}px`\n\n return {\n insetInlineStart: undefined,\n insetInlineEnd,\n maxWidth: `calc(100% - ${edgeSpacing} - max(${insetInlineEnd}, 0px))`,\n alignment: 'right',\n }\n}\n"],"names":[],"mappings":";;;;;;;;;;AAiBA;AACE;AACE;AACA;AACA;AACD;AACF;AAED;AACA;AAKO;AACL;AACA;;;;;;;;AAUE;;;AAIE;AAEA;;;;;;AAMC;AACD;AACA;AACF;;AAGA;AAEA;AAEA;AACE;AACF;AACF;AAEA;;;;;;;;;AA4BF;AAEA;;;;;AAQM;AACA;;;;;;;AAQA;AACA;;;;;AAOJ;;AAEI;AACA;AACA;;;;;;;AAQF;;AAEJ;AAQA;;AAME;;;AAIA;;AAIE;;;AAIE;AACA;AACA;;;;;;;;AAUA;AACA;AACA;;;;AAKJ;;AAGE;;AAEA;AACA;;AAEJ;;"}
1
+ {"version":3,"file":"TooltipPortal.cjs","sources":["../../../src/components/Tooltip/TooltipPortal.tsx"],"sourcesContent":["'use client'\n\nimport { type FC, type ReactNode, useEffect, useMemo, useRef, useState } from 'react'\nimport { tv } from 'tailwind-variants'\n\nimport { useTheme } from '../../hooks/useTheme'\nimport { debounce } from '../../libs/debounce'\n\nimport { ControlledTooltip } from './ControlledTooltip'\n\ntype Props = {\n messageId: string\n message: ReactNode\n isVisible: boolean\n parentRect: DOMRect | null\n isIcon?: boolean\n}\n\nconst classNameGenerator = tv({\n slots: {\n container: 'smarthr-ui-Tooltip-popup shr-absolute shr-z-overlap aria-hidden:shr-hidden',\n balloon: 'shr-max-w-full [&&&]:shr-whitespace-normal',\n balloonText: 'shr-m-0 shr-px-1 shr-py-0.5',\n },\n})\n\nconst OUTER_MARGIN = 10\nconst SPACING = 5\n\ntype HorizontalType = 'left' | 'center' | 'right'\ntype VerticalType = 'top' | 'middle' | 'bottom'\n\nexport const TooltipPortal: FC<Props> = ({ messageId, message, isVisible, parentRect, isIcon }) => {\n const theme = useTheme()\n const portalRef = useRef<HTMLDivElement>(null)\n const [style, setStyle] = useState<{ [key: string]: undefined | string }>({})\n const [actualHorizontal, setActualHorizontal] = useState<HorizontalType>('center')\n const [actualVertical, setActualVertical] = useState<VerticalType>('bottom')\n\n useEffect(() => {\n if (!portalRef.current || !parentRect) {\n return\n }\n\n const portal = portalRef.current\n\n const action = () => {\n const vertical = calculateVertical(portal.offsetHeight, parentRect)\n const horizontal = calculateHorizontal(portal.offsetWidth, parentRect, theme)\n\n setStyle({\n insetBlockStart: vertical.insetBlockStart,\n insetInlineStart: horizontal.insetInlineStart,\n insetInlineEnd: horizontal.insetInlineEnd,\n maxWidth: horizontal.maxWidth,\n maxHeight: vertical.maxHeight,\n })\n setActualVertical(vertical.alignment)\n setActualHorizontal(horizontal.alignment)\n }\n const debouncedAction = debounce(action, 100)\n\n action()\n\n window.addEventListener('resize', debouncedAction)\n\n return () => {\n window.removeEventListener('resize', debouncedAction)\n }\n }, [parentRect, theme])\n\n const classNames = useMemo(() => {\n const { container, balloon, balloonText } = classNameGenerator()\n\n return {\n container: container(),\n balloon: balloon(),\n balloonText: balloonText(),\n }\n }, [])\n\n return (\n <div\n ref={portalRef}\n role=\"tooltip\"\n aria-hidden={!isVisible}\n className={classNames.container}\n style={style}\n >\n <ControlledTooltip\n horizontal={actualHorizontal}\n vertical={actualVertical}\n triggerIcon={isIcon}\n className={classNames.balloon}\n >\n <div id={messageId} className={classNames.balloonText}>\n {message}\n </div>\n </ControlledTooltip>\n </div>\n )\n}\n\nconst calculateVertical = (\n portalHeight: number,\n parentRect: DOMRect,\n): { insetBlockStart: string; maxHeight: string | undefined; alignment: VerticalType } => {\n // トリガの上側の領域に収まる場合\n if (parentRect.top - portalHeight >= 0) {\n return {\n insetBlockStart: `${scrollY + parentRect.top - portalHeight - SPACING}px`,\n maxHeight: undefined,\n alignment: 'bottom',\n }\n }\n\n // トリガの下側の領域に収まる場合\n if (parentRect.bottom + portalHeight <= innerHeight) {\n return {\n insetBlockStart: `${scrollY + parentRect.bottom + SPACING}px`,\n maxHeight: undefined,\n alignment: 'top',\n }\n }\n\n const triggerHeight = parentRect.bottom - parentRect.top\n\n // 上側の領域のほうが広い場合\n if (parentRect.top + triggerHeight / 2 >= innerHeight / 2) {\n return {\n insetBlockStart: `${scrollY + OUTER_MARGIN - SPACING}px`,\n maxHeight: `${parentRect.top - OUTER_MARGIN}px`,\n alignment: 'bottom',\n }\n }\n\n // 下側の領域のほうが広い場合\n return {\n insetBlockStart: `${scrollY + parentRect.bottom + SPACING}px`,\n maxHeight: `${innerHeight - parentRect.bottom - OUTER_MARGIN}px`,\n alignment: 'top',\n }\n}\n\ntype ReturnCalculateHorizontalType = {\n insetInlineStart: string | undefined\n insetInlineEnd: string | undefined\n maxWidth: string\n alignment: HorizontalType\n}\nconst calculateHorizontal = (\n portalWidth: number,\n parentRect: DOMRect,\n theme: ReturnType<typeof useTheme>,\n): ReturnCalculateHorizontalType => {\n const triggerAlignCenter = parentRect.left + parentRect.width / 2\n const portalHalfWidth = portalWidth / 2\n const edgeSpacing = theme.spacingByChar(0.5)\n\n // トリガを中心に左右に十分な余白がある場合\n if (\n triggerAlignCenter - portalHalfWidth > SPACING &&\n triggerAlignCenter + portalHalfWidth < document.body.clientWidth - SPACING\n ) {\n const insetInlineStart = `${triggerAlignCenter - portalHalfWidth}px`\n\n return {\n insetInlineStart,\n insetInlineEnd: undefined,\n maxWidth: `calc(100% - max(${insetInlineStart}, 0px) - ${edgeSpacing})`,\n alignment: 'center',\n }\n }\n\n // トリガが画面左寄りの場合\n if (triggerAlignCenter <= document.body.clientWidth / 2) {\n const insetInlineStart = `${scrollX + parentRect.left - SPACING}px`\n\n return {\n insetInlineStart,\n insetInlineEnd: undefined,\n maxWidth: `calc(100% - max(${insetInlineStart}, 0px) - ${edgeSpacing})`,\n alignment: 'left',\n }\n }\n\n // トリガが画面右寄りの場合\n const insetInlineEnd = `${document.body.clientWidth - parentRect.right - scrollX - SPACING}px`\n\n return {\n insetInlineStart: undefined,\n insetInlineEnd,\n maxWidth: `calc(100% - ${edgeSpacing} - max(${insetInlineEnd}, 0px))`,\n alignment: 'right',\n }\n}\n"],"names":[],"mappings":";;;;;;;;;;AAkBA;AACE;AACE;AACA;AACA;AACD;AACF;AAED;AACA;AAKO;AACL;AACA;;;;;;;;AAUE;;;AAIE;AAEA;;;;;;AAMC;AACD;AACA;AACF;;AAGA;AAEA;AAEA;AACE;AACF;AACF;AAEA;;;;;;;;AAUA;AAoBF;AAEA;;;;;AAQM;AACA;;;;;;;AAQA;AACA;;;;;AAOJ;;AAEI;AACA;AACA;;;;;;;AAQF;;AAEJ;AAQA;;AAME;;;AAIA;;AAIE;;;AAIE;AACA;AACA;;;;;;;;AAUA;AACA;AACA;;;;AAKJ;;AAGE;;AAEA;AACA;;AAEJ;;"}
@@ -1,5 +1,6 @@
1
1
  import { type FC, type ReactNode } from 'react';
2
2
  type Props = {
3
+ messageId: string;
3
4
  message: ReactNode;
4
5
  isVisible: boolean;
5
6
  parentRect: DOMRect | null;
@@ -15,7 +15,7 @@ const classNameGenerator = ce({
15
15
  });
16
16
  const OUTER_MARGIN = 10;
17
17
  const SPACING = 5;
18
- const TooltipPortal = ({ message, isVisible, parentRect, isIcon }) => {
18
+ const TooltipPortal = ({ messageId, message, isVisible, parentRect, isIcon }) => {
19
19
  const theme = useTheme();
20
20
  const portalRef = useRef(null);
21
21
  const [style, setStyle] = useState({});
@@ -54,7 +54,7 @@ const TooltipPortal = ({ message, isVisible, parentRect, isIcon }) => {
54
54
  balloonText: balloonText(),
55
55
  };
56
56
  }, []);
57
- return (jsx("div", { ref: portalRef, role: "tooltip", "aria-hidden": !isVisible, className: classNames.container, style: style, children: jsx(ControlledTooltip, { horizontal: actualHorizontal, vertical: actualVertical, triggerIcon: isIcon, className: classNames.balloon, children: jsx("div", { className: classNames.balloonText, children: message }) }) }));
57
+ return (jsx("div", { ref: portalRef, role: "tooltip", "aria-hidden": !isVisible, className: classNames.container, style: style, children: jsx(ControlledTooltip, { horizontal: actualHorizontal, vertical: actualVertical, triggerIcon: isIcon, className: classNames.balloon, children: jsx("div", { id: messageId, className: classNames.balloonText, children: message }) }) }));
58
58
  };
59
59
  const calculateVertical = (portalHeight, parentRect) => {
60
60
  // トリガの上側の領域に収まる場合
@@ -1 +1 @@
1
- {"version":3,"file":"TooltipPortal.js","sources":["../../../src/components/Tooltip/TooltipPortal.tsx"],"sourcesContent":["'use client'\n\nimport { type FC, type ReactNode, useEffect, useMemo, useRef, useState } from 'react'\nimport { tv } from 'tailwind-variants'\n\nimport { useTheme } from '../../hooks/useTheme'\nimport { debounce } from '../../libs/debounce'\n\nimport { ControlledTooltip } from './ControlledTooltip'\n\ntype Props = {\n message: ReactNode\n isVisible: boolean\n parentRect: DOMRect | null\n isIcon?: boolean\n}\n\nconst classNameGenerator = tv({\n slots: {\n container: 'smarthr-ui-Tooltip-popup shr-absolute shr-z-overlap aria-hidden:shr-hidden',\n balloon: 'shr-max-w-full [&&&]:shr-whitespace-normal',\n balloonText: 'shr-m-0 shr-px-1 shr-py-0.5',\n },\n})\n\nconst OUTER_MARGIN = 10\nconst SPACING = 5\n\ntype HorizontalType = 'left' | 'center' | 'right'\ntype VerticalType = 'top' | 'middle' | 'bottom'\n\nexport const TooltipPortal: FC<Props> = ({ message, isVisible, parentRect, isIcon }) => {\n const theme = useTheme()\n const portalRef = useRef<HTMLDivElement>(null)\n const [style, setStyle] = useState<{ [key: string]: undefined | string }>({})\n const [actualHorizontal, setActualHorizontal] = useState<HorizontalType>('center')\n const [actualVertical, setActualVertical] = useState<VerticalType>('bottom')\n\n useEffect(() => {\n if (!portalRef.current || !parentRect) {\n return\n }\n\n const portal = portalRef.current\n\n const action = () => {\n const vertical = calculateVertical(portal.offsetHeight, parentRect)\n const horizontal = calculateHorizontal(portal.offsetWidth, parentRect, theme)\n\n setStyle({\n insetBlockStart: vertical.insetBlockStart,\n insetInlineStart: horizontal.insetInlineStart,\n insetInlineEnd: horizontal.insetInlineEnd,\n maxWidth: horizontal.maxWidth,\n maxHeight: vertical.maxHeight,\n })\n setActualVertical(vertical.alignment)\n setActualHorizontal(horizontal.alignment)\n }\n const debouncedAction = debounce(action, 100)\n\n action()\n\n window.addEventListener('resize', debouncedAction)\n\n return () => {\n window.removeEventListener('resize', debouncedAction)\n }\n }, [parentRect, theme])\n\n const classNames = useMemo(() => {\n const { container, balloon, balloonText } = classNameGenerator()\n\n return {\n container: container(),\n balloon: balloon(),\n balloonText: balloonText(),\n }\n }, [])\n\n return (\n <div\n ref={portalRef}\n role=\"tooltip\"\n aria-hidden={!isVisible}\n className={classNames.container}\n style={style}\n >\n <ControlledTooltip\n horizontal={actualHorizontal}\n vertical={actualVertical}\n triggerIcon={isIcon}\n className={classNames.balloon}\n >\n <div className={classNames.balloonText}>{message}</div>\n </ControlledTooltip>\n </div>\n )\n}\n\nconst calculateVertical = (\n portalHeight: number,\n parentRect: DOMRect,\n): { insetBlockStart: string; maxHeight: string | undefined; alignment: VerticalType } => {\n // トリガの上側の領域に収まる場合\n if (parentRect.top - portalHeight >= 0) {\n return {\n insetBlockStart: `${scrollY + parentRect.top - portalHeight - SPACING}px`,\n maxHeight: undefined,\n alignment: 'bottom',\n }\n }\n\n // トリガの下側の領域に収まる場合\n if (parentRect.bottom + portalHeight <= innerHeight) {\n return {\n insetBlockStart: `${scrollY + parentRect.bottom + SPACING}px`,\n maxHeight: undefined,\n alignment: 'top',\n }\n }\n\n const triggerHeight = parentRect.bottom - parentRect.top\n\n // 上側の領域のほうが広い場合\n if (parentRect.top + triggerHeight / 2 >= innerHeight / 2) {\n return {\n insetBlockStart: `${scrollY + OUTER_MARGIN - SPACING}px`,\n maxHeight: `${parentRect.top - OUTER_MARGIN}px`,\n alignment: 'bottom',\n }\n }\n\n // 下側の領域のほうが広い場合\n return {\n insetBlockStart: `${scrollY + parentRect.bottom + SPACING}px`,\n maxHeight: `${innerHeight - parentRect.bottom - OUTER_MARGIN}px`,\n alignment: 'top',\n }\n}\n\ntype ReturnCalculateHorizontalType = {\n insetInlineStart: string | undefined\n insetInlineEnd: string | undefined\n maxWidth: string\n alignment: HorizontalType\n}\nconst calculateHorizontal = (\n portalWidth: number,\n parentRect: DOMRect,\n theme: ReturnType<typeof useTheme>,\n): ReturnCalculateHorizontalType => {\n const triggerAlignCenter = parentRect.left + parentRect.width / 2\n const portalHalfWidth = portalWidth / 2\n const edgeSpacing = theme.spacingByChar(0.5)\n\n // トリガを中心に左右に十分な余白がある場合\n if (\n triggerAlignCenter - portalHalfWidth > SPACING &&\n triggerAlignCenter + portalHalfWidth < document.body.clientWidth - SPACING\n ) {\n const insetInlineStart = `${triggerAlignCenter - portalHalfWidth}px`\n\n return {\n insetInlineStart,\n insetInlineEnd: undefined,\n maxWidth: `calc(100% - max(${insetInlineStart}, 0px) - ${edgeSpacing})`,\n alignment: 'center',\n }\n }\n\n // トリガが画面左寄りの場合\n if (triggerAlignCenter <= document.body.clientWidth / 2) {\n const insetInlineStart = `${scrollX + parentRect.left - SPACING}px`\n\n return {\n insetInlineStart,\n insetInlineEnd: undefined,\n maxWidth: `calc(100% - max(${insetInlineStart}, 0px) - ${edgeSpacing})`,\n alignment: 'left',\n }\n }\n\n // トリガが画面右寄りの場合\n const insetInlineEnd = `${document.body.clientWidth - parentRect.right - scrollX - SPACING}px`\n\n return {\n insetInlineStart: undefined,\n insetInlineEnd,\n maxWidth: `calc(100% - ${edgeSpacing} - max(${insetInlineEnd}, 0px))`,\n alignment: 'right',\n }\n}\n"],"names":[],"mappings":";;;;;;;;AAiBA;AACE;AACE;AACA;AACA;AACD;AACF;AAED;AACA;AAKO;AACL;AACA;;;;;;;;AAUE;;;AAIE;AAEA;;;;;;AAMC;AACD;AACA;AACF;;AAGA;AAEA;AAEA;AACE;AACF;AACF;AAEA;;;;;;;;;AA4BF;AAEA;;;;;AAQM;AACA;;;;;;;AAQA;AACA;;;;;AAOJ;;AAEI;AACA;AACA;;;;;;;AAQF;;AAEJ;AAQA;;AAME;;;AAIA;;AAIE;;;AAIE;AACA;AACA;;;;;;;;AAUA;AACA;AACA;;;;AAKJ;;AAGE;;AAEA;AACA;;AAEJ;;"}
1
+ {"version":3,"file":"TooltipPortal.js","sources":["../../../src/components/Tooltip/TooltipPortal.tsx"],"sourcesContent":["'use client'\n\nimport { type FC, type ReactNode, useEffect, useMemo, useRef, useState } from 'react'\nimport { tv } from 'tailwind-variants'\n\nimport { useTheme } from '../../hooks/useTheme'\nimport { debounce } from '../../libs/debounce'\n\nimport { ControlledTooltip } from './ControlledTooltip'\n\ntype Props = {\n messageId: string\n message: ReactNode\n isVisible: boolean\n parentRect: DOMRect | null\n isIcon?: boolean\n}\n\nconst classNameGenerator = tv({\n slots: {\n container: 'smarthr-ui-Tooltip-popup shr-absolute shr-z-overlap aria-hidden:shr-hidden',\n balloon: 'shr-max-w-full [&&&]:shr-whitespace-normal',\n balloonText: 'shr-m-0 shr-px-1 shr-py-0.5',\n },\n})\n\nconst OUTER_MARGIN = 10\nconst SPACING = 5\n\ntype HorizontalType = 'left' | 'center' | 'right'\ntype VerticalType = 'top' | 'middle' | 'bottom'\n\nexport const TooltipPortal: FC<Props> = ({ messageId, message, isVisible, parentRect, isIcon }) => {\n const theme = useTheme()\n const portalRef = useRef<HTMLDivElement>(null)\n const [style, setStyle] = useState<{ [key: string]: undefined | string }>({})\n const [actualHorizontal, setActualHorizontal] = useState<HorizontalType>('center')\n const [actualVertical, setActualVertical] = useState<VerticalType>('bottom')\n\n useEffect(() => {\n if (!portalRef.current || !parentRect) {\n return\n }\n\n const portal = portalRef.current\n\n const action = () => {\n const vertical = calculateVertical(portal.offsetHeight, parentRect)\n const horizontal = calculateHorizontal(portal.offsetWidth, parentRect, theme)\n\n setStyle({\n insetBlockStart: vertical.insetBlockStart,\n insetInlineStart: horizontal.insetInlineStart,\n insetInlineEnd: horizontal.insetInlineEnd,\n maxWidth: horizontal.maxWidth,\n maxHeight: vertical.maxHeight,\n })\n setActualVertical(vertical.alignment)\n setActualHorizontal(horizontal.alignment)\n }\n const debouncedAction = debounce(action, 100)\n\n action()\n\n window.addEventListener('resize', debouncedAction)\n\n return () => {\n window.removeEventListener('resize', debouncedAction)\n }\n }, [parentRect, theme])\n\n const classNames = useMemo(() => {\n const { container, balloon, balloonText } = classNameGenerator()\n\n return {\n container: container(),\n balloon: balloon(),\n balloonText: balloonText(),\n }\n }, [])\n\n return (\n <div\n ref={portalRef}\n role=\"tooltip\"\n aria-hidden={!isVisible}\n className={classNames.container}\n style={style}\n >\n <ControlledTooltip\n horizontal={actualHorizontal}\n vertical={actualVertical}\n triggerIcon={isIcon}\n className={classNames.balloon}\n >\n <div id={messageId} className={classNames.balloonText}>\n {message}\n </div>\n </ControlledTooltip>\n </div>\n )\n}\n\nconst calculateVertical = (\n portalHeight: number,\n parentRect: DOMRect,\n): { insetBlockStart: string; maxHeight: string | undefined; alignment: VerticalType } => {\n // トリガの上側の領域に収まる場合\n if (parentRect.top - portalHeight >= 0) {\n return {\n insetBlockStart: `${scrollY + parentRect.top - portalHeight - SPACING}px`,\n maxHeight: undefined,\n alignment: 'bottom',\n }\n }\n\n // トリガの下側の領域に収まる場合\n if (parentRect.bottom + portalHeight <= innerHeight) {\n return {\n insetBlockStart: `${scrollY + parentRect.bottom + SPACING}px`,\n maxHeight: undefined,\n alignment: 'top',\n }\n }\n\n const triggerHeight = parentRect.bottom - parentRect.top\n\n // 上側の領域のほうが広い場合\n if (parentRect.top + triggerHeight / 2 >= innerHeight / 2) {\n return {\n insetBlockStart: `${scrollY + OUTER_MARGIN - SPACING}px`,\n maxHeight: `${parentRect.top - OUTER_MARGIN}px`,\n alignment: 'bottom',\n }\n }\n\n // 下側の領域のほうが広い場合\n return {\n insetBlockStart: `${scrollY + parentRect.bottom + SPACING}px`,\n maxHeight: `${innerHeight - parentRect.bottom - OUTER_MARGIN}px`,\n alignment: 'top',\n }\n}\n\ntype ReturnCalculateHorizontalType = {\n insetInlineStart: string | undefined\n insetInlineEnd: string | undefined\n maxWidth: string\n alignment: HorizontalType\n}\nconst calculateHorizontal = (\n portalWidth: number,\n parentRect: DOMRect,\n theme: ReturnType<typeof useTheme>,\n): ReturnCalculateHorizontalType => {\n const triggerAlignCenter = parentRect.left + parentRect.width / 2\n const portalHalfWidth = portalWidth / 2\n const edgeSpacing = theme.spacingByChar(0.5)\n\n // トリガを中心に左右に十分な余白がある場合\n if (\n triggerAlignCenter - portalHalfWidth > SPACING &&\n triggerAlignCenter + portalHalfWidth < document.body.clientWidth - SPACING\n ) {\n const insetInlineStart = `${triggerAlignCenter - portalHalfWidth}px`\n\n return {\n insetInlineStart,\n insetInlineEnd: undefined,\n maxWidth: `calc(100% - max(${insetInlineStart}, 0px) - ${edgeSpacing})`,\n alignment: 'center',\n }\n }\n\n // トリガが画面左寄りの場合\n if (triggerAlignCenter <= document.body.clientWidth / 2) {\n const insetInlineStart = `${scrollX + parentRect.left - SPACING}px`\n\n return {\n insetInlineStart,\n insetInlineEnd: undefined,\n maxWidth: `calc(100% - max(${insetInlineStart}, 0px) - ${edgeSpacing})`,\n alignment: 'left',\n }\n }\n\n // トリガが画面右寄りの場合\n const insetInlineEnd = `${document.body.clientWidth - parentRect.right - scrollX - SPACING}px`\n\n return {\n insetInlineStart: undefined,\n insetInlineEnd,\n maxWidth: `calc(100% - ${edgeSpacing} - max(${insetInlineEnd}, 0px))`,\n alignment: 'right',\n }\n}\n"],"names":[],"mappings":";;;;;;;;AAkBA;AACE;AACE;AACA;AACA;AACD;AACF;AAED;AACA;AAKO;AACL;AACA;;;;;;;;AAUE;;;AAIE;AAEA;;;;;;AAMC;AACD;AACA;AACF;;AAGA;AAEA;AAEA;AACE;AACF;AACF;AAEA;;;;;;;;AAUA;AAoBF;AAEA;;;;;AAQM;AACA;;;;;;;AAQA;AACA;;;;;AAOJ;;AAEI;AACA;AACA;;;;;;;AAQF;;AAEJ;AAQA;;AAME;;;AAIA;;AAIE;;;AAIE;AACA;AACA;;;;;;;;AAUA;AACA;AACA;;;;AAKJ;;AAGE;;AAEA;AACA;;AAEJ;;"}
@@ -32,6 +32,7 @@ function getTop({ parentRect, tooltipHeight, vertical, outerMargin, }) {
32
32
  return parentRect.top - tooltipHeight - outerMargin;
33
33
  }
34
34
  }
35
+ const BALLOON_ARROW_POSITION = 29; // length between Balloon edge and center of arrow
35
36
  function getLeft({ parentRect, tooltipWidth, horizontal, vertical, isIcon, outerMargin, }) {
36
37
  switch (vertical) {
37
38
  case 'middle':
@@ -43,8 +44,7 @@ function getLeft({ parentRect, tooltipWidth, horizontal, vertical, isIcon, outer
43
44
  }
44
45
  case 'top':
45
46
  case 'bottom': {
46
- const arrowPosition = 29; // length between Balloon edge and center of arrow
47
- const iconGap = isIcon ? arrowPosition - parentRect.width / 2 : 0; // to align center of Balloon arrow and icon
47
+ const iconGap = isIcon ? BALLOON_ARROW_POSITION - parentRect.width / 2 : 0; // to align center of Balloon arrow and icon
48
48
  switch (horizontal) {
49
49
  case 'right':
50
50
  return parentRect.left + parentRect.width - tooltipWidth + iconGap;
@@ -1 +1 @@
1
- {"version":3,"file":"tooltipHelper.cjs","sources":["../../../src/components/Tooltip/tooltipHelper.ts"],"sourcesContent":["export function getTooltipRect({\n parentRect,\n scrollOffset,\n tooltipSize,\n vertical,\n horizontal,\n isIcon = false,\n outerMargin,\n}: {\n parentRect: DOMRect\n scrollOffset: { top: number; left: number }\n tooltipSize: { width: number; height: number }\n vertical: 'top' | 'middle' | 'bottom'\n horizontal: 'left' | 'center' | 'right'\n isIcon: boolean\n outerMargin: number\n}): { top: number; left: number; $width: number; $height: number } {\n const top = getTop({\n parentRect,\n tooltipHeight: tooltipSize.height,\n vertical,\n outerMargin,\n })\n const left = getLeft({\n parentRect,\n tooltipWidth: tooltipSize.width,\n horizontal,\n vertical,\n isIcon,\n outerMargin,\n })\n\n return {\n top: top + scrollOffset.top,\n left: left + scrollOffset.left,\n $width: tooltipSize.width,\n $height: tooltipSize.height,\n }\n}\n\nfunction getTop({\n parentRect,\n tooltipHeight,\n vertical,\n outerMargin,\n}: {\n parentRect: DOMRect\n tooltipHeight: number\n vertical: 'top' | 'middle' | 'bottom'\n outerMargin: number\n}): number {\n switch (vertical) {\n case 'top':\n return parentRect.top + parentRect.height + outerMargin\n case 'middle':\n return parentRect.top + (parentRect.height - tooltipHeight) / 2\n case 'bottom':\n return parentRect.top - tooltipHeight - outerMargin\n }\n}\n\nfunction getLeft({\n parentRect,\n tooltipWidth,\n horizontal,\n vertical,\n isIcon,\n outerMargin,\n}: {\n parentRect: DOMRect\n tooltipWidth: number\n horizontal: 'left' | 'center' | 'right'\n vertical: 'top' | 'middle' | 'bottom'\n isIcon: boolean\n outerMargin: number\n}): number {\n switch (vertical) {\n case 'middle':\n switch (horizontal) {\n case 'right':\n return parentRect.left - tooltipWidth - outerMargin\n default:\n return parentRect.left + parentRect.width + outerMargin\n }\n case 'top':\n case 'bottom': {\n const arrowPosition = 29 // length between Balloon edge and center of arrow\n const iconGap = isIcon ? arrowPosition - parentRect.width / 2 : 0 // to align center of Balloon arrow and icon\n switch (horizontal) {\n case 'right':\n return parentRect.left + parentRect.width - tooltipWidth + iconGap\n case 'center':\n return parentRect.left + (parentRect.width - tooltipWidth) / 2\n case 'left':\n return parentRect.left - iconGap\n }\n }\n }\n}\n"],"names":[],"mappings":";;SAAgB,cAAc,CAAC,EAC7B,UAAU,EACV,YAAY,EACZ,WAAW,EACX,QAAQ,EACR,UAAU,EACV,MAAM,GAAG,KAAK,EACd,WAAW,GASZ,EAAA;IACC,MAAM,GAAG,GAAG,MAAM,CAAC;QACjB,UAAU;QACV,aAAa,EAAE,WAAW,CAAC,MAAM;QACjC,QAAQ;QACR,WAAW;AACZ,KAAA,CAAC;IACF,MAAM,IAAI,GAAG,OAAO,CAAC;QACnB,UAAU;QACV,YAAY,EAAE,WAAW,CAAC,KAAK;QAC/B,UAAU;QACV,QAAQ;QACR,MAAM;QACN,WAAW;AACZ,KAAA,CAAC;IAEF,OAAO;AACL,QAAA,GAAG,EAAE,GAAG,GAAG,YAAY,CAAC,GAAG;AAC3B,QAAA,IAAI,EAAE,IAAI,GAAG,YAAY,CAAC,IAAI;QAC9B,MAAM,EAAE,WAAW,CAAC,KAAK;QACzB,OAAO,EAAE,WAAW,CAAC,MAAM;KAC5B;AACH;AAEA,SAAS,MAAM,CAAC,EACd,UAAU,EACV,aAAa,EACb,QAAQ,EACR,WAAW,GAMZ,EAAA;IACC,QAAQ,QAAQ;AACd,QAAA,KAAK,KAAK;YACR,OAAO,UAAU,CAAC,GAAG,GAAG,UAAU,CAAC,MAAM,GAAG,WAAW;AACzD,QAAA,KAAK,QAAQ;AACX,YAAA,OAAO,UAAU,CAAC,GAAG,GAAG,CAAC,UAAU,CAAC,MAAM,GAAG,aAAa,IAAI,CAAC;AACjE,QAAA,KAAK,QAAQ;AACX,YAAA,OAAO,UAAU,CAAC,GAAG,GAAG,aAAa,GAAG,WAAW;;AAEzD;AAEA,SAAS,OAAO,CAAC,EACf,UAAU,EACV,YAAY,EACZ,UAAU,EACV,QAAQ,EACR,MAAM,EACN,WAAW,GAQZ,EAAA;IACC,QAAQ,QAAQ;AACd,QAAA,KAAK,QAAQ;YACX,QAAQ,UAAU;AAChB,gBAAA,KAAK,OAAO;AACV,oBAAA,OAAO,UAAU,CAAC,IAAI,GAAG,YAAY,GAAG,WAAW;AACrD,gBAAA;oBACE,OAAO,UAAU,CAAC,IAAI,GAAG,UAAU,CAAC,KAAK,GAAG,WAAW;;AAE7D,QAAA,KAAK,KAAK;QACV,KAAK,QAAQ,EAAE;AACb,YAAA,MAAM,aAAa,GAAG,EAAE,CAAA;AACxB,YAAA,MAAM,OAAO,GAAG,MAAM,GAAG,aAAa,GAAG,UAAU,CAAC,KAAK,GAAG,CAAC,GAAG,CAAC,CAAA;YACjE,QAAQ,UAAU;AAChB,gBAAA,KAAK,OAAO;oBACV,OAAO,UAAU,CAAC,IAAI,GAAG,UAAU,CAAC,KAAK,GAAG,YAAY,GAAG,OAAO;AACpE,gBAAA,KAAK,QAAQ;AACX,oBAAA,OAAO,UAAU,CAAC,IAAI,GAAG,CAAC,UAAU,CAAC,KAAK,GAAG,YAAY,IAAI,CAAC;AAChE,gBAAA,KAAK,MAAM;AACT,oBAAA,OAAO,UAAU,CAAC,IAAI,GAAG,OAAO;;QAEtC;;AAEJ;;;;"}
1
+ {"version":3,"file":"tooltipHelper.cjs","sources":["../../../src/components/Tooltip/tooltipHelper.ts"],"sourcesContent":["export function getTooltipRect({\n parentRect,\n scrollOffset,\n tooltipSize,\n vertical,\n horizontal,\n isIcon = false,\n outerMargin,\n}: {\n parentRect: DOMRect\n scrollOffset: { top: number; left: number }\n tooltipSize: { width: number; height: number }\n vertical: 'top' | 'middle' | 'bottom'\n horizontal: 'left' | 'center' | 'right'\n isIcon: boolean\n outerMargin: number\n}): { top: number; left: number; $width: number; $height: number } {\n const top = getTop({\n parentRect,\n tooltipHeight: tooltipSize.height,\n vertical,\n outerMargin,\n })\n const left = getLeft({\n parentRect,\n tooltipWidth: tooltipSize.width,\n horizontal,\n vertical,\n isIcon,\n outerMargin,\n })\n\n return {\n top: top + scrollOffset.top,\n left: left + scrollOffset.left,\n $width: tooltipSize.width,\n $height: tooltipSize.height,\n }\n}\n\nfunction getTop({\n parentRect,\n tooltipHeight,\n vertical,\n outerMargin,\n}: {\n parentRect: DOMRect\n tooltipHeight: number\n vertical: 'top' | 'middle' | 'bottom'\n outerMargin: number\n}): number {\n switch (vertical) {\n case 'top':\n return parentRect.top + parentRect.height + outerMargin\n case 'middle':\n return parentRect.top + (parentRect.height - tooltipHeight) / 2\n case 'bottom':\n return parentRect.top - tooltipHeight - outerMargin\n }\n}\n\nconst BALLOON_ARROW_POSITION = 29 // length between Balloon edge and center of arrow\n\nfunction getLeft({\n parentRect,\n tooltipWidth,\n horizontal,\n vertical,\n isIcon,\n outerMargin,\n}: {\n parentRect: DOMRect\n tooltipWidth: number\n horizontal: 'left' | 'center' | 'right'\n vertical: 'top' | 'middle' | 'bottom'\n isIcon: boolean\n outerMargin: number\n}): number {\n switch (vertical) {\n case 'middle':\n switch (horizontal) {\n case 'right':\n return parentRect.left - tooltipWidth - outerMargin\n default:\n return parentRect.left + parentRect.width + outerMargin\n }\n case 'top':\n case 'bottom': {\n const iconGap = isIcon ? BALLOON_ARROW_POSITION - parentRect.width / 2 : 0 // to align center of Balloon arrow and icon\n\n switch (horizontal) {\n case 'right':\n return parentRect.left + parentRect.width - tooltipWidth + iconGap\n case 'center':\n return parentRect.left + (parentRect.width - tooltipWidth) / 2\n case 'left':\n return parentRect.left - iconGap\n }\n }\n }\n}\n"],"names":[],"mappings":";;SAAgB,cAAc,CAAC,EAC7B,UAAU,EACV,YAAY,EACZ,WAAW,EACX,QAAQ,EACR,UAAU,EACV,MAAM,GAAG,KAAK,EACd,WAAW,GASZ,EAAA;IACC,MAAM,GAAG,GAAG,MAAM,CAAC;QACjB,UAAU;QACV,aAAa,EAAE,WAAW,CAAC,MAAM;QACjC,QAAQ;QACR,WAAW;AACZ,KAAA,CAAC;IACF,MAAM,IAAI,GAAG,OAAO,CAAC;QACnB,UAAU;QACV,YAAY,EAAE,WAAW,CAAC,KAAK;QAC/B,UAAU;QACV,QAAQ;QACR,MAAM;QACN,WAAW;AACZ,KAAA,CAAC;IAEF,OAAO;AACL,QAAA,GAAG,EAAE,GAAG,GAAG,YAAY,CAAC,GAAG;AAC3B,QAAA,IAAI,EAAE,IAAI,GAAG,YAAY,CAAC,IAAI;QAC9B,MAAM,EAAE,WAAW,CAAC,KAAK;QACzB,OAAO,EAAE,WAAW,CAAC,MAAM;KAC5B;AACH;AAEA,SAAS,MAAM,CAAC,EACd,UAAU,EACV,aAAa,EACb,QAAQ,EACR,WAAW,GAMZ,EAAA;IACC,QAAQ,QAAQ;AACd,QAAA,KAAK,KAAK;YACR,OAAO,UAAU,CAAC,GAAG,GAAG,UAAU,CAAC,MAAM,GAAG,WAAW;AACzD,QAAA,KAAK,QAAQ;AACX,YAAA,OAAO,UAAU,CAAC,GAAG,GAAG,CAAC,UAAU,CAAC,MAAM,GAAG,aAAa,IAAI,CAAC;AACjE,QAAA,KAAK,QAAQ;AACX,YAAA,OAAO,UAAU,CAAC,GAAG,GAAG,aAAa,GAAG,WAAW;;AAEzD;AAEA,MAAM,sBAAsB,GAAG,EAAE,CAAA;AAEjC,SAAS,OAAO,CAAC,EACf,UAAU,EACV,YAAY,EACZ,UAAU,EACV,QAAQ,EACR,MAAM,EACN,WAAW,GAQZ,EAAA;IACC,QAAQ,QAAQ;AACd,QAAA,KAAK,QAAQ;YACX,QAAQ,UAAU;AAChB,gBAAA,KAAK,OAAO;AACV,oBAAA,OAAO,UAAU,CAAC,IAAI,GAAG,YAAY,GAAG,WAAW;AACrD,gBAAA;oBACE,OAAO,UAAU,CAAC,IAAI,GAAG,UAAU,CAAC,KAAK,GAAG,WAAW;;AAE7D,QAAA,KAAK,KAAK;QACV,KAAK,QAAQ,EAAE;AACb,YAAA,MAAM,OAAO,GAAG,MAAM,GAAG,sBAAsB,GAAG,UAAU,CAAC,KAAK,GAAG,CAAC,GAAG,CAAC,CAAA;YAE1E,QAAQ,UAAU;AAChB,gBAAA,KAAK,OAAO;oBACV,OAAO,UAAU,CAAC,IAAI,GAAG,UAAU,CAAC,KAAK,GAAG,YAAY,GAAG,OAAO;AACpE,gBAAA,KAAK,QAAQ;AACX,oBAAA,OAAO,UAAU,CAAC,IAAI,GAAG,CAAC,UAAU,CAAC,KAAK,GAAG,YAAY,IAAI,CAAC;AAChE,gBAAA,KAAK,MAAM;AACT,oBAAA,OAAO,UAAU,CAAC,IAAI,GAAG,OAAO;;QAEtC;;AAEJ;;;;"}
@@ -30,6 +30,7 @@ function getTop({ parentRect, tooltipHeight, vertical, outerMargin, }) {
30
30
  return parentRect.top - tooltipHeight - outerMargin;
31
31
  }
32
32
  }
33
+ const BALLOON_ARROW_POSITION = 29; // length between Balloon edge and center of arrow
33
34
  function getLeft({ parentRect, tooltipWidth, horizontal, vertical, isIcon, outerMargin, }) {
34
35
  switch (vertical) {
35
36
  case 'middle':
@@ -41,8 +42,7 @@ function getLeft({ parentRect, tooltipWidth, horizontal, vertical, isIcon, outer
41
42
  }
42
43
  case 'top':
43
44
  case 'bottom': {
44
- const arrowPosition = 29; // length between Balloon edge and center of arrow
45
- const iconGap = isIcon ? arrowPosition - parentRect.width / 2 : 0; // to align center of Balloon arrow and icon
45
+ const iconGap = isIcon ? BALLOON_ARROW_POSITION - parentRect.width / 2 : 0; // to align center of Balloon arrow and icon
46
46
  switch (horizontal) {
47
47
  case 'right':
48
48
  return parentRect.left + parentRect.width - tooltipWidth + iconGap;
@@ -1 +1 @@
1
- {"version":3,"file":"tooltipHelper.js","sources":["../../../src/components/Tooltip/tooltipHelper.ts"],"sourcesContent":["export function getTooltipRect({\n parentRect,\n scrollOffset,\n tooltipSize,\n vertical,\n horizontal,\n isIcon = false,\n outerMargin,\n}: {\n parentRect: DOMRect\n scrollOffset: { top: number; left: number }\n tooltipSize: { width: number; height: number }\n vertical: 'top' | 'middle' | 'bottom'\n horizontal: 'left' | 'center' | 'right'\n isIcon: boolean\n outerMargin: number\n}): { top: number; left: number; $width: number; $height: number } {\n const top = getTop({\n parentRect,\n tooltipHeight: tooltipSize.height,\n vertical,\n outerMargin,\n })\n const left = getLeft({\n parentRect,\n tooltipWidth: tooltipSize.width,\n horizontal,\n vertical,\n isIcon,\n outerMargin,\n })\n\n return {\n top: top + scrollOffset.top,\n left: left + scrollOffset.left,\n $width: tooltipSize.width,\n $height: tooltipSize.height,\n }\n}\n\nfunction getTop({\n parentRect,\n tooltipHeight,\n vertical,\n outerMargin,\n}: {\n parentRect: DOMRect\n tooltipHeight: number\n vertical: 'top' | 'middle' | 'bottom'\n outerMargin: number\n}): number {\n switch (vertical) {\n case 'top':\n return parentRect.top + parentRect.height + outerMargin\n case 'middle':\n return parentRect.top + (parentRect.height - tooltipHeight) / 2\n case 'bottom':\n return parentRect.top - tooltipHeight - outerMargin\n }\n}\n\nfunction getLeft({\n parentRect,\n tooltipWidth,\n horizontal,\n vertical,\n isIcon,\n outerMargin,\n}: {\n parentRect: DOMRect\n tooltipWidth: number\n horizontal: 'left' | 'center' | 'right'\n vertical: 'top' | 'middle' | 'bottom'\n isIcon: boolean\n outerMargin: number\n}): number {\n switch (vertical) {\n case 'middle':\n switch (horizontal) {\n case 'right':\n return parentRect.left - tooltipWidth - outerMargin\n default:\n return parentRect.left + parentRect.width + outerMargin\n }\n case 'top':\n case 'bottom': {\n const arrowPosition = 29 // length between Balloon edge and center of arrow\n const iconGap = isIcon ? arrowPosition - parentRect.width / 2 : 0 // to align center of Balloon arrow and icon\n switch (horizontal) {\n case 'right':\n return parentRect.left + parentRect.width - tooltipWidth + iconGap\n case 'center':\n return parentRect.left + (parentRect.width - tooltipWidth) / 2\n case 'left':\n return parentRect.left - iconGap\n }\n }\n }\n}\n"],"names":[],"mappings":"SAAgB,cAAc,CAAC,EAC7B,UAAU,EACV,YAAY,EACZ,WAAW,EACX,QAAQ,EACR,UAAU,EACV,MAAM,GAAG,KAAK,EACd,WAAW,GASZ,EAAA;IACC,MAAM,GAAG,GAAG,MAAM,CAAC;QACjB,UAAU;QACV,aAAa,EAAE,WAAW,CAAC,MAAM;QACjC,QAAQ;QACR,WAAW;AACZ,KAAA,CAAC;IACF,MAAM,IAAI,GAAG,OAAO,CAAC;QACnB,UAAU;QACV,YAAY,EAAE,WAAW,CAAC,KAAK;QAC/B,UAAU;QACV,QAAQ;QACR,MAAM;QACN,WAAW;AACZ,KAAA,CAAC;IAEF,OAAO;AACL,QAAA,GAAG,EAAE,GAAG,GAAG,YAAY,CAAC,GAAG;AAC3B,QAAA,IAAI,EAAE,IAAI,GAAG,YAAY,CAAC,IAAI;QAC9B,MAAM,EAAE,WAAW,CAAC,KAAK;QACzB,OAAO,EAAE,WAAW,CAAC,MAAM;KAC5B;AACH;AAEA,SAAS,MAAM,CAAC,EACd,UAAU,EACV,aAAa,EACb,QAAQ,EACR,WAAW,GAMZ,EAAA;IACC,QAAQ,QAAQ;AACd,QAAA,KAAK,KAAK;YACR,OAAO,UAAU,CAAC,GAAG,GAAG,UAAU,CAAC,MAAM,GAAG,WAAW;AACzD,QAAA,KAAK,QAAQ;AACX,YAAA,OAAO,UAAU,CAAC,GAAG,GAAG,CAAC,UAAU,CAAC,MAAM,GAAG,aAAa,IAAI,CAAC;AACjE,QAAA,KAAK,QAAQ;AACX,YAAA,OAAO,UAAU,CAAC,GAAG,GAAG,aAAa,GAAG,WAAW;;AAEzD;AAEA,SAAS,OAAO,CAAC,EACf,UAAU,EACV,YAAY,EACZ,UAAU,EACV,QAAQ,EACR,MAAM,EACN,WAAW,GAQZ,EAAA;IACC,QAAQ,QAAQ;AACd,QAAA,KAAK,QAAQ;YACX,QAAQ,UAAU;AAChB,gBAAA,KAAK,OAAO;AACV,oBAAA,OAAO,UAAU,CAAC,IAAI,GAAG,YAAY,GAAG,WAAW;AACrD,gBAAA;oBACE,OAAO,UAAU,CAAC,IAAI,GAAG,UAAU,CAAC,KAAK,GAAG,WAAW;;AAE7D,QAAA,KAAK,KAAK;QACV,KAAK,QAAQ,EAAE;AACb,YAAA,MAAM,aAAa,GAAG,EAAE,CAAA;AACxB,YAAA,MAAM,OAAO,GAAG,MAAM,GAAG,aAAa,GAAG,UAAU,CAAC,KAAK,GAAG,CAAC,GAAG,CAAC,CAAA;YACjE,QAAQ,UAAU;AAChB,gBAAA,KAAK,OAAO;oBACV,OAAO,UAAU,CAAC,IAAI,GAAG,UAAU,CAAC,KAAK,GAAG,YAAY,GAAG,OAAO;AACpE,gBAAA,KAAK,QAAQ;AACX,oBAAA,OAAO,UAAU,CAAC,IAAI,GAAG,CAAC,UAAU,CAAC,KAAK,GAAG,YAAY,IAAI,CAAC;AAChE,gBAAA,KAAK,MAAM;AACT,oBAAA,OAAO,UAAU,CAAC,IAAI,GAAG,OAAO;;QAEtC;;AAEJ;;;;"}
1
+ {"version":3,"file":"tooltipHelper.js","sources":["../../../src/components/Tooltip/tooltipHelper.ts"],"sourcesContent":["export function getTooltipRect({\n parentRect,\n scrollOffset,\n tooltipSize,\n vertical,\n horizontal,\n isIcon = false,\n outerMargin,\n}: {\n parentRect: DOMRect\n scrollOffset: { top: number; left: number }\n tooltipSize: { width: number; height: number }\n vertical: 'top' | 'middle' | 'bottom'\n horizontal: 'left' | 'center' | 'right'\n isIcon: boolean\n outerMargin: number\n}): { top: number; left: number; $width: number; $height: number } {\n const top = getTop({\n parentRect,\n tooltipHeight: tooltipSize.height,\n vertical,\n outerMargin,\n })\n const left = getLeft({\n parentRect,\n tooltipWidth: tooltipSize.width,\n horizontal,\n vertical,\n isIcon,\n outerMargin,\n })\n\n return {\n top: top + scrollOffset.top,\n left: left + scrollOffset.left,\n $width: tooltipSize.width,\n $height: tooltipSize.height,\n }\n}\n\nfunction getTop({\n parentRect,\n tooltipHeight,\n vertical,\n outerMargin,\n}: {\n parentRect: DOMRect\n tooltipHeight: number\n vertical: 'top' | 'middle' | 'bottom'\n outerMargin: number\n}): number {\n switch (vertical) {\n case 'top':\n return parentRect.top + parentRect.height + outerMargin\n case 'middle':\n return parentRect.top + (parentRect.height - tooltipHeight) / 2\n case 'bottom':\n return parentRect.top - tooltipHeight - outerMargin\n }\n}\n\nconst BALLOON_ARROW_POSITION = 29 // length between Balloon edge and center of arrow\n\nfunction getLeft({\n parentRect,\n tooltipWidth,\n horizontal,\n vertical,\n isIcon,\n outerMargin,\n}: {\n parentRect: DOMRect\n tooltipWidth: number\n horizontal: 'left' | 'center' | 'right'\n vertical: 'top' | 'middle' | 'bottom'\n isIcon: boolean\n outerMargin: number\n}): number {\n switch (vertical) {\n case 'middle':\n switch (horizontal) {\n case 'right':\n return parentRect.left - tooltipWidth - outerMargin\n default:\n return parentRect.left + parentRect.width + outerMargin\n }\n case 'top':\n case 'bottom': {\n const iconGap = isIcon ? BALLOON_ARROW_POSITION - parentRect.width / 2 : 0 // to align center of Balloon arrow and icon\n\n switch (horizontal) {\n case 'right':\n return parentRect.left + parentRect.width - tooltipWidth + iconGap\n case 'center':\n return parentRect.left + (parentRect.width - tooltipWidth) / 2\n case 'left':\n return parentRect.left - iconGap\n }\n }\n }\n}\n"],"names":[],"mappings":"SAAgB,cAAc,CAAC,EAC7B,UAAU,EACV,YAAY,EACZ,WAAW,EACX,QAAQ,EACR,UAAU,EACV,MAAM,GAAG,KAAK,EACd,WAAW,GASZ,EAAA;IACC,MAAM,GAAG,GAAG,MAAM,CAAC;QACjB,UAAU;QACV,aAAa,EAAE,WAAW,CAAC,MAAM;QACjC,QAAQ;QACR,WAAW;AACZ,KAAA,CAAC;IACF,MAAM,IAAI,GAAG,OAAO,CAAC;QACnB,UAAU;QACV,YAAY,EAAE,WAAW,CAAC,KAAK;QAC/B,UAAU;QACV,QAAQ;QACR,MAAM;QACN,WAAW;AACZ,KAAA,CAAC;IAEF,OAAO;AACL,QAAA,GAAG,EAAE,GAAG,GAAG,YAAY,CAAC,GAAG;AAC3B,QAAA,IAAI,EAAE,IAAI,GAAG,YAAY,CAAC,IAAI;QAC9B,MAAM,EAAE,WAAW,CAAC,KAAK;QACzB,OAAO,EAAE,WAAW,CAAC,MAAM;KAC5B;AACH;AAEA,SAAS,MAAM,CAAC,EACd,UAAU,EACV,aAAa,EACb,QAAQ,EACR,WAAW,GAMZ,EAAA;IACC,QAAQ,QAAQ;AACd,QAAA,KAAK,KAAK;YACR,OAAO,UAAU,CAAC,GAAG,GAAG,UAAU,CAAC,MAAM,GAAG,WAAW;AACzD,QAAA,KAAK,QAAQ;AACX,YAAA,OAAO,UAAU,CAAC,GAAG,GAAG,CAAC,UAAU,CAAC,MAAM,GAAG,aAAa,IAAI,CAAC;AACjE,QAAA,KAAK,QAAQ;AACX,YAAA,OAAO,UAAU,CAAC,GAAG,GAAG,aAAa,GAAG,WAAW;;AAEzD;AAEA,MAAM,sBAAsB,GAAG,EAAE,CAAA;AAEjC,SAAS,OAAO,CAAC,EACf,UAAU,EACV,YAAY,EACZ,UAAU,EACV,QAAQ,EACR,MAAM,EACN,WAAW,GAQZ,EAAA;IACC,QAAQ,QAAQ;AACd,QAAA,KAAK,QAAQ;YACX,QAAQ,UAAU;AAChB,gBAAA,KAAK,OAAO;AACV,oBAAA,OAAO,UAAU,CAAC,IAAI,GAAG,YAAY,GAAG,WAAW;AACrD,gBAAA;oBACE,OAAO,UAAU,CAAC,IAAI,GAAG,UAAU,CAAC,KAAK,GAAG,WAAW;;AAE7D,QAAA,KAAK,KAAK;QACV,KAAK,QAAQ,EAAE;AACb,YAAA,MAAM,OAAO,GAAG,MAAM,GAAG,sBAAsB,GAAG,UAAU,CAAC,KAAK,GAAG,CAAC,GAAG,CAAC,CAAA;YAE1E,QAAQ,UAAU;AAChB,gBAAA,KAAK,OAAO;oBACV,OAAO,UAAU,CAAC,IAAI,GAAG,UAAU,CAAC,KAAK,GAAG,YAAY,GAAG,OAAO;AACpE,gBAAA,KAAK,QAAQ;AACX,oBAAA,OAAO,UAAU,CAAC,IAAI,GAAG,CAAC,UAAU,CAAC,KAAK,GAAG,YAAY,IAAI,CAAC;AAChE,gBAAA,KAAK,MAAM;AACT,oBAAA,OAAO,UAAU,CAAC,IAAI,GAAG,OAAO;;QAEtC;;AAEJ;;;;"}
@@ -13,14 +13,13 @@ const handleShowWareki = (date, locale) => {
13
13
  return null;
14
14
  }
15
15
  // 和暦を使う
16
- const calendarLocale = `${locale}-u-ca-japanese`;
17
- return date.toLocaleDateString(calendarLocale, {
16
+ return date.toLocaleDateString(`${locale}-u-ca-japanese`, {
18
17
  dateStyle: 'long',
19
18
  });
20
19
  };
21
20
  const WarekiPicker = (props) => {
22
21
  const { locale } = intl_useIntl.useIntl();
23
- return jsxRuntime.jsx(components_DatePicker_DatePicker.DatePicker, { ...props, showAlternative: (date) => handleShowWareki(date, locale) });
22
+ return (jsxRuntime.jsx(components_DatePicker_DatePicker.DatePicker, { ...props, showAlternative: (date) => handleShowWareki(date, locale) }));
24
23
  };
25
24
 
26
25
  exports.WarekiPicker = WarekiPicker;
@@ -1 +1 @@
1
- {"version":3,"file":"WarekiPicker.cjs","sources":["../../../src/components/WarekiPicker/WarekiPicker.tsx"],"sourcesContent":["import { useIntl } from '../../intl'\nimport { DatePicker } from '../DatePicker'\n\nimport type { ComponentProps, FC } from 'react'\n\ntype Props = Omit<ComponentProps<typeof DatePicker>, 'showAlternative'>\n\nconst handleShowWareki = (date: Date | null, locale: string) => {\n if (!date) {\n return null\n }\n\n // 和暦を使う\n const calendarLocale = `${locale}-u-ca-japanese`\n\n return date.toLocaleDateString(calendarLocale, {\n dateStyle: 'long',\n })\n}\n\nexport const WarekiPicker: FC<Props> = (props) => {\n const { locale } = useIntl()\n\n return <DatePicker {...props} showAlternative={(date) => handleShowWareki(date, locale)} />\n}\n"],"names":["useIntl","_jsx","DatePicker"],"mappings":";;;;;;;;;;AAOA,MAAM,gBAAgB,GAAG,CAAC,IAAiB,EAAE,MAAc,KAAI;IAC7D,IAAI,CAAC,IAAI,EAAE;AACT,QAAA,OAAO,IAAI;IACb;;AAGA,IAAA,MAAM,cAAc,GAAG,CAAA,EAAG,MAAM,gBAAgB;AAEhD,IAAA,OAAO,IAAI,CAAC,kBAAkB,CAAC,cAAc,EAAE;AAC7C,QAAA,SAAS,EAAE,MAAM;AAClB,KAAA,CAAC;AACJ,CAAC;AAEM,MAAM,YAAY,GAAc,CAAC,KAAK,KAAI;AAC/C,IAAA,MAAM,EAAE,MAAM,EAAE,GAAGA,oBAAO,EAAE;AAE5B,IAAA,OAAOC,eAACC,2CAAU,EAAA,EAAA,GAAK,KAAK,EAAE,eAAe,EAAE,CAAC,IAAI,KAAK,gBAAgB,CAAC,IAAI,EAAE,MAAM,CAAC,GAAI;AAC7F;;;;"}
1
+ {"version":3,"file":"WarekiPicker.cjs","sources":["../../../src/components/WarekiPicker/WarekiPicker.tsx"],"sourcesContent":["import { useIntl } from '../../intl'\nimport { DatePicker } from '../DatePicker'\n\nimport type { ComponentProps, FC } from 'react'\n\ntype Props = Omit<ComponentProps<typeof DatePicker>, 'showAlternative'>\n\nconst handleShowWareki = (date: Date | null, locale: string) => {\n if (!date) {\n return null\n }\n\n // 和暦を使う\n return date.toLocaleDateString(`${locale}-u-ca-japanese`, {\n dateStyle: 'long',\n })\n}\n\nexport const WarekiPicker: FC<Props> = (props) => {\n const { locale } = useIntl()\n\n return (\n <DatePicker\n {...props}\n showAlternative={(date: Date | null) => handleShowWareki(date, locale)}\n />\n )\n}\n"],"names":["useIntl","_jsx","DatePicker"],"mappings":";;;;;;;;;;AAOA,MAAM,gBAAgB,GAAG,CAAC,IAAiB,EAAE,MAAc,KAAI;IAC7D,IAAI,CAAC,IAAI,EAAE;AACT,QAAA,OAAO,IAAI;IACb;;AAGA,IAAA,OAAO,IAAI,CAAC,kBAAkB,CAAC,CAAA,EAAG,MAAM,gBAAgB,EAAE;AACxD,QAAA,SAAS,EAAE,MAAM;AAClB,KAAA,CAAC;AACJ,CAAC;AAEM,MAAM,YAAY,GAAc,CAAC,KAAK,KAAI;AAC/C,IAAA,MAAM,EAAE,MAAM,EAAE,GAAGA,oBAAO,EAAE;IAE5B,QACEC,eAACC,2CAAU,EAAA,EAAA,GACL,KAAK,EACT,eAAe,EAAE,CAAC,IAAiB,KAAK,gBAAgB,CAAC,IAAI,EAAE,MAAM,CAAC,EAAA,CACtE;AAEN;;;;"}
@@ -11,14 +11,13 @@ const handleShowWareki = (date, locale) => {
11
11
  return null;
12
12
  }
13
13
  // 和暦を使う
14
- const calendarLocale = `${locale}-u-ca-japanese`;
15
- return date.toLocaleDateString(calendarLocale, {
14
+ return date.toLocaleDateString(`${locale}-u-ca-japanese`, {
16
15
  dateStyle: 'long',
17
16
  });
18
17
  };
19
18
  const WarekiPicker = (props) => {
20
19
  const { locale } = useIntl();
21
- return jsx(DatePicker, { ...props, showAlternative: (date) => handleShowWareki(date, locale) });
20
+ return (jsx(DatePicker, { ...props, showAlternative: (date) => handleShowWareki(date, locale) }));
22
21
  };
23
22
 
24
23
  export { WarekiPicker };
@@ -1 +1 @@
1
- {"version":3,"file":"WarekiPicker.js","sources":["../../../src/components/WarekiPicker/WarekiPicker.tsx"],"sourcesContent":["import { useIntl } from '../../intl'\nimport { DatePicker } from '../DatePicker'\n\nimport type { ComponentProps, FC } from 'react'\n\ntype Props = Omit<ComponentProps<typeof DatePicker>, 'showAlternative'>\n\nconst handleShowWareki = (date: Date | null, locale: string) => {\n if (!date) {\n return null\n }\n\n // 和暦を使う\n const calendarLocale = `${locale}-u-ca-japanese`\n\n return date.toLocaleDateString(calendarLocale, {\n dateStyle: 'long',\n })\n}\n\nexport const WarekiPicker: FC<Props> = (props) => {\n const { locale } = useIntl()\n\n return <DatePicker {...props} showAlternative={(date) => handleShowWareki(date, locale)} />\n}\n"],"names":["_jsx"],"mappings":";;;;;;;;AAOA,MAAM,gBAAgB,GAAG,CAAC,IAAiB,EAAE,MAAc,KAAI;IAC7D,IAAI,CAAC,IAAI,EAAE;AACT,QAAA,OAAO,IAAI;IACb;;AAGA,IAAA,MAAM,cAAc,GAAG,CAAA,EAAG,MAAM,gBAAgB;AAEhD,IAAA,OAAO,IAAI,CAAC,kBAAkB,CAAC,cAAc,EAAE;AAC7C,QAAA,SAAS,EAAE,MAAM;AAClB,KAAA,CAAC;AACJ,CAAC;AAEM,MAAM,YAAY,GAAc,CAAC,KAAK,KAAI;AAC/C,IAAA,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,EAAE;AAE5B,IAAA,OAAOA,IAAC,UAAU,EAAA,EAAA,GAAK,KAAK,EAAE,eAAe,EAAE,CAAC,IAAI,KAAK,gBAAgB,CAAC,IAAI,EAAE,MAAM,CAAC,GAAI;AAC7F;;;;"}
1
+ {"version":3,"file":"WarekiPicker.js","sources":["../../../src/components/WarekiPicker/WarekiPicker.tsx"],"sourcesContent":["import { useIntl } from '../../intl'\nimport { DatePicker } from '../DatePicker'\n\nimport type { ComponentProps, FC } from 'react'\n\ntype Props = Omit<ComponentProps<typeof DatePicker>, 'showAlternative'>\n\nconst handleShowWareki = (date: Date | null, locale: string) => {\n if (!date) {\n return null\n }\n\n // 和暦を使う\n return date.toLocaleDateString(`${locale}-u-ca-japanese`, {\n dateStyle: 'long',\n })\n}\n\nexport const WarekiPicker: FC<Props> = (props) => {\n const { locale } = useIntl()\n\n return (\n <DatePicker\n {...props}\n showAlternative={(date: Date | null) => handleShowWareki(date, locale)}\n />\n )\n}\n"],"names":["_jsx"],"mappings":";;;;;;;;AAOA,MAAM,gBAAgB,GAAG,CAAC,IAAiB,EAAE,MAAc,KAAI;IAC7D,IAAI,CAAC,IAAI,EAAE;AACT,QAAA,OAAO,IAAI;IACb;;AAGA,IAAA,OAAO,IAAI,CAAC,kBAAkB,CAAC,CAAA,EAAG,MAAM,gBAAgB,EAAE;AACxD,QAAA,SAAS,EAAE,MAAM;AAClB,KAAA,CAAC;AACJ,CAAC;AAEM,MAAM,YAAY,GAAc,CAAC,KAAK,KAAI;AAC/C,IAAA,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,EAAE;IAE5B,QACEA,IAAC,UAAU,EAAA,EAAA,GACL,KAAK,EACT,eAAe,EAAE,CAAC,IAAiB,KAAK,gBAAgB,CAAC,IAAI,EAAE,MAAM,CAAC,EAAA,CACtE;AAEN;;;;"}
@@ -6,12 +6,12 @@ require('./themes/createSpacing.cjs');
6
6
  require('./_virtual/index.cjs');
7
7
  require('./_virtual/index2.cjs');
8
8
  require('./themes/createColor.cjs');
9
+ require('./themes/createTextColor.cjs');
10
+ require('styled-components');
9
11
  require('./themes/createShadow/defaultShadow.cjs');
10
12
  var themes_createWidth = require('./themes/createWidth.cjs');
11
13
  require('./themes/createBackgroundColor.cjs');
12
14
  require('./themes/createBorder.cjs');
13
- require('styled-components');
14
- require('./themes/createTextColor.cjs');
15
15
 
16
16
  const DEFAULT_WIDTH_KEYS = Object.keys(themes_createWidth.defaultWidth);
17
17
  index.defaultConfig.twMergeConfig = {
@@ -4,12 +4,12 @@ import './themes/createSpacing.js';
4
4
  import './_virtual/index.js';
5
5
  import './_virtual/index2.js';
6
6
  import './themes/createColor.js';
7
+ import './themes/createTextColor.js';
8
+ import 'styled-components';
7
9
  import './themes/createShadow/defaultShadow.js';
8
10
  import { defaultWidth } from './themes/createWidth.js';
9
11
  import './themes/createBackgroundColor.js';
10
12
  import './themes/createBorder.js';
11
- import 'styled-components';
12
- import './themes/createTextColor.js';
13
13
 
14
14
  const DEFAULT_WIDTH_KEYS = Object.keys(defaultWidth);
15
15
  ie.twMergeConfig = {
@@ -7,13 +7,13 @@ require('../../themes/createSpacing.cjs');
7
7
  require('../../_virtual/index.cjs');
8
8
  require('../../_virtual/index2.cjs');
9
9
  require('../../themes/createColor.cjs');
10
+ require('../../themes/createTextColor.cjs');
11
+ require('styled-components');
10
12
  require('../../themes/createShadow/defaultShadow.cjs');
11
13
  require('../../themes/createWidth.cjs');
12
14
  var themes_createBreakpoint = require('../../themes/createBreakpoint.cjs');
13
15
  require('../../themes/createBackgroundColor.cjs');
14
16
  require('../../themes/createBorder.cjs');
15
- require('styled-components');
16
- require('../../themes/createTextColor.cjs');
17
17
  var hooks_useDevice_useDevice = require('./useDevice.cjs');
18
18
 
19
19
  const mediaQuery = {
@@ -5,13 +5,13 @@ import '../../themes/createSpacing.js';
5
5
  import '../../_virtual/index.js';
6
6
  import '../../_virtual/index2.js';
7
7
  import '../../themes/createColor.js';
8
+ import '../../themes/createTextColor.js';
9
+ import 'styled-components';
8
10
  import '../../themes/createShadow/defaultShadow.js';
9
11
  import '../../themes/createWidth.js';
10
12
  import { defaultBreakpoint } from '../../themes/createBreakpoint.js';
11
13
  import '../../themes/createBackgroundColor.js';
12
14
  import '../../themes/createBorder.js';
13
- import 'styled-components';
14
- import '../../themes/createTextColor.js';
15
15
  import { DeviceContext } from './useDevice.js';
16
16
 
17
17
  const mediaQuery = {
@@ -8,12 +8,12 @@ require('../../themes/createSpacing.cjs');
8
8
  require('../../_virtual/index.cjs');
9
9
  require('../../_virtual/index2.cjs');
10
10
  require('../../themes/createColor.cjs');
11
+ require('../../themes/createTextColor.cjs');
12
+ require('styled-components');
11
13
  require('../../themes/createShadow/defaultShadow.cjs');
12
14
  require('../../themes/createWidth.cjs');
13
15
  require('../../themes/createBackgroundColor.cjs');
14
16
  require('../../themes/createBorder.cjs');
15
- require('styled-components');
16
- require('../../themes/createTextColor.cjs');
17
17
  var hooks_useMediaQueries_useMediaQueries = require('../useMediaQueries/useMediaQueries.cjs');
18
18
  var hooks_useTheme = require('../useTheme.cjs');
19
19
  var hooks_useEnvironment_useEnvironment = require('./useEnvironment.cjs');