@papernote/ui 1.9.3 → 1.10.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/DataTable.d.ts +3 -1
- package/dist/components/DataTable.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 +117 -4
- package/dist/index.esm.js +398 -77
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +400 -75
- package/dist/index.js.map +1 -1
- package/dist/styles.css +23 -0
- package/package.json +1 -1
- package/src/components/DataTable.tsx +7 -1
- 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.esm.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
2
2
|
import * as React from 'react';
|
|
3
|
-
import React__default, { forwardRef, useState, useEffect, useCallback, useRef, useId, useImperativeHandle, useMemo, Children, isValidElement, cloneElement, Component, createContext as createContext$1, useLayoutEffect, createElement,
|
|
3
|
+
import React__default, { forwardRef, useState, useEffect, useCallback, useRef, useId, useImperativeHandle, useMemo, Children, isValidElement, cloneElement, Component, createContext as createContext$1, useContext, useLayoutEffect, createElement, useReducer } from 'react';
|
|
4
4
|
import { Loader2, X, EyeOff, Eye, AlertTriangle, CheckCircle, AlertCircle, ChevronDown, Search, Check, Minus, Star, Calendar as Calendar$1, ChevronLeft, ChevronRight, Clock, ChevronUp, Plus, TrendingUp, TrendingDown, Info, Trash2, ChevronsLeft, ChevronsRight, Circle, MoreVertical, GripVertical, Upload, Bold, Italic, Underline, List, ListOrdered, Code, Link, MoreHorizontal, Home, FileText, Image, File as File$1, Menu as Menu$1, ArrowDown, User, Settings, LogOut, Moon, Sun, Bell, ExternalLink, Edit, Trash, Pin, PinOff, Download, Save, ArrowUpDown, Filter, XCircle, BarChart3, MessageSquare } from 'lucide-react';
|
|
5
5
|
import { createPortal } from 'react-dom';
|
|
6
6
|
import { useInRouterContext, useNavigate, useLocation, Link as Link$1 } from 'react-router-dom';
|
|
@@ -8171,11 +8171,254 @@ function Breadcrumbs({ items, showHome = true }) {
|
|
|
8171
8171
|
})] }));
|
|
8172
8172
|
}
|
|
8173
8173
|
|
|
8174
|
-
function
|
|
8174
|
+
function Badge({ children, variant = 'neutral', size = 'md', icon, onRemove, className = '', dot = false, pill = false, }) {
|
|
8175
|
+
const variantStyles = {
|
|
8176
|
+
success: 'bg-success-50 text-success-700 border-success-200',
|
|
8177
|
+
warning: 'bg-warning-50 text-warning-700 border-warning-200',
|
|
8178
|
+
error: 'bg-error-50 text-error-700 border-error-200',
|
|
8179
|
+
info: 'bg-primary-50 text-primary-700 border-primary-200',
|
|
8180
|
+
neutral: 'bg-paper-100 text-ink-700 border-paper-300',
|
|
8181
|
+
};
|
|
8182
|
+
const dotVariantStyles = {
|
|
8183
|
+
success: 'bg-success-500',
|
|
8184
|
+
warning: 'bg-warning-500',
|
|
8185
|
+
error: 'bg-error-500',
|
|
8186
|
+
info: 'bg-primary-500',
|
|
8187
|
+
neutral: 'bg-ink-400',
|
|
8188
|
+
};
|
|
8189
|
+
const sizeStyles = {
|
|
8190
|
+
sm: 'px-2 py-0.5 text-xs gap-1',
|
|
8191
|
+
md: 'px-3 py-1 text-xs gap-1.5',
|
|
8192
|
+
lg: 'px-3 py-1.5 text-sm gap-2',
|
|
8193
|
+
};
|
|
8194
|
+
// Pill variant has tighter horizontal padding and fully rounded ends
|
|
8195
|
+
const pillSizeStyles = {
|
|
8196
|
+
sm: 'px-1.5 py-0.5 text-xs gap-1',
|
|
8197
|
+
md: 'px-2 py-0.5 text-xs gap-1',
|
|
8198
|
+
lg: 'px-2.5 py-1 text-sm gap-1.5',
|
|
8199
|
+
};
|
|
8200
|
+
const dotSizeStyles = {
|
|
8201
|
+
sm: 'h-1.5 w-1.5',
|
|
8202
|
+
md: 'h-2 w-2',
|
|
8203
|
+
lg: 'h-2.5 w-2.5',
|
|
8204
|
+
};
|
|
8205
|
+
const iconSize = {
|
|
8206
|
+
sm: 'h-3 w-3',
|
|
8207
|
+
md: 'h-3.5 w-3.5',
|
|
8208
|
+
lg: 'h-4 w-4',
|
|
8209
|
+
};
|
|
8210
|
+
// Dot variant - just a colored circle
|
|
8211
|
+
if (dot) {
|
|
8212
|
+
return (jsx("span", { className: `
|
|
8213
|
+
inline-block rounded-full
|
|
8214
|
+
${dotVariantStyles[variant]}
|
|
8215
|
+
${dotSizeStyles[size]}
|
|
8216
|
+
${className}
|
|
8217
|
+
`, "aria-label": `${variant} indicator` }));
|
|
8218
|
+
}
|
|
8219
|
+
// Regular badge
|
|
8220
|
+
return (jsxs("span", { className: `
|
|
8221
|
+
inline-flex items-center border font-medium
|
|
8222
|
+
${pill ? 'rounded-full' : 'rounded-full'}
|
|
8223
|
+
${variantStyles[variant]}
|
|
8224
|
+
${pill ? pillSizeStyles[size] : sizeStyles[size]}
|
|
8225
|
+
${className}
|
|
8226
|
+
`, children: [icon && jsx("span", { className: iconSize[size], children: icon }), jsx("span", { children: children }), onRemove && (jsx("button", { onClick: onRemove, className: "ml-1 hover:opacity-70 transition-opacity", "aria-label": "Remove badge", children: jsx(X, { className: iconSize[size] }) }))] }));
|
|
8227
|
+
}
|
|
8228
|
+
|
|
8229
|
+
const TabsContext = createContext$1(null);
|
|
8230
|
+
function useTabsContext() {
|
|
8231
|
+
const context = useContext(TabsContext);
|
|
8232
|
+
if (!context) {
|
|
8233
|
+
throw new Error('Tabs compound components must be used within a TabsRoot component');
|
|
8234
|
+
}
|
|
8235
|
+
return context;
|
|
8236
|
+
}
|
|
8237
|
+
/**
|
|
8238
|
+
* TabsRoot - Root component for compound tabs pattern
|
|
8239
|
+
*
|
|
8240
|
+
* @example
|
|
8241
|
+
* ```tsx
|
|
8242
|
+
* <TabsRoot defaultValue="tab1">
|
|
8243
|
+
* <TabsList>
|
|
8244
|
+
* <TabsTrigger value="tab1">Tab 1</TabsTrigger>
|
|
8245
|
+
* <TabsTrigger value="tab2">Tab 2</TabsTrigger>
|
|
8246
|
+
* </TabsList>
|
|
8247
|
+
* <TabsContent value="tab1">Content 1</TabsContent>
|
|
8248
|
+
* <TabsContent value="tab2">Content 2</TabsContent>
|
|
8249
|
+
* </TabsRoot>
|
|
8250
|
+
* ```
|
|
8251
|
+
*/
|
|
8252
|
+
function TabsRoot({ children, defaultValue, value: controlledValue, onValueChange, variant = 'underline', orientation = 'horizontal', size = 'md', lazy = false, preserveState = false, className = '', }) {
|
|
8253
|
+
const [tabValues, setTabValues] = useState([]);
|
|
8254
|
+
const [internalValue, setInternalValue] = useState(defaultValue || '');
|
|
8255
|
+
const [visitedTabs, setVisitedTabs] = useState(new Set(defaultValue ? [defaultValue] : []));
|
|
8256
|
+
const isControlled = controlledValue !== undefined;
|
|
8257
|
+
const activeTab = isControlled ? controlledValue : internalValue;
|
|
8258
|
+
// Set initial value when tabs register
|
|
8259
|
+
useEffect(() => {
|
|
8260
|
+
if (!activeTab && tabValues.length > 0) {
|
|
8261
|
+
const firstTab = tabValues[0];
|
|
8262
|
+
if (isControlled) {
|
|
8263
|
+
onValueChange?.(firstTab);
|
|
8264
|
+
}
|
|
8265
|
+
else {
|
|
8266
|
+
setInternalValue(firstTab);
|
|
8267
|
+
}
|
|
8268
|
+
}
|
|
8269
|
+
}, [tabValues, activeTab, isControlled, onValueChange]);
|
|
8270
|
+
// Track visited tabs
|
|
8271
|
+
useEffect(() => {
|
|
8272
|
+
if (activeTab && preserveState) {
|
|
8273
|
+
setVisitedTabs(prev => new Set(prev).add(activeTab));
|
|
8274
|
+
}
|
|
8275
|
+
}, [activeTab, preserveState]);
|
|
8276
|
+
const setActiveTab = useCallback((value) => {
|
|
8277
|
+
if (!isControlled) {
|
|
8278
|
+
setInternalValue(value);
|
|
8279
|
+
}
|
|
8280
|
+
onValueChange?.(value);
|
|
8281
|
+
}, [isControlled, onValueChange]);
|
|
8282
|
+
const registerTab = useCallback((value) => {
|
|
8283
|
+
setTabValues(prev => prev.includes(value) ? prev : [...prev, value]);
|
|
8284
|
+
}, []);
|
|
8285
|
+
const unregisterTab = useCallback((value) => {
|
|
8286
|
+
setTabValues(prev => prev.filter(v => v !== value));
|
|
8287
|
+
}, []);
|
|
8288
|
+
const contextValue = {
|
|
8289
|
+
activeTab,
|
|
8290
|
+
setActiveTab,
|
|
8291
|
+
variant,
|
|
8292
|
+
orientation,
|
|
8293
|
+
size,
|
|
8294
|
+
lazy,
|
|
8295
|
+
preserveState,
|
|
8296
|
+
visitedTabs,
|
|
8297
|
+
registerTab,
|
|
8298
|
+
unregisterTab,
|
|
8299
|
+
tabValues,
|
|
8300
|
+
};
|
|
8301
|
+
// Size-specific gap classes
|
|
8302
|
+
const gapClasses = {
|
|
8303
|
+
sm: orientation === 'vertical' ? 'gap-1.5' : 'gap-4',
|
|
8304
|
+
md: orientation === 'vertical' ? 'gap-2' : 'gap-6',
|
|
8305
|
+
lg: orientation === 'vertical' ? 'gap-3' : 'gap-8',
|
|
8306
|
+
};
|
|
8307
|
+
return (jsx(TabsContext.Provider, { value: contextValue, children: jsx("div", { className: `w-full ${orientation === 'vertical' ? `flex ${gapClasses[size]}` : ''} ${className}`, children: children }) }));
|
|
8308
|
+
}
|
|
8309
|
+
/**
|
|
8310
|
+
* TabsList - Container for tab triggers
|
|
8311
|
+
*/
|
|
8312
|
+
function TabsList({ children, className = '' }) {
|
|
8313
|
+
const { variant, orientation, size } = useTabsContext();
|
|
8314
|
+
const sizeClasses = {
|
|
8315
|
+
sm: {
|
|
8316
|
+
gap: orientation === 'vertical' ? 'gap-1.5' : 'gap-4',
|
|
8317
|
+
minWidth: orientation === 'vertical' ? 'min-w-[150px]' : '',
|
|
8318
|
+
},
|
|
8319
|
+
md: {
|
|
8320
|
+
gap: orientation === 'vertical' ? 'gap-2' : 'gap-6',
|
|
8321
|
+
minWidth: orientation === 'vertical' ? 'min-w-[200px]' : '',
|
|
8322
|
+
},
|
|
8323
|
+
lg: {
|
|
8324
|
+
gap: orientation === 'vertical' ? 'gap-3' : 'gap-8',
|
|
8325
|
+
minWidth: orientation === 'vertical' ? 'min-w-[250px]' : '',
|
|
8326
|
+
},
|
|
8327
|
+
};
|
|
8328
|
+
return (jsx("div", { className: `
|
|
8329
|
+
flex ${orientation === 'vertical' ? 'flex-col' : 'items-center'}
|
|
8330
|
+
${variant === 'underline'
|
|
8331
|
+
? orientation === 'vertical'
|
|
8332
|
+
? `border-r border-paper-200 ${sizeClasses[size].gap} pr-6`
|
|
8333
|
+
: `border-b border-paper-200 ${sizeClasses[size].gap}`
|
|
8334
|
+
: `${sizeClasses[size].gap} p-1 bg-paper-50 rounded-lg`}
|
|
8335
|
+
${sizeClasses[size].minWidth}
|
|
8336
|
+
${className}
|
|
8337
|
+
`, role: "tablist", "aria-orientation": orientation, children: children }));
|
|
8338
|
+
}
|
|
8339
|
+
/**
|
|
8340
|
+
* TabsTrigger - Individual tab button
|
|
8341
|
+
*/
|
|
8342
|
+
function TabsTrigger({ children, value, disabled = false, icon, badge, badgeVariant = 'info', className = '', }) {
|
|
8343
|
+
const { activeTab, setActiveTab, variant, orientation, size, registerTab, unregisterTab } = useTabsContext();
|
|
8344
|
+
const isActive = activeTab === value;
|
|
8345
|
+
// Register this tab on mount
|
|
8346
|
+
useEffect(() => {
|
|
8347
|
+
registerTab(value);
|
|
8348
|
+
return () => unregisterTab(value);
|
|
8349
|
+
}, [value, registerTab, unregisterTab]);
|
|
8350
|
+
const sizeClasses = {
|
|
8351
|
+
sm: { padding: 'px-3 py-1.5', text: 'text-xs', icon: 'h-3.5 w-3.5', badgeSize: 'sm' },
|
|
8352
|
+
md: { padding: 'px-4 py-2.5', text: 'text-sm', icon: 'h-4 w-4', badgeSize: 'sm' },
|
|
8353
|
+
lg: { padding: 'px-5 py-3', text: 'text-base', icon: 'h-5 w-5', badgeSize: 'md' },
|
|
8354
|
+
};
|
|
8355
|
+
return (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: `
|
|
8356
|
+
flex items-center gap-2 ${sizeClasses[size].padding} ${sizeClasses[size].text} font-medium transition-all duration-200
|
|
8357
|
+
${orientation === 'vertical' ? 'w-full justify-start' : ''}
|
|
8358
|
+
${variant === 'underline'
|
|
8359
|
+
? isActive
|
|
8360
|
+
? orientation === 'vertical'
|
|
8361
|
+
? 'text-accent-900 border-r-2 border-accent-500 -mr-[1px]'
|
|
8362
|
+
: 'text-accent-900 border-b-2 border-accent-500 -mb-[1px]'
|
|
8363
|
+
: orientation === 'vertical'
|
|
8364
|
+
? 'text-ink-600 hover:text-ink-900 border-r-2 border-transparent'
|
|
8365
|
+
: 'text-ink-600 hover:text-ink-900 border-b-2 border-transparent'
|
|
8366
|
+
: isActive
|
|
8367
|
+
? 'bg-white text-accent-900 rounded-md shadow-xs'
|
|
8368
|
+
: 'text-ink-600 hover:text-ink-900 hover:bg-white/50 rounded-md'}
|
|
8369
|
+
${disabled ? 'opacity-40 cursor-not-allowed' : 'cursor-pointer'}
|
|
8370
|
+
focus:outline-none focus-visible:ring-2 focus-visible:ring-accent-500 focus-visible:ring-offset-1
|
|
8371
|
+
${className}
|
|
8372
|
+
`, children: [icon && jsx("span", { className: `flex-shrink-0 ${sizeClasses[size].icon}`, children: icon }), jsx("span", { children: children }), badge !== undefined && (jsx(Badge, { variant: badgeVariant, size: sizeClasses[size].badgeSize, children: badge }))] }));
|
|
8373
|
+
}
|
|
8374
|
+
/**
|
|
8375
|
+
* TabsContent - Content panel for a tab
|
|
8376
|
+
*/
|
|
8377
|
+
function TabsContent({ children, value, className = '' }) {
|
|
8378
|
+
const { activeTab, lazy, preserveState, visitedTabs, orientation, size } = useTabsContext();
|
|
8379
|
+
const isActive = activeTab === value;
|
|
8380
|
+
// Determine if content should be rendered
|
|
8381
|
+
const shouldRender = !lazy || isActive || (preserveState && visitedTabs.has(value));
|
|
8382
|
+
if (!shouldRender) {
|
|
8383
|
+
return null;
|
|
8384
|
+
}
|
|
8385
|
+
const spacingClasses = {
|
|
8386
|
+
sm: orientation === 'vertical' ? '' : 'mt-4',
|
|
8387
|
+
md: orientation === 'vertical' ? '' : 'mt-6',
|
|
8388
|
+
lg: orientation === 'vertical' ? '' : 'mt-8',
|
|
8389
|
+
};
|
|
8390
|
+
return (jsx("div", { id: `panel-${value}`, role: "tabpanel", "aria-labelledby": `tab-${value}`, hidden: !isActive, tabIndex: 0, className: `
|
|
8391
|
+
${orientation === 'vertical' ? 'flex-1' : spacingClasses[size]}
|
|
8392
|
+
${isActive ? 'animate-fade-in focus:outline-none' : 'hidden'}
|
|
8393
|
+
${className}
|
|
8394
|
+
`, children: children }));
|
|
8395
|
+
}
|
|
8396
|
+
// =============================================================================
|
|
8397
|
+
// Data-Driven Component (Original API)
|
|
8398
|
+
// =============================================================================
|
|
8399
|
+
/**
|
|
8400
|
+
* Tabs - Data-driven tabs component
|
|
8401
|
+
*
|
|
8402
|
+
* Use this for simple use cases where tabs are defined as an array.
|
|
8403
|
+
* For more complex layouts, use the compound components (TabsRoot, TabsList, TabsTrigger, TabsContent).
|
|
8404
|
+
*/
|
|
8405
|
+
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', }) {
|
|
8175
8406
|
const [internalActiveTab, setInternalActiveTab] = useState(defaultTab || tabs[0]?.id);
|
|
8407
|
+
const [focusedIndex, setFocusedIndex] = useState(-1);
|
|
8408
|
+
const [visitedTabs, setVisitedTabs] = useState(new Set([defaultTab || tabs[0]?.id]));
|
|
8409
|
+
const tabListRef = useRef(null);
|
|
8410
|
+
const tabRefs = useRef([]);
|
|
8176
8411
|
// Controlled mode: use activeTab prop, Uncontrolled mode: use internal state
|
|
8177
8412
|
const isControlled = controlledActiveTab !== undefined;
|
|
8178
8413
|
const activeTab = isControlled ? controlledActiveTab : internalActiveTab;
|
|
8414
|
+
// Track visited tabs for preserveState
|
|
8415
|
+
useEffect(() => {
|
|
8416
|
+
if (activeTab && preserveState) {
|
|
8417
|
+
setVisitedTabs(prev => new Set(prev).add(activeTab));
|
|
8418
|
+
}
|
|
8419
|
+
}, [activeTab, preserveState]);
|
|
8420
|
+
// Get enabled tab indices for keyboard navigation
|
|
8421
|
+
const enabledIndices = tabs.map((tab, index) => tab.disabled ? -1 : index).filter(i => i !== -1);
|
|
8179
8422
|
// Ensure the activeTab exists in the current tabs array
|
|
8180
8423
|
// This handles the case where tabs array reference changes at the same time as activeTab
|
|
8181
8424
|
useEffect(() => {
|
|
@@ -8190,66 +8433,196 @@ function Tabs({ tabs, activeTab: controlledActiveTab, defaultTab, variant = 'und
|
|
|
8190
8433
|
}
|
|
8191
8434
|
}
|
|
8192
8435
|
}, [tabs, activeTab, isControlled, onChange]);
|
|
8193
|
-
const handleTabChange = (tabId) => {
|
|
8436
|
+
const handleTabChange = useCallback((tabId) => {
|
|
8194
8437
|
if (!isControlled) {
|
|
8195
8438
|
setInternalActiveTab(tabId);
|
|
8196
8439
|
}
|
|
8197
8440
|
onChange?.(tabId);
|
|
8198
|
-
};
|
|
8441
|
+
}, [isControlled, onChange]);
|
|
8442
|
+
// Handle tab close
|
|
8443
|
+
const handleClose = useCallback((e, tabId) => {
|
|
8444
|
+
e.stopPropagation();
|
|
8445
|
+
onClose?.(tabId);
|
|
8446
|
+
}, [onClose]);
|
|
8447
|
+
// Keyboard navigation handler
|
|
8448
|
+
const handleKeyDown = useCallback((e) => {
|
|
8449
|
+
const currentIndex = focusedIndex >= 0 ? focusedIndex : tabs.findIndex(t => t.id === activeTab);
|
|
8450
|
+
const currentEnabledPosition = enabledIndices.indexOf(currentIndex);
|
|
8451
|
+
let nextIndex = -1;
|
|
8452
|
+
let shouldPreventDefault = true;
|
|
8453
|
+
// Determine navigation keys based on orientation
|
|
8454
|
+
const prevKey = orientation === 'vertical' ? 'ArrowUp' : 'ArrowLeft';
|
|
8455
|
+
const nextKey = orientation === 'vertical' ? 'ArrowDown' : 'ArrowRight';
|
|
8456
|
+
switch (e.key) {
|
|
8457
|
+
case prevKey:
|
|
8458
|
+
// Move to previous enabled tab
|
|
8459
|
+
if (currentEnabledPosition > 0) {
|
|
8460
|
+
nextIndex = enabledIndices[currentEnabledPosition - 1];
|
|
8461
|
+
}
|
|
8462
|
+
else {
|
|
8463
|
+
// Wrap to last enabled tab
|
|
8464
|
+
nextIndex = enabledIndices[enabledIndices.length - 1];
|
|
8465
|
+
}
|
|
8466
|
+
break;
|
|
8467
|
+
case nextKey:
|
|
8468
|
+
// Move to next enabled tab
|
|
8469
|
+
if (currentEnabledPosition < enabledIndices.length - 1) {
|
|
8470
|
+
nextIndex = enabledIndices[currentEnabledPosition + 1];
|
|
8471
|
+
}
|
|
8472
|
+
else {
|
|
8473
|
+
// Wrap to first enabled tab
|
|
8474
|
+
nextIndex = enabledIndices[0];
|
|
8475
|
+
}
|
|
8476
|
+
break;
|
|
8477
|
+
case 'Home':
|
|
8478
|
+
// Move to first enabled tab
|
|
8479
|
+
nextIndex = enabledIndices[0];
|
|
8480
|
+
break;
|
|
8481
|
+
case 'End':
|
|
8482
|
+
// Move to last enabled tab
|
|
8483
|
+
nextIndex = enabledIndices[enabledIndices.length - 1];
|
|
8484
|
+
break;
|
|
8485
|
+
case 'Enter':
|
|
8486
|
+
case ' ':
|
|
8487
|
+
// Activate focused tab
|
|
8488
|
+
if (focusedIndex >= 0 && !tabs[focusedIndex]?.disabled) {
|
|
8489
|
+
handleTabChange(tabs[focusedIndex].id);
|
|
8490
|
+
}
|
|
8491
|
+
break;
|
|
8492
|
+
case 'Delete':
|
|
8493
|
+
case 'Backspace':
|
|
8494
|
+
// Close focused tab if closeable
|
|
8495
|
+
if (focusedIndex >= 0) {
|
|
8496
|
+
const tab = tabs[focusedIndex];
|
|
8497
|
+
const isTabCloseable = tab.closeable !== undefined ? tab.closeable : closeable;
|
|
8498
|
+
if (isTabCloseable && !tab.disabled && onClose) {
|
|
8499
|
+
onClose(tab.id);
|
|
8500
|
+
}
|
|
8501
|
+
}
|
|
8502
|
+
break;
|
|
8503
|
+
default:
|
|
8504
|
+
shouldPreventDefault = false;
|
|
8505
|
+
}
|
|
8506
|
+
if (shouldPreventDefault) {
|
|
8507
|
+
e.preventDefault();
|
|
8508
|
+
}
|
|
8509
|
+
if (nextIndex >= 0 && nextIndex !== currentIndex) {
|
|
8510
|
+
setFocusedIndex(nextIndex);
|
|
8511
|
+
tabRefs.current[nextIndex]?.focus();
|
|
8512
|
+
}
|
|
8513
|
+
}, [focusedIndex, tabs, activeTab, enabledIndices, orientation, handleTabChange, closeable, onClose]);
|
|
8514
|
+
// Handle focus events
|
|
8515
|
+
const handleFocus = useCallback((index) => {
|
|
8516
|
+
setFocusedIndex(index);
|
|
8517
|
+
}, []);
|
|
8518
|
+
const handleBlur = useCallback(() => {
|
|
8519
|
+
setFocusedIndex(-1);
|
|
8520
|
+
}, []);
|
|
8199
8521
|
// Size-specific classes
|
|
8200
8522
|
const sizeClasses = {
|
|
8201
8523
|
sm: {
|
|
8202
8524
|
padding: 'px-3 py-1.5',
|
|
8203
8525
|
text: 'text-xs',
|
|
8204
8526
|
icon: 'h-3.5 w-3.5',
|
|
8527
|
+
closeIcon: 'h-3 w-3',
|
|
8205
8528
|
gap: orientation === 'vertical' ? 'gap-1.5' : 'gap-4',
|
|
8206
8529
|
minWidth: orientation === 'vertical' ? 'min-w-[150px]' : '',
|
|
8207
8530
|
spacing: orientation === 'vertical' ? 'mt-4' : 'mt-4',
|
|
8531
|
+
badgeSize: 'sm',
|
|
8532
|
+
addPadding: 'px-2 py-1.5',
|
|
8208
8533
|
},
|
|
8209
8534
|
md: {
|
|
8210
8535
|
padding: 'px-4 py-2.5',
|
|
8211
8536
|
text: 'text-sm',
|
|
8212
8537
|
icon: 'h-4 w-4',
|
|
8538
|
+
closeIcon: 'h-3.5 w-3.5',
|
|
8213
8539
|
gap: orientation === 'vertical' ? 'gap-2' : 'gap-6',
|
|
8214
8540
|
minWidth: orientation === 'vertical' ? 'min-w-[200px]' : '',
|
|
8215
8541
|
spacing: orientation === 'vertical' ? 'mt-6' : 'mt-6',
|
|
8542
|
+
badgeSize: 'sm',
|
|
8543
|
+
addPadding: 'px-3 py-2.5',
|
|
8216
8544
|
},
|
|
8217
8545
|
lg: {
|
|
8218
8546
|
padding: 'px-5 py-3',
|
|
8219
8547
|
text: 'text-base',
|
|
8220
8548
|
icon: 'h-5 w-5',
|
|
8549
|
+
closeIcon: 'h-4 w-4',
|
|
8221
8550
|
gap: orientation === 'vertical' ? 'gap-3' : 'gap-8',
|
|
8222
8551
|
minWidth: orientation === 'vertical' ? 'min-w-[250px]' : '',
|
|
8223
8552
|
spacing: orientation === 'vertical' ? 'mt-8' : 'mt-8',
|
|
8553
|
+
badgeSize: 'md',
|
|
8554
|
+
addPadding: 'px-4 py-3',
|
|
8224
8555
|
},
|
|
8225
8556
|
};
|
|
8226
|
-
|
|
8227
|
-
|
|
8557
|
+
// Determine which tabs should be rendered
|
|
8558
|
+
const shouldRenderContent = useCallback((tabId) => {
|
|
8559
|
+
if (!lazy) {
|
|
8560
|
+
// Not lazy: render all tabs
|
|
8561
|
+
return true;
|
|
8562
|
+
}
|
|
8563
|
+
if (tabId === activeTab) {
|
|
8564
|
+
// Always render active tab
|
|
8565
|
+
return true;
|
|
8566
|
+
}
|
|
8567
|
+
if (preserveState && visitedTabs.has(tabId)) {
|
|
8568
|
+
// Preserve state: render previously visited tabs
|
|
8569
|
+
return true;
|
|
8570
|
+
}
|
|
8571
|
+
return false;
|
|
8572
|
+
}, [lazy, activeTab, preserveState, visitedTabs]);
|
|
8573
|
+
return (jsxs("div", { className: `w-full ${orientation === 'vertical' ? `flex ${sizeClasses[size].gap}` : ''}`, children: [jsxs("div", { ref: tabListRef, className: `
|
|
8574
|
+
flex ${orientation === 'vertical' ? 'flex-col' : 'items-center'}
|
|
8228
8575
|
${variant === 'underline'
|
|
8229
8576
|
? orientation === 'vertical'
|
|
8230
8577
|
? `border-r border-paper-200 ${sizeClasses[size].gap} pr-6`
|
|
8231
8578
|
: `border-b border-paper-200 ${sizeClasses[size].gap}`
|
|
8232
8579
|
: `${sizeClasses[size].gap} p-1 bg-paper-50 rounded-lg`}
|
|
8233
8580
|
${sizeClasses[size].minWidth}
|
|
8234
|
-
`, role: "tablist", children: tabs.map((tab) => {
|
|
8235
|
-
|
|
8236
|
-
|
|
8581
|
+
`, role: "tablist", "aria-orientation": orientation, onKeyDown: handleKeyDown, children: [tabs.map((tab, index) => {
|
|
8582
|
+
const isActive = activeTab === tab.id;
|
|
8583
|
+
const isTabCloseable = tab.closeable !== undefined ? tab.closeable : closeable;
|
|
8584
|
+
return (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: `
|
|
8237
8585
|
flex items-center gap-2 ${sizeClasses[size].padding} ${sizeClasses[size].text} font-medium transition-all duration-200
|
|
8238
8586
|
${orientation === 'vertical' ? 'w-full justify-start' : ''}
|
|
8239
8587
|
${variant === 'underline'
|
|
8240
|
-
|
|
8241
|
-
|
|
8242
|
-
|
|
8243
|
-
|
|
8244
|
-
|
|
8245
|
-
|
|
8246
|
-
|
|
8247
|
-
|
|
8248
|
-
|
|
8249
|
-
|
|
8588
|
+
? isActive
|
|
8589
|
+
? orientation === 'vertical'
|
|
8590
|
+
? 'text-accent-900 border-r-2 border-accent-500 -mr-[1px]'
|
|
8591
|
+
: 'text-accent-900 border-b-2 border-accent-500 -mb-[1px]'
|
|
8592
|
+
: orientation === 'vertical'
|
|
8593
|
+
? 'text-ink-600 hover:text-ink-900 border-r-2 border-transparent'
|
|
8594
|
+
: 'text-ink-600 hover:text-ink-900 border-b-2 border-transparent'
|
|
8595
|
+
: isActive
|
|
8596
|
+
? 'bg-white text-accent-900 rounded-md shadow-xs'
|
|
8597
|
+
: 'text-ink-600 hover:text-ink-900 hover:bg-white/50 rounded-md'}
|
|
8250
8598
|
${tab.disabled ? 'opacity-40 cursor-not-allowed' : 'cursor-pointer'}
|
|
8251
|
-
|
|
8252
|
-
|
|
8599
|
+
focus:outline-none focus-visible:ring-2 focus-visible:ring-accent-500 focus-visible:ring-offset-1
|
|
8600
|
+
group
|
|
8601
|
+
`, children: [tab.icon && jsx("span", { className: `flex-shrink-0 ${sizeClasses[size].icon}`, children: tab.icon }), jsx("span", { className: isTabCloseable ? 'mr-1' : '', children: tab.label }), tab.badge !== undefined && (jsx(Badge, { variant: tab.badgeVariant || 'info', size: sizeClasses[size].badgeSize, children: tab.badge })), isTabCloseable && onClose && (jsx("span", { role: "button", "aria-label": `Close ${tab.label}`, onClick: (e) => handleClose(e, tab.id), className: `
|
|
8602
|
+
flex-shrink-0 p-0.5 rounded
|
|
8603
|
+
text-ink-400 hover:text-ink-700 hover:bg-paper-200
|
|
8604
|
+
opacity-0 group-hover:opacity-100 group-focus-visible:opacity-100
|
|
8605
|
+
${isActive ? 'opacity-100' : ''}
|
|
8606
|
+
transition-opacity duration-150
|
|
8607
|
+
`, children: jsx(X, { className: sizeClasses[size].closeIcon }) }))] }, tab.id));
|
|
8608
|
+
}), showAddButton && onAdd && (jsx("button", { type: "button", onClick: onAdd, "aria-label": addButtonLabel, title: addButtonLabel, className: `
|
|
8609
|
+
flex items-center justify-center ${sizeClasses[size].addPadding}
|
|
8610
|
+
text-ink-500 hover:text-ink-700 hover:bg-paper-100
|
|
8611
|
+
rounded transition-colors duration-150
|
|
8612
|
+
focus:outline-none focus-visible:ring-2 focus-visible:ring-accent-500 focus-visible:ring-offset-1
|
|
8613
|
+
${variant === 'underline'
|
|
8614
|
+
? orientation === 'vertical'
|
|
8615
|
+
? 'border-r-2 border-transparent'
|
|
8616
|
+
: 'border-b-2 border-transparent -mb-[1px]'
|
|
8617
|
+
: ''}
|
|
8618
|
+
`, children: jsx(Plus, { className: sizeClasses[size].icon }) }))] }), jsx("div", { className: `${orientation === 'vertical' ? 'flex-1' : sizeClasses[size].spacing}`, children: tabs.map((tab) => {
|
|
8619
|
+
const isActive = activeTab === tab.id;
|
|
8620
|
+
const shouldRender = shouldRenderContent(tab.id);
|
|
8621
|
+
if (!shouldRender) {
|
|
8622
|
+
return null;
|
|
8623
|
+
}
|
|
8624
|
+
return (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));
|
|
8625
|
+
}) })] }));
|
|
8253
8626
|
}
|
|
8254
8627
|
|
|
8255
8628
|
function Pagination({ currentPage, totalPages, onPageChange, showPageNumbers = true, maxPageNumbers = 5, showPageJump = false, }) {
|
|
@@ -8323,61 +8696,6 @@ function StepIndicator({ steps, currentStep, variant = 'horizontal', onStepClick
|
|
|
8323
8696
|
}) }) }));
|
|
8324
8697
|
}
|
|
8325
8698
|
|
|
8326
|
-
function Badge({ children, variant = 'neutral', size = 'md', icon, onRemove, className = '', dot = false, pill = false, }) {
|
|
8327
|
-
const variantStyles = {
|
|
8328
|
-
success: 'bg-success-50 text-success-700 border-success-200',
|
|
8329
|
-
warning: 'bg-warning-50 text-warning-700 border-warning-200',
|
|
8330
|
-
error: 'bg-error-50 text-error-700 border-error-200',
|
|
8331
|
-
info: 'bg-primary-50 text-primary-700 border-primary-200',
|
|
8332
|
-
neutral: 'bg-paper-100 text-ink-700 border-paper-300',
|
|
8333
|
-
};
|
|
8334
|
-
const dotVariantStyles = {
|
|
8335
|
-
success: 'bg-success-500',
|
|
8336
|
-
warning: 'bg-warning-500',
|
|
8337
|
-
error: 'bg-error-500',
|
|
8338
|
-
info: 'bg-primary-500',
|
|
8339
|
-
neutral: 'bg-ink-400',
|
|
8340
|
-
};
|
|
8341
|
-
const sizeStyles = {
|
|
8342
|
-
sm: 'px-2 py-0.5 text-xs gap-1',
|
|
8343
|
-
md: 'px-3 py-1 text-xs gap-1.5',
|
|
8344
|
-
lg: 'px-3 py-1.5 text-sm gap-2',
|
|
8345
|
-
};
|
|
8346
|
-
// Pill variant has tighter horizontal padding and fully rounded ends
|
|
8347
|
-
const pillSizeStyles = {
|
|
8348
|
-
sm: 'px-1.5 py-0.5 text-xs gap-1',
|
|
8349
|
-
md: 'px-2 py-0.5 text-xs gap-1',
|
|
8350
|
-
lg: 'px-2.5 py-1 text-sm gap-1.5',
|
|
8351
|
-
};
|
|
8352
|
-
const dotSizeStyles = {
|
|
8353
|
-
sm: 'h-1.5 w-1.5',
|
|
8354
|
-
md: 'h-2 w-2',
|
|
8355
|
-
lg: 'h-2.5 w-2.5',
|
|
8356
|
-
};
|
|
8357
|
-
const iconSize = {
|
|
8358
|
-
sm: 'h-3 w-3',
|
|
8359
|
-
md: 'h-3.5 w-3.5',
|
|
8360
|
-
lg: 'h-4 w-4',
|
|
8361
|
-
};
|
|
8362
|
-
// Dot variant - just a colored circle
|
|
8363
|
-
if (dot) {
|
|
8364
|
-
return (jsx("span", { className: `
|
|
8365
|
-
inline-block rounded-full
|
|
8366
|
-
${dotVariantStyles[variant]}
|
|
8367
|
-
${dotSizeStyles[size]}
|
|
8368
|
-
${className}
|
|
8369
|
-
`, "aria-label": `${variant} indicator` }));
|
|
8370
|
-
}
|
|
8371
|
-
// Regular badge
|
|
8372
|
-
return (jsxs("span", { className: `
|
|
8373
|
-
inline-flex items-center border font-medium
|
|
8374
|
-
${pill ? 'rounded-full' : 'rounded-full'}
|
|
8375
|
-
${variantStyles[variant]}
|
|
8376
|
-
${pill ? pillSizeStyles[size] : sizeStyles[size]}
|
|
8377
|
-
${className}
|
|
8378
|
-
`, children: [icon && jsx("span", { className: iconSize[size], children: icon }), jsx("span", { children: children }), onRemove && (jsx("button", { onClick: onRemove, className: "ml-1 hover:opacity-70 transition-opacity", "aria-label": "Remove badge", children: jsx(X, { className: iconSize[size] }) }))] }));
|
|
8379
|
-
}
|
|
8380
|
-
|
|
8381
8699
|
/**
|
|
8382
8700
|
* Avatar component that displays:
|
|
8383
8701
|
* - User initials in a colored circle (default)
|
|
@@ -10546,6 +10864,9 @@ function getColumnStyle(column, dynamicWidth) {
|
|
|
10546
10864
|
if (column.align) {
|
|
10547
10865
|
style.textAlign = column.align;
|
|
10548
10866
|
}
|
|
10867
|
+
if (column.verticalAlign) {
|
|
10868
|
+
style.verticalAlign = column.verticalAlign;
|
|
10869
|
+
}
|
|
10549
10870
|
return style;
|
|
10550
10871
|
}
|
|
10551
10872
|
/**
|
|
@@ -57870,5 +58191,5 @@ function Responsive({ mobile, tablet, desktop, }) {
|
|
|
57870
58191
|
return jsx(Fragment, { children: mobile || tablet || desktop });
|
|
57871
58192
|
}
|
|
57872
58193
|
|
|
57873
|
-
export { Accordion, ActionBar, ActionBarCenter, ActionBarLeft, ActionBarRight, ActionButton, AdminModal, Alert, AlertDialog, AppLayout, Autocomplete, Avatar, BREAKPOINTS, Badge, BottomNavigation, BottomNavigationSpacer, BottomSheet, BottomSheetActions, BottomSheetContent, BottomSheetHeader, Box, Breadcrumbs, Button, ButtonGroup, Calendar, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, CardView, Carousel, Checkbox, CheckboxList, Chip, ChipGroup, Collapsible, ColorPicker, Combobox, ComingSoon, CommandPalette, CompactStat, ConfirmDialog, ContextMenu, ControlBar, CurrencyDisplay, CurrencyInput, Dashboard, DashboardContent, DashboardHeader, DataGrid, DataTable, DataTableCardView, DateDisplay, DatePicker, DateRangePicker, DateTimePicker, DesktopOnly, Drawer, DrawerFooter, DropZone, Dropdown, DropdownTrigger, EmptyState, ErrorBoundary, ExpandablePanel, ExpandablePanelContainer, ExpandablePanelSpacer, ExpandableRowButton, ExpandableToolbar, ExpandedRowEditForm, ExportButton, FORMULA_CATEGORIES, FORMULA_DEFINITIONS, FORMULA_NAMES, FieldArray, FileUpload, FilterBar, FilterControls, FilterStatusBanner, FloatingActionButton, Form, FormContext, FormControl, FormWizard, Grid, GridItem, Hide, HorizontalScroll, HoverCard, InfiniteScroll, Input, KanbanBoard, Layout, Loading, LoadingOverlay, Logo, MarkdownEditor, MaskedInput, Menu, MenuDivider, MobileHeader, MobileHeaderSpacer, MobileLayout, MobileOnly, MobileProvider, Modal, ModalFooter, MultiSelect, NotificationBanner, NotificationBar, NotificationBell, NotificationIndicator, NumberInput, Page, PageHeader, PageLayout, PageNavigation, Pagination, PasswordInput, Popover, Progress, PullToRefresh, QueryTransparency, RadioGroup, Rating, Responsive, RichTextEditor, SearchBar, SearchableList, Select, Separator, Show, Sidebar, SidebarGroup, Skeleton, SkeletonCard$1 as SkeletonCard, SkeletonTable, Slider, Spreadsheet, SpreadsheetReport, Stack, StatCard, StatItem, StatsCardGrid, StatsGrid, StatusBadge, StatusBar, StepIndicator, Stepper, SwipeActions, SwipeableCard, Switch, Tabs, Text, Textarea, ThemeToggle, TimePicker, Timeline, Toast, ToastContainer, Tooltip, Transfer, TreeView, TwoColumnContent, UserProfileButton, addErrorMessage, addInfoMessage, addSuccessMessage, addWarningMessage, calculateColumnWidth, createActionsSection, createFiltersSection, createMultiSheetExcel, createPageControlsSection, createQueryDetailsSection, exportDataTableToExcel, exportToExcel, formatStatisticValue, formatStatistics, getFormula, getFormulasByCategory, loadColumnOrder, loadColumnWidths, reorderArray, saveColumnOrder, saveColumnWidths, searchFormulas, statusManager, useBreadcrumbReset, useBreakpoint, useBreakpointValue, useColumnReorder, useColumnResize, useCommandPalette, useConfirmDialog, useFABScroll, useFormContext, useIsDesktop, useIsMobile, useIsTablet, useIsTouchDevice, useMediaQuery, useMobileContext, useOrientation, usePrefersMobile, useResponsiveCallback, useSafeAreaInsets, useViewportSize, withMobileContext };
|
|
58194
|
+
export { Accordion, ActionBar, ActionBarCenter, ActionBarLeft, ActionBarRight, ActionButton, AdminModal, Alert, AlertDialog, AppLayout, Autocomplete, Avatar, BREAKPOINTS, Badge, BottomNavigation, BottomNavigationSpacer, BottomSheet, BottomSheetActions, BottomSheetContent, BottomSheetHeader, Box, Breadcrumbs, Button, ButtonGroup, Calendar, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, CardView, Carousel, Checkbox, CheckboxList, Chip, ChipGroup, Collapsible, ColorPicker, Combobox, ComingSoon, CommandPalette, CompactStat, ConfirmDialog, ContextMenu, ControlBar, CurrencyDisplay, CurrencyInput, Dashboard, DashboardContent, DashboardHeader, DataGrid, DataTable, DataTableCardView, DateDisplay, DatePicker, DateRangePicker, DateTimePicker, DesktopOnly, Drawer, DrawerFooter, DropZone, Dropdown, DropdownTrigger, EmptyState, ErrorBoundary, ExpandablePanel, ExpandablePanelContainer, ExpandablePanelSpacer, ExpandableRowButton, ExpandableToolbar, ExpandedRowEditForm, ExportButton, FORMULA_CATEGORIES, FORMULA_DEFINITIONS, FORMULA_NAMES, FieldArray, FileUpload, FilterBar, FilterControls, FilterStatusBanner, FloatingActionButton, Form, FormContext, FormControl, FormWizard, Grid, GridItem, Hide, HorizontalScroll, HoverCard, InfiniteScroll, Input, KanbanBoard, Layout, Loading, LoadingOverlay, Logo, MarkdownEditor, MaskedInput, Menu, MenuDivider, MobileHeader, MobileHeaderSpacer, MobileLayout, MobileOnly, MobileProvider, Modal, ModalFooter, MultiSelect, NotificationBanner, NotificationBar, NotificationBell, NotificationIndicator, NumberInput, Page, PageHeader, PageLayout, PageNavigation, Pagination, PasswordInput, Popover, Progress, PullToRefresh, QueryTransparency, RadioGroup, Rating, Responsive, RichTextEditor, SearchBar, SearchableList, Select, Separator, Show, Sidebar, SidebarGroup, Skeleton, SkeletonCard$1 as SkeletonCard, SkeletonTable, Slider, Spreadsheet, SpreadsheetReport, Stack, StatCard, StatItem, StatsCardGrid, StatsGrid, StatusBadge, StatusBar, StepIndicator, Stepper, SwipeActions, SwipeableCard, Switch, Tabs, TabsContent, TabsList, TabsRoot, TabsTrigger, Text, Textarea, ThemeToggle, TimePicker, Timeline, Toast, ToastContainer, Tooltip, Transfer, TreeView, TwoColumnContent, UserProfileButton, addErrorMessage, addInfoMessage, addSuccessMessage, addWarningMessage, calculateColumnWidth, createActionsSection, createFiltersSection, createMultiSheetExcel, createPageControlsSection, createQueryDetailsSection, exportDataTableToExcel, exportToExcel, formatStatisticValue, formatStatistics, getFormula, getFormulasByCategory, loadColumnOrder, loadColumnWidths, reorderArray, saveColumnOrder, saveColumnWidths, searchFormulas, statusManager, useBreadcrumbReset, useBreakpoint, useBreakpointValue, useColumnReorder, useColumnResize, useCommandPalette, useConfirmDialog, useFABScroll, useFormContext, useIsDesktop, useIsMobile, useIsTablet, useIsTouchDevice, useMediaQuery, useMobileContext, useOrientation, usePrefersMobile, useResponsiveCallback, useSafeAreaInsets, useViewportSize, withMobileContext };
|
|
57874
58195
|
//# sourceMappingURL=index.esm.js.map
|