@papernote/ui 1.9.2 → 1.10.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.
- package/dist/components/NotificationBell.d.ts +7 -1
- package/dist/components/NotificationBell.d.ts.map +1 -1
- package/dist/components/Tabs.d.ts +112 -1
- package/dist/components/Tabs.d.ts.map +1 -1
- package/dist/components/index.d.ts +2 -2
- package/dist/components/index.d.ts.map +1 -1
- package/dist/index.d.ts +120 -4
- package/dist/index.esm.js +437 -125
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +439 -123
- package/dist/index.js.map +1 -1
- package/dist/styles.css +23 -0
- package/package.json +1 -1
- package/src/components/NotificationBell.stories.tsx +71 -0
- package/src/components/NotificationBell.tsx +12 -4
- package/src/components/Tabs.stories.tsx +649 -6
- package/src/components/Tabs.tsx +613 -19
- package/src/components/index.ts +2 -2
package/dist/index.js
CHANGED
|
@@ -8191,11 +8191,254 @@ function Breadcrumbs({ items, showHome = true }) {
|
|
|
8191
8191
|
})] }));
|
|
8192
8192
|
}
|
|
8193
8193
|
|
|
8194
|
-
function
|
|
8194
|
+
function Badge({ children, variant = 'neutral', size = 'md', icon, onRemove, className = '', dot = false, pill = false, }) {
|
|
8195
|
+
const variantStyles = {
|
|
8196
|
+
success: 'bg-success-50 text-success-700 border-success-200',
|
|
8197
|
+
warning: 'bg-warning-50 text-warning-700 border-warning-200',
|
|
8198
|
+
error: 'bg-error-50 text-error-700 border-error-200',
|
|
8199
|
+
info: 'bg-primary-50 text-primary-700 border-primary-200',
|
|
8200
|
+
neutral: 'bg-paper-100 text-ink-700 border-paper-300',
|
|
8201
|
+
};
|
|
8202
|
+
const dotVariantStyles = {
|
|
8203
|
+
success: 'bg-success-500',
|
|
8204
|
+
warning: 'bg-warning-500',
|
|
8205
|
+
error: 'bg-error-500',
|
|
8206
|
+
info: 'bg-primary-500',
|
|
8207
|
+
neutral: 'bg-ink-400',
|
|
8208
|
+
};
|
|
8209
|
+
const sizeStyles = {
|
|
8210
|
+
sm: 'px-2 py-0.5 text-xs gap-1',
|
|
8211
|
+
md: 'px-3 py-1 text-xs gap-1.5',
|
|
8212
|
+
lg: 'px-3 py-1.5 text-sm gap-2',
|
|
8213
|
+
};
|
|
8214
|
+
// Pill variant has tighter horizontal padding and fully rounded ends
|
|
8215
|
+
const pillSizeStyles = {
|
|
8216
|
+
sm: 'px-1.5 py-0.5 text-xs gap-1',
|
|
8217
|
+
md: 'px-2 py-0.5 text-xs gap-1',
|
|
8218
|
+
lg: 'px-2.5 py-1 text-sm gap-1.5',
|
|
8219
|
+
};
|
|
8220
|
+
const dotSizeStyles = {
|
|
8221
|
+
sm: 'h-1.5 w-1.5',
|
|
8222
|
+
md: 'h-2 w-2',
|
|
8223
|
+
lg: 'h-2.5 w-2.5',
|
|
8224
|
+
};
|
|
8225
|
+
const iconSize = {
|
|
8226
|
+
sm: 'h-3 w-3',
|
|
8227
|
+
md: 'h-3.5 w-3.5',
|
|
8228
|
+
lg: 'h-4 w-4',
|
|
8229
|
+
};
|
|
8230
|
+
// Dot variant - just a colored circle
|
|
8231
|
+
if (dot) {
|
|
8232
|
+
return (jsxRuntime.jsx("span", { className: `
|
|
8233
|
+
inline-block rounded-full
|
|
8234
|
+
${dotVariantStyles[variant]}
|
|
8235
|
+
${dotSizeStyles[size]}
|
|
8236
|
+
${className}
|
|
8237
|
+
`, "aria-label": `${variant} indicator` }));
|
|
8238
|
+
}
|
|
8239
|
+
// Regular badge
|
|
8240
|
+
return (jsxRuntime.jsxs("span", { className: `
|
|
8241
|
+
inline-flex items-center border font-medium
|
|
8242
|
+
${pill ? 'rounded-full' : 'rounded-full'}
|
|
8243
|
+
${variantStyles[variant]}
|
|
8244
|
+
${pill ? pillSizeStyles[size] : sizeStyles[size]}
|
|
8245
|
+
${className}
|
|
8246
|
+
`, children: [icon && jsxRuntime.jsx("span", { className: iconSize[size], children: icon }), jsxRuntime.jsx("span", { children: children }), onRemove && (jsxRuntime.jsx("button", { onClick: onRemove, className: "ml-1 hover:opacity-70 transition-opacity", "aria-label": "Remove badge", children: jsxRuntime.jsx(lucideReact.X, { className: iconSize[size] }) }))] }));
|
|
8247
|
+
}
|
|
8248
|
+
|
|
8249
|
+
const TabsContext = React.createContext(null);
|
|
8250
|
+
function useTabsContext() {
|
|
8251
|
+
const context = React.useContext(TabsContext);
|
|
8252
|
+
if (!context) {
|
|
8253
|
+
throw new Error('Tabs compound components must be used within a TabsRoot component');
|
|
8254
|
+
}
|
|
8255
|
+
return context;
|
|
8256
|
+
}
|
|
8257
|
+
/**
|
|
8258
|
+
* TabsRoot - Root component for compound tabs pattern
|
|
8259
|
+
*
|
|
8260
|
+
* @example
|
|
8261
|
+
* ```tsx
|
|
8262
|
+
* <TabsRoot defaultValue="tab1">
|
|
8263
|
+
* <TabsList>
|
|
8264
|
+
* <TabsTrigger value="tab1">Tab 1</TabsTrigger>
|
|
8265
|
+
* <TabsTrigger value="tab2">Tab 2</TabsTrigger>
|
|
8266
|
+
* </TabsList>
|
|
8267
|
+
* <TabsContent value="tab1">Content 1</TabsContent>
|
|
8268
|
+
* <TabsContent value="tab2">Content 2</TabsContent>
|
|
8269
|
+
* </TabsRoot>
|
|
8270
|
+
* ```
|
|
8271
|
+
*/
|
|
8272
|
+
function TabsRoot({ children, defaultValue, value: controlledValue, onValueChange, variant = 'underline', orientation = 'horizontal', size = 'md', lazy = false, preserveState = false, className = '', }) {
|
|
8273
|
+
const [tabValues, setTabValues] = React.useState([]);
|
|
8274
|
+
const [internalValue, setInternalValue] = React.useState(defaultValue || '');
|
|
8275
|
+
const [visitedTabs, setVisitedTabs] = React.useState(new Set(defaultValue ? [defaultValue] : []));
|
|
8276
|
+
const isControlled = controlledValue !== undefined;
|
|
8277
|
+
const activeTab = isControlled ? controlledValue : internalValue;
|
|
8278
|
+
// Set initial value when tabs register
|
|
8279
|
+
React.useEffect(() => {
|
|
8280
|
+
if (!activeTab && tabValues.length > 0) {
|
|
8281
|
+
const firstTab = tabValues[0];
|
|
8282
|
+
if (isControlled) {
|
|
8283
|
+
onValueChange?.(firstTab);
|
|
8284
|
+
}
|
|
8285
|
+
else {
|
|
8286
|
+
setInternalValue(firstTab);
|
|
8287
|
+
}
|
|
8288
|
+
}
|
|
8289
|
+
}, [tabValues, activeTab, isControlled, onValueChange]);
|
|
8290
|
+
// Track visited tabs
|
|
8291
|
+
React.useEffect(() => {
|
|
8292
|
+
if (activeTab && preserveState) {
|
|
8293
|
+
setVisitedTabs(prev => new Set(prev).add(activeTab));
|
|
8294
|
+
}
|
|
8295
|
+
}, [activeTab, preserveState]);
|
|
8296
|
+
const setActiveTab = React.useCallback((value) => {
|
|
8297
|
+
if (!isControlled) {
|
|
8298
|
+
setInternalValue(value);
|
|
8299
|
+
}
|
|
8300
|
+
onValueChange?.(value);
|
|
8301
|
+
}, [isControlled, onValueChange]);
|
|
8302
|
+
const registerTab = React.useCallback((value) => {
|
|
8303
|
+
setTabValues(prev => prev.includes(value) ? prev : [...prev, value]);
|
|
8304
|
+
}, []);
|
|
8305
|
+
const unregisterTab = React.useCallback((value) => {
|
|
8306
|
+
setTabValues(prev => prev.filter(v => v !== value));
|
|
8307
|
+
}, []);
|
|
8308
|
+
const contextValue = {
|
|
8309
|
+
activeTab,
|
|
8310
|
+
setActiveTab,
|
|
8311
|
+
variant,
|
|
8312
|
+
orientation,
|
|
8313
|
+
size,
|
|
8314
|
+
lazy,
|
|
8315
|
+
preserveState,
|
|
8316
|
+
visitedTabs,
|
|
8317
|
+
registerTab,
|
|
8318
|
+
unregisterTab,
|
|
8319
|
+
tabValues,
|
|
8320
|
+
};
|
|
8321
|
+
// Size-specific gap classes
|
|
8322
|
+
const gapClasses = {
|
|
8323
|
+
sm: orientation === 'vertical' ? 'gap-1.5' : 'gap-4',
|
|
8324
|
+
md: orientation === 'vertical' ? 'gap-2' : 'gap-6',
|
|
8325
|
+
lg: orientation === 'vertical' ? 'gap-3' : 'gap-8',
|
|
8326
|
+
};
|
|
8327
|
+
return (jsxRuntime.jsx(TabsContext.Provider, { value: contextValue, children: jsxRuntime.jsx("div", { className: `w-full ${orientation === 'vertical' ? `flex ${gapClasses[size]}` : ''} ${className}`, children: children }) }));
|
|
8328
|
+
}
|
|
8329
|
+
/**
|
|
8330
|
+
* TabsList - Container for tab triggers
|
|
8331
|
+
*/
|
|
8332
|
+
function TabsList({ children, className = '' }) {
|
|
8333
|
+
const { variant, orientation, size } = useTabsContext();
|
|
8334
|
+
const sizeClasses = {
|
|
8335
|
+
sm: {
|
|
8336
|
+
gap: orientation === 'vertical' ? 'gap-1.5' : 'gap-4',
|
|
8337
|
+
minWidth: orientation === 'vertical' ? 'min-w-[150px]' : '',
|
|
8338
|
+
},
|
|
8339
|
+
md: {
|
|
8340
|
+
gap: orientation === 'vertical' ? 'gap-2' : 'gap-6',
|
|
8341
|
+
minWidth: orientation === 'vertical' ? 'min-w-[200px]' : '',
|
|
8342
|
+
},
|
|
8343
|
+
lg: {
|
|
8344
|
+
gap: orientation === 'vertical' ? 'gap-3' : 'gap-8',
|
|
8345
|
+
minWidth: orientation === 'vertical' ? 'min-w-[250px]' : '',
|
|
8346
|
+
},
|
|
8347
|
+
};
|
|
8348
|
+
return (jsxRuntime.jsx("div", { className: `
|
|
8349
|
+
flex ${orientation === 'vertical' ? 'flex-col' : 'items-center'}
|
|
8350
|
+
${variant === 'underline'
|
|
8351
|
+
? orientation === 'vertical'
|
|
8352
|
+
? `border-r border-paper-200 ${sizeClasses[size].gap} pr-6`
|
|
8353
|
+
: `border-b border-paper-200 ${sizeClasses[size].gap}`
|
|
8354
|
+
: `${sizeClasses[size].gap} p-1 bg-paper-50 rounded-lg`}
|
|
8355
|
+
${sizeClasses[size].minWidth}
|
|
8356
|
+
${className}
|
|
8357
|
+
`, role: "tablist", "aria-orientation": orientation, children: children }));
|
|
8358
|
+
}
|
|
8359
|
+
/**
|
|
8360
|
+
* TabsTrigger - Individual tab button
|
|
8361
|
+
*/
|
|
8362
|
+
function TabsTrigger({ children, value, disabled = false, icon, badge, badgeVariant = 'info', className = '', }) {
|
|
8363
|
+
const { activeTab, setActiveTab, variant, orientation, size, registerTab, unregisterTab } = useTabsContext();
|
|
8364
|
+
const isActive = activeTab === value;
|
|
8365
|
+
// Register this tab on mount
|
|
8366
|
+
React.useEffect(() => {
|
|
8367
|
+
registerTab(value);
|
|
8368
|
+
return () => unregisterTab(value);
|
|
8369
|
+
}, [value, registerTab, unregisterTab]);
|
|
8370
|
+
const sizeClasses = {
|
|
8371
|
+
sm: { padding: 'px-3 py-1.5', text: 'text-xs', icon: 'h-3.5 w-3.5', badgeSize: 'sm' },
|
|
8372
|
+
md: { padding: 'px-4 py-2.5', text: 'text-sm', icon: 'h-4 w-4', badgeSize: 'sm' },
|
|
8373
|
+
lg: { padding: 'px-5 py-3', text: 'text-base', icon: 'h-5 w-5', badgeSize: 'md' },
|
|
8374
|
+
};
|
|
8375
|
+
return (jsxRuntime.jsxs("button", { role: "tab", "aria-selected": isActive, "aria-controls": `panel-${value}`, "aria-disabled": disabled, tabIndex: isActive ? 0 : -1, disabled: disabled, onClick: () => !disabled && setActiveTab(value), className: `
|
|
8376
|
+
flex items-center gap-2 ${sizeClasses[size].padding} ${sizeClasses[size].text} font-medium transition-all duration-200
|
|
8377
|
+
${orientation === 'vertical' ? 'w-full justify-start' : ''}
|
|
8378
|
+
${variant === 'underline'
|
|
8379
|
+
? isActive
|
|
8380
|
+
? orientation === 'vertical'
|
|
8381
|
+
? 'text-accent-900 border-r-2 border-accent-500 -mr-[1px]'
|
|
8382
|
+
: 'text-accent-900 border-b-2 border-accent-500 -mb-[1px]'
|
|
8383
|
+
: orientation === 'vertical'
|
|
8384
|
+
? 'text-ink-600 hover:text-ink-900 border-r-2 border-transparent'
|
|
8385
|
+
: 'text-ink-600 hover:text-ink-900 border-b-2 border-transparent'
|
|
8386
|
+
: isActive
|
|
8387
|
+
? 'bg-white text-accent-900 rounded-md shadow-xs'
|
|
8388
|
+
: 'text-ink-600 hover:text-ink-900 hover:bg-white/50 rounded-md'}
|
|
8389
|
+
${disabled ? 'opacity-40 cursor-not-allowed' : 'cursor-pointer'}
|
|
8390
|
+
focus:outline-none focus-visible:ring-2 focus-visible:ring-accent-500 focus-visible:ring-offset-1
|
|
8391
|
+
${className}
|
|
8392
|
+
`, children: [icon && jsxRuntime.jsx("span", { className: `flex-shrink-0 ${sizeClasses[size].icon}`, children: icon }), jsxRuntime.jsx("span", { children: children }), badge !== undefined && (jsxRuntime.jsx(Badge, { variant: badgeVariant, size: sizeClasses[size].badgeSize, children: badge }))] }));
|
|
8393
|
+
}
|
|
8394
|
+
/**
|
|
8395
|
+
* TabsContent - Content panel for a tab
|
|
8396
|
+
*/
|
|
8397
|
+
function TabsContent({ children, value, className = '' }) {
|
|
8398
|
+
const { activeTab, lazy, preserveState, visitedTabs, orientation, size } = useTabsContext();
|
|
8399
|
+
const isActive = activeTab === value;
|
|
8400
|
+
// Determine if content should be rendered
|
|
8401
|
+
const shouldRender = !lazy || isActive || (preserveState && visitedTabs.has(value));
|
|
8402
|
+
if (!shouldRender) {
|
|
8403
|
+
return null;
|
|
8404
|
+
}
|
|
8405
|
+
const spacingClasses = {
|
|
8406
|
+
sm: orientation === 'vertical' ? '' : 'mt-4',
|
|
8407
|
+
md: orientation === 'vertical' ? '' : 'mt-6',
|
|
8408
|
+
lg: orientation === 'vertical' ? '' : 'mt-8',
|
|
8409
|
+
};
|
|
8410
|
+
return (jsxRuntime.jsx("div", { id: `panel-${value}`, role: "tabpanel", "aria-labelledby": `tab-${value}`, hidden: !isActive, tabIndex: 0, className: `
|
|
8411
|
+
${orientation === 'vertical' ? 'flex-1' : spacingClasses[size]}
|
|
8412
|
+
${isActive ? 'animate-fade-in focus:outline-none' : 'hidden'}
|
|
8413
|
+
${className}
|
|
8414
|
+
`, children: children }));
|
|
8415
|
+
}
|
|
8416
|
+
// =============================================================================
|
|
8417
|
+
// Data-Driven Component (Original API)
|
|
8418
|
+
// =============================================================================
|
|
8419
|
+
/**
|
|
8420
|
+
* Tabs - Data-driven tabs component
|
|
8421
|
+
*
|
|
8422
|
+
* Use this for simple use cases where tabs are defined as an array.
|
|
8423
|
+
* For more complex layouts, use the compound components (TabsRoot, TabsList, TabsTrigger, TabsContent).
|
|
8424
|
+
*/
|
|
8425
|
+
function Tabs({ tabs, activeTab: controlledActiveTab, defaultTab, variant = 'underline', orientation = 'horizontal', size = 'md', onChange, lazy = false, preserveState = false, closeable = false, onClose, showAddButton = false, onAdd, addButtonLabel = 'Add tab', }) {
|
|
8195
8426
|
const [internalActiveTab, setInternalActiveTab] = React.useState(defaultTab || tabs[0]?.id);
|
|
8427
|
+
const [focusedIndex, setFocusedIndex] = React.useState(-1);
|
|
8428
|
+
const [visitedTabs, setVisitedTabs] = React.useState(new Set([defaultTab || tabs[0]?.id]));
|
|
8429
|
+
const tabListRef = React.useRef(null);
|
|
8430
|
+
const tabRefs = React.useRef([]);
|
|
8196
8431
|
// Controlled mode: use activeTab prop, Uncontrolled mode: use internal state
|
|
8197
8432
|
const isControlled = controlledActiveTab !== undefined;
|
|
8198
8433
|
const activeTab = isControlled ? controlledActiveTab : internalActiveTab;
|
|
8434
|
+
// Track visited tabs for preserveState
|
|
8435
|
+
React.useEffect(() => {
|
|
8436
|
+
if (activeTab && preserveState) {
|
|
8437
|
+
setVisitedTabs(prev => new Set(prev).add(activeTab));
|
|
8438
|
+
}
|
|
8439
|
+
}, [activeTab, preserveState]);
|
|
8440
|
+
// Get enabled tab indices for keyboard navigation
|
|
8441
|
+
const enabledIndices = tabs.map((tab, index) => tab.disabled ? -1 : index).filter(i => i !== -1);
|
|
8199
8442
|
// Ensure the activeTab exists in the current tabs array
|
|
8200
8443
|
// This handles the case where tabs array reference changes at the same time as activeTab
|
|
8201
8444
|
React.useEffect(() => {
|
|
@@ -8210,66 +8453,196 @@ function Tabs({ tabs, activeTab: controlledActiveTab, defaultTab, variant = 'und
|
|
|
8210
8453
|
}
|
|
8211
8454
|
}
|
|
8212
8455
|
}, [tabs, activeTab, isControlled, onChange]);
|
|
8213
|
-
const handleTabChange = (tabId) => {
|
|
8456
|
+
const handleTabChange = React.useCallback((tabId) => {
|
|
8214
8457
|
if (!isControlled) {
|
|
8215
8458
|
setInternalActiveTab(tabId);
|
|
8216
8459
|
}
|
|
8217
8460
|
onChange?.(tabId);
|
|
8218
|
-
};
|
|
8461
|
+
}, [isControlled, onChange]);
|
|
8462
|
+
// Handle tab close
|
|
8463
|
+
const handleClose = React.useCallback((e, tabId) => {
|
|
8464
|
+
e.stopPropagation();
|
|
8465
|
+
onClose?.(tabId);
|
|
8466
|
+
}, [onClose]);
|
|
8467
|
+
// Keyboard navigation handler
|
|
8468
|
+
const handleKeyDown = React.useCallback((e) => {
|
|
8469
|
+
const currentIndex = focusedIndex >= 0 ? focusedIndex : tabs.findIndex(t => t.id === activeTab);
|
|
8470
|
+
const currentEnabledPosition = enabledIndices.indexOf(currentIndex);
|
|
8471
|
+
let nextIndex = -1;
|
|
8472
|
+
let shouldPreventDefault = true;
|
|
8473
|
+
// Determine navigation keys based on orientation
|
|
8474
|
+
const prevKey = orientation === 'vertical' ? 'ArrowUp' : 'ArrowLeft';
|
|
8475
|
+
const nextKey = orientation === 'vertical' ? 'ArrowDown' : 'ArrowRight';
|
|
8476
|
+
switch (e.key) {
|
|
8477
|
+
case prevKey:
|
|
8478
|
+
// Move to previous enabled tab
|
|
8479
|
+
if (currentEnabledPosition > 0) {
|
|
8480
|
+
nextIndex = enabledIndices[currentEnabledPosition - 1];
|
|
8481
|
+
}
|
|
8482
|
+
else {
|
|
8483
|
+
// Wrap to last enabled tab
|
|
8484
|
+
nextIndex = enabledIndices[enabledIndices.length - 1];
|
|
8485
|
+
}
|
|
8486
|
+
break;
|
|
8487
|
+
case nextKey:
|
|
8488
|
+
// Move to next enabled tab
|
|
8489
|
+
if (currentEnabledPosition < enabledIndices.length - 1) {
|
|
8490
|
+
nextIndex = enabledIndices[currentEnabledPosition + 1];
|
|
8491
|
+
}
|
|
8492
|
+
else {
|
|
8493
|
+
// Wrap to first enabled tab
|
|
8494
|
+
nextIndex = enabledIndices[0];
|
|
8495
|
+
}
|
|
8496
|
+
break;
|
|
8497
|
+
case 'Home':
|
|
8498
|
+
// Move to first enabled tab
|
|
8499
|
+
nextIndex = enabledIndices[0];
|
|
8500
|
+
break;
|
|
8501
|
+
case 'End':
|
|
8502
|
+
// Move to last enabled tab
|
|
8503
|
+
nextIndex = enabledIndices[enabledIndices.length - 1];
|
|
8504
|
+
break;
|
|
8505
|
+
case 'Enter':
|
|
8506
|
+
case ' ':
|
|
8507
|
+
// Activate focused tab
|
|
8508
|
+
if (focusedIndex >= 0 && !tabs[focusedIndex]?.disabled) {
|
|
8509
|
+
handleTabChange(tabs[focusedIndex].id);
|
|
8510
|
+
}
|
|
8511
|
+
break;
|
|
8512
|
+
case 'Delete':
|
|
8513
|
+
case 'Backspace':
|
|
8514
|
+
// Close focused tab if closeable
|
|
8515
|
+
if (focusedIndex >= 0) {
|
|
8516
|
+
const tab = tabs[focusedIndex];
|
|
8517
|
+
const isTabCloseable = tab.closeable !== undefined ? tab.closeable : closeable;
|
|
8518
|
+
if (isTabCloseable && !tab.disabled && onClose) {
|
|
8519
|
+
onClose(tab.id);
|
|
8520
|
+
}
|
|
8521
|
+
}
|
|
8522
|
+
break;
|
|
8523
|
+
default:
|
|
8524
|
+
shouldPreventDefault = false;
|
|
8525
|
+
}
|
|
8526
|
+
if (shouldPreventDefault) {
|
|
8527
|
+
e.preventDefault();
|
|
8528
|
+
}
|
|
8529
|
+
if (nextIndex >= 0 && nextIndex !== currentIndex) {
|
|
8530
|
+
setFocusedIndex(nextIndex);
|
|
8531
|
+
tabRefs.current[nextIndex]?.focus();
|
|
8532
|
+
}
|
|
8533
|
+
}, [focusedIndex, tabs, activeTab, enabledIndices, orientation, handleTabChange, closeable, onClose]);
|
|
8534
|
+
// Handle focus events
|
|
8535
|
+
const handleFocus = React.useCallback((index) => {
|
|
8536
|
+
setFocusedIndex(index);
|
|
8537
|
+
}, []);
|
|
8538
|
+
const handleBlur = React.useCallback(() => {
|
|
8539
|
+
setFocusedIndex(-1);
|
|
8540
|
+
}, []);
|
|
8219
8541
|
// Size-specific classes
|
|
8220
8542
|
const sizeClasses = {
|
|
8221
8543
|
sm: {
|
|
8222
8544
|
padding: 'px-3 py-1.5',
|
|
8223
8545
|
text: 'text-xs',
|
|
8224
8546
|
icon: 'h-3.5 w-3.5',
|
|
8547
|
+
closeIcon: 'h-3 w-3',
|
|
8225
8548
|
gap: orientation === 'vertical' ? 'gap-1.5' : 'gap-4',
|
|
8226
8549
|
minWidth: orientation === 'vertical' ? 'min-w-[150px]' : '',
|
|
8227
8550
|
spacing: orientation === 'vertical' ? 'mt-4' : 'mt-4',
|
|
8551
|
+
badgeSize: 'sm',
|
|
8552
|
+
addPadding: 'px-2 py-1.5',
|
|
8228
8553
|
},
|
|
8229
8554
|
md: {
|
|
8230
8555
|
padding: 'px-4 py-2.5',
|
|
8231
8556
|
text: 'text-sm',
|
|
8232
8557
|
icon: 'h-4 w-4',
|
|
8558
|
+
closeIcon: 'h-3.5 w-3.5',
|
|
8233
8559
|
gap: orientation === 'vertical' ? 'gap-2' : 'gap-6',
|
|
8234
8560
|
minWidth: orientation === 'vertical' ? 'min-w-[200px]' : '',
|
|
8235
8561
|
spacing: orientation === 'vertical' ? 'mt-6' : 'mt-6',
|
|
8562
|
+
badgeSize: 'sm',
|
|
8563
|
+
addPadding: 'px-3 py-2.5',
|
|
8236
8564
|
},
|
|
8237
8565
|
lg: {
|
|
8238
8566
|
padding: 'px-5 py-3',
|
|
8239
8567
|
text: 'text-base',
|
|
8240
8568
|
icon: 'h-5 w-5',
|
|
8569
|
+
closeIcon: 'h-4 w-4',
|
|
8241
8570
|
gap: orientation === 'vertical' ? 'gap-3' : 'gap-8',
|
|
8242
8571
|
minWidth: orientation === 'vertical' ? 'min-w-[250px]' : '',
|
|
8243
8572
|
spacing: orientation === 'vertical' ? 'mt-8' : 'mt-8',
|
|
8573
|
+
badgeSize: 'md',
|
|
8574
|
+
addPadding: 'px-4 py-3',
|
|
8244
8575
|
},
|
|
8245
8576
|
};
|
|
8246
|
-
|
|
8247
|
-
|
|
8577
|
+
// Determine which tabs should be rendered
|
|
8578
|
+
const shouldRenderContent = React.useCallback((tabId) => {
|
|
8579
|
+
if (!lazy) {
|
|
8580
|
+
// Not lazy: render all tabs
|
|
8581
|
+
return true;
|
|
8582
|
+
}
|
|
8583
|
+
if (tabId === activeTab) {
|
|
8584
|
+
// Always render active tab
|
|
8585
|
+
return true;
|
|
8586
|
+
}
|
|
8587
|
+
if (preserveState && visitedTabs.has(tabId)) {
|
|
8588
|
+
// Preserve state: render previously visited tabs
|
|
8589
|
+
return true;
|
|
8590
|
+
}
|
|
8591
|
+
return false;
|
|
8592
|
+
}, [lazy, activeTab, preserveState, visitedTabs]);
|
|
8593
|
+
return (jsxRuntime.jsxs("div", { className: `w-full ${orientation === 'vertical' ? `flex ${sizeClasses[size].gap}` : ''}`, children: [jsxRuntime.jsxs("div", { ref: tabListRef, className: `
|
|
8594
|
+
flex ${orientation === 'vertical' ? 'flex-col' : 'items-center'}
|
|
8248
8595
|
${variant === 'underline'
|
|
8249
8596
|
? orientation === 'vertical'
|
|
8250
8597
|
? `border-r border-paper-200 ${sizeClasses[size].gap} pr-6`
|
|
8251
8598
|
: `border-b border-paper-200 ${sizeClasses[size].gap}`
|
|
8252
8599
|
: `${sizeClasses[size].gap} p-1 bg-paper-50 rounded-lg`}
|
|
8253
8600
|
${sizeClasses[size].minWidth}
|
|
8254
|
-
`, role: "tablist", children: tabs.map((tab) => {
|
|
8255
|
-
|
|
8256
|
-
|
|
8601
|
+
`, role: "tablist", "aria-orientation": orientation, onKeyDown: handleKeyDown, children: [tabs.map((tab, index) => {
|
|
8602
|
+
const isActive = activeTab === tab.id;
|
|
8603
|
+
const isTabCloseable = tab.closeable !== undefined ? tab.closeable : closeable;
|
|
8604
|
+
return (jsxRuntime.jsxs("button", { ref: (el) => { tabRefs.current[index] = el; }, id: `tab-${tab.id}`, role: "tab", "aria-selected": isActive, "aria-controls": `panel-${tab.id}`, "aria-disabled": tab.disabled, tabIndex: isActive ? 0 : -1, disabled: tab.disabled, onClick: () => !tab.disabled && handleTabChange(tab.id), onFocus: () => handleFocus(index), onBlur: handleBlur, className: `
|
|
8257
8605
|
flex items-center gap-2 ${sizeClasses[size].padding} ${sizeClasses[size].text} font-medium transition-all duration-200
|
|
8258
8606
|
${orientation === 'vertical' ? 'w-full justify-start' : ''}
|
|
8259
8607
|
${variant === 'underline'
|
|
8260
|
-
|
|
8261
|
-
|
|
8262
|
-
|
|
8263
|
-
|
|
8264
|
-
|
|
8265
|
-
|
|
8266
|
-
|
|
8267
|
-
|
|
8268
|
-
|
|
8269
|
-
|
|
8608
|
+
? isActive
|
|
8609
|
+
? orientation === 'vertical'
|
|
8610
|
+
? 'text-accent-900 border-r-2 border-accent-500 -mr-[1px]'
|
|
8611
|
+
: 'text-accent-900 border-b-2 border-accent-500 -mb-[1px]'
|
|
8612
|
+
: orientation === 'vertical'
|
|
8613
|
+
? 'text-ink-600 hover:text-ink-900 border-r-2 border-transparent'
|
|
8614
|
+
: 'text-ink-600 hover:text-ink-900 border-b-2 border-transparent'
|
|
8615
|
+
: isActive
|
|
8616
|
+
? 'bg-white text-accent-900 rounded-md shadow-xs'
|
|
8617
|
+
: 'text-ink-600 hover:text-ink-900 hover:bg-white/50 rounded-md'}
|
|
8270
8618
|
${tab.disabled ? 'opacity-40 cursor-not-allowed' : 'cursor-pointer'}
|
|
8271
|
-
|
|
8272
|
-
|
|
8619
|
+
focus:outline-none focus-visible:ring-2 focus-visible:ring-accent-500 focus-visible:ring-offset-1
|
|
8620
|
+
group
|
|
8621
|
+
`, children: [tab.icon && jsxRuntime.jsx("span", { className: `flex-shrink-0 ${sizeClasses[size].icon}`, children: tab.icon }), jsxRuntime.jsx("span", { className: isTabCloseable ? 'mr-1' : '', children: tab.label }), tab.badge !== undefined && (jsxRuntime.jsx(Badge, { variant: tab.badgeVariant || 'info', size: sizeClasses[size].badgeSize, children: tab.badge })), isTabCloseable && onClose && (jsxRuntime.jsx("span", { role: "button", "aria-label": `Close ${tab.label}`, onClick: (e) => handleClose(e, tab.id), className: `
|
|
8622
|
+
flex-shrink-0 p-0.5 rounded
|
|
8623
|
+
text-ink-400 hover:text-ink-700 hover:bg-paper-200
|
|
8624
|
+
opacity-0 group-hover:opacity-100 group-focus-visible:opacity-100
|
|
8625
|
+
${isActive ? 'opacity-100' : ''}
|
|
8626
|
+
transition-opacity duration-150
|
|
8627
|
+
`, children: jsxRuntime.jsx(lucideReact.X, { className: sizeClasses[size].closeIcon }) }))] }, tab.id));
|
|
8628
|
+
}), showAddButton && onAdd && (jsxRuntime.jsx("button", { type: "button", onClick: onAdd, "aria-label": addButtonLabel, title: addButtonLabel, className: `
|
|
8629
|
+
flex items-center justify-center ${sizeClasses[size].addPadding}
|
|
8630
|
+
text-ink-500 hover:text-ink-700 hover:bg-paper-100
|
|
8631
|
+
rounded transition-colors duration-150
|
|
8632
|
+
focus:outline-none focus-visible:ring-2 focus-visible:ring-accent-500 focus-visible:ring-offset-1
|
|
8633
|
+
${variant === 'underline'
|
|
8634
|
+
? orientation === 'vertical'
|
|
8635
|
+
? 'border-r-2 border-transparent'
|
|
8636
|
+
: 'border-b-2 border-transparent -mb-[1px]'
|
|
8637
|
+
: ''}
|
|
8638
|
+
`, children: jsxRuntime.jsx(lucideReact.Plus, { className: sizeClasses[size].icon }) }))] }), jsxRuntime.jsx("div", { className: `${orientation === 'vertical' ? 'flex-1' : sizeClasses[size].spacing}`, children: tabs.map((tab) => {
|
|
8639
|
+
const isActive = activeTab === tab.id;
|
|
8640
|
+
const shouldRender = shouldRenderContent(tab.id);
|
|
8641
|
+
if (!shouldRender) {
|
|
8642
|
+
return null;
|
|
8643
|
+
}
|
|
8644
|
+
return (jsxRuntime.jsx("div", { id: `panel-${tab.id}`, role: "tabpanel", "aria-labelledby": `tab-${tab.id}`, hidden: !isActive, tabIndex: 0, className: isActive ? 'animate-fade-in focus:outline-none' : 'hidden', children: tab.content }, tab.id));
|
|
8645
|
+
}) })] }));
|
|
8273
8646
|
}
|
|
8274
8647
|
|
|
8275
8648
|
function Pagination({ currentPage, totalPages, onPageChange, showPageNumbers = true, maxPageNumbers = 5, showPageJump = false, }) {
|
|
@@ -8343,61 +8716,6 @@ function StepIndicator({ steps, currentStep, variant = 'horizontal', onStepClick
|
|
|
8343
8716
|
}) }) }));
|
|
8344
8717
|
}
|
|
8345
8718
|
|
|
8346
|
-
function Badge({ children, variant = 'neutral', size = 'md', icon, onRemove, className = '', dot = false, pill = false, }) {
|
|
8347
|
-
const variantStyles = {
|
|
8348
|
-
success: 'bg-success-50 text-success-700 border-success-200',
|
|
8349
|
-
warning: 'bg-warning-50 text-warning-700 border-warning-200',
|
|
8350
|
-
error: 'bg-error-50 text-error-700 border-error-200',
|
|
8351
|
-
info: 'bg-primary-50 text-primary-700 border-primary-200',
|
|
8352
|
-
neutral: 'bg-paper-100 text-ink-700 border-paper-300',
|
|
8353
|
-
};
|
|
8354
|
-
const dotVariantStyles = {
|
|
8355
|
-
success: 'bg-success-500',
|
|
8356
|
-
warning: 'bg-warning-500',
|
|
8357
|
-
error: 'bg-error-500',
|
|
8358
|
-
info: 'bg-primary-500',
|
|
8359
|
-
neutral: 'bg-ink-400',
|
|
8360
|
-
};
|
|
8361
|
-
const sizeStyles = {
|
|
8362
|
-
sm: 'px-2 py-0.5 text-xs gap-1',
|
|
8363
|
-
md: 'px-3 py-1 text-xs gap-1.5',
|
|
8364
|
-
lg: 'px-3 py-1.5 text-sm gap-2',
|
|
8365
|
-
};
|
|
8366
|
-
// Pill variant has tighter horizontal padding and fully rounded ends
|
|
8367
|
-
const pillSizeStyles = {
|
|
8368
|
-
sm: 'px-1.5 py-0.5 text-xs gap-1',
|
|
8369
|
-
md: 'px-2 py-0.5 text-xs gap-1',
|
|
8370
|
-
lg: 'px-2.5 py-1 text-sm gap-1.5',
|
|
8371
|
-
};
|
|
8372
|
-
const dotSizeStyles = {
|
|
8373
|
-
sm: 'h-1.5 w-1.5',
|
|
8374
|
-
md: 'h-2 w-2',
|
|
8375
|
-
lg: 'h-2.5 w-2.5',
|
|
8376
|
-
};
|
|
8377
|
-
const iconSize = {
|
|
8378
|
-
sm: 'h-3 w-3',
|
|
8379
|
-
md: 'h-3.5 w-3.5',
|
|
8380
|
-
lg: 'h-4 w-4',
|
|
8381
|
-
};
|
|
8382
|
-
// Dot variant - just a colored circle
|
|
8383
|
-
if (dot) {
|
|
8384
|
-
return (jsxRuntime.jsx("span", { className: `
|
|
8385
|
-
inline-block rounded-full
|
|
8386
|
-
${dotVariantStyles[variant]}
|
|
8387
|
-
${dotSizeStyles[size]}
|
|
8388
|
-
${className}
|
|
8389
|
-
`, "aria-label": `${variant} indicator` }));
|
|
8390
|
-
}
|
|
8391
|
-
// Regular badge
|
|
8392
|
-
return (jsxRuntime.jsxs("span", { className: `
|
|
8393
|
-
inline-flex items-center border font-medium
|
|
8394
|
-
${pill ? 'rounded-full' : 'rounded-full'}
|
|
8395
|
-
${variantStyles[variant]}
|
|
8396
|
-
${pill ? pillSizeStyles[size] : sizeStyles[size]}
|
|
8397
|
-
${className}
|
|
8398
|
-
`, children: [icon && jsxRuntime.jsx("span", { className: iconSize[size], children: icon }), jsxRuntime.jsx("span", { children: children }), onRemove && (jsxRuntime.jsx("button", { onClick: onRemove, className: "ml-1 hover:opacity-70 transition-opacity", "aria-label": "Remove badge", children: jsxRuntime.jsx(lucideReact.X, { className: iconSize[size] }) }))] }));
|
|
8399
|
-
}
|
|
8400
|
-
|
|
8401
8719
|
/**
|
|
8402
8720
|
* Avatar component that displays:
|
|
8403
8721
|
* - User initials in a colored circle (default)
|
|
@@ -10172,7 +10490,7 @@ function getPopoverPlacement(position) {
|
|
|
10172
10490
|
* />
|
|
10173
10491
|
* ```
|
|
10174
10492
|
*/
|
|
10175
|
-
function NotificationBell({ notifications, unreadCount: providedUnreadCount, onMarkAsRead, onMarkAllRead, onNotificationClick, onViewAll, loading = false, dropdownPosition = 'bottom-right', maxHeight = '400px', size = 'md', emptyMessage = 'No notifications', viewAllText = 'View all notifications', disabled = false, className = '', variant = 'compact', showUnreadInHeader = false, bellStyle = 'ghost', }) {
|
|
10493
|
+
function NotificationBell({ notifications, unreadCount: providedUnreadCount, onMarkAsRead, onMarkAllRead, onNotificationClick, onViewAll, loading = false, dropdownPosition = 'bottom-right', maxHeight = '400px', size = 'md', emptyMessage = 'No notifications', viewAllText = 'View all notifications', disabled = false, className = '', variant = 'compact', showUnreadInHeader = false, bellStyle = 'ghost', icon: customIcon, }) {
|
|
10176
10494
|
const [isOpen, setIsOpen] = React.useState(false);
|
|
10177
10495
|
// Calculate unread count if not provided
|
|
10178
10496
|
const unreadCount = React.useMemo(() => {
|
|
@@ -10217,6 +10535,8 @@ function NotificationBell({ notifications, unreadCount: providedUnreadCount, onM
|
|
|
10217
10535
|
md: 'p-3',
|
|
10218
10536
|
lg: 'p-4',
|
|
10219
10537
|
};
|
|
10538
|
+
// Default bell icon or custom icon
|
|
10539
|
+
const bellIcon = customIcon || jsxRuntime.jsx(lucideReact.Bell, { className: `${iconSizes[size]} text-ink-600` });
|
|
10220
10540
|
// Trigger button
|
|
10221
10541
|
const triggerButton = bellStyle === 'outlined' ? (jsxRuntime.jsxs("div", { className: "relative inline-block", children: [jsxRuntime.jsx("button", { className: `
|
|
10222
10542
|
${outlinedSizeClasses[size]}
|
|
@@ -10228,16 +10548,16 @@ function NotificationBell({ notifications, unreadCount: providedUnreadCount, onM
|
|
|
10228
10548
|
${className}
|
|
10229
10549
|
`, disabled: disabled, "aria-label": unreadCount > 0
|
|
10230
10550
|
? `Notifications - ${unreadCount} unread`
|
|
10231
|
-
: 'Notifications', children:
|
|
10551
|
+
: 'Notifications', children: bellIcon }), unreadCount > 0 && (jsxRuntime.jsx("span", { className: `
|
|
10232
10552
|
absolute -top-1 -right-1
|
|
10233
10553
|
flex items-center justify-center
|
|
10234
10554
|
min-w-[18px] h-[18px] px-1.5
|
|
10235
10555
|
rounded-full text-white font-semibold text-[11px]
|
|
10236
10556
|
bg-error-500 shadow-sm
|
|
10237
10557
|
pointer-events-none
|
|
10238
|
-
`, "aria-label": `${unreadCount > 99 ? '99+' : unreadCount} notifications`, children: unreadCount > 99 ? '99+' : unreadCount }))] })) : (jsxRuntime.jsx(Button, { variant: "ghost", iconOnly: true, size: size, disabled: disabled, badge: unreadCount > 0 ? unreadCount : undefined, badgeVariant: "error", "aria-label": unreadCount > 0
|
|
10558
|
+
`, "aria-label": `${unreadCount > 99 ? '99+' : unreadCount} notifications`, children: unreadCount > 99 ? '99+' : unreadCount }))] })) : (jsxRuntime.jsx(Button, { variant: "ghost", iconOnly: true, size: size, disabled: disabled, icon: bellIcon, badge: unreadCount > 0 ? unreadCount : undefined, badgeVariant: "error", "aria-label": unreadCount > 0
|
|
10239
10559
|
? `Notifications - ${unreadCount} unread`
|
|
10240
|
-
: 'Notifications', className: className
|
|
10560
|
+
: 'Notifications', className: className }));
|
|
10241
10561
|
// Header title with optional unread count
|
|
10242
10562
|
const headerTitle = showUnreadInHeader && unreadCount > 0
|
|
10243
10563
|
? `Notifications (${unreadCount} unread)`
|
|
@@ -11293,52 +11613,44 @@ function getAugmentedNamespace(n) {
|
|
|
11293
11613
|
* (A1, A1:C5, ...)
|
|
11294
11614
|
*/
|
|
11295
11615
|
|
|
11296
|
-
|
|
11297
|
-
var hasRequiredCollection;
|
|
11298
|
-
|
|
11299
|
-
function requireCollection () {
|
|
11300
|
-
if (hasRequiredCollection) return collection;
|
|
11301
|
-
hasRequiredCollection = 1;
|
|
11302
|
-
class Collection {
|
|
11616
|
+
let Collection$3 = class Collection {
|
|
11303
11617
|
|
|
11304
|
-
|
|
11305
|
-
|
|
11306
|
-
|
|
11307
|
-
|
|
11308
|
-
|
|
11309
|
-
|
|
11310
|
-
|
|
11311
|
-
|
|
11312
|
-
|
|
11313
|
-
|
|
11314
|
-
|
|
11618
|
+
constructor(data, refs) {
|
|
11619
|
+
if (data == null && refs == null) {
|
|
11620
|
+
this._data = [];
|
|
11621
|
+
this._refs = [];
|
|
11622
|
+
} else {
|
|
11623
|
+
if (data.length !== refs.length)
|
|
11624
|
+
throw Error('Collection: data length should match references length.');
|
|
11625
|
+
this._data = data;
|
|
11626
|
+
this._refs = refs;
|
|
11627
|
+
}
|
|
11628
|
+
}
|
|
11315
11629
|
|
|
11316
|
-
|
|
11317
|
-
|
|
11318
|
-
|
|
11630
|
+
get data() {
|
|
11631
|
+
return this._data;
|
|
11632
|
+
}
|
|
11319
11633
|
|
|
11320
|
-
|
|
11321
|
-
|
|
11322
|
-
|
|
11634
|
+
get refs() {
|
|
11635
|
+
return this._refs;
|
|
11636
|
+
}
|
|
11323
11637
|
|
|
11324
|
-
|
|
11325
|
-
|
|
11326
|
-
|
|
11638
|
+
get length() {
|
|
11639
|
+
return this._data.length;
|
|
11640
|
+
}
|
|
11327
11641
|
|
|
11328
|
-
|
|
11329
|
-
|
|
11330
|
-
|
|
11331
|
-
|
|
11332
|
-
|
|
11333
|
-
|
|
11334
|
-
|
|
11335
|
-
|
|
11336
|
-
|
|
11337
|
-
|
|
11642
|
+
/**
|
|
11643
|
+
* Add data and references to this collection.
|
|
11644
|
+
* @param {{}} obj - data
|
|
11645
|
+
* @param {{}} ref - reference
|
|
11646
|
+
*/
|
|
11647
|
+
add(obj, ref) {
|
|
11648
|
+
this._data.push(obj);
|
|
11649
|
+
this._refs.push(ref);
|
|
11650
|
+
}
|
|
11651
|
+
};
|
|
11338
11652
|
|
|
11339
|
-
|
|
11340
|
-
return collection;
|
|
11341
|
-
}
|
|
11653
|
+
var collection = Collection$3;
|
|
11342
11654
|
|
|
11343
11655
|
var helpers;
|
|
11344
11656
|
var hasRequiredHelpers;
|
|
@@ -11347,7 +11659,7 @@ function requireHelpers () {
|
|
|
11347
11659
|
if (hasRequiredHelpers) return helpers;
|
|
11348
11660
|
hasRequiredHelpers = 1;
|
|
11349
11661
|
const FormulaError = requireError();
|
|
11350
|
-
const Collection =
|
|
11662
|
+
const Collection = collection;
|
|
11351
11663
|
|
|
11352
11664
|
const Types = {
|
|
11353
11665
|
NUMBER: 0,
|
|
@@ -21001,7 +21313,7 @@ var engineering = EngineeringFunctions;
|
|
|
21001
21313
|
|
|
21002
21314
|
const FormulaError$b = requireError();
|
|
21003
21315
|
const {FormulaHelpers: FormulaHelpers$8, Types: Types$6, WildCard, Address: Address$3} = requireHelpers();
|
|
21004
|
-
const Collection$2 =
|
|
21316
|
+
const Collection$2 = collection;
|
|
21005
21317
|
const H$5 = FormulaHelpers$8;
|
|
21006
21318
|
|
|
21007
21319
|
const ReferenceFunctions$1 = {
|
|
@@ -32629,7 +32941,7 @@ var parsing = {
|
|
|
32629
32941
|
const FormulaError$4 = requireError();
|
|
32630
32942
|
const {Address: Address$1} = requireHelpers();
|
|
32631
32943
|
const {Prefix: Prefix$1, Postfix: Postfix$1, Infix: Infix$1, Operators: Operators$1} = operators;
|
|
32632
|
-
const Collection$1 =
|
|
32944
|
+
const Collection$1 = collection;
|
|
32633
32945
|
const MAX_ROW$1 = 1048576, MAX_COLUMN$1 = 16384;
|
|
32634
32946
|
const {NotAllInputParsedException} = require$$4;
|
|
32635
32947
|
|
|
@@ -33391,7 +33703,7 @@ var hooks$1 = {
|
|
|
33391
33703
|
const FormulaError$2 = requireError();
|
|
33392
33704
|
const {FormulaHelpers: FormulaHelpers$1, Types, Address} = requireHelpers();
|
|
33393
33705
|
const {Prefix, Postfix, Infix, Operators} = operators;
|
|
33394
|
-
const Collection =
|
|
33706
|
+
const Collection = collection;
|
|
33395
33707
|
const MAX_ROW = 1048576, MAX_COLUMN = 16384;
|
|
33396
33708
|
|
|
33397
33709
|
let Utils$1 = class Utils {
|
|
@@ -58051,6 +58363,10 @@ exports.SwipeActions = SwipeActions;
|
|
|
58051
58363
|
exports.SwipeableCard = SwipeableCard;
|
|
58052
58364
|
exports.Switch = Switch;
|
|
58053
58365
|
exports.Tabs = Tabs;
|
|
58366
|
+
exports.TabsContent = TabsContent;
|
|
58367
|
+
exports.TabsList = TabsList;
|
|
58368
|
+
exports.TabsRoot = TabsRoot;
|
|
58369
|
+
exports.TabsTrigger = TabsTrigger;
|
|
58054
58370
|
exports.Text = Text;
|
|
58055
58371
|
exports.Textarea = Textarea;
|
|
58056
58372
|
exports.ThemeToggle = ThemeToggle;
|