@entur/tab 1.0.0-alpha.0 → 1.0.0-next.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,199 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const utils = require("@entur/utils");
4
+ const jsxRuntime = require("react/jsx-runtime");
5
+ const React = require("react");
6
+ const classNames = require("classnames");
7
+ const TabsContext = React.createContext({
8
+ selectedIndex: 0,
9
+ onSelect: () => void 0,
10
+ tabsId: ""
11
+ });
12
+ const TabItemContext = React.createContext(
13
+ null
14
+ );
15
+ const TabPanelItemContext = React.createContext(null);
16
+ const Tab = ({
17
+ className,
18
+ removeActiveLine = false,
19
+ as,
20
+ disabled = false,
21
+ children,
22
+ ...rest
23
+ }) => {
24
+ const { selectedIndex, onSelect } = React.useContext(TabsContext);
25
+ const itemContext = React.useContext(TabItemContext);
26
+ const tabIndex = itemContext?.tabIndex ?? 0;
27
+ const isSelected = selectedIndex === tabIndex;
28
+ const Element = as || "button";
29
+ return /* @__PURE__ */ jsxRuntime.jsx(
30
+ Element,
31
+ {
32
+ role: "tab",
33
+ type: as ? void 0 : "button",
34
+ id: itemContext?.tabId,
35
+ "aria-selected": isSelected,
36
+ "aria-controls": itemContext?.panelId,
37
+ tabIndex: isSelected ? 0 : -1,
38
+ disabled: disabled || void 0,
39
+ "aria-disabled": disabled || void 0,
40
+ className: classNames(
41
+ "eds-tab",
42
+ { "eds-tab--remove-active-line": removeActiveLine },
43
+ className
44
+ ),
45
+ onClick: () => {
46
+ if (!disabled) onSelect(tabIndex);
47
+ },
48
+ ...rest,
49
+ children
50
+ }
51
+ );
52
+ };
53
+ const Tabs = ({
54
+ className,
55
+ index,
56
+ defaultIndex,
57
+ onChange,
58
+ as,
59
+ children,
60
+ ...rest
61
+ }) => {
62
+ const [internalIndex, setInternalIndex] = React.useState(defaultIndex ?? 0);
63
+ const isControlled = index !== void 0;
64
+ const selectedIndex = isControlled ? index : internalIndex;
65
+ const tabsId = React.useId();
66
+ const onSelect = React.useCallback(
67
+ (i) => {
68
+ if (!isControlled) {
69
+ setInternalIndex(i);
70
+ }
71
+ onChange?.(i);
72
+ },
73
+ [isControlled, onChange]
74
+ );
75
+ const Element = as || "div";
76
+ return /* @__PURE__ */ jsxRuntime.jsx(TabsContext.Provider, { value: { selectedIndex, onSelect, tabsId }, children: /* @__PURE__ */ jsxRuntime.jsx(Element, { className: classNames("eds-tabs", className), ...rest, children }) });
77
+ };
78
+ const TabPanel = ({
79
+ className,
80
+ as,
81
+ children,
82
+ ...rest
83
+ }) => {
84
+ const { selectedIndex } = React.useContext(TabsContext);
85
+ const itemContext = React.useContext(TabPanelItemContext);
86
+ const tabIndex = itemContext?.tabIndex ?? 0;
87
+ const keepMounted = itemContext?.keepMounted ?? false;
88
+ const isSelected = selectedIndex === tabIndex;
89
+ const isHiddenButMounted = keepMounted && !isSelected;
90
+ if (!isSelected && !keepMounted) return null;
91
+ const Element = as || "div";
92
+ return /* @__PURE__ */ jsxRuntime.jsx(
93
+ Element,
94
+ {
95
+ role: "tabpanel",
96
+ id: itemContext?.panelId,
97
+ "aria-labelledby": itemContext?.tabId,
98
+ tabIndex: isSelected ? 0 : -1,
99
+ hidden: isHiddenButMounted || void 0,
100
+ className: classNames("eds-tab-panel", className),
101
+ ...rest,
102
+ children
103
+ }
104
+ );
105
+ };
106
+ const TabPanels = ({
107
+ className,
108
+ as,
109
+ keepMounted = false,
110
+ children,
111
+ ...rest
112
+ }) => {
113
+ const { tabsId } = React.useContext(TabsContext);
114
+ const Element = as || "div";
115
+ return /* @__PURE__ */ jsxRuntime.jsx(Element, { className: classNames("eds-tab-panels", className), ...rest, children: React.Children.map(children, (child, idx) => /* @__PURE__ */ jsxRuntime.jsx(
116
+ TabPanelItemContext.Provider,
117
+ {
118
+ value: {
119
+ tabIndex: idx,
120
+ tabId: `${tabsId}-tab-${idx}`,
121
+ panelId: `${tabsId}-panel-${idx}`,
122
+ keepMounted
123
+ },
124
+ children: child
125
+ }
126
+ )) });
127
+ };
128
+ const TabList = ({
129
+ className,
130
+ width,
131
+ as,
132
+ children,
133
+ ...rest
134
+ }) => {
135
+ const { tabsId } = React.useContext(TabsContext);
136
+ const tabListRef = React.useRef(null);
137
+ const handleKeyDown = React.useCallback((e) => {
138
+ const tabs = tabListRef.current?.querySelectorAll(
139
+ '[role="tab"]:not([disabled])'
140
+ );
141
+ if (!tabs || tabs.length === 0) return;
142
+ const currentIndex = Array.from(tabs).findIndex(
143
+ (tab) => tab === document.activeElement
144
+ );
145
+ if (currentIndex === -1) return;
146
+ let nextIndex;
147
+ switch (e.key) {
148
+ case "ArrowRight":
149
+ nextIndex = (currentIndex + 1) % tabs.length;
150
+ break;
151
+ case "ArrowLeft":
152
+ nextIndex = (currentIndex - 1 + tabs.length) % tabs.length;
153
+ break;
154
+ case "Home":
155
+ nextIndex = 0;
156
+ break;
157
+ case "End":
158
+ nextIndex = tabs.length - 1;
159
+ break;
160
+ }
161
+ if (nextIndex !== void 0) {
162
+ e.preventDefault();
163
+ tabs[nextIndex].focus();
164
+ tabs[nextIndex].click();
165
+ }
166
+ }, []);
167
+ const Element = as || "div";
168
+ return /* @__PURE__ */ jsxRuntime.jsx(
169
+ Element,
170
+ {
171
+ role: "tablist",
172
+ tabIndex: -1,
173
+ ref: tabListRef,
174
+ className: classNames("eds-tab-list", className, {
175
+ "eds-tab-list--width-fluid": width === "fluid"
176
+ }),
177
+ onKeyDown: handleKeyDown,
178
+ ...rest,
179
+ children: React.Children.map(children, (child, idx) => /* @__PURE__ */ jsxRuntime.jsx(
180
+ TabItemContext.Provider,
181
+ {
182
+ value: {
183
+ tabIndex: idx,
184
+ tabId: `${tabsId}-tab-${idx}`,
185
+ panelId: `${tabsId}-panel-${idx}`
186
+ },
187
+ children: child
188
+ }
189
+ ))
190
+ }
191
+ );
192
+ };
193
+ utils.warnAboutMissingStyles("tab");
194
+ exports.Tab = Tab;
195
+ exports.TabList = TabList;
196
+ exports.TabPanel = TabPanel;
197
+ exports.TabPanels = TabPanels;
198
+ exports.Tabs = Tabs;
199
+ //# sourceMappingURL=tab.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tab.cjs.js","sources":["../src/TabsContext.tsx","../src/Tab.tsx","../src/Tabs.tsx","../src/TabPanel.tsx","../src/TabPanels.tsx","../src/TabList.tsx","../src/index.tsx"],"sourcesContent":["import React from 'react';\n\nexport type TabsContextValue = {\n selectedIndex: number;\n onSelect: (index: number) => void;\n tabsId: string;\n};\n\nexport const TabsContext = React.createContext<TabsContextValue>({\n selectedIndex: 0,\n onSelect: () => undefined,\n tabsId: '',\n});\n\nexport type TabItemContextValue = {\n tabIndex: number;\n tabId: string;\n panelId: string;\n};\n\nexport const TabItemContext = React.createContext<TabItemContextValue | null>(\n null,\n);\n\nexport type TabPanelItemContextValue = {\n tabIndex: number;\n tabId: string;\n panelId: string;\n keepMounted: boolean;\n};\n\nexport const TabPanelItemContext =\n React.createContext<TabPanelItemContextValue | null>(null);\n","import React, { useContext } from 'react';\nimport classNames from 'classnames';\n\nimport { TabItemContext, TabsContext } from './TabsContext';\n\nexport type TabProps = {\n /** Overskriften til taben */\n children: React.ReactNode;\n /** Om taben er disabled eller ikke */\n disabled?: boolean;\n /** HTML-elementet eller React-komponenten som lager komponenten */\n as?: keyof JSX.IntrinsicElements | React.ElementType;\n removeActiveLine?: boolean;\n className?: string;\n} & Omit<React.ComponentPropsWithoutRef<'button'>, 'children' | 'disabled'>;\n\nexport const Tab = ({\n className,\n removeActiveLine = false,\n as,\n disabled = false,\n children,\n ...rest\n}: TabProps) => {\n const { selectedIndex, onSelect } = useContext(TabsContext);\n const itemContext = useContext(TabItemContext);\n const tabIndex = itemContext?.tabIndex ?? 0;\n const isSelected = selectedIndex === tabIndex;\n const Element: React.ElementType = as || 'button';\n\n return (\n <Element\n role=\"tab\"\n type={as ? undefined : 'button'}\n id={itemContext?.tabId}\n aria-selected={isSelected}\n aria-controls={itemContext?.panelId}\n tabIndex={isSelected ? 0 : -1}\n disabled={disabled || undefined}\n aria-disabled={disabled || undefined}\n className={classNames(\n 'eds-tab',\n { 'eds-tab--remove-active-line': removeActiveLine },\n className,\n )}\n onClick={() => {\n if (!disabled) onSelect(tabIndex);\n }}\n {...rest}\n >\n {children}\n </Element>\n );\n};\n","import React, { useCallback, useId, useState } from 'react';\nimport classNames from 'classnames';\n\nimport { TabsContext } from './TabsContext';\n\nexport type TabsProps = {\n /** Tab-innholdet */\n children: React.ReactNode;\n /** Kalles når taben endres */\n onChange?: (index: number) => void;\n /** Hvilken tab som skal være åpen by default */\n defaultIndex?: number;\n /** Den åpne indexen (kontrollert) */\n index?: number;\n /** HTML-elementet eller React-komponenten som lager komponenten */\n as?: keyof JSX.IntrinsicElements | React.ElementType;\n className?: string;\n} & Omit<React.ComponentPropsWithoutRef<'div'>, 'children' | 'onChange'>;\n\nexport const Tabs = ({\n className,\n index,\n defaultIndex,\n onChange,\n as,\n children,\n ...rest\n}: TabsProps) => {\n const [internalIndex, setInternalIndex] = useState(defaultIndex ?? 0);\n const isControlled = index !== undefined;\n const selectedIndex = isControlled ? index : internalIndex;\n const tabsId = useId();\n\n const onSelect = useCallback(\n (i: number) => {\n if (!isControlled) {\n setInternalIndex(i);\n }\n onChange?.(i);\n },\n [isControlled, onChange],\n );\n\n const Element: React.ElementType = as || 'div';\n\n return (\n <TabsContext.Provider value={{ selectedIndex, onSelect, tabsId }}>\n <Element className={classNames('eds-tabs', className)} {...rest}>\n {children}\n </Element>\n </TabsContext.Provider>\n );\n};\n","import React, { useContext } from 'react';\nimport classNames from 'classnames';\n\nimport { TabPanelItemContext, TabsContext } from './TabsContext';\n\nexport type TabPanelProps = {\n /** Innholdet i tab-panelet */\n children?: React.ReactNode;\n /** HTML-elementet eller React-komponenten som lager komponenten */\n as?: keyof JSX.IntrinsicElements | React.ElementType;\n className?: string;\n} & Omit<React.ComponentPropsWithoutRef<'div'>, 'children'>;\n\nexport const TabPanel = ({\n className,\n as,\n children,\n ...rest\n}: TabPanelProps) => {\n const { selectedIndex } = useContext(TabsContext);\n const itemContext = useContext(TabPanelItemContext);\n const tabIndex = itemContext?.tabIndex ?? 0;\n const keepMounted = itemContext?.keepMounted ?? false;\n\n const isSelected = selectedIndex === tabIndex;\n const isHiddenButMounted = keepMounted && !isSelected;\n\n if (!isSelected && !keepMounted) return null;\n\n const Element: React.ElementType = as || 'div';\n\n return (\n <Element\n role=\"tabpanel\"\n id={itemContext?.panelId}\n aria-labelledby={itemContext?.tabId}\n tabIndex={isSelected ? 0 : -1}\n hidden={isHiddenButMounted || undefined}\n className={classNames('eds-tab-panel', className)}\n {...rest}\n >\n {children}\n </Element>\n );\n};\n","import React, { useContext } from 'react';\nimport classNames from 'classnames';\n\nimport { TabPanelItemContext, TabsContext } from './TabsContext';\n\nexport type TabPanelsProps = {\n /** Tab-panelene */\n children: React.ReactNode;\n /** HTML-elementet eller React-komponenten som lager komponenten */\n as?: keyof JSX.IntrinsicElements | React.ElementType;\n /** Behold alle panel-noder i DOM (skjult med hidden-attributt) i stedet for å avmontere */\n keepMounted?: boolean;\n className?: string;\n} & Omit<React.ComponentPropsWithoutRef<'div'>, 'children'>;\n\nexport const TabPanels = ({\n className,\n as,\n keepMounted = false,\n children,\n ...rest\n}: TabPanelsProps) => {\n const { tabsId } = useContext(TabsContext);\n\n const Element: React.ElementType = as || 'div';\n\n return (\n <Element className={classNames('eds-tab-panels', className)} {...rest}>\n {React.Children.map(children, (child, idx) => (\n <TabPanelItemContext.Provider\n value={{\n tabIndex: idx,\n tabId: `${tabsId}-tab-${idx}`,\n panelId: `${tabsId}-panel-${idx}`,\n keepMounted,\n }}\n >\n {child}\n </TabPanelItemContext.Provider>\n ))}\n </Element>\n );\n};\n","import React, { useCallback, useContext, useRef } from 'react';\nimport classNames from 'classnames';\n\nimport { TabItemContext, TabsContext } from './TabsContext';\n\nexport type TabListProps = {\n /** Tab-komponenter */\n children: React.ReactNode;\n /** HTML-elementet eller React-komponenten som lager komponenten */\n as?: keyof JSX.IntrinsicElements | React.ElementType;\n width?: 'fluid';\n className?: string;\n /** Tilgjengelig navn på tab-listen (dersom det ikke finnes en synlig overskrift) */\n 'aria-label'?: string;\n /** ID til elementet som navngir tab-listen */\n 'aria-labelledby'?: string;\n} & Omit<React.ComponentPropsWithoutRef<'div'>, 'children'>;\n\nexport const TabList = ({\n className,\n width,\n as,\n children,\n ...rest\n}: TabListProps) => {\n const { tabsId } = useContext(TabsContext);\n const tabListRef = useRef<HTMLElement>(null);\n\n const handleKeyDown = useCallback((e: React.KeyboardEvent) => {\n const tabs = tabListRef.current?.querySelectorAll<HTMLElement>(\n '[role=\"tab\"]:not([disabled])',\n );\n if (!tabs || tabs.length === 0) return;\n\n const currentIndex = Array.from(tabs).findIndex(\n tab => tab === document.activeElement,\n );\n if (currentIndex === -1) return;\n\n let nextIndex: number | undefined;\n switch (e.key) {\n case 'ArrowRight':\n nextIndex = (currentIndex + 1) % tabs.length;\n break;\n case 'ArrowLeft':\n nextIndex = (currentIndex - 1 + tabs.length) % tabs.length;\n break;\n case 'Home':\n nextIndex = 0;\n break;\n case 'End':\n nextIndex = tabs.length - 1;\n break;\n }\n\n if (nextIndex !== undefined) {\n e.preventDefault();\n tabs[nextIndex].focus();\n tabs[nextIndex].click();\n }\n }, []);\n\n const Element: React.ElementType = as || 'div';\n\n return (\n <Element\n role=\"tablist\"\n tabIndex={-1}\n ref={tabListRef}\n className={classNames('eds-tab-list', className, {\n 'eds-tab-list--width-fluid': width === 'fluid',\n })}\n onKeyDown={handleKeyDown}\n {...rest}\n >\n {React.Children.map(children, (child, idx) => (\n <TabItemContext.Provider\n value={{\n tabIndex: idx,\n tabId: `${tabsId}-tab-${idx}`,\n panelId: `${tabsId}-panel-${idx}`,\n }}\n >\n {child}\n </TabItemContext.Provider>\n ))}\n </Element>\n );\n};\n","import { warnAboutMissingStyles } from '@entur/utils';\nimport './index.scss';\n\nwarnAboutMissingStyles('tab');\n\nexport * from './Tab';\nexport * from './Tabs';\nexport * from './TabPanel';\nexport * from './TabPanels';\nexport * from './TabList';\n"],"names":["useContext","jsx","useState","useId","useCallback","useRef","warnAboutMissingStyles"],"mappings":"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"}
package/dist/tab.esm.js CHANGED
@@ -1,90 +1,199 @@
1
- import { warnAboutMissingStyles } from '@entur/utils';
2
- import React from 'react';
3
- import { Tab as Tab$1, Tabs as Tabs$1, TabPanel as TabPanel$1, TabPanels as TabPanels$1, TabList as TabList$1 } from '@reach/tabs';
4
- import classNames from 'classnames';
5
-
6
- function _extends() {
7
- _extends = Object.assign ? Object.assign.bind() : function (target) {
8
- for (var i = 1; i < arguments.length; i++) {
9
- var source = arguments[i];
10
- for (var key in source) {
11
- if (Object.prototype.hasOwnProperty.call(source, key)) {
12
- target[key] = source[key];
13
- }
14
- }
1
+ import { warnAboutMissingStyles } from "@entur/utils";
2
+ import { jsx } from "react/jsx-runtime";
3
+ import React, { useContext, useState, useId, useCallback, useRef } from "react";
4
+ import classNames from "classnames";
5
+ const TabsContext = React.createContext({
6
+ selectedIndex: 0,
7
+ onSelect: () => void 0,
8
+ tabsId: ""
9
+ });
10
+ const TabItemContext = React.createContext(
11
+ null
12
+ );
13
+ const TabPanelItemContext = React.createContext(null);
14
+ const Tab = ({
15
+ className,
16
+ removeActiveLine = false,
17
+ as,
18
+ disabled = false,
19
+ children,
20
+ ...rest
21
+ }) => {
22
+ const { selectedIndex, onSelect } = useContext(TabsContext);
23
+ const itemContext = useContext(TabItemContext);
24
+ const tabIndex = itemContext?.tabIndex ?? 0;
25
+ const isSelected = selectedIndex === tabIndex;
26
+ const Element = as || "button";
27
+ return /* @__PURE__ */ jsx(
28
+ Element,
29
+ {
30
+ role: "tab",
31
+ type: as ? void 0 : "button",
32
+ id: itemContext?.tabId,
33
+ "aria-selected": isSelected,
34
+ "aria-controls": itemContext?.panelId,
35
+ tabIndex: isSelected ? 0 : -1,
36
+ disabled: disabled || void 0,
37
+ "aria-disabled": disabled || void 0,
38
+ className: classNames(
39
+ "eds-tab",
40
+ { "eds-tab--remove-active-line": removeActiveLine },
41
+ className
42
+ ),
43
+ onClick: () => {
44
+ if (!disabled) onSelect(tabIndex);
45
+ },
46
+ ...rest,
47
+ children
15
48
  }
16
- return target;
17
- };
18
- return _extends.apply(this, arguments);
19
- }
20
- function _objectWithoutPropertiesLoose(source, excluded) {
21
- if (source == null) return {};
22
- var target = {};
23
- var sourceKeys = Object.keys(source);
24
- var key, i;
25
- for (i = 0; i < sourceKeys.length; i++) {
26
- key = sourceKeys[i];
27
- if (excluded.indexOf(key) >= 0) continue;
28
- target[key] = source[key];
29
- }
30
- return target;
31
- }
32
-
33
- var _excluded$4 = ["className", "removeActiveLine"];
34
- var Tab = function Tab(_ref) {
35
- var className = _ref.className,
36
- _ref$removeActiveLine = _ref.removeActiveLine,
37
- removeActiveLine = _ref$removeActiveLine === void 0 ? false : _ref$removeActiveLine,
38
- rest = _objectWithoutPropertiesLoose(_ref, _excluded$4);
39
- return React.createElement(Tab$1, _extends({
40
- className: classNames('eds-tab', {
41
- 'eds-tab--remove-active-line': removeActiveLine
42
- }, className)
43
- }, rest));
49
+ );
44
50
  };
45
-
46
- var _excluded$3 = ["className"];
47
- var Tabs = function Tabs(_ref) {
48
- var className = _ref.className,
49
- rest = _objectWithoutPropertiesLoose(_ref, _excluded$3);
50
- return React.createElement(Tabs$1, _extends({
51
- className: classNames('eds-tabs', className)
52
- }, rest));
51
+ const Tabs = ({
52
+ className,
53
+ index,
54
+ defaultIndex,
55
+ onChange,
56
+ as,
57
+ children,
58
+ ...rest
59
+ }) => {
60
+ const [internalIndex, setInternalIndex] = useState(defaultIndex ?? 0);
61
+ const isControlled = index !== void 0;
62
+ const selectedIndex = isControlled ? index : internalIndex;
63
+ const tabsId = useId();
64
+ const onSelect = useCallback(
65
+ (i) => {
66
+ if (!isControlled) {
67
+ setInternalIndex(i);
68
+ }
69
+ onChange?.(i);
70
+ },
71
+ [isControlled, onChange]
72
+ );
73
+ const Element = as || "div";
74
+ return /* @__PURE__ */ jsx(TabsContext.Provider, { value: { selectedIndex, onSelect, tabsId }, children: /* @__PURE__ */ jsx(Element, { className: classNames("eds-tabs", className), ...rest, children }) });
75
+ };
76
+ const TabPanel = ({
77
+ className,
78
+ as,
79
+ children,
80
+ ...rest
81
+ }) => {
82
+ const { selectedIndex } = useContext(TabsContext);
83
+ const itemContext = useContext(TabPanelItemContext);
84
+ const tabIndex = itemContext?.tabIndex ?? 0;
85
+ const keepMounted = itemContext?.keepMounted ?? false;
86
+ const isSelected = selectedIndex === tabIndex;
87
+ const isHiddenButMounted = keepMounted && !isSelected;
88
+ if (!isSelected && !keepMounted) return null;
89
+ const Element = as || "div";
90
+ return /* @__PURE__ */ jsx(
91
+ Element,
92
+ {
93
+ role: "tabpanel",
94
+ id: itemContext?.panelId,
95
+ "aria-labelledby": itemContext?.tabId,
96
+ tabIndex: isSelected ? 0 : -1,
97
+ hidden: isHiddenButMounted || void 0,
98
+ className: classNames("eds-tab-panel", className),
99
+ ...rest,
100
+ children
101
+ }
102
+ );
53
103
  };
54
-
55
- var _excluded$2 = ["className"];
56
- var TabPanel = function TabPanel(_ref) {
57
- var className = _ref.className,
58
- rest = _objectWithoutPropertiesLoose(_ref, _excluded$2);
59
- return React.createElement(TabPanel$1, _extends({
60
- className: classNames('eds-tab-panel', className)
61
- }, rest, {
62
- tabIndex: undefined
63
- }));
104
+ const TabPanels = ({
105
+ className,
106
+ as,
107
+ keepMounted = false,
108
+ children,
109
+ ...rest
110
+ }) => {
111
+ const { tabsId } = useContext(TabsContext);
112
+ const Element = as || "div";
113
+ return /* @__PURE__ */ jsx(Element, { className: classNames("eds-tab-panels", className), ...rest, children: React.Children.map(children, (child, idx) => /* @__PURE__ */ jsx(
114
+ TabPanelItemContext.Provider,
115
+ {
116
+ value: {
117
+ tabIndex: idx,
118
+ tabId: `${tabsId}-tab-${idx}`,
119
+ panelId: `${tabsId}-panel-${idx}`,
120
+ keepMounted
121
+ },
122
+ children: child
123
+ }
124
+ )) });
64
125
  };
65
-
66
- var _excluded$1 = ["className"];
67
- var TabPanels = function TabPanels(_ref) {
68
- var className = _ref.className,
69
- rest = _objectWithoutPropertiesLoose(_ref, _excluded$1);
70
- return React.createElement(TabPanels$1, _extends({
71
- className: classNames('eds-tab-panels', className)
72
- }, rest));
126
+ const TabList = ({
127
+ className,
128
+ width,
129
+ as,
130
+ children,
131
+ ...rest
132
+ }) => {
133
+ const { tabsId } = useContext(TabsContext);
134
+ const tabListRef = useRef(null);
135
+ const handleKeyDown = useCallback((e) => {
136
+ const tabs = tabListRef.current?.querySelectorAll(
137
+ '[role="tab"]:not([disabled])'
138
+ );
139
+ if (!tabs || tabs.length === 0) return;
140
+ const currentIndex = Array.from(tabs).findIndex(
141
+ (tab) => tab === document.activeElement
142
+ );
143
+ if (currentIndex === -1) return;
144
+ let nextIndex;
145
+ switch (e.key) {
146
+ case "ArrowRight":
147
+ nextIndex = (currentIndex + 1) % tabs.length;
148
+ break;
149
+ case "ArrowLeft":
150
+ nextIndex = (currentIndex - 1 + tabs.length) % tabs.length;
151
+ break;
152
+ case "Home":
153
+ nextIndex = 0;
154
+ break;
155
+ case "End":
156
+ nextIndex = tabs.length - 1;
157
+ break;
158
+ }
159
+ if (nextIndex !== void 0) {
160
+ e.preventDefault();
161
+ tabs[nextIndex].focus();
162
+ tabs[nextIndex].click();
163
+ }
164
+ }, []);
165
+ const Element = as || "div";
166
+ return /* @__PURE__ */ jsx(
167
+ Element,
168
+ {
169
+ role: "tablist",
170
+ tabIndex: -1,
171
+ ref: tabListRef,
172
+ className: classNames("eds-tab-list", className, {
173
+ "eds-tab-list--width-fluid": width === "fluid"
174
+ }),
175
+ onKeyDown: handleKeyDown,
176
+ ...rest,
177
+ children: React.Children.map(children, (child, idx) => /* @__PURE__ */ jsx(
178
+ TabItemContext.Provider,
179
+ {
180
+ value: {
181
+ tabIndex: idx,
182
+ tabId: `${tabsId}-tab-${idx}`,
183
+ panelId: `${tabsId}-panel-${idx}`
184
+ },
185
+ children: child
186
+ }
187
+ ))
188
+ }
189
+ );
73
190
  };
74
-
75
- var _excluded = ["className", "width"];
76
- var TabList = function TabList(_ref) {
77
- var className = _ref.className,
78
- width = _ref.width,
79
- rest = _objectWithoutPropertiesLoose(_ref, _excluded);
80
- return React.createElement(TabList$1, _extends({
81
- className: classNames('eds-tab-list', className, {
82
- 'eds-tab-list--width-fluid': width === 'fluid'
83
- })
84
- }, rest));
191
+ warnAboutMissingStyles("tab");
192
+ export {
193
+ Tab,
194
+ TabList,
195
+ TabPanel,
196
+ TabPanels,
197
+ Tabs
85
198
  };
86
-
87
- warnAboutMissingStyles('tab');
88
-
89
- export { Tab, TabList, TabPanel, TabPanels, Tabs };
90
199
  //# sourceMappingURL=tab.esm.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"tab.esm.js","sources":["../src/Tab.tsx","../src/Tabs.tsx","../src/TabPanel.tsx","../src/TabPanels.tsx","../src/TabList.tsx","../src/index.tsx"],"sourcesContent":["import React from 'react';\nimport { Tab as ReachTab } from '@reach/tabs';\nimport classNames from 'classnames';\n\nexport type TabProps = {\n /** Overskriften til taben */\n children: React.ReactNode;\n /** Om taben er disabled eller ikke */\n disabled?: boolean;\n /** HTML-elementet eller React-komponenten som lager komponenten */\n as?: keyof JSX.IntrinsicElements | any;\n removeActiveLine?: boolean;\n [key: string]: any;\n};\n\nexport const Tab: React.FC<TabProps> = ({\n className,\n removeActiveLine = false,\n ...rest\n}) => {\n return (\n <ReachTab\n className={classNames(\n 'eds-tab',\n { 'eds-tab--remove-active-line': removeActiveLine },\n className,\n )}\n {...rest}\n />\n );\n};\n","import React from 'react';\nimport { Tabs as ReachTabs } from '@reach/tabs';\nimport classNames from 'classnames';\n\nexport type TabsProps = {\n /** Overskriften til taben */\n children: React.ReactNode;\n /** Kalles når taben endres */\n onChange?: (index: number) => void;\n /** Hvilken tab som skal være åpen by default */\n defaultIndex?: number;\n /** Den åpne indexen */\n index?: number;\n /** HTML-elementet eller React-komponenten som lager komponenten */\n as?: keyof JSX.IntrinsicElements | any;\n\n [key: string]: any;\n};\n\nexport const Tabs: React.FC<TabsProps> = ({ className, ...rest }) => {\n return <ReachTabs className={classNames('eds-tabs', className)} {...rest} />;\n};\n","import React from 'react';\nimport { TabPanel as ReachTabPanel } from '@reach/tabs';\nimport classNames from 'classnames';\n\nexport type TabPanelProps = {\n /** Overskriften til taben */\n children: React.ReactNode;\n /** HTML-elementet eller React-komponenten som lager komponenten */\n as?: keyof JSX.IntrinsicElements | any;\n [key: string]: any;\n};\n\nexport const TabPanel: React.FC<TabPanelProps> = ({ className, ...rest }) => {\n return (\n <ReachTabPanel\n className={classNames('eds-tab-panel', className)}\n {...rest}\n tabIndex={undefined}\n />\n );\n};\n","import React from 'react';\nimport { TabPanels as ReachTabPanels } from '@reach/tabs';\nimport classNames from 'classnames';\n\nexport type TabPanelsProps = {\n /** Tab-panelene */\n children: React.ReactNode;\n /** HTML-elementet eller React-komponenten som lager komponenten */\n as?: keyof JSX.IntrinsicElements | any;\n [key: string]: any;\n};\n\nexport const TabPanels: React.FC<TabPanelsProps> = ({ className, ...rest }) => {\n return (\n <ReachTabPanels\n className={classNames('eds-tab-panels', className)}\n {...rest}\n />\n );\n};\n","import React from 'react';\nimport { TabList as ReachTabList } from '@reach/tabs';\nimport classNames from 'classnames';\n\nexport type TabListProps = {\n /** Tab-komponenter */\n children: React.ReactNode;\n /** HTML-elementet eller React-komponenten som lager komponenten */\n as?: keyof JSX.IntrinsicElements | any;\n width?: 'fluid';\n [key: string]: any;\n};\n\nexport const TabList: React.FC<TabListProps> = ({\n className,\n width,\n ...rest\n}) => {\n return (\n <ReachTabList\n className={classNames('eds-tab-list', className, {\n 'eds-tab-list--width-fluid': width === 'fluid',\n })}\n {...rest}\n />\n );\n};\n","import { warnAboutMissingStyles } from '@entur/utils';\nimport './index.scss';\n\nwarnAboutMissingStyles('tab');\n\nexport * from './Tab';\nexport * from './Tabs';\nexport * from './TabPanel';\nexport * from './TabPanels';\nexport * from './TabList';\n"],"names":["Tab","className","removeActiveLine","rest","_excluded","React","ReachTab","classNames","Tabs","createElement","ReachTabs","TabPanel","ReachTabPanel","tabIndex","undefined","TabPanels","ReachTabPanels","TabList","width","ReachTabList","warnAboutMissingStyles"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAeaA,IAAAA,GAAG,GAAuB,SAA1BA,GAAG,CAIX,IAAA,EAAA;EAAA,IAHHC,SAAS,QAATA,SAAS;AAAA,IAAA,qBAAA,GAAA,IAAA,CACTC,gBAAgB;AAAhBA,IAAAA,gBAAgB,sCAAG,KAAK,GAAA,qBAAA;IACrBC,IAAI,GAAA,6BAAA,CAAA,IAAA,EAAAC,WAAA,CAAA,CAAA;AAEP,EAAA,OACEC,oBAACC,KAAQ,EAAA,QAAA,CAAA;AACPL,IAAAA,SAAS,EAAEM,UAAU,CACnB,SAAS,EACT;AAAE,MAAA,6BAA6B,EAAEL,gBAAAA;KAAkB,EACnDD,SAAS,CAAA;AACV,GAAA,EACGE,IAAI,CACR,CAAA,CAAA;AAEN;;;ACXaK,IAAAA,IAAI,GAAwB,SAA5BA,IAAI,CAAmD,IAAA,EAAA;EAAA,IAAxBP,SAAS,QAATA,SAAS;IAAKE,IAAI,GAAA,6BAAA,CAAA,IAAA,EAAAC,WAAA,CAAA,CAAA;AAC5D,EAAA,OAAOC,KAAC,CAAAI,aAAA,CAAAC,MAAS,EAAA,QAAA,CAAA;AAACT,IAAAA,SAAS,EAAEM,UAAU,CAAC,UAAU,EAAEN,SAAS,CAAA;AAAC,GAAA,EAAME,IAAI,CAAI,CAAA,CAAA;AAC9E;;;ACTaQ,IAAAA,QAAQ,GAA4B,SAApCA,QAAQ,CAAuD,IAAA,EAAA;EAAA,IAAxBV,SAAS,QAATA,SAAS;IAAKE,IAAI,GAAA,6BAAA,CAAA,IAAA,EAAAC,WAAA,CAAA,CAAA;AACpE,EAAA,OACEC,oBAACO,UAAa,EAAA,QAAA,CAAA;AACZX,IAAAA,SAAS,EAAEM,UAAU,CAAC,eAAe,EAAEN,SAAS,CAAA;AAAC,GAAA,EAC7CE,IAAI,EAAA;AACRU,IAAAA,QAAQ,EAAEC,SAAAA;GACV,CAAA,CAAA,CAAA;AAEN;;;ACRaC,IAAAA,SAAS,GAA6B,SAAtCA,SAAS,CAAwD,IAAA,EAAA;EAAA,IAAxBd,SAAS,QAATA,SAAS;IAAKE,IAAI,GAAA,6BAAA,CAAA,IAAA,EAAAC,WAAA,CAAA,CAAA;AACtE,EAAA,OACEC,KAAC,CAAAI,aAAA,CAAAO,WAAc,EAAA,QAAA,CAAA;AACbf,IAAAA,SAAS,EAAEM,UAAU,CAAC,gBAAgB,EAAEN,SAAS,CAAA;AAAC,GAAA,EAC9CE,IAAI,CACR,CAAA,CAAA;AAEN;;;ACNac,IAAAA,OAAO,GAA2B,SAAlCA,OAAO,CAIf,IAAA,EAAA;EAAA,IAHHhB,SAAS,QAATA,SAAS;AACTiB,IAAAA,KAAK,QAALA,KAAK;IACFf,IAAI,GAAA,6BAAA,CAAA,IAAA,EAAA,SAAA,CAAA,CAAA;AAEP,EAAA,OACEE,KAAC,CAAAI,aAAA,CAAAU,SAAY,EAAA,QAAA,CAAA;AACXlB,IAAAA,SAAS,EAAEM,UAAU,CAAC,cAAc,EAAEN,SAAS,EAAE;MAC/C,2BAA2B,EAAEiB,KAAK,KAAK,OAAA;KACxC,CAAA;AAAC,GAAA,EACEf,IAAI,CACR,CAAA,CAAA;AAEN;;ACvBAiB,sBAAsB,CAAC,KAAK,CAAC;;;;"}
1
+ {"version":3,"file":"tab.esm.js","sources":["../src/TabsContext.tsx","../src/Tab.tsx","../src/Tabs.tsx","../src/TabPanel.tsx","../src/TabPanels.tsx","../src/TabList.tsx","../src/index.tsx"],"sourcesContent":["import React from 'react';\n\nexport type TabsContextValue = {\n selectedIndex: number;\n onSelect: (index: number) => void;\n tabsId: string;\n};\n\nexport const TabsContext = React.createContext<TabsContextValue>({\n selectedIndex: 0,\n onSelect: () => undefined,\n tabsId: '',\n});\n\nexport type TabItemContextValue = {\n tabIndex: number;\n tabId: string;\n panelId: string;\n};\n\nexport const TabItemContext = React.createContext<TabItemContextValue | null>(\n null,\n);\n\nexport type TabPanelItemContextValue = {\n tabIndex: number;\n tabId: string;\n panelId: string;\n keepMounted: boolean;\n};\n\nexport const TabPanelItemContext =\n React.createContext<TabPanelItemContextValue | null>(null);\n","import React, { useContext } from 'react';\nimport classNames from 'classnames';\n\nimport { TabItemContext, TabsContext } from './TabsContext';\n\nexport type TabProps = {\n /** Overskriften til taben */\n children: React.ReactNode;\n /** Om taben er disabled eller ikke */\n disabled?: boolean;\n /** HTML-elementet eller React-komponenten som lager komponenten */\n as?: keyof JSX.IntrinsicElements | React.ElementType;\n removeActiveLine?: boolean;\n className?: string;\n} & Omit<React.ComponentPropsWithoutRef<'button'>, 'children' | 'disabled'>;\n\nexport const Tab = ({\n className,\n removeActiveLine = false,\n as,\n disabled = false,\n children,\n ...rest\n}: TabProps) => {\n const { selectedIndex, onSelect } = useContext(TabsContext);\n const itemContext = useContext(TabItemContext);\n const tabIndex = itemContext?.tabIndex ?? 0;\n const isSelected = selectedIndex === tabIndex;\n const Element: React.ElementType = as || 'button';\n\n return (\n <Element\n role=\"tab\"\n type={as ? undefined : 'button'}\n id={itemContext?.tabId}\n aria-selected={isSelected}\n aria-controls={itemContext?.panelId}\n tabIndex={isSelected ? 0 : -1}\n disabled={disabled || undefined}\n aria-disabled={disabled || undefined}\n className={classNames(\n 'eds-tab',\n { 'eds-tab--remove-active-line': removeActiveLine },\n className,\n )}\n onClick={() => {\n if (!disabled) onSelect(tabIndex);\n }}\n {...rest}\n >\n {children}\n </Element>\n );\n};\n","import React, { useCallback, useId, useState } from 'react';\nimport classNames from 'classnames';\n\nimport { TabsContext } from './TabsContext';\n\nexport type TabsProps = {\n /** Tab-innholdet */\n children: React.ReactNode;\n /** Kalles når taben endres */\n onChange?: (index: number) => void;\n /** Hvilken tab som skal være åpen by default */\n defaultIndex?: number;\n /** Den åpne indexen (kontrollert) */\n index?: number;\n /** HTML-elementet eller React-komponenten som lager komponenten */\n as?: keyof JSX.IntrinsicElements | React.ElementType;\n className?: string;\n} & Omit<React.ComponentPropsWithoutRef<'div'>, 'children' | 'onChange'>;\n\nexport const Tabs = ({\n className,\n index,\n defaultIndex,\n onChange,\n as,\n children,\n ...rest\n}: TabsProps) => {\n const [internalIndex, setInternalIndex] = useState(defaultIndex ?? 0);\n const isControlled = index !== undefined;\n const selectedIndex = isControlled ? index : internalIndex;\n const tabsId = useId();\n\n const onSelect = useCallback(\n (i: number) => {\n if (!isControlled) {\n setInternalIndex(i);\n }\n onChange?.(i);\n },\n [isControlled, onChange],\n );\n\n const Element: React.ElementType = as || 'div';\n\n return (\n <TabsContext.Provider value={{ selectedIndex, onSelect, tabsId }}>\n <Element className={classNames('eds-tabs', className)} {...rest}>\n {children}\n </Element>\n </TabsContext.Provider>\n );\n};\n","import React, { useContext } from 'react';\nimport classNames from 'classnames';\n\nimport { TabPanelItemContext, TabsContext } from './TabsContext';\n\nexport type TabPanelProps = {\n /** Innholdet i tab-panelet */\n children?: React.ReactNode;\n /** HTML-elementet eller React-komponenten som lager komponenten */\n as?: keyof JSX.IntrinsicElements | React.ElementType;\n className?: string;\n} & Omit<React.ComponentPropsWithoutRef<'div'>, 'children'>;\n\nexport const TabPanel = ({\n className,\n as,\n children,\n ...rest\n}: TabPanelProps) => {\n const { selectedIndex } = useContext(TabsContext);\n const itemContext = useContext(TabPanelItemContext);\n const tabIndex = itemContext?.tabIndex ?? 0;\n const keepMounted = itemContext?.keepMounted ?? false;\n\n const isSelected = selectedIndex === tabIndex;\n const isHiddenButMounted = keepMounted && !isSelected;\n\n if (!isSelected && !keepMounted) return null;\n\n const Element: React.ElementType = as || 'div';\n\n return (\n <Element\n role=\"tabpanel\"\n id={itemContext?.panelId}\n aria-labelledby={itemContext?.tabId}\n tabIndex={isSelected ? 0 : -1}\n hidden={isHiddenButMounted || undefined}\n className={classNames('eds-tab-panel', className)}\n {...rest}\n >\n {children}\n </Element>\n );\n};\n","import React, { useContext } from 'react';\nimport classNames from 'classnames';\n\nimport { TabPanelItemContext, TabsContext } from './TabsContext';\n\nexport type TabPanelsProps = {\n /** Tab-panelene */\n children: React.ReactNode;\n /** HTML-elementet eller React-komponenten som lager komponenten */\n as?: keyof JSX.IntrinsicElements | React.ElementType;\n /** Behold alle panel-noder i DOM (skjult med hidden-attributt) i stedet for å avmontere */\n keepMounted?: boolean;\n className?: string;\n} & Omit<React.ComponentPropsWithoutRef<'div'>, 'children'>;\n\nexport const TabPanels = ({\n className,\n as,\n keepMounted = false,\n children,\n ...rest\n}: TabPanelsProps) => {\n const { tabsId } = useContext(TabsContext);\n\n const Element: React.ElementType = as || 'div';\n\n return (\n <Element className={classNames('eds-tab-panels', className)} {...rest}>\n {React.Children.map(children, (child, idx) => (\n <TabPanelItemContext.Provider\n value={{\n tabIndex: idx,\n tabId: `${tabsId}-tab-${idx}`,\n panelId: `${tabsId}-panel-${idx}`,\n keepMounted,\n }}\n >\n {child}\n </TabPanelItemContext.Provider>\n ))}\n </Element>\n );\n};\n","import React, { useCallback, useContext, useRef } from 'react';\nimport classNames from 'classnames';\n\nimport { TabItemContext, TabsContext } from './TabsContext';\n\nexport type TabListProps = {\n /** Tab-komponenter */\n children: React.ReactNode;\n /** HTML-elementet eller React-komponenten som lager komponenten */\n as?: keyof JSX.IntrinsicElements | React.ElementType;\n width?: 'fluid';\n className?: string;\n /** Tilgjengelig navn på tab-listen (dersom det ikke finnes en synlig overskrift) */\n 'aria-label'?: string;\n /** ID til elementet som navngir tab-listen */\n 'aria-labelledby'?: string;\n} & Omit<React.ComponentPropsWithoutRef<'div'>, 'children'>;\n\nexport const TabList = ({\n className,\n width,\n as,\n children,\n ...rest\n}: TabListProps) => {\n const { tabsId } = useContext(TabsContext);\n const tabListRef = useRef<HTMLElement>(null);\n\n const handleKeyDown = useCallback((e: React.KeyboardEvent) => {\n const tabs = tabListRef.current?.querySelectorAll<HTMLElement>(\n '[role=\"tab\"]:not([disabled])',\n );\n if (!tabs || tabs.length === 0) return;\n\n const currentIndex = Array.from(tabs).findIndex(\n tab => tab === document.activeElement,\n );\n if (currentIndex === -1) return;\n\n let nextIndex: number | undefined;\n switch (e.key) {\n case 'ArrowRight':\n nextIndex = (currentIndex + 1) % tabs.length;\n break;\n case 'ArrowLeft':\n nextIndex = (currentIndex - 1 + tabs.length) % tabs.length;\n break;\n case 'Home':\n nextIndex = 0;\n break;\n case 'End':\n nextIndex = tabs.length - 1;\n break;\n }\n\n if (nextIndex !== undefined) {\n e.preventDefault();\n tabs[nextIndex].focus();\n tabs[nextIndex].click();\n }\n }, []);\n\n const Element: React.ElementType = as || 'div';\n\n return (\n <Element\n role=\"tablist\"\n tabIndex={-1}\n ref={tabListRef}\n className={classNames('eds-tab-list', className, {\n 'eds-tab-list--width-fluid': width === 'fluid',\n })}\n onKeyDown={handleKeyDown}\n {...rest}\n >\n {React.Children.map(children, (child, idx) => (\n <TabItemContext.Provider\n value={{\n tabIndex: idx,\n tabId: `${tabsId}-tab-${idx}`,\n panelId: `${tabsId}-panel-${idx}`,\n }}\n >\n {child}\n </TabItemContext.Provider>\n ))}\n </Element>\n );\n};\n","import { warnAboutMissingStyles } from '@entur/utils';\nimport './index.scss';\n\nwarnAboutMissingStyles('tab');\n\nexport * from './Tab';\nexport * from './Tabs';\nexport * from './TabPanel';\nexport * from './TabPanels';\nexport * from './TabList';\n"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,35 +1,57 @@
1
1
  {
2
2
  "name": "@entur/tab",
3
- "version": "1.0.0-alpha.0",
3
+ "version": "1.0.0-next.1",
4
4
  "license": "EUPL-1.2",
5
- "main": "dist/index.js",
5
+ "main": "dist/tab.cjs.js",
6
6
  "module": "dist/tab.esm.js",
7
- "typings": "dist/index.d.ts",
7
+ "types": "dist/index.d.ts",
8
8
  "files": [
9
9
  "dist"
10
10
  ],
11
11
  "repository": {
12
12
  "type": "git",
13
- "url": "https://bitbucket.org/enturas/design-system.git",
13
+ "url": "https://github.com/entur/design-system.git",
14
14
  "directory": "packages/tab"
15
15
  },
16
16
  "publishConfig": {
17
17
  "access": "public"
18
18
  },
19
19
  "scripts": {
20
- "start": "dts watch --noClean",
21
- "build": "dts build",
22
- "lint": "dts lint src"
20
+ "start": "vite build --watch",
21
+ "build": "vite build",
22
+ "test": "jest"
23
23
  },
24
24
  "peerDependencies": {
25
- "react": ">=16.8.0",
26
- "react-dom": ">=16.8.0"
25
+ "react": ">=18.0.0",
26
+ "react-dom": ">=18.0.0"
27
27
  },
28
28
  "dependencies": {
29
- "@entur/tokens": "^3.11.1",
30
- "@entur/utils": "^0.9.5",
31
- "@reach/tabs": "^0.18.0",
32
- "classnames": "^2.3.1"
29
+ "@entur/tokens": "^4.0.0-next.0",
30
+ "@entur/utils": "^1.0.0-next.1",
31
+ "classnames": "^2.5.1"
33
32
  },
34
- "gitHead": "46d0a52a33d2b59431ab6c60385ec2759c74dc59"
33
+ "devDependencies": {
34
+ "@testing-library/jest-dom": "^5.17.0",
35
+ "@testing-library/react": "^16.3.0",
36
+ "@testing-library/user-event": "14.6.1",
37
+ "@vitejs/plugin-react": "^5.0.1",
38
+ "jest": "^29.0.0",
39
+ "jest-environment-jsdom": "^29.0.0",
40
+ "ts-jest": "^29.0.0",
41
+ "typescript": "^5.9.2",
42
+ "vite": "^7.3.2",
43
+ "vite-plugin-dts": "^4.5.4"
44
+ },
45
+ "exports": {
46
+ ".": {
47
+ "types": "./dist/index.d.ts",
48
+ "import": "./dist/tab.esm.js",
49
+ "require": "./dist/tab.cjs.js",
50
+ "default": "./dist/tab.esm.js"
51
+ },
52
+ "./styles": "./dist/styles.css",
53
+ "./dist/styles.css": "./dist/styles.css",
54
+ "./package.json": "./package.json"
55
+ },
56
+ "gitHead": "0696d63a328007af9797bc57b63c8e1c65ecfa5a"
35
57
  }
package/dist/index.js DELETED
@@ -1,8 +0,0 @@
1
-
2
- 'use strict'
3
-
4
- if (process.env.NODE_ENV === 'production') {
5
- module.exports = require('./tab.cjs.production.min.js')
6
- } else {
7
- module.exports = require('./tab.cjs.development.js')
8
- }