@mittwald/flow-react-components 0.2.0-alpha.976 → 0.2.0-alpha.977

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 (86) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/dist/assets/doc-properties.json +11808 -6283
  3. package/dist/css/all-layered.css +1 -1
  4. package/dist/css/all.css +1 -1
  5. package/dist/js/_virtual/_.locale.json@7a653b01c4df8873ee850d41727b7e3c.mjs +12 -0
  6. package/dist/js/_virtual/_.locale.json@7a653b01c4df8873ee850d41727b7e3c.mjs.map +1 -0
  7. package/dist/js/default.mjs +1 -0
  8. package/dist/js/default.mjs.map +1 -1
  9. package/dist/js/flr-universal.mjs +1 -0
  10. package/dist/js/flr-universal.mjs.map +1 -1
  11. package/dist/js/packages/components/src/components/LayoutCard/LayoutCard.mjs +2 -2
  12. package/dist/js/packages/components/src/components/LayoutCard/LayoutCard.mjs.map +1 -1
  13. package/dist/js/packages/components/src/components/LayoutCard/LayoutCard.module.scss.mjs +3 -3
  14. package/dist/js/packages/components/src/components/MenuItem/MenuItem.mjs +3 -0
  15. package/dist/js/packages/components/src/components/MenuItem/MenuItem.mjs.map +1 -1
  16. package/dist/js/packages/components/src/components/TabNavigation/TabNavigation.mjs +74 -0
  17. package/dist/js/packages/components/src/components/TabNavigation/TabNavigation.mjs.map +1 -0
  18. package/dist/js/packages/components/src/components/TabNavigation/TabNavigation.module.scss.mjs +21 -0
  19. package/dist/js/packages/components/src/components/TabNavigation/TabNavigation.module.scss.mjs.map +1 -0
  20. package/dist/js/packages/components/src/components/TabNavigation/components/LinkContent/LinkContent.mjs +46 -0
  21. package/dist/js/packages/components/src/components/TabNavigation/components/LinkContent/LinkContent.mjs.map +1 -0
  22. package/dist/js/packages/components/src/components/TabNavigation/lib/getVisibleItemCount.mjs +22 -0
  23. package/dist/js/packages/components/src/components/TabNavigation/lib/getVisibleItemCount.mjs.map +1 -0
  24. package/dist/js/packages/components/src/components/TabNavigation/lib/useCollapsingItems.mjs +65 -0
  25. package/dist/js/packages/components/src/components/TabNavigation/lib/useCollapsingItems.mjs.map +1 -0
  26. package/dist/js/packages/components/src/components/Tabs/components/TabList/TabList.mjs +20 -2
  27. package/dist/js/packages/components/src/components/Tabs/components/TabList/TabList.mjs.map +1 -1
  28. package/dist/js/packages/components/src/components/Tabs/components/TabList/TabList.module.scss.mjs +5 -1
  29. package/dist/js/packages/components/src/components/Tabs/components/TabList/TabList.module.scss.mjs.map +1 -1
  30. package/dist/js/packages/components/src/components/Tabs/lib/useTabIndicator.mjs +61 -0
  31. package/dist/js/packages/components/src/components/Tabs/lib/useTabIndicator.mjs.map +1 -0
  32. package/dist/js/packages/components/src/components/propTypes/index.mjs +1 -0
  33. package/dist/js/packages/components/src/components/propTypes/index.mjs.map +1 -1
  34. package/dist/js/packages/components/src/lib/dom/createFrameResizeObserver.mjs +34 -0
  35. package/dist/js/packages/components/src/lib/dom/createFrameResizeObserver.mjs.map +1 -0
  36. package/dist/js/packages/components/src/lib/hooks/dom/useObserveOverflow.mjs +54 -29
  37. package/dist/js/packages/components/src/lib/hooks/dom/useObserveOverflow.mjs.map +1 -1
  38. package/dist/js/packages/components/src/status/component-status.json.mjs +1 -0
  39. package/dist/js/packages/components/src/status/component-status.json.mjs.map +1 -1
  40. package/dist/js/packages/design-tokens/dist/json/all-dark.json.mjs +2 -1
  41. package/dist/js/packages/design-tokens/dist/json/all-dark.json.mjs.map +1 -1
  42. package/dist/js/packages/design-tokens/dist/json/all-light.json.mjs +2 -1
  43. package/dist/js/packages/design-tokens/dist/json/all-light.json.mjs.map +1 -1
  44. package/dist/types/components/LayoutCard/stories/Default.stories.d.ts +1 -1
  45. package/dist/types/components/LayoutCard/stories/Default.stories.d.ts.map +1 -1
  46. package/dist/types/components/MenuItem/MenuItem.d.ts +2 -0
  47. package/dist/types/components/MenuItem/MenuItem.d.ts.map +1 -1
  48. package/dist/types/components/TabNavigation/TabNavigation.browser.test.d.ts +2 -0
  49. package/dist/types/components/TabNavigation/TabNavigation.browser.test.d.ts.map +1 -0
  50. package/dist/types/components/TabNavigation/TabNavigation.d.ts +12 -0
  51. package/dist/types/components/TabNavigation/TabNavigation.d.ts.map +1 -0
  52. package/dist/types/components/TabNavigation/components/LinkContent/LinkContent.d.ts +13 -0
  53. package/dist/types/components/TabNavigation/components/LinkContent/LinkContent.d.ts.map +1 -0
  54. package/dist/types/components/TabNavigation/components/LinkContent/index.d.ts +3 -0
  55. package/dist/types/components/TabNavigation/components/LinkContent/index.d.ts.map +1 -0
  56. package/dist/types/components/TabNavigation/index.d.ts +4 -0
  57. package/dist/types/components/TabNavigation/index.d.ts.map +1 -0
  58. package/dist/types/components/TabNavigation/lib/getVisibleItemCount.d.ts +2 -0
  59. package/dist/types/components/TabNavigation/lib/getVisibleItemCount.d.ts.map +1 -0
  60. package/dist/types/components/TabNavigation/lib/getVisibleItemCount.test.d.ts +2 -0
  61. package/dist/types/components/TabNavigation/lib/getVisibleItemCount.test.d.ts.map +1 -0
  62. package/dist/types/components/TabNavigation/lib/useCollapsingItems.d.ts +24 -0
  63. package/dist/types/components/TabNavigation/lib/useCollapsingItems.d.ts.map +1 -0
  64. package/dist/types/components/TabNavigation/stories/Default.stories.d.ts +7 -0
  65. package/dist/types/components/TabNavigation/stories/Default.stories.d.ts.map +1 -0
  66. package/dist/types/components/TabNavigation/view.d.ts +8 -0
  67. package/dist/types/components/TabNavigation/view.d.ts.map +1 -0
  68. package/dist/types/components/Tabs/components/TabList/TabList.d.ts.map +1 -1
  69. package/dist/types/components/Tabs/lib/useTabIndicator.d.ts +13 -0
  70. package/dist/types/components/Tabs/lib/useTabIndicator.d.ts.map +1 -0
  71. package/dist/types/components/propTypes/index.d.ts +2 -0
  72. package/dist/types/components/propTypes/index.d.ts.map +1 -1
  73. package/dist/types/components/public.d.ts +1 -0
  74. package/dist/types/components/public.d.ts.map +1 -1
  75. package/dist/types/lib/dom/createFrameResizeObserver.browser.test.d.ts +2 -0
  76. package/dist/types/lib/dom/createFrameResizeObserver.browser.test.d.ts.map +1 -0
  77. package/dist/types/lib/dom/createFrameResizeObserver.d.ts +27 -0
  78. package/dist/types/lib/dom/createFrameResizeObserver.d.ts.map +1 -0
  79. package/dist/types/lib/hooks/dom/useObserveOverflow.d.ts +7 -2
  80. package/dist/types/lib/hooks/dom/useObserveOverflow.d.ts.map +1 -1
  81. package/dist/types/lib/theming/hooks/useDesignTokens.d.ts +226 -3
  82. package/dist/types/lib/theming/hooks/useDesignTokens.d.ts.map +1 -1
  83. package/dist/types/status/component-status.json.d.ts +4 -0
  84. package/dist/types/views/TabNavigationView.d.ts +5 -0
  85. package/dist/types/views/TabNavigationView.d.ts.map +1 -0
  86. package/package.json +6 -6
@@ -0,0 +1,12 @@
1
+ "use client"
2
+ /* */
3
+ const locales = {"de-DE":{
4
+ "moreButton.title": "Weitere"
5
+ }
6
+ ,"en-US":{
7
+ "moreButton.title": "More"
8
+ }
9
+ };
10
+
11
+ export { locales as default };
12
+ //# sourceMappingURL=_.locale.json@7a653b01c4df8873ee850d41727b7e3c.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"_.locale.json@7a653b01c4df8873ee850d41727b7e3c.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;"}
@@ -73,6 +73,7 @@ export { Flex } from './packages/components/src/components/Flex/Flex.mjs';
73
73
  export { Header } from './packages/components/src/components/Header/Header.mjs';
74
74
  export { HeaderNavigation } from './packages/components/src/components/HeaderNavigation/HeaderNavigation.mjs';
75
75
  export { Heading } from './packages/components/src/components/Heading/Heading.mjs';
76
+ export { TabNavigation } from './packages/components/src/components/TabNavigation/TabNavigation.mjs';
76
77
  export { iconCategories } from '@mittwald/flow-icons';
77
78
  export { IconSetProvider } from './packages/components/src/components/Icon/components/IconSetProvider.mjs';
78
79
  export { Icon } from './packages/components/src/components/Icon/Icon.mjs';
@@ -1 +1 @@
1
- {"version":3,"file":"default.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"default.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -206,6 +206,7 @@ import './packages/components/src/components/FileCardList/FileCardList.mjs';
206
206
  import './packages/components/src/components/FileDropZone/FileDropZone.mjs';
207
207
  import './packages/components/src/components/FileField/FileField.mjs';
208
208
  import './packages/components/src/components/Header/Header.mjs';
209
+ import './packages/components/src/components/TabNavigation/TabNavigation.mjs';
209
210
  import '@mittwald/flow-icons';
210
211
  import './packages/components/src/components/Icon/components/IconSetProvider.mjs';
211
212
  import './packages/components/src/components/Icon/Icon.mjs';
@@ -1 +1 @@
1
- {"version":3,"file":"flr-universal.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"flr-universal.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -14,8 +14,8 @@ const LayoutCard = flowComponent(
14
14
  const rootClassName = clsx(styles.layoutCard, className);
15
15
  const Element = elementType;
16
16
  const propsContext = {
17
- Tabs: {
18
- className: styles.tabs
17
+ TabNavigation: {
18
+ className: styles.tabNavigation
19
19
  },
20
20
  AccentBox: { className: styles.accentBox }
21
21
  };
@@ -1 +1 @@
1
- {"version":3,"file":"LayoutCard.mjs","sources":["../../../../../../../src/components/LayoutCard/LayoutCard.tsx"],"sourcesContent":["import type { PropsWithChildren } from \"react\";\nimport styles from \"./LayoutCard.module.scss\";\nimport clsx from \"clsx\";\nimport type { PropsWithElementType } from \"@/lib/types/props\";\nimport type { FlowComponentProps } from \"@/lib/componentFactory/flowComponent\";\nimport { flowComponent } from \"@/lib/componentFactory/flowComponent\";\nimport type { PropsContext } from \"@/lib/propsContext\";\nimport { PropsContextProvider } from \"@/lib/propsContext\";\n\nexport interface LayoutCardProps\n extends\n PropsWithChildren,\n PropsWithElementType<\"div\" | \"main\" | \"footer\" | \"header\">,\n FlowComponentProps {}\n\n/** @flr-generate all */\nexport const LayoutCard = flowComponent(\n \"LayoutCard\",\n (props) => {\n const { children, className, elementType = \"div\", ref, ...rest } = props;\n\n const rootClassName = clsx(styles.layoutCard, className);\n\n const Element = elementType;\n\n const propsContext: PropsContext = {\n Tabs: {\n className: styles.tabs,\n },\n AccentBox: { className: styles.accentBox },\n };\n\n return (\n <Element className={rootClassName} {...rest} ref={ref}>\n <PropsContextProvider props={propsContext}>\n {children}\n </PropsContextProvider>\n </Element>\n );\n },\n { type: \"layout\" },\n);\n\nexport default LayoutCard;\n"],"names":[],"mappings":";;;;;;;AAgBO,MAAM,UAAA,GAAa,aAAA;AAAA,EACxB,YAAA;AAAA,EACA,CAAC,KAAA,KAAU;AACT,IAAA,MAAM,EAAE,UAAU,SAAA,EAAW,WAAA,GAAc,OAAO,GAAA,EAAK,GAAG,MAAK,GAAI,KAAA;AAEnE,IAAA,MAAM,aAAA,GAAgB,IAAA,CAAK,MAAA,CAAO,UAAA,EAAY,SAAS,CAAA;AAEvD,IAAA,MAAM,OAAA,GAAU,WAAA;AAEhB,IAAA,MAAM,YAAA,GAA6B;AAAA,MACjC,IAAA,EAAM;AAAA,QACJ,WAAW,MAAA,CAAO;AAAA,OACpB;AAAA,MACA,SAAA,EAAW,EAAE,SAAA,EAAW,MAAA,CAAO,SAAA;AAAU,KAC3C;AAEA,IAAA,uBACE,GAAA,CAAC,OAAA,EAAA,EAAQ,SAAA,EAAW,aAAA,EAAgB,GAAG,IAAA,EAAM,GAAA,EAC3C,QAAA,kBAAA,GAAA,CAAC,oBAAA,EAAA,EAAqB,KAAA,EAAO,YAAA,EAC1B,QAAA,EACH,CAAA,EACF,CAAA;AAAA,EAEJ,CAAA;AAAA,EACA,EAAE,MAAM,QAAA;AACV;;;;"}
1
+ {"version":3,"file":"LayoutCard.mjs","sources":["../../../../../../../src/components/LayoutCard/LayoutCard.tsx"],"sourcesContent":["import type { PropsWithChildren } from \"react\";\nimport styles from \"./LayoutCard.module.scss\";\nimport clsx from \"clsx\";\nimport type { PropsWithElementType } from \"@/lib/types/props\";\nimport type { FlowComponentProps } from \"@/lib/componentFactory/flowComponent\";\nimport { flowComponent } from \"@/lib/componentFactory/flowComponent\";\nimport type { PropsContext } from \"@/lib/propsContext\";\nimport { PropsContextProvider } from \"@/lib/propsContext\";\n\nexport interface LayoutCardProps\n extends\n PropsWithChildren,\n PropsWithElementType<\"div\" | \"main\" | \"footer\" | \"header\">,\n FlowComponentProps {}\n\n/** @flr-generate all */\nexport const LayoutCard = flowComponent(\n \"LayoutCard\",\n (props) => {\n const { children, className, elementType = \"div\", ref, ...rest } = props;\n\n const rootClassName = clsx(styles.layoutCard, className);\n\n const Element = elementType;\n\n const propsContext: PropsContext = {\n TabNavigation: {\n className: styles.tabNavigation,\n },\n AccentBox: { className: styles.accentBox },\n };\n\n return (\n <Element className={rootClassName} {...rest} ref={ref}>\n <PropsContextProvider props={propsContext}>\n {children}\n </PropsContextProvider>\n </Element>\n );\n },\n { type: \"layout\" },\n);\n\nexport default LayoutCard;\n"],"names":[],"mappings":";;;;;;;AAgBO,MAAM,UAAA,GAAa,aAAA;AAAA,EACxB,YAAA;AAAA,EACA,CAAC,KAAA,KAAU;AACT,IAAA,MAAM,EAAE,UAAU,SAAA,EAAW,WAAA,GAAc,OAAO,GAAA,EAAK,GAAG,MAAK,GAAI,KAAA;AAEnE,IAAA,MAAM,aAAA,GAAgB,IAAA,CAAK,MAAA,CAAO,UAAA,EAAY,SAAS,CAAA;AAEvD,IAAA,MAAM,OAAA,GAAU,WAAA;AAEhB,IAAA,MAAM,YAAA,GAA6B;AAAA,MACjC,aAAA,EAAe;AAAA,QACb,WAAW,MAAA,CAAO;AAAA,OACpB;AAAA,MACA,SAAA,EAAW,EAAE,SAAA,EAAW,MAAA,CAAO,SAAA;AAAU,KAC3C;AAEA,IAAA,uBACE,GAAA,CAAC,OAAA,EAAA,EAAQ,SAAA,EAAW,aAAA,EAAgB,GAAG,IAAA,EAAM,GAAA,EAC3C,QAAA,kBAAA,GAAA,CAAC,oBAAA,EAAA,EAAqB,KAAA,EAAO,YAAA,EAC1B,QAAA,EACH,CAAA,EACF,CAAA;AAAA,EAEJ,CAAA;AAAA,EACA,EAAE,MAAM,QAAA;AACV;;;;"}
@@ -1,13 +1,13 @@
1
1
  "use client"
2
2
  /* */
3
3
  const layoutCard = "flow--layout-card";
4
- const tabs = "flow--layout-card--tabs";
4
+ const tabNavigation = "flow--layout-card--tab-navigation";
5
5
  const accentBox = "flow--layout-card--accent-box";
6
6
  const styles = {
7
7
  layoutCard: layoutCard,
8
- tabs: tabs,
8
+ tabNavigation: tabNavigation,
9
9
  accentBox: accentBox
10
10
  };
11
11
 
12
- export { accentBox, styles as default, layoutCard, tabs };
12
+ export { accentBox, styles as default, layoutCard, tabNavigation };
13
13
  //# sourceMappingURL=LayoutCard.module.scss.mjs.map
@@ -36,11 +36,13 @@ const MenuItem = flowComponent("MenuItem", (props) => {
36
36
  id,
37
37
  ref,
38
38
  "aria-disabled": ariaDisabled,
39
+ "aria-current": ariaCurrent,
39
40
  isPending,
40
41
  isSucceeded,
41
42
  isFailed,
42
43
  ...rest
43
44
  } = props;
45
+ const currentProps = ariaCurrent && ariaCurrent !== "false" ? { "data-current": true } : {};
44
46
  const rootClassName = clsx(
45
47
  styles.menuItem,
46
48
  (ariaDisabled || isFailed || isSucceeded || isPending) && styles.ariaDisabled,
@@ -60,6 +62,7 @@ const MenuItem = flowComponent("MenuItem", (props) => {
60
62
  Aria.MenuItem,
61
63
  {
62
64
  ...rest,
65
+ ...currentProps,
63
66
  key: id,
64
67
  id,
65
68
  className: rootClassName,
@@ -1 +1 @@
1
- {"version":3,"file":"MenuItem.mjs","sources":["../../../../../../../src/components/MenuItem/MenuItem.tsx"],"sourcesContent":["import type { PropsWithChildren } from \"react\";\nimport * as Aria from \"react-aria-components\";\nimport styles from \"./MenuItem.module.scss\";\nimport clsx from \"clsx\";\nimport { MenuItemContent } from \"@/components/MenuItem/components/MenuItemContent/MenuItemContent\";\nimport type { FlowComponentProps } from \"@/lib/componentFactory/flowComponent\";\nimport { flowComponent } from \"@/lib/componentFactory/flowComponent\";\nimport { useAriaAnnounceActionState } from \"@/components/Action/lib/ariaLive\";\nimport { IconFailed, IconSucceeded } from \"@/components/Icon/components/icons\";\nimport LoadingSpinner from \"@/components/LoadingSpinner\";\n\nexport interface MenuItemProps\n extends\n Omit<Aria.MenuItemProps, \"children\">,\n PropsWithChildren,\n FlowComponentProps {\n selectionVariant?: \"control\" | \"navigation\" | \"switch\";\n /** Whether the button is in a pending state. */\n isPending?: boolean;\n /** Whether the button is in a succeeded state. */\n isSucceeded?: boolean;\n /** Whether the button is in a failed state. */\n isFailed?: boolean;\n /** Disables button but keeps it focusable. */\n \"aria-disabled\"?: boolean;\n}\n\nconst disablePendingProps = (props: MenuItemProps) => {\n if (\n props.isPending ||\n props.isSucceeded ||\n props.isFailed ||\n props[\"aria-disabled\"]\n ) {\n props = { ...props };\n props.onPress = undefined;\n props.onPressStart = undefined;\n props.onPressEnd = undefined;\n props.onPressChange = undefined;\n props.onPressUp = undefined;\n }\n\n return props;\n};\n\n/** @flr-generate all */\nexport const MenuItem = flowComponent(\"MenuItem\", (props) => {\n props = disablePendingProps(props);\n\n const {\n children,\n className,\n selectionVariant,\n id,\n ref,\n \"aria-disabled\": ariaDisabled,\n isPending,\n isSucceeded,\n isFailed,\n ...rest\n } = props;\n\n const rootClassName = clsx(\n styles.menuItem /**\n * Workaround warning: The Aria.MenuItem does not support \"aria-disabled\" by\n * now, so this MenuItem will be visually disabled via CSS.\n */,\n (ariaDisabled || isFailed || isSucceeded || isPending) &&\n styles.ariaDisabled,\n className,\n );\n\n useAriaAnnounceActionState(\n isPending\n ? \"isPending\"\n : isSucceeded\n ? \"isSucceeded\"\n : isFailed\n ? \"isFailed\"\n : \"isIdle\",\n );\n\n const StateIconComponent = isSucceeded\n ? IconSucceeded\n : isFailed\n ? IconFailed\n : isPending\n ? LoadingSpinner\n : undefined;\n\n const stateIcon = StateIconComponent && (\n <div className={styles.stateIcon}>\n <StateIconComponent\n status={isFailed ? \"danger\" : isSucceeded ? \"success\" : undefined}\n />\n </div>\n );\n\n return (\n <Aria.MenuItem\n {...rest}\n key={id}\n id={id}\n className={rootClassName}\n ref={ref}\n >\n {(props) => (\n <>\n <MenuItemContent {...props} selectionVariant={selectionVariant}>\n {children}\n </MenuItemContent>\n {stateIcon}\n </>\n )}\n </Aria.MenuItem>\n );\n});\n\nexport default MenuItem;\n"],"names":["props"],"mappings":";;;;;;;;;;;;;;;;AA2BA,MAAM,mBAAA,GAAsB,CAAC,KAAA,KAAyB;AACpD,EAAA,IACE,KAAA,CAAM,aACN,KAAA,CAAM,WAAA,IACN,MAAM,QAAA,IACN,KAAA,CAAM,eAAe,CAAA,EACrB;AACA,IAAA,KAAA,GAAQ,EAAE,GAAG,KAAA,EAAM;AACnB,IAAA,KAAA,CAAM,OAAA,GAAU,MAAA;AAChB,IAAA,KAAA,CAAM,YAAA,GAAe,MAAA;AACrB,IAAA,KAAA,CAAM,UAAA,GAAa,MAAA;AACnB,IAAA,KAAA,CAAM,aAAA,GAAgB,MAAA;AACtB,IAAA,KAAA,CAAM,SAAA,GAAY,MAAA;AAAA,EACpB;AAEA,EAAA,OAAO,KAAA;AACT,CAAA;AAGO,MAAM,QAAA,GAAW,aAAA,CAAc,UAAA,EAAY,CAAC,KAAA,KAAU;AAC3D,EAAA,KAAA,GAAQ,oBAAoB,KAAK,CAAA;AAEjC,EAAA,MAAM;AAAA,IACJ,QAAA;AAAA,IACA,SAAA;AAAA,IACA,gBAAA;AAAA,IACA,EAAA;AAAA,IACA,GAAA;AAAA,IACA,eAAA,EAAiB,YAAA;AAAA,IACjB,SAAA;AAAA,IACA,WAAA;AAAA,IACA,QAAA;AAAA,IACA,GAAG;AAAA,GACL,GAAI,KAAA;AAEJ,EAAA,MAAM,aAAA,GAAgB,IAAA;AAAA,IACpB,MAAA,CAAO,QAAA;AAAA,IAAA,CAIN,YAAA,IAAgB,QAAA,IAAY,WAAA,IAAe,SAAA,KAC1C,MAAA,CAAO,YAAA;AAAA,IACT;AAAA,GACF;AAEA,EAAA,0BAAA;AAAA,IACE,SAAA,GACI,WAAA,GACA,WAAA,GACE,aAAA,GACA,WACE,UAAA,GACA;AAAA,GACV;AAEA,EAAA,MAAM,qBAAqB,WAAA,GACvB,aAAA,GACA,QAAA,GACE,UAAA,GACA,YACE,cAAA,GACA,MAAA;AAER,EAAA,MAAM,YAAY,kBAAA,oBAChB,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,OAAO,SAAA,EACrB,QAAA,kBAAA,GAAA;AAAA,IAAC,kBAAA;AAAA,IAAA;AAAA,MACC,MAAA,EAAQ,QAAA,GAAW,QAAA,GAAW,WAAA,GAAc,SAAA,GAAY;AAAA;AAAA,GAC1D,EACF,CAAA;AAGF,EAAA,uBACE,aAAA;AAAA,IAAC,IAAA,CAAK,QAAA;AAAA,IAAL;AAAA,MACE,GAAG,IAAA;AAAA,MACJ,GAAA,EAAK,EAAA;AAAA,MACL,EAAA;AAAA,MACA,SAAA,EAAW,aAAA;AAAA,MACX;AAAA,KAAA;AAAA,IAEC,CAACA,2BACA,IAAA,CAAA,QAAA,EAAA,EACE,QAAA,EAAA;AAAA,sBAAA,GAAA,CAAC,eAAA,EAAA,EAAiB,GAAGA,MAAAA,EAAO,gBAAA,EACzB,QAAA,EACH,CAAA;AAAA,MACC;AAAA,KAAA,EACH;AAAA,GAEJ;AAEJ,CAAC;;;;"}
1
+ {"version":3,"file":"MenuItem.mjs","sources":["../../../../../../../src/components/MenuItem/MenuItem.tsx"],"sourcesContent":["import type { PropsWithChildren } from \"react\";\nimport * as Aria from \"react-aria-components\";\nimport styles from \"./MenuItem.module.scss\";\nimport clsx from \"clsx\";\nimport { MenuItemContent } from \"@/components/MenuItem/components/MenuItemContent/MenuItemContent\";\nimport type { FlowComponentProps } from \"@/lib/componentFactory/flowComponent\";\nimport { flowComponent } from \"@/lib/componentFactory/flowComponent\";\nimport { useAriaAnnounceActionState } from \"@/components/Action/lib/ariaLive\";\nimport { IconFailed, IconSucceeded } from \"@/components/Icon/components/icons\";\nimport LoadingSpinner from \"@/components/LoadingSpinner\";\n\nexport interface MenuItemProps\n extends\n Omit<Aria.MenuItemProps, \"children\">,\n PropsWithChildren,\n FlowComponentProps {\n selectionVariant?: \"control\" | \"navigation\" | \"switch\";\n /** Whether the button is in a pending state. */\n isPending?: boolean;\n /** Whether the button is in a succeeded state. */\n isSucceeded?: boolean;\n /** Whether the button is in a failed state. */\n isFailed?: boolean;\n /** Disables button but keeps it focusable. */\n \"aria-disabled\"?: boolean;\n /** Marks the menu item as referring to the currently active page. */\n \"aria-current\"?: string;\n}\n\nconst disablePendingProps = (props: MenuItemProps) => {\n if (\n props.isPending ||\n props.isSucceeded ||\n props.isFailed ||\n props[\"aria-disabled\"]\n ) {\n props = { ...props };\n props.onPress = undefined;\n props.onPressStart = undefined;\n props.onPressEnd = undefined;\n props.onPressChange = undefined;\n props.onPressUp = undefined;\n }\n\n return props;\n};\n\n/** @flr-generate all */\nexport const MenuItem = flowComponent(\"MenuItem\", (props) => {\n props = disablePendingProps(props);\n\n const {\n children,\n className,\n selectionVariant,\n id,\n ref,\n \"aria-disabled\": ariaDisabled,\n \"aria-current\": ariaCurrent,\n isPending,\n isSucceeded,\n isFailed,\n ...rest\n } = props;\n\n /**\n * React Aria drops `aria-current` from the props it forwards to the DOM, so\n * the current state is exposed as a data attribute (`data-*` passes the\n * filter) — that is what the `menuItem` styling matches on. Every\n * `aria-current` value marks the item as current, except an explicit\n * \"false\".\n */\n const currentProps =\n ariaCurrent && ariaCurrent !== \"false\" ? { \"data-current\": true } : {};\n\n const rootClassName = clsx(\n styles.menuItem /**\n * Workaround warning: The Aria.MenuItem does not support \"aria-disabled\" by\n * now, so this MenuItem will be visually disabled via CSS.\n */,\n (ariaDisabled || isFailed || isSucceeded || isPending) &&\n styles.ariaDisabled,\n className,\n );\n\n useAriaAnnounceActionState(\n isPending\n ? \"isPending\"\n : isSucceeded\n ? \"isSucceeded\"\n : isFailed\n ? \"isFailed\"\n : \"isIdle\",\n );\n\n const StateIconComponent = isSucceeded\n ? IconSucceeded\n : isFailed\n ? IconFailed\n : isPending\n ? LoadingSpinner\n : undefined;\n\n const stateIcon = StateIconComponent && (\n <div className={styles.stateIcon}>\n <StateIconComponent\n status={isFailed ? \"danger\" : isSucceeded ? \"success\" : undefined}\n />\n </div>\n );\n\n return (\n <Aria.MenuItem\n {...rest}\n {...currentProps}\n key={id}\n id={id}\n className={rootClassName}\n ref={ref}\n >\n {(props) => (\n <>\n <MenuItemContent {...props} selectionVariant={selectionVariant}>\n {children}\n </MenuItemContent>\n {stateIcon}\n </>\n )}\n </Aria.MenuItem>\n );\n});\n\nexport default MenuItem;\n"],"names":["props"],"mappings":";;;;;;;;;;;;;;;;AA6BA,MAAM,mBAAA,GAAsB,CAAC,KAAA,KAAyB;AACpD,EAAA,IACE,KAAA,CAAM,aACN,KAAA,CAAM,WAAA,IACN,MAAM,QAAA,IACN,KAAA,CAAM,eAAe,CAAA,EACrB;AACA,IAAA,KAAA,GAAQ,EAAE,GAAG,KAAA,EAAM;AACnB,IAAA,KAAA,CAAM,OAAA,GAAU,MAAA;AAChB,IAAA,KAAA,CAAM,YAAA,GAAe,MAAA;AACrB,IAAA,KAAA,CAAM,UAAA,GAAa,MAAA;AACnB,IAAA,KAAA,CAAM,aAAA,GAAgB,MAAA;AACtB,IAAA,KAAA,CAAM,SAAA,GAAY,MAAA;AAAA,EACpB;AAEA,EAAA,OAAO,KAAA;AACT,CAAA;AAGO,MAAM,QAAA,GAAW,aAAA,CAAc,UAAA,EAAY,CAAC,KAAA,KAAU;AAC3D,EAAA,KAAA,GAAQ,oBAAoB,KAAK,CAAA;AAEjC,EAAA,MAAM;AAAA,IACJ,QAAA;AAAA,IACA,SAAA;AAAA,IACA,gBAAA;AAAA,IACA,EAAA;AAAA,IACA,GAAA;AAAA,IACA,eAAA,EAAiB,YAAA;AAAA,IACjB,cAAA,EAAgB,WAAA;AAAA,IAChB,SAAA;AAAA,IACA,WAAA;AAAA,IACA,QAAA;AAAA,IACA,GAAG;AAAA,GACL,GAAI,KAAA;AASJ,EAAA,MAAM,YAAA,GACJ,eAAe,WAAA,KAAgB,OAAA,GAAU,EAAE,cAAA,EAAgB,IAAA,KAAS,EAAC;AAEvE,EAAA,MAAM,aAAA,GAAgB,IAAA;AAAA,IACpB,MAAA,CAAO,QAAA;AAAA,IAAA,CAIN,YAAA,IAAgB,QAAA,IAAY,WAAA,IAAe,SAAA,KAC1C,MAAA,CAAO,YAAA;AAAA,IACT;AAAA,GACF;AAEA,EAAA,0BAAA;AAAA,IACE,SAAA,GACI,WAAA,GACA,WAAA,GACE,aAAA,GACA,WACE,UAAA,GACA;AAAA,GACV;AAEA,EAAA,MAAM,qBAAqB,WAAA,GACvB,aAAA,GACA,QAAA,GACE,UAAA,GACA,YACE,cAAA,GACA,MAAA;AAER,EAAA,MAAM,YAAY,kBAAA,oBAChB,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,OAAO,SAAA,EACrB,QAAA,kBAAA,GAAA;AAAA,IAAC,kBAAA;AAAA,IAAA;AAAA,MACC,MAAA,EAAQ,QAAA,GAAW,QAAA,GAAW,WAAA,GAAc,SAAA,GAAY;AAAA;AAAA,GAC1D,EACF,CAAA;AAGF,EAAA,uBACE,aAAA;AAAA,IAAC,IAAA,CAAK,QAAA;AAAA,IAAL;AAAA,MACE,GAAG,IAAA;AAAA,MACH,GAAG,YAAA;AAAA,MACJ,GAAA,EAAK,EAAA;AAAA,MACL,EAAA;AAAA,MACA,SAAA,EAAW,aAAA;AAAA,MACX;AAAA,KAAA;AAAA,IAEC,CAACA,2BACA,IAAA,CAAA,QAAA,EAAA,EACE,QAAA,EAAA;AAAA,sBAAA,GAAA,CAAC,eAAA,EAAA,EAAiB,GAAGA,MAAAA,EAAO,gBAAA,EACzB,QAAA,EACH,CAAA;AAAA,MACC;AAAA,KAAA,EACH;AAAA,GAEJ;AAEJ,CAAC;;;;"}
@@ -0,0 +1,74 @@
1
+ "use client"
2
+ /* */
3
+ import { jsxs, jsx } from 'react/jsx-runtime';
4
+ import clsx from 'clsx';
5
+ import { Button } from '../Button/Button.mjs';
6
+ import 'react';
7
+ import '@mittwald/flow-icons';
8
+ import '../Icon/components/IconSetProvider.mjs';
9
+ import '../Icon/Icon.mjs';
10
+ import '../../views/IconView.mjs';
11
+ import { IconChevronDown } from '../Icon/components/icons/IconChevronDown.mjs';
12
+ import { Text } from '../Text/Text.mjs';
13
+ import '../TranslationProvider/TranslationProvider.mjs';
14
+ import { useLocalizedStringFormatter } from '../TranslationProvider/useLocalizedStringFormatter.mjs';
15
+ import { UiComponentTunnelExit } from '../UiComponentTunnel/UiComponentTunnelExit.mjs';
16
+ import { flowComponent } from '../../lib/componentFactory/flowComponent.mjs';
17
+ import { dynamic } from '../../lib/propsContext/dynamicProps/dynamic.mjs';
18
+ import '../../lib/propsContext/propsContext.mjs';
19
+ import { PropsContextProvider } from '../../lib/propsContext/components/PropsContextProvider.mjs';
20
+ import ContextMenuTriggerView from '../../views/ContextMenuTriggerView.mjs';
21
+ import ContextMenuView from '../../views/ContextMenuView.mjs';
22
+ import { LinkContent } from './components/LinkContent/LinkContent.mjs';
23
+ import styles from './TabNavigation.module.scss.mjs';
24
+ import locales from '../../../../../_virtual/_.locale.json@7a653b01c4df8873ee850d41727b7e3c.mjs';
25
+ import { useCollapsingItems } from './lib/useCollapsingItems.mjs';
26
+
27
+ const TabNavigation = flowComponent("TabNavigation", (props) => {
28
+ const { children, className, ref, ...rest } = props;
29
+ const stringFormatter = useLocalizedStringFormatter(locales, "TabNavigation");
30
+ const { listRef, moreRef, visibleCount, hasOverflow, menuHasCurrentItem } = useCollapsingItems();
31
+ const rootClassName = clsx(
32
+ styles.tabNavigation,
33
+ hasOverflow && styles.collapsed,
34
+ className
35
+ );
36
+ const propsContext = {
37
+ Link: {
38
+ wrapWith: /* @__PURE__ */ jsx("li", {}),
39
+ className: styles.link,
40
+ unstyled: true,
41
+ children: dynamic((linkProps) => /* @__PURE__ */ jsx(LinkContent, { linkProps }))
42
+ }
43
+ };
44
+ return /* @__PURE__ */ jsxs("nav", { className: rootClassName, role: "navigation", ...rest, ref, children: [
45
+ /* @__PURE__ */ jsx("ul", { ref: listRef, children: /* @__PURE__ */ jsx(PropsContextProvider, { props: propsContext, children }) }),
46
+ /* @__PURE__ */ jsx("div", { className: styles.more, ref: moreRef, children: /* @__PURE__ */ jsxs(ContextMenuTriggerView, { children: [
47
+ /* @__PURE__ */ jsxs(
48
+ Button,
49
+ {
50
+ unstyled: true,
51
+ className: clsx(
52
+ styles.moreButton,
53
+ menuHasCurrentItem && styles.current
54
+ ),
55
+ children: [
56
+ /* @__PURE__ */ jsx(Text, { emulateBoldWidth: true, children: stringFormatter.format("moreButton.title") }),
57
+ /* @__PURE__ */ jsx(IconChevronDown, {})
58
+ ]
59
+ }
60
+ ),
61
+ /* @__PURE__ */ jsx(ContextMenuView, { placement: "bottom end", children: /* @__PURE__ */ jsx(
62
+ UiComponentTunnelExit,
63
+ {
64
+ id: "menuItems",
65
+ component: "TabNavigation",
66
+ children: (menuItems) => Array.isArray(menuItems) ? menuItems.slice(visibleCount ?? menuItems.length) : menuItems
67
+ }
68
+ ) })
69
+ ] }) })
70
+ ] });
71
+ });
72
+
73
+ export { TabNavigation };
74
+ //# sourceMappingURL=TabNavigation.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TabNavigation.mjs","sources":["../../../../../../../src/components/TabNavigation/TabNavigation.tsx"],"sourcesContent":["import type { ComponentProps, PropsWithChildren } from \"react\";\nimport clsx from \"clsx\";\nimport { Button } from \"@/components/Button\";\nimport { IconChevronDown } from \"@/components/Icon/components/icons\";\nimport { Text } from \"@/components/Text\";\nimport { useLocalizedStringFormatter } from \"@/components/TranslationProvider\";\nimport { UiComponentTunnelExit } from \"@/components/UiComponentTunnel/UiComponentTunnelExit\";\nimport {\n flowComponent,\n type FlowComponentProps,\n} from \"@/lib/componentFactory/flowComponent\";\nimport {\n dynamic,\n type PropsContext,\n PropsContextProvider,\n} from \"@/lib/propsContext\";\nimport type { PropsWithClassName } from \"@/lib/types/props\";\nimport ContextMenuTriggerView from \"@/views/ContextMenuTriggerView\";\nimport ContextMenuView from \"@/views/ContextMenuView\";\nimport { LinkContent } from \"./components/LinkContent\";\nimport styles from \"./TabNavigation.module.scss\";\nimport locales from \"./locales/*.locale.json\";\nimport { useCollapsingItems } from \"./lib/useCollapsingItems\";\n\nexport interface TabNavigationProps\n extends\n PropsWithChildren<ComponentProps<\"nav\">>,\n PropsWithClassName,\n FlowComponentProps<HTMLElement> {}\n\n/**\n * @flr-generate all\n * @flowStatus new\n */\nexport const TabNavigation = flowComponent(\"TabNavigation\", (props) => {\n const { children, className, ref, ...rest } = props;\n\n const stringFormatter = useLocalizedStringFormatter(locales, \"TabNavigation\");\n\n const { listRef, moreRef, visibleCount, hasOverflow, menuHasCurrentItem } =\n useCollapsingItems();\n\n const rootClassName = clsx(\n styles.tabNavigation,\n hasOverflow && styles.collapsed,\n className,\n );\n\n const propsContext: PropsContext = {\n Link: {\n wrapWith: <li />,\n className: styles.link,\n unstyled: true,\n children: dynamic((linkProps) => <LinkContent linkProps={linkProps} />),\n },\n };\n\n return (\n <nav className={rootClassName} role=\"navigation\" {...rest} ref={ref}>\n <ul ref={listRef}>\n <PropsContextProvider props={propsContext}>\n {children}\n </PropsContextProvider>\n </ul>\n <div className={styles.more} ref={moreRef}>\n <ContextMenuTriggerView>\n <Button\n unstyled\n className={clsx(\n styles.moreButton,\n menuHasCurrentItem && styles.current,\n )}\n >\n <Text emulateBoldWidth>\n {stringFormatter.format(\"moreButton.title\")}\n </Text>\n <IconChevronDown />\n </Button>\n <ContextMenuView placement=\"bottom end\">\n <UiComponentTunnelExit\n id=\"menuItems\"\n component=\"TabNavigation\"\n children={(menuItems) =>\n Array.isArray(menuItems)\n ? menuItems.slice(visibleCount ?? menuItems.length)\n : menuItems\n }\n />\n </ContextMenuView>\n </ContextMenuTriggerView>\n </div>\n </nav>\n );\n});\n\nexport default TabNavigation;\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAkCO,MAAM,aAAA,GAAgB,aAAA,CAAc,eAAA,EAAiB,CAAC,KAAA,KAAU;AACrE,EAAA,MAAM,EAAE,QAAA,EAAU,SAAA,EAAW,GAAA,EAAK,GAAG,MAAK,GAAI,KAAA;AAE9C,EAAA,MAAM,eAAA,GAAkB,2BAAA,CAA4B,OAAA,EAAS,eAAe,CAAA;AAE5E,EAAA,MAAM,EAAE,OAAA,EAAS,OAAA,EAAS,cAAc,WAAA,EAAa,kBAAA,KACnD,kBAAA,EAAmB;AAErB,EAAA,MAAM,aAAA,GAAgB,IAAA;AAAA,IACpB,MAAA,CAAO,aAAA;AAAA,IACP,eAAe,MAAA,CAAO,SAAA;AAAA,IACtB;AAAA,GACF;AAEA,EAAA,MAAM,YAAA,GAA6B;AAAA,IACjC,IAAA,EAAM;AAAA,MACJ,QAAA,sBAAW,IAAA,EAAA,EAAG,CAAA;AAAA,MACd,WAAW,MAAA,CAAO,IAAA;AAAA,MAClB,QAAA,EAAU,IAAA;AAAA,MACV,UAAU,OAAA,CAAQ,CAAC,8BAAc,GAAA,CAAC,WAAA,EAAA,EAAY,WAAsB,CAAE;AAAA;AACxE,GACF;AAEA,EAAA,uBACE,IAAA,CAAC,SAAI,SAAA,EAAW,aAAA,EAAe,MAAK,YAAA,EAAc,GAAG,MAAM,GAAA,EACzD,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,IAAA,EAAA,EAAG,KAAK,OAAA,EACP,QAAA,kBAAA,GAAA,CAAC,wBAAqB,KAAA,EAAO,YAAA,EAC1B,UACH,CAAA,EACF,CAAA;AAAA,oBACA,GAAA,CAAC,SAAI,SAAA,EAAW,MAAA,CAAO,MAAM,GAAA,EAAK,OAAA,EAChC,+BAAC,sBAAA,EAAA,EACC,QAAA,EAAA;AAAA,sBAAA,IAAA;AAAA,QAAC,MAAA;AAAA,QAAA;AAAA,UACC,QAAA,EAAQ,IAAA;AAAA,UACR,SAAA,EAAW,IAAA;AAAA,YACT,MAAA,CAAO,UAAA;AAAA,YACP,sBAAsB,MAAA,CAAO;AAAA,WAC/B;AAAA,UAEA,QAAA,EAAA;AAAA,4BAAA,GAAA,CAAC,QAAK,gBAAA,EAAgB,IAAA,EACnB,QAAA,EAAA,eAAA,CAAgB,MAAA,CAAO,kBAAkB,CAAA,EAC5C,CAAA;AAAA,gCACC,eAAA,EAAA,EAAgB;AAAA;AAAA;AAAA,OACnB;AAAA,sBACA,GAAA,CAAC,eAAA,EAAA,EAAgB,SAAA,EAAU,YAAA,EACzB,QAAA,kBAAA,GAAA;AAAA,QAAC,qBAAA;AAAA,QAAA;AAAA,UACC,EAAA,EAAG,WAAA;AAAA,UACH,SAAA,EAAU,eAAA;AAAA,UACV,QAAA,EAAU,CAAC,SAAA,KACT,KAAA,CAAM,OAAA,CAAQ,SAAS,CAAA,GACnB,SAAA,CAAU,KAAA,CAAM,YAAA,IAAgB,SAAA,CAAU,MAAM,CAAA,GAChD;AAAA;AAAA,OAER,EACF;AAAA,KAAA,EACF,CAAA,EACF;AAAA,GAAA,EACF,CAAA;AAEJ,CAAC;;;;"}
@@ -0,0 +1,21 @@
1
+ "use client"
2
+ /* */
3
+ const tabNavigation = "flow--tab-navigation";
4
+ const link = "flow--tab-navigation--link";
5
+ const text = "flow--tab-navigation--text";
6
+ const more = "flow--tab-navigation--more";
7
+ const moreButton = "flow--tab-navigation--more-button";
8
+ const current = "flow--tab-navigation--current";
9
+ const collapsed = "flow--tab-navigation--collapsed";
10
+ const styles = {
11
+ tabNavigation: tabNavigation,
12
+ link: link,
13
+ text: text,
14
+ more: more,
15
+ moreButton: moreButton,
16
+ current: current,
17
+ collapsed: collapsed
18
+ };
19
+
20
+ export { collapsed, current, styles as default, link, more, moreButton, tabNavigation, text };
21
+ //# sourceMappingURL=TabNavigation.module.scss.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TabNavigation.module.scss.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;"}
@@ -0,0 +1,46 @@
1
+ "use client"
2
+ /* */
3
+ import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
4
+ import { MenuItem } from '../../../MenuItem/MenuItem.mjs';
5
+ import { Text } from '../../../Text/Text.mjs';
6
+ import { UiComponentTunnelEntry } from '../../../UiComponentTunnel/UiComponentTunnelEntry.mjs';
7
+ import styles from '../../TabNavigation.module.scss.mjs';
8
+
9
+ const LinkContent = (props) => {
10
+ const { linkProps } = props;
11
+ const {
12
+ children,
13
+ href,
14
+ target,
15
+ rel,
16
+ download,
17
+ hrefLang,
18
+ ping,
19
+ referrerPolicy,
20
+ routerOptions,
21
+ "aria-label": ariaLabel,
22
+ "aria-current": ariaCurrent
23
+ } = linkProps;
24
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
25
+ /* @__PURE__ */ jsx(Text, { emulateBoldWidth: true, children: /* @__PURE__ */ jsx("span", { className: styles.text, children }) }),
26
+ /* @__PURE__ */ jsx(UiComponentTunnelEntry, { id: "menuItems", component: "TabNavigation", children: /* @__PURE__ */ jsx(
27
+ MenuItem,
28
+ {
29
+ "aria-current": ariaCurrent,
30
+ href,
31
+ target,
32
+ rel,
33
+ download,
34
+ hrefLang,
35
+ ping,
36
+ referrerPolicy,
37
+ routerOptions,
38
+ "aria-label": ariaLabel,
39
+ children
40
+ }
41
+ ) })
42
+ ] });
43
+ };
44
+
45
+ export { LinkContent };
46
+ //# sourceMappingURL=LinkContent.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LinkContent.mjs","sources":["../../../../../../../../../src/components/TabNavigation/components/LinkContent/LinkContent.tsx"],"sourcesContent":["import type { FC } from \"react\";\nimport type { LinkProps } from \"@/components/Link\";\nimport { MenuItem } from \"@/components/MenuItem\";\nimport { Text } from \"@/components/Text\";\nimport { UiComponentTunnelEntry } from \"@/components/UiComponentTunnel/UiComponentTunnelEntry\";\nimport styles from \"../../TabNavigation.module.scss\";\n\ninterface Props {\n linkProps: Partial<LinkProps>;\n}\n\n/**\n * Renders the content of a link inside the tab navigation and mirrors the link\n * as a menu item into the overflow context menu (via tunnel). The context menu\n * only renders the menu items of the currently collapsed links.\n */\nexport const LinkContent: FC<Props> = (props) => {\n const { linkProps } = props;\n\n const {\n children,\n href,\n target,\n rel,\n download,\n hrefLang,\n ping,\n referrerPolicy,\n routerOptions,\n \"aria-label\": ariaLabel,\n \"aria-current\": ariaCurrent,\n } = linkProps;\n\n return (\n <>\n <Text emulateBoldWidth>\n <span className={styles.text}>{children}</span>\n </Text>\n <UiComponentTunnelEntry id=\"menuItems\" component=\"TabNavigation\">\n <MenuItem\n aria-current={ariaCurrent}\n href={href}\n target={target}\n rel={rel}\n download={download}\n hrefLang={hrefLang}\n ping={ping}\n referrerPolicy={referrerPolicy}\n routerOptions={routerOptions}\n aria-label={ariaLabel}\n >\n {children}\n </MenuItem>\n </UiComponentTunnelEntry>\n </>\n );\n};\n\nexport default LinkContent;\n"],"names":[],"mappings":";;;;;;AAgBO,MAAM,WAAA,GAAyB,CAAC,KAAA,KAAU;AAC/C,EAAA,MAAM,EAAE,WAAU,GAAI,KAAA;AAEtB,EAAA,MAAM;AAAA,IACJ,QAAA;AAAA,IACA,IAAA;AAAA,IACA,MAAA;AAAA,IACA,GAAA;AAAA,IACA,QAAA;AAAA,IACA,QAAA;AAAA,IACA,IAAA;AAAA,IACA,cAAA;AAAA,IACA,aAAA;AAAA,IACA,YAAA,EAAc,SAAA;AAAA,IACd,cAAA,EAAgB;AAAA,GAClB,GAAI,SAAA;AAEJ,EAAA,uBACE,IAAA,CAAA,QAAA,EAAA,EACE,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,IAAA,EAAA,EAAK,kBAAgB,IAAA,EACpB,QAAA,kBAAA,GAAA,CAAC,UAAK,SAAA,EAAW,MAAA,CAAO,IAAA,EAAO,QAAA,EAAS,CAAA,EAC1C,CAAA;AAAA,oBACA,GAAA,CAAC,sBAAA,EAAA,EAAuB,EAAA,EAAG,WAAA,EAAY,WAAU,eAAA,EAC/C,QAAA,kBAAA,GAAA;AAAA,MAAC,QAAA;AAAA,MAAA;AAAA,QACC,cAAA,EAAc,WAAA;AAAA,QACd,IAAA;AAAA,QACA,MAAA;AAAA,QACA,GAAA;AAAA,QACA,QAAA;AAAA,QACA,QAAA;AAAA,QACA,IAAA;AAAA,QACA,cAAA;AAAA,QACA,aAAA;AAAA,QACA,YAAA,EAAY,SAAA;AAAA,QAEX;AAAA;AAAA,KACH,EACF;AAAA,GAAA,EACF,CAAA;AAEJ;;;;"}
@@ -0,0 +1,22 @@
1
+ "use client"
2
+ /* */
3
+ const floatTolerance = 0.5;
4
+ const getVisibleItemCount = (itemWidths, availableWidth, moreItemWidth) => {
5
+ const totalWidth = itemWidths.reduce((sum, width) => sum + width, 0);
6
+ if (totalWidth <= availableWidth + floatTolerance) {
7
+ return itemWidths.length;
8
+ }
9
+ let usedWidth = moreItemWidth;
10
+ let visibleCount = 0;
11
+ for (const itemWidth of itemWidths) {
12
+ if (usedWidth + itemWidth > availableWidth + floatTolerance) {
13
+ break;
14
+ }
15
+ usedWidth += itemWidth;
16
+ visibleCount++;
17
+ }
18
+ return visibleCount;
19
+ };
20
+
21
+ export { getVisibleItemCount };
22
+ //# sourceMappingURL=getVisibleItemCount.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getVisibleItemCount.mjs","sources":["../../../../../../../../src/components/TabNavigation/lib/getVisibleItemCount.ts"],"sourcesContent":["/**\n * Tolerance for sub-pixel rounding differences between measured item widths and\n * the available width.\n */\nconst floatTolerance = 0.5;\n\nexport const getVisibleItemCount = (\n itemWidths: number[],\n availableWidth: number,\n moreItemWidth: number,\n): number => {\n const totalWidth = itemWidths.reduce((sum, width) => sum + width, 0);\n\n if (totalWidth <= availableWidth + floatTolerance) {\n return itemWidths.length;\n }\n\n let usedWidth = moreItemWidth;\n let visibleCount = 0;\n\n for (const itemWidth of itemWidths) {\n if (usedWidth + itemWidth > availableWidth + floatTolerance) {\n break;\n }\n usedWidth += itemWidth;\n visibleCount++;\n }\n\n return visibleCount;\n};\n"],"names":[],"mappings":"AAIA,MAAM,cAAA,GAAiB,GAAA;AAEhB,MAAM,mBAAA,GAAsB,CACjC,UAAA,EACA,cAAA,EACA,aAAA,KACW;AACX,EAAA,MAAM,UAAA,GAAa,WAAW,MAAA,CAAO,CAAC,KAAK,KAAA,KAAU,GAAA,GAAM,OAAO,CAAC,CAAA;AAEnE,EAAA,IAAI,UAAA,IAAc,iBAAiB,cAAA,EAAgB;AACjD,IAAA,OAAO,UAAA,CAAW,MAAA;AAAA,EACpB;AAEA,EAAA,IAAI,SAAA,GAAY,aAAA;AAChB,EAAA,IAAI,YAAA,GAAe,CAAA;AAEnB,EAAA,KAAA,MAAW,aAAa,UAAA,EAAY;AAClC,IAAA,IAAI,SAAA,GAAY,SAAA,GAAY,cAAA,GAAiB,cAAA,EAAgB;AAC3D,MAAA;AAAA,IACF;AACA,IAAA,SAAA,IAAa,SAAA;AACb,IAAA,YAAA,EAAA;AAAA,EACF;AAEA,EAAA,OAAO,YAAA;AACT;;;;"}
@@ -0,0 +1,65 @@
1
+ "use client"
2
+ /* */
3
+ import { useRef, useState, useCallback, useLayoutEffect } from 'react';
4
+ import { createFrameResizeObserver } from '../../../lib/dom/createFrameResizeObserver.mjs';
5
+ import { getVisibleItemCount } from './getVisibleItemCount.mjs';
6
+
7
+ const initialState = {
8
+ visibleCount: null,
9
+ hasOverflow: false,
10
+ menuHasCurrentItem: false
11
+ };
12
+ const useCollapsingItems = () => {
13
+ const listRef = useRef(null);
14
+ const moreRef = useRef(null);
15
+ const [state, setState] = useState(initialState);
16
+ const update = useCallback(() => {
17
+ const list = listRef.current;
18
+ const more = moreRef.current;
19
+ const container = list?.parentElement;
20
+ if (!list || !more || !container) {
21
+ return;
22
+ }
23
+ const items = Array.from(list.children).filter(
24
+ (child) => child instanceof HTMLElement
25
+ );
26
+ const containerStyle = window.getComputedStyle(container);
27
+ const availableWidth = container.clientWidth - (parseFloat(containerStyle.paddingInlineStart) || 0) - (parseFloat(containerStyle.paddingInlineEnd) || 0);
28
+ const visibleCount = getVisibleItemCount(
29
+ items.map((item) => item.getBoundingClientRect().width),
30
+ availableWidth,
31
+ more.getBoundingClientRect().width
32
+ );
33
+ items.forEach((item, index) => {
34
+ item.style.visibility = index < visibleCount ? "" : "hidden";
35
+ });
36
+ const menuHasCurrentItem = items.slice(visibleCount).some(
37
+ (item) => !!item.querySelector('[aria-current]:not([aria-current="false"])')
38
+ );
39
+ setState((previous) => {
40
+ const next = {
41
+ visibleCount,
42
+ hasOverflow: visibleCount < items.length,
43
+ menuHasCurrentItem
44
+ };
45
+ const isUnchanged = previous.visibleCount === next.visibleCount && previous.hasOverflow === next.hasOverflow && previous.menuHasCurrentItem === next.menuHasCurrentItem;
46
+ return isUnchanged ? previous : next;
47
+ });
48
+ }, []);
49
+ useLayoutEffect(() => {
50
+ const list = listRef.current;
51
+ const more = moreRef.current;
52
+ const container = list?.parentElement;
53
+ if (!list || !more || !container) {
54
+ return;
55
+ }
56
+ const observer = createFrameResizeObserver(update);
57
+ observer.observe([container, more, ...list.children]);
58
+ update();
59
+ return () => observer.disconnect();
60
+ });
61
+ return { ...state, listRef, moreRef };
62
+ };
63
+
64
+ export { useCollapsingItems };
65
+ //# sourceMappingURL=useCollapsingItems.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useCollapsingItems.mjs","sources":["../../../../../../../../src/components/TabNavigation/lib/useCollapsingItems.ts"],"sourcesContent":["import type { RefObject } from \"react\";\nimport { useCallback, useLayoutEffect, useRef, useState } from \"react\";\nimport { createFrameResizeObserver } from \"@/lib/dom/createFrameResizeObserver\";\nimport { getVisibleItemCount } from \"./getVisibleItemCount\";\n\ninterface CollapsingItemsState {\n /** Number of visible items. `null` until the first measurement was done. */\n visibleCount: number | null;\n /** Whether at least one item does not fit and is collapsed. */\n hasOverflow: boolean;\n /** Whether one of the collapsed items contains the current page link. */\n menuHasCurrentItem: boolean;\n}\n\ninterface UseCollapsingItemsReturn extends CollapsingItemsState {\n listRef: RefObject<HTMLUListElement | null>;\n moreRef: RefObject<HTMLDivElement | null>;\n}\n\nconst initialState: CollapsingItemsState = {\n visibleCount: null,\n hasOverflow: false,\n menuHasCurrentItem: false,\n};\n\n/**\n * Observes the items of the list and computes how many of them fit into the\n * available width of the list's parent element. Items that do not fit are\n * hidden via `visibility: hidden` (removes them from the accessibility tree and\n * the tab order while keeping them measurable). The width of the \"more\" element\n * is reserved whenever items are collapsed, so it must always be rendered\n * (visually hidden when there is no overflow).\n */\nexport const useCollapsingItems = (): UseCollapsingItemsReturn => {\n const listRef = useRef<HTMLUListElement>(null);\n const moreRef = useRef<HTMLDivElement>(null);\n\n const [state, setState] = useState(initialState);\n\n const update = useCallback(() => {\n const list = listRef.current;\n const more = moreRef.current;\n const container = list?.parentElement;\n\n if (!list || !more || !container) {\n return;\n }\n\n const items = Array.from(list.children).filter(\n (child): child is HTMLElement => child instanceof HTMLElement,\n );\n\n const containerStyle = window.getComputedStyle(container);\n const availableWidth =\n container.clientWidth -\n (parseFloat(containerStyle.paddingInlineStart) || 0) -\n (parseFloat(containerStyle.paddingInlineEnd) || 0);\n\n const visibleCount = getVisibleItemCount(\n items.map((item) => item.getBoundingClientRect().width),\n availableWidth,\n more.getBoundingClientRect().width,\n );\n\n items.forEach((item, index) => {\n item.style.visibility = index < visibleCount ? \"\" : \"hidden\";\n });\n\n const menuHasCurrentItem = items\n .slice(visibleCount)\n .some(\n (item) =>\n !!item.querySelector('[aria-current]:not([aria-current=\"false\"])'),\n );\n\n setState((previous) => {\n const next: CollapsingItemsState = {\n visibleCount,\n hasOverflow: visibleCount < items.length,\n menuHasCurrentItem,\n };\n\n const isUnchanged =\n previous.visibleCount === next.visibleCount &&\n previous.hasOverflow === next.hasOverflow &&\n previous.menuHasCurrentItem === next.menuHasCurrentItem;\n\n return isUnchanged ? previous : next;\n });\n }, []);\n\n // Runs after every render (no dependency array): the rendered items may\n // have changed, so the observed elements are re-collected and re-measured.\n // `update()` only triggers a re-render when the computed state changed.\n useLayoutEffect(() => {\n const list = listRef.current;\n const more = moreRef.current;\n const container = list?.parentElement;\n\n if (!list || !more || !container) {\n return;\n }\n\n const observer = createFrameResizeObserver(update);\n observer.observe([container, more, ...list.children]);\n\n update();\n\n return () => observer.disconnect();\n });\n\n return { ...state, listRef, moreRef };\n};\n\nexport default useCollapsingItems;\n"],"names":[],"mappings":";;;;AAmBA,MAAM,YAAA,GAAqC;AAAA,EACzC,YAAA,EAAc,IAAA;AAAA,EACd,WAAA,EAAa,KAAA;AAAA,EACb,kBAAA,EAAoB;AACtB,CAAA;AAUO,MAAM,qBAAqB,MAAgC;AAChE,EAAA,MAAM,OAAA,GAAU,OAAyB,IAAI,CAAA;AAC7C,EAAA,MAAM,OAAA,GAAU,OAAuB,IAAI,CAAA;AAE3C,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAI,SAAS,YAAY,CAAA;AAE/C,EAAA,MAAM,MAAA,GAAS,YAAY,MAAM;AAC/B,IAAA,MAAM,OAAO,OAAA,CAAQ,OAAA;AACrB,IAAA,MAAM,OAAO,OAAA,CAAQ,OAAA;AACrB,IAAA,MAAM,YAAY,IAAA,EAAM,aAAA;AAExB,IAAA,IAAI,CAAC,IAAA,IAAQ,CAAC,IAAA,IAAQ,CAAC,SAAA,EAAW;AAChC,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,KAAA,GAAQ,KAAA,CAAM,IAAA,CAAK,IAAA,CAAK,QAAQ,CAAA,CAAE,MAAA;AAAA,MACtC,CAAC,UAAgC,KAAA,YAAiB;AAAA,KACpD;AAEA,IAAA,MAAM,cAAA,GAAiB,MAAA,CAAO,gBAAA,CAAiB,SAAS,CAAA;AACxD,IAAA,MAAM,cAAA,GACJ,SAAA,CAAU,WAAA,IACT,UAAA,CAAW,cAAA,CAAe,kBAAkB,CAAA,IAAK,CAAA,CAAA,IACjD,UAAA,CAAW,cAAA,CAAe,gBAAgB,CAAA,IAAK,CAAA,CAAA;AAElD,IAAA,MAAM,YAAA,GAAe,mBAAA;AAAA,MACnB,MAAM,GAAA,CAAI,CAAC,SAAS,IAAA,CAAK,qBAAA,GAAwB,KAAK,CAAA;AAAA,MACtD,cAAA;AAAA,MACA,IAAA,CAAK,uBAAsB,CAAE;AAAA,KAC/B;AAEA,IAAA,KAAA,CAAM,OAAA,CAAQ,CAAC,IAAA,EAAM,KAAA,KAAU;AAC7B,MAAA,IAAA,CAAK,KAAA,CAAM,UAAA,GAAa,KAAA,GAAQ,YAAA,GAAe,EAAA,GAAK,QAAA;AAAA,IACtD,CAAC,CAAA;AAED,IAAA,MAAM,kBAAA,GAAqB,KAAA,CACxB,KAAA,CAAM,YAAY,CAAA,CAClB,IAAA;AAAA,MACC,CAAC,IAAA,KACC,CAAC,CAAC,IAAA,CAAK,cAAc,4CAA4C;AAAA,KACrE;AAEF,IAAA,QAAA,CAAS,CAAC,QAAA,KAAa;AACrB,MAAA,MAAM,IAAA,GAA6B;AAAA,QACjC,YAAA;AAAA,QACA,WAAA,EAAa,eAAe,KAAA,CAAM,MAAA;AAAA,QAClC;AAAA,OACF;AAEA,MAAA,MAAM,WAAA,GACJ,QAAA,CAAS,YAAA,KAAiB,IAAA,CAAK,YAAA,IAC/B,QAAA,CAAS,WAAA,KAAgB,IAAA,CAAK,WAAA,IAC9B,QAAA,CAAS,kBAAA,KAAuB,IAAA,CAAK,kBAAA;AAEvC,MAAA,OAAO,cAAc,QAAA,GAAW,IAAA;AAAA,IAClC,CAAC,CAAA;AAAA,EACH,CAAA,EAAG,EAAE,CAAA;AAKL,EAAA,eAAA,CAAgB,MAAM;AACpB,IAAA,MAAM,OAAO,OAAA,CAAQ,OAAA;AACrB,IAAA,MAAM,OAAO,OAAA,CAAQ,OAAA;AACrB,IAAA,MAAM,YAAY,IAAA,EAAM,aAAA;AAExB,IAAA,IAAI,CAAC,IAAA,IAAQ,CAAC,IAAA,IAAQ,CAAC,SAAA,EAAW;AAChC,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,QAAA,GAAW,0BAA0B,MAAM,CAAA;AACjD,IAAA,QAAA,CAAS,QAAQ,CAAC,SAAA,EAAW,MAAM,GAAG,IAAA,CAAK,QAAQ,CAAC,CAAA;AAEpD,IAAA,MAAA,EAAO;AAEP,IAAA,OAAO,MAAM,SAAS,UAAA,EAAW;AAAA,EACnC,CAAC,CAAA;AAED,EAAA,OAAO,EAAE,GAAG,KAAA,EAAO,OAAA,EAAS,OAAA,EAAQ;AACtC;;;;"}
@@ -4,9 +4,11 @@ import { jsxs, jsx } from 'react/jsx-runtime';
4
4
  import { useId } from 'react';
5
5
  import * as Aria from 'react-aria-components';
6
6
  import styles from './TabList.module.scss.mjs';
7
+ import { useTabIndicator } from '../../lib/useTabIndicator.mjs';
7
8
  import { useObserveOverflow } from '../../../../lib/hooks/dom/useObserveOverflow.mjs';
8
9
  import { Button } from '../../../Button/Button.mjs';
9
10
  import clsx from 'clsx';
11
+ import { useMergeRefs } from 'use-callback-ref';
10
12
  import ContextMenuTriggerView from '../../../../views/ContextMenuTriggerView.mjs';
11
13
  import ContextMenuView from '../../../../views/ContextMenuView.mjs';
12
14
  import '@mittwald/flow-icons';
@@ -22,10 +24,15 @@ const TabList = (props) => {
22
24
  const overflowObserver = useObserveOverflow();
23
25
  const isCollapsed = overflowObserver.isOverflowing;
24
26
  const rootClassName = clsx(styles.tabList, isCollapsed && styles.collapsed);
27
+ const tabIndicator = useTabIndicator(isCollapsed);
28
+ const setTitlesRef = useMergeRefs([
29
+ overflowObserver.ref,
30
+ tabIndicator.titlesRef
31
+ ]);
25
32
  const handleContextMenuSelectionChange = (key) => {
26
33
  onContextMenuSelectionChange(key);
27
34
  };
28
- const regularTabTitles = /* @__PURE__ */ jsx(Aria.TabList, { className: styles.titles, ref: overflowObserver.ref, children: /* @__PURE__ */ jsx(UiComponentTunnelExit, { id: "Titles", component: "Tabs" }) });
35
+ const regularTabTitles = /* @__PURE__ */ jsx(Aria.TabList, { className: styles.titles, ref: setTitlesRef, children: /* @__PURE__ */ jsx(UiComponentTunnelExit, { id: "Titles", component: "Tabs" }) });
29
36
  const contextMenuWhenCollapsed = isCollapsed && /* @__PURE__ */ jsxs(ContextMenuTriggerView, { children: [
30
37
  /* @__PURE__ */ jsxs(
31
38
  Button,
@@ -51,7 +58,18 @@ const TabList = (props) => {
51
58
  }
52
59
  )
53
60
  ] });
54
- return /* @__PURE__ */ jsxs("div", { className: rootClassName, children: [
61
+ return /* @__PURE__ */ jsxs("div", { className: rootClassName, ref: tabIndicator.rootRef, children: [
62
+ !isCollapsed && tabIndicator.indicatorStyle && /* @__PURE__ */ jsx(
63
+ "div",
64
+ {
65
+ "aria-hidden": "true",
66
+ className: clsx(
67
+ styles.activeIndicator,
68
+ tabIndicator.isAnimated && styles.animated
69
+ ),
70
+ style: tabIndicator.indicatorStyle
71
+ }
72
+ ),
55
73
  regularTabTitles,
56
74
  contextMenuWhenCollapsed
57
75
  ] });
@@ -1 +1 @@
1
- {"version":3,"file":"TabList.mjs","sources":["../../../../../../../../../src/components/Tabs/components/TabList/TabList.tsx"],"sourcesContent":["import type { FC } from \"react\";\nimport { useId } from \"react\";\nimport * as Aria from \"react-aria-components\";\nimport styles from \"./TabList.module.scss\";\nimport { useObserveOverflow } from \"@/lib/hooks/dom/useObserveOverflow\";\nimport { Button } from \"@/components/Button\";\nimport clsx from \"clsx\";\nimport ContextMenuTriggerView from \"@/views/ContextMenuTriggerView\";\nimport ContextMenuView from \"@/views/ContextMenuView\";\nimport { IconChevronDown } from \"@/components/Icon/components/icons\";\nimport { UiComponentTunnelExit } from \"@/components/UiComponentTunnel/UiComponentTunnelExit\";\n\ninterface Props {\n selection: Aria.Key | undefined;\n onContextMenuSelectionChange: (key: Aria.Key) => void;\n disabledKeys?: Iterable<Aria.Key>;\n}\n\nexport const TabList: FC<Props> = (props) => {\n const { selection, disabledKeys, onContextMenuSelectionChange } = props;\n\n const titleCollapsedElementId = useId();\n const overflowObserver = useObserveOverflow();\n const isCollapsed = overflowObserver.isOverflowing;\n const rootClassName = clsx(styles.tabList, isCollapsed && styles.collapsed);\n\n const handleContextMenuSelectionChange = (key: Aria.Key) => {\n onContextMenuSelectionChange(key);\n };\n\n const regularTabTitles = (\n <Aria.TabList className={styles.titles} ref={overflowObserver.ref}>\n <UiComponentTunnelExit id=\"Titles\" component=\"Tabs\" />\n </Aria.TabList>\n );\n\n const contextMenuWhenCollapsed = isCollapsed && (\n <ContextMenuTriggerView>\n <Button\n variant=\"solid\"\n className={styles.contextMenuButton}\n color=\"light\"\n aria-labelledby={titleCollapsedElementId}\n >\n <UiComponentTunnelExit id=\"ActiveTitle\" component=\"Tabs\" />\n <IconChevronDown />\n </Button>\n\n <ContextMenuView\n disabledKeys={disabledKeys}\n selectedKeys={selection ? [selection] : undefined}\n selectionMode=\"navigation\"\n onAction={(key) => handleContextMenuSelectionChange(key)}\n >\n <UiComponentTunnelExit id=\"ContextMenuItems\" component=\"Tabs\" />\n </ContextMenuView>\n </ContextMenuTriggerView>\n );\n\n return (\n <div className={rootClassName}>\n {regularTabTitles}\n {contextMenuWhenCollapsed}\n </div>\n );\n};\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAkBO,MAAM,OAAA,GAAqB,CAAC,KAAA,KAAU;AAC3C,EAAA,MAAM,EAAE,SAAA,EAAW,YAAA,EAAc,4BAAA,EAA6B,GAAI,KAAA;AAElE,EAAA,MAAM,0BAA0B,KAAA,EAAM;AACtC,EAAA,MAAM,mBAAmB,kBAAA,EAAmB;AAC5C,EAAA,MAAM,cAAc,gBAAA,CAAiB,aAAA;AACrC,EAAA,MAAM,gBAAgB,IAAA,CAAK,MAAA,CAAO,OAAA,EAAS,WAAA,IAAe,OAAO,SAAS,CAAA;AAE1E,EAAA,MAAM,gCAAA,GAAmC,CAAC,GAAA,KAAkB;AAC1D,IAAA,4BAAA,CAA6B,GAAG,CAAA;AAAA,EAClC,CAAA;AAEA,EAAA,MAAM,mCACJ,GAAA,CAAC,IAAA,CAAK,OAAA,EAAL,EAAa,WAAW,MAAA,CAAO,MAAA,EAAQ,GAAA,EAAK,gBAAA,CAAiB,KAC5D,QAAA,kBAAA,GAAA,CAAC,qBAAA,EAAA,EAAsB,IAAG,QAAA,EAAS,SAAA,EAAU,QAAO,CAAA,EACtD,CAAA;AAGF,EAAA,MAAM,wBAAA,GAA2B,WAAA,oBAC/B,IAAA,CAAC,sBAAA,EAAA,EACC,QAAA,EAAA;AAAA,oBAAA,IAAA;AAAA,MAAC,MAAA;AAAA,MAAA;AAAA,QACC,OAAA,EAAQ,OAAA;AAAA,QACR,WAAW,MAAA,CAAO,iBAAA;AAAA,QAClB,KAAA,EAAM,OAAA;AAAA,QACN,iBAAA,EAAiB,uBAAA;AAAA,QAEjB,QAAA,EAAA;AAAA,0BAAA,GAAA,CAAC,qBAAA,EAAA,EAAsB,EAAA,EAAG,aAAA,EAAc,SAAA,EAAU,MAAA,EAAO,CAAA;AAAA,8BACxD,eAAA,EAAA,EAAgB;AAAA;AAAA;AAAA,KACnB;AAAA,oBAEA,GAAA;AAAA,MAAC,eAAA;AAAA,MAAA;AAAA,QACC,YAAA;AAAA,QACA,YAAA,EAAc,SAAA,GAAY,CAAC,SAAS,CAAA,GAAI,MAAA;AAAA,QACxC,aAAA,EAAc,YAAA;AAAA,QACd,QAAA,EAAU,CAAC,GAAA,KAAQ,gCAAA,CAAiC,GAAG,CAAA;AAAA,QAEvD,QAAA,kBAAA,GAAA,CAAC,qBAAA,EAAA,EAAsB,EAAA,EAAG,kBAAA,EAAmB,WAAU,MAAA,EAAO;AAAA;AAAA;AAChE,GAAA,EACF,CAAA;AAGF,EAAA,uBACE,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,aAAA,EACb,QAAA,EAAA;AAAA,IAAA,gBAAA;AAAA,IACA;AAAA,GAAA,EACH,CAAA;AAEJ;;;;"}
1
+ {"version":3,"file":"TabList.mjs","sources":["../../../../../../../../../src/components/Tabs/components/TabList/TabList.tsx"],"sourcesContent":["import type { FC } from \"react\";\nimport { useId } from \"react\";\nimport * as Aria from \"react-aria-components\";\nimport styles from \"./TabList.module.scss\";\nimport { useTabIndicator } from \"../../lib/useTabIndicator\";\nimport { useObserveOverflow } from \"@/lib/hooks/dom/useObserveOverflow\";\nimport { Button } from \"@/components/Button\";\nimport clsx from \"clsx\";\nimport { useMergeRefs } from \"use-callback-ref\";\nimport ContextMenuTriggerView from \"@/views/ContextMenuTriggerView\";\nimport ContextMenuView from \"@/views/ContextMenuView\";\nimport { IconChevronDown } from \"@/components/Icon/components/icons\";\nimport { UiComponentTunnelExit } from \"@/components/UiComponentTunnel/UiComponentTunnelExit\";\n\ninterface Props {\n selection: Aria.Key | undefined;\n onContextMenuSelectionChange: (key: Aria.Key) => void;\n disabledKeys?: Iterable<Aria.Key>;\n}\n\nexport const TabList: FC<Props> = (props) => {\n const { selection, disabledKeys, onContextMenuSelectionChange } = props;\n\n const titleCollapsedElementId = useId();\n const overflowObserver = useObserveOverflow();\n const isCollapsed = overflowObserver.isOverflowing;\n const rootClassName = clsx(styles.tabList, isCollapsed && styles.collapsed);\n const tabIndicator = useTabIndicator(isCollapsed);\n\n const setTitlesRef = useMergeRefs<HTMLDivElement>([\n overflowObserver.ref,\n tabIndicator.titlesRef,\n ]);\n\n const handleContextMenuSelectionChange = (key: Aria.Key) => {\n onContextMenuSelectionChange(key);\n };\n\n const regularTabTitles = (\n <Aria.TabList className={styles.titles} ref={setTitlesRef}>\n <UiComponentTunnelExit id=\"Titles\" component=\"Tabs\" />\n </Aria.TabList>\n );\n\n const contextMenuWhenCollapsed = isCollapsed && (\n <ContextMenuTriggerView>\n <Button\n variant=\"solid\"\n className={styles.contextMenuButton}\n color=\"light\"\n aria-labelledby={titleCollapsedElementId}\n >\n <UiComponentTunnelExit id=\"ActiveTitle\" component=\"Tabs\" />\n <IconChevronDown />\n </Button>\n\n <ContextMenuView\n disabledKeys={disabledKeys}\n selectedKeys={selection ? [selection] : undefined}\n selectionMode=\"navigation\"\n onAction={(key) => handleContextMenuSelectionChange(key)}\n >\n <UiComponentTunnelExit id=\"ContextMenuItems\" component=\"Tabs\" />\n </ContextMenuView>\n </ContextMenuTriggerView>\n );\n\n return (\n <div className={rootClassName} ref={tabIndicator.rootRef}>\n {!isCollapsed && tabIndicator.indicatorStyle && (\n <div\n aria-hidden=\"true\"\n className={clsx(\n styles.activeIndicator,\n tabIndicator.isAnimated && styles.animated,\n )}\n style={tabIndicator.indicatorStyle}\n />\n )}\n {regularTabTitles}\n {contextMenuWhenCollapsed}\n </div>\n );\n};\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;AAoBO,MAAM,OAAA,GAAqB,CAAC,KAAA,KAAU;AAC3C,EAAA,MAAM,EAAE,SAAA,EAAW,YAAA,EAAc,4BAAA,EAA6B,GAAI,KAAA;AAElE,EAAA,MAAM,0BAA0B,KAAA,EAAM;AACtC,EAAA,MAAM,mBAAmB,kBAAA,EAAmB;AAC5C,EAAA,MAAM,cAAc,gBAAA,CAAiB,aAAA;AACrC,EAAA,MAAM,gBAAgB,IAAA,CAAK,MAAA,CAAO,OAAA,EAAS,WAAA,IAAe,OAAO,SAAS,CAAA;AAC1E,EAAA,MAAM,YAAA,GAAe,gBAAgB,WAAW,CAAA;AAEhD,EAAA,MAAM,eAAe,YAAA,CAA6B;AAAA,IAChD,gBAAA,CAAiB,GAAA;AAAA,IACjB,YAAA,CAAa;AAAA,GACd,CAAA;AAED,EAAA,MAAM,gCAAA,GAAmC,CAAC,GAAA,KAAkB;AAC1D,IAAA,4BAAA,CAA6B,GAAG,CAAA;AAAA,EAClC,CAAA;AAEA,EAAA,MAAM,mCACJ,GAAA,CAAC,IAAA,CAAK,OAAA,EAAL,EAAa,WAAW,MAAA,CAAO,MAAA,EAAQ,GAAA,EAAK,YAAA,EAC3C,8BAAC,qBAAA,EAAA,EAAsB,EAAA,EAAG,QAAA,EAAS,SAAA,EAAU,QAAO,CAAA,EACtD,CAAA;AAGF,EAAA,MAAM,wBAAA,GAA2B,WAAA,oBAC/B,IAAA,CAAC,sBAAA,EAAA,EACC,QAAA,EAAA;AAAA,oBAAA,IAAA;AAAA,MAAC,MAAA;AAAA,MAAA;AAAA,QACC,OAAA,EAAQ,OAAA;AAAA,QACR,WAAW,MAAA,CAAO,iBAAA;AAAA,QAClB,KAAA,EAAM,OAAA;AAAA,QACN,iBAAA,EAAiB,uBAAA;AAAA,QAEjB,QAAA,EAAA;AAAA,0BAAA,GAAA,CAAC,qBAAA,EAAA,EAAsB,EAAA,EAAG,aAAA,EAAc,SAAA,EAAU,MAAA,EAAO,CAAA;AAAA,8BACxD,eAAA,EAAA,EAAgB;AAAA;AAAA;AAAA,KACnB;AAAA,oBAEA,GAAA;AAAA,MAAC,eAAA;AAAA,MAAA;AAAA,QACC,YAAA;AAAA,QACA,YAAA,EAAc,SAAA,GAAY,CAAC,SAAS,CAAA,GAAI,MAAA;AAAA,QACxC,aAAA,EAAc,YAAA;AAAA,QACd,QAAA,EAAU,CAAC,GAAA,KAAQ,gCAAA,CAAiC,GAAG,CAAA;AAAA,QAEvD,QAAA,kBAAA,GAAA,CAAC,qBAAA,EAAA,EAAsB,EAAA,EAAG,kBAAA,EAAmB,WAAU,MAAA,EAAO;AAAA;AAAA;AAChE,GAAA,EACF,CAAA;AAGF,EAAA,4BACG,KAAA,EAAA,EAAI,SAAA,EAAW,aAAA,EAAe,GAAA,EAAK,aAAa,OAAA,EAC9C,QAAA,EAAA;AAAA,IAAA,CAAC,WAAA,IAAe,aAAa,cAAA,oBAC5B,GAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,aAAA,EAAY,MAAA;AAAA,QACZ,SAAA,EAAW,IAAA;AAAA,UACT,MAAA,CAAO,eAAA;AAAA,UACP,YAAA,CAAa,cAAc,MAAA,CAAO;AAAA,SACpC;AAAA,QACA,OAAO,YAAA,CAAa;AAAA;AAAA,KACtB;AAAA,IAED,gBAAA;AAAA,IACA;AAAA,GAAA,EACH,CAAA;AAEJ;;;;"}
@@ -1,15 +1,19 @@
1
1
  "use client"
2
2
  /* */
3
3
  const tabList = "flow--tabs--tab-list";
4
+ const activeIndicator = "flow--tabs--tab-list--active-indicator";
5
+ const animated = "flow--tabs--tab-list--animated";
4
6
  const contextMenuButton = "flow--tabs--tab-list--context-menu-button";
5
7
  const titles = "flow--tabs--tab-list--titles";
6
8
  const collapsed = "flow--tabs--tab-list--collapsed";
7
9
  const styles = {
8
10
  tabList: tabList,
11
+ activeIndicator: activeIndicator,
12
+ animated: animated,
9
13
  contextMenuButton: contextMenuButton,
10
14
  titles: titles,
11
15
  collapsed: collapsed
12
16
  };
13
17
 
14
- export { collapsed, contextMenuButton, styles as default, tabList, titles };
18
+ export { activeIndicator, animated, collapsed, contextMenuButton, styles as default, tabList, titles };
15
19
  //# sourceMappingURL=TabList.module.scss.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"TabList.module.scss.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;"}
1
+ {"version":3,"file":"TabList.module.scss.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;"}
@@ -0,0 +1,61 @@
1
+ "use client"
2
+ /* */
3
+ import { useRef, useState, useLayoutEffect } from 'react';
4
+ import { createFrameResizeObserver } from '../../../lib/dom/createFrameResizeObserver.mjs';
5
+
6
+ const getTabIndicatorStyle = (state) => state && {
7
+ "--tab-indicator-x": `${state.x}px`,
8
+ "--tab-indicator-width": `${state.width}px`
9
+ };
10
+ const useTabIndicator = (isCollapsed) => {
11
+ const rootRef = useRef(null);
12
+ const titlesRef = useRef(null);
13
+ const hasMeasuredRef = useRef(false);
14
+ const [indicator, setIndicator] = useState();
15
+ const resetIndicator = () => {
16
+ hasMeasuredRef.current = false;
17
+ setIndicator(void 0);
18
+ };
19
+ useLayoutEffect(() => {
20
+ const root = rootRef.current;
21
+ const titles = titlesRef.current;
22
+ if (!root || !titles || isCollapsed) {
23
+ resetIndicator();
24
+ return;
25
+ }
26
+ const measureIndicator = () => {
27
+ const selectedTab = titles.querySelector("[data-selected]");
28
+ if (!selectedTab) {
29
+ resetIndicator();
30
+ return;
31
+ }
32
+ const rootRect = root.getBoundingClientRect();
33
+ const selectedTabRect = selectedTab.getBoundingClientRect();
34
+ const nextIndicator = {
35
+ x: selectedTabRect.left - rootRect.left,
36
+ width: selectedTabRect.width,
37
+ isAnimated: hasMeasuredRef.current
38
+ };
39
+ setIndicator((previousIndicator) => {
40
+ if (previousIndicator && previousIndicator.x === nextIndicator.x && previousIndicator.width === nextIndicator.width && previousIndicator.isAnimated === nextIndicator.isAnimated) {
41
+ return previousIndicator;
42
+ }
43
+ return nextIndicator;
44
+ });
45
+ hasMeasuredRef.current = true;
46
+ };
47
+ measureIndicator();
48
+ const observer = createFrameResizeObserver(measureIndicator);
49
+ observer.observe([root, titles]);
50
+ return () => observer.disconnect();
51
+ });
52
+ return {
53
+ rootRef,
54
+ titlesRef,
55
+ indicatorStyle: getTabIndicatorStyle(indicator),
56
+ isAnimated: indicator?.isAnimated ?? false
57
+ };
58
+ };
59
+
60
+ export { useTabIndicator };
61
+ //# sourceMappingURL=useTabIndicator.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useTabIndicator.mjs","sources":["../../../../../../../../src/components/Tabs/lib/useTabIndicator.ts"],"sourcesContent":["import type { CSSProperties } from \"react\";\nimport { useLayoutEffect, useRef, useState } from \"react\";\nimport { createFrameResizeObserver } from \"@/lib/dom/createFrameResizeObserver\";\n\ninterface TabIndicatorState {\n x: number;\n width: number;\n isAnimated: boolean;\n}\n\ninterface TabIndicatorStyle extends CSSProperties {\n \"--tab-indicator-x\": string;\n \"--tab-indicator-width\": string;\n}\n\nconst getTabIndicatorStyle = (\n state: TabIndicatorState | undefined,\n): TabIndicatorStyle | undefined =>\n state && {\n \"--tab-indicator-x\": `${state.x}px`,\n \"--tab-indicator-width\": `${state.width}px`,\n };\n\nexport const useTabIndicator = (isCollapsed: boolean) => {\n const rootRef = useRef<HTMLDivElement | null>(null);\n const titlesRef = useRef<HTMLDivElement | null>(null);\n const hasMeasuredRef = useRef(false);\n const [indicator, setIndicator] = useState<TabIndicatorState | undefined>();\n\n const resetIndicator = () => {\n hasMeasuredRef.current = false;\n // React bails out of the re-render when the state is already `undefined`.\n setIndicator(undefined);\n };\n\n useLayoutEffect(() => {\n const root = rootRef.current;\n const titles = titlesRef.current;\n\n if (!root || !titles || isCollapsed) {\n resetIndicator();\n return;\n }\n\n const measureIndicator = () => {\n const selectedTab = titles.querySelector<HTMLElement>(\"[data-selected]\");\n\n if (!selectedTab) {\n resetIndicator();\n return;\n }\n\n const rootRect = root.getBoundingClientRect();\n const selectedTabRect = selectedTab.getBoundingClientRect();\n const nextIndicator: TabIndicatorState = {\n x: selectedTabRect.left - rootRect.left,\n width: selectedTabRect.width,\n isAnimated: hasMeasuredRef.current,\n };\n\n setIndicator((previousIndicator) => {\n if (\n previousIndicator &&\n previousIndicator.x === nextIndicator.x &&\n previousIndicator.width === nextIndicator.width &&\n previousIndicator.isAnimated === nextIndicator.isAnimated\n ) {\n return previousIndicator;\n }\n\n return nextIndicator;\n });\n\n hasMeasuredRef.current = true;\n };\n\n measureIndicator();\n\n const observer = createFrameResizeObserver(measureIndicator);\n observer.observe([root, titles]);\n\n return () => observer.disconnect();\n });\n\n return {\n rootRef,\n titlesRef,\n indicatorStyle: getTabIndicatorStyle(indicator),\n isAnimated: indicator?.isAnimated ?? false,\n };\n};\n"],"names":[],"mappings":";;;AAeA,MAAM,oBAAA,GAAuB,CAC3B,KAAA,KAEA,KAAA,IAAS;AAAA,EACP,mBAAA,EAAqB,CAAA,EAAG,KAAA,CAAM,CAAC,CAAA,EAAA,CAAA;AAAA,EAC/B,uBAAA,EAAyB,CAAA,EAAG,KAAA,CAAM,KAAK,CAAA,EAAA;AACzC,CAAA;AAEK,MAAM,eAAA,GAAkB,CAAC,WAAA,KAAyB;AACvD,EAAA,MAAM,OAAA,GAAU,OAA8B,IAAI,CAAA;AAClD,EAAA,MAAM,SAAA,GAAY,OAA8B,IAAI,CAAA;AACpD,EAAA,MAAM,cAAA,GAAiB,OAAO,KAAK,CAAA;AACnC,EAAA,MAAM,CAAC,SAAA,EAAW,YAAY,CAAA,GAAI,QAAA,EAAwC;AAE1E,EAAA,MAAM,iBAAiB,MAAM;AAC3B,IAAA,cAAA,CAAe,OAAA,GAAU,KAAA;AAEzB,IAAA,YAAA,CAAa,MAAS,CAAA;AAAA,EACxB,CAAA;AAEA,EAAA,eAAA,CAAgB,MAAM;AACpB,IAAA,MAAM,OAAO,OAAA,CAAQ,OAAA;AACrB,IAAA,MAAM,SAAS,SAAA,CAAU,OAAA;AAEzB,IAAA,IAAI,CAAC,IAAA,IAAQ,CAAC,MAAA,IAAU,WAAA,EAAa;AACnC,MAAA,cAAA,EAAe;AACf,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,mBAAmB,MAAM;AAC7B,MAAA,MAAM,WAAA,GAAc,MAAA,CAAO,aAAA,CAA2B,iBAAiB,CAAA;AAEvE,MAAA,IAAI,CAAC,WAAA,EAAa;AAChB,QAAA,cAAA,EAAe;AACf,QAAA;AAAA,MACF;AAEA,MAAA,MAAM,QAAA,GAAW,KAAK,qBAAA,EAAsB;AAC5C,MAAA,MAAM,eAAA,GAAkB,YAAY,qBAAA,EAAsB;AAC1D,MAAA,MAAM,aAAA,GAAmC;AAAA,QACvC,CAAA,EAAG,eAAA,CAAgB,IAAA,GAAO,QAAA,CAAS,IAAA;AAAA,QACnC,OAAO,eAAA,CAAgB,KAAA;AAAA,QACvB,YAAY,cAAA,CAAe;AAAA,OAC7B;AAEA,MAAA,YAAA,CAAa,CAAC,iBAAA,KAAsB;AAClC,QAAA,IACE,iBAAA,IACA,iBAAA,CAAkB,CAAA,KAAM,aAAA,CAAc,CAAA,IACtC,iBAAA,CAAkB,KAAA,KAAU,aAAA,CAAc,KAAA,IAC1C,iBAAA,CAAkB,UAAA,KAAe,aAAA,CAAc,UAAA,EAC/C;AACA,UAAA,OAAO,iBAAA;AAAA,QACT;AAEA,QAAA,OAAO,aAAA;AAAA,MACT,CAAC,CAAA;AAED,MAAA,cAAA,CAAe,OAAA,GAAU,IAAA;AAAA,IAC3B,CAAA;AAEA,IAAA,gBAAA,EAAiB;AAEjB,IAAA,MAAM,QAAA,GAAW,0BAA0B,gBAAgB,CAAA;AAC3D,IAAA,QAAA,CAAS,OAAA,CAAQ,CAAC,IAAA,EAAM,MAAM,CAAC,CAAA;AAE/B,IAAA,OAAO,MAAM,SAAS,UAAA,EAAW;AAAA,EACnC,CAAC,CAAA;AAED,EAAA,OAAO;AAAA,IACL,OAAA;AAAA,IACA,SAAA;AAAA,IACA,cAAA,EAAgB,qBAAqB,SAAS,CAAA;AAAA,IAC9C,UAAA,EAAY,WAAW,UAAA,IAAc;AAAA,GACvC;AACF;;;;"}
@@ -38,6 +38,7 @@ const propsContextSupportingComponentsMap = {
38
38
  FileDropZone: true,
39
39
  Header: true,
40
40
  Heading: true,
41
+ TabNavigation: true,
41
42
  Icon: true,
42
43
  IllustratedMessage: true,
43
44
  Image: true,