@sproutsocial/seeds-react-tabs 1.4.14 → 1.4.16
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.
- package/dist/esm/index.js +168 -49
- package/dist/esm/index.js.map +1 -1
- package/dist/index.d.mts +14 -2
- package/dist/index.d.ts +14 -2
- package/dist/index.js +167 -48
- package/dist/index.js.map +1 -1
- package/dist/tabs.css +122 -0
- package/package.json +16 -5
- package/.eslintignore +0 -6
- package/.eslintrc.js +0 -4
- package/.turbo/turbo-build.log +0 -21
- package/CHANGELOG.md +0 -391
- package/jest.config.js +0 -9
- package/src/Tabs.stories.tsx +0 -258
- package/src/Tabs.tsx +0 -284
- package/src/TabsTypes.ts +0 -48
- package/src/__tests__/Tabs.typetest.tsx +0 -20
- package/src/__tests__/tabs.test.tsx +0 -462
- package/src/index.ts +0 -5
- package/src/styled.d.ts +0 -7
- package/src/styles.ts +0 -119
- package/tsconfig.json +0 -9
- package/tsup.config.ts +0 -12
package/dist/index.js
CHANGED
|
@@ -36,7 +36,11 @@ __export(index_exports, {
|
|
|
36
36
|
module.exports = __toCommonJS(index_exports);
|
|
37
37
|
|
|
38
38
|
// src/Tabs.tsx
|
|
39
|
-
var
|
|
39
|
+
var React4 = __toESM(require("react"));
|
|
40
|
+
|
|
41
|
+
// src/TabsHybrid.tsx
|
|
42
|
+
var React3 = __toESM(require("react"));
|
|
43
|
+
var import_seeds_react_system_props2 = require("@sproutsocial/seeds-react-system-props");
|
|
40
44
|
|
|
41
45
|
// src/styles.ts
|
|
42
46
|
var import_styled_components = __toESM(require("styled-components"));
|
|
@@ -146,16 +150,83 @@ var TabButton = (0, import_styled_components.default)(import_seeds_react_button.
|
|
|
146
150
|
`;
|
|
147
151
|
var styles_default = Container;
|
|
148
152
|
|
|
149
|
-
// src/
|
|
153
|
+
// src/TabsTailwind.tsx
|
|
154
|
+
var React2 = __toESM(require("react"));
|
|
155
|
+
var import_seeds_react_button2 = require("@sproutsocial/seeds-react-button");
|
|
150
156
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
151
|
-
|
|
152
|
-
|
|
157
|
+
function cn(...inputs) {
|
|
158
|
+
const classes = [];
|
|
159
|
+
for (const input of inputs) {
|
|
160
|
+
if (!input) continue;
|
|
161
|
+
if (typeof input === "string") {
|
|
162
|
+
classes.push(input);
|
|
163
|
+
} else if (typeof input === "object") {
|
|
164
|
+
for (const [key, value] of Object.entries(input)) {
|
|
165
|
+
if (value) {
|
|
166
|
+
classes.push(key);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
return classes.join(" ");
|
|
172
|
+
}
|
|
173
|
+
var TabsContainerTailwind = React2.forwardRef(
|
|
174
|
+
({
|
|
175
|
+
fullWidth,
|
|
176
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
177
|
+
selectedId,
|
|
178
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
179
|
+
onSelect,
|
|
180
|
+
className,
|
|
181
|
+
children,
|
|
182
|
+
...rest
|
|
183
|
+
}, ref) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
184
|
+
"div",
|
|
185
|
+
{
|
|
186
|
+
ref,
|
|
187
|
+
className: cn(
|
|
188
|
+
"seeds-tab-container",
|
|
189
|
+
{ "seeds-tab-container-fullwidth": !!fullWidth },
|
|
190
|
+
className
|
|
191
|
+
),
|
|
192
|
+
...rest,
|
|
193
|
+
children
|
|
194
|
+
}
|
|
195
|
+
)
|
|
196
|
+
);
|
|
197
|
+
TabsContainerTailwind.displayName = "TabsContainerTailwind";
|
|
198
|
+
var TabButtonTailwind = ({
|
|
199
|
+
isSelected,
|
|
200
|
+
fullWidth,
|
|
201
|
+
className,
|
|
202
|
+
children,
|
|
203
|
+
...rest
|
|
204
|
+
}) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
205
|
+
import_seeds_react_button2.Button,
|
|
206
|
+
{
|
|
207
|
+
className: cn(
|
|
208
|
+
"seeds-tab-button",
|
|
209
|
+
{
|
|
210
|
+
"seeds-tab-button-selected": !!isSelected,
|
|
211
|
+
"seeds-tab-button-fullwidth": !!fullWidth
|
|
212
|
+
},
|
|
213
|
+
className
|
|
214
|
+
),
|
|
215
|
+
...rest,
|
|
216
|
+
children
|
|
217
|
+
}
|
|
218
|
+
);
|
|
219
|
+
|
|
220
|
+
// src/TabsHybrid.tsx
|
|
221
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
222
|
+
var TabButtonContext = React3.createContext({});
|
|
223
|
+
var TabItemButton = class extends React3.Component {
|
|
153
224
|
static contextType = TabButtonContext;
|
|
154
225
|
// @ts-notes - using the legacy syntax here because `declare` does not play well with babel
|
|
155
226
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
156
227
|
//@ts-ignore
|
|
157
228
|
context;
|
|
158
|
-
buttonRef =
|
|
229
|
+
buttonRef = React3.createRef();
|
|
159
230
|
componentDidMount() {
|
|
160
231
|
this.context.onTabMount?.(this.props.id, this.buttonRef);
|
|
161
232
|
}
|
|
@@ -171,8 +242,29 @@ var TabItemButton = class extends React2.Component {
|
|
|
171
242
|
const { children, id, ...rest } = this.props;
|
|
172
243
|
const { selectedId, onActivate, fullWidth } = this.context;
|
|
173
244
|
const isSelected = selectedId === id;
|
|
174
|
-
|
|
175
|
-
|
|
245
|
+
if ((0, import_seeds_react_system_props2.hasStyledProps)(rest)) {
|
|
246
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
247
|
+
TabButton,
|
|
248
|
+
{
|
|
249
|
+
innerRef: this.buttonRef,
|
|
250
|
+
id,
|
|
251
|
+
onClick: () => onActivate?.(id),
|
|
252
|
+
isSelected,
|
|
253
|
+
tabIndex: isSelected ? 0 : -1,
|
|
254
|
+
fullWidth,
|
|
255
|
+
"data-qa-tab-button": id,
|
|
256
|
+
"data-qa-tab-button-state": isSelected,
|
|
257
|
+
"aria-selected": isSelected,
|
|
258
|
+
role: "tab",
|
|
259
|
+
"aria-controls": `${id}-panel`,
|
|
260
|
+
...rest,
|
|
261
|
+
children
|
|
262
|
+
},
|
|
263
|
+
id
|
|
264
|
+
);
|
|
265
|
+
}
|
|
266
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
267
|
+
TabButtonTailwind,
|
|
176
268
|
{
|
|
177
269
|
innerRef: this.buttonRef,
|
|
178
270
|
id,
|
|
@@ -194,16 +286,16 @@ var TabItemButton = class extends React2.Component {
|
|
|
194
286
|
};
|
|
195
287
|
var TabPanel = ({ children, id, ...rest }) => {
|
|
196
288
|
const panelId = `${id}-panel`;
|
|
197
|
-
return /* @__PURE__ */ (0,
|
|
289
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { id: panelId, role: "tabpanel", "aria-labelledby": id, ...rest, children });
|
|
198
290
|
};
|
|
199
|
-
var Tabs = class extends
|
|
291
|
+
var Tabs = class extends React3.Component {
|
|
200
292
|
static Button = TabItemButton;
|
|
201
293
|
static Panel = TabPanel;
|
|
202
294
|
buttonRefs = {};
|
|
203
295
|
tabList = [];
|
|
204
|
-
containerRef =
|
|
205
|
-
startSentinelRef =
|
|
206
|
-
endSentinelRef =
|
|
296
|
+
containerRef = React3.createRef();
|
|
297
|
+
startSentinelRef = React3.createRef();
|
|
298
|
+
endSentinelRef = React3.createRef();
|
|
207
299
|
startObserver = null;
|
|
208
300
|
endObserver = null;
|
|
209
301
|
componentDidMount() {
|
|
@@ -327,54 +419,81 @@ var Tabs = class extends React2.Component {
|
|
|
327
419
|
"aria-label": ariaLabel,
|
|
328
420
|
...rest
|
|
329
421
|
} = this.props;
|
|
330
|
-
|
|
331
|
-
|
|
422
|
+
const inner = /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
|
|
423
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
424
|
+
"div",
|
|
425
|
+
{
|
|
426
|
+
ref: this.startSentinelRef,
|
|
427
|
+
"aria-hidden": "true",
|
|
428
|
+
style: { flexShrink: 0, width: 1 }
|
|
429
|
+
}
|
|
430
|
+
),
|
|
431
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
432
|
+
TabButtonContext.Provider,
|
|
433
|
+
{
|
|
434
|
+
value: {
|
|
435
|
+
selectedId: this.getSelectedId(),
|
|
436
|
+
fullWidth: this.props.fullWidth,
|
|
437
|
+
onActivate: this.onActivate,
|
|
438
|
+
onTabMount: this.onTabMount,
|
|
439
|
+
onTabUpdate: this.onTabUpdate,
|
|
440
|
+
onTabUnmount: this.onTabUnmount
|
|
441
|
+
},
|
|
442
|
+
children
|
|
443
|
+
}
|
|
444
|
+
),
|
|
445
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
446
|
+
"div",
|
|
447
|
+
{
|
|
448
|
+
ref: this.endSentinelRef,
|
|
449
|
+
"aria-hidden": "true",
|
|
450
|
+
style: { flexShrink: 0, width: 1 }
|
|
451
|
+
}
|
|
452
|
+
)
|
|
453
|
+
] });
|
|
454
|
+
if ((0, import_seeds_react_system_props2.hasStyledProps)(rest)) {
|
|
455
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
456
|
+
styles_default,
|
|
457
|
+
{
|
|
458
|
+
ref: this.containerRef,
|
|
459
|
+
"data-qa-tabs": "",
|
|
460
|
+
onKeyDown: this.keyHandler,
|
|
461
|
+
onSelect,
|
|
462
|
+
role: "tablist",
|
|
463
|
+
"aria-label": ariaLabel,
|
|
464
|
+
...qa,
|
|
465
|
+
...rest,
|
|
466
|
+
children: inner
|
|
467
|
+
}
|
|
468
|
+
);
|
|
469
|
+
}
|
|
470
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
471
|
+
TabsContainerTailwind,
|
|
332
472
|
{
|
|
333
473
|
ref: this.containerRef,
|
|
334
474
|
"data-qa-tabs": "",
|
|
335
475
|
onKeyDown: this.keyHandler,
|
|
336
|
-
onSelect,
|
|
337
476
|
role: "tablist",
|
|
338
477
|
"aria-label": ariaLabel,
|
|
478
|
+
fullWidth: this.props.fullWidth,
|
|
339
479
|
...qa,
|
|
340
480
|
...rest,
|
|
341
|
-
children:
|
|
342
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
343
|
-
"div",
|
|
344
|
-
{
|
|
345
|
-
ref: this.startSentinelRef,
|
|
346
|
-
"aria-hidden": "true",
|
|
347
|
-
style: { flexShrink: 0, width: 1 }
|
|
348
|
-
}
|
|
349
|
-
),
|
|
350
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
351
|
-
TabButtonContext.Provider,
|
|
352
|
-
{
|
|
353
|
-
value: {
|
|
354
|
-
selectedId: this.getSelectedId(),
|
|
355
|
-
fullWidth: this.props.fullWidth,
|
|
356
|
-
onActivate: this.onActivate,
|
|
357
|
-
onTabMount: this.onTabMount,
|
|
358
|
-
onTabUpdate: this.onTabUpdate,
|
|
359
|
-
onTabUnmount: this.onTabUnmount
|
|
360
|
-
},
|
|
361
|
-
children
|
|
362
|
-
}
|
|
363
|
-
),
|
|
364
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
365
|
-
"div",
|
|
366
|
-
{
|
|
367
|
-
ref: this.endSentinelRef,
|
|
368
|
-
"aria-hidden": "true",
|
|
369
|
-
style: { flexShrink: 0, width: 1 }
|
|
370
|
-
}
|
|
371
|
-
)
|
|
372
|
-
]
|
|
481
|
+
children: inner
|
|
373
482
|
}
|
|
374
483
|
);
|
|
375
484
|
}
|
|
376
485
|
};
|
|
377
|
-
var
|
|
486
|
+
var TabsHybrid_default = Tabs;
|
|
487
|
+
|
|
488
|
+
// src/Tabs.tsx
|
|
489
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
490
|
+
var Tabs2 = React4.forwardRef(
|
|
491
|
+
(props, ref) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(TabsHybrid_default, { ...props, ref })
|
|
492
|
+
);
|
|
493
|
+
Tabs2.displayName = "Tabs";
|
|
494
|
+
Tabs2.Button = TabsHybrid_default.Button;
|
|
495
|
+
Tabs2.Panel = TabsHybrid_default.Panel;
|
|
496
|
+
var Tabs_default = Tabs2;
|
|
378
497
|
|
|
379
498
|
// src/index.ts
|
|
380
499
|
var index_default = Tabs_default;
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/Tabs.tsx","../src/styles.ts","../src/TabsTypes.ts"],"sourcesContent":["import Tabs from \"./Tabs\";\n\nexport default Tabs;\nexport { Tabs };\nexport * from \"./TabsTypes\";\n","import * as React from \"react\";\nimport Container, { TabButton } from \"./styles\";\nimport type {\n TypeTabButtonsProps,\n TypeTabsProps,\n TypeTabPanelProps,\n} from \"./TabsTypes\";\n\ninterface TypeTabButtonRef {\n current: null | React.ElementRef<\"button\">;\n}\ninterface TypeTabButtonContext {\n onActivate: (arg0: string) => void;\n onTabMount: (id: string, ref: TypeTabButtonRef) => void;\n onTabUpdate: (previousId: string, nextId: string) => void;\n onTabUnmount: (id: string) => void;\n selectedId: string;\n fullWidth?: boolean;\n}\n\nconst TabButtonContext = React.createContext<Partial<TypeTabButtonContext>>({});\n\nclass TabItemButton extends React.Component<TypeTabButtonsProps> {\n static override contextType = TabButtonContext;\n // @ts-notes - using the legacy syntax here because `declare` does not play well with babel\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n //@ts-ignore\n context!: React.ContextType<typeof TabButtonContext>;\n\n buttonRef: TypeTabButtonRef = React.createRef<React.ElementRef<\"button\">>();\n\n override componentDidMount() {\n this.context.onTabMount?.(this.props.id, this.buttonRef);\n }\n\n override componentDidUpdate(prevProps: TypeTabButtonsProps) {\n if (prevProps.id !== this.props.id) {\n this.context.onTabUpdate?.(prevProps.id, this.props.id);\n }\n }\n\n override componentWillUnmount() {\n this.context.onTabUnmount?.(this.props.id);\n }\n\n override render() {\n const { children, id, ...rest } = this.props;\n const { selectedId, onActivate, fullWidth } = this.context;\n const isSelected = selectedId === id;\n\n return (\n <TabButton\n key={id}\n innerRef={this.buttonRef}\n id={id}\n onClick={() => onActivate?.(id)}\n isSelected={isSelected}\n tabIndex={isSelected ? 0 : -1}\n fullWidth={fullWidth}\n data-qa-tab-button={id}\n data-qa-tab-button-state={isSelected}\n aria-selected={isSelected}\n role=\"tab\"\n aria-controls={`${id}-panel`}\n {...rest}\n >\n {children}\n </TabButton>\n );\n }\n}\n\nconst TabPanel: React.FC<TypeTabPanelProps> = ({ children, id, ...rest }) => {\n const panelId = `${id}-panel`;\n\n return (\n <div id={panelId} role=\"tabpanel\" aria-labelledby={id} {...rest}>\n {children}\n </div>\n );\n};\n\n/**\n * Render a group of buttons in a tab-heading style\n */\nclass Tabs extends React.Component<TypeTabsProps> {\n static Button = TabItemButton;\n static Panel = TabPanel;\n buttonRefs: Record<string, TypeTabButtonRef | null | undefined> = {};\n tabList: string[] = [];\n\n containerRef = React.createRef<HTMLDivElement>();\n startSentinelRef = React.createRef<HTMLDivElement>();\n endSentinelRef = React.createRef<HTMLDivElement>();\n startObserver: IntersectionObserver | null = null;\n endObserver: IntersectionObserver | null = null;\n\n override componentDidMount() {\n const container = this.containerRef.current;\n if (!container) return;\n container.addEventListener(\"wheel\", this.handleWheel, { passive: false });\n\n const startSentinel = this.startSentinelRef.current;\n const endSentinel = this.endSentinelRef.current;\n if (!startSentinel || !endSentinel) return;\n if (typeof IntersectionObserver === \"undefined\") return;\n this.startObserver = new IntersectionObserver(\n ([entry]) => {\n container.toggleAttribute(\"data-fade-left\", !entry?.isIntersecting);\n },\n { root: container, threshold: 1.0, rootMargin: \"0px 0px 0px 1px\" }\n );\n this.endObserver = new IntersectionObserver(\n ([entry]) => {\n container.toggleAttribute(\"data-fade-right\", !entry?.isIntersecting);\n },\n { root: container, threshold: 1.0, rootMargin: \"0px 1px 0px 0px\" }\n );\n this.startObserver.observe(startSentinel);\n this.endObserver.observe(endSentinel);\n }\n\n override componentWillUnmount() {\n this.containerRef.current?.removeEventListener(\"wheel\", this.handleWheel);\n this.startObserver?.disconnect();\n this.endObserver?.disconnect();\n this.startObserver = null;\n this.endObserver = null;\n }\n\n handleWheel = (e: WheelEvent) => {\n const container = this.containerRef.current;\n if (!container) return;\n // Only redirect pure-vertical wheel input. Trackpad horizontal swipes\n // (deltaX !== 0) already scroll natively — don't fight them.\n if (e.deltaY === 0 || e.deltaX !== 0) return;\n // No horizontal overflow means there's nothing to scroll.\n if (container.scrollWidth <= container.clientWidth) return;\n // Release at ends so the page can scroll past the tab bar instead of\n // trapping the user. WCAG 2.1.1 / 2.1.2 spirit.\n const atStart = container.scrollLeft <= 0;\n const atEnd =\n container.scrollLeft + container.clientWidth >= container.scrollWidth;\n if ((atEnd && e.deltaY > 0) || (atStart && e.deltaY < 0)) return;\n\n e.preventDefault();\n // Normalize deltaY across deltaMode units (Firefox can emit LINE/PAGE).\n const lineHeight = 16;\n const pixelDelta =\n e.deltaMode === 1\n ? e.deltaY * lineHeight\n : e.deltaMode === 2\n ? e.deltaY * container.clientHeight\n : e.deltaY;\n container.scrollBy({ left: pixelDelta, behavior: \"instant\" });\n };\n\n getSelectedId = () => this.props.selectedId;\n onActivate = (id: string) => {\n this.props.onSelect(id);\n this.scrollTabIntoView(id);\n };\n\n scrollTabIntoView = (id: string) => {\n const button = this.buttonRefs[id]?.current;\n const container = this.containerRef.current;\n if (!button || !container) return;\n const buttonRect = button.getBoundingClientRect();\n const containerRect = container.getBoundingClientRect();\n const fadePadding = 48;\n const isFullyVisible =\n buttonRect.left >= containerRect.left + fadePadding &&\n buttonRect.right <= containerRect.right - fadePadding;\n if (isFullyVisible) return;\n button.scrollIntoView?.({ block: \"nearest\", inline: \"nearest\" });\n };\n onTabMount = (id: string, ref: TypeTabButtonRef) => {\n if (!this.tabList.includes(id)) {\n this.tabList.push(id);\n this.buttonRefs[id] = ref;\n }\n };\n\n onTabUpdate = (previousId: string, newId: string) => {\n if (this.tabList.includes(previousId)) {\n this.tabList = this.tabList.map((id) => (id === previousId ? newId : id));\n this.buttonRefs[newId] = this.buttonRefs[previousId];\n this.buttonRefs[previousId] = undefined;\n }\n };\n\n onTabUnmount = (id: string) => {\n if (this.tabList.includes(id)) {\n this.tabList = this.tabList.filter((currentId) => currentId !== id);\n this.buttonRefs[id] = undefined;\n }\n };\n\n selectNextTab = (id: string) => {\n this.props.onSelect(id);\n this.buttonRefs[id]?.current?.focus?.({ preventScroll: true });\n this.scrollTabIntoView(id);\n };\n\n keyHandler = (e: React.KeyboardEvent<HTMLDivElement>) => {\n switch (e.keyCode) {\n // left arrow\n case 37:\n this.tabList.forEach((id, index) => {\n e.preventDefault();\n if (id === this.getSelectedId()) {\n const count = this.tabList.length;\n const nextIndex = index - 1 >= 0 ? index - 1 : count - 1;\n const nextId = this.tabList[nextIndex];\n this.selectNextTab(nextId ? nextId : \"\");\n }\n });\n break;\n\n // right arrow\n case 39:\n this.tabList.forEach((id, index) => {\n e.preventDefault();\n if (id === this.getSelectedId()) {\n const count = this.tabList.length;\n const nextIndex = index + 1 < count ? index + 1 : 0;\n const nextId = this.tabList[nextIndex];\n this.selectNextTab(nextId ? nextId : \"\");\n }\n });\n break;\n\n default:\n break;\n }\n };\n\n override render() {\n const {\n children,\n qa,\n onSelect,\n \"aria-label\": ariaLabel,\n ...rest\n } = this.props;\n return (\n <Container\n ref={this.containerRef}\n data-qa-tabs=\"\"\n onKeyDown={this.keyHandler}\n onSelect={onSelect}\n role=\"tablist\"\n aria-label={ariaLabel}\n {...qa}\n {...rest}\n >\n <div\n ref={this.startSentinelRef}\n aria-hidden=\"true\"\n style={{ flexShrink: 0, width: 1 }}\n />\n <TabButtonContext.Provider\n value={{\n selectedId: this.getSelectedId(),\n fullWidth: this.props.fullWidth,\n onActivate: this.onActivate,\n onTabMount: this.onTabMount,\n onTabUpdate: this.onTabUpdate,\n onTabUnmount: this.onTabUnmount,\n }}\n >\n {children}\n </TabButtonContext.Provider>\n <div\n ref={this.endSentinelRef}\n aria-hidden=\"true\"\n style={{ flexShrink: 0, width: 1 }}\n />\n </Container>\n );\n }\n}\n\nexport default Tabs;\n","import styled, { css } from \"styled-components\";\nimport { COMMON } from \"@sproutsocial/seeds-react-system-props\";\nimport { Button } from \"@sproutsocial/seeds-react-button\";\nimport { type TypeTabsProps } from \"./TabsTypes\";\n\ninterface TypeTabState {\n isSelected: boolean;\n}\ntype TypeFullWidth = Pick<TypeTabsProps, \"fullWidth\">;\ninterface TypeStyleProps extends TypeFullWidth, TypeTabState {}\n\nconst Container = styled.div<TypeTabsProps>`\n display: ${(props) => (props.fullWidth ? \"flex\" : \"inline-flex\")};\n margin: 0;\n padding: 0;\n min-width: 0;\n max-width: 100%;\n min-height: min-content;\n flex-shrink: 0;\n overflow-x: auto;\n overflow-y: hidden;\n scrollbar-width: none;\n scroll-padding-inline: 48px;\n scroll-behavior: smooth;\n border-bottom: ${(props) => props.theme.borders[500]}\n ${(props) => props.theme.colors.container.border.base};\n\n &::-webkit-scrollbar {\n display: none;\n }\n\n &[data-fade-right] {\n -webkit-mask-image: linear-gradient(\n to right,\n black 0,\n black calc(100% - 48px),\n transparent\n );\n mask-image: linear-gradient(\n to right,\n black 0,\n black calc(100% - 48px),\n transparent\n );\n }\n\n &[data-fade-left] {\n -webkit-mask-image: linear-gradient(\n to right,\n transparent,\n black 48px,\n black 100%\n );\n mask-image: linear-gradient(to right, transparent, black 48px, black 100%);\n }\n\n &[data-fade-left][data-fade-right] {\n -webkit-mask-image: linear-gradient(\n to right,\n transparent,\n black 48px,\n black calc(100% - 48px),\n transparent\n );\n mask-image: linear-gradient(\n to right,\n transparent,\n black 48px,\n black calc(100% - 48px),\n transparent\n );\n }\n\n ${COMMON}\n`;\n\nexport const TabButton = styled(Button)<TypeStyleProps>`\n margin-bottom: -1px;\n padding: ${(props) =>\n `${props.theme.space[350]} ${\n props.fullWidth ? 0 : props.theme.space[350]\n }`};\n color: ${(props) => props.theme.colors.text.headline};\n border-radius: 0;\n border-width: 0 0 3px;\n width: 100%;\n\n ${(props) =>\n props.fullWidth &&\n css`\n flex-grow: 1;\n `};\n\n ${(props) =>\n props.isSelected &&\n css`\n color: ${(props) => props.theme.colors.link.base};\n border-color: transparent transparent\n ${(props) => props.theme.colors.button.primary.background.base};\n `};\n\n &:hover {\n ${(props) =>\n props.isSelected &&\n css`\n color: ${(props) => props.theme.colors.link.hover};\n `};\n }\n\n &:focus,\n &:active {\n box-shadow: none;\n }\n\n &:active {\n transform: none;\n }\n`;\nexport default Container;\n","import * as React from \"react\";\nimport type {\n TypeStyledComponentsCommonProps,\n TypeSystemCommonProps,\n} from \"@sproutsocial/seeds-react-system-props\";\nimport type { TypeButtonProps } from \"@sproutsocial/seeds-react-button\";\n\nexport interface TypeTabButtonsProps extends TypeButtonProps {\n children: React.ReactNode;\n\n /** Should be unique among sibling elements */\n id: string;\n}\n\nexport interface TypeTabPanelProps\n extends React.ComponentPropsWithoutRef<\"div\"> {\n children: React.ReactNode;\n\n /** Should match the corresponding tab button id */\n id: string;\n}\n\nexport interface TypeTabsProps\n extends TypeStyledComponentsCommonProps,\n TypeSystemCommonProps,\n Omit<\n React.ComponentPropsWithoutRef<\"ul\">,\n keyof TypeSystemCommonProps | \"onSelect\"\n > {\n children: React.ReactNode;\n onSelect: (arg0: string) => void;\n\n /** Whether or not the tabs should stretch to fill the width of their container */\n fullWidth?: boolean;\n qa?: object;\n\n /** ID of the selected tab */\n selectedId: string;\n\n /**\n * Accessible label for the tab list. Forwarded to the `role=\"tablist\"`\n * element. Recommended by the WAI-ARIA Tabs pattern so screen readers\n * can announce what the tabs represent (e.g. \"Report sections\").\n * Use `aria-labelledby` instead via `{...rest}` if you have a visible\n * heading to reference.\n */\n \"aria-label\"?: string;\n}\n"],"mappings":"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","names":["React","styled","props"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/Tabs.tsx","../src/TabsHybrid.tsx","../src/styles.ts","../src/TabsTypes.ts","../src/TabsTailwind.tsx"],"sourcesContent":["import Tabs from \"./Tabs\";\n\nexport default Tabs;\nexport { Tabs };\nexport * from \"./TabsTypes\";\n","import * as React from \"react\";\nimport type { TypeTabsProps } from \"./TabsTypes\";\nimport TabsHybrid from \"./TabsHybrid\";\n\n// TabsHybrid's default export is the stateful class that carries the\n// Button/Panel statics; a forwarded ref resolves to that class instance\n// (same as the original Tabs class — no consumer relies on a DOM ref here).\ntype TabsComponent = React.ForwardRefExoticComponent<\n React.PropsWithoutRef<TypeTabsProps> &\n React.RefAttributes<InstanceType<typeof TabsHybrid>>\n> & {\n Button: typeof TabsHybrid.Button;\n Panel: typeof TabsHybrid.Panel;\n};\n\n/**\n * Tabs component. Automatically routes between the Tailwind implementation\n * (preferred) and the styled-components implementation (for consumers using\n * system props). Defined as a real wrapper (not a bare re-export) so\n * react-docgen can extract its props for the Racine props-docs build.\n */\nconst Tabs = React.forwardRef<InstanceType<typeof TabsHybrid>, TypeTabsProps>(\n (props, ref) => <TabsHybrid {...props} ref={ref} />\n) as TabsComponent;\n\nTabs.displayName = \"Tabs\";\n// Preserve the compound-component API consumed as <Tabs.Button> / <Tabs.Panel>.\nTabs.Button = TabsHybrid.Button;\nTabs.Panel = TabsHybrid.Panel;\n\nexport default Tabs;\n","import * as React from \"react\";\nimport { hasStyledProps } from \"@sproutsocial/seeds-react-system-props\";\nimport Container, { TabButton } from \"./styles\";\nimport { TabsContainerTailwind, TabButtonTailwind } from \"./TabsTailwind\";\nimport type {\n TypeTabButtonsProps,\n TypeTabsProps,\n TypeTabPanelProps,\n} from \"./TabsTypes\";\n\ninterface TypeTabButtonRef {\n current: null | React.ElementRef<\"button\">;\n}\ninterface TypeTabButtonContext {\n onActivate: (arg0: string) => void;\n onTabMount: (id: string, ref: TypeTabButtonRef) => void;\n onTabUpdate: (previousId: string, nextId: string) => void;\n onTabUnmount: (id: string) => void;\n selectedId: string;\n fullWidth?: boolean;\n}\n\nconst TabButtonContext = React.createContext<Partial<TypeTabButtonContext>>({});\n\nclass TabItemButton extends React.Component<TypeTabButtonsProps> {\n static override contextType = TabButtonContext;\n // @ts-notes - using the legacy syntax here because `declare` does not play well with babel\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n //@ts-ignore\n context!: React.ContextType<typeof TabButtonContext>;\n\n buttonRef: TypeTabButtonRef = React.createRef<React.ElementRef<\"button\">>();\n\n override componentDidMount() {\n this.context.onTabMount?.(this.props.id, this.buttonRef);\n }\n\n override componentDidUpdate(prevProps: TypeTabButtonsProps) {\n if (prevProps.id !== this.props.id) {\n this.context.onTabUpdate?.(prevProps.id, this.props.id);\n }\n }\n\n override componentWillUnmount() {\n this.context.onTabUnmount?.(this.props.id);\n }\n\n override render() {\n const { children, id, ...rest } = this.props;\n const { selectedId, onActivate, fullWidth } = this.context;\n const isSelected = selectedId === id;\n\n // Route per-render: consumers passing styled-system props get the\n // styled-components TabButton (path unchanged from before the migration);\n // everyone else gets the CSS-class path. Both branches pass the identical\n // prop set — isSelected/fullWidth are consumed as styled props in the SC\n // path and mapped to classes in the Tailwind path.\n if (hasStyledProps(rest)) {\n return (\n <TabButton\n key={id}\n innerRef={this.buttonRef}\n id={id}\n onClick={() => onActivate?.(id)}\n isSelected={isSelected}\n tabIndex={isSelected ? 0 : -1}\n fullWidth={fullWidth}\n data-qa-tab-button={id}\n data-qa-tab-button-state={isSelected}\n aria-selected={isSelected}\n role=\"tab\"\n aria-controls={`${id}-panel`}\n {...rest}\n >\n {children}\n </TabButton>\n );\n }\n\n return (\n <TabButtonTailwind\n key={id}\n innerRef={this.buttonRef}\n id={id}\n onClick={() => onActivate?.(id)}\n isSelected={isSelected}\n tabIndex={isSelected ? 0 : -1}\n fullWidth={fullWidth}\n data-qa-tab-button={id}\n data-qa-tab-button-state={isSelected}\n aria-selected={isSelected}\n role=\"tab\"\n aria-controls={`${id}-panel`}\n {...rest}\n >\n {children}\n </TabButtonTailwind>\n );\n }\n}\n\nconst TabPanel: React.FC<TypeTabPanelProps> = ({ children, id, ...rest }) => {\n const panelId = `${id}-panel`;\n\n return (\n <div id={panelId} role=\"tabpanel\" aria-labelledby={id} {...rest}>\n {children}\n </div>\n );\n};\n\n/**\n * Render a group of buttons in a tab-heading style\n */\nclass Tabs extends React.Component<TypeTabsProps> {\n static Button = TabItemButton;\n static Panel = TabPanel;\n buttonRefs: Record<string, TypeTabButtonRef | null | undefined> = {};\n tabList: string[] = [];\n\n containerRef = React.createRef<HTMLDivElement>();\n startSentinelRef = React.createRef<HTMLDivElement>();\n endSentinelRef = React.createRef<HTMLDivElement>();\n startObserver: IntersectionObserver | null = null;\n endObserver: IntersectionObserver | null = null;\n\n override componentDidMount() {\n const container = this.containerRef.current;\n if (!container) return;\n container.addEventListener(\"wheel\", this.handleWheel, { passive: false });\n\n const startSentinel = this.startSentinelRef.current;\n const endSentinel = this.endSentinelRef.current;\n if (!startSentinel || !endSentinel) return;\n if (typeof IntersectionObserver === \"undefined\") return;\n this.startObserver = new IntersectionObserver(\n ([entry]) => {\n container.toggleAttribute(\"data-fade-left\", !entry?.isIntersecting);\n },\n { root: container, threshold: 1.0, rootMargin: \"0px 0px 0px 1px\" }\n );\n this.endObserver = new IntersectionObserver(\n ([entry]) => {\n container.toggleAttribute(\"data-fade-right\", !entry?.isIntersecting);\n },\n { root: container, threshold: 1.0, rootMargin: \"0px 1px 0px 0px\" }\n );\n this.startObserver.observe(startSentinel);\n this.endObserver.observe(endSentinel);\n }\n\n override componentWillUnmount() {\n this.containerRef.current?.removeEventListener(\"wheel\", this.handleWheel);\n this.startObserver?.disconnect();\n this.endObserver?.disconnect();\n this.startObserver = null;\n this.endObserver = null;\n }\n\n handleWheel = (e: WheelEvent) => {\n const container = this.containerRef.current;\n if (!container) return;\n // Only redirect pure-vertical wheel input. Trackpad horizontal swipes\n // (deltaX !== 0) already scroll natively — don't fight them.\n if (e.deltaY === 0 || e.deltaX !== 0) return;\n // No horizontal overflow means there's nothing to scroll.\n if (container.scrollWidth <= container.clientWidth) return;\n // Release at ends so the page can scroll past the tab bar instead of\n // trapping the user. WCAG 2.1.1 / 2.1.2 spirit.\n const atStart = container.scrollLeft <= 0;\n const atEnd =\n container.scrollLeft + container.clientWidth >= container.scrollWidth;\n if ((atEnd && e.deltaY > 0) || (atStart && e.deltaY < 0)) return;\n\n e.preventDefault();\n // Normalize deltaY across deltaMode units (Firefox can emit LINE/PAGE).\n const lineHeight = 16;\n const pixelDelta =\n e.deltaMode === 1\n ? e.deltaY * lineHeight\n : e.deltaMode === 2\n ? e.deltaY * container.clientHeight\n : e.deltaY;\n container.scrollBy({ left: pixelDelta, behavior: \"instant\" });\n };\n\n getSelectedId = () => this.props.selectedId;\n onActivate = (id: string) => {\n this.props.onSelect(id);\n this.scrollTabIntoView(id);\n };\n\n scrollTabIntoView = (id: string) => {\n const button = this.buttonRefs[id]?.current;\n const container = this.containerRef.current;\n if (!button || !container) return;\n const buttonRect = button.getBoundingClientRect();\n const containerRect = container.getBoundingClientRect();\n const fadePadding = 48;\n const isFullyVisible =\n buttonRect.left >= containerRect.left + fadePadding &&\n buttonRect.right <= containerRect.right - fadePadding;\n if (isFullyVisible) return;\n button.scrollIntoView?.({ block: \"nearest\", inline: \"nearest\" });\n };\n onTabMount = (id: string, ref: TypeTabButtonRef) => {\n if (!this.tabList.includes(id)) {\n this.tabList.push(id);\n this.buttonRefs[id] = ref;\n }\n };\n\n onTabUpdate = (previousId: string, newId: string) => {\n if (this.tabList.includes(previousId)) {\n this.tabList = this.tabList.map((id) => (id === previousId ? newId : id));\n this.buttonRefs[newId] = this.buttonRefs[previousId];\n this.buttonRefs[previousId] = undefined;\n }\n };\n\n onTabUnmount = (id: string) => {\n if (this.tabList.includes(id)) {\n this.tabList = this.tabList.filter((currentId) => currentId !== id);\n this.buttonRefs[id] = undefined;\n }\n };\n\n selectNextTab = (id: string) => {\n this.props.onSelect(id);\n this.buttonRefs[id]?.current?.focus?.({ preventScroll: true });\n this.scrollTabIntoView(id);\n };\n\n keyHandler = (e: React.KeyboardEvent<HTMLDivElement>) => {\n switch (e.keyCode) {\n // left arrow\n case 37:\n this.tabList.forEach((id, index) => {\n e.preventDefault();\n if (id === this.getSelectedId()) {\n const count = this.tabList.length;\n const nextIndex = index - 1 >= 0 ? index - 1 : count - 1;\n const nextId = this.tabList[nextIndex];\n this.selectNextTab(nextId ? nextId : \"\");\n }\n });\n break;\n\n // right arrow\n case 39:\n this.tabList.forEach((id, index) => {\n e.preventDefault();\n if (id === this.getSelectedId()) {\n const count = this.tabList.length;\n const nextIndex = index + 1 < count ? index + 1 : 0;\n const nextId = this.tabList[nextIndex];\n this.selectNextTab(nextId ? nextId : \"\");\n }\n });\n break;\n\n default:\n break;\n }\n };\n\n override render() {\n const {\n children,\n qa,\n onSelect,\n \"aria-label\": ariaLabel,\n ...rest\n } = this.props;\n\n const inner = (\n <>\n <div\n ref={this.startSentinelRef}\n aria-hidden=\"true\"\n style={{ flexShrink: 0, width: 1 }}\n />\n <TabButtonContext.Provider\n value={{\n selectedId: this.getSelectedId(),\n fullWidth: this.props.fullWidth,\n onActivate: this.onActivate,\n onTabMount: this.onTabMount,\n onTabUpdate: this.onTabUpdate,\n onTabUnmount: this.onTabUnmount,\n }}\n >\n {children}\n </TabButtonContext.Provider>\n <div\n ref={this.endSentinelRef}\n aria-hidden=\"true\"\n style={{ flexShrink: 0, width: 1 }}\n />\n </>\n );\n\n // Styled-components path — byte-identical to the pre-migration render so\n // consumers using styled() extension or styled-system props are unaffected.\n if (hasStyledProps(rest)) {\n return (\n <Container\n ref={this.containerRef}\n data-qa-tabs=\"\"\n onKeyDown={this.keyHandler}\n onSelect={onSelect}\n role=\"tablist\"\n aria-label={ariaLabel}\n {...qa}\n {...rest}\n >\n {inner}\n </Container>\n );\n }\n\n // Tailwind / CSS-class path (preferred — zero styled-components runtime).\n return (\n <TabsContainerTailwind\n ref={this.containerRef}\n data-qa-tabs=\"\"\n onKeyDown={this.keyHandler}\n role=\"tablist\"\n aria-label={ariaLabel}\n fullWidth={this.props.fullWidth}\n {...qa}\n {...rest}\n >\n {inner}\n </TabsContainerTailwind>\n );\n }\n}\n\nexport default Tabs;\n","import styled, { css } from \"styled-components\";\nimport { COMMON } from \"@sproutsocial/seeds-react-system-props\";\nimport { Button } from \"@sproutsocial/seeds-react-button\";\nimport { type TypeTabsProps } from \"./TabsTypes\";\n\ninterface TypeTabState {\n isSelected: boolean;\n}\ntype TypeFullWidth = Pick<TypeTabsProps, \"fullWidth\">;\ninterface TypeStyleProps extends TypeFullWidth, TypeTabState {}\n\nconst Container = styled.div<TypeTabsProps>`\n display: ${(props) => (props.fullWidth ? \"flex\" : \"inline-flex\")};\n margin: 0;\n padding: 0;\n min-width: 0;\n max-width: 100%;\n min-height: min-content;\n flex-shrink: 0;\n overflow-x: auto;\n overflow-y: hidden;\n scrollbar-width: none;\n scroll-padding-inline: 48px;\n scroll-behavior: smooth;\n border-bottom: ${(props) => props.theme.borders[500]}\n ${(props) => props.theme.colors.container.border.base};\n\n &::-webkit-scrollbar {\n display: none;\n }\n\n &[data-fade-right] {\n -webkit-mask-image: linear-gradient(\n to right,\n black 0,\n black calc(100% - 48px),\n transparent\n );\n mask-image: linear-gradient(\n to right,\n black 0,\n black calc(100% - 48px),\n transparent\n );\n }\n\n &[data-fade-left] {\n -webkit-mask-image: linear-gradient(\n to right,\n transparent,\n black 48px,\n black 100%\n );\n mask-image: linear-gradient(to right, transparent, black 48px, black 100%);\n }\n\n &[data-fade-left][data-fade-right] {\n -webkit-mask-image: linear-gradient(\n to right,\n transparent,\n black 48px,\n black calc(100% - 48px),\n transparent\n );\n mask-image: linear-gradient(\n to right,\n transparent,\n black 48px,\n black calc(100% - 48px),\n transparent\n );\n }\n\n ${COMMON}\n`;\n\nexport const TabButton = styled(Button)<TypeStyleProps>`\n margin-bottom: -1px;\n padding: ${(props) =>\n `${props.theme.space[350]} ${\n props.fullWidth ? 0 : props.theme.space[350]\n }`};\n color: ${(props) => props.theme.colors.text.headline};\n border-radius: 0;\n border-width: 0 0 3px;\n width: 100%;\n\n ${(props) =>\n props.fullWidth &&\n css`\n flex-grow: 1;\n `};\n\n ${(props) =>\n props.isSelected &&\n css`\n color: ${(props) => props.theme.colors.link.base};\n border-color: transparent transparent\n ${(props) => props.theme.colors.button.primary.background.base};\n `};\n\n &:hover {\n ${(props) =>\n props.isSelected &&\n css`\n color: ${(props) => props.theme.colors.link.hover};\n `};\n }\n\n &:focus,\n &:active {\n box-shadow: none;\n }\n\n &:active {\n transform: none;\n }\n`;\nexport default Container;\n","import * as React from \"react\";\nimport type {\n TypeStyledComponentsCommonProps,\n TypeSystemCommonProps,\n} from \"@sproutsocial/seeds-react-system-props\";\nimport type { TypeButtonProps } from \"@sproutsocial/seeds-react-button\";\n\nexport interface TypeTabButtonsProps extends TypeButtonProps {\n children: React.ReactNode;\n\n /** Should be unique among sibling elements */\n id: string;\n}\n\nexport interface TypeTabPanelProps\n extends React.ComponentPropsWithoutRef<\"div\"> {\n children: React.ReactNode;\n\n /** Should match the corresponding tab button id */\n id: string;\n}\n\nexport interface TypeTabsProps\n extends TypeStyledComponentsCommonProps,\n TypeSystemCommonProps,\n Omit<\n React.ComponentPropsWithoutRef<\"ul\">,\n keyof TypeSystemCommonProps | \"onSelect\"\n > {\n children: React.ReactNode;\n onSelect: (arg0: string) => void;\n\n /** Whether or not the tabs should stretch to fill the width of their container */\n fullWidth?: boolean;\n qa?: object;\n\n /** ID of the selected tab */\n selectedId: string;\n\n /**\n * Accessible label for the tab list. Forwarded to the `role=\"tablist\"`\n * element. Recommended by the WAI-ARIA Tabs pattern so screen readers\n * can announce what the tabs represent (e.g. \"Report sections\").\n * Use `aria-labelledby` instead via `{...rest}` if you have a visible\n * heading to reference.\n */\n \"aria-label\"?: string;\n}\n","/**\n * Tailwind CSS implementation of the Tabs component's styled wrappers.\n * Renders the container `<div>` and tab `<Button>` with Seeds tab CSS classes\n * from tabs.css instead of styled-components. Used by TabsHybrid for consumers\n * that pass no styled-system props.\n */\n\nimport * as React from \"react\";\nimport { Button } from \"@sproutsocial/seeds-react-button\";\nimport type { TypeButtonProps } from \"@sproutsocial/seeds-react-button\";\n\n// Local cn — copied from ButtonTailwind.tsx (NOT imported from seeds-react-utilities,\n// which does not export it). Merges strings and { className: boolean } maps.\nfunction cn(\n ...inputs: (string | undefined | null | false | Record<string, boolean>)[]\n): string {\n const classes: string[] = [];\n\n for (const input of inputs) {\n if (!input) continue;\n\n if (typeof input === \"string\") {\n classes.push(input);\n } else if (typeof input === \"object\") {\n for (const [key, value] of Object.entries(input)) {\n if (value) {\n classes.push(key);\n }\n }\n }\n }\n\n return classes.join(\" \");\n}\n\ninterface TabsContainerTailwindProps {\n /** Mapped to a layout class; never forwarded to the DOM. */\n fullWidth?: boolean;\n /** Consumed/stripped so they never land on the <div> (styled-components\n * silently dropped these non-DOM props; a plain <div> would not). */\n selectedId?: string;\n onSelect?: (id: string) => void;\n className?: string;\n children?: React.ReactNode;\n // The container forwards the remaining tablist props (role, aria-label,\n // data-qa-tabs, onKeyDown, …). They originate from TypeTabsProps (a `ul`-based\n // type) but render onto a `div`, so accept them loosely here.\n [key: string]: unknown;\n}\n\nexport const TabsContainerTailwind = React.forwardRef<\n HTMLDivElement,\n TabsContainerTailwindProps\n>(\n (\n {\n fullWidth,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n selectedId,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n onSelect,\n className,\n children,\n ...rest\n },\n ref\n ) => (\n <div\n ref={ref}\n className={cn(\n \"seeds-tab-container\",\n { \"seeds-tab-container-fullwidth\": !!fullWidth },\n className\n )}\n {...(rest as unknown as React.HTMLAttributes<HTMLDivElement>)}\n >\n {children}\n </div>\n )\n);\nTabsContainerTailwind.displayName = \"TabsContainerTailwind\";\n\ninterface TabButtonTailwindProps extends TypeButtonProps {\n // Custom (non-DOM) props mapped to classes — must not be forwarded to Button.\n isSelected?: boolean;\n fullWidth?: boolean;\n}\n\nexport const TabButtonTailwind = ({\n isSelected,\n fullWidth,\n className,\n children,\n ...rest\n}: TabButtonTailwindProps) => (\n <Button\n className={cn(\n \"seeds-tab-button\",\n {\n \"seeds-tab-button-selected\": !!isSelected,\n \"seeds-tab-button-fullwidth\": !!fullWidth,\n },\n className\n )}\n {...rest}\n >\n {children}\n </Button>\n);\n"],"mappings":"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","names":["React","React","import_seeds_react_system_props","styled","props","React","import_seeds_react_button","import_jsx_runtime","import_jsx_runtime","Tabs"]}
|
package/dist/tabs.css
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Seeds Tabs component classes
|
|
3
|
+
* CSS-class implementation of the tab list container and tab buttons, mirroring
|
|
4
|
+
* the styled-components version in styles.ts. Used by the Tailwind path of the
|
|
5
|
+
* hybrid Tabs component.
|
|
6
|
+
*
|
|
7
|
+
* Requires @sproutsocial/seeds-react-theme/dist/theme-all.css imported for
|
|
8
|
+
* CSS variable definitions and dark mode support. Tab buttons render on top of
|
|
9
|
+
* the .seeds-btn / .seeds-btn-unstyled classes from button.css — both files
|
|
10
|
+
* are in `@layer components`, so source order (tabs imported after button)
|
|
11
|
+
* determines which overrides win.
|
|
12
|
+
*
|
|
13
|
+
* All rules are wrapped in `@layer components` so consumer Tailwind utilities
|
|
14
|
+
* (which are unlayered) win the cascade over these component styles. Without the
|
|
15
|
+
* layer, equal-specificity utilities like `mx-200`, `p-300`, or `inline-flex`
|
|
16
|
+
* would be decided by source order and could silently lose to the component CSS.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
@layer components {
|
|
20
|
+
.seeds-tab-container {
|
|
21
|
+
display: inline-flex;
|
|
22
|
+
margin: 0;
|
|
23
|
+
padding: 0;
|
|
24
|
+
min-width: 0;
|
|
25
|
+
max-width: 100%;
|
|
26
|
+
min-height: min-content;
|
|
27
|
+
flex-shrink: 0;
|
|
28
|
+
overflow-x: auto;
|
|
29
|
+
overflow-y: hidden;
|
|
30
|
+
scrollbar-width: none;
|
|
31
|
+
scroll-padding-inline: 48px;
|
|
32
|
+
scroll-behavior: smooth;
|
|
33
|
+
border-bottom: 1px solid var(--color-container-border-base);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.seeds-tab-container-fullwidth {
|
|
37
|
+
display: flex;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.seeds-tab-container::-webkit-scrollbar {
|
|
41
|
+
display: none;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.seeds-tab-container[data-fade-right] {
|
|
45
|
+
-webkit-mask-image: linear-gradient(
|
|
46
|
+
to right,
|
|
47
|
+
black 0,
|
|
48
|
+
black calc(100% - 48px),
|
|
49
|
+
transparent
|
|
50
|
+
);
|
|
51
|
+
mask-image: linear-gradient(
|
|
52
|
+
to right,
|
|
53
|
+
black 0,
|
|
54
|
+
black calc(100% - 48px),
|
|
55
|
+
transparent
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.seeds-tab-container[data-fade-left] {
|
|
60
|
+
-webkit-mask-image: linear-gradient(
|
|
61
|
+
to right,
|
|
62
|
+
transparent,
|
|
63
|
+
black 48px,
|
|
64
|
+
black 100%
|
|
65
|
+
);
|
|
66
|
+
mask-image: linear-gradient(to right, transparent, black 48px, black 100%);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.seeds-tab-container[data-fade-left][data-fade-right] {
|
|
70
|
+
-webkit-mask-image: linear-gradient(
|
|
71
|
+
to right,
|
|
72
|
+
transparent,
|
|
73
|
+
black 48px,
|
|
74
|
+
black calc(100% - 48px),
|
|
75
|
+
transparent
|
|
76
|
+
);
|
|
77
|
+
mask-image: linear-gradient(
|
|
78
|
+
to right,
|
|
79
|
+
transparent,
|
|
80
|
+
black 48px,
|
|
81
|
+
black calc(100% - 48px),
|
|
82
|
+
transparent
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
.seeds-tab-button {
|
|
87
|
+
margin-bottom: -1px;
|
|
88
|
+
padding: var(--space-350) var(--space-350);
|
|
89
|
+
color: var(--color-text-headline);
|
|
90
|
+
border-radius: 0;
|
|
91
|
+
border-width: 0 0 3px;
|
|
92
|
+
/* Reserve the 3px indicator while keeping it invisible until selected, so
|
|
93
|
+
selecting a tab causes no layout shift (matches the styled-components path,
|
|
94
|
+
which inherits transparent borders from .seeds-btn-unstyled). */
|
|
95
|
+
border-color: transparent;
|
|
96
|
+
width: 100%;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.seeds-tab-button-fullwidth {
|
|
100
|
+
flex-grow: 1;
|
|
101
|
+
padding-left: 0;
|
|
102
|
+
padding-right: 0;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
.seeds-tab-button-selected {
|
|
106
|
+
color: var(--color-link-base);
|
|
107
|
+
border-color: transparent transparent var(--color-button-primary-bg-base);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.seeds-tab-button-selected:hover {
|
|
111
|
+
color: var(--color-link-hover);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
.seeds-tab-button:focus,
|
|
115
|
+
.seeds-tab-button:active {
|
|
116
|
+
box-shadow: none;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
.seeds-tab-button:active {
|
|
120
|
+
transform: none;
|
|
121
|
+
}
|
|
122
|
+
}
|
package/package.json
CHANGED
|
@@ -1,15 +1,26 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sproutsocial/seeds-react-tabs",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.16",
|
|
4
4
|
"description": "Seeds React Tabs",
|
|
5
5
|
"author": "Sprout Social, Inc.",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"main": "dist/index.js",
|
|
8
8
|
"module": "dist/esm/index.js",
|
|
9
9
|
"types": "dist/index.d.ts",
|
|
10
|
+
"files": [
|
|
11
|
+
"dist"
|
|
12
|
+
],
|
|
13
|
+
"exports": {
|
|
14
|
+
".": {
|
|
15
|
+
"import": "./dist/esm/index.js",
|
|
16
|
+
"require": "./dist/index.js",
|
|
17
|
+
"types": "./dist/index.d.ts"
|
|
18
|
+
},
|
|
19
|
+
"./dist/tabs.css": "./dist/tabs.css"
|
|
20
|
+
},
|
|
10
21
|
"scripts": {
|
|
11
|
-
"build": "tsup --dts",
|
|
12
|
-
"build:debug": "tsup --dts --metafile",
|
|
22
|
+
"build": "tsup --dts && cp src/tabs.css dist/tabs.css",
|
|
23
|
+
"build:debug": "tsup --dts --metafile && cp src/tabs.css dist/tabs.css",
|
|
13
24
|
"dev": "tsup --watch --dts",
|
|
14
25
|
"clean": "rm -rf .turbo dist",
|
|
15
26
|
"clean:modules": "rm -rf node_modules",
|
|
@@ -18,9 +29,9 @@
|
|
|
18
29
|
"test:watch": "jest --watch --coverage=false"
|
|
19
30
|
},
|
|
20
31
|
"dependencies": {
|
|
21
|
-
"@sproutsocial/seeds-react-theme": "^4.2.
|
|
32
|
+
"@sproutsocial/seeds-react-theme": "^4.2.1",
|
|
22
33
|
"@sproutsocial/seeds-react-system-props": "^3.1.2",
|
|
23
|
-
"@sproutsocial/seeds-react-button": "^2.2.
|
|
34
|
+
"@sproutsocial/seeds-react-button": "^2.2.5"
|
|
24
35
|
},
|
|
25
36
|
"devDependencies": {
|
|
26
37
|
"@types/react": "^18.0.0",
|
package/.eslintignore
DELETED
package/.eslintrc.js
DELETED
package/.turbo/turbo-build.log
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
yarn run v1.22.22
|
|
2
|
-
$ tsup --dts
|
|
3
|
-
[34mCLI[39m Building entry: src/index.ts
|
|
4
|
-
[34mCLI[39m Using tsconfig: tsconfig.json
|
|
5
|
-
[34mCLI[39m tsup v8.5.0
|
|
6
|
-
[34mCLI[39m Using tsup config: /home/runner/_work/seeds/seeds/seeds-react/seeds-react-tabs/tsup.config.ts
|
|
7
|
-
[34mCLI[39m Target: es2022
|
|
8
|
-
[34mCLI[39m Cleaning output folder
|
|
9
|
-
[34mCJS[39m Build start
|
|
10
|
-
[34mESM[39m Build start
|
|
11
|
-
[32mCJS[39m [1mdist/index.js [22m[32m11.88 KB[39m
|
|
12
|
-
[32mCJS[39m [1mdist/index.js.map [22m[32m19.36 KB[39m
|
|
13
|
-
[32mCJS[39m ⚡️ Build success in 17ms
|
|
14
|
-
[32mESM[39m [1mdist/esm/index.js [22m[32m9.89 KB[39m
|
|
15
|
-
[32mESM[39m [1mdist/esm/index.js.map [22m[32m19.31 KB[39m
|
|
16
|
-
[32mESM[39m ⚡️ Build success in 17ms
|
|
17
|
-
[34mDTS[39m Build start
|
|
18
|
-
[32mDTS[39m ⚡️ Build success in 5362ms
|
|
19
|
-
[32mDTS[39m [1mdist/index.d.ts [22m[32m3.38 KB[39m
|
|
20
|
-
[32mDTS[39m [1mdist/index.d.mts [22m[32m3.38 KB[39m
|
|
21
|
-
Done in 6.71s.
|