@eztrak/shared 0.3.1 → 0.4.0

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,40 @@
1
+ import * as react from 'react';
2
+ import { ReactNode } from 'react';
3
+
4
+ type EztrakTab = {
5
+ id: string;
6
+ label: ReactNode;
7
+ content?: ReactNode;
8
+ disabled?: boolean;
9
+ icon?: ReactNode;
10
+ };
11
+ type EztrakTabsClassNames = {
12
+ wrapper?: string;
13
+ list?: string;
14
+ item?: string;
15
+ itemActive?: string;
16
+ button?: string;
17
+ buttonActive?: string;
18
+ label?: string;
19
+ icon?: string;
20
+ underline?: string;
21
+ panel?: string;
22
+ content?: string;
23
+ };
24
+ type EztrakTabsProps = {
25
+ tabs: EztrakTab[];
26
+ activeTab?: string;
27
+ defaultTabId?: string;
28
+ onTabChange?: (id: string) => void;
29
+ /** When false, only the tab list is rendered (nav-only). Default: true */
30
+ showPanels?: boolean;
31
+ /** Keep inactive panels in the DOM (hidden). Default: false */
32
+ keepMounted?: boolean;
33
+ classNames?: EztrakTabsClassNames;
34
+ /** Shorthand for classNames.wrapper */
35
+ className?: string;
36
+ };
37
+
38
+ declare function EztrakTabs({ tabs, activeTab, defaultTabId, onTabChange, showPanels, keepMounted, classNames, className, }: EztrakTabsProps): react.JSX.Element | null;
39
+
40
+ export { type EztrakTab, EztrakTabs, type EztrakTabsClassNames, type EztrakTabsProps };
@@ -0,0 +1,248 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/components/index.ts
31
+ var components_exports = {};
32
+ __export(components_exports, {
33
+ EztrakTabs: () => EztrakTabs
34
+ });
35
+ module.exports = __toCommonJS(components_exports);
36
+
37
+ // src/components/tabs/EztrakTabs.tsx
38
+ var import_react = require("react");
39
+
40
+ // src/utils/cn.ts
41
+ var import_clsx = __toESM(require("clsx"));
42
+ var import_tailwind_merge = require("tailwind-merge");
43
+ function cn(...inputs) {
44
+ return (0, import_tailwind_merge.twMerge)((0, import_clsx.default)(inputs));
45
+ }
46
+
47
+ // src/components/tabs/EztrakTabs.tsx
48
+ var import_jsx_runtime = require("react/jsx-runtime");
49
+ function getInitialTabId(tabs, defaultTabId) {
50
+ if (defaultTabId && tabs.some((t) => t.id === defaultTabId && !t.disabled)) {
51
+ return defaultTabId;
52
+ }
53
+ return tabs.find((t) => !t.disabled)?.id;
54
+ }
55
+ function getEnabledTabIds(tabs) {
56
+ return tabs.filter((t) => !t.disabled).map((t) => t.id);
57
+ }
58
+ function EztrakTabs({
59
+ tabs,
60
+ activeTab,
61
+ defaultTabId,
62
+ onTabChange,
63
+ showPanels = true,
64
+ keepMounted = false,
65
+ classNames,
66
+ className
67
+ }) {
68
+ const baseId = (0, import_react.useId)().replace(/:/g, "");
69
+ const isControlled = activeTab !== void 0 && activeTab !== null;
70
+ const [uncontrolledActive, setUncontrolledActive] = (0, import_react.useState)(
71
+ () => getInitialTabId(tabs, defaultTabId)
72
+ );
73
+ const tabRefs = (0, import_react.useRef)(/* @__PURE__ */ new Map());
74
+ const displayActive = isControlled ? activeTab : uncontrolledActive;
75
+ (0, import_react.useEffect)(() => {
76
+ if (isControlled) return;
77
+ const enabledIds = getEnabledTabIds(tabs);
78
+ if (!displayActive || !enabledIds.includes(displayActive)) {
79
+ const next = getInitialTabId(tabs, defaultTabId);
80
+ if (next !== displayActive) {
81
+ setUncontrolledActive(next);
82
+ }
83
+ }
84
+ }, [tabs, defaultTabId, isControlled, displayActive]);
85
+ const handleTabClick = (0, import_react.useCallback)(
86
+ (tabId, disabled) => {
87
+ if (disabled) return;
88
+ if (!isControlled) {
89
+ setUncontrolledActive(tabId);
90
+ }
91
+ onTabChange?.(tabId);
92
+ },
93
+ [isControlled, onTabChange]
94
+ );
95
+ const focusTab = (0, import_react.useCallback)((tabId) => {
96
+ tabRefs.current.get(tabId)?.focus();
97
+ }, []);
98
+ const handleListKeyDown = (0, import_react.useCallback)(
99
+ (event) => {
100
+ const enabledIds = getEnabledTabIds(tabs);
101
+ if (enabledIds.length === 0) return;
102
+ const currentIndex = displayActive ? enabledIds.indexOf(displayActive) : -1;
103
+ let nextIndex = currentIndex;
104
+ switch (event.key) {
105
+ case "ArrowRight":
106
+ case "ArrowDown":
107
+ event.preventDefault();
108
+ nextIndex = currentIndex < 0 ? 0 : (currentIndex + 1) % enabledIds.length;
109
+ break;
110
+ case "ArrowLeft":
111
+ case "ArrowUp":
112
+ event.preventDefault();
113
+ nextIndex = currentIndex < 0 ? enabledIds.length - 1 : (currentIndex - 1 + enabledIds.length) % enabledIds.length;
114
+ break;
115
+ case "Home":
116
+ event.preventDefault();
117
+ nextIndex = 0;
118
+ break;
119
+ case "End":
120
+ event.preventDefault();
121
+ nextIndex = enabledIds.length - 1;
122
+ break;
123
+ default:
124
+ return;
125
+ }
126
+ const nextId = enabledIds[nextIndex];
127
+ if (nextId) {
128
+ handleTabClick(nextId);
129
+ focusTab(nextId);
130
+ }
131
+ },
132
+ [tabs, displayActive, handleTabClick, focusTab]
133
+ );
134
+ if (!tabs.length) {
135
+ return null;
136
+ }
137
+ const wrapperClass = cn(
138
+ "eztrak-tabs-wrapper",
139
+ classNames?.wrapper,
140
+ className
141
+ );
142
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: wrapperClass, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "eztrak-tabs-container", children: [
143
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("nav", { className: "eztrak-tabs-nav", "aria-label": "Tabs", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
144
+ "ul",
145
+ {
146
+ role: "tablist",
147
+ className: cn("eztrak-tabs-list", classNames?.list),
148
+ onKeyDown: handleListKeyDown,
149
+ children: tabs.map((tab) => {
150
+ const isActive = displayActive === tab.id;
151
+ const tabId = `${baseId}-tab-${tab.id}`;
152
+ const panelId = `${baseId}-panel-${tab.id}`;
153
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
154
+ "li",
155
+ {
156
+ role: "presentation",
157
+ className: cn(
158
+ "eztrak-tabs-item",
159
+ isActive && "eztrak-tabs-item-active",
160
+ classNames?.item,
161
+ isActive && classNames?.itemActive
162
+ ),
163
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
164
+ "button",
165
+ {
166
+ ref: (el) => {
167
+ if (el) {
168
+ tabRefs.current.set(tab.id, el);
169
+ } else {
170
+ tabRefs.current.delete(tab.id);
171
+ }
172
+ },
173
+ type: "button",
174
+ role: "tab",
175
+ id: tabId,
176
+ "aria-selected": isActive,
177
+ "aria-controls": showPanels ? panelId : void 0,
178
+ tabIndex: isActive ? 0 : -1,
179
+ disabled: tab.disabled,
180
+ className: cn(
181
+ "eztrak-tabs-button",
182
+ isActive && "eztrak-tabs-button-active",
183
+ classNames?.button,
184
+ isActive && classNames?.buttonActive
185
+ ),
186
+ onClick: () => handleTabClick(tab.id, tab.disabled),
187
+ children: [
188
+ tab.icon ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
189
+ "span",
190
+ {
191
+ className: cn("eztrak-tabs-icon", classNames?.icon),
192
+ "aria-hidden": true,
193
+ children: tab.icon
194
+ }
195
+ ) : null,
196
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
197
+ "span",
198
+ {
199
+ className: cn("eztrak-tabs-label", classNames?.label),
200
+ children: tab.label
201
+ }
202
+ ),
203
+ isActive ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
204
+ "span",
205
+ {
206
+ className: cn(
207
+ "eztrak-tabs-underline",
208
+ classNames?.underline
209
+ ),
210
+ "aria-hidden": true
211
+ }
212
+ ) : null
213
+ ]
214
+ }
215
+ )
216
+ },
217
+ tab.id
218
+ );
219
+ })
220
+ }
221
+ ) }),
222
+ showPanels ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: cn("eztrak-tabs-content", classNames?.content), children: tabs.map((tab) => {
223
+ const isActive = displayActive === tab.id;
224
+ const panelId = `${baseId}-panel-${tab.id}`;
225
+ const tabId = `${baseId}-tab-${tab.id}`;
226
+ if (!keepMounted && !isActive) {
227
+ return null;
228
+ }
229
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
230
+ "div",
231
+ {
232
+ id: panelId,
233
+ role: "tabpanel",
234
+ "aria-labelledby": tabId,
235
+ hidden: !isActive,
236
+ className: cn("eztrak-tabs-panel", classNames?.panel),
237
+ children: tab.content
238
+ },
239
+ tab.id
240
+ );
241
+ }) }) : null
242
+ ] }) });
243
+ }
244
+ // Annotate the CommonJS export names for ESM import in node:
245
+ 0 && (module.exports = {
246
+ EztrakTabs
247
+ });
248
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/components/index.ts","../../src/components/tabs/EztrakTabs.tsx","../../src/utils/cn.ts"],"sourcesContent":["export { EztrakTabs } from \"./tabs/EztrakTabs\";\r\nexport type {\r\n EztrakTab,\r\n EztrakTabsClassNames,\r\n EztrakTabsProps,\r\n} from \"./tabs/types\";\r\n","import {\r\n useCallback,\r\n useEffect,\r\n useId,\r\n useRef,\r\n useState,\r\n type KeyboardEvent,\r\n} from \"react\";\r\nimport { cn } from \"../../utils/cn\";\r\nimport type { EztrakTab, EztrakTabsProps } from \"./types\";\r\n\r\nfunction getInitialTabId(\r\n tabs: EztrakTab[],\r\n defaultTabId?: string\r\n): string | undefined {\r\n if (defaultTabId && tabs.some((t) => t.id === defaultTabId && !t.disabled)) {\r\n return defaultTabId;\r\n }\r\n return tabs.find((t) => !t.disabled)?.id;\r\n}\r\n\r\nfunction getEnabledTabIds(tabs: EztrakTab[]): string[] {\r\n return tabs.filter((t) => !t.disabled).map((t) => t.id);\r\n}\r\n\r\nexport function EztrakTabs({\r\n tabs,\r\n activeTab,\r\n defaultTabId,\r\n onTabChange,\r\n showPanels = true,\r\n keepMounted = false,\r\n classNames,\r\n className,\r\n}: EztrakTabsProps) {\r\n const baseId = useId().replace(/:/g, \"\");\r\n const isControlled = activeTab !== undefined && activeTab !== null;\r\n const [uncontrolledActive, setUncontrolledActive] = useState(() =>\r\n getInitialTabId(tabs, defaultTabId)\r\n );\r\n const tabRefs = useRef<Map<string, HTMLButtonElement>>(new Map());\r\n\r\n const displayActive = isControlled ? activeTab : uncontrolledActive;\r\n\r\n useEffect(() => {\r\n if (isControlled) return;\r\n const enabledIds = getEnabledTabIds(tabs);\r\n if (!displayActive || !enabledIds.includes(displayActive)) {\r\n const next = getInitialTabId(tabs, defaultTabId);\r\n if (next !== displayActive) {\r\n setUncontrolledActive(next);\r\n }\r\n }\r\n }, [tabs, defaultTabId, isControlled, displayActive]);\r\n\r\n const handleTabClick = useCallback(\r\n (tabId: string, disabled?: boolean) => {\r\n if (disabled) return;\r\n if (!isControlled) {\r\n setUncontrolledActive(tabId);\r\n }\r\n onTabChange?.(tabId);\r\n },\r\n [isControlled, onTabChange]\r\n );\r\n\r\n const focusTab = useCallback((tabId: string) => {\r\n tabRefs.current.get(tabId)?.focus();\r\n }, []);\r\n\r\n const handleListKeyDown = useCallback(\r\n (event: KeyboardEvent<HTMLUListElement>) => {\r\n const enabledIds = getEnabledTabIds(tabs);\r\n if (enabledIds.length === 0) return;\r\n\r\n const currentIndex = displayActive\r\n ? enabledIds.indexOf(displayActive)\r\n : -1;\r\n let nextIndex = currentIndex;\r\n\r\n switch (event.key) {\r\n case \"ArrowRight\":\r\n case \"ArrowDown\":\r\n event.preventDefault();\r\n nextIndex =\r\n currentIndex < 0\r\n ? 0\r\n : (currentIndex + 1) % enabledIds.length;\r\n break;\r\n case \"ArrowLeft\":\r\n case \"ArrowUp\":\r\n event.preventDefault();\r\n nextIndex =\r\n currentIndex < 0\r\n ? enabledIds.length - 1\r\n : (currentIndex - 1 + enabledIds.length) % enabledIds.length;\r\n break;\r\n case \"Home\":\r\n event.preventDefault();\r\n nextIndex = 0;\r\n break;\r\n case \"End\":\r\n event.preventDefault();\r\n nextIndex = enabledIds.length - 1;\r\n break;\r\n default:\r\n return;\r\n }\r\n\r\n const nextId = enabledIds[nextIndex];\r\n if (nextId) {\r\n handleTabClick(nextId);\r\n focusTab(nextId);\r\n }\r\n },\r\n [tabs, displayActive, handleTabClick, focusTab]\r\n );\r\n\r\n if (!tabs.length) {\r\n return null;\r\n }\r\n\r\n const wrapperClass = cn(\r\n \"eztrak-tabs-wrapper\",\r\n classNames?.wrapper,\r\n className\r\n );\r\n\r\n return (\r\n <div className={wrapperClass}>\r\n <div className=\"eztrak-tabs-container\">\r\n <nav className=\"eztrak-tabs-nav\" aria-label=\"Tabs\">\r\n <ul\r\n role=\"tablist\"\r\n className={cn(\"eztrak-tabs-list\", classNames?.list)}\r\n onKeyDown={handleListKeyDown}\r\n >\r\n {tabs.map((tab) => {\r\n const isActive = displayActive === tab.id;\r\n const tabId = `${baseId}-tab-${tab.id}`;\r\n const panelId = `${baseId}-panel-${tab.id}`;\r\n\r\n return (\r\n <li\r\n key={tab.id}\r\n role=\"presentation\"\r\n className={cn(\r\n \"eztrak-tabs-item\",\r\n isActive && \"eztrak-tabs-item-active\",\r\n classNames?.item,\r\n isActive && classNames?.itemActive\r\n )}\r\n >\r\n <button\r\n ref={(el) => {\r\n if (el) {\r\n tabRefs.current.set(tab.id, el);\r\n } else {\r\n tabRefs.current.delete(tab.id);\r\n }\r\n }}\r\n type=\"button\"\r\n role=\"tab\"\r\n id={tabId}\r\n aria-selected={isActive}\r\n aria-controls={showPanels ? panelId : undefined}\r\n tabIndex={isActive ? 0 : -1}\r\n disabled={tab.disabled}\r\n className={cn(\r\n \"eztrak-tabs-button\",\r\n isActive && \"eztrak-tabs-button-active\",\r\n classNames?.button,\r\n isActive && classNames?.buttonActive\r\n )}\r\n onClick={() => handleTabClick(tab.id, tab.disabled)}\r\n >\r\n {tab.icon ? (\r\n <span\r\n className={cn(\"eztrak-tabs-icon\", classNames?.icon)}\r\n aria-hidden\r\n >\r\n {tab.icon}\r\n </span>\r\n ) : null}\r\n <span\r\n className={cn(\"eztrak-tabs-label\", classNames?.label)}\r\n >\r\n {tab.label}\r\n </span>\r\n {isActive ? (\r\n <span\r\n className={cn(\r\n \"eztrak-tabs-underline\",\r\n classNames?.underline\r\n )}\r\n aria-hidden\r\n />\r\n ) : null}\r\n </button>\r\n </li>\r\n );\r\n })}\r\n </ul>\r\n </nav>\r\n\r\n {showPanels ? (\r\n <div className={cn(\"eztrak-tabs-content\", classNames?.content)}>\r\n {tabs.map((tab) => {\r\n const isActive = displayActive === tab.id;\r\n const panelId = `${baseId}-panel-${tab.id}`;\r\n const tabId = `${baseId}-tab-${tab.id}`;\r\n\r\n if (!keepMounted && !isActive) {\r\n return null;\r\n }\r\n\r\n return (\r\n <div\r\n key={tab.id}\r\n id={panelId}\r\n role=\"tabpanel\"\r\n aria-labelledby={tabId}\r\n hidden={!isActive}\r\n className={cn(\"eztrak-tabs-panel\", classNames?.panel)}\r\n >\r\n {tab.content}\r\n </div>\r\n );\r\n })}\r\n </div>\r\n ) : null}\r\n </div>\r\n </div>\r\n );\r\n}\r\n","import clsx from \"clsx\";\r\nimport { twMerge } from \"tailwind-merge\";\r\n\r\nexport function cn(...inputs: Parameters<typeof clsx>) {\r\n return twMerge(clsx(inputs));\r\n}\r\n"],"mappings":"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","names":["clsx"]}
@@ -0,0 +1,8 @@
1
+ import {
2
+ EztrakTabs
3
+ } from "../chunk-SNADLOOV.mjs";
4
+ import "../chunk-5L6SERQP.mjs";
5
+ export {
6
+ EztrakTabs
7
+ };
8
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,205 @@
1
+ /* Theme tokens — override on :root or a wrapper */
2
+ :root {
3
+ --eztrak-tabs-accent: #f54e00;
4
+ --eztrak-tabs-inactive-bg: #f3f4f6;
5
+ --eztrak-tabs-inactive-border: #e0e0e0;
6
+ --eztrak-tabs-active-bg: #ffffff;
7
+ --eztrak-tabs-label-inactive: #9ca3af;
8
+ --eztrak-tabs-label-active: #1f2937;
9
+ --eztrak-tabs-label-hover: #6b7280;
10
+ --eztrak-tabs-hover-bg: #e5e7eb;
11
+ --eztrak-tabs-hover-border: #d1d5db;
12
+ --eztrak-tabs-radius: 6px;
13
+ --eztrak-tabs-gap: 8px;
14
+ --eztrak-tabs-padding: 10px 18px;
15
+ --eztrak-tabs-focus-color: #3b82f6;
16
+ }
17
+
18
+ .eztrak-tabs-wrapper {
19
+ width: 100%;
20
+ background: transparent;
21
+ }
22
+
23
+ .eztrak-tabs-container {
24
+ width: 100%;
25
+ background: transparent;
26
+ }
27
+
28
+ .eztrak-tabs-nav {
29
+ width: 100%;
30
+ background: transparent;
31
+ }
32
+
33
+ .eztrak-tabs-list {
34
+ display: flex;
35
+ align-items: center;
36
+ justify-content: flex-start;
37
+ gap: var(--eztrak-tabs-gap);
38
+ list-style: none;
39
+ margin: 0;
40
+ padding: 0;
41
+ background: transparent;
42
+ }
43
+
44
+ .eztrak-tabs-item {
45
+ position: relative;
46
+ margin: 0;
47
+ padding: 0;
48
+ }
49
+
50
+ .eztrak-tabs-button {
51
+ position: relative;
52
+ display: flex;
53
+ flex-direction: row;
54
+ align-items: center;
55
+ justify-content: center;
56
+ gap: 6px;
57
+ padding: var(--eztrak-tabs-padding);
58
+ background: var(--eztrak-tabs-inactive-bg);
59
+ border: 1px solid var(--eztrak-tabs-inactive-border);
60
+ border-radius: var(--eztrak-tabs-radius);
61
+ box-shadow:
62
+ 0 1px 3px rgba(0, 0, 0, 0.08),
63
+ 0 0 1px rgba(0, 0, 0, 0.05);
64
+ cursor: pointer;
65
+ outline: none;
66
+ transition: all 0.2s ease;
67
+ min-width: fit-content;
68
+ white-space: nowrap;
69
+ }
70
+
71
+ .eztrak-tabs-button:disabled {
72
+ opacity: 0.5;
73
+ cursor: not-allowed;
74
+ }
75
+
76
+ .eztrak-tabs-icon {
77
+ display: inline-flex;
78
+ align-items: center;
79
+ flex-shrink: 0;
80
+ }
81
+
82
+ .eztrak-tabs-label {
83
+ font-size: 14px;
84
+ font-weight: 400;
85
+ color: var(--eztrak-tabs-label-inactive);
86
+ transition: color 0.2s ease;
87
+ font-family:
88
+ -apple-system,
89
+ BlinkMacSystemFont,
90
+ "Segoe UI",
91
+ Roboto,
92
+ Oxygen,
93
+ Ubuntu,
94
+ Cantarell,
95
+ "Fira Sans",
96
+ "Droid Sans",
97
+ "Helvetica Neue",
98
+ sans-serif;
99
+ line-height: 1.4;
100
+ letter-spacing: 0.01em;
101
+ }
102
+
103
+ .eztrak-tabs-item-active .eztrak-tabs-button {
104
+ flex-direction: column;
105
+ background: var(--eztrak-tabs-active-bg);
106
+ border: none;
107
+ box-shadow: none;
108
+ padding-bottom: 12px;
109
+ }
110
+
111
+ .eztrak-tabs-item-active .eztrak-tabs-label {
112
+ color: var(--eztrak-tabs-label-active);
113
+ font-weight: 500;
114
+ }
115
+
116
+ .eztrak-tabs-underline {
117
+ position: absolute;
118
+ bottom: 0;
119
+ left: 0;
120
+ right: 0;
121
+ height: 3px;
122
+ background: var(--eztrak-tabs-accent);
123
+ border-radius: 2px 2px 0 0;
124
+ animation: eztrak-tabs-slide-in 0.2s ease;
125
+ }
126
+
127
+ @keyframes eztrak-tabs-slide-in {
128
+ from {
129
+ opacity: 0;
130
+ transform: scaleX(0);
131
+ }
132
+ to {
133
+ opacity: 1;
134
+ transform: scaleX(1);
135
+ }
136
+ }
137
+
138
+ .eztrak-tabs-item:not(.eztrak-tabs-item-active) .eztrak-tabs-button:hover:not(:disabled) {
139
+ background: var(--eztrak-tabs-hover-bg);
140
+ border-color: var(--eztrak-tabs-hover-border);
141
+ box-shadow:
142
+ 0 2px 4px rgba(0, 0, 0, 0.1),
143
+ 0 0 1px rgba(0, 0, 0, 0.08);
144
+ }
145
+
146
+ .eztrak-tabs-item:not(.eztrak-tabs-item-active)
147
+ .eztrak-tabs-button:hover:not(:disabled)
148
+ .eztrak-tabs-label {
149
+ color: var(--eztrak-tabs-label-hover);
150
+ }
151
+
152
+ .eztrak-tabs-button:focus-visible {
153
+ outline: 2px solid var(--eztrak-tabs-focus-color);
154
+ outline-offset: 2px;
155
+ border-radius: 8px;
156
+ }
157
+
158
+ .eztrak-tabs-item-active .eztrak-tabs-button:focus-visible {
159
+ outline-offset: 4px;
160
+ }
161
+
162
+ .eztrak-tabs-content {
163
+ width: 100%;
164
+ background: transparent;
165
+ margin-top: 0;
166
+ }
167
+
168
+ .eztrak-tabs-panel {
169
+ width: 100%;
170
+ background: transparent;
171
+ }
172
+
173
+ .eztrak-tabs-panel-hidden {
174
+ display: none;
175
+ }
176
+
177
+ @media screen and (max-width: 768px) {
178
+ .eztrak-tabs-list {
179
+ flex-wrap: wrap;
180
+ gap: var(--eztrak-tabs-gap);
181
+ }
182
+
183
+ .eztrak-tabs-button {
184
+ padding: 10px 16px;
185
+ font-size: 13px;
186
+ }
187
+
188
+ .eztrak-tabs-label {
189
+ font-size: 13px;
190
+ }
191
+ }
192
+
193
+ @media screen and (max-width: 480px) {
194
+ .eztrak-tabs-list {
195
+ gap: 6px;
196
+ }
197
+
198
+ .eztrak-tabs-button {
199
+ padding: 8px 12px;
200
+ }
201
+
202
+ .eztrak-tabs-label {
203
+ font-size: 12px;
204
+ }
205
+ }
package/dist/index.d.mts CHANGED
@@ -1,4 +1,6 @@
1
1
  export { HandleApiErrorOptions, RtkQueryError, capitalizeText, checkIfExistsInArray, cn, convertCommaDataToArray, currencyFormatter, deserializeJson, flattenTableData, formatDate, formatDateTime, formatValidationErrorsHtml, getApiError, getErrorMessages, getFieldsByCategory, getFieldsByInputType, getFieldsByName, handleApiError, isEmpty, normalizeApiListItems, parseCurrencyValueToNumber, removeByPropertyValues, toDateInputValue, toLowerCaseText, truncateText } from './utils/index.mjs';
2
2
  export { UseGridHeightOptions, useGridHeight, usePaginationUrlSync } from './hooks/index.mjs';
3
+ export { EztrakTab, EztrakTabs, EztrakTabsClassNames, EztrakTabsProps } from './components/index.mjs';
3
4
  import 'clsx';
4
5
  import 'react-router-dom';
6
+ import 'react';
package/dist/index.d.ts CHANGED
@@ -1,4 +1,6 @@
1
1
  export { HandleApiErrorOptions, RtkQueryError, capitalizeText, checkIfExistsInArray, cn, convertCommaDataToArray, currencyFormatter, deserializeJson, flattenTableData, formatDate, formatDateTime, formatValidationErrorsHtml, getApiError, getErrorMessages, getFieldsByCategory, getFieldsByInputType, getFieldsByName, handleApiError, isEmpty, normalizeApiListItems, parseCurrencyValueToNumber, removeByPropertyValues, toDateInputValue, toLowerCaseText, truncateText } from './utils/index.js';
2
2
  export { UseGridHeightOptions, useGridHeight, usePaginationUrlSync } from './hooks/index.js';
3
+ export { EztrakTab, EztrakTabs, EztrakTabsClassNames, EztrakTabsProps } from './components/index.js';
3
4
  import 'clsx';
4
5
  import 'react-router-dom';
6
+ import 'react';