@neasg/design-system 0.4.35 → 0.4.113
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/README.md +9 -0
- package/dist/activity-card.d.ts +31 -0
- package/dist/activity-card.js +65 -0
- package/dist/alert.d.ts +1 -1
- package/dist/autocomplete.d.ts +84 -0
- package/dist/autocomplete.js +267 -0
- package/dist/avatar.d.ts +3 -1
- package/dist/avatar.js +27 -10
- package/dist/badge.d.ts +1 -1
- package/dist/badge.js +1 -1
- package/dist/button.d.ts +2 -2
- package/dist/button.js +3 -1
- package/dist/calendar.js +1 -1
- package/dist/card.d.ts +1 -1
- package/dist/card.js +1 -1
- package/dist/changelog-action-panel.d.ts +17 -0
- package/dist/changelog-action-panel.js +14 -0
- package/dist/checklist.d.ts +63 -0
- package/dist/checklist.js +30 -0
- package/dist/compound-search-input.d.ts +10 -0
- package/dist/compound-search-input.js +19 -0
- package/dist/date-input.js +3 -3
- package/dist/dialog.d.ts +4 -1
- package/dist/dialog.js +7 -2
- package/dist/draggable-tabs.js +9 -8
- package/dist/dropdown-button.js +1 -0
- package/dist/editable-table.js +2 -2
- package/dist/field-counter.d.ts +7 -0
- package/dist/field-counter.js +5 -0
- package/dist/index.d.ts +22 -4
- package/dist/index.js +12 -2
- package/dist/input.d.ts +2 -0
- package/dist/input.js +11 -3
- package/dist/label-value-grid.js +6 -4
- package/dist/layout.d.ts +39 -6
- package/dist/layout.js +118 -42
- package/dist/lib/utils.js +1 -0
- package/dist/message-action-panel.d.ts +12 -0
- package/dist/message-action-panel.js +11 -0
- package/dist/message-item.d.ts +23 -3
- package/dist/message-item.js +115 -16
- package/dist/notification.d.ts +14 -3
- package/dist/notification.js +36 -7
- package/dist/page-section.d.ts +2 -1
- package/dist/page-section.js +2 -2
- package/dist/popover-menu.d.ts +4 -2
- package/dist/popover-menu.js +65 -5
- package/dist/popover.d.ts +10 -2
- package/dist/popover.js +7 -3
- package/dist/rich-text-editor.d.ts +2 -1
- package/dist/rich-text-editor.js +29 -6
- package/dist/routing-action-panel.d.ts +38 -0
- package/dist/routing-action-panel.js +19 -0
- package/dist/routing-timeline.d.ts +7 -2
- package/dist/routing-timeline.js +67 -29
- package/dist/search-input.d.ts +6 -0
- package/dist/search-input.js +6 -4
- package/dist/select-primitive.js +1 -1
- package/dist/select.d.ts +3 -1
- package/dist/select.js +9 -4
- package/dist/status-dot.d.ts +13 -0
- package/dist/status-dot.js +19 -0
- package/dist/styles.css +0 -19
- package/dist/table-add-row.d.ts +8 -0
- package/dist/table-add-row.js +7 -0
- package/dist/table-column-filter.js +7 -5
- package/dist/table.d.ts +9 -1
- package/dist/table.js +25 -11
- package/dist/tabs.d.ts +1 -1
- package/dist/tabs.js +6 -4
- package/dist/tailwind-preset.js +10 -0
- package/dist/textarea.d.ts +5 -0
- package/dist/textarea.js +18 -3
- package/dist/theme-switcher.d.ts +3 -1
- package/dist/theme-switcher.js +8 -2
- package/package.json +1 -1
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import * as React from "react";
|
|
4
4
|
import { FilterIcon } from "./animated-icons";
|
|
5
|
+
import { buttonVariants } from "./button";
|
|
5
6
|
import { DateInput } from "./date-input";
|
|
6
7
|
import { FilterPopover } from "./filter-popover";
|
|
7
8
|
import { FilterToggle, filterToggleVariants, } from "./filter-toggle";
|
|
@@ -29,7 +30,7 @@ function getOptionsFilterSummary(filter) {
|
|
|
29
30
|
}
|
|
30
31
|
return ((_c = (_b = filter.options.find((option) => option.value === filter.values[0])) === null || _b === void 0 ? void 0 : _b.label) !== null && _c !== void 0 ? _c : filter.values[0]);
|
|
31
32
|
}
|
|
32
|
-
const TableFilterTrigger = React.forwardRef(({ active, disabled, label, children, ...props }, ref) => (_jsx(FilterToggle, { ref: ref, type: "button", disabled: disabled, selected: active, "aria-label": `Filter by ${label}${active ? ", active" : ""}`, className: cn("h-
|
|
33
|
+
const TableFilterTrigger = React.forwardRef(({ active, disabled, label, children, ...props }, ref) => (_jsx(FilterToggle, { ref: ref, type: "button", disabled: disabled, selected: active, "aria-label": `Filter by ${label}${active ? ", active" : ""}`, className: cn("h-8 w-full min-w-0 justify-start overflow-hidden px-2 text-sm font-normal", !active &&
|
|
33
34
|
"bg-transparent text-muted-foreground hover:bg-accent hover:text-accent-foreground"), icon: _jsx(FilterIcon, { "aria-hidden": "true", className: "shrink-0", size: 16 }), ...props, children: _jsx("span", { className: "min-w-0 flex-1 truncate text-left", children: children }) })));
|
|
34
35
|
TableFilterTrigger.displayName = "TableFilterTrigger";
|
|
35
36
|
function TextColumnFilter({ filter, label, }) {
|
|
@@ -71,15 +72,16 @@ function DateColumnFilter({ filter, label, }) {
|
|
|
71
72
|
var _a, _b;
|
|
72
73
|
const active = isTableColumnFilterActive(filter);
|
|
73
74
|
const accessibleLabel = (_a = filter.label) !== null && _a !== void 0 ? _a : label;
|
|
74
|
-
return (_jsx(DateInput, { label: `Filter by ${accessibleLabel}${active ? ", active" : ""}`, hideLabel: true, value: filter.value, onValueChange: filter.onValueChange, placeholder: (_b = filter.placeholder) !== null && _b !== void 0 ? _b : "Pick a date", disabled: filter.disabled, minDate: filter.minDate, maxDate: filter.maxDate, clearable: true, clearLabel: `Clear ${accessibleLabel} filter`, className: "gap-0", triggerClassName: cn(
|
|
75
|
-
"border-
|
|
75
|
+
return (_jsx(DateInput, { label: `Filter by ${accessibleLabel}${active ? ", active" : ""}`, hideLabel: true, value: filter.value, onValueChange: filter.onValueChange, placeholder: (_b = filter.placeholder) !== null && _b !== void 0 ? _b : "Pick a date", popoverTitle: `Filter by ${accessibleLabel}`, disabled: filter.disabled, minDate: filter.minDate, maxDate: filter.maxDate, clearable: true, clearLabel: `Clear ${accessibleLabel} filter`, className: "gap-0", triggerClassName: cn(buttonVariants({ variant: "outline", size: "sm" }), "h-8 w-full min-w-0 justify-start font-normal shadow-none", active ? "pl-2 pr-16" : "pl-2 pr-9", active
|
|
76
|
+
? "border-transparent bg-highlight text-highlight-foreground hover:bg-highlight/80"
|
|
77
|
+
: "bg-transparent text-muted-foreground hover:bg-accent hover:text-accent-foreground") }));
|
|
76
78
|
}
|
|
77
79
|
function DateRangeColumnFilter({ filter, label, }) {
|
|
78
80
|
var _a, _b;
|
|
79
81
|
const active = isTableColumnFilterActive(filter);
|
|
80
82
|
const accessibleLabel = (_a = filter.label) !== null && _a !== void 0 ? _a : label;
|
|
81
|
-
return (_jsx(DateInput, { mode: "range", label: `Filter by ${accessibleLabel}${active ? ", active" : ""}`, hideLabel: true, value: filter.value, onValueChange: filter.onValueChange, placeholder: (_b = filter.placeholder) !== null && _b !== void 0 ? _b : "Pick date range", disabled: filter.disabled, minDate: filter.minDate, maxDate: filter.maxDate, clearable: true, clearLabel: `Clear ${accessibleLabel} filter`, className: "gap-0", triggerClassName: cn(filterToggleVariants({ selected: active }), "h-
|
|
82
|
-
"
|
|
83
|
+
return (_jsx(DateInput, { mode: "range", label: `Filter by ${accessibleLabel}${active ? ", active" : ""}`, hideLabel: true, value: filter.value, onValueChange: filter.onValueChange, placeholder: (_b = filter.placeholder) !== null && _b !== void 0 ? _b : "Pick date range", popoverTitle: `Filter by ${accessibleLabel}`, disabled: filter.disabled, minDate: filter.minDate, maxDate: filter.maxDate, clearable: true, clearLabel: `Clear ${accessibleLabel} filter`, className: "gap-0", triggerClassName: cn(filterToggleVariants({ selected: active }), "h-8 w-full min-w-0 justify-start border-0 text-sm font-normal shadow-none", active ? "pl-2 pr-16" : "pl-2 pr-9", !active &&
|
|
84
|
+
"bg-transparent text-muted-foreground hover:bg-accent hover:text-accent-foreground") }));
|
|
83
85
|
}
|
|
84
86
|
function TableColumnFilterControl({ filter, label, }) {
|
|
85
87
|
if (filter.type === "text") {
|
package/dist/table.d.ts
CHANGED
|
@@ -123,6 +123,12 @@ export interface TableRowExpansionProps<Row> {
|
|
|
123
123
|
/** Accessible label for a row's expansion toggle. */
|
|
124
124
|
getToggleLabel?: (row: Row, rowIndex: number, expanded: boolean) => string;
|
|
125
125
|
}
|
|
126
|
+
export interface TableRowIndicatorProps<Row> {
|
|
127
|
+
/** Renders a compact status marker in a fixed leading column for each row. */
|
|
128
|
+
render: (row: Row, rowIndex: number) => React.ReactNode;
|
|
129
|
+
/** Accessible name for the otherwise visually empty indicator column header. */
|
|
130
|
+
headerLabel?: string;
|
|
131
|
+
}
|
|
126
132
|
interface SortableTableHeadProps extends Omit<React.ThHTMLAttributes<HTMLTableCellElement>, "children" | "style"> {
|
|
127
133
|
field: string;
|
|
128
134
|
children: React.ReactNode;
|
|
@@ -194,6 +200,8 @@ export interface TableProps<Row> extends Omit<React.HTMLAttributes<HTMLDivElemen
|
|
|
194
200
|
emptyStateMinHeight?: React.CSSProperties["minHeight"];
|
|
195
201
|
/** When true, applies alternating row backgrounds for easier scanning. */
|
|
196
202
|
striped?: boolean;
|
|
203
|
+
/** Adds a compact, non-reorderable status column at the leading edge of every row. */
|
|
204
|
+
rowIndicator?: TableRowIndicatorProps<Row>;
|
|
197
205
|
/** Adds a disclosure column and full-width expandable content for nested tables or row details. */
|
|
198
206
|
rowExpansion?: TableRowExpansionProps<Row>;
|
|
199
207
|
/** When true, non-sticky header cells become draggable for column reordering. */
|
|
@@ -201,5 +209,5 @@ export interface TableProps<Row> extends Omit<React.HTMLAttributes<HTMLDivElemen
|
|
|
201
209
|
/** Called with the new ordered column key array after a drag-and-drop reorder. */
|
|
202
210
|
onColumnOrderChange?: (columnKeys: string[]) => void;
|
|
203
211
|
}
|
|
204
|
-
declare function Table<Row>({ accessibleLabel, columns, rows, getRowKey, emptyState, toolbar, caption, className, containerClassName, tableClassName, rowClassName, rowTone, maxHeight, minHeight, sorting, pagination, loading, loadingLabel, loadingRows, visibleColumnKeys, resizableColumns, columnResizeMode, columnWidths, defaultColumnWidths, onColumnWidthsChange, renderColumnResizeHandle, tableLayout, centerEmptyState, emptyStateMinHeight, striped, rowExpansion, reorderableColumns, onColumnOrderChange, onScroll, style, ...props }: TableProps<Row>): import("react/jsx-runtime").JSX.Element;
|
|
212
|
+
declare function Table<Row>({ accessibleLabel, columns, rows, getRowKey, emptyState, toolbar, caption, className, containerClassName, tableClassName, rowClassName, rowTone, maxHeight, minHeight, sorting, pagination, loading, loadingLabel, loadingRows, visibleColumnKeys, resizableColumns, columnResizeMode, columnWidths, defaultColumnWidths, onColumnWidthsChange, renderColumnResizeHandle, tableLayout, centerEmptyState, emptyStateMinHeight, striped, rowIndicator, rowExpansion, reorderableColumns, onColumnOrderChange, onScroll, style, ...props }: TableProps<Row>): import("react/jsx-runtime").JSX.Element;
|
|
205
213
|
export { Table, TableRoot, TableContainer, TableHeader, TableBody, TableFooter, TableHead, TableRow, TableCell, TableRowHeader, TableCaption, SortableTableHead, TableRowSkeleton, };
|
package/dist/table.js
CHANGED
|
@@ -19,6 +19,7 @@ const DEFAULT_COLUMN_RESIZE_MIN_WIDTH = 64;
|
|
|
19
19
|
const DEFAULT_COLUMN_RESIZE_START_WIDTH = 160;
|
|
20
20
|
const DEFAULT_COLUMN_RESIZE_MAX_WIDTH = 1200;
|
|
21
21
|
const COLUMN_RESIZE_KEYBOARD_STEP = 16;
|
|
22
|
+
const TABLE_ROW_INDICATOR_COLUMN_WIDTH = 32;
|
|
22
23
|
const TABLE_EXPANSION_COLUMN_WIDTH = 48;
|
|
23
24
|
const TABLE_MIN_WIDTH_CSS_VAR = "--table-min-width";
|
|
24
25
|
const DEFAULT_TABLE_MIN_HEIGHT = "var(--table-min-height, var(--app-table-min-height, 24rem))";
|
|
@@ -159,7 +160,7 @@ const TableFooter = React.forwardRef(({ className, ...props }, ref) => (_jsx("tf
|
|
|
159
160
|
TableFooter.displayName = "TableFooter";
|
|
160
161
|
const TableRow = React.forwardRef(({ className, ...props }, ref) => (_jsx("tr", { ref: ref, className: cn("border-b border-[hsl(var(--table-border))] bg-card text-card-foreground transition-colors data-[state=selected]:bg-muted", className), ...props })));
|
|
161
162
|
TableRow.displayName = "TableRow";
|
|
162
|
-
const TableHead = React.forwardRef(({ className, style, width, minWidth, maxWidth, wrap = false, treatWidthAsMinWidth, containOverflow, ...props }, ref) => (_jsx("th", { ref: ref, className: cn("h-11 px-4 py-
|
|
163
|
+
const TableHead = React.forwardRef(({ className, style, width, minWidth, maxWidth, wrap = false, treatWidthAsMinWidth, containOverflow, ...props }, ref) => (_jsx("th", { ref: ref, className: cn("h-11 px-4 py-[4px] text-left align-middle font-medium text-instructional [&:has([role=checkbox])]:pr-0", wrap ? "whitespace-normal" : "whitespace-nowrap", overflowContainmentClassName({ containOverflow, wrap }), className), style: getTableColumnSizingStyle({
|
|
163
164
|
style: {
|
|
164
165
|
...style,
|
|
165
166
|
fontWeight: 500,
|
|
@@ -170,7 +171,7 @@ const TableHead = React.forwardRef(({ className, style, width, minWidth, maxWidt
|
|
|
170
171
|
treatWidthAsMinWidth,
|
|
171
172
|
}), ...props })));
|
|
172
173
|
TableHead.displayName = "TableHead";
|
|
173
|
-
const TableCell = React.forwardRef(({ className, style, width, minWidth, maxWidth, wrap = false, treatWidthAsMinWidth, containOverflow, ...props }, ref) => (_jsx("td", { ref: ref, className: cn("h-12 px-4 py-
|
|
174
|
+
const TableCell = React.forwardRef(({ className, style, width, minWidth, maxWidth, wrap = false, treatWidthAsMinWidth, containOverflow, ...props }, ref) => (_jsx("td", { ref: ref, className: cn("h-12 px-4 py-[4px] align-middle text-card-foreground [&:has([role=checkbox])]:pr-0 [&_[data-slot=button]]:px-0", wrap ? "whitespace-normal" : "whitespace-nowrap", overflowContainmentClassName({ containOverflow, wrap }), className), style: getTableColumnSizingStyle({
|
|
174
175
|
style,
|
|
175
176
|
width,
|
|
176
177
|
minWidth,
|
|
@@ -178,7 +179,7 @@ const TableCell = React.forwardRef(({ className, style, width, minWidth, maxWidt
|
|
|
178
179
|
treatWidthAsMinWidth,
|
|
179
180
|
}), ...props })));
|
|
180
181
|
TableCell.displayName = "TableCell";
|
|
181
|
-
const TableRowHeader = React.forwardRef(({ className, style, width, minWidth, maxWidth, wrap = false, treatWidthAsMinWidth, containOverflow, scope = "row", ...props }, ref) => (_jsx("th", { ref: ref, scope: scope, className: cn("h-12 px-4 py-
|
|
182
|
+
const TableRowHeader = React.forwardRef(({ className, style, width, minWidth, maxWidth, wrap = false, treatWidthAsMinWidth, containOverflow, scope = "row", ...props }, ref) => (_jsx("th", { ref: ref, scope: scope, className: cn("h-12 px-4 py-[4px] text-left align-middle font-medium text-card-foreground [&:has([role=checkbox])]:pr-0", wrap ? "whitespace-normal" : "whitespace-nowrap", overflowContainmentClassName({ containOverflow, wrap }), className), style: getTableColumnSizingStyle({
|
|
182
183
|
style,
|
|
183
184
|
width,
|
|
184
185
|
minWidth,
|
|
@@ -240,7 +241,7 @@ function SkeletonCell({ config }) {
|
|
|
240
241
|
return (_jsx(TableCell, { children: _jsx(SkeletonBlock, { width: config.width, height: config.height, badge: config.badge }) }));
|
|
241
242
|
}
|
|
242
243
|
function TableRowSkeleton({ columns, rows = 1 }) {
|
|
243
|
-
return (_jsx(_Fragment, { children: Array.from({ length: rows }).map((_, rowIndex) => (_jsx(TableRow, { children: columns.map((config, columnIndex) => (_jsx(SkeletonCell, { config: config }, columnIndex))) }, rowIndex))) }));
|
|
244
|
+
return (_jsx(_Fragment, { children: Array.from({ length: rows }).map((_, rowIndex) => (_jsx(TableRow, { "data-slot": "table-skeleton-row", className: "h-12", children: columns.map((config, columnIndex) => (_jsx(SkeletonCell, { config: config }, columnIndex))) }, rowIndex))) }));
|
|
244
245
|
}
|
|
245
246
|
export const TABLE_SKELETON_PRESETS = {
|
|
246
247
|
text: (width = "8rem", height = "1rem") => ({
|
|
@@ -278,7 +279,7 @@ const SortableTableHead = React.forwardRef(function SortableTableHead({ field, c
|
|
|
278
279
|
? currentSortDirection === "asc"
|
|
279
280
|
? "ascending"
|
|
280
281
|
: "descending"
|
|
281
|
-
: undefined, className: cn(resizeHandle && "relative", alignClassName(align), className), style: style, wrap: allowWrap, width: width, minWidth: minWidth, maxWidth: maxWidth, treatWidthAsMinWidth: treatWidthAsMinWidth, containOverflow: containOverflow, ...rest, children: [gripIcon, _jsxs("button", { type: "button", onClick: () => onSort(field), className: cn("-ml-1.5 flex h-7 cursor-pointer items-center gap-1 rounded px-1.5 py-0 font-medium transition-colors hover:text-foreground", containOverflow && "max-w-full overflow-hidden", allowWrap
|
|
282
|
+
: undefined, className: cn(resizeHandle && "relative", alignClassName(align), className), style: style, wrap: allowWrap, width: width, minWidth: minWidth, maxWidth: maxWidth, treatWidthAsMinWidth: treatWidthAsMinWidth, containOverflow: containOverflow, ...rest, children: [gripIcon, _jsxs("button", { type: "button", onClick: () => onSort(field), className: cn("-ml-1.5 flex h-auto min-h-7 cursor-pointer items-center gap-1 rounded px-1.5 py-0 font-medium transition-colors hover:text-foreground", containOverflow && "max-w-full overflow-hidden", allowWrap
|
|
282
283
|
? "max-w-full whitespace-normal text-left"
|
|
283
284
|
: "whitespace-nowrap", align === "right" && "ml-auto justify-end", align === "center" && "mx-auto justify-center"), style: { font: "inherit", color: "inherit", fontWeight: 500 }, "aria-label": `Sort by ${resolvedSortLabel}`, children: [_jsx("span", { className: cn("min-w-0", containOverflow && !allowWrap && "truncate", containOverflow &&
|
|
284
285
|
allowWrap &&
|
|
@@ -398,8 +399,10 @@ function getColumnPairResizeRange(column, nextColumn, columnWidths) {
|
|
|
398
399
|
maxWidth: Math.round(currentWidth + maxDelta),
|
|
399
400
|
};
|
|
400
401
|
}
|
|
401
|
-
function Table({ accessibleLabel, columns, rows, getRowKey, emptyState = (_jsx(EmptyState, { message: "No data available", description: "There are no rows to display in this table yet.", className: "border-0 bg-transparent px-0 py-6" })), toolbar, caption, className, containerClassName, tableClassName, rowClassName, rowTone, maxHeight, minHeight, sorting, pagination, loading = false, loadingLabel = "Loading table data", loadingRows = 5, visibleColumnKeys, resizableColumns = false, columnResizeMode = "pair", columnWidths, defaultColumnWidths, onColumnWidthsChange, renderColumnResizeHandle, tableLayout, centerEmptyState = false, emptyStateMinHeight = DEFAULT_CENTERED_EMPTY_STATE_MIN_HEIGHT, striped = false, rowExpansion, reorderableColumns = false, onColumnOrderChange, onScroll, style, ...props }) {
|
|
402
|
+
function Table({ accessibleLabel, columns, rows, getRowKey, emptyState = (_jsx(EmptyState, { message: "No data available", description: "There are no rows to display in this table yet.", className: "border-0 bg-transparent px-0 py-6" })), toolbar, caption, className, containerClassName, tableClassName, rowClassName, rowTone, maxHeight, minHeight, sorting, pagination, loading = false, loadingLabel = "Loading table data", loadingRows = 5, visibleColumnKeys, resizableColumns = false, columnResizeMode = "pair", columnWidths, defaultColumnWidths, onColumnWidthsChange, renderColumnResizeHandle, tableLayout, centerEmptyState = false, emptyStateMinHeight = DEFAULT_CENTERED_EMPTY_STATE_MIN_HEIGHT, striped = false, rowIndicator, rowExpansion, reorderableColumns = false, onColumnOrderChange, onScroll, style, ...props }) {
|
|
403
|
+
var _a;
|
|
402
404
|
const visibleColumns = getVisibleColumns(columns, visibleColumnKeys);
|
|
405
|
+
const hasRowIndicatorColumn = Boolean(rowIndicator);
|
|
403
406
|
const hasExpansionColumn = Boolean(rowExpansion);
|
|
404
407
|
const hasColumnFilters = visibleColumns.some((column) => column.filter);
|
|
405
408
|
const isGrowResizeMode = columnResizeMode === "grow";
|
|
@@ -413,6 +416,7 @@ function Table({ accessibleLabel, columns, rows, getRowKey, emptyState = (_jsx(E
|
|
|
413
416
|
const hasResolvedColumnWidths = hasColumnWidthOverrides(resolvedColumnWidths);
|
|
414
417
|
const growTableMinWidth = isGrowResizeMode
|
|
415
418
|
? getTableMinWidth(visibleColumns, resolvedColumnWidths) +
|
|
419
|
+
(hasRowIndicatorColumn ? TABLE_ROW_INDICATOR_COLUMN_WIDTH : 0) +
|
|
416
420
|
(hasExpansionColumn ? TABLE_EXPANSION_COLUMN_WIDTH : 0)
|
|
417
421
|
: undefined;
|
|
418
422
|
const resolvedMinHeight = minHeight !== null && minHeight !== void 0 ? minHeight : (centerEmptyState ? DEFAULT_TABLE_MIN_HEIGHT : undefined);
|
|
@@ -673,7 +677,11 @@ function Table({ accessibleLabel, columns, rows, getRowKey, emptyState = (_jsx(E
|
|
|
673
677
|
}, ...props, children: [_jsxs(TableRoot, { "aria-busy": loading, className: cn(shouldUseFixedLayout && "table-fixed", isGrowResizeMode &&
|
|
674
678
|
(hasResolvedColumnWidths
|
|
675
679
|
? "w-[var(--table-min-width)]"
|
|
676
|
-
: "min-w-[var(--table-min-width)]"), tableClassName), children: [_jsx(TableCaption, { className: caption ? undefined : "sr-only !m-0", children: caption !== null && caption !== void 0 ? caption : accessibleLabel }), _jsxs("colgroup", { children: [
|
|
680
|
+
: "min-w-[var(--table-min-width)]"), tableClassName), children: [_jsx(TableCaption, { className: caption ? undefined : "sr-only !m-0", children: caption !== null && caption !== void 0 ? caption : accessibleLabel }), _jsxs("colgroup", { children: [hasRowIndicatorColumn ? (_jsx("col", { style: {
|
|
681
|
+
width: `${TABLE_ROW_INDICATOR_COLUMN_WIDTH}px`,
|
|
682
|
+
minWidth: `${TABLE_ROW_INDICATOR_COLUMN_WIDTH}px`,
|
|
683
|
+
maxWidth: `${TABLE_ROW_INDICATOR_COLUMN_WIDTH}px`,
|
|
684
|
+
} })) : null, hasExpansionColumn ? (_jsx("col", { style: {
|
|
677
685
|
width: `${TABLE_EXPANSION_COLUMN_WIDTH}px`,
|
|
678
686
|
minWidth: `${TABLE_EXPANSION_COLUMN_WIDTH}px`,
|
|
679
687
|
maxWidth: `${TABLE_EXPANSION_COLUMN_WIDTH}px`,
|
|
@@ -686,14 +694,17 @@ function Table({ accessibleLabel, columns, rows, getRowKey, emptyState = (_jsx(E
|
|
|
686
694
|
minWidth: getRenderedColumnMinWidth(column, isColumnResizingEnabled),
|
|
687
695
|
maxWidth: getRenderedColumnMaxWidth(column, isColumnResizingEnabled),
|
|
688
696
|
treatWidthAsMinWidth: !isColumnResizingEnabled,
|
|
689
|
-
}) }, column.key)))] }), _jsxs(TableHeader, { children: [_jsxs(TableRow, { children: [hasExpansionColumn ? (_jsx(TableHead, { "data-slot": "table-expansion-head", "aria-label": "Expand rows", scope: "col", className: "w-12 px-2" })) : null, renderColumnHeaders(visibleColumns)] }), hasColumnFilters ? (_jsxs(TableRow, { "data-slot": "table-filter-row", className: "!bg-card", children: [hasExpansionColumn ? (_jsx(TableCell, { "data-slot": "table-expansion-filter-cell", "aria-hidden": "true", className: "w-12 px-2" })) : null, visibleColumns.map((column) => {
|
|
697
|
+
}) }, column.key)))] }), _jsxs(TableHeader, { children: [_jsxs(TableRow, { children: [hasRowIndicatorColumn ? (_jsx(TableHead, { "data-slot": "table-row-indicator-head", "aria-label": (_a = rowIndicator === null || rowIndicator === void 0 ? void 0 : rowIndicator.headerLabel) !== null && _a !== void 0 ? _a : "Row status", scope: "col", className: "w-8 px-2" })) : null, hasExpansionColumn ? (_jsx(TableHead, { "data-slot": "table-expansion-head", "aria-label": "Expand rows", scope: "col", className: "w-12 px-2" })) : null, renderColumnHeaders(visibleColumns)] }), hasColumnFilters ? (_jsxs(TableRow, { "data-slot": "table-filter-row", className: "!bg-card", children: [hasRowIndicatorColumn ? (_jsx(TableCell, { "data-slot": "table-row-indicator-filter-cell", "aria-hidden": "true", className: "h-11 w-8 px-2 py-[4px]" })) : null, hasExpansionColumn ? (_jsx(TableCell, { "data-slot": "table-expansion-filter-cell", "aria-hidden": "true", className: "h-11 w-12 px-2 py-[4px]" })) : null, visibleColumns.map((column) => {
|
|
690
698
|
const columnWidth = getRenderedColumnWidth({
|
|
691
699
|
column,
|
|
692
700
|
columnWidths: resolvedColumnWidths,
|
|
693
701
|
resizing: isColumnResizingEnabled,
|
|
694
702
|
});
|
|
695
|
-
return (_jsx(TableCell, { "data-slot": "table-filter-cell", width: columnWidth, minWidth: getRenderedColumnMinWidth(column, isColumnResizingEnabled), maxWidth: getRenderedColumnMaxWidth(column, isColumnResizingEnabled), treatWidthAsMinWidth: !isColumnResizingEnabled, containOverflow: isColumnResizingEnabled, className: cn("relative h-11 px-2 py-
|
|
703
|
+
return (_jsx(TableCell, { "data-slot": "table-filter-cell", width: columnWidth, minWidth: getRenderedColumnMinWidth(column, isColumnResizingEnabled), maxWidth: getRenderedColumnMaxWidth(column, isColumnResizingEnabled), treatWidthAsMinWidth: !isColumnResizingEnabled, containOverflow: isColumnResizingEnabled, className: cn("relative h-11 px-2 py-[4px] font-normal", stickyClassName(column.sticky, "filter", getStickyShadowVisibility(column.sticky, stickyScrollState)), column.filterClassName), children: column.filter ? (_jsx("div", { "data-slot": "table-filter-control", className: "absolute inset-x-2 inset-y-[4px] min-w-0", children: _jsx(TableColumnFilterControl, { filter: column.filter, label: getColumnResizeLabel(column) }) })) : null }, column.key));
|
|
696
704
|
})] })) : null] }), _jsx(TableBody, { "aria-hidden": loading ? "true" : undefined, children: loading ? (_jsx(TableRowSkeleton, { rows: loadingRows, columns: [
|
|
705
|
+
...(hasRowIndicatorColumn
|
|
706
|
+
? [{ width: "0.5rem", height: "0.5rem", badge: true }]
|
|
707
|
+
: []),
|
|
697
708
|
...(hasExpansionColumn
|
|
698
709
|
? [{ width: "1rem", height: "1rem" }]
|
|
699
710
|
: []),
|
|
@@ -715,7 +726,7 @@ function Table({ accessibleLabel, columns, rows, getRowKey, emptyState = (_jsx(E
|
|
|
715
726
|
!resolvedTone &&
|
|
716
727
|
"bg-[hsl(var(--table-row-striped-background))]", tableRowToneClassName(resolvedTone), typeof rowClassName === "function"
|
|
717
728
|
? rowClassName(row, rowIndex)
|
|
718
|
-
: rowClassName), children: [hasExpansionColumn ? (_jsx(TableCell, { className: "w-12 px-2 text-center", children: isRowExpandable ? (_jsx("button", { type: "button", "aria-expanded": isExpanded, "aria-controls": isExpanded ? expandedContentId : undefined, "aria-label": (_d = (_c = rowExpansion === null || rowExpansion === void 0 ? void 0 : rowExpansion.getToggleLabel) === null || _c === void 0 ? void 0 : _c.call(rowExpansion, row, rowIndex, isExpanded)) !== null && _d !== void 0 ? _d : `${isExpanded ? "Collapse" : "Expand"} row ${rowIndex + 1}`, onClick: (event) => {
|
|
729
|
+
: rowClassName), children: [hasRowIndicatorColumn ? (_jsx(TableCell, { "data-slot": "table-row-indicator-cell", className: "w-8 px-2 text-center", children: rowIndicator === null || rowIndicator === void 0 ? void 0 : rowIndicator.render(row, rowIndex) })) : null, hasExpansionColumn ? (_jsx(TableCell, { className: "w-12 px-2 text-center", children: isRowExpandable ? (_jsx("button", { type: "button", "aria-expanded": isExpanded, "aria-controls": isExpanded ? expandedContentId : undefined, "aria-label": (_d = (_c = rowExpansion === null || rowExpansion === void 0 ? void 0 : rowExpansion.getToggleLabel) === null || _c === void 0 ? void 0 : _c.call(rowExpansion, row, rowIndex, isExpanded)) !== null && _d !== void 0 ? _d : `${isExpanded ? "Collapse" : "Expand"} row ${rowIndex + 1}`, onClick: (event) => {
|
|
719
730
|
event.stopPropagation();
|
|
720
731
|
toggleExpandedRow(rowKey);
|
|
721
732
|
}, className: "inline-flex h-8 w-8 cursor-pointer items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2", children: _jsx(ChevronRight, { "aria-hidden": "true", className: cn("h-4 w-4 transition-transform duration-150", isExpanded && "rotate-90") }) })) : null })) : null, visibleColumns.map((column) => {
|
|
@@ -733,8 +744,11 @@ function Table({ accessibleLabel, columns, rows, getRowKey, emptyState = (_jsx(E
|
|
|
733
744
|
: TableCell;
|
|
734
745
|
return (_jsx(Cell, { width: columnWidth, minWidth: getRenderedColumnMinWidth(column, isColumnResizingEnabled), maxWidth: getRenderedColumnMaxWidth(column, isColumnResizingEnabled), wrap: column.wrap, treatWidthAsMinWidth: !isColumnResizingEnabled, containOverflow: isColumnResizingEnabled, className: cn(alignClassName(column.align), stickyClassName(column.sticky, "cell", getStickyShadowVisibility(column.sticky, stickyScrollState)), column.cellClassName), children: value }, column.key));
|
|
735
746
|
})] }), isExpanded ? (_jsx(TableRow, { id: expandedContentId, "data-slot": "table-expanded-row", className: "bg-[hsl(var(--table-row-striped-background))] hover:bg-[hsl(var(--table-row-striped-background))]", children: _jsx(TableCell, { colSpan: Math.max(visibleColumns.length +
|
|
747
|
+
(hasRowIndicatorColumn ? 1 : 0) +
|
|
736
748
|
(hasExpansionColumn ? 1 : 0), 1), className: "h-auto whitespace-normal p-4", children: rowExpansion === null || rowExpansion === void 0 ? void 0 : rowExpansion.renderExpandedContent(row, rowIndex) }) })) : null] }, rowKey));
|
|
737
|
-
})) : (_jsx(TableRow, { className: "cursor-default hover:bg-card", children: _jsx(TableCell, { colSpan: Math.max(visibleColumns.length +
|
|
749
|
+
})) : (_jsx(TableRow, { className: "cursor-default hover:bg-card", children: _jsx(TableCell, { colSpan: Math.max(visibleColumns.length +
|
|
750
|
+
(hasRowIndicatorColumn ? 1 : 0) +
|
|
751
|
+
(hasExpansionColumn ? 1 : 0), 1), className: "p-6", children: resolvedEmptyState }) })) })] }), _jsx("div", { role: "status", className: "sr-only", children: loading ? loadingLabel : null })] }));
|
|
738
752
|
const reorderableContainer = reorderableColumns ? (_jsx(DndContext, { sensors: columnReorderSensors, collisionDetection: closestCenter, onDragEnd: handleColumnDragEnd, children: _jsx(SortableContext, { items: reorderableColumnIds, strategy: horizontalListSortingStrategy, children: container }) })) : (container);
|
|
739
753
|
if (!pagination) {
|
|
740
754
|
return (_jsxs("div", { className: "space-y-4", children: [toolbar, reorderableContainer] }));
|
package/dist/tabs.d.ts
CHANGED
|
@@ -65,7 +65,7 @@ export interface TabsProps extends Omit<React.ComponentPropsWithoutRef<typeof Ta
|
|
|
65
65
|
defaultValue?: string;
|
|
66
66
|
value?: string;
|
|
67
67
|
onValueChange?: (value: string) => void;
|
|
68
|
-
size?: "default" | "compact";
|
|
68
|
+
size?: "default" | "compact" | "comfortable";
|
|
69
69
|
renderPanels?: boolean;
|
|
70
70
|
listWrapperClassName?: string;
|
|
71
71
|
listClassName?: string;
|
package/dist/tabs.js
CHANGED
|
@@ -144,13 +144,15 @@ function Tabs({ items, defaultValue, value, onValueChange, size = "default", ren
|
|
|
144
144
|
if (!items.length) {
|
|
145
145
|
return null;
|
|
146
146
|
}
|
|
147
|
-
return (_jsxs(TabsRoot, { defaultValue: fallbackValue, value: value, onValueChange: handleValueChange, className: cn("space-y-4", className), ...props, children: [_jsx("div", { ref: listWrapperRef, className: listWrapperClassName, children: _jsx(TabsList, { className: cn(size === "compact" && "p-0.5", listClassName), children: items.map((item) => item.sections && item.sections.length > 0 ? (_jsx(TabTriggerWithDropdown, { item: item, suppressAriaControls: !renderPanels, triggerClassName: cn(size === "compact" &&
|
|
148
|
-
"min-h-7 px-2.5 py-0.5 data-[state=active]:shadow-sm",
|
|
149
|
-
"min-h-
|
|
147
|
+
return (_jsxs(TabsRoot, { defaultValue: fallbackValue, value: value, onValueChange: handleValueChange, className: cn("space-y-4", className), ...props, children: [_jsx("div", { ref: listWrapperRef, className: listWrapperClassName, children: _jsx(TabsList, { className: cn(size === "compact" && "p-0.5", size === "comfortable" && "rounded-[10px]", listClassName), children: items.map((item) => item.sections && item.sections.length > 0 ? (_jsx(TabTriggerWithDropdown, { item: item, suppressAriaControls: !renderPanels, triggerClassName: cn(size === "compact" &&
|
|
148
|
+
"min-h-7 px-2.5 py-0.5 data-[state=active]:shadow-sm", size === "comfortable" &&
|
|
149
|
+
"min-h-[40px] rounded-md px-[12px] py-[8px] text-[16px]", triggerClassName) }, item.value)) : (_jsx(TabTriggerItem, { item: item, suppressAriaControls: !renderPanels, triggerClassName: cn(size === "compact" &&
|
|
150
|
+
"min-h-7 px-2.5 py-0.5 data-[state=active]:shadow-sm", size === "comfortable" &&
|
|
151
|
+
"min-h-[40px] rounded-md px-[12px] py-[8px] text-[16px]", triggerClassName) }, item.value))) }) }), renderPanels
|
|
150
152
|
? items.map((item) => (_jsx(TabsContent, { value: item.value, className: cn("pt-4", panelClassName), children: item.content }, item.value)))
|
|
151
153
|
: null] }));
|
|
152
154
|
}
|
|
153
155
|
function SubTabs({ className, listWrapperClassName, listClassName, triggerClassName, panelClassName, ...props }) {
|
|
154
|
-
return (_jsx(Tabs, { className: cn("space-y-0", className), listWrapperClassName: cn("min-w-0 overflow-x-auto", listWrapperClassName), listClassName: cn("w-full min-w-max justify-start overflow-visible rounded-none border-0 border-b border-[hsl(var(--tab-list-border))] bg-transparent p-0", listClassName), triggerClassName: cn("min-h-9 rounded-none border-b-
|
|
156
|
+
return (_jsx(Tabs, { className: cn("space-y-0", className), listWrapperClassName: cn("min-w-0 overflow-x-auto", listWrapperClassName), listClassName: cn("w-full min-w-max justify-start overflow-visible rounded-none border-0 border-b border-[hsl(var(--tab-list-border))] bg-transparent p-0", listClassName), triggerClassName: cn("min-h-9 rounded-none border-b-[3px] border-transparent bg-transparent px-3 py-2 text-[hsl(var(--tab-trigger-foreground))] shadow-none focus-visible:ring-inset focus-visible:ring-offset-0 data-[state=inactive]:hover:bg-[hsl(var(--tab-trigger-hover-background))] data-[state=active]:border-[hsl(var(--tab-indicator))] data-[state=active]:bg-transparent data-[state=active]:text-[hsl(var(--tab-trigger-active-foreground))] data-[state=active]:shadow-none", triggerClassName), panelClassName: cn("pt-4", panelClassName), ...props }));
|
|
155
157
|
}
|
|
156
158
|
export { Tabs, SubTabs, TabsRoot, TabsList, TabsTrigger, TabsContent, TabWithDropdown, };
|
package/dist/tailwind-preset.js
CHANGED
|
@@ -147,6 +147,14 @@ export const neaTailwindPreset = {
|
|
|
147
147
|
12: "var(--space-12)",
|
|
148
148
|
},
|
|
149
149
|
keyframes: {
|
|
150
|
+
"collapsible-down": {
|
|
151
|
+
from: { height: "0" },
|
|
152
|
+
to: { height: "var(--radix-collapsible-content-height)" },
|
|
153
|
+
},
|
|
154
|
+
"collapsible-up": {
|
|
155
|
+
from: { height: "var(--radix-collapsible-content-height)" },
|
|
156
|
+
to: { height: "0" },
|
|
157
|
+
},
|
|
150
158
|
"accordion-down": {
|
|
151
159
|
from: { height: "0" },
|
|
152
160
|
to: { height: "var(--radix-accordion-content-height)" },
|
|
@@ -157,6 +165,8 @@ export const neaTailwindPreset = {
|
|
|
157
165
|
},
|
|
158
166
|
},
|
|
159
167
|
animation: {
|
|
168
|
+
"collapsible-down": "collapsible-down 0.2s ease-out",
|
|
169
|
+
"collapsible-up": "collapsible-up 0.2s ease-out",
|
|
160
170
|
"accordion-down": "accordion-down 0.2s ease-out",
|
|
161
171
|
"accordion-up": "accordion-up 0.2s ease-out",
|
|
162
172
|
},
|
package/dist/textarea.d.ts
CHANGED
|
@@ -2,7 +2,12 @@ import * as React from "react";
|
|
|
2
2
|
declare const TextareaControl: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.TextareaHTMLAttributes<HTMLTextAreaElement>, HTMLTextAreaElement>, "ref"> & React.RefAttributes<HTMLTextAreaElement>>;
|
|
3
3
|
export interface TextareaProps extends Omit<React.ComponentProps<typeof TextareaControl>, "className"> {
|
|
4
4
|
label: React.ReactNode;
|
|
5
|
+
size?: "default" | "comfortable";
|
|
5
6
|
description?: React.ReactNode;
|
|
7
|
+
/** Show a word counter and validate this limit without truncating the entered text. */
|
|
8
|
+
maxWords?: number;
|
|
9
|
+
/** Display a character counter for maxLength; maxWords takes precedence. */
|
|
10
|
+
showCount?: boolean;
|
|
6
11
|
error?: React.ReactNode;
|
|
7
12
|
invalid?: boolean;
|
|
8
13
|
hideLabel?: boolean;
|
package/dist/textarea.js
CHANGED
|
@@ -2,12 +2,22 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import * as React from "react";
|
|
3
3
|
import { Field, FieldDescription, FieldError, FieldLabel } from "./field";
|
|
4
4
|
import { inputControlPaddingClassName } from "./input-control";
|
|
5
|
+
import { FieldCounter } from "./field-counter";
|
|
5
6
|
import { cn } from "./lib/utils";
|
|
6
7
|
const TextareaControl = React.forwardRef(({ className, ...props }, ref) => (_jsx("textarea", { ref: ref, "data-slot": "textarea", className: cn("flex min-h-16 w-full rounded-control border border-input bg-background text-sm transition-[color,box-shadow] outline-none placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-[invalid=true]:border-destructive aria-[invalid=true]:ring-destructive/20", inputControlPaddingClassName, className), ...props })));
|
|
7
8
|
TextareaControl.displayName = "TextareaControl";
|
|
8
|
-
const Textarea = React.forwardRef(({ label, description, error, invalid = false, hideLabel = false, className, textareaClassName, labelClassName, descriptionClassName, errorClassName, id, disabled, "aria-invalid": ariaInvalid, "aria-describedby": ariaDescribedBy, ...props }, ref) => {
|
|
9
|
+
const Textarea = React.forwardRef(({ label, size = "default", description, maxWords, showCount = false, value, defaultValue, onChange, error: suppliedError, invalid = false, hideLabel = false, className, textareaClassName, labelClassName, descriptionClassName, errorClassName, id, disabled, "aria-invalid": ariaInvalid, "aria-describedby": ariaDescribedBy, ...props }, ref) => {
|
|
10
|
+
const [uncontrolledValue, setUncontrolledValue] = React.useState(defaultValue !== null && defaultValue !== void 0 ? defaultValue : "");
|
|
11
|
+
const text = String(value !== null && value !== void 0 ? value : uncontrolledValue);
|
|
12
|
+
const words = text.trim() ? text.trim().split(/\s+/).length : 0;
|
|
13
|
+
const hasWordLimit = maxWords !== undefined;
|
|
14
|
+
const error = suppliedError || (hasWordLimit && words > maxWords
|
|
15
|
+
? `Use ${maxWords} words or fewer.`
|
|
16
|
+
: undefined);
|
|
9
17
|
const generatedId = React.useId();
|
|
10
18
|
const textareaId = id !== null && id !== void 0 ? id : `textarea-${generatedId}`;
|
|
19
|
+
const limit = maxWords !== null && maxWords !== void 0 ? maxWords : (showCount ? props.maxLength : undefined);
|
|
20
|
+
const wordLimitId = limit !== undefined ? `${textareaId}-word-limit` : undefined;
|
|
11
21
|
const errorId = error ? `${textareaId}-error` : undefined;
|
|
12
22
|
const showDescription = Boolean(description) && !error;
|
|
13
23
|
const descriptionId = showDescription ? `${textareaId}-description` : undefined;
|
|
@@ -15,10 +25,15 @@ const Textarea = React.forwardRef(({ label, description, error, invalid = false,
|
|
|
15
25
|
ariaInvalid === true ||
|
|
16
26
|
ariaInvalid === "true" ||
|
|
17
27
|
Boolean(error);
|
|
18
|
-
const describedBy = [ariaDescribedBy, descriptionId, errorId]
|
|
28
|
+
const describedBy = [ariaDescribedBy, descriptionId, errorId, wordLimitId]
|
|
19
29
|
.filter(Boolean)
|
|
20
30
|
.join(" ") || undefined;
|
|
21
|
-
return (_jsxs(Field, { className: className, "data-disabled": disabled ? "true" : undefined, "data-invalid": isInvalid ? "true" : undefined, children: [_jsx(FieldLabel, { htmlFor: textareaId, className: cn(hideLabel && "sr-only", labelClassName), children: label }), _jsx(TextareaControl, { ref: ref, id: textareaId, disabled: disabled, "aria-invalid": isInvalid ? "true" : undefined, "aria-describedby": describedBy, className:
|
|
31
|
+
return (_jsxs(Field, { className: cn(size === "comfortable" && "gap-[8px]", className), "data-disabled": disabled ? "true" : undefined, "data-invalid": isInvalid ? "true" : undefined, children: [_jsx(FieldLabel, { htmlFor: textareaId, className: cn(size === "comfortable" && "text-[16px] leading-[24px]", hideLabel && "sr-only", labelClassName), children: label }), _jsx(TextareaControl, { ref: ref, id: textareaId, disabled: disabled, "aria-invalid": isInvalid ? "true" : undefined, "aria-describedby": describedBy, className: cn(size === "comfortable" &&
|
|
32
|
+
"min-h-[76px] px-[16px] py-[12px] text-[16px] leading-[24px]", textareaClassName), ...props, value: value, defaultValue: defaultValue, onChange: (event) => {
|
|
33
|
+
if (value === undefined)
|
|
34
|
+
setUncontrolledValue(event.target.value);
|
|
35
|
+
onChange === null || onChange === void 0 ? void 0 : onChange(event);
|
|
36
|
+
} }), showDescription ? (_jsx(FieldDescription, { id: descriptionId, className: cn(size === "comfortable" && "text-[14px] leading-[20px]", descriptionClassName), children: description })) : null, limit !== undefined && _jsx(FieldCounter, { id: wordLimitId, count: hasWordLimit ? words : text.length, limit: limit, unit: hasWordLimit ? "words" : "characters" }), _jsx(FieldError, { id: errorId, className: errorClassName, children: error })] }));
|
|
22
37
|
});
|
|
23
38
|
Textarea.displayName = "Textarea";
|
|
24
39
|
export { Textarea };
|
package/dist/theme-switcher.d.ts
CHANGED
|
@@ -9,6 +9,8 @@ export interface ThemeSwitcherProps extends Omit<SwitchProps, "checked" | "defau
|
|
|
9
9
|
onCheckedChange?: (checked: boolean) => void;
|
|
10
10
|
/** Icon-only mode for collapsed sidebars. */
|
|
11
11
|
isCollapsed?: boolean;
|
|
12
|
+
/** Animates between expanded and icon-only presentations. */
|
|
13
|
+
animateModeChange?: boolean;
|
|
12
14
|
/** Text shown before the switch. Defaults to the active theme label. */
|
|
13
15
|
label?: React.ReactNode;
|
|
14
16
|
/** Label shown when light theme is active and no `label` is provided. */
|
|
@@ -21,7 +23,7 @@ export interface ThemeSwitcherProps extends Omit<SwitchProps, "checked" | "defau
|
|
|
21
23
|
useLightLabel?: string;
|
|
22
24
|
className?: string;
|
|
23
25
|
}
|
|
24
|
-
declare function ThemeSwitcher({ checked, defaultChecked, onCheckedChange, isCollapsed, label, lightLabel, darkLabel, useDarkLabel, useLightLabel, className, disabled, tabIndex, ...props }: ThemeSwitcherProps): import("react/jsx-runtime").JSX.Element;
|
|
26
|
+
declare function ThemeSwitcher({ checked, defaultChecked, onCheckedChange, isCollapsed, animateModeChange, label, lightLabel, darkLabel, useDarkLabel, useLightLabel, className, disabled, tabIndex, ...props }: ThemeSwitcherProps): import("react/jsx-runtime").JSX.Element;
|
|
25
27
|
declare namespace ThemeSwitcher {
|
|
26
28
|
var displayName: string;
|
|
27
29
|
}
|
package/dist/theme-switcher.js
CHANGED
|
@@ -5,7 +5,7 @@ import { Moon, Sun } from "lucide-react";
|
|
|
5
5
|
import { Button } from "./button";
|
|
6
6
|
import { cn } from "./lib/utils";
|
|
7
7
|
import { Switch } from "./switch";
|
|
8
|
-
function ThemeSwitcher({ checked, defaultChecked = false, onCheckedChange, isCollapsed = false, label, lightLabel = "Light theme", darkLabel = "Dark theme", useDarkLabel = "Use dark theme", useLightLabel = "Use light theme", className, disabled, tabIndex, ...props }) {
|
|
8
|
+
function ThemeSwitcher({ checked, defaultChecked = false, onCheckedChange, isCollapsed = false, animateModeChange = true, label, lightLabel = "Light theme", darkLabel = "Dark theme", useDarkLabel = "Use dark theme", useLightLabel = "Use light theme", className, disabled, tabIndex, ...props }) {
|
|
9
9
|
const isControlled = checked !== undefined;
|
|
10
10
|
const [uncontrolledChecked, setUncontrolledChecked] = React.useState(defaultChecked);
|
|
11
11
|
const isDark = isControlled ? checked : uncontrolledChecked;
|
|
@@ -17,7 +17,13 @@ function ThemeSwitcher({ checked, defaultChecked = false, onCheckedChange, isCol
|
|
|
17
17
|
}
|
|
18
18
|
onCheckedChange === null || onCheckedChange === void 0 ? void 0 : onCheckedChange(nextChecked);
|
|
19
19
|
}, [isControlled, onCheckedChange]);
|
|
20
|
-
return (_jsxs("div", { "data-slot": "theme-switcher", className: cn("relative w-full overflow-hidden py-1
|
|
20
|
+
return (_jsxs("div", { "data-slot": "theme-switcher", className: cn("relative w-full overflow-hidden py-1", animateModeChange
|
|
21
|
+
? "transition-[padding] duration-300 ease-in-out"
|
|
22
|
+
: "transition-none", isCollapsed ? "px-0" : "px-1.5", className), children: [_jsx(Button, { type: "button", variant: "ghost", size: "icon", disabled: disabled, "aria-hidden": isCollapsed ? undefined : true, "aria-label": isDark ? useLightLabel : useDarkLabel, "aria-pressed": isDark, tabIndex: isCollapsed ? tabIndex : -1, className: cn("absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2", animateModeChange
|
|
23
|
+
? "transition-opacity duration-150"
|
|
24
|
+
: "transition-none", isCollapsed ? "opacity-100" : "pointer-events-none opacity-0"), onClick: () => handleCheckedChange(!isDark), children: _jsx(ActiveIcon, { "aria-hidden": "true", className: "h-4 w-4" }) }), _jsx("div", { "aria-hidden": isCollapsed ? true : undefined, className: cn(animateModeChange
|
|
25
|
+
? "transition-[opacity,transform] duration-150"
|
|
26
|
+
: "transition-none", isCollapsed
|
|
21
27
|
? "pointer-events-none translate-x-1 opacity-0"
|
|
22
28
|
: "translate-x-0 opacity-100"), children: _jsx(Switch, { checked: isDark, onCheckedChange: handleCheckedChange, disabled: disabled, tabIndex: isCollapsed ? -1 : tabIndex, label: _jsxs("span", { className: "inline-flex min-w-0 items-center gap-2", children: [_jsx(ActiveIcon, { "aria-hidden": "true", className: "h-4 w-4 shrink-0" }), _jsx("span", { className: "truncate", children: activeLabel })] }), wrapperClassName: "w-full flex-row-reverse justify-between rounded-control px-3 py-2 text-muted-foreground transition-colors hover:bg-card hover:text-foreground", ...props }) })] }));
|
|
23
29
|
}
|